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

Generated on Wed Jun 15 18:12:42 2005 for Sh by  doxygen 1.4.3-20050530