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
00029 template<typename T> struct Identity
00030 {
00031 T const& operator()( T const& t )
00032 {
00033 return t;
00034 }
00035 };
00036
00037
00038 template<int N, typename T, typename RT, typename PlusT, typename TimesT>
00039 struct InnerProduct
00040 {
00041
00042
00043
00044 RT operator()( T const* v1, T const* v2 )
00045 {
00046 return PlusT()( InnerProduct<N-1,T,RT,PlusT,TimesT>()(v1,v2),
00047 TimesT()(v1[N-1],v2[N-1]) );
00048 }
00049 RT operator()( T const* v, T const& x )
00050 {
00051 return PlusT()( InnerProduct<N-1,T,RT,PlusT,TimesT>()(v,x),
00052 TimesT()(v[N-1],x) );
00053
00054 }
00055 };
00056
00057 template<typename PlusT, typename T, typename RT, typename TimesT>
00058 struct InnerProduct<1,T,RT,PlusT,TimesT>
00059 {
00060 RT operator()( T const* v1, T const* v2 )
00061 {
00062 return TimesT()( v1[0], v2[0] );
00063 }
00064 RT operator()( T const* v, T const& x )
00065 {
00066 return TimesT()( v[0], x );
00067 }
00068 };
00069
00070
00071
00072 template<int N, typename T, typename CompareT>
00073 inline bool pointwiseCompare( T const* v1, T const* v2 )
00074 {
00075 return InnerProduct< N,T,bool,
00076 std::logical_and<bool>,
00077 CompareT >()( v1, v2 );
00078 }
00079
00080 template<int N, typename T, typename CompareT>
00081 inline bool pointwiseCompare( T const* v, T const& x )
00082 {
00083 return InnerProduct< N,T,bool,
00084 std::logical_and<bool>,
00085 CompareT >()( v, x );
00086 }
00087
00088
00089
00090 template<int N, typename T, typename ReduceT, typename TransformT=Identity<T> >
00091 struct Accum
00092 {
00093 T operator()( T const * v ) const
00094 {
00095 return ReduceT()( TransformT()(v[N-1]), Accum<N-1,T,ReduceT,TransformT>()(v) );
00096 }
00097
00098
00099 T operator()( T const * v, TransformT const& xform ) const
00100 {
00101 return ReduceT()( xform(v,N-1), Accum<N-1,T,ReduceT,TransformT>()(v,xform) );
00102 }
00103 };
00104
00105 template<typename T, typename ReduceT, typename TransformT >
00106 struct Accum<1,T,ReduceT,TransformT>
00107 {
00108 T operator()( T const * v ) const
00109 {
00110 return TransformT()(v[0]);
00111 }
00112
00113
00114 T operator()( T const * v, TransformT const& xform ) const
00115 {
00116 return xform(v,0);
00117 }
00118 };
00119
00120
00121
00122 template<int N, typename T> struct LexLT
00123 {
00124 bool operator()( const T* v1, const T* v2 )
00125 {
00126 return doit( v1+N, v2+N );
00127 }
00128
00129 static bool doit( const T* v1, const T* v2 )
00130 {
00131 if ( v1[-N] < v2[-N] ) return true;
00132 else if ( v1[-N] > v2[-N] ) return false;
00133 else return LexLT<N-1,T>::doit(v1,v2);
00134 }
00135 };
00136
00137 template<typename T> struct LexLT<1,T>
00138 {
00139 bool operator()( const T* v1, const T* v2 )
00140 {
00141 return doit( v1+1, v2+1 );
00142 }
00143 static bool doit( const T* v1, const T* v2 )
00144 {
00145 if ( v1[-1] < v2[-1] ) return true;
00146 else return false;
00147 }
00148 };
00149
00150
00151
00152 template<int N, typename T, typename FunctorT> struct Transform
00153 {
00154 void operator()( T* v )
00155 {
00156 v[N-1] = FunctorT()(v[N-1]);
00157 Transform<N-1,T,FunctorT>()(v);
00158 }
00159 void operator()( T* v, const T& x )
00160 {
00161 v[N-1] = FunctorT()(v[N-1],x);
00162 Transform<N-1,T,FunctorT>()(v,x);
00163 }
00164 void operator()( T* v1, const T* v2 )
00165 {
00166 v1[N-1] = FunctorT()(v1[N-1],v2[N-1]);
00167 Transform<N-1,T,FunctorT>()(v1,v2);
00168 }
00169 };
00170
00171 template<typename T, typename FunctorT> struct Transform<1,T,FunctorT>
00172 {
00173 void operator()( T* v )
00174 {
00175 v[0] = FunctorT()(v[0]);
00176 }
00177 void operator()( T* v, const T& x )
00178 {
00179 v[0] = FunctorT()(v[0],x);
00180 }
00181 void operator()( T* v1, const T* v2 )
00182 {
00183 v1[0] = FunctorT()(v1[0],v2[0]);
00184 }
00185 };
00186
00187
00188
00189 template<int N, int P> struct Pow
00190 {
00191 static const int value = N * Pow<N,P-1>::value;
00192 };
00193
00194 template<int N> struct Pow<N,1>
00195 {
00196 static const int value = N;
00197 };
00198
00199
00200
00201 template<int N, class OP> struct NestedLoop
00202 {
00203 void operator()( int * index, int lo, int hi, OP& op ) const
00204 {
00205 for ( index[N-1]=lo; index[N-1]<hi; ++index[N-1] )
00206 {
00207 NestedLoop<N-1,OP>()( index, lo, hi, op );
00208 }
00209 }
00210 void operator()( int * index, const int * lo, const int * hi, OP& op ) const
00211 {
00212 for ( index[N-1]=lo[N-1]; index[N-1]<hi[N-1]; ++index[N-1] )
00213 {
00214 NestedLoop<N-1,OP>()( index, lo, hi, op );
00215 }
00216 }
00217 };
00218
00219 template<class OP> struct NestedLoop<0,OP>
00220 {
00221 void operator()( int * index, int lo, int hi, OP& op ) const
00222 {
00223 op( index );
00224 }
00225 void operator()( int * index, const int * lo, const int * hi, OP& op ) const
00226 {
00227 op( index );
00228 }
00229 };
00230
00231
00232
00233 template<int N, class OP> struct NestedPrestagedLoop
00234 {
00235 void operator()( int * index, int lo, int hi, OP& op ) const
00236 {
00237 for ( index[N-1]=lo; index[N-1]<hi; ++index[N-1] )
00238 {
00239 op.prestage(N-1);
00240 NestedPrestagedLoop<N-1,OP>()( index, lo, hi, op );
00241 }
00242 }
00243 void operator()( int * index, const int * lo, const int * hi, OP& op ) const
00244 {
00245 for ( index[N-1]=lo[N-1]; index[N-1]<hi[N-1]; ++index[N-1] )
00246 {
00247 op.prestage(N-1);
00248 NestedPrestagedLoop<N-1,OP>()( index, lo, hi, op );
00249 }
00250 }
00251 };
00252
00253 template<class OP> struct NestedPrestagedLoop<0,OP>
00254 {
00255 void operator()( int * index, int lo, int hi, OP& op ) const
00256 {
00257 op( index );
00258 }
00259 void operator()( int * index, const int * lo, const int * hi, OP& op ) const
00260 {
00261 op( index );
00262 }
00263 };
00264
00265
00266
00267
00268
00269
00270 template<int N, class OP> struct dterm
00271 {
00272 void operator()( OP& op ) const
00273 {
00274 dterm<N-1,OP>()( op );
00275 op( N-1 );
00276 }
00277 };
00278
00279 template<class OP> struct dterm<1,OP>
00280 {
00281 void operator()( OP& op ) const
00282 {
00283 op( 0 );
00284 }
00285 };
00286
00287
00288 }
00289
00290 #endif // include guard