// DoubleTuple.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, Tommy Jasmin and Jeff McWhirter. 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 visad.*; import java.rmi.RemoteException; import java.util.Arrays; /** * This provides a LoCal RealTuple that can hold numeric values without * taking the hit that having lots and lots of Real objects around. * * @author MetApps Development Team * @version $Revision: 1.5 $ $Date: 2009-12-01 03:39:21 $ */ public class DoubleTuple extends RealTuple { private Data[] prototypes; /** The numeric values */ double[] doubles; /** The tuple type */ RealTupleType tt; /** The units for the numeric values */ Unit[] units; /** Holds the components as we create them */ Data[] components; /** * Construct a new DoubleTuple of generic values * * @param doubles the values * * @throws VisADException problem creating MathType */ public DoubleTuple(double[] doubles) throws VisADException { this(makeGenericTypes(doubles.length), doubles, null); } /** * Construct a new DoubleTuple * * @param type The type * @param doubles The reals */ public DoubleTuple(RealTupleType type, double[] doubles) { this(type, doubles, null); } /** * Construct a new DoubleTuple * * @param type The type * @param doubles The reals * @param units The units for the reals (may be null) */ public DoubleTuple(RealTupleType type, double[] doubles, Unit[] units) { this(type, null, doubles, units); } public DoubleTuple(RealTupleType type, Data[]prototypes, double[] doubles, Unit[] units) { super(type); this.tt = type; this.prototypes = prototypes; this.doubles = doubles; this.units = units; if (units == null) { this.units = type.getDefaultUnits(); } } /** * Make a RealTupleType of RealType.Generic for num elements * * @param num number of elements * * @return corresponding RealTupleType * * @throws VisADException unable to create the RealTupleType */ private static RealTupleType makeGenericTypes(int num) throws VisADException { RealType[] types = new RealType[num]; Arrays.fill(types, RealType.Generic); return new RealTupleType(types); } /** * Check if there is no Data in this Tuple. * @return true if there is no data. */ public boolean isMissing() { return doubles == null; } /** * Get the i'th component. This creates it if needed and stores * it in the components array * * @param i Which one * * @return The component * * @throws RemoteException On badness * @throws VisADException On badness */ public Data getComponent(int i) throws VisADException, RemoteException { if (components == null) { components = new Data[getDimension()]; } if (0 <= i && i < getDimension()) { if (components[i] == null) { components[i] = getComponentInner(i); if (components[i] != null) { ((DataImpl) components[i]).setParent(this); } } return components[i]; } else { throw new TypeException("Tuple: component index out of range: "+i); } } /** * Actually get the component * * @param i index * * @return The component * * @throws RemoteException On badness * @throws VisADException */ private Data getComponentInner(int i) throws VisADException, RemoteException { //System.err.println ("get component:" +tt.getComponent(i)); if ((doubles != null)) { if(prototypes!=null) { return ((Real) prototypes[i]).cloneButValue(doubles[i]); } if ((units == null) || (units[i] == null)) { return new Real((RealType) tt.getComponent(i), doubles[i]); } else { return new Real((RealType) tt.getComponent(i), doubles[i], units[i]); } } return null; } /** * Create, if needed, and return the component array. * * @return components */ public Data[] getComponents(boolean copy) { try { //Create the array and populate it if needed if (components == null) { components = new Data[getDimension()]; } for (int i = 0; i < getDimension(); i++) { components[i] = getComponent(i); } return components; } catch (Exception exc) { throw new IllegalStateException("Error making component array:"+exc); } } /** * Get Units of Real components * * @return the units of the components */ public Unit[] getTupleUnits() { return Unit.copyUnitsArray(units); } /** * Get the values of the Real components * @return double array of the values of each Real component */ public double[] getValues() { if (doubles == null) { return null; } return (double[]) doubles.clone(); } /** * Indicates if this Tuple is identical to an object. * * @param obj The object. * @return <code>true</code> if and only if the object is * a Tuple and both Tuple-s have identical component * sequences. */ public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof DoubleTuple)) { return false; } DoubleTuple that = (DoubleTuple) obj; return Arrays.equals(doubles, that.doubles) && tt.equals(that.tt) && Arrays.equals(units, that.units); } /** * Returns the hash code of this object. * @return The hash code of this object. */ public int hashCode() { int hashCode = 0; if (doubles != null) { hashCode ^= doubles.hashCode(); } hashCode ^= tt.hashCode(); return hashCode; } /** * run 'java visad.DoubleTuple' to test the RealTuple class * * @param args ignored * * @throws RemoteException Java RMI problem * @throws VisADException Unable to create the VisAD objects */ public static void main(String args[]) throws VisADException, RemoteException { byte b = 10; Real w = new Real(b); Real[] reals1 = {new Real(1), new Real(2), new Real(3)}; //RealTuple rt1 = new RealTuple(reals1); DoubleTuple rt1 = new DoubleTuple(new double[] {1, 2, 3}); DoubleTuple rt2 = new DoubleTuple(new double[] {6, 5, 4}); System.out.println("rt1 = "+rt1+"\nrt2 = "+rt2); System.out.println("rt1 + rt2 = "+rt1.add(rt2)); System.out.println("rt1 - rt2 = "+rt1.subtract(rt2)); System.out.println("rt1 * rt2 = "+rt1.multiply(rt2)); System.out.println("rt1 / rt2 = "+rt1.divide(rt2)); System.out.println("sqrt(rt1) = "+rt1.sqrt()); System.out.println("rt1 + w = "+rt1.add(w)); System.out.println("rt1 - w = "+rt1.subtract(w)); System.out.println("rt1 * w = "+rt1.multiply(w)); System.out.println("rt1 / w = "+rt1.divide(w)); System.out.println("w + rt2 = "+w.add(rt2)); System.out.println("w - rt2 = "+w.subtract(rt2)); System.out.println("w * rt2 = "+w.multiply(rt2)); System.out.println("w / rt2 = "+w.divide(rt2)); RealTupleType tt = RealTupleType.LatitudeLongitudeAltitude; Unit foot = CommonUnit.meter.scale(.3048); // approximate try { foot = visad.data.units.Parser.parse("foot"); } catch (visad.data.units.ParseException pe) {} DoubleTuple one = new DoubleTuple(tt, new double[] {40.5, -105.0, 5338}, new Unit[] {CommonUnit.degree, CommonUnit.degree, foot}); System.out.println("one = "+one.toString()); visad.util.DataUtility.isSerializable(one, true); visad.util.Util.printArray("one.values", one.getValues()); visad.util.Util.printArray("one.units", one.getTupleUnits()); System.out.println("one.cs = "+one.getCoordinateSystem()); DoubleTuple two = new DoubleTuple(tt, new double[] {45, -75.0, 400}); System.out.println("two = "+two.toString()); System.out.println("one - two = "+one.subtract(two)); System.out.println("one + two = "+one.add(two)); } /* Here's the output: rt1 = (1.0, 2.0, 3.0) rt2 = (6.0, 5.0, 4.0) rt1 + rt2 = (7.0, 7.0, 7.0) rt1 - rt2 = (-5.0, -3.0, -1.0) rt1 * rt2 = (6.0, 10.0, 12.0) rt1 / rt2 = (0.16666666666666666, 0.4, 0.75) sqrt(rt1) = (1.0, 1.4142135623730951, 1.7320508075688772) rt1 + w = (11.0, 12.0, 13.0) rt1 - w = (-9.0, -8.0, -7.0) rt1 * w = (10.0, 20.0, 30.0) rt1 / w = (0.1, 0.2, 0.3) w + rt2 = (16.0, 15.0, 14.0) w - rt2 = (4.0, 5.0, 6.0) w * rt2 = (60.0, 50.0, 40.0) w / rt2 = (1.6666666666666667, 2.0, 2.5) one = (40.5, -105.0, 5338.0) one.values: [0]: 40.5 [1]: -105.0 [2]: 5338.0 one.units: [0]: deg [1]: deg [2]: international foot one.cs = null two = (45.0, -75.0, 400.0) one - two = (-4.5, -30.0, 4025.6640419947507) one + two = (85.5, -180.0, 6650.335958005249) */ }