ShVariantImpl.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 SHVARIANT_IMPL_HPP
00021 #define SHVARIANT_IMPL_HPP
00022 
00023 #include <algorithm>
00024 #include <sstream>
00025 #include "ShDebug.hpp"
00026 #include "ShError.hpp"
00027 #include "ShCastManager.hpp"
00028 #include "ShVariant.hpp"
00029 #include "ShTypeInfo.hpp"
00030 
00031 namespace SH {
00032 
00033 #ifdef SH_USE_MEMORY_POOL
00034 template<typename T, ShDataType DT>
00035 ShPool* ShDataVariant<T, DT>::m_pool = 0;
00036 #endif
00037 
00038 template<typename T, ShDataType DT>
00039 ShDataVariant<T, DT>::ShDataVariant(int N)
00040   : m_managed(true)
00041 {
00042   alloc(N);
00043   std::fill(m_begin, m_end, ShDataTypeConstant<T, DT>::Zero);
00044 }
00045 
00046 template<typename T, ShDataType DT>
00047 ShDataVariant<T, DT>::ShDataVariant(int N, const DataType &value)
00048   : m_managed(true)
00049 {
00050   alloc(N);
00051   std::fill(m_begin, m_end, value); 
00052 }
00053 
00054 template<typename T, ShDataType DT>
00055 ShDataVariant<T, DT>::ShDataVariant(std::string encodedValue) 
00056   : m_managed(true)
00057 {
00058   std::istringstream in(encodedValue);
00059 
00060   int size;
00061   in >> size;
00062   alloc(size);
00063 
00064   for(iterator I = m_begin; I != m_end; ++I) {
00065     in.ignore(1, '$');
00066     in >> (*I); 
00067   }
00068 }
00069 
00070 template<typename T, ShDataType DT>
00071 ShDataVariant<T, DT>::ShDataVariant(int N, void *data, bool managed)
00072   : m_managed(managed)
00073 {
00074   if(m_managed) {
00075     alloc(N);
00076     DataType* cast_data = reinterpret_cast<DataType*>(data); 
00077     std::copy(cast_data, cast_data + N, m_begin);
00078   } else {
00079     m_begin = reinterpret_cast<DataType*>(data);
00080     m_end = m_begin + N;
00081   }
00082 }
00083 
00084 template<typename T, ShDataType DT>
00085 ShDataVariant<T, DT>::ShDataVariant(const ShDataVariant<T, DT> &other)
00086   : m_managed(true)
00087 {
00088   int size = other.size();
00089   alloc(size);
00090   std::copy(other.begin(), other.end(), m_begin);
00091 }
00092 
00093 template<typename T, ShDataType DT>
00094 ShDataVariant<T, DT>::ShDataVariant(const ShDataVariant<T, DT> &other, 
00095     bool neg, const ShSwizzle &swizzle, int count)
00096   : m_managed(true)
00097 {
00098   const int swizzle_size = swizzle.size();
00099   const int other_size = other.size() / count;
00100   
00101   alloc(swizzle_size * count);
00102   for (int j = 0; j < count; j++) {
00103     for (int i = 0; i < swizzle_size; ++i) {
00104       m_begin[j*swizzle_size + i] = other[j*other_size + swizzle[i]];
00105     }
00106   }
00107   if(neg) negate();
00108 }
00109 
00110 template<typename T, ShDataType DT>
00111 ShDataVariant<T, DT>::~ShDataVariant() 
00112 {
00113   if(m_managed) delete[] m_begin;
00114 }
00115 
00116 template<typename T, ShDataType DT>
00117 ShValueType ShDataVariant<T, DT>::valueType() const {
00118   return value_type; 
00119 }
00120 
00121 template<typename T, ShDataType DT>
00122 ShDataType ShDataVariant<T, DT>::dataType() const {
00123   return DT; 
00124 }
00125 
00126 template<typename T, ShDataType DT>
00127 bool ShDataVariant<T, DT>::typeMatches(
00128     ShValueType valueType, ShDataType dataType) const {
00129   return (valueType == value_type) && (dataType == DT);
00130 }
00131 
00132 
00133 template<typename T, ShDataType DT>
00134 const char* ShDataVariant<T, DT>::typeName() const {
00135   return ShStorageTypeInfo<T>::name;
00136 }
00137 
00138 template<typename T, ShDataType DT>
00139 int ShDataVariant<T, DT>::size() const
00140 {
00141   return m_end - m_begin; 
00142 }
00143 
00144 template<typename T, ShDataType DT>
00145 int ShDataVariant<T, DT>::datasize() const
00146 {
00147   return sizeof(DataType); 
00148 }
00149 
00150 template<typename T, ShDataType DT>
00151 bool ShDataVariant<T, DT>::managed() const
00152 {
00153   return m_managed; 
00154 }
00155 
00156 template<typename T, ShDataType DT>
00157 void ShDataVariant<T, DT>::negate()
00158 {
00159   transform(m_begin, m_end, m_begin, std::negate<DataType>());
00160 }
00161 
00162 template<typename T, ShDataType DT>
00163 void ShDataVariant<T, DT>::set(const ShVariant* other)
00164 {
00165   SH_DEBUG_ASSERT(other->size() == size());
00166 
00167   CPtrType cast_other = variant_cast<T, DT>(other);
00168   if(cast_other) {
00169     std::copy(cast_other->begin(), cast_other->end(), begin());
00170   } else {
00171     ShCastManager::instance()->doCast(this, other);
00172   }
00173 }
00174 
00175 template<typename T, ShDataType DT>
00176 void ShDataVariant<T, DT>::set(ShVariantCPtr other)
00177 {
00178   set(other.object());
00179 }
00180 
00181 template<typename T, ShDataType DT>
00182 void ShDataVariant<T, DT>::set(const ShVariant* other, int index)
00183 {
00184   SH_DEBUG_ASSERT(other->size() == 1); 
00185   CPtrType cast_other = variant_cast<T, DT>(other);
00186   if(cast_other) {
00187     m_begin[index] = (*cast_other)[0];
00188   } else {
00189     // make a new DataVariant that uses the index element as it's array 
00190     ShDataVariant *temp = new ShDataVariant(1, m_begin + index, false);
00191     ShCastManager::instance()->doCast(temp, other);
00192     delete temp; // okay - it doesn't delete its array
00193   }
00194 }
00195 
00196 template<typename T, ShDataType DT>
00197 void ShDataVariant<T, DT>::set(ShVariantCPtr other, int index)
00198 {
00199   set(other.object(), index);
00200 }
00201 
00202 template<typename T, ShDataType DT>
00203 void ShDataVariant<T, DT>::set(const ShVariant* other, bool neg, const ShSwizzle &writemask) 
00204 {
00205   int wmsize = writemask.size();
00206   SH_DEBUG_ASSERT(wmsize == other->size());
00207 
00208   if(writemask.identity() && (wmsize == size())) {
00209     set(other);
00210     if(neg) negate();
00211     return;
00212   }
00213 
00214 
00215   CPtrType cast_other = variant_cast<T, DT>(other);
00216   if(cast_other) {
00217     for(int i = 0; i < wmsize; ++i) {
00218       m_begin[writemask[i]] = (*cast_other)[i];
00219     }
00220     if(neg) negate();
00221   } else {
00222   // otherwise we need a temp buffer variant...doh
00223     ShDataVariant *temp = new ShDataVariant(wmsize);
00224     ShCastManager::instance()->doCast(temp, other);
00225     for(int i = 0; i < wmsize; ++i) {
00226       m_begin[writemask[i]] = neg ? -(*temp)[i] : (*temp)[i];
00227     }
00228     delete temp;
00229   }
00230 }
00231 
00232 template<typename T, ShDataType DT>
00233 void ShDataVariant<T, DT>::set(ShVariantCPtr other, bool neg, const ShSwizzle &writemask) 
00234 {
00235   set(other.object(), neg, writemask);
00236 }
00237 
00238 template<typename T, ShDataType DT>
00239 ShVariantPtr ShDataVariant<T, DT>::get() const
00240 {
00241   return new ShDataVariant<T, DT>(*this);
00242 }
00243 
00244 template<typename T, ShDataType DT>
00245 ShVariantPtr ShDataVariant<T, DT>::get(int index) const
00246 {
00247   return new ShDataVariant<T, DT>(1, m_begin[index]);
00248 }
00249 
00250 template<typename T, ShDataType DT>
00251 ShVariantPtr ShDataVariant<T, DT>::get(bool neg, const ShSwizzle &swizzle, int count) const 
00252 {
00253   return new ShDataVariant<T, DT>(*this, neg, swizzle, count);
00254 }
00255 
00256 
00257 template<typename T, ShDataType DT>
00258 bool ShDataVariant<T, DT>::equals(const ShVariant* other) const 
00259 {
00260   if(!other || (size() != other->size()) 
00261       || !other->typeMatches(valueType(), dataType())) return false;
00262 
00263   const ShDataVariant* castOther = variant_cast<T, DT>(other);
00264   const_iterator I, J;
00265   I = m_begin; 
00266   J = castOther->begin(); 
00267   for(;I != m_end; ++I, ++J) {
00268     if(!shDataTypeEqual((*I), (*J))) return false;
00269   }
00270   return true;
00271 }
00272 
00273 template<typename T, ShDataType DT>
00274 bool ShDataVariant<T, DT>::equals(ShVariantCPtr other) const 
00275 {
00276   return equals(other.object());
00277 }
00278 
00279 template<typename T, ShDataType DT>
00280 bool ShDataVariant<T, DT>::isTrue() const 
00281 {
00282   for(const_iterator I = begin(); I != end(); ++I) {
00283     if(!shDataTypeIsPositive((*I))) return false;
00284   }
00285   return true;
00286 }
00287 
00288 template<typename T, ShDataType DT>
00289 void* ShDataVariant<T, DT>::array()
00290 {
00291   return m_begin;
00292 }
00293 
00294 template<typename T, ShDataType DT>
00295 const void* ShDataVariant<T, DT>::array() const
00296 {
00297   return m_begin;
00298 }
00299 
00300 template<typename T, ShDataType DT>
00301 typename ShDataVariant<T, DT>::DataType& ShDataVariant<T, DT>::operator[](int index) 
00302 {
00303   return m_begin[index];
00304 }
00305 
00306 template<typename T, ShDataType DT>
00307 const typename ShDataVariant<T, DT>::DataType& ShDataVariant<T, DT>::operator[](int index) const
00308 {
00309   return m_begin[index];
00310 }
00311 
00312 template<typename T, ShDataType DT>
00313 typename ShDataVariant<T, DT>::iterator ShDataVariant<T, DT>::begin() {
00314   return m_begin;
00315 }
00316 
00317 template<typename T, ShDataType DT>
00318 typename ShDataVariant<T, DT>::iterator ShDataVariant<T, DT>::end() {
00319   return m_end;
00320 }
00321 
00322 template<typename T, ShDataType DT>
00323 typename ShDataVariant<T, DT>::const_iterator ShDataVariant<T, DT>::begin() const {
00324   return m_begin;
00325 }
00326 
00327 template<typename T, ShDataType DT>
00328 typename ShDataVariant<T, DT>::const_iterator ShDataVariant<T, DT>::end() const {
00329   return m_end;
00330 }
00331 
00332 template<typename T, ShDataType DT>
00333 std::string ShDataVariant<T, DT>::encode() const {
00334   if(size() < 1) return "";
00335 
00336   std::ostringstream out;
00337   out << size();
00338   for(const_iterator I = m_begin; I != m_end; ++I) {
00339     out << "," << *I;
00340   }
00341   return out.str();
00342 }
00343 template<typename T, ShDataType DT>
00344 std::string ShDataVariant<T, DT>::encode(int index, int repeats) const 
00345 {
00346   std::ostringstream out;
00347   out << repeats;
00348   for(int i = 0; i < repeats; ++i) {
00349     out << ", " << m_begin[index];
00350   }
00351   return out.str();
00352 }
00353 
00354 template<typename T, ShDataType DT>
00355 std::string ShDataVariant<T, DT>::encode(bool neg, const ShSwizzle &swizzle) const 
00356 {
00357   std::ostringstream out;
00358   out << swizzle.size(); 
00359   for(int i = 0; i < swizzle.size(); ++i) {
00360     out << ", " << m_begin[swizzle[i]];
00361   }
00362   return out.str();
00363 }
00364 
00365 template<typename T, ShDataType DT>
00366 std::string ShDataVariant<T, DT>::encodeArray() const {
00367   if(size() < 1) return "";
00368 
00369   std::ostringstream out;
00370   for(const_iterator I = m_begin; I != m_end; ++I) {
00371     if(I != m_begin) out << ", ";
00372     out << *I;
00373   }
00374   return out.str();
00375 }
00376 
00377 template<typename T, ShDataType DT>
00378 void ShDataVariant<T, DT>::alloc(int N) {
00379   // SH_DEBUG_PRINT("alloc " << valueTypeName[V] << " " << dataTypeName[DT]);
00380   m_begin = new DataType[N];
00381   m_end = m_begin + N;
00382 }
00383 
00384 #ifdef SH_USE_MEMORY_POOL
00385 template<typename T, ShDataType DT>
00386 void* ShDataVariant<T, DT>::operator new(std::size_t size)
00387 {
00388   if (size != sizeof(ShDataVariant)) return ::operator new(size);
00389   if (!m_pool) {
00390     m_pool = new ShPool(sizeof(ShDataVariant), 32768);
00391   }
00392   return m_pool->alloc();
00393 }
00394 
00395 template<typename T, ShDataType DT>
00396 void ShDataVariant<T, DT>::operator delete(void* ptr, std::size_t size)
00397 {
00398   if(size != sizeof(ShDataVariant)) {
00399     SH_DEBUG_PRINT("delete size does not match " << size << " " << sizeof(ShDataVariant));
00400   }
00401   if(!m_pool) shError( ShException( "Deleting from memory pool without an m_pool." ) );
00402   m_pool->free(ptr);
00403 }
00404 #endif
00405 
00406 template<typename T, ShDataType DT>
00407 inline
00408 ShPointer<ShDataVariant<T, DT> > variant_cast(ShVariantPtr c)
00409 {
00410   return shref_dynamic_cast<ShDataVariant<T, DT> >(c);
00411 }
00412 
00413 template<typename T, ShDataType DT>
00414 inline
00415 ShPointer<const ShDataVariant<T, DT> > variant_cast(ShVariantCPtr c)
00416 {
00417   return shref_dynamic_cast<const ShDataVariant<T, DT> >(c);
00418 }
00419 
00420 template<typename T, ShDataType DT>
00421 inline
00422 ShDataVariant<T, DT>* variant_cast(ShVariant* c)
00423 {
00424   return dynamic_cast<ShDataVariant<T, DT>*>(c);
00425 }
00426 
00427 template<typename T, ShDataType DT>
00428 inline
00429 const ShDataVariant<T, DT>* variant_cast(const ShVariant* c)
00430 {
00431   return dynamic_cast<const ShDataVariant<T, DT>*>(c);
00432 }
00433 
00434 template<typename T, ShDataType DT>
00435 ShPointer<ShDataVariant<T, DT> > variant_convert(ShVariantCPtr c)
00436 {
00437   ShDataVariant<T, DT>* result = new ShDataVariant<T, DT>(c->size());
00438   result->set(c);
00439   return result;
00440 }
00441 
00442 }
00443 #endif

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