Java API By Example, From Geeks To Geeks.

# Java > Open Source Codes > org > jscience > physics > measures > Measure

 `1 /*2  * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.3  * Copyright (C) 2006 - JScience (http://jscience.org/)4  * All rights reserved.5  * 6  * Permission to use, copy, modify, and distribute this software is7  * freely granted, provided that this notice is preserved.8  */9 package org.jscience.physics.measures;10 11 import java.io.Serializable ;12 13 import javolution.lang.Immutable;14 import javolution.lang.MathLib;15 import javolution.text.Text;16 import javolution.context.RealtimeObject;17 import javolution.util.FastComparator;18 import javolution.util.FastMap;19 import javolution.xml.XMLFormat;20 import javolution.xml.stream.XMLStreamException;21 22 import org.jscience.mathematics.structures.Field;23 24 import javax.measure.converters.ConversionException;25 import javax.measure.converters.RationalConverter;26 import javax.measure.converters.UnitConverter;27 import javax.measure.quantities.Dimensionless;28 import javax.measure.quantities.Quantity;29 import javax.measure.units.Unit;30 import javax.realtime.MemoryArea;31 32 /**33  *

This class represents a measurable amount; the nature of the amount34  * is deduced from the measure {@link #getUnit() unit}; the quality of 35  * the measure is given by the measurement {@link #getAbsoluteError()36  * error}.

37  * 38  *

Measures can be {@link #isExact() exact}, in which case they can be39  * expressed as an exact long integer in the measure unit.40  * The framework tries to keep measures exact as much as possible.41  * For example:[code]42  * Measure m = Measure.valueOf(33, FOOT).divide(11).times(2);43  * System.out.println(m);44  * System.out.println(m.isExact() ? "exact" : "inexact");45  * System.out.println(m.getExactValue());46  * > 6 ft47  * > exact48  * > 6[/code] 49  *

50  * 51  *

Errors (including numeric errors) are calculated using numeric intervals.52  * It is possible to resolve systems of linear equations involving 53  * measures (ref. {@link org.jscience.mathematics.vectors.Matrix Matrix}),54  * even if the system is close to singularity; in which case the error 55  * associated with some (or all) components of the solution may be large.56  *

57  * 58  *

By default, non-exact measure instances are shown using the plus/minus 59  * character ('±') (see {@link MeasureFormat}). For example, 60  * "(2.0 ± 0.001) km/s" represents a velocity of 61  * 2 km/s with an absolute error of ± 1 m/s. Exact measurements use an62  * integer notation (no decimal point, e.g. "2000 m").

63  * 64  *

Operations between different measures may or may not be authorized 65  * based upon the current {@link org.jscience.physics.models.PhysicalModel66  * PhysicalModel}. For example, adding Measure<Length> and 67  * Measure<Duration> is not allowed by the 68  * {@link org.jscience.physics.models.StandardModel StandardModel}, 69  * but is authorized with the {@link70  * org.jscience.physics.models.RelativisticModel RelativisticModel}.

71  * 72  * @author Jean-Marie Dautelle73  * @version 3.0, February 26, 200674  * @see 75  * Wikipedia: Measuring76  */77 public final class Measure extends RealtimeObject implements78         Quantity, Field>, Comparable , Serializable , Immutable {79 80 ////////////////////////////////////////////////////////////////////////////////81 // Note: In the future, Measure might be abstract (with more measure types) // 82 // We don't provide public constructors, factory methods should be used.//83 ////////////////////////////////////////////////////////////////////////////////84 85     /**86      * Holds a dimensionless measure of zero (exact).87      */88     public static final Measure ZERO = new Measure();89     static {90         ZERO._unit = Unit.ONE;91         ZERO._isExact = true;92         ZERO._exactValue = 0L;93         ZERO._minimum = 0;94         ZERO._maximum = 0; 95     }96 97     /**98      * Holds a dimensionless measure of one (exact).99      */100     public static final Measure ONE = new Measure();101     static {102         ONE._unit = Unit.ONE;103         ONE._isExact = true;104         ONE._exactValue = 1L;105         ONE._minimum = 1.0;106         ONE._maximum = 1.0; 107     }108     109     /**110      * Holds the default XML representation for measures.111      * This representation consists of a value, 112      * an unit and an optional error attribute 113      * when the measure is not exact.114      * The unit attribute determinates the measurement type. For example:
115      * <Measure value="12" unit="µA"/>
116      * represents an electric current measurement.117      */118     protected static final XMLFormat XML = new XMLFormat(119             Measure.class) {120         121         @Override 122         public Measure newInstance(Class cls, InputElement xml) throws XMLStreamException {123             Unit unit = Unit.valueOf(xml.getAttribute("unit"));124             Measure m = Measure.newInstance(unit);125             if (xml.getAttribute("error") == null) // Exact.126 return m.setExact(xml.getAttribute("value", 0L));127             m._isExact = false;128             double estimatedValue = xml.getAttribute("value", 0.0);129             double error = xml.getAttribute("error", 0.0);130             m._minimum = estimatedValue - error;131             m._maximum = estimatedValue + error;132             return m;133         }134 135         @Override 136         public void read(javolution.xml.XMLFormat.InputElement arg0, Measure arg1) throws XMLStreamException {137             // Nothing to do.138 }139 140         @Override 141         public void write(Measure m, OutputElement xml) throws XMLStreamException {142             if (m._isExact) {143                 xml.setAttribute("value", m._exactValue);144             } else {145                 xml.setAttribute("value", m.getEstimatedValue());146                 xml.setAttribute("error", m.getAbsoluteError());147             }148             xml.setAttribute("unit", m._unit.toString());149         }150     };151 152     /**153      * Returns the exact measure corresponding to the value stated in the 154      * specified unit.155      *156      * @param value the exact value stated in the specified unit.157      * @param unit the unit in which the value is stated.158      * @return the corresponding measure object.159      */160     public static Measure valueOf(long value,161             Unit unit) {162         Measure m = Measure.newInstance(unit);163         return m.setExact(value);164     }165 166     /**167      * Returns the measure corresponding to an approximate value 168      * (double) stated in the specified unit; 169      * the precision of the measure is assumed to be the 170      * double precision (64 bits IEEE 754 format).171      *172      * @param value the estimated value (± LSB) stated in the specified unit.173      * @param unit the unit in which the value is stated.174      * @return the corresponding measure object.175      */176     public static Measure valueOf(double value,177             Unit unit) {178         Measure m = Measure.newInstance(unit);179         m._isExact = false;180         double valInc = value * INCREMENT;181         double valDec = value * DECREMENT;182         m._minimum = (value < 0) ? valInc : valDec;183         m._maximum = (value < 0) ? valDec : valInc;184         return m;185     }186 187     /**188      * Returns the measure corresponding to the specified approximate value 189      * and measurement error, both stated in the specified unit.190      *191      * @param value the estimated amount (± error) stated in the specified unit.192      * @param error the measurement error (absolute).193      * @param unit the unit in which the amount and the error are stated.194      * @return the corresponding measure object.195      * @throws IllegalArgumentException if error < 0.0196      */197     public static Measure valueOf(double value,198             double error, Unit unit) {199         if (error < 0)200             throw new IllegalArgumentException ("error: " + error201                     + " is negative");202         Measure m = Measure.newInstance(unit);203         double min = value - error;204         double max = value + error;205         m._isExact = false;206         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;207         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;208         return m;209     }210 211     /**212      * Returns the measure corresponding to the specified interval stated 213      * in the specified unit.214      *215      * @param minimum the lower bound for the measure value.216      * @param maximum the upper bound for the measure value.217      * @param unit the unit for both the minimum and maximum values.218      * @return the corresponding measure object.219      * @throws IllegalArgumentException if minimum > maximum220      */221     public static Measure rangeOf(double minimum,222             double maximum, Unit unit) {223         if (minimum > maximum)224             throw new IllegalArgumentException ("minimum: " + minimum225                     + " greater than maximum: " + maximum);226         Measure m = Measure.newInstance(unit);227         m._isExact = false;228         m._minimum = (minimum < 0) ? minimum * INCREMENT : minimum * DECREMENT;229         m._maximum = (maximum < 0) ? maximum * DECREMENT : maximum * INCREMENT;230         return m;231     }232 233     /**234      * Returns the measure represented by the specified character sequence.235      *236      * @param csq the character sequence.237      * @return MeasureFormat.getInstance().parse(csq)238      */239     public static Measure valueOf(CharSequence csq) {240         return MeasureFormat.getInstance().parse(csq);241     }242 243     /**244      * Indicates if this measure is exact.245      */246     private boolean _isExact;247 248     /**249      * Holds the exact value (when exact) stated in this measure unit.250      */251     private long _exactValue;252 253     /**254      * Holds the minimum value stated in this measure unit.255      * For inexact measures: _minimum < _maximum 256      */257     private double _minimum;258 259     /**260      * Holds the maximum value stated in this measure unit.261      * For inexact measures: _maximum > _minimum 262      */263     private double _maximum;264 265     /**266      * Holds this measure unit. 267      */268     private Unit _unit;269 270     /**271      * Indicates if this measure amount is exact. An exact amount is 272      * guarantee exact only when stated in this measure unit273      * (e.g. this.longValue()); stating the amount274      * in any other unit may introduce conversion errors. 275      *276      * @return true if this measure is exact;277      * false otherwise.278      */279     public boolean isExact() {280         return _isExact;281     }282 283     /**284      * Returns the unit in which the {@link #getEstimatedValue()285      * estimated value} and {@link #getAbsoluteError() absolute error}286      * are stated.287      *288      * @return the measure unit.289      */290     public Unit getUnit() {291         return _unit;292     }293 294     /**295      * Returns the exact value for this measure stated in this measure296      * {@link #getUnit unit}. 297      *298      * @return the exact measure value (long) stated 299      * in this measure's {@link #getUnit unit}300      * @throws MeasureException if this measure is not {@link #isExact()}301      */302     public long getExactValue() throws MeasureException {303         if (!_isExact)304             throw new MeasureException(305                     "Inexact measures don't have exact values");306         return _exactValue;307     }308 309     /**310      * Returns the estimated value for this measure stated in this measure311      * {@link #getUnit unit}. 312      *313      * @return the median value of the measure interval.314      */315     public double getEstimatedValue() {316         return (_isExact) ? _exactValue : (_minimum + _maximum) * 0.5;317     }318 319     /**320      * Returns the lower bound interval value for this measure stated in 321      * this measure unit.322      *323      * @return the minimum value.324      */325     public double getMinimumValue() {326         return _minimum;327     }328 329     /**330      * Returns the upper bound interval value for this measure stated in 331      * this measure unit.332      *333      * @return the maximum value.334      */335     public double getMaximumValue() {336         return _maximum;337     }338 339     /**340      * Returns the value by which the{@link #getEstimatedValue() estimated 341      * value} may differ from the true value (all stated in base units).342      *343      * @return the absolute error stated in base units.344      */345     public double getAbsoluteError() {346         return MathLib.abs(_maximum - _minimum) * 0.5;347     }348 349     /**350      * Returns the percentage by which the estimated amount may differ351      * from the true amount.352      *353      * @return the relative error.354      */355     public double getRelativeError() {356         return (_maximum - _minimum) / (_minimum + _maximum);357     }358 359     /**360      * Returns the measure equivalent to this measure but stated in the 361      * specified unit. The returned measure may not be exact even if this 362      * measure is exact due to conversion errors. 363      *364      * @param unit the unit of the measure to be returned.365      * @return a measure equivalent to this measure but stated in the 366      * specified unit.367      * @throws ConversionException if the current model does not allows for368      * conversion to the specified unit.369      */370     @SuppressWarnings ("unchecked")371     public Measure to(Unit unit) {372         if ((_unit == unit) || this._unit.equals(unit))373             return (Measure) this;374         UnitConverter cvtr = Measure.converterOf(_unit, unit);375         if (cvtr == UnitConverter.IDENTITY) { // No conversion necessary.376 Measure result = Measure.copyOf(this);377             result._unit = unit;378             return result;379         }380         if (cvtr instanceof RationalConverter) { // Exact conversion.381 RationalConverter rc = (RationalConverter) cvtr;382              Measure result = this.times(rc.getDividend()).divide(rc.getDivisor());383              result._unit = unit;384              return result;385         }386         Measure result = Measure.newInstance(unit);387         double min = cvtr.convert(_minimum);388         double max = cvtr.convert(_maximum);389         result._isExact = false;390         result._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;391         result._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;392         return result;393     }394 395     /**396      * Returns the opposite of this measure.397      *398      * @return -this.399      */400     public Measure opposite() {401         Measure m = Measure.newInstance(_unit);402         if ((_isExact) && (_exactValue != Long.MAX_VALUE))403             return m.setExact(-_exactValue);404         m._isExact = false;405         m._minimum = -_maximum;406         m._maximum = -_minimum;407         return m;408     }409 410     /**411      * Returns the sum of this measure with the one specified.412      *413      * @param that the measure to be added.414      * @return this + that.415      * @throws ConversionException if the current model does not allows for416      * these quantities to be added.417      */418     @SuppressWarnings ("unchecked")419     public Measure plus(Measure that) throws ConversionException {420         final Measure thatToUnit = that.to(_unit);421         Measure m = Measure.newInstance(_unit);422         if (this._isExact && thatToUnit._isExact) {423             long sumLong = this._exactValue + thatToUnit._exactValue;424             double sumDouble = ((double) this._exactValue)425                     + ((double) thatToUnit._exactValue);426             if (sumLong == sumDouble)427                 return m.setExact(sumLong);428         }429         double min = this._minimum + thatToUnit._minimum;430         double max = this._maximum + thatToUnit._maximum;431         m._isExact = false;432         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;433         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;434         return m;435     }436 437     /**438      * Returns the difference of this measure with the one specified.439      *440      * @param that the measure to be subtracted.441      * @return this - that.442      * @throws ConversionException if the current model does not allows for443      * these quantities to be subtracted.444      */445     @SuppressWarnings ("unchecked")446     public Measure minus(Measure that) throws ConversionException {447         final Measure thatToUnit = that.to(_unit);448         Measure m = Measure.newInstance(_unit);449         if (this._isExact && thatToUnit._isExact) {450             long diffLong = this._exactValue - thatToUnit._exactValue;451             double diffDouble = ((double) this._exactValue)452                     - ((double) thatToUnit._exactValue);453             if (diffLong == diffDouble)454                 return m.setExact(diffLong);455         }456         double min = this._minimum - thatToUnit._maximum;457         double max = this._maximum - thatToUnit._minimum;458         m._isExact = false;459         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;460         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;461         return m;462     }463 464     /**465      * Returns this measure scaled by the specified exact factor 466      * (dimensionless).467      *468      * @param factor the scaling factor.469      * @return this · factor.470      */471     public Measure times(long factor) {472         Measure m = Measure.newInstance(_unit);473         if (this._isExact) {474             long productLong = _exactValue * factor;475             double productDouble = ((double) _exactValue) * factor;476             if (productLong == productDouble)477                 return m.setExact(productLong);478         }479         m._isExact = false;480         m._minimum = (factor > 0) ? _minimum * factor : _maximum * factor;481         m._maximum = (factor > 0) ? _maximum * factor : _minimum * factor;482         return m;483     }484 485     /**486      * Returns this measure scaled by the specified approximate factor487      * (dimensionless).488      *489      * @param factor the scaling factor.490      * @return this · factor.491      */492     public Measure times(double factor) {493         Measure m = Measure.newInstance(_unit);494         double min = (factor > 0) ? _minimum * factor : _maximum * factor;495         double max = (factor > 0) ? _maximum * factor : _minimum * factor;496         m._isExact = false;497         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;498         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;499         return m;500     }501 502     /**503      * Returns the product of this measure with the one specified.504      *505      * @param that the measure multiplier.506      * @return this · that.507      */508     @SuppressWarnings ("unchecked")509     public Measure times(Measure that) {510         Unit unit = Measure.productOf(this._unit, that._unit);511         if (that._isExact) {512             Measure m = this.times(that._exactValue);513             m._unit = unit;514             return m;515         }516         Measure m = Measure.newInstance(unit);517         double min, max;518         if (_minimum >= 0) {519             if (that._minimum >= 0) {520                 min = _minimum * that._minimum;521                 max = _maximum * that._maximum;522             } else if (that._maximum < 0) {523                 min = _maximum * that._minimum;524                 max = _minimum * that._maximum;525             } else {526                 min = _maximum * that._minimum;527                 max = _maximum * that._maximum;528             }529         } else if (_maximum < 0) {530             if (that._minimum >= 0) {531                 min = _minimum * that._maximum;532                 max = _maximum * that._minimum;533             } else if (that._maximum < 0) {534                 min = _maximum * that._maximum;535                 max = _minimum * that._minimum;536             } else {537                 min = _minimum * that._maximum;538                 max = _minimum * that._minimum;539             }540         } else {541             if (that._minimum >= 0) {542                 min = _minimum * that._maximum;543                 max = _maximum * that._maximum;544             } else if (that._maximum < 0) {545                 min = _maximum * that._minimum;546                 max = _minimum * that._minimum;547             } else { // Both around zero.548 min = MathLib.min(_minimum * that._maximum, _maximum549                         * that._minimum);550                 max = MathLib.max(_minimum * that._minimum, _maximum551                         * that._maximum);552             }553         }554         m._isExact = false;555         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;556         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;557         return m;558     }559 560     /**561      * Returns the multiplicative inverse of this measure.562      * If this measure is possibly zero, then the result is unbounded563      * (]-infinity, +infinity[).564      *565      * @return 1 / this.566      */567     public Measure inverse() {568         Measure m = newInstance(Measure.inverseOf(_unit));569         if ((_isExact) && (_exactValue == 1L)) { // Only one exact inverse: one570 m.setExact(1L);571             return m;572         }573         m._isExact = false;574         if ((_minimum <= 0) && (_maximum >= 0)) { // Encompass zero.575 m._minimum = Double.NEGATIVE_INFINITY;576             m._maximum = Double.POSITIVE_INFINITY;577             return m;578         }579         double min = 1.0 / _maximum;580         double max = 1.0 / _minimum;581         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;582         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;583         return m;584     }585 586     /**587      * Returns this measure divided by the specified exact divisor588      * (dimensionless).589      *590      * @param divisor the exact divisor.591      * @return this / divisor.592      * @throws ArithmeticException if this measure is exact and the 593      * specified divisor is zero.594      */595     public Measure divide(long divisor) {596         Measure m = Measure.newInstance(_unit);597         if (this._isExact) {598             long quotientLong = _exactValue / divisor;599             double quotientDouble = ((double) _exactValue) / divisor;600             if (quotientLong == quotientDouble)601                 return m.setExact(quotientLong);602         }603         double min = (divisor > 0) ? _minimum / divisor : _maximum / divisor;604         double max = (divisor > 0) ? _maximum / divisor : _minimum / divisor;605         m._isExact = false;606         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;607         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;608         return m;609     }610 611     /**612      * Returns this measure divided by the specified approximate divisor613      * (dimensionless).614      *615      * @param divisor the approximated divisor.616      * @return this / divisor.617      */618     public Measure divide(double divisor) {619         Measure m = Measure.newInstance(_unit);620         double min = (divisor > 0) ? _minimum / divisor : _maximum / divisor;621         double max = (divisor > 0) ? _maximum / divisor : _minimum / divisor;622         m._isExact = false;623         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;624         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;625         return m;626     }627 628     /**629      * Returns this measure divided by the one specified.630      *631      * @param that the measure divisor.632      * @return this / that.633      */634     @SuppressWarnings ("unchecked")635     public Measure divide(Measure that) {636         if (that._isExact) {637             Measure m = this.divide(that._exactValue);638             m._unit = Measure.productOf(this._unit, Measure639                     .inverseOf(that._unit));640             return m;641         }642         return this.times(that.inverse());643     }644 645     /**646      * Returns the absolute value of this measure.647      *648      * @return |this|.649      */650     public Measure abs() {651         return (_isExact) ? ((_exactValue < 0) ? this.opposite() : this)652                 : (_minimum >= -_maximum) ? this : this.opposite();653     }654 655     /**656      * Returns the square root of this measure.657      *658      * @return sqrt(this)659      * 660      */661     public Measure sqrt() {662         Measure m = Measure.newInstance(_unit.root(2));663         if (this._isExact) {664             double sqrtDouble = MathLib.sqrt(_exactValue);665             long sqrtLong = (long) sqrtDouble;666             if (sqrtLong * sqrtLong == _exactValue)667                 return m.setExact(sqrtLong);668         }669         double min = MathLib.sqrt(_minimum);670         double max = MathLib.sqrt(_maximum);671         m._isExact = false;672         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;673         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;674         return m;675     }676 677     /**678      * Returns the given root of this measure.679      *680      * @param n the root's order (n != 0).681      * @return the result of taking the given root of this quantity.682      * @throws ArithmeticException if n == 0.683      */684     public Measure root(int n) {685         if (n == 0)686             throw new ArithmeticException ("Root's order of zero");687         if (n < 0)688             return this.root(-n).inverse();689         if (n == 2)690             return this.sqrt();691         Measure m = Measure.newInstance(_unit.root(n));692         if (this._isExact) {693             double rootDouble = MathLib.pow(_exactValue, 1.0 / n);694             long rootLong = (long) rootDouble;695             long thisLong = rootLong;696             for (int i = 1; i < n; i++) {697                 thisLong *= rootLong;698             }699             if (thisLong == _exactValue)700                 return m.setExact(rootLong);701         }702         double min = MathLib.pow(_minimum, 1.0 / n);703         double max = MathLib.pow(_maximum, 1.0 / n);704         m._isExact = false;705         m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;706         m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;707         return m;708     }709 710     /**711      * Returns this measure raised at the specified exponent.712      *713      * @param exp the exponent.714      * @return thisexp715      */716     public Measure pow(int exp) {717         if (exp < 0)718             return this.pow(-exp).inverse();719         if (exp == 0)720             return ONE;721         Measure pow2 = this;722         Measure result = null;723         while (exp >= 1) { // Iteration.724 if ((exp & 1) == 1) {725                 result = (result == null) ? pow2 : result.times(pow2);726             }727             pow2 = pow2.times(pow2);728             exp >>>= 1;729         }730         return result;731     }732 733     /**734      * Compares this measure with the one specified regardless of the 735      * units in which this measure and that measure are stated.736      *737      * @param that the measure to compare with.738      * @return a negative integer, zero, or a positive integer as this measure739      * is less than, equal to, or greater than that measure.740      * @throws ConversionException if the current model does not allows for741      * these measure to be compared.742      */743     @SuppressWarnings ("unchecked")744     public int compareTo(Measure that) {745         Measure thatToUnit = that.to(_unit);746         if (_isExact && thatToUnit._isExact)747             return _exactValue < thatToUnit._exactValue ? -1748                     : _exactValue > thatToUnit._exactValue ? 1 : 0;749         double thisValue = this.getEstimatedValue();750         double thatToUnitValue = thatToUnit.getEstimatedValue();751         if (thisValue < thatToUnitValue) {752             return -1;753         } else if (thisValue > thatToUnitValue) {754             return 1;755         } else {756             long l1 = Double.doubleToLongBits(thisValue);757             long l2 = Double.doubleToLongBits(thatToUnitValue);758             return (l1 == l2 ? 0 : (l1 < l2 ? -1 : 1));759         }760     }761 762     /**763      * Compares this measure against the specified object for strict 764      * equality (same value interval and same units).765      *766      * @param that the object to compare with.767      * @return true if this measure is identical to that768      * measure; false otherwise.769      */770     public boolean equals(Object that) {771         if (this == that)772             return true;773         if (!(that instanceof Measure))774             return false;775         Measure m = (Measure) that;776         if (!_unit.equals(m._unit))777             return false;778         if (_isExact != m._isExact)779             return false;780         if (_isExact && (this._exactValue == m._exactValue))781             return true;782         if (_minimum != m._minimum)783             return false;784         if (_maximum != m._maximum)785             return false;786         return true;787     }788 789     /**790      * Returns the hash code for this measure.791      * 792      * @return the hash code value.793      */794     public int hashCode() {795         int h = Float.floatToIntBits((float) _minimum);796         h += ~(h << 9);797         h ^= (h >>> 14);798         h += (h << 4);799         return h ^ (h >>> 10);800     }801 802     /**803      * Indicates if this measure approximates that measure.804      * Measures are considered approximately equals if their value intervals805      * overlaps. It should be noted that less accurate measurements are 806      * more likely to be approximately equals. It is therefore recommended807      * to ensure that the measurement error is not too large before testing808      * for approximate equality.809      *810      * @return this ≅ that811      */812     @SuppressWarnings ("unchecked")813     public boolean approximates(Measure that) {814         Measure thatToUnit = that.to(_unit);815         return (this._maximum >= thatToUnit._minimum)816                 && (thatToUnit._maximum >= this._minimum);817     }818 819     /**820      * Indicates if this measure is ordered before that measure821      * (independently of the measure unit).822      *823      * @return this.compareTo(that) < 0.824      */825     public boolean isLessThan(Measure that) {826         return this.compareTo(that) < 0;827     }828 829     /**830      * Indicates if this measure is ordered after that measure831      * (independently of the measure unit).832      *833      * @return this.compareTo(that) > 0.834      */835     public boolean isGreaterThan(Measure that) {836         return this.compareTo(that) > 0;837     }838 839     /**840      * Compares this measure with that measure ignoring the sign.841      *842      * @return |this| > |that|843      */844     public boolean isLargerThan(Measure that) {845         return this.abs().isGreaterThan(that.abs());846     }847 848     /**849      * Returns the text representation of this measure.850      *851      * @return MeasureFormat.getInstance().format(this)852      */853     public Text toText() {854         return MeasureFormat.getInstance().format(this);855     }856 857     // Implements Quantity.858 public double doubleValue(Unit unit) {859         return ((_unit == unit) || _unit.equals(unit)) ? this860                 .getEstimatedValue() : this.to(unit).getEstimatedValue();861     }862 863     // Implements Quantity.864 public final long longValue(Unit unit) {865         if (!_unit.equals(unit))866             return this.to(unit).longValue(unit);867         if (_isExact)868             return _exactValue;869         double doubleValue = this.getEstimatedValue();870         if ((doubleValue >= Long.MIN_VALUE) && (doubleValue <= Long.MAX_VALUE))871             return Math.round(doubleValue);872         throw new ArithmeticException (doubleValue + " " + _unit873                 + " cannot be represented as long");874     }875 876     ///////////////////877 // Lookup tables //878 ///////////////////879 880     static final FastMap> MULT_LOOKUP = new FastMap>(881             "UNITS_MULT_LOOKUP").setKeyComparator(FastComparator.DIRECT);882 883     static final FastMap INV_LOOKUP = new FastMap(884             "UNITS_INV_LOOKUP").setKeyComparator(FastComparator.DIRECT);885 886     static final FastMap> CVTR_LOOKUP = new FastMap>(887             "UNITS_CVTR_LOOKUP").setKeyComparator(FastComparator.DIRECT);888 889     private static Unit productOf(Unit left, Unit right) {890         FastMap leftTable = MULT_LOOKUP.get(left);891         if (leftTable == null)892             return calculateProductOf(left, right);893         Unit result = leftTable.get(right);894         if (result == null)895             return calculateProductOf(left, right);896         return result;897     }898 899     private static synchronized Unit calculateProductOf(final Unit left, final Unit right) {900         MemoryArea memoryArea = MemoryArea.getMemoryArea(MULT_LOOKUP);901         memoryArea.executeInArea(new Runnable () {902             public void run() {903                 FastMap leftTable = MULT_LOOKUP.get(left);904                 if (leftTable == null) {905                     leftTable = new FastMap().setKeyComparator(906                             FastComparator.DIRECT);907                     MULT_LOOKUP.put(left, leftTable);908                 }909                 Unit result = leftTable.get(right);910                 if (result == null) {911                     result = left.times(right);912                     leftTable.put(right, result);913                 }914             }915         });916         return MULT_LOOKUP.get(left).get(right);917     }918 919     private static Unit inverseOf(Unit unit) {920         Unit inverse = INV_LOOKUP.get(unit);921         if (inverse == null)922             return calculateInverseOf(unit);923         return inverse;924     }925 926     private static synchronized Unit calculateInverseOf(final Unit unit) {927         MemoryArea memoryArea = MemoryArea.getMemoryArea(INV_LOOKUP);928         memoryArea.executeInArea(new Runnable () {929             public void run() {930                 Unit inverse = INV_LOOKUP.get(unit);931                 if (inverse == null) {932                     inverse = unit.inverse();933                     INV_LOOKUP.put(unit, inverse);934                 }935             }936         });937         return INV_LOOKUP.get(unit);938     }939 940     private static UnitConverter converterOf(Unit left, Unit right) {941         FastMap leftTable = CVTR_LOOKUP.get(left);942         if (leftTable == null)943             return calculateConverterOf(left, right);944         UnitConverter result = leftTable.get(right);945         if (result == null)946             return calculateConverterOf(left, right);947         return result;948     }949 950     private static synchronized UnitConverter calculateConverterOf(final Unit left,951             final Unit right) {952         MemoryArea memoryArea = MemoryArea.getMemoryArea(CVTR_LOOKUP);953         memoryArea.executeInArea(new Runnable () {954             public void run() {955                 FastMap leftTable = CVTR_LOOKUP.get(left);956                 if (leftTable == null) {957                     leftTable = new FastMap()958                             .setKeyComparator(FastComparator.DIRECT);959                     synchronized (CVTR_LOOKUP) {960                         CVTR_LOOKUP.put(left, leftTable);961                     }962                 }963                 UnitConverter result = leftTable.get(right);964                 if (result == null) {965                     result = left.getConverterTo(right);966                     synchronized (leftTable) {967                         leftTable.put(right, result);968                     }969                 }970             }971         });972         return CVTR_LOOKUP.get(left).get(right);973     }974 975     //////////////////////976 // Factory Creation //977 //////////////////////978 979     @SuppressWarnings ("unchecked")980     private static Measure newInstance(Unit unit) {981         Measure measure = FACTORY.object();982         measure._unit = unit;983         return measure;984     }985 986     @SuppressWarnings ("unchecked")987     private static Measure copyOf(Measure original) {988         Measure measure = FACTORY.object();989         measure._exactValue = original._exactValue;990         measure._isExact = original._isExact;991         measure._maximum = original._maximum;992         measure._minimum = original._minimum;993         measure._unit = original._unit;994         return measure;995     }996 997     private static Factory FACTORY = new Factory() {998 999         @Override 1000        protected Measure create() {1001            return new Measure();1002        }1003    };10041005    private Measure() {1006    }10071008    private Measure setExact(long exactValue) {1009        _isExact = true;1010        _exactValue = exactValue;1011        double doubleValue = exactValue;1012        if (doubleValue == exactValue) {1013            _minimum = doubleValue;1014            _maximum = doubleValue;1015        } else {1016            double valInc = exactValue * INCREMENT;1017            double valDec = exactValue * DECREMENT;1018            _minimum = (_exactValue < 0) ? valInc : valDec;1019            _maximum = (_exactValue < 0) ? valDec : valInc;1020        }1021        return this;1022    }10231024    static final double DOUBLE_RELATIVE_ERROR = MathLib.pow(2, -53);10251026    static final double DECREMENT = (1.0 - DOUBLE_RELATIVE_ERROR);10271028    static final double INCREMENT = (1.0 + DOUBLE_RELATIVE_ERROR);10291030    private static final long serialVersionUID = 1L;1031}` Popular Tags