00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _METAPROGRAMS_H_
00022 #define _METAPROGRAMS_H_
00023
00024 #include <functional>
00025
00026 namespace Metaprograms {
00027
00028 template<typename T> struct Identity
00029 {
00030 T const& operator()( T const& t ) { return t; }
00031 };
00032
00033
00034 template<int N, typename T, typename RT, typename PlusT, typename TimesT>
00035 struct InnerProduct
00036 {
00037
00038
00039
00040 RT operator()( T const* v1, T const* v2 )
00041 {
00042 return PlusT()( InnerProduct<N-1,T,RT,PlusT,TimesT>()(v1,v2),
00043 TimesT()(v1[N-1],v2[N-1]) );
00044 }
00045 RT operator()( T const* v, T const& x )
00046 {
00047 return PlusT()( InnerProduct<N-1,T,RT,PlusT,TimesT>()(v,x),
00048 TimesT()(v[N-1],x) );
00049
00050 }
00051 };
00052
00053 template<typename PlusT, typename T, typename RT, typename TimesT>
00054 struct InnerProduct<1,T,RT,PlusT,TimesT>
00055 {
00056 RT operator()( T const* v1, T const* v2 )
00057 {
00058 return TimesT()( v1[0], v2[0] );
00059 }
00060 RT operator()( T const* v, T const& x )
00061 {
00062 return TimesT()( v[0], x );
00063 }
00064 };
00065
00066
00067
00068 template<int N, typename T, typename CompareT>
00069 inline bool pointwiseCompare( T const* v1, T const* v2 )
00070 {
00071 return InnerProduct< N,T,bool,
00072 std::logical_and<bool>,
00073 CompareT >()( v1, v2 );
00074 }
00075
00076 template<int N, typename T, typename CompareT>
00077 inline bool pointwiseCompare( T const* v, T const& x )
00078 {
00079 return InnerProduct< N,T,bool,
00080 std::logical_and<bool>,
00081 CompareT >()( v, x );
00082 }
00083
00084
00085
00086 template<int N, typename T, typename ReduceT, typename TransformT=Identity<T> >
00087 struct Accum
00088 {
00089 T operator()( T const * v ) const
00090 {
00091 return ReduceT()( TransformT()(v[N-1]), Accum<N-1,T,ReduceT,TransformT>()(v) );
00092 }
00093
00094
00095 T operator()( T const * v, TransformT const& xform ) const
00096 {
00097 return ReduceT()( xform(v,N-1), Accum<N-1,T,ReduceT,TransformT>()(v,xform) );
00098 }
00099 };
00100
00101 template<typename T, typename ReduceT, typename TransformT >
00102 struct Accum<1,T,ReduceT,TransformT>
00103 {
00104 T operator()( T const * v ) const
00105 {
00106 return TransformT()(v[0]);
00107 }
00108
00109
00110 T operator()( T const * v, TransformT const& xform ) const
00111 {
00112 return xform(v,0);
00113 }
00114 };
00115
00116
00117
00118 template<int N, typename T> struct LexLT
00119 {
00120 bool operator()( const T* v1, const T* v2 )
00121 {
00122 return doit( v1+N, v2+N );
00123 }
00124
00125 static bool doit( const T* v1, const T* v2 )
00126 {
00127 if ( v1[-N] < v2[-N] ) return true;
00128 else if ( v1[-N] > v2[-N] ) return false;
00129 else return LexLT<N-1,T>::doit(v1,v2);
00130 }
00131 };
00132
00133
00134 template<typename T> struct LexLT<1,T>
00135 {
00136 bool operator()( const T* v1, const T* v2 )
00137 {
00138 return doit(v1,v2);
00139 }
00140 static bool doit( const T* v1, const T* v2 )
00141 {
00142 if( v1[-1] < v2[-1] ) return true;
00143 else return false;
00144 }
00145 };
00146
00147
00148
00149 template<int N, typename T, typename FunctorT> struct Transform
00150 {
00151 void operator()( T* v )
00152 {
00153 v[N-1] = FunctorT()(v[N-1]);
00154 Transform<N-1,T,FunctorT>()(v);
00155 }
00156 void operator()( T* v, const T& x )
00157 {
00158 v[N-1] = FunctorT()(v[N-1],x);
00159 Transform<N-1,T,FunctorT>()(v,x);
00160 }
00161 void operator()( T* v1, const T* v2 )
00162 {
00163 v1[N-1] = FunctorT()(v1[N-1],v2[N-1]);
00164 Transform<N-1,T,FunctorT>()(v1,v2);
00165 }
00166 };
00167
00168 template<typename T, typename FunctorT> struct Transform<1,T,FunctorT>
00169 {
00170 void operator()( T* v )
00171 {
00172 v[0] = FunctorT()(v[0]);
00173 }
00174 void operator()( T* v, const T& x )
00175 {
00176 v[0] = FunctorT()(v[0],x);
00177 }
00178 void operator()( T* v1, const T* v2 )
00179 {
00180 v1[0] = FunctorT()(v1[0],v2[0]);
00181 }
00182 };
00183
00184
00185
00186
00187 template<int N, int P> struct Pow
00188 {
00189 static const int value = N * Pow<N,P-1>::value;
00190 };
00191
00192 template<int N> struct Pow<N,1>
00193 {
00194 static const int value = N;
00195 };
00196
00197
00198
00221 template<int N, class OP> struct NestedLoop
00222 {
00223 void operator()( int * index, int lo, int hi, OP& op ) const
00224 {
00225 for( index[N-1]=lo; index[N-1]<hi; ++index[N-1] )
00226 {
00227 NestedLoop<N-1,OP>()( index, lo, hi, op );
00228 }
00229 }
00230 void operator()( int * index, const int * lo, const int * hi, OP& op ) const
00231 {
00232 for( index[N-1]=lo[N-1]; index[N-1]<hi[N-1]; ++index[N-1] )
00233 {
00234 NestedLoop<N-1,OP>()( index, lo, hi, op );
00235 }
00236 }
00237 };
00238
00239
00240 template<class OP> struct NestedLoop<0,OP>
00241 {
00242 void operator()( int * index, int lo, int hi, OP& op ) const
00243 {
00244 op( index );
00245 }
00246 void operator()( int * index, const int * lo, const int * hi, OP& op ) const
00247 {
00248 op( index );
00249 }
00250 };
00251
00252
00253
00254 template<int N, class OP> struct NestedPrestagedLoop
00255 {
00256 void operator()( int * index, int lo, int hi, OP& op ) const
00257 {
00258 for( index[N-1]=lo; index[N-1]<hi; ++index[N-1] )
00259 {
00260 op.prestage(N-1);
00261 NestedPrestagedLoop<N-1,OP>()( index, lo, hi, op );
00262 }
00263 }
00264 void operator()( int * index, const int * lo, const int * hi, OP& op ) const
00265 {
00266 for( index[N-1]=lo[N-1]; index[N-1]<hi[N-1]; ++index[N-1] )
00267 {
00268 op.prestage(N-1);
00269 NestedPrestagedLoop<N-1,OP>()( index, lo, hi, op );
00270 }
00271 }
00272 };
00273
00274
00275 template<class OP> struct NestedPrestagedLoop<0,OP>
00276 {
00277 void operator()( int * index, int lo, int hi, OP& op ) const
00278 {
00279 op( index );
00280 }
00281 void operator()( int * index, const int * lo, const int * hi, OP& op ) const
00282 {
00283 op( index );
00284 }
00285 };
00286
00287
00288
00292 template<int N, class OP> struct dterm
00293 {
00294 void operator()( OP& op ) const
00295 {
00296 dterm<N-1,OP>()( op );
00297 op( N-1 );
00298 }
00299 };
00300
00301 template<class OP> struct dterm<1,OP>
00302 {
00303 void operator()( OP& op ) const
00304 {
00305 op( 0 );
00306 }
00307 };
00308
00309
00310 }
00311
00312 #endif // include guard