ShSwizzleImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright 2003-2005 Serious Hack Inc.
00004 // 
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00018 // MA  02110-1301, USA
00020 #ifndef SH_SWIZZLEIMPL_HPP
00021 #define SH_SWIZZLEIMPL_HPP
00022 #include <iostream>
00023 #include "ShSwizzle.hpp"
00024 #include "ShError.hpp"
00025 #include "ShDebug.hpp"
00026 
00027 namespace SH {
00028 
00029 inline ShSwizzle::ShSwizzle()
00030   : m_srcSize(0),
00031     m_size(0)
00032 {
00033   alloc();
00034 }
00035 
00036 inline ShSwizzle::ShSwizzle(int srcSize)
00037   : m_srcSize(srcSize),
00038     m_size(srcSize)
00039 {
00040   if(alloc()) {
00041     for(int i = 0; i < m_size; ++i) m_index.ptr[i] = i;
00042   } 
00043 }
00044 
00045 inline ShSwizzle::ShSwizzle(int srcSize, int i0)
00046   : m_srcSize(srcSize),
00047     m_size(1)
00048 {
00049   checkSrcSize(i0);
00050   if(alloc()) {
00051     m_index.ptr[0] = i0;
00052   } else {
00053     m_index.local[0] = (unsigned char)i0;
00054   }
00055 }
00056 
00057 inline ShSwizzle::ShSwizzle(int srcSize, int i0, int i1)
00058   : m_srcSize(srcSize),
00059     m_size(2)
00060 {
00061   checkSrcSize(i0);
00062   checkSrcSize(i1);
00063   if(alloc()) {
00064     m_index.ptr[0] = i0;
00065     m_index.ptr[1] = i1;
00066   } else {
00067     m_index.local[0] = (unsigned char)i0;
00068     m_index.local[1] = (unsigned char)i1;
00069   }
00070 }
00071 
00072 inline ShSwizzle::ShSwizzle(int srcSize, int i0, int i1, int i2)
00073   : m_srcSize(srcSize),
00074     m_size(3)
00075 {
00076   checkSrcSize(i0);
00077   checkSrcSize(i1);
00078   checkSrcSize(i2);
00079   if(alloc()) {
00080     m_index.ptr[0] = i0;
00081     m_index.ptr[1] = i1;
00082     m_index.ptr[2] = i2;
00083   } else {
00084     m_index.local[0] = (unsigned char)i0;
00085     m_index.local[1] = (unsigned char)i1;
00086     m_index.local[2] = (unsigned char)i2;
00087   }
00088 }
00089 
00090 inline ShSwizzle::ShSwizzle(int srcSize, int i0, int i1, int i2, int i3)
00091   : m_srcSize(srcSize),
00092     m_size(4)
00093 {
00094   checkSrcSize(i0);
00095   checkSrcSize(i1);
00096   checkSrcSize(i2);
00097   checkSrcSize(i3);
00098   if(alloc()) {
00099     m_index.ptr[0] = i0;
00100     m_index.ptr[1] = i1;
00101     m_index.ptr[2] = i2;
00102     m_index.ptr[3] = i3;
00103   } else {
00104     m_index.local[0] = (unsigned char)i0;
00105     m_index.local[1] = (unsigned char)i1;
00106     m_index.local[2] = (unsigned char)i2;
00107     m_index.local[3] = (unsigned char)i3;
00108   }
00109 }
00110 
00111 inline ShSwizzle::ShSwizzle(int srcSize, int size, int* indices)
00112   : m_srcSize(srcSize),
00113     m_size(size)
00114 {
00115   int i;
00116   for (i = 0; i < size; i++) checkSrcSize(indices[i]);
00117   if(alloc()) {
00118     for (i = 0; i < size; i++) m_index.ptr[i] = indices[i];
00119   } else {
00120     for (i = 0; i < size; i++) m_index.local[i] = (unsigned char)indices[i];
00121   }
00122 }
00123 
00124 
00125 inline ShSwizzle::ShSwizzle(const ShSwizzle& other)
00126   : m_srcSize(other.m_srcSize),
00127     m_size(other.m_size)
00128 {
00129   copy(other, !alloc());
00130 }
00131 
00132 inline ShSwizzle::~ShSwizzle()
00133 {
00134   dealloc();
00135 }
00136 
00137 inline ShSwizzle& ShSwizzle::operator=(const ShSwizzle& other)
00138 {
00139   if(this == &other) return *this;
00140 
00141   if(m_size != other.m_size || m_srcSize != other.m_srcSize) {
00142     dealloc();
00143     m_size = other.m_size;
00144     m_srcSize = other.m_srcSize;
00145     alloc();
00146   } 
00147   copy(other, local());
00148   return *this;
00149 }
00150 
00151 inline ShSwizzle& ShSwizzle::operator*=(const ShSwizzle& other)  
00152 {
00153   (*this) = (*this) * other;
00154   return (*this);
00155 }
00156 
00157 inline ShSwizzle ShSwizzle::operator*(const ShSwizzle& other) const
00158 {
00159   ShSwizzle result;
00160   result.m_size = other.m_size;
00161   result.m_srcSize = m_srcSize;
00162   bool resultLocal = true; 
00163   if(m_srcSize >= 256 || other.m_size > 4) { // result must go ptr 
00164     result.alloc();
00165     resultLocal = false;
00166   } 
00167 
00168   const bool isLocal = local();
00169   for (int i = 0; i < other.m_size; i++) {
00170     int oi = other[i];
00171     if (oi >= m_size) shError( ShSwizzleException(*this, oi, size()) );
00172     int index = isLocal ? m_index.local[oi] : m_index.ptr[oi];
00173     if(resultLocal) result.m_index.local[i] = index;
00174     else result.m_index.ptr[i] = index;
00175   }
00176   return result;
00177 }
00178 
00179 inline int ShSwizzle::operator[](int index) const
00180 {
00181   if (index >= m_size || index < 0) shError( ShSwizzleException(*this, index, m_size) );
00182   if(local()) return m_index.local[index];
00183   return m_index.ptr[index];
00184 }
00185 
00186 inline void ShSwizzle::copy(const ShSwizzle &other, bool islocal) 
00187 {
00188   if(islocal) {
00189     m_index.intval = other.m_index.intval;
00190   } else {
00191     memcpy(m_index.ptr, other.m_index.ptr, sizeof(int)*m_size);
00192   }
00193 }
00194 
00195 inline void ShSwizzle::checkSrcSize(int index) 
00196 {
00197   if (index < 0 || index >= m_srcSize) {
00198     shError( ShSwizzleException(*this, index, m_srcSize) );
00199   }
00200 }
00201 
00202 inline bool ShSwizzle::alloc()
00203 {
00204   if(local()) {
00205     m_index.intval = idswiz(); 
00206     return false; 
00207   } 
00208   m_index.ptr = new int[m_size];
00209   return true;
00210 }
00211 
00212 inline void ShSwizzle::dealloc()
00213 {
00214   if(!local()) delete [] m_index.ptr;
00215 }
00216 
00217 inline bool ShSwizzle::local() const
00218 {
00219   return (m_srcSize < 256 && m_size <= 4); 
00220 }
00221 
00222 inline int ShSwizzle::idswiz() const
00223 {
00224 // @todo type detect endianess correctly
00225 // mac's are not the only big endian machines...
00226 #ifdef __APPLE__
00227   return 0x00010203;
00228 #else
00229   return 0x03020100;
00230 #endif
00231 }
00232 
00233 inline bool ShSwizzle::identity() const
00234 {
00235   if (m_size != m_srcSize) return false;
00236   if (local()) {
00237     // @todo type this is probably not portable...
00238     return m_index.intval == idswiz(); 
00239   } 
00240   for(int i = 0; i < m_size; ++i) {
00241     if(m_index.ptr[i] != i) return false;
00242   }
00243   return true; 
00244 }
00245 
00246 inline bool ShSwizzle::operator==(const ShSwizzle& other) const
00247 {
00248   if (m_srcSize != other.m_srcSize) return false;
00249   if (m_size != other.m_size) return false;
00250   if (local()) return m_index.intval == other.m_index.intval;
00251   return memcmp(m_index.ptr, other.m_index.ptr, sizeof(int)*m_size) == 0;
00252 }
00253 
00254 } // namespace SH
00255 
00256 #endif

Generated on Wed Nov 9 15:29:40 2005 for Sh by  doxygen 1.4.5