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
00019
00020
00021
00022
00023
00024
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
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
00191
00192
00193
00194
00195
00196
00197
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
00215
00216
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
00231
00232
00233
00234
00235
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
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
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
00273
00274
00275
00276
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
00305
00306 }
00307
00308 #include "texp_operators.hpp"
00309 #include "texp_operators_prototypes.hpp"
00310
00311 #endif