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

ShManipulatorImpl.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 SHMANIPULATORIMPL_HPP
00025 #define SHMANIPULATORIMPL_HPP
00026 
00027 #include <cstdarg>
00028 #include <cassert>
00029 #include <sstream>
00030 #include "ShVariableNode.hpp"
00031 #include "ShError.hpp"
00032 #include "ShDebug.hpp"
00033 #include "ShAlgebra.hpp"
00034 #include "ShManipulator.hpp"
00035 #include "ShInstructions.hpp"
00036 
00037 namespace SH {
00038 
00039 // TODO figure out a better way...
00040 #define _FIRST -54545454
00041 #define _SECOND -54545453
00042 #define _LAST 54545454
00043 
00044 template<typename T>
00045 OffsetRange<T>::OffsetRange() {}
00046 
00047 template<typename T>
00048 OffsetRange<T>::OffsetRange( T start, T end )
00049   : start( start ), end( end ), startOffset( 0 ), endOffset( 0 ) {}
00050 
00051 template<typename T>
00052 OffsetRange<T>::OffsetRange( T start, int startOffset, T end, int endOffset )
00053   : start( start ), end( end ), startOffset( startOffset ), endOffset( endOffset ) {}
00054 
00055 template<typename T>
00056 int OffsetRange<T>::absStartIndex( const ShProgramNode::VarList vars ) const {
00057   return absIndex( start, startOffset, vars );
00058 }
00059 
00060 template<typename T>
00061 int OffsetRange<T>::absEndIndex( const ShProgramNode::VarList vars ) const {
00062   return absIndex( end, endOffset, vars );
00063 }
00064 
00065 template<typename T>
00066 std::string OffsetRange<T>::toString() const {
00067   std::ostringstream os;
00068   os << "(" << start << (startOffset >= 0 ? "+" : "" ) << startOffset
00069      << ", " << end << (endOffset >= 0 ? "+" : "" ) << endOffset << ")";
00070   return os.str();
00071 }
00072 
00073 template<typename T>
00074 ShManipulator<T>::ShManipulator() {} 
00075 
00076 template<typename T>
00077 ShManipulator<T>::~ShManipulator() {
00078 } 
00079 
00080 template<typename T>
00081 ShManipulator<T>& ShManipulator<T>::operator()(T i) {
00082   m_ranges.push_back(IndexRange(i, i));
00083   return *this;
00084 }
00085 
00086 template<typename T>
00087 ShManipulator<T>& ShManipulator<T>::operator()(T start, T end) {
00088   m_ranges.push_back(IndexRange(start, end));
00089   return *this;
00090 }
00091 
00092 template<typename T>
00093 ShManipulator<T>& ShManipulator<T>::operator()(const IndexRange &range) {
00094   m_ranges.push_back(range);
00095   return *this;
00096 }
00097 
00098 template<typename T>
00099 typename ShManipulator<T>::IndexRangeVector ShManipulator<T>::getRanges() const { 
00100   return m_ranges;
00101 }
00102 
00103 template<typename T>
00104 std::string ShManipulator<T>::toString() const {
00105   std::ostringstream os;
00106   for(typename IndexRangeVector::const_iterator it = m_ranges.begin(); it != m_ranges.end(); ++it) {
00107     if(it != m_ranges.begin()) os << ", ";
00108     os << it->toString();
00109   }
00110   return os.str();
00111 }
00112 
00113 /* input permutation */
00114 template<typename T>
00115 ShProgram operator<<(const ShProgram &p, const ShManipulator<T> &m) {
00116   typedef typename ShManipulator<T>::IndexRangeVector RangeVec;
00117   RangeVec mranges = m.getRanges();
00118   int i;
00119 
00120   ShProgram permuter = SH_BEGIN_PROGRAM() {
00121     /* Make shader outputs from p's inputs 
00122      * default output value is zero, so for those that have
00123      * no matching inputs, they become zero outputs */
00124     std::vector<ShVariable> outputs;
00125     for(ShProgramNode::VarList::const_iterator inIt = p.node()->inputs.begin();
00126         inIt != p.node()->inputs.end(); ++inIt) {
00127       ShVariable out((*inIt)->clone(SH_OUTPUT));
00128       outputs.push_back(out);
00129     }
00130 
00131     int size = outputs.size();
00132 
00133     /* Make shader outputs from permuted ranges of inputs */
00134     std::vector<bool> used(size, false); //mark used inputs
00135     for(typename RangeVec::const_iterator irvIt = mranges.begin();
00136         irvIt != mranges.end(); ++irvIt) {
00137       int start = irvIt->absStartIndex( p.node()->inputs );
00138       int end = irvIt->absEndIndex( p.node()->inputs ); 
00139 
00140       if(start == OFFSET_RANGE_BAD_OFFSET || end == OFFSET_RANGE_BAD_OFFSET ) continue;
00141       if(start == OFFSET_RANGE_BAD_INDEX || end == OFFSET_RANGE_BAD_INDEX ) {
00142         std::ostringstream os;
00143         os << "Invalid ShManipulator Range " << irvIt->toString() 
00144           << " for an ShProgram with output size " << size;
00145         shError(ShAlgebraException(os.str())); 
00146       }
00147 
00148       for(i = start; i <= end; ++i) {
00149         if(used[i]) {
00150           std::ostringstream os;
00151           os << "Duplicate index " << i << " in range " << irvIt->toString() 
00152             << " not allowed for input manipulators"; 
00153           shError(ShAlgebraException(os.str()));
00154         }
00155         used[i] = true;
00156 
00157         ShVariable input(outputs[i].node()->clone(SH_INPUT));
00158         shASN(outputs[i], input);
00159       }
00160     }
00161   } SH_END;
00162 
00163   return connect(permuter, p); 
00164 }
00165 
00166 template<typename T>
00167 ShProgram operator<<(const ShManipulator<T> &m, const ShProgram &p) {
00168   typedef typename ShManipulator<T>::IndexRangeVector RangeVec;
00169   RangeVec mranges = m.getRanges();
00170 
00171   ShProgram permuter = SH_BEGIN_PROGRAM() {
00172     /* Make shader inputs from p's outputs */
00173     std::vector<ShVariable> inputs;
00174     for(ShProgramNode::VarList::const_iterator outIt = p.node()->outputs.begin();
00175         outIt != p.node()->outputs.end(); ++outIt) {
00176       ShVariable in((*outIt)->clone(SH_INPUT));
00177       inputs.push_back(in);
00178     }
00179 
00180     int size = inputs.size();
00181 
00182     /* Make shader outputs from permuted ranges of inputs */
00183     for(typename RangeVec::const_iterator irvIt = mranges.begin();
00184         irvIt != mranges.end(); ++irvIt) {
00185       int start = irvIt->absStartIndex( p.node()->outputs );
00186       int end = irvIt->absEndIndex( p.node()->outputs ); 
00187 
00188       if(start == OFFSET_RANGE_BAD_OFFSET || end == OFFSET_RANGE_BAD_OFFSET ) continue;
00189       if(start == OFFSET_RANGE_BAD_INDEX || end == OFFSET_RANGE_BAD_INDEX ) {
00190         std::ostringstream os;
00191         os << "Invalid ShManipulator Range " << irvIt->toString() << 
00192           " for an ShProgram with output size " << size;
00193         shError(ShAlgebraException(os.str())); 
00194       }
00195 
00196       for(int i = start; i <= end; ++i) { // handles end < start case
00197         ShVariable output(inputs[i].node()->clone(SH_OUTPUT));
00198         shASN(output, inputs[i]);
00199       }
00200     }
00201   } SH_END;
00202 
00203   return connect(p, permuter); 
00204 }
00205 
00206 template<typename T>
00207 ShManipulator<T> shSwizzle(T i0) {
00208   ShManipulator<T> m;
00209   m(i0);
00210   return m;
00211 }
00212 template<typename T>
00213 ShManipulator<T> shSwizzle(T i0, T i1) {
00214   ShManipulator<T> m;
00215   m(i0); m(i1);
00216   return m;
00217 }
00218 template<typename T>
00219 ShManipulator<T> shSwizzle(T i0, T i1, T i2) {
00220   ShManipulator<T> m;
00221   m(i0); m(i1); m(i2); 
00222   return m;
00223 }
00224 
00225 template<typename T>
00226 ShManipulator<T> shSwizzle(T i0, T i1, T i2, T i3) {
00227   ShManipulator<T> m;
00228   m(i0); m(i1); m(i2); m(i3);
00229   return m;
00230 }
00231 
00232 template<typename T>
00233 ShManipulator<T> shSwizzle(T i0, T i1, T i2, T i3, T i4) {
00234   ShManipulator<T> m;
00235   m(i0); m(i1); m(i2); m(i3); m(i4); 
00236   return m;
00237 }
00238 
00239 template<typename T>
00240 ShManipulator<T> shSwizzle(T i0, T i1, T i2, T i3, T i4, T i5) {
00241   ShManipulator<T> m;
00242   m(i0); m(i1); m(i2); m(i3); m(i4); m(i5); 
00243   return m;
00244 }
00245 
00246 template<typename T>
00247 ShManipulator<T> shSwizzle(T i0, T i1, T i2, T i3, T i4, T i5, T i6) {
00248   ShManipulator<T> m;
00249   m(i0); m(i1); m(i2); m(i3); m(i4); m(i5); m(i6); 
00250   return m;
00251 }
00252 
00253 template<typename T>
00254 ShManipulator<T> shSwizzle(T i0, T i1, T i2, T i3, T i4, T i5, T i6, T i7) {
00255   ShManipulator<T> m;
00256   m(i0); m(i1); m(i2); m(i3); m(i4); m(i5); m(i6); m(i7); 
00257   return m;
00258 }
00259 
00260 template<typename T>
00261 ShManipulator<T> shSwizzle(T i0, T i1, T i2, T i3, T i4, T i5, T i6, T i7, T i8) {
00262   ShManipulator<T> m;
00263   m(i0); m(i1); m(i2); m(i3); m(i4); m(i5); m(i6); 
00264   m(i7); m(i8);
00265   return m;
00266 }
00267 
00268 template<typename T>
00269 ShManipulator<T> shSwizzle(T i0, T i1, T i2, T i3, T i4, T i5, T i6, T i7, T i8, T i9) {
00270   ShManipulator<T> m;
00271   m(i0); m(i1); m(i2); m(i3); m(i4); m(i5); m(i6); 
00272   m(i7); m(i8); m(i9);
00273   return m;
00274 }
00275 
00276 template<typename T>
00277 ShManipulator<T> shSwizzle(std::vector<T> indices) {
00278   ShManipulator<T> m;
00279   for(typename std::vector<T>::iterator it = indices.begin();
00280       it != indices.end(); ++it) {
00281     m(*it);
00282   }
00283   return m;
00284 }
00285 
00286 template<typename T>
00287 ShManipulator<T> shRange(T i) {
00288   ShManipulator<T> m;
00289   m(i);
00290   return m;
00291 }
00292 
00293 template<typename T>
00294 ShManipulator<T> shRange(T start, T end) {
00295   ShManipulator<T> m;
00296   m(start, end);
00297   return m;
00298 }
00299 
00300 template<typename T>
00301 ShManipulator<T> shExtract(T k) {
00302   ShManipulator<T> m;
00303   m(k);
00304   typedef typename ShManipulator<T>::IndexRange Range;
00305   m(Range(k,_FIRST,k,-1));
00306   m(Range(k,1,k,_LAST));
00307   return m;
00308 }
00309 
00310 template<typename T>
00311 ShManipulator<T> shInsert(T k) {
00312   ShManipulator<T> m;
00313   typedef typename ShManipulator<T>::IndexRange Range;
00314   
00315   m(Range(k,_SECOND,k,0));
00316   m(Range(k,_FIRST,k,_FIRST));
00317   m(Range(k,1,k,_LAST));
00318   std::cout << m.toString() << std::endl;
00319   return m;
00320 }
00321 
00322 template<typename T>
00323 ShManipulator<T> shDrop(T k) {
00324   ShManipulator<T> m;
00325   typedef typename ShManipulator<T>::IndexRange Range; 
00326   m(Range(k,_FIRST,k,-1));
00327   m(Range(k,1,k,_LAST));
00328   return m;
00329 }
00330 
00331 }
00332 
00333 #endif

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