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

ucar.units.ScaledUnit Maven / Gradle / Ivy

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 a unit that is a mutiplicative factor of a reference
 * unit.
 * 
 * Instances of this class are immutable.
 * 
 * @author Steven R. Emmerson
 */
@Immutable
public final class ScaledUnit extends UnitImpl implements DerivableUnit {
  private static final long serialVersionUID = 1L;

  /**
   * The multiplicative factor.
   * 
   * @serial
   */
  private final double _scale;

  /**
   * The reference unit.
   * 
   * @serial
   */
  private final Unit _unit;

  /**
   * Constructs from a multiplicative factor. Returns a dimensionless unit
   * whose value is the multiplicative factor rather than unity.
   * 
   * @param scale
   *        The multiplicative factor.
   */
  public ScaledUnit(final double scale) {
    this(scale, DerivedUnitImpl.DIMENSIONLESS);
  }

  /**
   * Constructs from a multiplicative factor and a reference unit.
   * 
   * @param scale
   *        The multiplicative factor.
   * @param unit
   *        The reference unit.
   */
  public ScaledUnit(final double scale, final Unit unit) {
    this(scale, unit, null);
  }

  /**
   * Constructs from a multiplicative factor, a reference unit, and an
   * identifier.
   * 
   * @param scale
   *        The multiplicative factor.
   * @param unit
   *        The reference unit.
   * @param id
   *        The identifier for the unit.
   */
  public ScaledUnit(final double scale, final Unit unit, final UnitName id) {
    super(id);
    if (!(unit instanceof ScaledUnit)) {
      _unit = unit;
      _scale = scale;
    } else {
      _unit = ((ScaledUnit) unit)._unit;
      _scale = ((ScaledUnit) unit)._scale * scale;
    }
  }

  static Unit getInstance(final double scale, final Unit unit) throws MultiplyException {
    if (scale == 0) {
      throw new MultiplyException(scale, unit);
    }
    return scale == 1 ? unit : new ScaledUnit(scale, unit);
  }

  /**
   * Returns the multiplicative factor.
   * 
   * @return The multiplicative factor.
   */
  public double getScale() {
    return _scale;
  }

  /**
   * Returns the reference unit.
   * 
   * @return The reference unit.
   */
  public Unit getUnit() {
    return _unit;
  }

  /*
   * From UnitImpl:
   */

  /**
   * Clones this unit, changing the identifier.
   * 
   * @param id
   *        The new identifier.
   * @return A ScaledUnit with the new identifier.
   */
  public Unit clone(final UnitName id) {
    return new ScaledUnit(_scale, getUnit(), id);
  }

  @Override
  public Unit multiplyBy(final double scale) throws MultiplyException {
    return getInstance(scale * _scale, _unit);
  }

  /**
   * Multiplies this unit by another unit.
   * 
   * @param that
   *        The other unit.
   * @return The product of this unit and the other unit.
   * @throws MultiplyException
   *         Can't multiply these units together.
   */
  @Override
  protected Unit myMultiplyBy(final Unit that) throws MultiplyException {
    return that instanceof ScaledUnit
        ? new ScaledUnit(getScale() * ((ScaledUnit) that).getScale(),
            getUnit().multiplyBy(((ScaledUnit) that).getUnit()))
        : new ScaledUnit(getScale(), getUnit().multiplyBy(that));
  }

  /**
   * Divides this unit by another unit.
   * 
   * @param that
   *        The other unit.
   * @return The quotient of this unit divided by the other unit.
   * @throws OperationException
   *         Can't divide these units.
   */
  @Override
  protected Unit myDivideBy(final Unit that) throws OperationException {
    return that instanceof ScaledUnit
        ? new ScaledUnit(getScale() / ((ScaledUnit) that).getScale(), getUnit().divideBy(((ScaledUnit) that).getUnit()))
        : new ScaledUnit(getScale(), getUnit().divideBy(that));
  }

  /**
   * Divides this unit into another unit.
   * 
   * @param that
   *        The other unit.
   * @return The quotient of this unit divided into the other unit.
   * @throws OperationException
   *         Can't divide these units.
   */
  @Override
  protected Unit myDivideInto(final Unit that) throws OperationException {
    return that instanceof ScaledUnit
        ? new ScaledUnit(((ScaledUnit) that).getScale() / getScale(),
            getUnit().divideInto(((ScaledUnit) that).getUnit()))
        : new ScaledUnit(1 / getScale(), getUnit().divideInto(that));
  }

  /**
   * Raises this unit to a power.
   * 
   * @param power
   *        The power.
   * @return The result of raising this unit to the power.
   * @throws RaiseException
   *         Can't raise this unit to a power.
   */
  @Override
  protected Unit myRaiseTo(final int power) throws RaiseException {
    return new ScaledUnit(Math.pow(getScale(), power), getUnit().raiseTo(power));
  }

  /**
   * Gets the derived unit underlying this unit.
   * 
   * @return The derived unit which underlies this unit.
   */
  public DerivedUnit getDerivedUnit() {
    return getUnit().getDerivedUnit();
  }

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

  /**
   * Converts a numeric value from this unit to the underlying derived unit.
   * 
   * @param amount
   *        The numeric value in this unit.
   * @return The equivalent value in the underlying derived unit.
   * @throws ConversionException
   *         Can't convert value to the underlying derived unit.
   */
  public double toDerivedUnit(final double amount) throws ConversionException {
    if (!(_unit instanceof DerivableUnit)) {
      throw new ConversionException(this, getDerivedUnit());
    }
    return ((DerivableUnit) _unit).toDerivedUnit(amount * getScale());
  }

  /**
   * Converts numeric values from this unit to the underlying derived unit.
   * 
   * @param input
   *        The numeric values in this unit.
   * @param output
   *        The equivalent values in the underlying derived unit.
   * @return output.
   * @throws ConversionException
   *         Can't convert values to the underlying derived unit.
   */
  public float[] toDerivedUnit(final float[] input, final float[] output) throws ConversionException {
    final float scale = (float) getScale();
    for (int i = input.length; --i >= 0;) {
      output[i] = input[i] * scale;
    }
    if (!(_unit instanceof DerivableUnit)) {
      throw new ConversionException(this, getDerivedUnit());
    }
    return ((DerivableUnit) getUnit()).toDerivedUnit(output, output);
  }

  /**
   * Converts numeric values from this unit to the underlying derived unit.
   * 
   * @param input
   *        The numeric values in this unit.
   * @param output
   *        The equivalent values in the underlying derived unit.
   * @return output.
   * @throws ConversionException
   *         Can't convert values to the underlying derived unit.
   */
  public double[] toDerivedUnit(final double[] input, final double[] output) throws ConversionException {
    final double scale = getScale();
    for (int i = input.length; --i >= 0;) {
      output[i] = input[i] * scale;
    }
    if (!(_unit instanceof DerivableUnit)) {
      throw new ConversionException(this, getDerivedUnit());
    }
    return ((DerivableUnit) getUnit()).toDerivedUnit(output, output);
  }

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

  /**
   * Converts a numeric value from the underlying derived unit to this unit.
   * 
   * @param amount
   *        The numeric value in the underlying derived unit.
   * @return The equivalent value in this unit.
   * @throws ConversionException
   *         Can't convert value.
   */
  public double fromDerivedUnit(final double amount) throws ConversionException {
    if (!(_unit instanceof DerivableUnit)) {
      throw new ConversionException(getDerivedUnit(), this);
    }
    return ((DerivableUnit) getUnit()).fromDerivedUnit(amount) / getScale();
  }

  /**
   * Converts numeric values from the underlying derived unit to this unit.
   * 
   * @param input
   *        The numeric values in the underlying derived unit.
   * @param output
   *        The equivalent values in this unit.
   * @return output.
   * @throws ConversionException
   *         Can't convert values.
   */
  public float[] fromDerivedUnit(final float[] input, final float[] output) throws ConversionException {
    if (!(_unit instanceof DerivableUnit)) {
      throw new ConversionException(getDerivedUnit(), this);
    }
    ((DerivableUnit) getUnit()).fromDerivedUnit(input, output);
    final float scale = (float) getScale();
    for (int i = input.length; --i >= 0;) {
      output[i] /= scale;
    }
    return output;
  }

  /**
   * Converts numeric values from the underlying derived unit to this unit.
   * 
   * @param input
   *        The numeric values in the underlying derived unit.
   * @param output
   *        The equivalent values in this unit.
   * @return output.
   * @throws ConversionException
   *         Can't convert values.
   */
  public double[] fromDerivedUnit(final double[] input, final double[] output) throws ConversionException {
    if (!(_unit instanceof DerivableUnit)) {
      throw new ConversionException(getDerivedUnit(), this);
    }
    ((DerivableUnit) getUnit()).fromDerivedUnit(input, output);
    final double scale = getScale();
    for (int i = input.length; --i >= 0;) {
      output[i] /= scale;
    }
    return output;
  }

  /**
   * Indicates if this unit is semantically identical to an object.
   * 
   * @param object
   *        The object.
   * @return true if an only if this unit is semantically
   *         identical to object
   *        .
   */
  public boolean equals(final Object object) {
    if (this == object) {
      return true;
    }
    if (_scale == 1) {
      return object.equals(_unit);
    }
    if (!(object instanceof ScaledUnit)) {
      return false;
    }
    ScaledUnit that = (ScaledUnit) object;
    if (Double.compare(that._scale, _scale) != 0)
      return false;
    return _unit.equals(that._unit);
  }

  /**
   * Returns the hash code of this instance.
   * 
   * @return The hash code of this instance.
   */
  @Override
  public int hashCode() {
    return (getScale() == 1 ? 0 : Double.valueOf(getScale()).hashCode()) ^ getUnit().hashCode();
  }

  /**
   * Indicates if this unit is dimensionless. A ScaledUnit is dimensionless if
   * and only if the reference unit is dimensionless.
   * 
   * @return true if and only if this unit is dimensionless.
   */
  public boolean isDimensionless() {
    return getUnit().isDimensionless();
  }

  /**
   * 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 DerivedUnitImpl.DIMENSIONLESS.equals(_unit) ? Double.toString(getScale())
        : getScale() + " " + _unit.toString();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy