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

ucar.units.LogarithmicUnit Maven / Gradle / Ivy

Go to download

The ucar.units Java package is for decoding and encoding formatted unit specifications (e.g. "m/s"), converting numeric values between compatible units (e.g. between "m/s" and "knot"), and for performing arithmetic operations on units (e.g. dividing one unit by another, or raising a unit to a power).

The newest version!
/*
 * Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */
package ucar.units;

import javax.annotation.concurrent.Immutable;

/**
 * Provides support for units that are based on a logarithm of the ratio of a
 * physical quantity to an underlying reference level.
 * 
 * Instances of this class are immutable.
 * 
 * @author Steven R. Emmerson
 */
@Immutable
public final class LogarithmicUnit extends UnitImpl implements DerivableUnit {
    private static final long           serialVersionUID = 1L;

    /**
     * The logarithmic base.
     * 
     * @serial
     */
    private final double                base;

    private final transient double      lnBase;

    /**
     * The reference level.
     * 
     * @serial
     */
    private final DerivableUnit         reference;
    private final transient DerivedUnit derivedUnit;

    /**
     * Constructs from a reference level and a logarithmic base.
     * 
     * @param reference
     *            The reference level. Must be a {@link DerivableUnit}.
     * @param base
     *            The logarithmic base. Must be 2, {@link Math#E}, or 10.
     * @throws IllegalArgumentException
     *             if {@code reference} isn't a {@link DerivableUnit}.
     * @throws IllegalArgumentException
     *             if {@code base} isn't one of the allowed values.
     * @throws NullPointerException
     *             if {@code reference} is {@code null}.
     */
    public LogarithmicUnit(final Unit reference, final double base) {
        this(reference, base, null);
    }

    /**
     * Constructs from a reference level, a logarithmic base, and a unit
     * identifier.
     * 
     * @param reference
     *            The reference level. Must be a {@link DerivableUnit}.
     * @param base
     *            The logarithmic base. Must be 2, {@link Math#E}, or 10.
     * @param id
     *            The identifier for the new unit.
     * @throws IllegalArgumentException
     *             if {@code reference} isn't a {@link DerivableUnit}.
     * @throws IllegalArgumentException
     *             if {@code base} isn't one of the allowed values.
     * @throws NullPointerException
     *             if {@code reference} is {@code null}.
     */
    public LogarithmicUnit(final Unit reference, final double base,
            final UnitName id) {
        super(id);
        if (reference == null) {
            throw new NullPointerException("Null reference argument");
        }
        if (!(reference instanceof DerivableUnit)) {
            throw new IllegalArgumentException("Not a DerivableUnit: "
                    + reference);
        }
        this.reference = (DerivableUnit) reference;
        if (base != 2 && base != 10 && base != Math.E) {
            throw new IllegalArgumentException("Invalid base: " + base);
        }
        this.base = base;
        lnBase = base == Math.E
                ? 1
                : Math.log(base);
        derivedUnit = reference.getDerivedUnit();
    }

    static Unit getInstance(final Unit unit, final double base) {
        return new LogarithmicUnit(unit, base);
    }

    /**
     * Returns the reference level.
     * 
     * @return The reference level.
     */
    public DerivableUnit getReference() {
        return reference;
    }

    /**
     * Returns the logarithmic base.
     * 
     * @return The logarithmic base of this unit.
     */
    public double getBase() {
        return base;
    }

    /*
     * From UnitImpl:
     */

    /**
     * Clones this unit, changing the identifier.
     * 
     * @param id
     *            The identifier for the new unit.
     * @return This unit with its identifier changed.
     */
    public Unit clone(final UnitName id) {
        return new LogarithmicUnit((Unit) reference, getBase(), id);
    }

    /**
     * Multiply this unit by another unit.
     * 
     * @param that
     *            The unit to multiply this unit by. Must be dimensionless.
     * @return The product of this unit and that.
     * @throws MultiplyException
     *             Can't multiply these units together.
     */
    @Override
    protected Unit myMultiplyBy(final Unit that) throws MultiplyException {
        if (!that.isDimensionless()) {
            throw new MultiplyException(that);
        }
        return that instanceof ScaledUnit
                ? new ScaledUnit(((ScaledUnit) that).getScale(), this)
                : this;
    }

    /**
     * Divide this unit by another unit.
     * 
     * @param that
     *            The unit to divide this unit by.
     * @return The quotient of this unit and that.
     * @throws DivideException
     *             Can't divide these units.
     */
    @Override
    protected Unit myDivideBy(final Unit that) throws DivideException {
        if (!that.isDimensionless()) {
            throw new DivideException(that);
        }
        return that instanceof ScaledUnit
                ? new ScaledUnit(1.0 / ((ScaledUnit) that).getScale(), this)
                : this;
    }

    /**
     * Divide this unit into another unit.
     * 
     * @param that
     *            The unit to divide this unit into.
     * @return The quotient of that unit and this unit.
     * @throws DivideException
     *             Can't divide these units.
     */
    @Override
    protected Unit myDivideInto(final Unit that) throws OperationException {
        throw new DivideException(that);
    }

    /**
     * Raise this unit to a power.
     * 
     * @param power
     *            The power to raise this unit by. The only meaningful values
     *            are 0 and 1.
     * @return The result of raising this unit by the power power.
     * @throws RaiseException
     *             Can't raise this unit to {@code power}, which is neither 0
     *             nor 1.
     */
    @Override
    protected Unit myRaiseTo(final int power) throws RaiseException {
        if (power == 0) {
            return DerivedUnitImpl.DIMENSIONLESS;
        }
        if (power == 1) {
            return this;
        }
        throw new RaiseException(this);
    }

    /**
     * Returns the derived unit that is convertible with this unit.
     * 
     * @return The derived unit that is convertible with this unit.
     */
    public DerivedUnit getDerivedUnit() {
        return derivedUnit;
    }

    /**
     * Converts a value in this unit to the equivalent value in the convertible
     * derived unit.
     * 
     * @param amount
     *            The value in this unit.
     * @return The equivalent value in the convertible derived unit.
     * @throws ConversionException
     *             Can't convert between units.
     */
    public float toDerivedUnit(final float amount) throws ConversionException {
        return (float) toDerivedUnit((double) amount);
    }

    /**
     * Converts a value in this unit to the equivalent value in the convertible
     * derived unit.
     * 
     * @param amount
     *            The value in this unit.
     * @return The equivalent value in the convertible derived unit.
     * @throws ConversionException
     *             Can't convert between units.
     */
    public double toDerivedUnit(final double amount) throws ConversionException {
        return reference.toDerivedUnit(Math.exp(amount * lnBase));
    }

    /**
     * Converts values in this unit to the equivalent values in the convertible
     * derived unit.
     * 
     * @param input
     *            The values in this unit.
     * @param output
     *            The equivalent values in the convertible derived unit. May be
     *            the same array as input.
     * @return output.
     * @throws ConversionException
     *             Can't convert between units.
     */
    public float[] toDerivedUnit(final float[] input, final float[] output)
            throws ConversionException {
        for (int i = input.length; --i >= 0;) {
            output[i] = (float) (Math.exp(input[i] * lnBase));
        }
        return reference.toDerivedUnit(output, output);
    }

    /**
     * Converts values in this unit to the equivalent values in the convertible
     * derived unit.
     * 
     * @param input
     *            The values in this unit.
     * @param output
     *            The equivalent values in the convertible derived unit. May be
     *            the same array as input.
     * @return output.
     * @throws ConversionException
     *             Can't convert between units.
     */
    public double[] toDerivedUnit(final double[] input, final double[] output)
            throws ConversionException {
        for (int i = input.length; --i >= 0;) {
            output[i] = Math.exp(input[i] * lnBase);
        }
        return reference.toDerivedUnit(output, output);
    }

    /**
     * Converts a value in the convertible derived unit to the equivalent value
     * in this unit.
     * 
     * @param amount
     *            The value in the convertible derived unit.
     * @return The equivalent value in this unit.
     * @throws ConversionException
     *             Can't convert between units.
     */
    public float fromDerivedUnit(final float amount) throws ConversionException {
        return (float) fromDerivedUnit((double) amount);
    }

    /**
     * Converts a value in the convertible derived unit to the equivalent value
     * in this unit.
     * 
     * @param amount
     *            The value in the convertible derived unit.
     * @return The equivalent value in this unit.
     * @throws ConversionException
     *             Can't convert between units.
     */
    public double fromDerivedUnit(final double amount)
            throws ConversionException {
        return Math.log(reference.fromDerivedUnit(amount)) / lnBase;
    }

    /**
     * Converts values in the convertible derived unit to the equivalent values
     * in this unit.
     * 
     * @param input
     *            The values in the convertible derived unit.
     * @param output
     *            The equivalent values in this unit. May be the same array as
     *            input.
     * @return output.
     * @throws ConversionException
     *             Can't convert between units.
     */
    public float[] fromDerivedUnit(final float[] input, final float[] output)
            throws ConversionException {
        reference.fromDerivedUnit(input, output);
        for (int i = input.length; --i >= 0;) {
            output[i] = (float) (Math.log(output[i]) / lnBase);
        }
        return output;
    }

    /**
     * Converts values in the convertible derived unit to the equivalent values
     * in this unit.
     * 
     * @param input
     *            The values in the convertible derived unit.
     * @param output
     *            The equivalent values in this unit. May be the same array as
     *            input.
     * @return output.
     * @throws ConversionException
     *             Can't convert between units.
     */
    public double[] fromDerivedUnit(final double[] input, final double[] output)
            throws ConversionException {
        reference.fromDerivedUnit(input, output);
        for (int i = input.length; --i >= 0;) {
            output[i] = (float) (Math.log(output[i]) / lnBase);
        }
        return output;
    }

    /**
     * Indicates if this unit is semantically identical to an object.
     * 
     * @param object
     *            The object.
     * @return true if and only if this unit is semantically
     *         identical to object
     *				.
     */
    @Override
    public boolean equals(final Object object) {
        if (this == object) {
            return true;
        }
        if (!(object instanceof LogarithmicUnit)) {
            return false;
        }
        final LogarithmicUnit that = (LogarithmicUnit) object;
        return base == that.base && reference.equals(that.reference);
    }

    /**
     * Returns the hash code of this instance.
     * 
     * @return The hash code of this instance.
     */
    @Override
    public int hashCode() {
        return Double.valueOf(base).hashCode() ^ getReference().hashCode();
    }

    /**
     * Indicates if this unit is dimensionless.
     * 
     * @return true, always.
     */
    public boolean isDimensionless() {
        return true;
    }

    /**
     * Returns the string representation of this unit.
     * 
     * @return The string representation of this 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 (base == 2
                ? "lb"
                : base == Math.E
                        ? "ln"
                        : "lg") + "(re " + getReference().toString() + ")";
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy