Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShVariantImpl.hpp

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

Generated on Thu Apr 21 17:32:50 2005 for Sh by  doxygen 1.4.2