basix_doc 0.1
|
00001 00002 /****************************************************************************** 00003 * MODULE : routine.hpp 00004 * DESCRIPTION: Abstract routines for generic expressions 00005 * COPYRIGHT : (C) 2006 Joris van der Hoeven 00006 ******************************************************************************* 00007 * This software falls under the GNU general public license and comes WITHOUT 00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00009 * If you don't have this file, write to the Free Software Foundation, Inc., 00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00011 ******************************************************************************/ 00012 00013 #ifndef __ROUTINE_HPP 00014 #define __ROUTINE_HPP 00015 #include <basix/evaluator.hpp> 00016 #include <basix/vector.hpp> 00017 #include <basix/wrap.hpp> 00018 #include <basix/compound.hpp> 00019 00021 00022 namespace mmx { 00023 class environment; 00024 00025 /****************************************************************************** 00026 * Abstraction 00027 *****************************************************************************/ 00028 00029 template<typename T> 00030 struct generic_converter { 00031 static inline T make_concrete (const generic& x) { 00032 return as<T,generic> (x); } 00033 static inline generic make_abstract (const T& x) { 00034 // NOTE: returning as<generic,T> does not seem to call the appropriate 00035 // converter in the case when T=bool. A compiler bug? 00036 return new generic_concrete_rep<T> (x); } 00037 }; 00038 00039 STMPL 00040 struct generic_converter<generic> { 00041 static inline generic make_concrete (const generic& x) { 00042 return x; } 00043 static inline generic make_abstract (const generic& x) { 00044 return x; } 00045 }; 00046 00047 template<typename T> inline T 00048 make_concrete (const generic& x) { 00049 return generic_converter<T>::make_concrete (x); 00050 } 00051 00052 template<typename T> inline generic 00053 make_abstract (const T& x) { 00054 return generic_converter<T>::make_abstract (x); 00055 } 00056 00057 /****************************************************************************** 00058 * Abstract generic routines 00059 ******************************************************************************/ 00060 00061 class routine; 00062 class routine_rep: public rep_struct { 00063 public: 00064 generic name; 00065 public: 00066 inline routine_rep (const generic& name2): name (name2) {} 00067 virtual inline ~routine_rep () {} 00068 virtual generic apply () const; 00069 virtual generic apply (const generic& g1) const; 00070 virtual generic apply (const generic& g1, const generic& g2) const; 00071 virtual generic apply (const vector<generic>& args) const; 00072 virtual vector<nat> signature () const; 00073 virtual void overload (const routine& fun) const; 00074 virtual bool is_overloaded () const; 00075 virtual vector<routine> meanings () const; 00076 virtual generic function_body () const; 00077 virtual generic function_type () const; 00078 virtual routine clone () const; 00079 }; 00080 00081 class routine { 00082 INDIRECT_PROTO (routine, routine_rep) 00083 public: 00084 inline const routine_rep* operator * () const { return rep; } 00085 inline routine (): rep (NULL) {} 00086 inline generic operator () () { 00087 return rep->apply (); } 00088 inline generic operator () (const generic& g1) { 00089 return rep->apply (g1); } 00090 inline generic operator () (const generic& g1, const generic& g2) { 00091 return rep->apply (g1, g2); } 00092 inline generic operator () (const vector<generic>& v) { 00093 return rep->apply (v); } 00094 friend inline bool is_nil (const routine& fun); 00095 }; 00096 INDIRECT_NULL_IMPL (routine, routine_rep) 00097 00098 inline bool is_nil (const routine& fun) { 00099 return fun.rep == NULL; } 00100 inline syntactic flatten (const routine& fun) { 00101 if (is_nil (fun)) return as_syntactic (GEN_NIL); 00102 else return as_syntactic (fun->name); } 00103 00104 WRAP_INDIRECT_IMPL(inline,routine) 00105 00106 /****************************************************************************** 00107 * Evaluation 00108 ******************************************************************************/ 00109 00110 inline generic 00111 eval (const routine& f, const vector<generic>& v) { 00112 return f->apply (v); 00113 } 00114 00115 template<typename C> inline C 00116 eval (const routine& f, const vector<C>& v) { 00117 return as<C> (f->apply (as<vector<generic> > (v))); 00118 } 00119 00120 template<typename C> vector<C> 00121 eval (const vector<routine>& f, const vector<C>& v) { 00122 vector<C> r= fill<C> (N(f)); 00123 for (nat i=0; i<N(f); i++) 00124 r[i]= eval (f[i], v); 00125 return r; 00126 } 00127 00128 /****************************************************************************** 00129 * Concrete generic routines 00130 ******************************************************************************/ 00131 00132 template<typename D> 00133 class nullary_routine_rep: public routine_rep { 00134 typedef D (*function_type) (); 00135 function_type fun; 00136 public: 00137 nullary_routine_rep (const generic& name, function_type fun2): 00138 routine_rep (name), fun (fun2) {} 00139 generic apply () const { 00140 return make_abstract<D> (fun ()); 00141 } 00142 generic apply (const vector<generic>& v) const { 00143 ASSERT (N(v) == 0, "zero arguments expected"); 00144 return apply (); 00145 } 00146 vector<nat> signature () const { 00147 return vec<nat> (type_information<D>::id); 00148 } 00149 }; 00150 00151 template<> 00152 class nullary_routine_rep<void>: public routine_rep { 00153 typedef void (*function_type) (); 00154 function_type fun; 00155 public: 00156 nullary_routine_rep (const generic& name, function_type fun2): 00157 routine_rep (name), fun (fun2) {} 00158 generic apply () const { 00159 fun (); 00160 return void_value (); 00161 } 00162 generic apply (const vector<generic>& v) const { 00163 ASSERT (N(v) == 0, "zero arguments expected"); 00164 return apply (); 00165 } 00166 vector<nat> signature () const { 00167 return vec<nat> ((nat) 0); 00168 } 00169 }; 00170 00171 template<typename D> routine 00172 nullary_routine (const generic& name, D (*fun) ()) { 00173 return new nullary_routine_rep<D> (name, fun); 00174 } 00175 00176 extern generic type_name (nat id); 00177 00178 template<typename D, typename S1> 00179 class unary_routine_rep: public routine_rep { 00180 typedef D (*function_type) (const S1&); 00181 function_type fun; 00182 public: 00183 unary_routine_rep (const generic& name, function_type fun2): 00184 routine_rep (name), fun (fun2) {} 00185 generic apply (const generic& x1) const { 00186 return make_abstract<D> (fun (make_concrete<S1> (x1))); 00187 } 00188 generic apply (const vector<generic>& v) const { 00189 ASSERT (N(v) == 1, "one argument expected"); 00190 return apply (v[0]); 00191 } 00192 vector<nat> signature () const { 00193 return vec<nat> (type_information<D>::id, type_information<S1>::id); 00194 } 00195 }; 00196 00197 template<typename S1> 00198 class unary_routine_rep<void,S1>: public routine_rep { 00199 typedef void (*function_type) (const S1&); 00200 function_type fun; 00201 public: 00202 unary_routine_rep (const generic& name, function_type fun2): 00203 routine_rep (name), fun (fun2) {} 00204 generic apply (const generic& x1) const { 00205 fun (make_concrete<S1> (x1)); 00206 return void_value (); 00207 } 00208 generic apply (const vector<generic>& v) const { 00209 ASSERT (N(v) == 1, "one argument expected"); 00210 return apply (v[0]); 00211 } 00212 vector<nat> signature () const { 00213 return vec<nat> ((nat) 0, type_information<S1>::id); 00214 } 00215 }; 00216 00217 template<typename D, typename S1> routine 00218 unary_routine (const generic& name, D (*fun) (const S1&)) { 00219 return new unary_routine_rep<D,S1> (name, fun); 00220 } 00221 00222 template<typename D, typename S1, typename S2> 00223 class binary_routine_rep: public routine_rep { 00224 typedef D (*function_type) (const S1&, const S2&); 00225 function_type fun; 00226 public: 00227 binary_routine_rep (const generic& name, function_type fun2): 00228 routine_rep (name), fun (fun2) {} 00229 generic apply (const generic& x1, const generic& x2) const { 00230 return make_abstract<D> (fun (make_concrete<S1> (x1), 00231 make_concrete<S2> (x2))); 00232 } 00233 generic apply (const vector<generic>& v) const { 00234 ASSERT (N(v) == 2, "two arguments expected"); 00235 return apply (v[0], v[1]); 00236 } 00237 vector<nat> signature () const { 00238 return vec<nat> (type_information<D>::id, 00239 type_information<S1>::id, 00240 type_information<S2>::id); 00241 } 00242 }; 00243 00244 template<typename S1, typename S2> 00245 class binary_routine_rep<void,S1,S2>: public routine_rep { 00246 typedef void (*function_type) (const S1&, const S2&); 00247 function_type fun; 00248 public: 00249 binary_routine_rep (const generic& name, function_type fun2): 00250 routine_rep (name), fun (fun2) {} 00251 generic apply (const generic& x1, const generic& x2) const { 00252 fun (make_concrete<S1> (x1), make_concrete<S2> (x2)); 00253 return void_value (); 00254 } 00255 generic apply (const vector<generic>& v) const { 00256 ASSERT (N(v) == 2, "two arguments expected"); 00257 return apply (v[0], v[1]); 00258 } 00259 vector<nat> signature () const { 00260 return vec<nat> ((nat) 0, 00261 type_information<S1>::id, 00262 type_information<S2>::id); 00263 } 00264 }; 00265 00266 template<typename D, typename S1, typename S2> routine 00267 binary_routine (const generic& name, D (*f) (const S1&, const S2&)) { 00268 return new binary_routine_rep<D,S1,S2> (name, f); 00269 } 00270 00271 template<typename D, typename S1, typename S2, typename S3> 00272 class ternary_routine_rep: public routine_rep { 00273 typedef D (*function_type) (const S1&, const S2&, const S3&); 00274 function_type fun; 00275 public: 00276 ternary_routine_rep (const generic& name, function_type fun2): 00277 routine_rep (name), fun (fun2) {} 00278 generic apply (const vector<generic>& v) const { 00279 ASSERT (N(v) == 3, "three arguments expected"); 00280 return make_abstract<D> (fun (make_concrete<S1> (v[0]), 00281 make_concrete<S2> (v[1]), 00282 make_concrete<S3> (v[2]))); 00283 } 00284 vector<nat> signature () const { 00285 return vec<nat> (type_information<D>::id, 00286 type_information<S1>::id, 00287 type_information<S2>::id, 00288 type_information<S3>::id); 00289 } 00290 }; 00291 00292 template<typename S1, typename S2, typename S3> 00293 class ternary_routine_rep<void,S1,S2,S3>: public routine_rep { 00294 typedef void (*function_type) (const S1&, const S2&, const S3&); 00295 function_type fun; 00296 public: 00297 ternary_routine_rep (const generic& name, function_type fun2): 00298 routine_rep (name), fun (fun2) {} 00299 generic apply (const vector<generic>& v) const { 00300 ASSERT (N(v) == 3, "three arguments expected"); 00301 fun (make_concrete<S1> (v[0]), 00302 make_concrete<S2> (v[1]), 00303 make_concrete<S3> (v[2])); 00304 return void_value (); 00305 } 00306 vector<nat> signature () const { 00307 return vec<nat> ((nat) 0, 00308 type_information<S1>::id, 00309 type_information<S2>::id, 00310 type_information<S3>::id); 00311 } 00312 }; 00313 00314 template<typename D, typename S1, typename S2, typename S3> routine 00315 ternary_routine (const generic& name, 00316 D (*f) (const S1&, const S2&, const S3&)) { 00317 return new ternary_routine_rep<D,S1,S2,S3> (name, f); 00318 } 00319 00320 template<typename D, typename S1, typename S2, typename S3, typename S4> 00321 class quaternary_routine_rep: public routine_rep { 00322 typedef D (*function_type) (const S1&, const S2&, const S3&, const S4&); 00323 function_type fun; 00324 public: 00325 quaternary_routine_rep (const generic& name, function_type fun2): 00326 routine_rep (name), fun (fun2) {} 00327 generic apply (const vector<generic>& v) const { 00328 ASSERT (N(v) == 4, "four arguments expected"); 00329 return make_abstract<D> (fun (make_concrete<S1> (v[0]), 00330 make_concrete<S2> (v[1]), 00331 make_concrete<S3> (v[2]), 00332 make_concrete<S4> (v[3]))); 00333 } 00334 vector<nat> signature () const { 00335 return vec<nat> (type_information<D>::id, 00336 type_information<S1>::id, 00337 type_information<S2>::id, 00338 type_information<S3>::id, 00339 type_information<S4>::id); 00340 } 00341 }; 00342 00343 template<typename S1, typename S2, typename S3, typename S4> 00344 class quaternary_routine_rep<void,S1,S2,S3,S4>: public routine_rep { 00345 typedef void (*function_type) (const S1&, const S2&, const S3&, const S4&); 00346 function_type fun; 00347 public: 00348 quaternary_routine_rep (const generic& name, function_type fun2): 00349 routine_rep (name), fun (fun2) {} 00350 generic apply (const vector<generic>& v) const { 00351 ASSERT (N(v) == 4, "four arguments expected"); 00352 fun (make_concrete<S1> (v[0]), 00353 make_concrete<S2> (v[1]), 00354 make_concrete<S3> (v[2]), 00355 make_concrete<S4> (v[3])); 00356 return void_value (); 00357 } 00358 vector<nat> signature () const { 00359 return vec<nat> ((nat) 0, 00360 type_information<S1>::id, 00361 type_information<S2>::id, 00362 type_information<S3>::id, 00363 type_information<S4>::id); 00364 } 00365 }; 00366 00367 template<typename D, typename S1, typename S2, typename S3, typename S4> routine 00368 quaternary_routine (const generic& name, 00369 D (*f) (const S1&, const S2&, const S3&,const S4&)) { 00370 return new quaternary_routine_rep<D,S1,S2,S3,S4> (name, f); 00371 } 00372 00373 template<typename D, typename S1, typename S2, typename S3, 00374 typename S4, typename S5> 00375 class quintary_routine_rep: public routine_rep { 00376 typedef D (*function_type) (const S1&, const S2&, const S3&, 00377 const S4&, const S5&); 00378 function_type fun; 00379 public: 00380 quintary_routine_rep (const generic& name, function_type fun2): 00381 routine_rep (name), fun (fun2) {} 00382 generic apply (const vector<generic>& v) const { 00383 ASSERT (N(v) == 5, "five arguments expected"); 00384 return make_abstract<D> (fun (make_concrete<S1> (v[0]), 00385 make_concrete<S2> (v[1]), 00386 make_concrete<S3> (v[2]), 00387 make_concrete<S4> (v[3]), 00388 make_concrete<S4> (v[4]))); 00389 } 00390 vector<nat> signature () const { 00391 return vec<nat> (type_information<D>::id, 00392 type_information<S1>::id, 00393 type_information<S2>::id, 00394 type_information<S3>::id, 00395 type_information<S4>::id, 00396 type_information<S5>::id); 00397 } 00398 }; 00399 00400 template<typename S1, typename S2, typename S3, typename S4, typename S5> 00401 class quintary_routine_rep<void,S1,S2,S3,S4,S5>: public routine_rep { 00402 typedef void (*function_type) (const S1&, const S2&, const S3&, 00403 const S4&, const S5&); 00404 function_type fun; 00405 public: 00406 quintary_routine_rep (const generic& name, function_type fun2): 00407 routine_rep (name), fun (fun2) {} 00408 generic apply (const vector<generic>& v) const { 00409 ASSERT (N(v) == 4, "four arguments expected"); 00410 fun (make_concrete<S1> (v[0]), 00411 make_concrete<S2> (v[1]), 00412 make_concrete<S3> (v[2]), 00413 make_concrete<S4> (v[3]), 00414 make_concrete<S4> (v[4])); 00415 return void_value (); 00416 } 00417 vector<nat> signature () const { 00418 return vec<nat> ((nat) 0, 00419 type_information<S1>::id, 00420 type_information<S2>::id, 00421 type_information<S3>::id, 00422 type_information<S4>::id, 00423 type_information<S5>::id); 00424 } 00425 }; 00426 00427 template<typename D, typename S1, typename S2, typename S3, 00428 typename S4, typename S5> routine 00429 quintary_routine (const generic& name, 00430 D (*f) (const S1&, const S2&, const S3&, 00431 const S4&, const S5&)) { 00432 return new quintary_routine_rep<D,S1,S2,S3,S4,S5> (name, f); 00433 } 00434 00435 /****************************************************************************** 00436 * Other types of routines 00437 ******************************************************************************/ 00438 00439 routine identity_routine (const vector<nat>& sig); 00440 routine compose (const routine& fun, const vector<routine>& args); 00441 inline routine compose (const routine& fun, const routine& arg) { 00442 return compose (fun, vec (arg)); } 00443 routine change_signature (const routine& r, const vector<nat>& sig); 00444 routine default_routine (const generic& name); 00445 routine integrate (const routine& fun); 00446 00447 } // namespace mmx 00448 #endif // __ROUTINE_HPP