1 9 package org.jscience.mathematics.numbers; 10 11 import org.jscience.mathematics.structures.Field; 12 13 import javolution.lang.MathLib; 14 import javolution.context.LocalContext; 15 import javolution.text.Text; 16 import javolution.text.TypeFormat; 17 import javolution.xml.XMLFormat; 18 import javolution.xml.stream.XMLStreamException; 19 20 61 public final class Real extends Number <Real> implements Field<Real> { 62 63 68 protected static final XMLFormat<Real> XML = new XMLFormat<Real>(Real.class) { 69 70 @Override 71 public Real newInstance(Class <Real> cls, InputElement xml) throws XMLStreamException { 72 return Real.valueOf(xml.getAttribute("value")); 73 } 74 75 public void write(Real real, OutputElement xml) throws XMLStreamException { 76 xml.setAttribute("value", real.toText()); 77 } 78 79 public void read(InputElement xml, Real real) { 80 } 82 }; 83 84 87 public static final Real NaN = new Real(); static { 89 NaN._mantissa = LargeInteger.ZERO; 90 NaN._error = LargeInteger.ONE; 91 NaN._exponent = Integer.MAX_VALUE; 92 } 93 94 97 public static final Real ZERO = new Real(); 98 static { 99 ZERO._mantissa = LargeInteger.ZERO; 100 ZERO._error = LargeInteger.ZERO; 101 ZERO._exponent = 0; 102 } 103 104 107 public static final Real ONE = new Real(); 108 static { 109 ZERO._mantissa = LargeInteger.ONE; 110 ZERO._error = LargeInteger.ZERO; 111 ZERO._exponent = 0; 112 } 113 114 117 private static final LocalContext.Reference<Integer > EXACT_PRECISION = 118 new LocalContext.Reference<Integer >(new Integer (19)); 119 120 123 private LargeInteger _mantissa; 124 125 128 private LargeInteger _error; 129 130 133 private int _exponent; 134 135 138 private Real() { 139 } 140 141 148 public static int getExactMinimumPrecision() { 149 return EXACT_PRECISION.get(); 150 } 151 152 159 public static void setExactMinimumPrecision(int precision) { 160 EXACT_PRECISION.set(precision); 161 } 162 163 182 public static Real valueOf(LargeInteger mantissa, LargeInteger error, 183 int exponent) { 184 if (error.isNegative()) 185 throw new IllegalArgumentException ("Error cannot be negative"); 186 Real real = FACTORY.object(); 187 real._mantissa = mantissa; 188 real._error = error; 189 real._exponent = exponent; 190 return real; 191 } 192 193 202 public static Real valueOf(double doubleValue) { 203 if (doubleValue == 0.0) 204 return Real.ZERO; 205 int e = MathLib.floorLog10(doubleValue) - 18 + 1; long mantissa = MathLib.toLongPow10(doubleValue, -e); 208 int error = (int) MathLib.toLongPow10(Math.ulp(doubleValue), -e) + 1; 209 return 210 Real.valueOf(LargeInteger.valueOf(mantissa), LargeInteger.valueOf(error), e); 211 } 212 213 214 221 public static Real valueOf(long longValue) { 222 return Real.valueOf(LargeInteger.valueOf(longValue), LargeInteger.ZERO, 0); 223 } 224 225 237 public static Real valueOf(CharSequence chars) throws NumberFormatException { 238 Text txt = Text.valueOf(chars); if ((txt.length() == 3) && (txt.indexOf("NaN", 0) == 0)) 240 return NaN; 241 if (txt.equals("0")) return ZERO; 242 int exponentIndex = txt.indexOf("E", 0); 243 if (exponentIndex >= 0) { 244 int exponent = TypeFormat.parseInt(txt.subtext( 245 exponentIndex + 1, txt.length())); 246 Real r = valueOf(txt.subtext(0, exponentIndex)); 247 if (r == ZERO) 248 return valueOf(LargeInteger.ZERO, LargeInteger.ONE, exponent); 249 r._exponent += exponent; 250 return r; 251 } 252 Real real = FACTORY.object(); 253 int errorIndex = txt.indexOf("±", 0); 254 if (errorIndex >= 0) { 255 real._mantissa = LargeInteger.valueOf(txt.subtext(0, 256 errorIndex)); 257 real._error = LargeInteger.valueOf(txt.subtext( 258 errorIndex + 1, txt.length())); 259 if (real._error.isNegative()) 260 throw new NumberFormatException (chars 261 + " not parsable (error cannot be negative)"); 262 real._exponent = 0; 263 return real; 264 } 265 int decimalPointIndex = txt.indexOf(".", 0); 266 if (decimalPointIndex >= 0) { 267 LargeInteger integer = LargeInteger.valueOf(txt.subtext(0, 268 decimalPointIndex)); 269 LargeInteger fraction = LargeInteger.valueOf(txt.subtext( 270 decimalPointIndex + 1, txt.length())); 271 int fractionDigits = chars.length() - decimalPointIndex - 1; 272 real._mantissa = integer.isNegative() ? 273 integer.times10pow(fractionDigits).minus(fraction) : 274 integer.times10pow(fractionDigits).plus(fraction); 275 real._error = LargeInteger.ZERO; 276 real._exponent = -fractionDigits; 277 return real; 278 } else { 279 real._mantissa = LargeInteger.valueOf(chars); 280 real._error = LargeInteger.ZERO; 281 real._exponent = 0; 282 return real; 283 } 284 } 285 286 291 public LargeInteger getMantissa() { 292 return _mantissa; 293 } 294 295 300 public LargeInteger getError() { 301 return _error; 302 } 303 304 309 public int getExponent() { 310 return _exponent; 311 } 312 313 319 public boolean isExact() { 320 return _error.isZero(); 321 } 322 323 329 public int getAccuracy() { 330 if (_error.isZero()) return Integer.MAX_VALUE; 331 if (this == NaN) return Integer.MIN_VALUE; 332 return -_exponent - _error.digitLength(); 333 } 334 335 341 public final int getPrecision() { 342 if (_error.isZero()) return Integer.MAX_VALUE; 343 if (this == NaN) return Integer.MIN_VALUE; 344 return _mantissa.digitLength() - _error.digitLength(); 345 } 346 347 352 public boolean isPositive() { 353 return _mantissa.isPositive(); 354 } 355 356 361 public boolean isNegative() { 362 return _mantissa.isNegative(); 363 } 364 365 371 public boolean isNaN() { 372 return this == NaN; 373 } 374 375 387 public boolean approximates(Real that) { 388 Real diff = this.minus(that); 389 if (diff == NaN) return false; 390 return diff._error.isLargerThan(diff._mantissa); 391 } 392 393 400 public LargeInteger toLargeInteger() { 401 if (this == NaN) 402 throw new ArithmeticException ("Cannot convert NaN to integer value"); 403 return _mantissa.times10pow(_exponent); 404 } 405 406 411 public Real opposite() { 412 if (this == NaN) return NaN; 413 Real real = FACTORY.object(); 414 real._mantissa = _mantissa.opposite(); 415 real._exponent = _exponent; 416 real._error = _error; 417 return real; 418 } 419 420 426 public Real plus(Real that) { 427 if ((this == NaN) || (that == NaN)) return NaN; 428 if (this._exponent > that._exponent) 429 return that.plus(this); int scale = that._exponent - this._exponent; Real real = (Real) FACTORY.object(); 432 real._exponent = _exponent; 433 real._mantissa = this._mantissa.plus(that._mantissa.times10pow(scale)); 434 real._error = this._error.plus(that._error.times10pow(scale)); 435 return real; 436 } 437 438 445 public Real minus(Real that) { 446 return this.plus(that.opposite()); 447 } 448 449 456 public Real times(long multiplier) { 457 if (this == NaN) return NaN; 458 Real real = FACTORY.object(); 459 real._exponent = this._exponent; 460 real._mantissa = this._mantissa.times(multiplier); 461 real._error = this._error.times(multiplier); 462 return real; 463 } 464 465 471 public Real times(Real that) { 472 if ((this == NaN) || (that == NaN)) return NaN; 473 long exp = ((long) this._exponent) + that._exponent; 474 if (exp > Integer.MAX_VALUE || (exp < Integer.MIN_VALUE)) 475 return NaN; LargeInteger thisMin = this._mantissa.minus(this._error); 477 LargeInteger thisMax = this._mantissa.plus(this._error); 478 LargeInteger thatMin = that._mantissa.minus(that._error); 479 LargeInteger thatMax = that._mantissa.plus(that._error); 480 LargeInteger min, max; 481 if (thisMin.compareTo(thisMax.opposite()) > 0) { 482 if (thatMin.compareTo(thatMax.opposite()) > 0) { 483 min = thisMin.times(thatMin); 484 max = thisMax.times(thatMax); 485 } else { 486 min = thisMax.times(thatMin); 487 max = thisMin.times(thatMax); 488 } 489 } else { 490 if (thatMin.compareTo(thatMax.opposite()) > 0) { 491 min = thisMin.times(thatMax); 492 max = thisMax.times(thatMin); 493 } else { 494 min = thisMax.times(thatMax); 495 max = thisMin.times(thatMin); 496 } 497 } 498 Real real = FACTORY.object(); 499 real._exponent = (int) exp; 500 real._mantissa = min.plus(max).shiftRight(1); 501 real._error = max.minus(min); 502 return real; 503 } 504 505 512 public Real divide(long divisor) { 513 return this.divide(Real.valueOf(divisor)); 514 } 515 516 523 public Real divide(Real that) { 524 return this.times(that.inverse()); 525 } 526 527 532 public Real inverse() { 533 if ((this == NaN) || (this == ZERO)) 534 return NaN; 535 if (this.isExact()) return this.toInexact().inverse(); 536 LargeInteger thisMin = this._mantissa.minus(this._error); 537 LargeInteger thisMax = this._mantissa.plus(this._error); 538 if (thisMin.isNegative() && thisMax.isPositive()) return NaN; 540 int digits = MathLib.max(thisMin.digitLength(), thisMax.digitLength()); 541 long exp = ((long) -this._exponent) - digits - digits; 542 if ((exp > Integer.MAX_VALUE || (exp < Integer.MIN_VALUE))) 543 return NaN; LargeInteger min = div(2 * digits, thisMax); 545 LargeInteger max = div(2 * digits, thisMin); 546 Real real = (Real) FACTORY.object(); 547 real._exponent = (int) exp; 548 real._mantissa = min.plus(max).shiftRight(1); 549 real._error = max.minus(min).plus(LargeInteger.ONE); 550 return real; 551 } 552 private static LargeInteger div(int exp, LargeInteger mantissa) { 553 int expBitLength = (int) (exp * DIGITS_TO_BITS); 554 int precision = expBitLength - mantissa.bitLength() + 1; 555 LargeInteger reciprocal = mantissa.inverseScaled(precision); 556 LargeInteger result = reciprocal.times10pow(exp); 557 return result.shiftRight(expBitLength + 1); 558 } 559 private static final double DIGITS_TO_BITS = MathLib.LOG10 / MathLib.LOG2; 560 561 private Real toInexact() { 562 int precision = Real.getExactMinimumPrecision(); 563 Real z = FACTORY.object(); 564 z._mantissa = _mantissa.times10pow(precision); 565 z._error = LargeInteger.ONE; 566 z._exponent = _exponent - precision; 567 return z; 568 } 569 570 575 public Real abs() { 576 return _mantissa.isNegative() ? this.opposite() : this; 577 } 578 579 585 public boolean isLargerThan(Real that) { 586 return this.abs().compareTo(that.abs()) > 0; 587 } 588 589 595 public Real sqrt() { 596 if (this == NaN) return NaN; 597 if (this.isExact()) return this.toInexact().sqrt(); 598 LargeInteger thisMin = this._mantissa.minus(this._error); 599 LargeInteger thisMax = this._mantissa.plus(this._error); 600 if (thisMin.isNegative()) return NaN; 601 int exponent = _exponent >> 1; 602 if ((_exponent & 1) == 1) { thisMin = thisMin.times10pow(1); 604 thisMax = thisMax.times10pow(1); 605 } 606 LargeInteger minSqrt = thisMin.sqrt(); 607 LargeInteger maxSqrt = thisMax.sqrt().plus(LargeInteger.ONE); 608 LargeInteger sqrt = minSqrt.plus(maxSqrt).shiftRight(1); 609 Real z = FACTORY.object(); 610 z._mantissa = sqrt; 611 z._error = maxSqrt.minus(sqrt); 612 z._exponent = exponent; 613 return z; 614 } 615 616 621 public Text toText() { 622 if (this == NaN) return Text.valueOf("NaN"); 623 if (this == ZERO) return Text.valueOf("0"); 624 int errorDigits = _error.digitLength(); 625 LargeInteger m = (_mantissa.isPositive()) ? _mantissa.plus(FIVE 626 .times10pow(errorDigits - 1)) : _mantissa.plus(MINUS_FIVE 627 .times10pow(errorDigits - 1)); 628 m = m.times10pow(-errorDigits); 629 int exp = _exponent + errorDigits; 630 Text txt = m.toText(); 631 int digits = (m.isNegative()) ? txt.length() - 1 : txt.length(); 632 if (digits > 1) { 633 if ((exp < 0) && (-exp < digits)) { 634 txt = txt.insert(txt.length() + exp, Text.valueOf('.')); 635 } else { txt = txt.insert(txt.length() - digits + 1, Text.valueOf('.')); 637 txt = txt.concat(Text.valueOf('E')).concat(Text.valueOf(exp + digits - 1)); 638 } 639 } else { 640 txt = txt.concat(Text.valueOf('E')).concat(Text.valueOf(exp)); 641 } 642 return txt; 643 } 644 private static final LargeInteger FIVE = LargeInteger.valueOf(5).moveHeap(); 645 private static final LargeInteger MINUS_FIVE = LargeInteger.valueOf(-5).moveHeap(); 646 647 659 public boolean equals(Object that) { 660 if (this == that) return true; 661 if (!(that instanceof Real)) 662 return false; 663 Real thatReal = (Real) that; 664 return this._mantissa.equals(thatReal._mantissa) && this._error.equals(thatReal._error) 665 && (this._exponent == thatReal._exponent); 666 } 667 668 673 public int hashCode() { 674 return _mantissa.hashCode() + _error.hashCode() + _exponent * 31; 675 } 676 677 683 public long longValue() { 684 return (long) doubleValue(); 685 } 686 687 693 public double doubleValue() { 694 if (this == NaN) return Double.NaN; 695 if (this == ZERO) return 0.0; 696 int nbrDigits = _mantissa.digitLength(); 698 int digitShift = nbrDigits - 18; 699 long reducedMantissa = _mantissa.times10pow(-digitShift).longValue(); 700 int exponent = _exponent + digitShift; 701 return MathLib.toDoublePow10(reducedMantissa, exponent); 702 } 703 704 712 public int compareTo(Real that) { 713 Real diff = this.minus(that); 714 if (diff.isPositive()) { 715 return 1; 716 } else if (diff.isNegative()) { 717 return -1; 718 } else { 719 return 0; 720 } 721 } 722 723 public boolean move(ObjectSpace os) { 725 if (super.move(os)) { 726 _mantissa.move(os); 727 _error.move(os); 728 return true; 729 } 730 return false; 731 } 732 733 736 private static final Factory<Real> FACTORY = new Factory<Real>() { 737 738 public Real create() { 739 return new Real(); 740 } 741 }; 742 743 private static final long serialVersionUID = 1L; 744 745 } | Popular Tags |