00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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) {
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
00225
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
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 }
00255
00256 #endif