//
// Unit.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.io.Serializable;
/**
* A class that represents a unit of a quantity.
*
* Instances are immutable.
*
* @author Steven R. Emmerson
*
* This is part of Steve Emmerson's Unit package that has been
* incorporated into VisAD.
*/
public abstract class Unit implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The identifier (name or abbreviation) for this unit.
*
* @serial
*/
private final String identifier;
protected transient int hashCode = 0;
/*
* added by Bill Hibbard for VisAD
*/
/**
* <p>
* Converts a tuple of double value arrays; returning a new tuple.
* </p>
*
* <p>
* This implementation uses {@link #toThis(double[], Unit)} to convert the
* individual arrays.
* </p>
*
* @param value
* The tuple of numeric value arrays to convert.
* <code> value[i][j]</code> is the value of the <code> i</code>
* th component of sample-point <code>j </code>.
* @param units_in
* The units of the input numeric values.
* <code>units_in[i]</code> is the unit of the <code>i</code>th
* conponent.
* @param units_out
* The units of the output numeric values.
* <code>units_out[i]</code> is the unit for the <code>i</code>th
* conponent.
* @return Returns the converted values in a new array where RETURN_VALUE
* <code>[i][j]</code> is the converted value of
* <code>value[i][j]</code>.
* @throws UnitException
* If an ouput unit is <code>null</code> and the corresponding
* input unit is neither <code>null</code> nor a
* {@link PromiscuousUnit}, or if an input unit is not
* convertible with its corresponding output unit.
* @throws VisADException
* if a VisAD failure occurs.
*/
public static double[][] convertTuple(final double[][] value,
final Unit[] units_in, final Unit[] units_out)
throws UnitException, VisADException {
return convertTuple(value, units_in, units_out, true);
}
/**
* <p>
* Converts a tuple of double value arrays, optionally returning a new tuple
* depending on the value of <code>copy</code>.
* </p>
*
* <p>
* This implementation uses {@link #toThis(double[], Unit)} to convert the
* individual arrays.
* </p>
*
* @param value
* The tuple of numeric value arrays to convert.
* <code> value[i][j]</code> is the value of the <code> i</code>
* th component of sample-point <code>j </code>.
* @param units_in
* The units of the input numeric values.
* <code>units_in[i]</code> is the unit of the <code>i</code>th
* conponent.
* @param units_out
* The units of the output numeric values.
* <code>units_out[i]</code> is the unit for the <code>i</code>th
* conponent.
* @param copy
* If true, a new array is created, otherwise if a unit in
* <code>units_in</code> equals the unit at the corresponding
* index in the <code>units_out</code>, the input value array at
* that index is returned instead of a new array.
* @return If <code>units_in</code> equals <code>units_out
* </code>
* copy is false, then this just returns the value argument.
* Otherwise, returns the the converted values in a new array where
* RETURN_VALUE <code>[i][j]</code> is the converted value of
* <code>value[i][j]</code>.
* @throws UnitException
* If an ouput unit is <code>null</code> and the corresponding
* input unit is neither <code>null</code> nor a
* {@link PromiscuousUnit}, or if an input unit is not
* convertible with its corresponding output unit.
* @throws VisADException
* if a VisAD failure occurs.
*/
public static double[][] convertTuple(final double[][] value,
final Unit[] units_in, final Unit[] units_out, final boolean copy)
throws UnitException, VisADException {
// If the input array equals the output array then simply return the
// value array
if (java.util.Arrays.equals(units_in, units_out) && !copy) {
return value;
}
final double[][] new_value = new double[value.length][];
for (int i = 0; i < value.length; i++) {
if (units_out[i] == null) {
if (units_in[i] != null
&& !(units_in[i] instanceof PromiscuousUnit)) {
throw new UnitException(
"Unit.convertTuple: illegal Unit conversion");
}
new_value[i] = (copy)
? (double[]) value[i].clone()
: value[i];
}
else {
// If they are equal just do an assignment
if (units_out[i].equals(units_in[i]) && !copy) {
new_value[i] = value[i];
}
else {
// else do the conversion (creates a new array)
new_value[i] = units_out[i].toThis(value[i], units_in[i]);
}
}
}
return new_value;
}
/**
* <p>
* Converts a tuple of float value arrays; returning a new tuple.
* </p>
*
* <p>
* This implementation uses {@link #toThis(float[], Unit)} to convert the
* individual arrays.
* </p>
*
* @param value
* The tuple of numeric value arrays to convert.
* <code> value[i][j]</code> is the value of the <code> i</code>
* th component of sample-point <code>j </code>.
* @param units_in
* The units of the input numeric values.
* <code>units_in[i]</code> is the unit of the <code>i</code>th
* conponent.
* @param units_out
* The units of the output numeric values.
* <code>units_out[i]</code> is the unit for the <code>i</code>th
* conponent.
* @return Returns the converted values in a new array where RETURN_VALUE
* <code>[i][j]</code> is the converted value of
* <code>value[i][j]</code>.
* @throws UnitException
* If an ouput unit is <code>null</code> and the corresponding
* input unit is neither <code>null</code> nor a
* {@link PromiscuousUnit}, or if an input unit is not
* convertible with its corresponding output unit.
* @throws VisADException
* if a VisAD failure occurs.
*/
public static float[][] convertTuple(final float[][] value,
final Unit[] units_in, final Unit[] units_out)
throws UnitException, VisADException {
return convertTuple(value, units_in, units_out, true);
}
/**
* <p>
* Converts a tuple of float value arrays, optionally returning a new tuple
* depending on the value of <code>copy</code>.
* </p>
*
* <p>
* This implementation uses {@link #toThis(float[], Unit)} to convert the
* individual arrays.
* </p>
*
* @param value
* The tuple of numeric value arrays to convert.
* <code> value[i][j]</code> is the value of the <code> i</code>
* th component of sample-point <code>j </code>.
* @param units_in
* The units of the input numeric values.
* <code>units_in[i]</code> is the unit of the <code>i</code>th
* conponent.
* @param units_out
* The units of the output numeric values.
* <code>units_out[i]</code> is the unit for the <code>i</code>th
* conponent.
* @param copy
* If true, a new array is created, otherwise if a unit in
* <code>units_in</code> equals the unit at the corresponding
* index in the <code>units_out</code>, the input value array at
* that index is returned instead of a new array.
* @return If <code>units_in</code> equals <code>units_out
* </code>
* copy is false, then this just returns the value argument.
* Otherwise, returns the the converted values in a new array where
* RETURN_VALUE <code>[i][j]</code> is the converted value of
* <code>value[i][j]</code>.
* @throws UnitException
* If an ouput unit is <code>null</code> and the corresponding
* input unit is neither <code>null</code> nor a
* {@link PromiscuousUnit}, or if an input unit is not
* convertible with its corresponding output unit.
* @throws VisADException
* if a VisAD failure occurs.
*/
public static float[][] convertTuple(final float[][] value,
final Unit[] units_in, final Unit[] units_out, final boolean copy)
throws UnitException, VisADException {
// If the input array equals the output array then simply return the
// value array
if (java.util.Arrays.equals(units_in, units_out) && !copy) {
return value;
}
final float[][] new_value = new float[value.length][];
for (int i = 0; i < value.length; i++) {
if (units_out[i] == null) {
if (units_in[i] != null
&& !(units_in[i] instanceof PromiscuousUnit)) {
throw new UnitException(
"Unit.convertTuple: illegal Unit conversion");
}
new_value[i] = (copy)
? (float[]) value[i].clone()
: value[i];
}
else {
// If they are equal just do an assignment
if (units_out[i].equals(units_in[i]) && !copy) {
new_value[i] = value[i];
}
else {
// else do the conversion
new_value[i] = units_out[i].toThis(value[i], units_in[i]);
}
}
}
return new_value;
}
/**
* Indicates if values in two units are convertible. The values of two units
* are convertible if each unit is either <code>null</code> or the
* promiscuous unit, or if one unit is neither <code>null</code> nor the
* promiscuous unit and the other unit is either the promiscuous unit or a
* convertible unit.
*
* @param unita
* One unit.
* @param unitb
* The other unit.
* @return <code>true</code> if and only if values in the the two units are
* convertible.
* @see #isConvertible(Unit)
*/
public static boolean canConvert(Unit unita, Unit unitb) {
if (CommonUnit.promiscuous.equals(unita) ||
CommonUnit.promiscuous.equals(unitb)) {
return true;
}
if (unita == null && unitb == null) {
return true;
}
if (unita == null || unitb == null) {
return false;
}
// WLH - real logic goes here
return unita.isConvertible(unitb);
}
/**
* Indicate whether this unit is convertible with another unit. If one unit
* is convertible with another, then the <code>toThis(...)</code>/ and
* <code>toThat(...)</code> methods will not throw a UnitException. Unit A
* is convertible with unit B if and only if unit B is convertible with unit
* A; hence, calling-order is irrelevant.
*
* @param unit
* The other unit.
* @return True if and only if this unit is convertible with the other unit.
*/
public abstract boolean isConvertible(Unit unit);
/**
* <p>
* Indicates whether or not two unit arrays are convertible. Two such arrays
* are convertible if and only if the units of their corresponding elements
* are convertible.
* </p>
*
* <p>
* This implementation uses {@link #canConvert(Unit, Unit)} to determine
* convertibility of the element pairs.
*
* @param unita
* One array of units. May be <code>null</code>.
* @param unitb
* The other array of units. May be <code>null</code>.
* @return <code>true</code> if and only if both unit arrays are
* <code>null</code> or the two unit arrays are element-by-element
* convertible.
*/
public static boolean canConvertArray(Unit[] unita, Unit[] unitb) {
if (unita == null && unitb == null) {
return true;
}
if (unita == null) {
unita = new Unit[unitb.length];
}
if (unitb == null) {
unitb = new Unit[unita.length];
}
final int n = unita.length;
if (n != unitb.length) {
return false;
}
for (int i = 0; i < n; i++) {
if (!canConvert(unita[i], unitb[i])) {
// System.out.println("i = " + i + " " + unita[i] + " != " +
// unitb[i]);
return false;
}
}
return true;
}
/**
* Copys an array of units. This is a helper method for {@link Set},
* {@link RealTupleType}, {@link CoordinateSystem}, etc.
*
* @param units
* The array of units or <code>null</code>.
* @return A copy of the array of units or <code>null</code>. if the input
* array is <code>null</code>.
*/
public static Unit[] copyUnitsArray(final Unit[] units) {
return units == null
? null
: (Unit[]) units.clone();
}
/**
* Indicates whether or not this instance is equal to an object.
*
* @param that
* The object in question.
* @return <code>true</code> if and only if this instance equals the unit.
*/
@Override
public boolean equals(final Object that) {
if (!(that instanceof Unit)) {
return false;
}
return equals((Unit) that);
}
/**
* Abstract method for computing hashcode
*/
@Override
public abstract int hashCode();
/**
* Indicates whether or not this instance is equal to a unit.
*
* @param unit
* The unit.
* @return <code>true</code> if and only if this instance equals the unit.
*/
public abstract boolean equals(Unit unit);
/**
* Transform double values and (optionally) error estimates.
*
* @param unit_out
* The unit of the output numeric values or <code>null</code>.
* @param errors_out
* The output error estimate. <code>errors_out[0]
* </code>
* will contain the output error estimate, which may be
* <code>null</code>.
* @param unit_in
* The unit of the input numeric values.
* @param error_in
* The input error estimate or <code>null</code>.
* @param value
* The input numeric value.
* @return The corresponding, transformed numeric values in the same array
* only if the input and output units were <code>null</code>;
* otherwise, a new array is returned.
* @throws NullPointerException
* if <code>errors_out</code> is <code>null
* </code>
* .
* @throws UnitException
* if the input and output unit aren't convertible.
* @throws VisADException
* if a VisAD failure occurs.
*/
public static double[] transformUnits(final Unit unit_out,
final ErrorEstimate[] errors_out, final Unit unit_in,
final ErrorEstimate error_in, final double[] value)
throws UnitException, VisADException {
return transformUnits(unit_out, errors_out, unit_in, error_in, value,
true);
}
/**
* Transform float values and (optionally) error estimates.
*
* @param unit_out
* The unit of the output numeric values or <code>null</code>.
* @param errors_out
* The output error estimate. <code>errors_out[0]
* </code>
* will contain the output error estimate, which may be
* <code>null</code>.
* @param unit_in
* The unit of the input numeric values.
* @param error_in
* The input error estimate or <code>null</code>.
* @param value
* The input numeric value.
* @return The corresponding, transformed numeric values in the same array
* only if the input and output units were <code>null</code>;
* otherwise, a new array is returned.
* @throws NullPointerException
* if <code>errors_out</code> is <code>null
* </code>
* .
* @throws UnitException
* if the input and output unit aren't convertible.
* @throws VisADException
* if a VisAD failure occurs.
*/
public static float[] transformUnits(final Unit unit_out,
final ErrorEstimate[] errors_out, final Unit unit_in,
final ErrorEstimate error_in, final float[] value)
throws UnitException, VisADException {
return transformUnits(unit_out, errors_out, unit_in, error_in, value,
true);
}
/**
* Transform double values and (optionally) error estimates.
*
* @param unit_out
* The unit of the output numeric values or <code>null</code>.
* @param errors_out
* The output error estimate. <code>errors_out[0]
* </code>
* will contain the output error estimate, which may be
* <code>null</code>.
* @param unit_in
* The unit of the input numeric values.
* @param error_in
* The input error estimate or <code>null</code>.
* @param value
* The input numeric value.
* @param copy
* if false and <code>unit_out</code> equals <code>unit_in</code>
* , transform values in place.
* @return The corresponding, transformed numeric values in the same array
* only if the input and output units were <code>null</code>;
* otherwise, a new array is returned.
* @throws NullPointerException
* if <code>errors_out</code> is <code>null
* </code>
* .
* @throws UnitException
* if the input and output unit aren't convertible.
* @throws VisADException
* if a VisAD failure occurs.
*/
public static double[] transformUnits(final Unit unit_out,
final ErrorEstimate[] errors_out, final Unit unit_in,
final ErrorEstimate error_in, final double[] value,
final boolean copy) throws UnitException, VisADException {
if (unit_out == null || unit_in == null) {
errors_out[0] = error_in;
return (copy)
? (double[]) value.clone()
: value;
}
else {
// convert value array
final double[] val = unit_out.toThis(value, unit_in, copy);
// construct new ErrorEstimate, if needed
if (error_in == null) {
errors_out[0] = null;
}
else {
// scale data.ErrorEstimate for Unit.toThis
final double error = 0.5 * error_in.getErrorValue();
final double mean = error_in.getMean();
final double new_error = Math.abs(unit_out.toThis(mean + error,
unit_in)
- unit_out.toThis(mean - error, unit_in));
errors_out[0] = new ErrorEstimate(val, new_error, unit_out);
}
// return value array
return val;
}
}
/**
* Transform float values and (optionally) error estimates.
*
* @param unit_out
* The unit of the output numeric values or <code>null</code>.
* @param errors_out
* The output error estimate. <code>errors_out[0]
* </code>
* will contain the output error estimate, which may be
* <code>null</code>.
* @param unit_in
* The unit of the input numeric values.
* @param error_in
* The input error estimate or <code>null</code>.
* @param value
* The input numeric value.
* @param copy
* if false and <code>unit_out</code> equals <code>unit_in</code>
* , transform values in place.
* @return The corresponding, transformed numeric values in the same array
* only if the input and output units were <code>null</code>;
* otherwise, a new array is returned.
* @throws NullPointerException
* if <code>errors_out</code> is <code>null
* </code>
* .
* @throws UnitException
* if the input and output unit aren't convertible.
* @throws VisADException
* if a VisAD failure occurs.
*/
public static float[] transformUnits(final Unit unit_out,
final ErrorEstimate[] errors_out, final Unit unit_in,
final ErrorEstimate error_in, final float[] value,
final boolean copy) throws UnitException, VisADException {
if (unit_out == null || unit_in == null) {
errors_out[0] = error_in;
return (copy)
? (float[]) value.clone()
: value;
}
else {
// convert value array
final float[] val = unit_out.toThis(value, unit_in, copy);
// construct new ErrorEstimate, if needed
if (error_in == null) {
errors_out[0] = null;
}
else {
// scale data.ErrorEstimate for Unit.toThis
final double error = 0.5 * error_in.getErrorValue();
final double mean = error_in.getMean();
final double new_error = Math.abs(unit_out.toThis(mean + error,
unit_in)
- unit_out.toThis(mean - error, unit_in));
errors_out[0] = new ErrorEstimate(val, new_error, unit_out);
}
// return value array
return val;
}
}
Unit scale(final double amount, final boolean b) {
return new ScaledUnit(amount, this);
}
/*
* end of added by Bill Hibbard for VisAD
*/
/**
* Constructs from nothing.
*/
protected Unit() {
this.identifier = null;
}
/**
* Constructs from an identifier.
*
* @param identifier
* Name or abbreviation for the unit. May be <code>null</code> or
* empty.
*/
protected Unit(String identifier) {
try {
identifier = adjustCheckAndCache(identifier);
}
catch (final UnitExistsException e) {
System.err.println("WARNING: " + e);
}
this.identifier = identifier;
}
/**
* Adjusts, checks, and caches a unit identifier and its unit.
*
* @param identifier
* Name or abbreviation for the unit. May be <code>null</code> or
* empty.
* @return The identifier adjusted as necessary in order to be valid (e.g.
* whitespace replacement).
* @throws UnitExistsException
* A different unit with the same, non-null and non-empty
* identifier already exists. The identifier and unit are not
* cached.
*/
protected final String adjustCheckAndCache(final String identifier)
throws UnitExistsException {
if (identifier != null && identifier.length() > 0) {
/*
* identifier = identifier.replace(' ', '_'); // ensure no
* whitespace synchronized(identifierMap) { Unit previous =
* (Unit)identifierMap.get(identifier); if (previous != null) throw
* new UnitExistsException(identifier);
* identifierMap.put(identifier, this); }
*/
}
return identifier;
}
/**
* <p>
* Indicates if this instance is dimensionless. A unit is dimensionless if
* it is a measure of a dimensionless quantity like angle or concentration.
* Examples of dimensionless units include radian, degree, steradian, and
* "g/kg".
* </p>
*
* @return True if an only if this unit is dimensionless.
*/
public abstract boolean isDimensionless();
/**
* <p>
* Clones this unit, changing the identifier.
* </p>
*
* <p>
* This implementation uses the {@link #protectedClone(String)} method.
* </p>
*
* @param identifier
* The name or abbreviation for the cloned unit. May be
* <code>null</code> or empty.
* @return A unit equal to this instance but with the given identifier
* (adjusted if necessary).
* @throws UnitException
* The unit may not be cloned. This will only occur if
* <code>getIdentifier()!=null</code>.
* @see #adjustCheckAndCache(String)
*/
public Unit clone(final String identifier) throws UnitException {
return protectedClone(adjustCheckAndCache(identifier));
}
/**
* Clones this unit, changing the identifier.
*
* @param identifier
* The name or abbreviation for the cloned unit. May be
* <code>null</code> or empty. It shall have already passed the
* {@link #adjustCheckAndCache(String)} method.
* @return A unit equal to this instance but with the given identifier.
* @throws UnitException
* if the unit may not be cloned. This will only occur if
* <code>getIdentifier()!=null</code>.
*/
protected abstract Unit protectedClone(String identifier)
throws UnitException;
/**
* Raise this unit to a power.
*
* @param power
* The power to raise this unit by.
* @return The resulting unit.
* require: The unit is not an offset unit.
* promise: The unit has not been modified.
* @exception UnitException
* It's meaningless to raise this unit by a power.
*/
public abstract Unit pow(int power) throws UnitException;
/**
* Returns the N-th root of this unit.
*
* @param root
* The root to take (e.g. 2 means square root). Must not be zero.
* @return The unit corresponding to the <code>root</code>-th root of this
* unit.
* require: The unit is not an offset unit.
* promise: The unit has not been modified.
* @exception UnitException
* It's meaningless to raise this unit by a power.
* @throws IllegalArgumentException
* The root value is zero or the resulting unit would have a
* non-integral unit dimension.
*/
public abstract Unit root(int root) throws IllegalArgumentException,
UnitException;
/**
* Returns the square-root of this unit. This method is identical to
* {@link #root(int root)} with a value of <code>2</code>.
*
* @return The unit corresponding to the square-root of this unit.
* promise: This unit has not been modified.
* @throws IllegalArgumentException
* The resulting unit would have a non-integral unit dimension.
* @throws UnitException
* It is meaningless to take a root of this unit.
*/
public Unit sqrt() throws IllegalArgumentException, UnitException {
return root(2);
}
/**
* Raise a unit to a power.
*
* @param power
* The power to raise this unit by. If this unit is not
* dimensionless, then the value must be integral.
* @return The unit resulting from raising this unit to <code>power</code>.
* @throws UnitException
* It's meaningless to raise this unit by a power.
* @throws IllegalArgumentException
* This unit is not dimensionless and <code>power</code> has a
* non-integral value.
* promise: The unit has not been modified.
*/
public abstract Unit pow(double power) throws UnitException,
IllegalArgumentException;
/**
* Scale this unit by an amount.
*
* @param amount
* The amount by which to scale this unit. E.g. Unit yard =
* meter.scale(0.9144);
* @return A unit equal to this instance scaled by the given amount.
* @exception UnitException
* This unit cannot be scaled.
*/
public abstract Unit scale(final double amount) throws UnitException;
/**
* Shift this unit by an amount.
*
* @param offset
* The amount by which to shift this unit. E.g. Unit celsius =
* kelvin.shift(273.15);
* @return A unit equal to this instance with the origin shifted by the
* given amount.
* @exception UnitException
* The unit subclass is unknown.
*/
public abstract Unit shift(final double offset) throws UnitException;
/**
* Returns the logarithmic unit that has this unit as its reference level.
* Not all units can be used as a reference level.
*
* @param base
* The logarithmic base: one of {@code 2}, {@link Math#E}, or
* {@code 10}.
* @return The logarithmic unit that has this instance as its reference
* level.
* @throws IllegalArgumentException
* if {@code base} isn't one of the allowed values.
* @throws UnitException
* if this unit can't be used as a reference level for a
* logarithmic unit.
*/
public abstract Unit log(final double base) throws UnitException;
/**
* Multiply this unit by another unit.
*
* @param that
* The given unit to multiply this unit by.
* @return The resulting unit.
* @throws UnitException
* It's meaningless to multiply these units.
*/
public abstract Unit multiply(Unit that) throws UnitException;
/**
* Divide this unit by another unit.
*
* @param that
* The unit to divide into this unit.
* @return The quotient of the two units.
* promise: Neither unit has been modified.
* @throws UnitException
* It's meaningless to divide these units.
*/
public abstract Unit divide(Unit that) throws UnitException;
/**
* Divide this unit into another unit.
*
* @param that
* The unit to be divided by this unit.
* @return The quotient of the two units.
* @throws UnitException
* It's meaningless to divide these units.
*/
protected abstract Unit divideInto(Unit that) throws UnitException;
/**
* Convert a value to this unit from another unit.
*
* @param value
* The value in units of the other unit.
* @param that
* The other unit.
* @return The value converted from the other unit to this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public double toThis(final double value, final Unit that)
throws UnitException {
return toThis(new double[] { value }, that, false)[0];
}
/**
* Convert values to this unit from another unit.
*
* @param values
* Values in units of the other unit.
* @param that
* The other unit.
* @return Values in this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public abstract double[] toThis(double[] values, Unit that)
throws UnitException;
/**
* Convert values to this unit from another unit.
*
* @param values
* Values in units of the other unit.
* @param that
* The other unit.
* @return Values in this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public abstract float[] toThis(float[] values, Unit that)
throws UnitException;
/**
* Convert values to this unit from another unit.
*
* @param values
* Values in units of the other unit.
* @param that
* The other unit.
* @param copy
* true to make a copy if units are not equal. Ignored in this
* class.
* @return Values in this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public double[] toThis(final double[] values, final Unit that,
final boolean copy) throws UnitException {
return toThis(values, that);
}
/**
* Convert values to this unit from another unit.
*
* @param values
* Values in units of the other unit.
* @param that
* The other unit.
* @param copy
* true to make a copy if units are not equal. Ignored in this
* class.
* @return Values in this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public float[] toThis(final float[] values, final Unit that,
final boolean copy) throws UnitException {
return toThis(values, that);
}
/**
* Convert a value from this unit to another unit.
*
* @param value
* The value in this unit.
* @param that
* The other unit.
* @return The value in units of the other unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public double toThat(final double value, final Unit that)
throws UnitException {
return toThat(new double[] { value }, that, false)[0];
}
/**
* Convert values from this unit to another unit.
*
* @param values
* The values in this unit.
* @param that
* The other unit.
* @return Values converted to the other unit from this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public abstract double[] toThat(double[] values, Unit that)
throws UnitException;
/**
* Convert values from this unit to another unit.
*
* @param values
* The values in this unit.
* @param that
* The other unit.
* @return Values converted to the other unit from this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public abstract float[] toThat(float[] values, Unit that)
throws UnitException;
/**
* Convert values from this unit to another unit.
*
* @param values
* The values in this unit.
* @param that
* The other unit.
* @param copy
* true to make a copy if units are not equal. Ignored in this
* class.
* @return Values converted to the other unit from this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public double[] toThat(final double[] values, final Unit that,
final boolean copy) throws UnitException {
return toThat(values, that);
}
/**
* Convert values from this unit to another unit.
*
* @param values
* The values in this unit.
* @param that
* The other unit.
* @param copy
* true to make a copy if units are not equal. Ignored in this
* class.
* @return Values converted to the other unit from this unit.
* require: The units are convertible.
* promise: Neither unit has been modified.
* @exception UnitException
* The units are not convertible.
*/
public float[] toThat(final float[] values, final Unit that,
final boolean copy) throws UnitException {
return toThat(values, that);
}
/**
* Returns a string representation of this unit.
*
* @return The string representation of this unit. Won't be
* <code>null</code> but may be empty.
*/
@Override
public final String toString() {
String s = getIdentifier();
if (s == null || s.length() == 0) {
s = getDefinition();
}
return s;
}
/**
* Returns the identifier (name or abbreviation) of this unit.
*
* @return The identifier of this unit. May be <code>null</code> but won't
* be empty.
*/
public final String getIdentifier() {
return identifier;
}
/**
* Returns the definition of this unit.
*
* @return The definition of this unit. Won't be <code>null
* </code>
* but may be empty.
*/
public abstract String getDefinition();
/**
* Gets the absolute unit of this unit. An interval in the underlying
* physical quantity has the same numeric value in an absolute unit of a
* unit as in the unit itself -- but an absolute unit is always referenced
* to the physical origin of the underlying physical quantity. For example,
* the absolute unit corresponding to degrees celsius is degrees kelvin --
* and calling this method on a degrees celsius unit obtains a degrees
* kelvin unit.
*
* @return The absolute unit corresponding to this unit.
*/
public Unit getAbsoluteUnit() {
return this;
}
/**
* Returns the derived unit that underlies this unit.
*
* @return The derived unit that underlies this unit.
*/
public abstract DerivedUnit getDerivedUnit();
private static void myAssert(boolean value) {
if (!value)
throw new AssertionError();
}
/**
* Test this class.
*
* @param args Arguments (ignored).
* @exception UnitException A problem occurred.
*/
public static void main(String[] args) throws UnitException {
BaseUnit m = BaseUnit.addBaseUnit("length", "meter", "m");
Unit one = new DerivedUnit();
myAssert(m.equals(new ScaledUnit(1.0, m)));
myAssert(m.equals(new OffsetUnit(0.0, m)));
myAssert(one.equals(new ScaledUnit(1.0, one)));
myAssert(one.equals(new OffsetUnit(0.0, one)));
myAssert(new ScaledUnit(1.0, m).equals(new OffsetUnit(0.0, m)));
myAssert(new OffsetUnit(0.0, m).equals(new ScaledUnit(1.0, m)));
myAssert(!m.equals(null));
myAssert(!new DerivedUnit(m).equals(null));
myAssert(new DerivedUnit(m).equals(m));
myAssert(m.equals(new DerivedUnit(m)));
System.out.println("Success");
}
}