KickJava   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 is
7  * freely granted, provided that this notice is preserved.
8  */

9 package org.jscience.physics.measures;
10
11 import java.io.Serializable JavaDoc;
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  * <p> This class represents a measurable amount; the nature of the amount
34  * is deduced from the measure {@link #getUnit() unit}; the quality of
35  * the measure is given by the measurement {@link #getAbsoluteError()
36  * error}.</p>
37  *
38  * <p> Measures can be {@link #isExact() exact}, in which case they can be
39  * expressed as an exact <code>long</code> integer in the measure unit.
40  * The framework tries to keep measures exact as much as possible.
41  * For example:[code]
42  * Measure<Length> 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 ft
47  * > exact
48  * > 6[/code]
49  * </p>
50  *
51  * <p> 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  * </p>
57  *
58  * <p> By default, non-exact measure instances are shown using the plus/minus
59  * character ('±') (see {@link MeasureFormat}). For example,
60  * <code>"(2.0 ± 0.001) km/s"</code> represents a velocity of
61  * 2 km/s with an absolute error of ± 1 m/s. Exact measurements use an
62  * integer notation (no decimal point, e.g. <code>"2000 m"</code>).</p>
63  *
64  * <p> Operations between different measures may or may not be authorized
65  * based upon the current {@link org.jscience.physics.models.PhysicalModel
66  * PhysicalModel}. For example, adding <code>Measure&lt;Length&gt; and
67  * <code>Measure&lt;Duration&gt; is not allowed by the
68  * {@link org.jscience.physics.models.StandardModel StandardModel},
69  * but is authorized with the {@link
70  * org.jscience.physics.models.RelativisticModel RelativisticModel}.</p>
71  *
72  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
73  * @version 3.0, February 26, 2006
74  * @see <a HREF="http://en.wikipedia.org/wiki/Measuring">
75  * Wikipedia: Measuring</a>
76  */

77 public final class Measure<Q extends Quantity> extends RealtimeObject implements
78         Quantity<Q>, Field<Measure<?>>, Comparable JavaDoc<Measure>, Serializable JavaDoc, 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<Dimensionless> ZERO = new Measure<Dimensionless>();
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<Dimensionless> ONE = new Measure<Dimensionless>();
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 <code>value</code>,
112      * an <code>unit</code> and an optional <code>error</code> attribute
113      * when the measure is not exact.
114      * The unit attribute determinates the measurement type. For example:<pre>
115      * &lt;Measure value="12" unit="µA"/&gt;</pre>
116      * represents an electric current measurement.
117      */

118     protected static final XMLFormat<Measure> XML = new XMLFormat<Measure>(
119             Measure.class) {
120         
121         @Override JavaDoc
122         public Measure newInstance(Class JavaDoc<Measure> 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 JavaDoc
136         public void read(javolution.xml.XMLFormat.InputElement arg0, Measure arg1) throws XMLStreamException {
137             // Nothing to do.
138
}
139
140         @Override JavaDoc
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 <Q extends Quantity> Measure<Q> valueOf(long value,
161             Unit<Q> unit) {
162         Measure<Q> m = Measure.newInstance(unit);
163         return m.setExact(value);
164     }
165
166     /**
167      * Returns the measure corresponding to an approximate value
168      * (<code>double</code>) stated in the specified unit;
169      * the precision of the measure is assumed to be the
170      * <code>double</code> 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 <Q extends Quantity> Measure<Q> valueOf(double value,
177             Unit<Q> unit) {
178         Measure<Q> 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 <code>error &lt; 0.0</code>
196      */

197     public static <Q extends Quantity> Measure<Q> valueOf(double value,
198             double error, Unit<Q> unit) {
199         if (error < 0)
200             throw new IllegalArgumentException JavaDoc("error: " + error
201                     + " is negative");
202         Measure<Q> 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 <code>minimum &gt; maximum</code>
220      */

221     public static <Q extends Quantity> Measure<Q> rangeOf(double minimum,
222             double maximum, Unit<Q> unit) {
223         if (minimum > maximum)
224             throw new IllegalArgumentException JavaDoc("minimum: " + minimum
225                     + " greater than maximum: " + maximum);
226         Measure<Q> 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 <code>MeasureFormat.getInstance().parse(csq)</code>
238      */

239     public static Measure<?> valueOf(CharSequence JavaDoc 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<Q> _unit;
269
270     /**
271      * Indicates if this measure amount is exact. An exact amount is
272      * guarantee exact only when stated in this measure unit
273      * (e.g. <code>this.longValue()</code>); stating the amount
274      * in any other unit may introduce conversion errors.
275      *
276      * @return <code>true</code> if this measure is exact;
277      * <code>false</code> 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<Q> getUnit() {
291         return _unit;
292     }
293
294     /**
295      * Returns the exact value for this measure stated in this measure
296      * {@link #getUnit unit}.
297      *
298      * @return the exact measure value (<code>long</code>) 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 measure
311      * {@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 differ
351      * 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 for
368      * conversion to the specified unit.
369      */

370     @SuppressWarnings JavaDoc("unchecked")
371     public <R extends Quantity> Measure<R> to(Unit<R> unit) {
372         if ((_unit == unit) || this._unit.equals(unit))
373             return (Measure<R>) 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<R> 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 <code>-this</code>.
399      */

400     public Measure<Q> opposite() {
401         Measure<Q> 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 <code>this + that</code>.
415      * @throws ConversionException if the current model does not allows for
416      * these quantities to be added.
417      */

418     @SuppressWarnings JavaDoc("unchecked")
419     public Measure<Q> plus(Measure that) throws ConversionException {
420         final Measure thatToUnit = that.to(_unit);
421         Measure<Q> 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 <code>this - that</code>.
442      * @throws ConversionException if the current model does not allows for
443      * these quantities to be subtracted.
444      */

445     @SuppressWarnings JavaDoc("unchecked")
446     public Measure<Q> minus(Measure that) throws ConversionException {
447         final Measure thatToUnit = that.to(_unit);
448         Measure<Q> 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 <code>this · factor</code>.
470      */

471     public Measure<Q> times(long factor) {
472         Measure<Q> 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 factor
487      * (dimensionless).
488      *
489      * @param factor the scaling factor.
490      * @return <code>this · factor</code>.
491      */

492     public Measure<Q> times(double factor) {
493         Measure<Q> 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 <code>this · that</code>.
507      */

508     @SuppressWarnings JavaDoc("unchecked")
509     public Measure<? extends Quantity> 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<Q> 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, _maximum
549                         * that._minimum);
550                 max = MathLib.max(_minimum * that._minimum, _maximum
551                         * 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 unbounded
563      * (]-infinity, +infinity[).
564      *
565      * @return <code>1 / this</code>.
566      */

567     public Measure<? extends Quantity> inverse() {
568         Measure<? extends Quantity> m = newInstance(Measure.inverseOf(_unit));
569         if ((_isExact) && (_exactValue == 1L)) { // Only one exact inverse: one
570
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 divisor
588      * (dimensionless).
589      *
590      * @param divisor the exact divisor.
591      * @return <code>this / divisor</code>.
592      * @throws ArithmeticException if this measure is exact and the
593      * specified divisor is zero.
594      */

595     public Measure<Q> divide(long divisor) {
596         Measure<Q> 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 divisor
613      * (dimensionless).
614      *
615      * @param divisor the approximated divisor.
616      * @return <code>this / divisor</code>.
617      */

618     public Measure<Q> divide(double divisor) {
619         Measure<Q> 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 <code>this / that</code>.
633      */

634     @SuppressWarnings JavaDoc("unchecked")
635     public Measure<? extends Quantity> divide(Measure that) {
636         if (that._isExact) {
637             Measure m = this.divide(that._exactValue);
638             m._unit = Measure.productOf(this._unit, Measure
639                     .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 <code>|this|</code>.
649      */

650     public Measure<Q> 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 <code>sqrt(this)</code>
659      *
660      */

661     public Measure<? extends Quantity> sqrt() {
662         Measure<Q> 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 <code>n == 0</code>.
683      */

684     public Measure<? extends Quantity> root(int n) {
685         if (n == 0)
686             throw new ArithmeticException JavaDoc("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<Q> 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 <code>this<sup>exp</sup></code>
715      */

716     public Measure<? extends Quantity> 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 measure
739      * is less than, equal to, or greater than that measure.
740      * @throws ConversionException if the current model does not allows for
741      * these measure to be compared.
742      */

743     @SuppressWarnings JavaDoc("unchecked")
744     public int compareTo(Measure that) {
745         Measure thatToUnit = that.to(_unit);
746         if (_isExact && thatToUnit._isExact)
747             return _exactValue < thatToUnit._exactValue ? -1
748                     : _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 <code>true</code> if this measure is identical to that
768      * measure; <code>false</code> otherwise.
769      */

770     public boolean equals(Object JavaDoc 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 intervals
805      * overlaps. It should be noted that less accurate measurements are
806      * more likely to be approximately equals. It is therefore recommended
807      * to ensure that the measurement error is not too large before testing
808      * for approximate equality.
809      *
810      * @return <code>this ≅ that</code>
811      */

812     @SuppressWarnings JavaDoc("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 measure
821      * (independently of the measure unit).
822      *
823      * @return <code>this.compareTo(that) < 0</code>.
824      */

825     public boolean isLessThan(Measure<Q> that) {
826         return this.compareTo(that) < 0;
827     }
828
829     /**
830      * Indicates if this measure is ordered after that measure
831      * (independently of the measure unit).
832      *
833      * @return <code>this.compareTo(that) > 0</code>.
834      */

835     public boolean isGreaterThan(Measure<Q> that) {
836         return this.compareTo(that) > 0;
837     }
838
839     /**
840      * Compares this measure with that measure ignoring the sign.
841      *
842      * @return <code>|this| > |that|</code>
843      */

844     public boolean isLargerThan(Measure<Q> that) {
845         return this.abs().isGreaterThan(that.abs());
846     }
847
848     /**
849      * Returns the text representation of this measure.
850      *
851      * @return <code>MeasureFormat.getInstance().format(this)</code>
852      */

853     public Text toText() {
854         return MeasureFormat.getInstance().format(this);
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 JavaDoc(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 JavaDoc() {
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 JavaDoc() {
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 JavaDoc() {
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     //////////////////////
976
// Factory Creation //
977
//////////////////////
978

979     @SuppressWarnings JavaDoc("unchecked")
980     private static <Q extends Quantity> Measure<Q> newInstance(Unit unit) {
981         Measure<Q> measure = FACTORY.object();
982         measure._unit = unit;
983         return measure;
984     }
985
986     @SuppressWarnings JavaDoc("unchecked")
987     private static <Q extends Quantity> Measure<Q> copyOf(Measure original) {
988         Measure<Q> 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<Measure> FACTORY = new Factory<Measure>() {
998
999         @Override JavaDoc
1000        protected Measure create() {
1001            return new Measure();
1002        }
1003    };
1004
1005    private Measure() {
1006    }
1007
1008    private Measure<Q> 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    }
1023
1024    static final double DOUBLE_RELATIVE_ERROR = MathLib.pow(2, -53);
1025
1026    static final double DECREMENT = (1.0 - DOUBLE_RELATIVE_ERROR);
1027
1028    static final double INCREMENT = (1.0 + DOUBLE_RELATIVE_ERROR);
1029
1030    private static final long serialVersionUID = 1L;
1031}
Popular Tags