001: /*
002: * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003: * Copyright (C) 2007 - 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: */
009: package org.jscience.mathematics.number;
010:
011: import org.jscience.mathematics.structure.Field;
012:
013: import javolution.context.LocalContext;
014: import javolution.context.ObjectFactory;
015: import javolution.lang.MathLib;
016: import javolution.text.Text;
017: import javolution.text.TextBuilder;
018: import javolution.xml.XMLFormat;
019: import javolution.xml.stream.XMLStreamException;
020:
021: /**
022: * <p> This class represents a floating point number of arbitrary precision.
023: * A floating point number consists of a {@link #getSignificand significand}
024: * and a decimal {@link #getExponent exponent}:
025: * (<code>significand · 10<sup>exponent</sup></code>).</p>
026: *
027: * <p> Unlike {@link Real} numbers, no calculation error is performed on
028: * floating point instances but the number of digits used during
029: * calculations can be specified (see {@link #setDigits(int)}). The
030: * largest the number of digits, the smallest the numeric error.
031: * For example:[code]
032: * FloatingPoint two = FloatingPoint.valueOf(2);
033: * FloatingPoint.setDigits(30); // 30 digits calculations.
034: * System.out.println(two.sqrt());
035: * > 0.141421356237309504880168872420E1
036: * [/code]</p>
037: *
038: * <p> Instances of this class are immutable and can be used to find
039: * accurate solutions to linear equations with the {@link
040: * org.jscience.mathematics.vector.Matrix Matrix} class.</p>
041: *
042: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
043: * @version 4.1, June 8, 2007
044: * @see <a href="http://en.wikipedia.org/wiki/Floating_point">
045: * Wikipedia: Floating point</a>
046: */
047: public final class FloatingPoint extends Number<FloatingPoint>
048: implements Field<FloatingPoint> {
049:
050: /**
051: * Holds the default XML representation for floating point numbers.
052: * This representation consists of a simple <code>value</code> attribute
053: * holding the {@link #toText() textual} representation.
054: */
055: static final XMLFormat<FloatingPoint> XML = new XMLFormat<FloatingPoint>(
056: FloatingPoint.class) {
057:
058: @Override
059: public FloatingPoint newInstance(Class<FloatingPoint> cls,
060: InputElement xml) throws XMLStreamException {
061: return FloatingPoint.valueOf(xml.getAttribute("value"));
062: }
063:
064: public void write(FloatingPoint FloatingPoint, OutputElement xml)
065: throws XMLStreamException {
066: xml.setAttribute("value", FloatingPoint.toText());
067: }
068:
069: public void read(InputElement xml, FloatingPoint FloatingPoint) {
070: // Nothing to do, immutable.
071: }
072: };
073:
074: /**
075: * Holds the factory constructing floating point instances.
076: */
077: private static final ObjectFactory<FloatingPoint> FACTORY = new ObjectFactory<FloatingPoint>() {
078:
079: protected FloatingPoint create() {
080: return new FloatingPoint();
081: }
082: };
083:
084: /**
085: * The floating point instance representing the additive identity.
086: */
087: public static final FloatingPoint ZERO = new FloatingPoint(
088: LargeInteger.ZERO, 0);
089:
090: /**
091: * The floating point instance representing the multiplicative identity.
092: */
093: public static final FloatingPoint ONE = new FloatingPoint(
094: LargeInteger.ONE, 0);
095:
096: /**
097: * The Not-a-Number instance (unique).
098: */
099: public static final FloatingPoint NaN = new FloatingPoint(
100: LargeInteger.ZERO, Integer.MAX_VALUE);
101:
102: /**
103: * Holds the number of digits to be used (default 20 digits).
104: */
105: private static final LocalContext.Reference<Integer> DIGITS = new LocalContext.Reference<Integer>(
106: 20);
107:
108: /**
109: * Holds the significand value.
110: */
111: private LargeInteger _significand;
112:
113: /**
114: * Holds the power of 10 exponent.
115: */
116: private int _exponent;
117:
118: /**
119: * Default constructor.
120: */
121: private FloatingPoint() {
122: }
123:
124: /**
125: * Creates a floating point number for the specified significand and
126: * exponent.
127: *
128: * @param significand the significand.
129: * @param exponent the power of two exponent.
130: */
131: private FloatingPoint(LargeInteger significand, int exponent) {
132: _significand = significand;
133: _exponent = exponent;
134: }
135:
136: /**
137: * Returns the floating point number for the specified {@link
138: * LargeInteger} significand and power of two exponent.
139: *
140: * @param significand the significand value.
141: * @param exponent the power of two exponent.
142: * @return <code>(significand · 2<sup>exponent</sup></code>
143: */
144: public static FloatingPoint valueOf(LargeInteger significand,
145: int exponent) {
146: FloatingPoint fp = FACTORY.object();
147: fp._significand = significand;
148: fp._exponent = exponent;
149: return fp;
150: }
151:
152: /**
153: * Returns the floating point number for the specified <code>long</code>
154: * significand and power of two exponent (convenience method).
155: *
156: * @param significand the significand value.
157: * @param exponent the power of two exponent.
158: * @return <code>(significand · 2<sup>exponent</sup></code>
159: */
160: public static FloatingPoint valueOf(long significand, int exponent) {
161: FloatingPoint fp = FACTORY.object();
162: fp._significand = LargeInteger.valueOf(significand);
163: fp._exponent = exponent;
164: return fp;
165: }
166:
167: /**
168: * Returns the floating point number for the specified <code>long</code>
169: * value (convenience method).
170: *
171: * @param longValue the <code>long</code> value.
172: * @return <code>FloatingPoint.valueOf(longValue, 0)</code>
173: */
174: public static FloatingPoint valueOf(long longValue) {
175: return FloatingPoint.valueOf(longValue, 0);
176: }
177:
178: /**
179: * Returns the floating point number for the specified <code>double</code>
180: * value (convenience method).
181: *
182: * @param doubleValue the <code>double</code> value.
183: * @return <code>FloatingPoint.valueOf(longValue, 0)</code>
184: */
185: public static FloatingPoint valueOf(double doubleValue) {
186: if (doubleValue == 0.0)
187: return FloatingPoint.ZERO;
188: if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue))
189: return FloatingPoint.NaN;
190:
191: // Find the exponent e such as: value == x.xxx * 10^e
192: int e = MathLib.floorLog10(doubleValue) - 18 + 1; // 18 digits significand.
193: long significand = MathLib.toLongPow10(doubleValue, -e);
194: return FloatingPoint.valueOf(significand, e);
195: }
196:
197: /**
198: * Returns the floating point number for the specified character sequence.
199: * The number of digits
200: *
201: * @param chars the character sequence.
202: * @return the corresponding FloatingPoint number.
203: */
204: public static FloatingPoint valueOf(CharSequence chars) {
205: // Use same format as Real.
206: Real real = Real.valueOf(chars);
207: if (real.getError() != 0)
208: throw new IllegalArgumentException("No error allowed");
209: return FloatingPoint.valueOf(real.getSignificand(), real
210: .getExponent());
211: }
212:
213: /**
214: * Returns the {@link javolution.context.LocalContext local} number of
215: * digits used during calculations (default 20 digits).
216: *
217: * @return the number of digits.
218: */
219: public static int getDigits() {
220: return DIGITS.get();
221: }
222:
223: /**
224: * Sets the {@link javolution.context.LocalContext local} number of digits
225: * to be used during calculations.
226: *
227: * @param digits the number of digits.
228: * @throws IllegalArgumentException if <code>digits <= 0</code>
229: */
230: public static void setDigits(int digits) {
231: if (digits <= 0)
232: throw new IllegalArgumentException("digits: " + digits
233: + " has to be greater than 0");
234: DIGITS.set(digits);
235: }
236:
237: /**
238: * Returns the significand value.
239: *
240: * @return this floating point significand.
241: */
242: public LargeInteger getSignificand() {
243: return _significand;
244: }
245:
246: /**
247: * Returns the decimal exponent.
248: *
249: * @return this floating point decimal exponent.
250: */
251: public int getExponent() {
252: return _exponent;
253: }
254:
255: /**
256: * Returns the closest integer to this floating point number.
257: *
258: * @return this floating point rounded to the nearest integer.
259: */
260: public LargeInteger round() {
261: if (this == NaN)
262: throw new ArithmeticException(
263: "Cannot convert NaN to integer value");
264: LargeInteger half = LargeInteger.FIVE.times10pow(_exponent - 1);
265: return isNegative() ? _significand.minus(half).times10pow(
266: _exponent) : _significand.plus(half).times10pow(
267: _exponent);
268: }
269:
270: /**
271: * Returns the opposite of this floating point number.
272: *
273: * @return <code>-this</code>.
274: */
275: public FloatingPoint opposite() {
276: return FloatingPoint
277: .valueOf(_significand.opposite(), _exponent);
278: }
279:
280: /**
281: * Returns the sum of this floating point number with the one specified.
282: *
283: * @param that the floating point number to be added.
284: * @return <code>this + that</code>.
285: */
286: public FloatingPoint plus(FloatingPoint that) {
287: if (this ._exponent > that._exponent)
288: return that.plus(this );
289: int pow10Scaling = that._exponent - this ._exponent;
290: LargeInteger thatScaled = that._significand
291: .times10pow(pow10Scaling);
292: return FloatingPoint.valueOf(_significand.plus(thatScaled),
293: _exponent).normalize();
294: }
295:
296: /**
297: * Returns the difference between this FloatingPoint number and the one
298: * specified.
299: *
300: * @param that the floating point number to be subtracted.
301: * @return <code>this - that</code>.
302: */
303: public FloatingPoint minus(FloatingPoint that) {
304: if (this ._exponent > that._exponent)
305: return that.plus(this );
306: int pow10Scaling = that._exponent - this ._exponent;
307: LargeInteger thatScaled = that._significand
308: .times10pow(pow10Scaling);
309: return FloatingPoint.valueOf(_significand.minus(thatScaled),
310: _exponent).normalize();
311: }
312:
313: /**
314: * Returns the product of this floating point number with the specified
315: * <code>long</code> multiplier.
316: *
317: * @param multiplier the <code>long</code> multiplier.
318: * @return <code>this · multiplier</code>.
319: */
320: public FloatingPoint times(long multiplier) {
321: return this .times(FloatingPoint.valueOf(multiplier));
322: }
323:
324: /**
325: * Returns the product of this floating point number with the one specified.
326: *
327: * @param that the floating point number multiplier.
328: * @return <code>this · that</code>.
329: */
330: public FloatingPoint times(FloatingPoint that) {
331: return FloatingPoint.valueOf(
332: this ._significand.times(that._significand),
333: this ._exponent + that._exponent).normalize();
334: }
335:
336: /**
337: * Returns the inverse of this floating point number.
338: *
339: * @return <code>1 / this</code>.
340: * @throws ArithmeticException if <code>dividend.isZero()</code>
341: */
342: public FloatingPoint inverse() {
343: if (_significand.isZero())
344: return NaN;
345: int pow10 = DIGITS.get() + _significand.digitLength();
346: LargeInteger dividend = LargeInteger.ONE.times10pow(pow10);
347: return FloatingPoint.valueOf(dividend.divide(_significand),
348: -pow10 - _exponent).normalize();
349: }
350:
351: /**
352: * Returns this floating point number divided by the one specified.
353: *
354: * @param that the FloatingPoint number divisor.
355: * @return <code>this / that</code>.
356: * @throws ArithmeticException if <code>that.equals(ZERO)</code>
357: */
358: public FloatingPoint divide(FloatingPoint that) {
359: if (that._significand.isZero())
360: return NaN;
361: int pow10 = DIGITS.get() + that._significand.digitLength();
362: LargeInteger dividend = _significand.times10pow(pow10);
363: return FloatingPoint.valueOf(
364: dividend.divide(that._significand),
365: this ._exponent - pow10 - that._exponent).normalize();
366: }
367:
368: /**
369: * Returns the absolute value of this floating point number.
370: *
371: * @return <code>|this|</code>.
372: */
373: public FloatingPoint abs() {
374: return FloatingPoint.valueOf(_significand.abs(), _exponent);
375: }
376:
377: /**
378: * Returns the square root of this floating point number.
379: *
380: * @return the positive square root of this floating point number.
381: */
382: public FloatingPoint sqrt() {
383: if (this == NaN)
384: return NaN;
385: int pow10 = DIGITS.get() * 2 - _significand.digitLength();
386: int exp = _exponent - pow10;
387: if ((exp & 1) == 1) { // Ensures that exp is even.
388: pow10++;
389: exp--;
390: }
391: LargeInteger scaledValue = _significand.times10pow(pow10);
392: return FloatingPoint.valueOf(scaledValue.sqrt(), exp >> 1)
393: .normalize();
394: }
395:
396: /**
397: * Indicates if this floating point number is equal to zero.
398: *
399: * @return <code>this == 0</code>
400: */
401: public boolean isZero() {
402: return _significand.isZero() && (this != NaN);
403: }
404:
405: /**
406: * Indicates if this floating point number is greater than zero.
407: *
408: * @return <code>this > 0</code>
409: */
410: public boolean isPositive() {
411: return _significand.isPositive();
412: }
413:
414: /**
415: * Indicates if this rational number is less than zero.
416: *
417: * @return <code>this < 0</code>
418: */
419: public boolean isNegative() {
420: return _significand.isNegative();
421: }
422:
423: /**
424: * Indicates if this floating point is Not-a-Number.
425: *
426: * @return <code>true</code> if this number has unbounded value;
427: * <code>false</code> otherwise.
428: */
429: public boolean isNaN() {
430: return this == NaN;
431: }
432:
433: /**
434: * Compares the absolute value of two FloatingPoint numbers.
435: *
436: * @param that the FloatingPoint number to be compared with.
437: * @return <code>|this| > |that|</code>
438: */
439: public boolean isLargerThan(FloatingPoint that) {
440: return this .abs().compareTo(that.abs()) > 0;
441: }
442:
443: /**
444: * Returns the decimal text representation of this number.
445: *
446: * @return the text representation of this number.
447: */
448: public Text toText() {
449: if (this == NaN)
450: return Text.valueOf("NaN");
451: if (this ._significand.isZero())
452: return Text.valueOf("0.0");
453: TextBuilder tb = TextBuilder.newInstance();
454: LargeInteger m = _significand;
455: if (isNegative()) {
456: tb.append('-');
457: m = m.opposite();
458: }
459: tb.append("0.");
460: LargeInteger.DECIMAL_FORMAT.format(m, tb);
461: int exp = _exponent + m.digitLength();
462: if (exp != 0) {
463: tb.append("E");
464: tb.append(_exponent + m.digitLength());
465: }
466: Text txt = tb.toText();
467: TextBuilder.recycle(tb);
468: return txt;
469: }
470:
471: /**
472: * Compares this floating point number against the specified object.
473: *
474: * @param that the object to compare with.
475: * @return <code>true</code> if the objects are the same;
476: * <code>false</code> otherwise.
477: */
478: public boolean equals(Object that) {
479: if (that instanceof FloatingPoint) {
480: return this .minus((FloatingPoint) that).isZero();
481: } else {
482: return false;
483: }
484: }
485:
486: /**
487: * Returns the hash code for this floating point number.
488: *
489: * @return the hash code value.
490: */
491: public int hashCode() {
492: return _significand.hashCode() - _exponent;
493: }
494:
495: /**
496: * Returns the value of this floating point number as a <code>long</code>.
497: *
498: * @return the numeric value represented by this floating point
499: * after conversion to type <code>long</code>.
500: */
501: public long longValue() {
502: Real real = Real.valueOf(_significand, 0, _exponent);
503: return real.longValue();
504: }
505:
506: /**
507: * Returns the value of this floating point number as a <code>double</code>.
508: *
509: * @return the numeric value represented by this FloatingPoint after conversion
510: * to type <code>double</code>.
511: */
512: public double doubleValue() {
513: Real real = Real.valueOf(_significand, 0, _exponent);
514: return real.doubleValue();
515: }
516:
517: /**
518: * Compares two floating point number numerically.
519: *
520: * @param that the floating point number to compare with.
521: * @return -1, 0 or 1 as this FloatingPoint number is numerically less than,
522: * equal to, or greater than <code>that</code>.
523: */
524: public int compareTo(FloatingPoint that) {
525: FloatingPoint diff = this .minus(that);
526: if (diff.isPositive()) {
527: return 1;
528: } else if (diff.isNegative()) {
529: return -1;
530: } else {
531: return 0;
532: }
533: }
534:
535: /**
536: * Returns this floating point number after normalization based upon
537: * the number of digits.
538: *
539: * @return <code>this</code>
540: */
541: private FloatingPoint normalize() {
542: int digits = FloatingPoint.getDigits();
543: int this Digits = this ._significand.digitLength();
544: if (this Digits > digits) { // Scale down.
545: int pow10 = digits - this Digits; // Negative.
546: _significand = _significand.times10pow(pow10);
547: long exponent = ((long) _exponent) - pow10;
548: if (exponent > Integer.MAX_VALUE)
549: return NaN;
550: if (exponent < Integer.MIN_VALUE)
551: return ZERO;
552: _exponent = (int) exponent;
553: }
554: return this ;
555: }
556:
557: @Override
558: public FloatingPoint copy() {
559: if (this == NaN)
560: return NaN; // Maintains unicity.
561: FloatingPoint r = FACTORY.object();
562: r._significand = _significand.copy();
563: r._exponent = _exponent;
564: return r;
565: }
566:
567: private static final long serialVersionUID = 1L;
568: }
|