realroot_doc 0.1.1
|
00001 #ifndef realroot_ARITHM_TEXP_TEMPLATE_EXPRESSION_H 00002 #define realroot_ARITHM_TEXP_TEMPLATE_EXPRESSION_H 00003 #include <iostream> 00004 #include <realroot/assign.hpp> 00005 #include <realroot/texp_sup.hpp> 00006 #include <realroot/texp_structureof.hpp> 00007 00008 namespace mmx { 00009 00010 namespace texp { 00011 00012 template<class F, class X, class Y> 00013 struct operator_iscommutative 00014 { 00015 enum { V = 0 }; 00016 typedef texp::false_t T; 00017 }; 00018 // in place example 00019 // G(r,s,t) (1) ==> r = s; G(r,z) (2) 00020 // (2) is better than (1) if G is "in place" otherwise G(r,z) ==> G(r,s=r,z) (3) 00021 // and (3) is worst than (1). 00022 // note: makes sense if s or t are unevaluated expression, (2) is better because the 00023 // expression s will be evaluated in the same memory space as the following call to operator. 00024 // note: able to "unroll" (a . b. c. d) as r = a, r.= b, r .=c, r .=d 00025 template<class F, class X, class Y> 00026 struct operator_isinplace 00027 { 00028 enum { V = 0 }; 00029 typedef texp::false_t T; 00030 }; 00031 00032 template<class op, class X> 00033 struct unary_operator_prototype 00034 { 00035 typedef X F; 00036 typedef X U; 00037 }; 00038 00039 00040 template<class op, class X, class Y, class SX, class SY> 00041 struct binary_operator_structure_prototype 00042 { 00043 typedef typename sup< X, Y >::T F; 00044 typedef X U; 00045 typedef Y V; 00046 }; 00047 00048 template<class op, class X, class Y> 00049 struct binary_operator_prototype 00050 { 00051 typedef binary_operator_structure_prototype< op, X, Y, 00052 typename structureof<X>::T, 00053 typename structureof<Y>::T > proto; 00054 typedef typename proto::F F; 00055 typedef typename proto::U U; 00056 typedef typename proto::V V; 00057 }; 00058 00059 template<typename O, typename A> struct unary_operator {}; 00060 template<typename O, typename A, typename B> struct binary_operator {}; 00061 template< class A > 00062 struct template_expression_operand { typedef const A & T; }; 00063 template<> 00064 struct template_expression_operand<int> { typedef int T; }; 00065 00066 template<class A> 00067 struct template_expression 00068 { 00069 typedef true_t terminal_t; 00070 typedef A E; 00071 typename template_expression_operand<A>::T a; 00072 inline const A & term() const { return a; }; 00073 template<class X> operator X() { return X(term()); }; 00074 template_expression( const A & a ) : a(a) {}; 00075 }; 00076 00077 00078 template< class O, class A > 00079 struct template_expression< unary_operator<O,A> > 00080 { 00081 typedef false_t terminal_t; 00082 typedef typename unary_operator_prototype<O,typename A::E>::F E; 00083 typedef typename unary_operator_prototype<O,typename A::E>::U L; 00084 00085 A a; 00086 00087 operator E() 00088 { 00089 E tmp; 00090 eval(tmp); 00091 return tmp; 00092 }; 00093 00094 00095 template<class E> inline template_expression( const E& e ): a(e.a) { }; 00096 inline template_expression( const A& _a ): a(_a) {}; 00097 00098 00099 template<class R> 00100 static inline void evalterm ( E & r, R & l ) { L tmp; let::assign(tmp,l); O()(r,l); }; 00101 static inline void evalterm ( E & r, L & l ) { O()(r,l); }; 00102 00103 inline void evaltree( E & r ) const 00104 { 00105 L tmp; 00106 a.eval(tmp); 00107 O()(r,tmp); 00108 }; 00109 00110 inline void eval ( E & r, const false_t & ) const { evaltree( r ); }; 00111 inline void eval ( E & r, const true_t& ) const { evalterm( r, a.a ); }; 00112 inline void eval ( E & r ) const { eval(r,typename A::terminal_t()); }; 00113 template<class R> 00114 inline void eval( R & r ) const 00115 { 00116 E tmp; 00117 eval(tmp); 00118 let::assign(r,tmp); 00119 }; 00120 }; 00121 00122 00123 // evaluation on terminals. 00124 00125 00126 template< class O, class A, class B> 00127 struct template_expression< binary_operator< O, A, B > > 00128 { 00129 typedef texp::false_t false_t; 00130 typedef texp::true_t true_t; 00131 typedef texp::false_t terminal_t; 00132 00133 A a; 00134 B b; 00135 typedef O Operator; 00136 typedef binary_operator_prototype< O, typename A::E, typename B::E > S; 00137 typedef typename S::F E; 00138 typedef typename S::U L; 00139 typedef typename S::V R; 00140 00141 inline operator E() { E tmp; eval(tmp); return tmp; }; 00142 00143 inline template_expression(){}; 00144 template<class E> 00145 inline template_expression( const E& e ) { a = e.a; b = e.b; }; 00146 inline template_expression( const A& _a, const B& _b ) : a(_a), b(_b) {}; 00147 00148 template<class S> 00149 bool operator!=( const S& s ) 00150 { 00151 E tmp; 00152 eval(tmp); 00153 return tmp != s; 00154 }; 00155 00156 public: 00157 inline void eval( E & e, const L & l, const R & r ) const { O()(e,l,r); }; 00158 00159 template<class X> inline 00160 void eval( E & r, const X & a, const R & b ) const 00161 { 00162 using namespace let; 00163 L _a; 00164 let::assign(_a,a); 00165 O()(r,_a,b); 00166 }; 00167 00168 template<class Y> inline 00169 void eval( E & r, const L & a, const Y & b ) const 00170 { 00171 using namespace let; 00172 R _b; 00173 let::assign(_b,b); 00174 O()(r,a,_b); 00175 }; 00176 00177 template<class X, class Y> inline 00178 void eval( E & r, const X & a, const Y & b ) const 00179 { 00180 L _a; 00181 R _b; 00182 using namespace let; 00183 let::assign(_a,a); 00184 let::assign(_b,b); 00185 O()( r, _a, _b ); 00186 }; 00187 00188 inline void _eval_( E& r, const false_t&, const false_t& ) const 00189 { 00190 /* if ( isinplace< O, L, R >::V ) 00191 { 00192 a._eval_(r); 00193 R b_; 00194 b.eval(b_); 00195 eval(r,b.a); 00196 } 00197 else */ 00198 { 00199 L _a; a._eval_(_a); 00200 R _b; b._eval_(_b); 00201 eval(r,_a,_b); 00202 }; 00203 }; 00204 00205 inline void eval( E& r, const false_t&, const false_t& ) const 00206 { 00207 L _a; a._eval_(_a); 00208 R _b; b._eval_(_b); 00209 eval(r,_a,_b); 00210 }; 00211 00212 inline void _eval_( E & r, const false_t&, const true_t& ) const 00213 { 00214 /* if ( isinplace< O, L, R >::V ) (check if E == A::E) 00215 { a._eval_( r ); eval(r,b.a); } 00216 else 00217 */ 00218 00219 { L _a; a._eval_(_a); eval(r,_a,b.a); }; 00220 }; 00221 inline void eval ( E & r, const false_t&, const true_t& ) const 00222 { 00223 L _a; 00224 a._eval_(_a); 00225 eval(r,_a,b.a); 00226 }; 00227 00228 inline void _eval_( E & r, const true_t&, const false_t& ) const 00229 { 00230 /* if ( isinplace< O, L, R >::V && iscommutative< O, L, R >::V ) 00231 { 00232 b._eval_(r); 00233 eval(r,a.a); 00234 } 00235 else */ 00236 { 00237 R b_; 00238 b._eval_(b_); 00239 eval(r,a.a,b_); 00240 }; 00241 }; 00242 00243 inline void eval ( E & r, const true_t&, const false_t& ) const 00244 { R _b; b._eval_(_b); eval(r,a.a,_b); }; 00245 00246 00247 inline void eval ( E & r, const true_t& , const true_t& ) const { eval(r,a.a,b.a); }; 00248 inline void _eval_( E & r, const true_t& , const true_t& ) const { eval(r,a.a,b.a); }; 00249 00250 00251 // evaluation on T which is not the result type F of the operator O(A::E,B::E) 00252 template<class T> inline 00253 void eval( T & r ) const 00254 { 00255 using namespace let; 00256 E tmp; 00257 _eval_(tmp, typename A::terminal_t(), typename B::terminal_t()); 00258 let::assign(r,tmp); 00259 }; 00260 // same thing on temporary object 00261 template<class U> inline 00262 void _eval_( U & r ) const 00263 { 00264 using namespace let; 00265 E tmp; 00266 _eval_(tmp,typename A::terminal_t(), typename B::terminal_t()); 00267 let::assign(r,tmp); 00268 }; 00269 00270 inline void eval( E& r ) const { eval( r, typename A::terminal_t(), typename B::terminal_t() ); }; 00271 inline void _eval_( E& r ) const { _eval_( r, typename A::terminal_t(), typename B::terminal_t() ); }; 00272 //template<class X> operator X() { X tmp; eval(tmp,*this); return tmp; }; 00273 /* operator E() { 00274 E tmp; 00275 _eval_(tmp); 00276 return tmp; 00277 }; 00278 */ 00279 }; 00280 00281 00282 template< class A > inline 00283 std::ostream& operator<<( std::ostream& o, const template_expression<A>& e ) 00284 { 00285 o << (e.a); 00286 return o; 00287 }; 00288 00289 template< class O, class A > inline 00290 std::ostream& operator<<( std::ostream& o, const template_expression< unary_operator< O, A > > & a ) 00291 { 00292 return (o << O::name() << "(" << a.a << ")"); 00293 }; 00294 00295 template< class O, class A, class B > inline 00296 std::ostream& operator<<( std::ostream& o, const template_expression< binary_operator< O, A, B > >& a ) 00297 { 00298 o << O::name() << "("; 00299 o << a.a << "," << a.b << ")"; 00300 return o; 00301 }; 00302 } 00303 00304 //using namespace arithm; 00305 00306 }// end namespace mmx 00307 00308 #include "texp_operators.hpp" 00309 #include "texp_operators_prototypes.hpp" 00310 00311 #endif