1 9 package org.jscience.physics.measures; 10 11 import java.io.Serializable ; 12 13 import javolution.lang.Immutable; 14 import javolution.lang.MathLib; 15 import javolution.text.Text; 16 import javolution.context.RealtimeObject; 17 import javolution.util.FastComparator; 18 import javolution.util.FastMap; 19 import javolution.xml.XMLFormat; 20 import javolution.xml.stream.XMLStreamException; 21 22 import org.jscience.mathematics.structures.Field; 23 24 import javax.measure.converters.ConversionException; 25 import javax.measure.converters.RationalConverter; 26 import javax.measure.converters.UnitConverter; 27 import javax.measure.quantities.Dimensionless; 28 import javax.measure.quantities.Quantity; 29 import javax.measure.units.Unit; 30 import javax.realtime.MemoryArea; 31 32 77 public final class Measure<Q extends Quantity> extends RealtimeObject implements 78 Quantity<Q>, Field<Measure<?>>, Comparable <Measure>, Serializable , Immutable { 79 80 85 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 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 118 protected static final XMLFormat<Measure> XML = new XMLFormat<Measure>( 119 Measure.class) { 120 121 @Override 122 public Measure newInstance(Class <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) return m.setExact(xml.getAttribute("value", 0L)); 127 m._isExact = false; 128 double estimatedValue = xml.getAttribute("value", 0.0); 129 double error = xml.getAttribute("error", 0.0); 130 m._minimum = estimatedValue - error; 131 m._maximum = estimatedValue + error; 132 return m; 133 } 134 135 @Override 136 public void read(javolution.xml.XMLFormat.InputElement arg0, Measure arg1) throws XMLStreamException { 137 } 139 140 @Override 141 public void write(Measure m, OutputElement xml) throws XMLStreamException { 142 if (m._isExact) { 143 xml.setAttribute("value", m._exactValue); 144 } else { 145 xml.setAttribute("value", m.getEstimatedValue()); 146 xml.setAttribute("error", m.getAbsoluteError()); 147 } 148 xml.setAttribute("unit", m._unit.toString()); 149 } 150 }; 151 152 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 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 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 ("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 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 ("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 239 public static Measure<?> valueOf(CharSequence csq) { 240 return MeasureFormat.getInstance().parse(csq); 241 } 242 243 246 private boolean _isExact; 247 248 251 private long _exactValue; 252 253 257 private double _minimum; 258 259 263 private double _maximum; 264 265 268 private Unit<Q> _unit; 269 270 279 public boolean isExact() { 280 return _isExact; 281 } 282 283 290 public Unit<Q> getUnit() { 291 return _unit; 292 } 293 294 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 315 public double getEstimatedValue() { 316 return (_isExact) ? _exactValue : (_minimum + _maximum) * 0.5; 317 } 318 319 325 public double getMinimumValue() { 326 return _minimum; 327 } 328 329 335 public double getMaximumValue() { 336 return _maximum; 337 } 338 339 345 public double getAbsoluteError() { 346 return MathLib.abs(_maximum - _minimum) * 0.5; 347 } 348 349 355 public double getRelativeError() { 356 return (_maximum - _minimum) / (_minimum + _maximum); 357 } 358 359 370 @SuppressWarnings ("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) { Measure result = Measure.copyOf(this); 377 result._unit = unit; 378 return result; 379 } 380 if (cvtr instanceof RationalConverter) { 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 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 418 @SuppressWarnings ("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 445 @SuppressWarnings ("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 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 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 508 @SuppressWarnings ("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 { 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 567 public Measure<? extends Quantity> inverse() { 568 Measure<? extends Quantity> m = newInstance(Measure.inverseOf(_unit)); 569 if ((_isExact) && (_exactValue == 1L)) { m.setExact(1L); 571 return m; 572 } 573 m._isExact = false; 574 if ((_minimum <= 0) && (_maximum >= 0)) { 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 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 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 634 @SuppressWarnings ("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 650 public Measure<Q> abs() { 651 return (_isExact) ? ((_exactValue < 0) ? this.opposite() : this) 652 : (_minimum >= -_maximum) ? this : this.opposite(); 653 } 654 655 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 684 public Measure<? extends Quantity> root(int n) { 685 if (n == 0) 686 throw new ArithmeticException ("Root's order of zero"); 687 if (n < 0) 688 return this.root(-n).inverse(); 689 if (n == 2) 690 return this.sqrt(); 691 Measure<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 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) { 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 743 @SuppressWarnings ("unchecked") 744 public int compareTo(Measure that) { 745 Measure thatToUnit = that.to(_unit); 746 if (_isExact && thatToUnit._isExact) 747 return _exactValue < thatToUnit._exactValue ? -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 770 public boolean equals(Object that) { 771 if (this == that) 772 return true; 773 if (!(that instanceof Measure)) 774 return false; 775 Measure<?> m = (Measure) that; 776 if (!_unit.equals(m._unit)) 777 return false; 778 if (_isExact != m._isExact) 779 return false; 780 if (_isExact && (this._exactValue == m._exactValue)) 781 return true; 782 if (_minimum != m._minimum) 783 return false; 784 if (_maximum != m._maximum) 785 return false; 786 return true; 787 } 788 789 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 812 @SuppressWarnings ("unchecked") 813 public boolean approximates(Measure that) { 814 Measure thatToUnit = that.to(_unit); 815 return (this._maximum >= thatToUnit._minimum) 816 && (thatToUnit._maximum >= this._minimum); 817 } 818 819 825 public boolean isLessThan(Measure<Q> that) { 826 return this.compareTo(that) < 0; 827 } 828 829 835 public boolean isGreaterThan(Measure<Q> that) { 836 return this.compareTo(that) > 0; 837 } 838 839 844 public boolean isLargerThan(Measure<Q> that) { 845 return this.abs().isGreaterThan(that.abs()); 846 } 847 848 853 public Text toText() { 854 return MeasureFormat.getInstance().format(this); 855 } 856 857 public double doubleValue(Unit<Q> unit) { 859 return ((_unit == unit) || _unit.equals(unit)) ? this 860 .getEstimatedValue() : this.to(unit).getEstimatedValue(); 861 } 862 863 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 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 979 @SuppressWarnings ("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 ("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 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 |