All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.units.DerivedUnitImpl Maven / Gradle / Ivy

Go to download

The NetCDF-Java Library is a Java interface to NetCDF files, as well as to many other types of scientific data formats.

There is a newer version: 4.3.22
Show newest version
// $Id: DerivedUnitImpl.java 64 2006-07-12 22:30:50Z edavis $
/*
 * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
 *
 * Portions of this software were developed by the Unidata Program at the
 * University Corporation for Atmospheric Research.
 *
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 *
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */
package ucar.units;

/**
 * Provides support for a concrete implementation of derived units.
 * 
 * @author Steven R. Emmerson
 * @version $Id: DerivedUnitImpl.java 64 2006-07-12 22:30:50Z edavis $
 */
public class DerivedUnitImpl extends UnitImpl implements DerivedUnit,
        DerivableUnit {
    private static final long           serialVersionUID = 1L;

    /**
     * The dimensionless derived unit.
     */
    public static final DerivedUnitImpl DIMENSIONLESS    = new DerivedUnitImpl();

    /**
     * The dimension of this derived unit.
     * 
     * @serial
     */
    private/* final */UnitDimension     dimension;

    /**
     * Constructs a dimensionless derived unit from nothing.
     */
    protected DerivedUnitImpl() {
        // dimensionless derived unit
        this(new UnitDimension(), dimensionlessID());
    }

    /**
     * Returns the identifiers associated with the dimensionless, derived unit.
     * 
     * @return The identifiers of the dimensionless, derived unit.
     */
    private static UnitName dimensionlessID() {
        UnitName id;
        try {
            id = UnitName.newUnitName("1", "1", "1");
        }
        catch (final NameException e) {
            id = null;
        }
        return id;
    }

    /**
     * Constructs from a unit dimension. This is a trusted constructor for use
     * by subclasses only.
     * 
     * @param dimension
     *            The unit dimension.
     */
    protected DerivedUnitImpl(final UnitDimension dimension) {
        this(dimension, null);
    }

    /**
     * Constructs from identifiers. This is a trusted constructor for use by
     * subclasses only.
     * 
     * @param id
     *            The identifiers for the unit.
     */
    protected DerivedUnitImpl(final UnitName id) {
        this(null, id);
    }

    /**
     * Constructs from a unit dimension and identifiers. This is a trusted
     * constructor for use by subclasses only.
     * 
     * @param dimension
     *            The unit dimension.
     * @param id
     *            The identifiers for the unit.
     */
    protected DerivedUnitImpl(final UnitDimension dimension, final UnitName id) {
        super(id);
        this.dimension = dimension;
    }

    /**
     * Sets the unit dimension of this derived unit. This is a trusted method
     * for use by subclasses only and should be called only once immediately
     * after construction of this superinstance.
     * 
     * @param dimension
     *            The unit dimension.
     */
    protected void setDimension(final UnitDimension dimension) {
        this.dimension = dimension;
    }

    /**
     * Returns the unit dimension of this derived unit.
     * 
     * @return The unit dimension of this derived unit.
     */
    public final UnitDimension getDimension() {
        return dimension;
    }

    /**
     * Returns the quantity dimension of this derived unit.
     * 
     * @return The quantity dimension of this derived unit.
     */
    public final QuantityDimension getQuantityDimension() {
        return getDimension().getQuantityDimension();
    }

    /*
     * From DerivedUnit:
     */

    /**
     * Indicates if this derived unit is the reciprocal of another derived unit
     * (e.g. "second" and "hertz").
     * 
     * @param that
     *            The other, derived unit.
     */
    public final boolean isReciprocalOf(final DerivedUnit that) {
        return dimension.isReciprocalOf(that.getDimension());
    }

    /*
     * From UnitImpl:
     */

    /**
     * Returns the derived unit that is convertible with this unit. Obviously,
     * the method returns this derived unit.
     * 
     * @return this.
     */
    public final DerivedUnit getDerivedUnit() {
        return this;
    }

    /**
     * Clones the derived unit changing the identifiers.
     * 
     * @param id
     *            The identifiers for the new unit.
     * @return The new unit.
     */
    public final Unit clone(final UnitName id) {
        return new DerivedUnitImpl(dimension, id);
    }

    /**
     * Multiplies this derived unit by another.
     * 
     * @param that
     *            The other unit.
     * @return The product of the two units.
     * @throws MultiplyException
     *             Can't multiply these units.
     */
    @Override
    protected Unit myMultiplyBy(final Unit that) throws MultiplyException {
        Unit result;
        if (dimension.getRank() == 0) {
            result = that;
        }
        else {
            if (!(that instanceof DerivedUnit)) {
                result = that.multiplyBy(this);
            }
            else {
                final UnitDimension thatDimension = ((DerivedUnit) that)
                        .getDimension();
                result = thatDimension.getRank() == 0
                        ? this
                        : new DerivedUnitImpl(dimension
                                .multiplyBy(thatDimension));
            }
        }
        return result;
    }

    /**
     * Divides this derived unit by another.
     * 
     * @param that
     *            The other unit.
     * @return The quotient of the two units.
     * @throws OperationException
     *             Can't divide these units.
     */
    @Override
    protected Unit myDivideBy(final Unit that) throws OperationException {
        Unit result;
        if (dimension.getRank() == 0) {
            result = that.raiseTo(-1);
        }
        else {
            if (!(that instanceof DerivedUnit)) {
                result = that.divideInto(this);
            }
            else {
                final UnitDimension thatDimension = ((DerivedUnit) that)
                        .getDimension();
                result = thatDimension.getRank() == 0
                        ? this
                        : new DerivedUnitImpl(dimension.divideBy(thatDimension));
            }
        }
        return result;
    }

    /**
     * Divides this derived unit into another.
     * 
     * @param that
     *            The other unit.
     * @return The quotient of the two units.
     * @throws OperationException
     *             Can't divide these units.
     */
    @Override
    protected Unit myDivideInto(final Unit that) throws OperationException {
        return that.divideBy(this);
    }

    /**
     * Raises this derived unit to a power.
     * 
     * @param power
     *            The power.
     * @return This derived unit raised to the given power.
     */
    @Override
    protected Unit myRaiseTo(final int power) {
        return power == 1
                ? this
                : new DerivedUnitImpl(dimension.raiseTo(power));
    }

    /**
     * Converts a numerical value from this unit to the derived unit. Obviously,
     * the numerical value is unchanged.
     * 
     * @param amount
     *            The numerical values in this unit.
     * @return The numerical value in the derived unit.
     */
    public final float toDerivedUnit(final float amount) {
        return amount;
    }

    /**
     * Converts a numerical value from this unit to the derived unit. Obviously,
     * the numerical value is unchanged.
     * 
     * @param amount
     *            The numerical values in this unit.
     * @return The numerical value in the derived unit.
     */
    public final double toDerivedUnit(final double amount) {
        return amount;
    }

    /**
     * Converts numerical values from this unit to the derived unit. Obviously,
     * the numerical values are unchanged.
     * 
     * @param input
     *            The numerical values in this unit.
     * @param output
     *            The numerical values in the derived unit. May be the same
     *            array as input.
     * @return output.
     */
    public final float[] toDerivedUnit(final float[] input, final float[] output) {
        if (input != output) {
            System.arraycopy(input, 0, output, 0, input.length);
        }
        return output;
    }

    /**
     * Converts numerical values from this unit to the derived unit. Obviously,
     * the numerical values are unchanged.
     * 
     * @param input
     *            The numerical values in this unit.
     * @param output
     *            The numerical values in the derived unit. May be the same
     *            array as input.
     * @return output.
     */
    public final double[] toDerivedUnit(final double[] input,
            final double[] output) {
        if (input != output) {
            System.arraycopy(input, 0, output, 0, input.length);
        }
        return output;
    }

    /**
     * Converts a numerical value to this unit from the derived unit. Obviously,
     * the numerical value is unchanged.
     * 
     * @param amount
     *            The numerical values in the derived unit.
     * @return The numerical value in this unit.
     */
    public final float fromDerivedUnit(final float amount) {
        return amount;
    }

    /**
     * Converts a numerical value to this unit from the derived unit. Obviously,
     * the numerical value is unchanged.
     * 
     * @param amount
     *            The numerical values in the derived unit.
     * @return The numerical value in this unit.
     */
    public final double fromDerivedUnit(final double amount) {
        return amount;
    }

    /**
     * Converts numerical values to this unit from the derived unit. Obviously,
     * the numerical values are unchanged.
     * 
     * @param input
     *            The numerical values in the derived unit.
     * @param output
     *            The numerical values in this unit. May be the same array as
     *            input.
     * @return output.
     */
    public final float[] fromDerivedUnit(final float[] input,
            final float[] output) {
        return toDerivedUnit(input, output);
    }

    /**
     * Converts numerical values to this unit from the derived unit. Obviously,
     * the numerical values are unchanged.
     * 
     * @param input
     *            The numerical values in the derived unit.
     * @param output
     *            The numerical values in this unit. May be the same array as
     *            input.
     * @return output.
     */
    public final double[] fromDerivedUnit(final double[] input,
            final double[] output) {
        return toDerivedUnit(input, output);
    }

    /**
     * Indicates if values in this unit are convertible with another unit.
     * 
     * @param that
     *            The other unit.
     * @return true if and only if values in this unit are
     *         convertible to values in 
     *				that.
     */
    @Override
    public final boolean isCompatible(final Unit that) {
        final DerivedUnit unit = that.getDerivedUnit();
        return equals(unit) || isReciprocalOf(unit);
    }

    /**
     * Indicates if this derived unit is semantically identical to an object.
     * 
     * @param object
     *            The object
     * @return true if and only if this derived unit is
     *         semantically identical to 
     *				object.
     */
    @Override
    public boolean equals(final Object object) {
        if (this == object) {
            return true;
        }
        if (!(object instanceof DerivedUnit)) {
            return false;
        }
        final DerivedUnit that = (DerivedUnit) object;
        return (this instanceof BaseUnit && that instanceof BaseUnit)
                ? false
                : dimension.equals(that.getDimension());
    }

    /**
     * Returns the hash code of this instance.
     * 
     * @return The hash code of this instance.
     */
    @Override
    public int hashCode() {
        return this instanceof BaseUnit
                ? System.identityHashCode(this)
                : dimension.hashCode();
    }

    /**
     * Indicates if this derived unit is dimensionless.
     * 
     * @return true if and only if this derived unit is
     *         dimensionless.
     */
    public boolean isDimensionless() {
        return dimension.isDimensionless();
    }

    /**
     * Returns a string representation of this unit. If the symbol or name is
     * available, then that is returned; otherwise, the corresponding expression
     * in base units is returned.
     * 
     * @return The string expression for this derived unit.
     */
    @Override
    public String toString() {
        final String string = super.toString(); // get symbol or name
        return string != null
                ? string
                : getCanonicalString();
    }

    /**
     * Returns the canonical string representation of the unit.
     * 
     * @return The canonical string representation.
     */
    public String getCanonicalString() {
        return dimension.toString();
    }

    /**
     * Tests this class.
     */
    public static void main(final String[] args) throws Exception {
        final BaseUnit second = BaseUnit.getOrCreate(UnitName.newUnitName(
                "second", null, "s"), BaseQuantity.TIME);
        System.out.println("second = \"" + second + '"');
        final BaseUnit meter = BaseUnit.getOrCreate(UnitName.newUnitName(
                "meter", null, "m"), BaseQuantity.LENGTH);
        System.out.println("meter = \"" + meter + '"');
        final DerivedUnitImpl meterSecond = (DerivedUnitImpl) meter
                .myMultiplyBy(second);
        System.out.println("meterSecond = \"" + meterSecond + '"');
        final DerivedUnitImpl meterPerSecond = (DerivedUnitImpl) meter
                .myDivideBy(second);
        System.out.println("meterPerSecond = \"" + meterPerSecond + '"');
        final DerivedUnitImpl secondPerMeter = (DerivedUnitImpl) second
                .myDivideBy(meter);
        System.out.println("secondPerMeter = \"" + secondPerMeter + '"');
        System.out.println("meterPerSecond.isReciprocalOf(secondPerMeter)="
                + meterPerSecond.isReciprocalOf(secondPerMeter));
        System.out.println("meter.toDerivedUnit(1.0)="
                + meter.toDerivedUnit(1.0));
        System.out
                .println("meter.toDerivedUnit(new double[] {1,2,3}, new double[3])[1]="
                        + meter.toDerivedUnit(new double[] { 1, 2, 3 },
                                new double[3])[1]);
        System.out.println("meter.fromDerivedUnit(1.0)="
                + meter.fromDerivedUnit(1.0));
        System.out
                .println("meter.fromDerivedUnit(new double[] {1,2,3}, new double[3])[2]="
                        + meter.fromDerivedUnit(new double[] { 1, 2, 3 },
                                new double[3])[2]);
        System.out.println("meter.isCompatible(meter)="
                + meter.isCompatible(meter));
        System.out.println("meter.isCompatible(second)="
                + meter.isCompatible(second));
        System.out.println("meter.equals(meter)=" + meter.equals(meter));
        System.out.println("meter.equals(second)=" + meter.equals(second));
        System.out
                .println("meter.isDimensionless()=" + meter.isDimensionless());
        final Unit sPerS = second.myDivideBy(second);
        System.out.println("sPerS = \"" + sPerS + '"');
        System.out
                .println("sPerS.isDimensionless()=" + sPerS.isDimensionless());
        meterPerSecond.raiseTo(2);
        meter.myDivideBy(meterPerSecond);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy