// // 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(); } }