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<Length> and 070 * <code>Amount<Duration> 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 * <Amount value="12" unit="µA"/></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 < 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 > 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}