00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MEMOIZE_HPP
00014 #define __MEMOIZE_HPP
00015 #include <basix/table.hpp>
00016 #include <basix/triple.hpp>
00017 #include <basix/list.hpp>
00018
00020
00021 namespace mmx {
00022
00023
00024
00025
00026
00027 struct std_memoizer {
00028 typedef hard_eq_table table_variant;
00029 };
00030
00031 struct exact_eq_memoizer {
00032 typedef exact_eq_table table_variant;
00033 };
00034
00035 struct equal_memoizer {
00036 typedef equal_table table_variant;
00037 };
00038
00039
00040
00041
00042
00043 template<typename V>
00044 struct memoizer {
00045 typedef typename V::table_variant table_variant;
00046 typedef void (*cleaner) (void);
00047 static bool busy;
00048 static list<cleaner> to_clean;
00049
00050 static inline void start () {
00051 busy= true; }
00052 static inline void end () {
00053 while (!is_nil (to_clean)) {
00054 read_car (to_clean) ();
00055 to_clean= read_cdr (to_clean);
00056 }
00057 busy= false; }
00058
00059 template<typename D, typename S1,
00060 D (*fun) (const S1&)>
00061 struct unary {
00062 typedef D (*fun_type) (const S1&);
00063 static bool busy;
00064 static table<D,S1,table_variant> t;
00065 static void end () {
00066 busy= false;
00067 t= table<D,S1,table_variant> (); }
00068 static inline void start () {
00069 if (!busy) {
00070 busy= true;
00071 to_clean= cons<cleaner> (end, to_clean); } }
00072 };
00073
00074 template<typename D, typename S1, typename S2,
00075 D (*fun) (const S1&, const S2&)>
00076 struct binary {
00077 typedef D (*fun_type) (const S1&, const S2&);
00078 static bool busy;
00079 static table<D,pair<S1,S2>,table_variant> t;
00080 static void end () {
00081 busy= false;
00082 t= table<D,pair<S1,S2>,table_variant> (); }
00083 static inline void start () {
00084 if (!busy) {
00085 busy= true;
00086 to_clean= cons<cleaner> (end, to_clean); } }
00087 };
00088
00089 template<typename D, typename S1, typename S2, typename S3,
00090 D (*fun) (const S1&, const S2&, const S3&)>
00091 struct ternary {
00092 static bool busy;
00093 typedef D (*fun_type) (const S1&, const S2&, const S3&);
00094 static table<D,triple<S1,S2,S3>,table_variant> t;
00095 static void end () {
00096 busy= false;
00097 t= table<D,triple<S1,S2,S3>,table_variant> (); }
00098 static inline void start () {
00099 if (!busy) {
00100 busy= true;
00101 to_clean= cons<cleaner> (end, to_clean); } }
00102 };
00103 };
00104
00105 template<typename V> bool memoizer<V>::busy= false;
00106 template<typename V> list<typename memoizer<V>::cleaner> memoizer<V>::to_clean=
00107 list<typename memoizer<V>::cleaner> ();
00108
00109 template<typename V>
00110 template<typename D, typename S1,
00111 D (*fun) (const S1&)>
00112 bool
00113 memoizer<V>::unary<D,S1,fun>::busy= false;
00114
00115 template<typename V>
00116 template<typename D, typename S1,
00117 D (*fun) (const S1&)>
00118 table<D,S1,typename V::table_variant>
00119 memoizer<V>::unary<D,S1,fun>::t= table<D,S1,typename V::table_variant> ();
00120
00121 template<typename V>
00122 template<typename D, typename S1, typename S2,
00123 D (*fun) (const S1&, const S2&)>
00124 bool
00125 memoizer<V>::binary<D,S1,S2,fun>::busy= false;
00126
00127 template<typename V>
00128 template<typename D, typename S1, typename S2,
00129 D (*fun) (const S1&, const S2&)>
00130 table<D,pair<S1,S2>,typename V::table_variant>
00131 memoizer<V>::binary<D,S1,S2,fun>::t=
00132 table<D,pair<S1,S2>,typename V::table_variant> ();
00133
00134 template<typename V>
00135 template<typename D, typename S1, typename S2, typename S3,
00136 D (*fun) (const S1&, const S2&, const S3&)>
00137 bool
00138 memoizer<V>::ternary<D,S1,S2,S3,fun>::busy= false;
00139
00140 template<typename V>
00141 template<typename D, typename S1, typename S2, typename S3,
00142 D (*fun) (const S1&, const S2&, const S3&)>
00143 table<D,triple<S1,S2,S3>,typename V::table_variant>
00144 memoizer<V>::ternary<D,S1,S2,S3,fun>::t=
00145 table<D,triple<S1,S2,S3>,typename V::table_variant> ();
00146
00147
00148
00149
00150
00151 #define START_MEMOIZER(V,dest,call) \
00152 if (!memoizer<V>::busy) { \
00153 memoizer<V>::start (); \
00154 dest res= call; \
00155 memoizer<V>::end (); \
00156 return res; \
00157 }
00158
00159 #define MEMOIZE_UNARY(V,dest,src1,fun,arg1,lazy) \
00160 typedef memoizer<V>::unary<dest,src1,fun> memo; \
00161 if (!memo::busy) { \
00162 START_MEMOIZER(V,dest,(fun)(arg1)); \
00163 memo::start (); \
00164 } \
00165 dest res; \
00166 if (memo::t->get (arg1, res)) return res; \
00167 res= lazy; \
00168 memo::t [arg1]= res; \
00169 return res;
00170
00171 #define MEMOIZE_BINARY(V,dest,src1,src2,fun,arg1,arg2,lazy) \
00172 typedef memoizer<V>::binary<dest,src1,src2,fun> memo; \
00173 if (!memo::busy) { \
00174 START_MEMOIZER(V,dest,(fun)(arg1,arg2)); \
00175 memo::start (); \
00176 } \
00177 pair<src1,src2> arg (arg1, arg2); \
00178 dest res; \
00179 if (memo::t->get (arg, res)) return res; \
00180 res= lazy; \
00181 memo::t [arg]= res; \
00182 return res;
00183
00184 #define MEMOIZE_TERNARY(V,dest,src1,src2,src3,fun,arg1,arg2,arg3,lazy) \
00185 typedef memoizer<V>::ternary<dest,src1,src2,src3,fun> memo; \
00186 if (!memo::busy) { \
00187 START_MEMOIZER(V,dest,(fun)(arg1,arg2, arg3)); \
00188 memo::start (); \
00189 } \
00190 triple<src1,src2,src3> arg (arg1, arg2, arg3); \
00191 dest res; \
00192 if (memo::t->get (arg, res)) return res; \
00193 res= lazy; \
00194 memo::t [arg]= res; \
00195 return res;
00196
00197 }
00198 #endif // __MEMOIZE_HPP