001/*
002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003 * Copyright (C) 2006 - JScience (http://jscience.org/)
004 * All rights reserved.
005 * 
006 * Permission to use, copy, modify, and distribute this software is
007 * freely granted, provided that this notice is preserved.
008 */
009package org.jscience.physics.amount;
010
011import java.io.Serializable;
012
013import javolution.context.ObjectFactory;
014import javolution.lang.Immutable;
015import javolution.lang.MathLib;
016import javolution.text.Text;
017import javolution.util.FastComparator;
018import javolution.util.FastMap;
019import javolution.xml.XMLFormat;
020import javolution.xml.stream.XMLStreamException;
021
022import org.jscience.mathematics.structure.Field;
023
024import javax.measure.converter.ConversionException;
025import javax.measure.converter.RationalConverter;
026import javax.measure.converter.UnitConverter;
027import javax.measure.quantity.Dimensionless;
028import javax.measure.quantity.Quantity;
029import javax.measure.unit.Unit;
030import javax.measure.Measurable;
031import javax.realtime.MemoryArea;
032
033/**
034 * <p> This class represents a determinate or estimated amount for which 
035 *     operations such as addition, subtraction, multiplication and division
036 *     can be performed (it implements the {@link Field} interface).</p>
037 *     
038 * <p> The nature of an amount can be deduced from its parameterization 
039 *     (compile time) or its {@link #getUnit() unit} (run time).
040 *     Its precision is given by its {@link #getAbsoluteError() error}.</p>
041 *     
042 * <p> Amounts can be {@link #isExact() exact}, in which case they can be
043 *     expressed as an exact <code>long</code> integer in the amount unit.
044 *     The framework tries to keep amount exact as much as possible.
045 *     For example:[code]
046 *        Amount<Length> m = Amount.valueOf(33, FOOT).divide(11).times(2);
047 *        System.out.println(m);
048 *        System.out.println(m.isExact() ? "exact" : "inexact");
049 *        System.out.println(m.getExactValue());
050 *        > 6 ft
051 *        > exact
052 *        > 6[/code] 
053 *     </p>
054 *     
055 * <p> Errors (including numeric errors) are calculated using numeric intervals.
056 *     It is possible to resolve systems of linear equations involving 
057 *     {@link org.jscience.mathematics.vector.Matrix matrices}, even if the 
058 *     system is close to singularity; in which case the error associated with
059 *     some (or all) components of the solution may be large.</p>
060 *     
061 * <p> By default, non-exact amounts are shown using the plus/minus  
062 *     character ('±') (see {@link AmountFormat}). For example, 
063 *     <code>"(2.0 ± 0.001) km/s"</code> represents a velocity of 
064 *     2 km/s with an absolute error of ± 1 m/s. Exact amount use an
065 *     integer notation (no decimal point, e.g. <code>"2000 m"</code>).</p>
066 *     
067 * <p> Operations between different amounts may or may not be authorized 
068 *     based upon the current {@link org.jscience.physics.model.PhysicalModel
069 *     PhysicalModel}. For example, adding <code>Amount&lt;Length&gt; and 
070 *     <code>Amount&lt;Duration&gt; is not allowed by the 
071 *     {@link org.jscience.physics.model.StandardModel StandardModel}, 
072 *     but is authorized with the {@link
073 *     org.jscience.physics.model.RelativisticModel RelativisticModel}.</p>
074 *     
075 * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
076 * @version 4.0, June 4, 2007
077 * @see <a href="http://en.wikipedia.org/wiki/Measuring">
078 *       Wikipedia: Measuring</a>
079 */
080public final class Amount<Q extends Quantity> implements
081        Measurable<Q>, Field<Amount<?>>, Serializable, Immutable {
082
083////////////////////////////////////////////////////////////////////////////////
084// Note: In the future, Amount might be abstract (with more measure types)   // 
085//       We don't provide public constructors, factory methods should be used.//
086////////////////////////////////////////////////////////////////////////////////
087    
088    /**
089     * Holds a dimensionless measure of zero (exact).
090     */
091    public static final Amount<Dimensionless> ZERO = new Amount<Dimensionless>();
092    static {
093        ZERO._unit = Unit.ONE;
094        ZERO._isExact = true;
095        ZERO._exactValue = 0L;
096        ZERO._minimum = 0;
097        ZERO._maximum = 0;        
098    }
099
100    /**
101     * Holds a dimensionless measure of one (exact).
102     */
103    public static final Amount<Dimensionless> ONE = new Amount<Dimensionless>();
104    static {
105        ONE._unit = Unit.ONE;
106        ONE._isExact = true;
107        ONE._exactValue = 1L;
108        ONE._minimum = 1.0;
109        ONE._maximum = 1.0;        
110    }
111    
112    /**
113     * Holds the default XML representation for measures.
114     * This representation consists of a <code>value</code>, 
115     * an <code>unit</code> and an optional <code>error</code> attribute 
116     * when the measure is not exact.
117     * The unit attribute determinates the measurement type. For example:<pre>
118     * &lt;Amount value="12" unit="µA"/&gt;</pre>
119     * represents an electric current measurement.
120     */
121    @SuppressWarnings("unchecked")
122    protected static final XMLFormat<Amount> XML = new XMLFormat<Amount>(
123            Amount.class) {
124        
125        @Override
126        public Amount newInstance(Class<Amount> cls, InputElement xml) throws XMLStreamException {
127            Unit unit = Unit.valueOf(xml.getAttribute("unit"));
128            Amount<?> m = Amount.newInstance(unit);
129            if (xml.getAttribute("error") == null) // Exact.
130                return m.setExact(xml.getAttribute("value", 0L));
131            m._isExact = false;
132            double estimatedValue = xml.getAttribute("value", 0.0);
133            double error = xml.getAttribute("error", 0.0);
134            m._minimum = estimatedValue - error;
135            m._maximum = estimatedValue + error;
136            return m;
137        }
138
139        @Override
140        public void read(javolution.xml.XMLFormat.InputElement arg0, Amount arg1) throws XMLStreamException {
141            // Nothing to do.
142        }
143
144        @Override
145        public void write(Amount m, OutputElement xml) throws XMLStreamException {
146            if (m._isExact) {
147                xml.setAttribute("value", m._exactValue);
148            } else {
149                xml.setAttribute("value", m.getEstimatedValue());
150                xml.setAttribute("error", m.getAbsoluteError());
151            }
152            xml.setAttribute("unit", m._unit.toString());
153        }
154    };
155
156    /**
157     * Returns the exact measure corresponding to the value stated in the 
158     * specified unit.
159     *
160     * @param value the exact value stated in the specified unit.
161     * @param unit the unit in which the value is stated.
162     * @return the corresponding measure object.
163     */
164    public static <Q extends Quantity> Amount<Q> valueOf(long value,
165            Unit<Q> unit) {
166        Amount<Q> m = Amount.newInstance(unit);
167        return m.setExact(value);
168    }
169
170    /**
171     * Returns the measure corresponding to an approximate value 
172     * (<code>double</code>) stated in the specified unit; 
173     * the precision of the measure is assumed to be the 
174     * <code>double</code> precision (64 bits IEEE 754 format).
175     *
176     * @param value the estimated value (± LSB) stated in the specified unit.
177     * @param unit the unit in which the value is stated.
178     * @return the corresponding measure object.
179     */
180    public static <Q extends Quantity> Amount<Q> valueOf(double value,
181            Unit<Q> unit) {
182        Amount<Q> m = Amount.newInstance(unit);
183        m._isExact = false;
184        double valInc = value * INCREMENT;
185        double valDec = value * DECREMENT;
186        m._minimum = (value < 0) ? valInc : valDec;
187        m._maximum = (value < 0) ? valDec : valInc;
188        return m;
189    }
190
191    /**
192     * Returns the measure corresponding to the specified approximate value 
193     * and measurement error, both stated in the specified unit.
194     *
195     * @param value the estimated amount (± error) stated in the specified unit.
196     * @param error the measurement error (absolute).
197     * @param unit the unit in which the amount and the error are stated.
198     * @return the corresponding measure object.
199     * @throws IllegalArgumentException if <code>error &lt; 0.0</code>
200     */
201    public static <Q extends Quantity> Amount<Q> valueOf(double value,
202            double error, Unit<Q> unit) {
203        if (error < 0)
204            throw new IllegalArgumentException("error: " + error
205                    + " is negative");
206        Amount<Q> m = Amount.newInstance(unit);
207        double min = value - error;
208        double max = value + error;
209        m._isExact = false;
210        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
211        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
212        return m;
213    }
214
215    /**
216     * Returns the measure corresponding to the specified interval stated 
217     * in the specified unit.
218     *
219     * @param  minimum the lower bound for the measure value.
220     * @param  maximum the upper bound for the measure value.
221     * @param unit the unit for both the minimum and maximum values.
222     * @return the corresponding measure object.
223     * @throws IllegalArgumentException if <code>minimum &gt; maximum</code>
224     */
225    public static <Q extends Quantity> Amount<Q> rangeOf(double minimum,
226            double maximum, Unit<Q> unit) {
227        if (minimum > maximum)
228            throw new IllegalArgumentException("minimum: " + minimum
229                    + " greater than maximum: " + maximum);
230        Amount<Q> m = Amount.newInstance(unit);
231        m._isExact = false;
232        m._minimum = (minimum < 0) ? minimum * INCREMENT : minimum * DECREMENT;
233        m._maximum = (maximum < 0) ? maximum * DECREMENT : maximum * INCREMENT;
234        return m;
235    }
236
237    /**
238     * Returns the measure represented by the specified character sequence.
239     *
240     * @param csq the character sequence.
241     * @return <code>AmountFormat.getInstance().parse(csq)</code>
242     */
243    public static Amount<?> valueOf(CharSequence csq) {
244        return AmountFormat.getInstance().parse(csq);
245    }
246
247    /**
248     * Indicates if this measure is exact.
249     */
250    private boolean _isExact;
251
252    /**
253     * Holds the exact value (when exact) stated in this measure unit.
254     */
255    private long _exactValue;
256
257    /**
258     * Holds the minimum value stated in this measure unit.
259     * For inexact measures: _minimum < _maximum 
260     */
261    private double _minimum;
262
263    /**
264     * Holds the maximum value stated in this measure unit.
265     * For inexact measures: _maximum > _minimum 
266     */
267    private double _maximum;
268
269    /**
270     * Holds this measure unit. 
271     */
272    private Unit<Q> _unit;
273
274    /**
275     * Indicates if this measure amount is exact. An exact amount is 
276     * guarantee exact only when stated in this measure unit
277     * (e.g. <code>this.longValue()</code>); stating the amount
278     * in any other unit may introduce conversion errors. 
279     *
280     * @return <code>true</code> if this measure is exact;
281     *         <code>false</code> otherwise.
282     */
283    public boolean isExact() {
284        return _isExact;
285    }
286
287    /**
288     * Returns the unit in which the {@link #getEstimatedValue()
289     * estimated value} and {@link #getAbsoluteError() absolute error}
290     * are stated.
291     *
292     * @return the measure unit.
293     */
294    public Unit<Q> getUnit() {
295        return _unit;
296    }
297
298    /**
299     * Returns the exact value for this measure stated in this measure
300     * {@link #getUnit unit}. 
301     *
302     * @return the exact measure value (<code>long</code>) stated 
303     *         in this measure's {@link #getUnit unit}
304     * @throws AmountException if this measure is not {@link #isExact()}
305     */
306    public long getExactValue() throws AmountException {
307        if (!_isExact)
308            throw new AmountException(
309                    "Inexact measures don't have exact values");
310        return _exactValue;
311    }
312
313    /**
314     * Returns the estimated value for this measure stated in this measure
315     * {@link #getUnit unit}. 
316     *
317     * @return the median value of the measure interval.
318     */
319    public double getEstimatedValue() {
320        return (_isExact) ? _exactValue : (_minimum + _maximum) * 0.5;
321    }
322
323    /**
324     * Returns the lower bound interval value for this measure stated in 
325     * this measure unit.
326     *
327     * @return the minimum value.
328     */
329    public double getMinimumValue() {
330        return _minimum;
331    }
332
333    /**
334     * Returns the upper bound interval value for this measure stated in 
335     * this measure unit.
336     *
337     * @return the maximum value.
338     */
339    public double getMaximumValue() {
340        return _maximum;
341    }
342
343    /**
344     * Returns the value by which the{@link #getEstimatedValue() estimated 
345     * value} may differ from the true value (all stated in base units).
346     *
347     * @return the absolute error stated in base units.
348     */
349    public double getAbsoluteError() {
350        return MathLib.abs(_maximum - _minimum) * 0.5;
351    }
352
353    /**
354     * Returns the percentage by which the estimated amount may differ
355     * from the true amount.
356     *
357     * @return the relative error.
358     */
359    public double getRelativeError() {
360        return _isExact ? 0 : (_maximum - _minimum) / (_minimum + _maximum);
361    }
362
363    /**
364     * Returns the measure equivalent to this measure but stated in the 
365     * specified unit. The returned measure may not be exact even if this 
366     * measure is exact due to conversion errors. 
367     *
368     * @param  unit the unit of the measure to be returned.
369     * @return a measure equivalent to this measure but stated in the 
370     *         specified unit.
371     * @throws ConversionException if the current model does not allows for
372     *         conversion to the specified unit.
373     */
374    @SuppressWarnings("unchecked")
375    public <R extends Quantity> Amount<R> to(Unit<R> unit) {
376        if ((_unit == unit) || this._unit.equals(unit))
377            return (Amount<R>) this;
378        UnitConverter cvtr = Amount.converterOf(_unit, unit);
379        if (cvtr == UnitConverter.IDENTITY) { // No conversion necessary.
380            Amount result = Amount.copyOf(this);
381            result._unit = unit;
382            return result;
383        }
384        if (cvtr instanceof RationalConverter) { // Exact conversion.
385             RationalConverter rc = (RationalConverter) cvtr;
386             Amount result = this.times(rc.getDividend()).divide(rc.getDivisor());
387             result._unit = unit;
388             return result;
389        }
390        Amount<R> result = Amount.newInstance(unit);
391        double min = cvtr.convert(_minimum);
392        double max = cvtr.convert(_maximum);
393        result._isExact = false;
394        result._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
395        result._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
396        return result;
397    }
398
399    /**
400     * Returns the opposite of this measure.
401     *
402     * @return <code>-this</code>.
403     */
404    public Amount<Q> opposite() {
405        Amount<Q> m = Amount.newInstance(_unit);
406        if ((_isExact) && (_exactValue != Long.MAX_VALUE))
407            return m.setExact(-_exactValue);
408        m._isExact = false;
409        m._minimum = -_maximum;
410        m._maximum = -_minimum;
411        return m;
412    }
413
414    /**
415     * Returns the sum of this measure with the one specified.
416     *
417     * @param  that the measure to be added.
418     * @return <code>this + that</code>.
419     * @throws ConversionException if the current model does not allows for
420     *         these quantities to be added.
421     */
422    @SuppressWarnings("unchecked")
423    public Amount<Q> plus(Amount that) throws ConversionException {
424        final Amount thatToUnit = that.to(_unit);
425        Amount<Q> m = Amount.newInstance(_unit);
426        if (this._isExact && thatToUnit._isExact) {
427            long sumLong = this._exactValue + thatToUnit._exactValue;
428            double sumDouble = ((double) this._exactValue)
429                    + ((double) thatToUnit._exactValue);
430            if (sumLong == sumDouble)
431                return m.setExact(sumLong);
432        }
433        double min = this._minimum + thatToUnit._minimum;
434        double max = this._maximum + thatToUnit._maximum;
435        m._isExact = false;
436        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
437        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
438        return m;
439    }
440
441    /**
442     * Returns the difference of this measure with the one specified.
443     *
444     * @param  that the measure to be subtracted.
445     * @return <code>this - that</code>.
446     * @throws ConversionException if the current model does not allows for
447     *         these quantities to be subtracted.
448     */
449    @SuppressWarnings("unchecked")
450    public Amount<Q> minus(Amount that) throws ConversionException {
451        final Amount thatToUnit = that.to(_unit);
452        Amount<Q> m = Amount.newInstance(_unit);
453        if (this._isExact && thatToUnit._isExact) {
454            long diffLong = this._exactValue - thatToUnit._exactValue;
455            double diffDouble = ((double) this._exactValue)
456                    - ((double) thatToUnit._exactValue);
457            if (diffLong == diffDouble)
458                return m.setExact(diffLong);
459        }
460        double min = this._minimum - thatToUnit._maximum;
461        double max = this._maximum - thatToUnit._minimum;
462        m._isExact = false;
463        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
464        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
465        return m;
466    }
467
468    /**
469     * Returns this measure scaled by the specified exact factor 
470     * (dimensionless).
471     *
472     * @param  factor the scaling factor.
473     * @return <code>this · factor</code>.
474     */
475    public Amount<Q> times(long factor) {
476        Amount<Q> m = Amount.newInstance(_unit);
477        if (this._isExact) {
478            long productLong = _exactValue * factor;
479            double productDouble = ((double) _exactValue) * factor;
480            if (productLong == productDouble)
481                return m.setExact(productLong);
482        }
483        m._isExact = false;
484        m._minimum = (factor > 0) ? _minimum * factor : _maximum * factor;
485        m._maximum = (factor > 0) ? _maximum * factor : _minimum * factor;
486        return m;
487    }
488
489    /**
490     * Returns this measure scaled by the specified approximate factor
491     * (dimensionless).
492     *
493     * @param  factor the scaling factor.
494     * @return <code>this · factor</code>.
495     */
496    public Amount<Q> times(double factor) {
497        Amount<Q> m = Amount.newInstance(_unit);
498        double min = (factor > 0) ? _minimum * factor : _maximum * factor;
499        double max = (factor > 0) ? _maximum * factor : _minimum * factor;
500        m._isExact = false;
501        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
502        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
503        return m;
504    }
505
506    /**
507     * Returns the product of this measure with the one specified.
508     *
509     * @param  that the measure multiplier.
510     * @return <code>this · that</code>.
511     */
512    @SuppressWarnings("unchecked")
513    public Amount<? extends Quantity> times(Amount that) {
514        Unit<?> unit = Amount.productOf(this._unit, that._unit);
515        if (that._isExact) {
516            Amount m = this.times(that._exactValue);
517            m._unit = unit;
518            return m;
519        }
520        Amount<Q> m = Amount.newInstance(unit);
521        double min, max;
522        if (_minimum >= 0) {
523            if (that._minimum >= 0) {
524                min = _minimum * that._minimum;
525                max = _maximum * that._maximum;
526            } else if (that._maximum < 0) {
527                min = _maximum * that._minimum;
528                max = _minimum * that._maximum;
529            } else {
530                min = _maximum * that._minimum;
531                max = _maximum * that._maximum;
532            }
533        } else if (_maximum < 0) {
534            if (that._minimum >= 0) {
535                min = _minimum * that._maximum;
536                max = _maximum * that._minimum;
537            } else if (that._maximum < 0) {
538                min = _maximum * that._maximum;
539                max = _minimum * that._minimum;
540            } else {
541                min = _minimum * that._maximum;
542                max = _minimum * that._minimum;
543            }
544        } else {
545            if (that._minimum >= 0) {
546                min = _minimum * that._maximum;
547                max = _maximum * that._maximum;
548            } else if (that._maximum < 0) {
549                min = _maximum * that._minimum;
550                max = _minimum * that._minimum;
551            } else { // Both around zero.
552                min = MathLib.min(_minimum * that._maximum, _maximum
553                        * that._minimum);
554                max = MathLib.max(_minimum * that._minimum, _maximum
555                        * that._maximum);
556            }
557        }
558        m._isExact = false;
559        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
560        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
561        return m;
562    }
563
564    /**
565     * Returns the multiplicative inverse of this measure.
566     * If this measure is possibly zero, then the result is unbounded
567     * (]-infinity, +infinity[).
568     *
569     * @return <code>1 / this</code>.
570     */
571    public Amount<? extends Quantity> inverse() {
572        Amount<? extends Quantity> m = newInstance(Amount.inverseOf(_unit));
573        if ((_isExact) && (_exactValue == 1L)) { // Only one exact inverse: one
574            m.setExact(1L);
575            return m;
576        }
577        m._isExact = false;
578        if ((_minimum <= 0) && (_maximum >= 0)) { // Encompass zero.
579            m._minimum = Double.NEGATIVE_INFINITY;
580            m._maximum = Double.POSITIVE_INFINITY;
581            return m;
582        }
583        double min = 1.0 / _maximum;
584        double max = 1.0 / _minimum;
585        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
586        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
587        return m;
588    }
589
590    /**
591     * Returns this measure divided by the specified exact divisor
592     * (dimensionless).
593     *
594     * @param  divisor the exact divisor.
595     * @return <code>this / divisor</code>.
596     * @throws ArithmeticException if this measure is exact and the 
597     *         specified divisor is zero.
598     */
599    public Amount<Q> divide(long divisor) {
600        Amount<Q> m = Amount.newInstance(_unit);
601        if (this._isExact) {
602            long quotientLong = _exactValue / divisor;
603            double quotientDouble = ((double) _exactValue) / divisor;
604            if (quotientLong == quotientDouble)
605                return m.setExact(quotientLong);
606        }
607        double min = (divisor > 0) ? _minimum / divisor : _maximum / divisor;
608        double max = (divisor > 0) ? _maximum / divisor : _minimum / divisor;
609        m._isExact = false;
610        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
611        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
612        return m;
613    }
614
615    /**
616     * Returns this measure divided by the specified approximate divisor
617     * (dimensionless).
618     *
619     * @param  divisor the approximated divisor.
620     * @return <code>this / divisor</code>.
621     */
622    public Amount<Q> divide(double divisor) {
623        Amount<Q> m = Amount.newInstance(_unit);
624        double min = (divisor > 0) ? _minimum / divisor : _maximum / divisor;
625        double max = (divisor > 0) ? _maximum / divisor : _minimum / divisor;
626        m._isExact = false;
627        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
628        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
629        return m;
630    }
631
632    /**
633     * Returns this measure divided by the one specified.
634     *
635     * @param  that the measure divisor.
636     * @return <code>this / that</code>.
637     */
638    @SuppressWarnings("unchecked")
639    public Amount<? extends Quantity> divide(Amount that) {
640        if (that._isExact) {
641            Amount m = this.divide(that._exactValue);
642            m._unit = Amount.productOf(this._unit, Amount
643                    .inverseOf(that._unit));
644            return m;
645        }
646        return this.times(that.inverse());
647    }
648
649    /**
650     * Returns the absolute value of this measure.
651     *
652     * @return  <code>|this|</code>.
653     */
654    public Amount<Q> abs() {
655        return (_isExact) ? ((_exactValue < 0) ? this.opposite() : this)
656                : (_minimum >= -_maximum) ? this : this.opposite();
657    }
658
659    /**
660     * Returns the square root of this measure.
661     *
662     * @return <code>sqrt(this)</code>
663     * 
664     */
665    public Amount<? extends Quantity> sqrt() {
666        Amount<Q> m = Amount.newInstance(_unit.root(2));
667        if (this._isExact) {
668            double sqrtDouble = MathLib.sqrt(_exactValue);
669            long sqrtLong = (long) sqrtDouble;
670            if (sqrtLong * sqrtLong == _exactValue)
671                return m.setExact(sqrtLong);
672        }
673        double min = MathLib.sqrt(_minimum);
674        double max = MathLib.sqrt(_maximum);
675        m._isExact = false;
676        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
677        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
678        return m;
679    }
680
681    /**
682     * Returns the given root of this measure.
683     *
684     * @param  n the root's order (n != 0).
685     * @return the result of taking the given root of this quantity.
686     * @throws ArithmeticException if <code>n == 0</code>.
687     */
688    public Amount<? extends Quantity> root(int n) {
689        if (n == 0)
690            throw new ArithmeticException("Root's order of zero");
691        if (n < 0)
692            return this.root(-n).inverse();
693        if (n == 2)
694            return this.sqrt();
695        Amount<Q> m = Amount.newInstance(_unit.root(n));
696        if (this._isExact) {
697            double rootDouble = MathLib.pow(_exactValue, 1.0 / n);
698            long rootLong = (long) rootDouble;
699            long thisLong = rootLong;
700            for (int i = 1; i < n; i++) {
701                thisLong *= rootLong;
702            }
703            if (thisLong == _exactValue)
704                return m.setExact(rootLong);
705        }
706        double min = MathLib.pow(_minimum, 1.0 / n);
707        double max = MathLib.pow(_maximum, 1.0 / n);
708        m._isExact = false;
709        m._minimum = (min < 0) ? min * INCREMENT : min * DECREMENT;
710        m._maximum = (max < 0) ? max * DECREMENT : max * INCREMENT;
711        return m;
712    }
713
714    /**
715     * Returns this measure raised at the specified exponent.
716     *
717     * @param  exp the exponent.
718     * @return <code>this<sup>exp</sup></code>
719     */
720    public Amount<? extends Quantity> pow(int exp) {
721        if (exp < 0)
722            return this.pow(-exp).inverse();
723        if (exp == 0)
724            return ONE;
725        Amount<?> pow2 = this;
726        Amount<?> result = null;
727        while (exp >= 1) { // Iteration.
728            if ((exp & 1) == 1) {
729                result = (result == null) ? pow2 : result.times(pow2);
730            }
731            pow2 = pow2.times(pow2);
732            exp >>>= 1;
733        }
734        return result;
735    }
736
737    /**
738     * Compares this measure with the specified measurable object.
739     *
740     * @param  that the measure to compare with.
741     * @return a negative integer, zero, or a positive integer as this measure
742     *         is less than, equal to, or greater than that measurable.
743     * @throws ConversionException if the current model does not allows for
744     *         these measure to be compared.
745     */
746    @SuppressWarnings("unchecked")
747    public int compareTo(Measurable<Q> that) {
748        double thatValue = that.doubleValue(_unit);
749        return Double.compare(this.getEstimatedValue(), thatValue);
750    }
751
752    /**
753     * Compares this measure against the specified object for strict 
754     * equality (same value interval and same units).
755     *
756     * @param  that the object to compare with.
757     * @return <code>true</code> if this measure is identical to that
758     *         measure; <code>false</code> otherwise.
759     */
760    public boolean equals(Object that) {
761        if (this == that)
762            return true;
763        if (!(that instanceof Amount<?>))
764            return false;
765        Amount<?> m = (Amount<?>) that;
766        if (!_unit.equals(m._unit))
767            return false;
768        if (_isExact != m._isExact)
769            return false;
770        if (_isExact && (this._exactValue == m._exactValue))
771            return true;
772        if (_minimum != m._minimum)
773            return false;
774        if (_maximum != m._maximum)
775            return false;
776        return true;
777    }
778
779    /**
780     * Returns the hash code for this measure.
781     * 
782     * @return the hash code value.
783     */
784    public int hashCode() {
785        int h = Float.floatToIntBits((float) _minimum);
786        h += ~(h << 9);
787        h ^= (h >>> 14);
788        h += (h << 4);
789        return h ^ (h >>> 10);
790    }
791
792    /**
793     * Indicates if this measure approximates that measure.
794     * Measures are considered approximately equals if their value intervals
795     * overlaps. It should be noted that less accurate measurements are 
796     * more likely to be approximately equals. It is therefore recommended
797     * to ensure that the measurement error is not too large before testing
798     * for approximate equality.
799     *
800     * @return <code>this ≅ that</code>
801     */
802    @SuppressWarnings("unchecked")
803    public boolean approximates(Amount that) {
804        Amount thatToUnit = that.to(_unit);
805        return (this._maximum >= thatToUnit._minimum)
806                && (thatToUnit._maximum >= this._minimum);
807    }
808
809    /**
810     * Indicates if this measure is ordered before that measure
811     * (independently of the measure unit).
812     *
813     * @return <code>this.compareTo(that) < 0</code>.
814     */
815    public boolean isLessThan(Amount<Q> that) {
816        return this.compareTo(that) < 0;
817    }
818
819    /**
820     * Indicates if this measure is ordered after that measure
821     * (independently of the measure unit).
822     *
823     * @return <code>this.compareTo(that) > 0</code>.
824     */
825    public boolean isGreaterThan(Amount<Q> that) {
826        return this.compareTo(that) > 0;
827    }
828
829    /**
830     * Compares this measure with that measure ignoring the sign.
831     *
832     * @return <code>|this| > |that|</code>
833     */
834    public boolean isLargerThan(Amount<Q> that) {
835        return this.abs().isGreaterThan(that.abs());
836    }
837
838    /**
839     * Returns the text representation of this measure.
840     *
841     * @return <code>AmountFormat.getInstance().format(this)</code>
842     */
843    public Text toText() {
844        return AmountFormat.getInstance().format(this);
845    }
846
847    /**
848     * Returns the text representation of this amount as a 
849     * <code>java.lang.String</code>.
850     * 
851     * @return <code>toText().toString()</code>
852     */
853    public final String toString() {
854        return toText().toString();
855    }
856
857    // Implements Quantity.
858    public double doubleValue(Unit<Q> unit) {
859        return ((_unit == unit) || _unit.equals(unit)) ? this
860                .getEstimatedValue() : this.to(unit).getEstimatedValue();
861    }
862
863    // Implements Quantity.
864    public final long longValue(Unit<Q> 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 + " " + _unit
873                + " cannot be represented as long");
874    }
875
876    ///////////////////
877    // Lookup tables //
878    ///////////////////
879
880    static final FastMap<Unit<?>, FastMap<Unit<?>, Unit<?>>> MULT_LOOKUP = new FastMap<Unit<?>, FastMap<Unit<?>, Unit<?>>>(
881            "UNITS_MULT_LOOKUP").setKeyComparator(FastComparator.DIRECT);
882
883    static final FastMap<Unit<?>, Unit<?>> INV_LOOKUP = new FastMap<Unit<?>, Unit<?>>(
884            "UNITS_INV_LOOKUP").setKeyComparator(FastComparator.DIRECT);
885
886    static final FastMap<Unit<?>, FastMap<Unit<?>, UnitConverter>> CVTR_LOOKUP = new FastMap<Unit<?>, FastMap<Unit<?>, UnitConverter>>(
887            "UNITS_CVTR_LOOKUP").setKeyComparator(FastComparator.DIRECT);
888
889    private static Unit<?> productOf(Unit<?> left, Unit<?> right) {
890        FastMap<Unit<?>, Unit<?>> 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<Unit<?>, Unit<?>> leftTable = MULT_LOOKUP.get(left);
904                if (leftTable == null) {
905                    leftTable = new FastMap<Unit<?>, Unit<?>>().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<Unit<?>, UnitConverter> 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<Unit<?>, UnitConverter> leftTable = CVTR_LOOKUP.get(left);
956                if (leftTable == null) {
957                    leftTable = new FastMap<Unit<?>, UnitConverter>()
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    public Amount<Q> copy() {
976        Amount<Q> estimate = Amount.newInstance(_unit);
977        estimate._isExact = _isExact;
978        estimate._exactValue = _exactValue;
979        estimate._minimum = _minimum;
980        estimate._maximum = _maximum;
981        return estimate;
982    }
983    
984    //////////////////////
985    // Factory Creation //
986    //////////////////////
987
988    @SuppressWarnings("unchecked")
989    private static <Q extends Quantity> Amount<Q> newInstance(Unit<?> unit) {
990        Amount<Q> measure = FACTORY.object();
991        measure._unit = (Unit<Q>)unit;
992        return measure;
993    }
994
995    @SuppressWarnings("unchecked")
996    private static <Q extends Quantity> Amount<Q> copyOf(Amount original) {
997        Amount<Q> measure = FACTORY.object();
998        measure._exactValue = original._exactValue;
999        measure._isExact = original._isExact;
1000        measure._maximum = original._maximum;
1001        measure._minimum = original._minimum;
1002        measure._unit = original._unit;
1003        return measure;
1004    }
1005
1006    @SuppressWarnings("unchecked")
1007    private static final ObjectFactory<Amount> FACTORY = new ObjectFactory<Amount>() {
1008
1009        @Override
1010        protected Amount create() {
1011            return new Amount();
1012        }
1013    };
1014
1015    private Amount() {
1016    }
1017
1018    private Amount<Q> setExact(long exactValue) {
1019        _isExact = true;
1020        _exactValue = exactValue;
1021        double doubleValue = exactValue;
1022        if (doubleValue == exactValue) {
1023            _minimum = doubleValue;
1024            _maximum = doubleValue;
1025        } else {
1026            double valInc = exactValue * INCREMENT;
1027            double valDec = exactValue * DECREMENT;
1028            _minimum = (_exactValue < 0) ? valInc : valDec;
1029            _maximum = (_exactValue < 0) ? valDec : valInc;
1030        }
1031        return this;
1032    }
1033
1034    static final double DOUBLE_RELATIVE_ERROR = MathLib.pow(2, -53);
1035
1036    static final double DECREMENT = (1.0 - DOUBLE_RELATIVE_ERROR);
1037
1038    static final double INCREMENT = (1.0 + DOUBLE_RELATIVE_ERROR);
1039
1040    private static final long serialVersionUID = 1L;
1041
1042   
1043}