basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/include/basix/memoize.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines