/* Copyright (c) 2018
   Charles Jordan (Hokkaido University, Sapporo, Japan),
   Michael Joswig, Lars Kastner (Technische Universitaet Berlin, Germany)

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
-----------------------------------------------------------------------------
*/

///////////////////////////////////////////////////////////////////////////////
// File: GKZCache.hh
//
// In this class we cache the results of GKZ computations, since they might be
// computed a lot.
///////////////////////////////////////////////////////////////////////////////

#ifndef GKZCACHE_HH
#define GKZCACHE_HH

#include "mptopcom_typedefs.hh"
#include "TriangNode.hh"
#include "Flip.hh"
#include "GKZ.hh"

#include "LRUCache.hh"

template<bool checkFine>
class GKZCache{
   private:
      const gkz_type& gkz;
      mutable LRUCache<TriangNode, gkz_vector_type> triang_cache;
      // mutable LRUCache<Flip, gkz_vector_type> flip_cache;

   public:
      GKZCache(int size, const gkz_type& gkz_in): gkz(gkz_in), triang_cache(size) {}//, flip_cache(size) {}

      gkz_vector_type evaluate(const TriangNode& t) const{
         if(triang_cache.exist(t)){
            return triang_cache.get(t);
         } else {
            gkz_vector_type result;
            if(checkFine){
               result = gkz.evaluate_fine(t);
            } else {
               result = gkz.evaluate(t);
            }
            triang_cache.put(t, result);
            return triang_cache.get(t);
         }
      }
      
      gkz_vector_type evaluate(const Flip& f) const{
         if(checkFine){
            return gkz.evaluate_fine(f);
         } else {
            return gkz.evaluate(f);
         }
      }
      
      gkz_vector_type evaluate(const TriangNode& source, const TriangNode& target) const{
         return evaluate(target) - evaluate(source);
      }

};

#endif
