basix_doc 0.1
|
00001 00002 /****************************************************************************** 00003 * MODULE : memoize.hpp 00004 * DESCRIPTION: Remember option 00005 * COPYRIGHT : (C) 2007 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 __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 * Different variants of memoizers 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 * The memoizer template class 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 * Memoization macros 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 } // namespace mmx 00198 #endif // __MEMOIZE_HPP