GiNaC  1.6.2
remember.cpp
Go to the documentation of this file.
00001 
00006 /*
00007  *  GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany
00008  *
00009  *  This program is free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  This program is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with this program; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  */
00023 
00024 #include "function.h"
00025 #include "utils.h"
00026 #include "remember.h"
00027 
00028 #include <stdexcept>
00029 
00030 namespace GiNaC {
00031 
00033 // class remember_table_entry
00035 
00036 remember_table_entry::remember_table_entry(function const & f, ex const & r)
00037   : hashvalue(f.gethash()), seq(f.seq), result(r)
00038 {
00039     ++last_access = access_counter;
00040     successful_hits = 0;
00041 }
00042 
00043 bool remember_table_entry::is_equal(function const & f) const
00044 {
00045     GINAC_ASSERT(f.seq.size()==seq.size());
00046     if (f.gethash()!=hashvalue) return false;
00047     size_t num = seq.size();
00048     for (size_t i=0; i<num; ++i)
00049         if (!seq[i].is_equal(f.seq[i])) return false;
00050     ++last_access = access_counter;
00051     ++successful_hits;
00052     return true;
00053 }
00054 
00055 unsigned long remember_table_entry::access_counter = 0;
00056 
00058 // class remember_table_list
00060 
00061 remember_table_list::remember_table_list(unsigned as, unsigned strat)
00062 {
00063     max_assoc_size = as;
00064     remember_strategy = strat;
00065 }
00066 
00067 
00068 void remember_table_list::add_entry(function const & f, ex const & result)
00069 {
00070     if ((max_assoc_size!=0) &&
00071         (remember_strategy!=remember_strategies::delete_never) &&
00072         (size()>=max_assoc_size)) {
00073         // table is full, we must delete an older entry
00074         GINAC_ASSERT(size()>0); // there must be at least one entry
00075         
00076         switch (remember_strategy) {
00077         case remember_strategies::delete_cyclic: {
00078             // delete oldest entry (first in list)
00079             erase(begin());
00080             break;
00081         }
00082         case remember_strategies::delete_lru: {
00083             // delete least recently used entry
00084             iterator it = begin();
00085             iterator lowest_access_it = it;
00086             unsigned long lowest_access = (*it).get_last_access();
00087             ++it;
00088             while (it!=end()) {
00089                 if ((*it).get_last_access()<lowest_access) {
00090                     lowest_access = (*it).get_last_access();
00091                     lowest_access_it = it;
00092                 }
00093                 ++it;
00094             }
00095             erase(lowest_access_it);
00096             break;
00097         }
00098         case remember_strategies::delete_lfu: {
00099             // delete least frequently used entry
00100             iterator it = begin();
00101             iterator lowest_hits_it = it;
00102             unsigned lowest_hits = (*it).get_successful_hits();
00103             ++it;
00104             while (it!=end()) {
00105                 if ((*it).get_successful_hits()<lowest_hits) {
00106                     lowest_hits = (*it).get_successful_hits();
00107                     lowest_hits_it = it;
00108                 }
00109                 ++it;
00110             }
00111             erase(lowest_hits_it);
00112             break;
00113         }
00114         default:
00115             throw(std::logic_error("remember_table_list::add_entry(): invalid remember_strategy"));
00116         }
00117         GINAC_ASSERT(size()==max_assoc_size-1);
00118     }
00119     push_back(remember_table_entry(f,result));
00120 }
00121 
00122 bool remember_table_list::lookup_entry(function const & f, ex & result) const
00123 {
00124     const_iterator i = begin(), iend = end();
00125     while (i != iend) {
00126         if (i->is_equal(f)) {
00127             result = i->get_result();
00128             return true;
00129         }
00130         ++i;
00131     }
00132     return false;
00133 }
00134 
00136 // class remember_table
00138 
00139 remember_table::remember_table()
00140 {
00141     table_size=0;
00142     max_assoc_size=0;
00143     remember_strategy=remember_strategies::delete_never;
00144 }
00145 
00146 remember_table::remember_table(unsigned s, unsigned as, unsigned strat)
00147   : max_assoc_size(as), remember_strategy(strat)
00148 {
00149     // we keep max_assoc_size and remember_strategy if we need to clear
00150     // all entries
00151     
00152     // use some power of 2 next to s
00153     table_size = 1 << log2(s);
00154     init_table();
00155 }
00156 
00157 bool remember_table::lookup_entry(function const & f, ex & result) const
00158 {
00159     unsigned entry = f.gethash() & (table_size-1);
00160     GINAC_ASSERT(entry<size());
00161     return operator[](entry).lookup_entry(f,result);
00162 }
00163 
00164 void remember_table::add_entry(function const & f, ex const & result)
00165 {
00166     unsigned entry = f.gethash() & (table_size-1);
00167     GINAC_ASSERT(entry<size());
00168     operator[](entry).add_entry(f,result);
00169 }        
00170 
00171 void remember_table::clear_all_entries()
00172 {
00173     clear();
00174     init_table();
00175 }
00176 
00177 void remember_table::init_table()
00178 {
00179     reserve(table_size);
00180     for (unsigned i=0; i<table_size; ++i)
00181         push_back(remember_table_list(max_assoc_size,remember_strategy));
00182 }
00183 
00184 std::vector<remember_table> & remember_table::remember_tables()
00185 {
00186     static std::vector<remember_table> rt = std::vector<remember_table>();
00187     return rt;
00188 }
00189 
00190 } // namespace GiNaC

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.