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

ucar.units.Dimension 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: Dimension.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 the concept of "dimension": pairs of base entities and
 * exponents.
 * 
 * @author Steven R. Emmerson
 * @version $Id: Dimension.java 64 2006-07-12 22:30:50Z edavis $
 */
public abstract class Dimension {
    /**
     * The individual elements of this dimension.
     * 
     * @serial
     */
    protected final Factor[]       _factors;

    private transient volatile int hashCode;

    /**
     * Constructs a dimensionless dimension from nothing.
     */
    public Dimension() {
        this(new Factor[0]);
    }

    /**
     * Constructs from a single Factor.
     * 
     * @param factor
     *            The single Factor that defines the dimension.
     */
    protected Dimension(final Factor factor) {
        this(new Factor[] { factor });
    }

    /**
     * Constructs from an array of Factor-s. This is a trusted constructor for
     * use by subclasses only.
     * 
     * @param factors
     *            The factors that define the dimension.
     */
    protected Dimension(final Factor[] factors) {
        _factors = factors;
    }

    /**
     * Returns the rank of this dimension. The rank is the number of base entity
     * and exponent pairs (i.e. the number of Factor-s constituting this
     * dimension).
     * 
     * @return The rank of this dimension.
     */
    public final int getRank() {
        return _factors.length;
    }

    /**
     * Returns the array of Factor-s constituting this dimension.
     * 
     * @return The array of Factor-s constituting this dimension.
     */
    public final Factor[] getFactors() {
        final Factor[] factors = new Factor[_factors.length];
        System.arraycopy(_factors, 0, factors, 0, factors.length);
        return factors;
    }

    /**
     * Multiplies this dimension by another dimension.
     * 
     * @param that
     *            The other dimension.
     * @return The product of the Factor-s of this dimension and the Factor-s of
     *         the other dimension.
     */
    protected Factor[] mult(final Dimension that) {
        // relys on _factors always sorted
        final Factor[] factors1 = _factors;
        final Factor[] factors2 = that._factors;
        int i1 = 0;
        int i2 = 0;
        int k = 0;
        Factor[] newFactors = new Factor[factors1.length + factors2.length];
        for (;;) {
            if (i1 == factors1.length) {
                final int n = factors2.length - i2;
                System.arraycopy(factors2, i2, newFactors, k, n);
                k += n;
                break;
            }
            if (i2 == factors2.length) {
                final int n = factors1.length - i1;
                System.arraycopy(factors1, i1, newFactors, k, n);
                k += n;
                break;
            }
            final Factor f1 = factors1[i1];
            final Factor f2 = factors2[i2];
            final int comp = f1.getID().compareTo(f2.getID());
            if (comp < 0) {
                newFactors[k++] = f1;
                i1++;
            }
            else if (comp == 0) {
                final int exponent = f1.getExponent() + f2.getExponent();
                if (exponent != 0) {
                    newFactors[k++] = new Factor(f1, exponent);
                }
                i1++;
                i2++;
            }
            else {
                newFactors[k++] = f2;
                i2++;
            }
        }
        if (k < newFactors.length) {
            final Factor[] tmp = new Factor[k];
            System.arraycopy(newFactors, 0, tmp, 0, k);
            newFactors = tmp;
        }
        return newFactors;
    }

    /**
     * Raises this dimension to a power.
     * 
     * @param power
     *            The power to raise this dimension by.
     * @return The Factor-s of this dimension raised to the power
     *         power.
     */
    protected Factor[] pow(final int power) {
        Factor[] factors;
        if (power == 0) {
            factors = new Factor[0];
        }
        else {
            factors = getFactors();
            if (power != 1) {
                for (int i = factors.length; --i >= 0;) {
                    factors[i] = factors[i].pow(power);
                }
            }
        }
        return factors;
    }

    /**
     * Indicates if this Dimension is the reciprocal of another dimension.
     * 
     * @param that
     *            The other dimension.
     * @return true if and only if this dimension is the reciprocal
     *         of the other dimension.
     */
    public final boolean isReciprocalOf(final Dimension that) {
        final Factor[] theseFactors = _factors;
        final Factor[] thoseFactors = that._factors;
        boolean isReciprocalOf;
        if (theseFactors.length != thoseFactors.length) {
            isReciprocalOf = false;
        }
        else {
            int i;
            for (i = theseFactors.length; --i >= 0;) {
                if (!theseFactors[i].isReciprocalOf(thoseFactors[i])) {
                    break;
                }
            }
            isReciprocalOf = i < 0;
        }
        return isReciprocalOf;
    }

    /**
     * Indicates if this dimension is semantically identical to an object.
     * 
     * @param object
     *            The object.
     * @return true if and only if this dimension is semantically
     *         identical to object.
     */
    @Override
    public final boolean equals(final Object object) {
        boolean equals;
        if (this == object) {
            equals = true;
        }
        else if (!(object instanceof Dimension)) {
            equals = false;
        }
        else {
            final Factor[] thatFactors = ((Dimension) object)._factors;
            if (_factors.length != thatFactors.length) {
                equals = false;
            }
            else {
                int i = _factors.length;
                while (--i >= 0) {
                    if (!_factors[i].equals(thatFactors[i])) {
                        break;
                    }
                }
                equals = i < 0;
            }
        }
        return equals;
    }

    /**
     * Returns the hash code of this instance.
     * 
     * @return The hash code of this instance.
     */
    @Override
    public int hashCode() {
        if (hashCode == 0) {
            int hash = 0;
            for (int i = 0; i < _factors.length; i++) {
                hash ^= _factors[i].hashCode();
            }
            hashCode = hash;
        }
        return hashCode;
    }

    /**
     * Indicates if this dimension is dimensionless. A dimension is
     * dimensionless if it has no Factor-s or if all Factor-s are, themselves,
     * dimensionless.
     * 
     * @return true if and only if this dimension is dimensionless.
     */
    public final boolean isDimensionless() {
        for (int i = _factors.length; --i >= 0;) {
            if (!_factors[i].isDimensionless()) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns the string representation of this dimension.
     * 
     * @return The string representation of this dimension.
     */
    @Override
    public String toString() {
        final StringBuffer buf = new StringBuffer(40);
        for (int i = 0; i < _factors.length; i++) {
            buf.append(_factors[i]).append('.');
        }
        if (buf.length() != 0) {
            buf.setLength(buf.length() - 1);
        }
        return buf.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy