//
// CachingCoordinateSystem.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

package visad;


import java.util.Arrays;

import visad.util.Util;

import visad.data.ArrayCache;


/**
 * A wrapper class for CoordinateSystems that will cache the last
 * values input and output values of the toReference and fromReference
 * methods.  If the inputs are the same as the last time these
 * methods were called, the previously calculated values are returned.
 *
 * @author Don Murray
 * @version $Revision: 1.11 $ $Date: 2009-12-07 12:16:19 $
 */
public class CachingCoordinateSystem extends CoordinateSystem {

  /** The coordinate system I wrap */
  private CoordinateSystem myCS = null;

  /**  Does the actual caching         */
  private ArrayCache arrayCache = new ArrayCache();

  /** Show time to transform           */
  public static boolean debugTime = 
    Boolean.parseBoolean(System.getProperty("visad.cachingcoordinatesystem.debugtime",
                                            "false"));

  /**  counter to show which object this is         */
  private static int cnt = 0;

  /**  counter to show which object this is         */
  private int mycnt = cnt++;


  /**
   * Construct a new CachingCoordinateSystem that wraps around the input.
   * @param cs CoordinateSystem to wrap
   *
   * @throws VisADException 
   */
  public CachingCoordinateSystem(CoordinateSystem cs) throws VisADException {
    super(cs.getReference(), cs.getCoordinateSystemUnits());
    myCS = cs;
  }


  /**
   * Wrapper around the toReference method of the input CoordinateSystem.
   * If the inputs are the same as the last time this method was called,
   * the previously computed outputs will be returned, otherwise the
   * toReference method of the wrapped CS is called and it's output
   * is returned
   *
   * @param   inputs  values to transform
   * @return  transformed input values.
   * @throws  VisADException  when wrapped CS does
   */
  public double[][] toReference(double[][] inputs) throws VisADException {
    if (inputs == null) return inputs;
    long t1 = System.currentTimeMillis();
    boolean hit = true;
    String key = "toReferenceD";
    ArrayCache.DoubleResult results = arrayCache.get(key, inputs);    
    if (results.values == null) {
      double[][] tmp = results.cloneForCache(inputs);
      results.values = myCS.toReference(inputs);
      arrayCache.put(key, tmp, results);
      hit = false;
    }
    if(debugTime  && results.getShouldCache())
        debugTime(inputs[0].length, key +" hit?" + hit, t1,System.currentTimeMillis());
    //    System.err.println (Util.getStackTrace());

    return results.values;
  }

    private void debugTime(int size, String msg, long t1, long t2) {
        if(size>100 && debugTime && t1!=t2) {
            System.err.println("CCS #" +cnt + " size:" + size+ " " +  msg+" time:" + (t2 - t1));
        }
    }


  /**
   * Wrapper around the fromReference method of the input CoordinateSystem.
   * If the inputs are the same as the last time this method was called,
   * the previously computed outputs will be returned, otherwise the
   * fromReference method of the wrapped CS is called and it's output
   * is returned
   *
   * @param   inputs  values to transform
   * @return  transformed input values.
   * @throws  VisADException  when wrapped CS does
   */
  public double[][] fromReference(double[][] inputs) throws VisADException {
    if (inputs == null) return inputs;

    long t1 = System.currentTimeMillis();
    boolean hit = true;
    String key = "fromReferenceD";
    ArrayCache.DoubleResult results = arrayCache.get(key, inputs);
    if (results.values == null) {
      double[][] tmp = results.cloneForCache(inputs);
      results.values = myCS.fromReference(inputs);
      arrayCache.put(key, tmp, results);
      hit = false;
    }
    if(debugTime  && results.getShouldCache())
        debugTime(inputs[0].length,key +" hit?" + hit, t1,System.currentTimeMillis());
    return results.values;

  }





  /**
   * Wrapper around the toReference method of the input CoordinateSystem.
   * If the inputs are the same as the last time this method was called,
   * the previously computed outputs will be returned, otherwise the
   * toReference method of the wrapped CS is called and it's output
   * is returned
   *
   * @param   inputs  values to transform
   * @return  transformed input values.
   * @throws  VisADException  when wrapped CS does
   */
  public float[][] toReference(float[][] inputs) throws VisADException {
    if (inputs == null) return inputs;

    long t1 = System.currentTimeMillis();
    boolean hit = true;
    String key = "toReferenceF";

    ArrayCache.FloatResult results = arrayCache.get(key, inputs);
    if (results.values == null) {
      float[][] tmp = results.cloneForCache(inputs);
      results.values = myCS.toReference(inputs);
      arrayCache.put(key, tmp, results);
      hit = false;
    }

    if(debugTime  && results.getShouldCache())
        debugTime(inputs[0].length,key +" hit?" + hit, t1,System.currentTimeMillis());
    return results.values;
  }


  /**
   * Wrapper around the fromReference method of the input CoordinateSystem.
   * If the inputs are the same as the last time this method was called,
   * the previously computed outputs will be returned, otherwise the
   * fromReference method of the wrapped CS is called and it's output
   * is returned
   *
   * @param   inputs  values to transform
   * @return  transformed input values.
   * @throws  VisADException  when wrapped CS does
   */
  public float[][] fromReference(float[][] inputs) throws VisADException {
    if (inputs == null) return inputs;
    long t1 = System.currentTimeMillis();
    boolean hit = true;
    String key = "fromReferenceF";
    ArrayCache.FloatResult results = arrayCache.get(key, inputs);
    if (results.values==null) {
      float[][] tmp = results.cloneForCache(inputs);
      results.values = myCS.fromReference(inputs);
      arrayCache.put(key, tmp, results);
      hit = false;
    }
    if(debugTime  && results.getShouldCache())
        debugTime(inputs[0].length,key +" hit?" + hit, t1,System.currentTimeMillis());
    return results.values;
  }

  /**
   * Check for equality of CoordinateSystem objects
   * @param  obj  other object in question
   * @return  true if the object in question is a CachingCoordinateSystem
   *          and it's CS is equal this object's CS
   */
  public boolean equals(Object obj) {
    if (!(obj instanceof CachingCoordinateSystem)) return false;
    CachingCoordinateSystem that = (CachingCoordinateSystem)obj;
    return that.myCS.equals(myCS);
  }

  /**
   * Access to the "cached" CS
   * @return  cached CoordinateSystem
   */
  public CoordinateSystem getCachedCoordinateSystem() {
    return myCS;
  }

  /**
   * A decriptive string of this CS.
   * @return a descriptive String
   */
  public String toString() {
    return "Cached CS: " + myCS.toString();
  }

}


 

Ads help maintain this website.