ShManipulatorImpl.hpp

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

Generated on Thu Feb 16 14:51:35 2006 for Sh by  doxygen 1.4.6