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 */
009package org.jscience.mathematics.number;
010
011import org.jscience.mathematics.structure.Field;
012
013import javolution.context.LocalContext;
014import javolution.context.ObjectFactory;
015import javolution.lang.MathLib;
016import javolution.text.Text;
017import javolution.text.TextBuilder;
018import javolution.xml.XMLFormat;
019import 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 */
047public final class FloatingPoint extends Number<FloatingPoint> implements
048        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(LargeInteger.ONE,
094            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, int exponent) {
145        FloatingPoint fp = FACTORY.object();
146        fp._significand = significand;
147        fp._exponent = exponent;
148        return fp;
149    }
150
151    /**
152     * Returns the floating point number for the specified <code>long</code>
153     * significand and power of two exponent (convenience method). 
154     * 
155     * @param significand the significand value.
156     * @param exponent the power of two exponent.
157     * @return <code>(significand · 2<sup>exponent</sup></code>
158     */
159    public static FloatingPoint valueOf(long significand, int exponent) {
160        FloatingPoint fp = FACTORY.object();
161        fp._significand = LargeInteger.valueOf(significand);
162        fp._exponent = exponent;
163        return fp;
164    }
165
166    /**
167     * Returns the floating point number for the specified <code>long</code>
168     * value (convenience method). 
169     * 
170     * @param longValue the <code>long</code> value.
171     * @return <code>FloatingPoint.valueOf(longValue, 0)</code>
172     */
173    public static FloatingPoint valueOf(long longValue) {
174        return FloatingPoint.valueOf(longValue, 0);
175    }
176
177    /**
178     * Returns the floating point number for the specified <code>double</code>
179     * value (convenience method). 
180     * 
181     * @param doubleValue the <code>double</code> value.
182     * @return <code>FloatingPoint.valueOf(longValue, 0)</code>
183     */
184    public static FloatingPoint valueOf(double doubleValue) {
185        if (doubleValue == 0.0)
186            return FloatingPoint.ZERO;
187        if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue))
188            return FloatingPoint.NaN;
189
190        // Find the exponent e such as: value == x.xxx * 10^e
191        int e = MathLib.floorLog10(doubleValue) - 18 + 1; // 18 digits significand.
192        long significand = MathLib.toLongPow10(doubleValue, -e);
193        return FloatingPoint.valueOf(significand, e);
194    }
195
196    /**
197     * Returns the floating point number for the specified character sequence.
198     * The number of digits
199     * 
200     * @param  chars the character sequence.
201     * @return the corresponding FloatingPoint number.
202     */
203    public static FloatingPoint valueOf(CharSequence chars) {
204        // Use same format as Real.
205        Real real = Real.valueOf(chars);
206        if (real.getError() != 0)
207            throw new IllegalArgumentException("No error allowed");
208        return FloatingPoint.valueOf(real.getSignificand(), real.getExponent());
209    }
210
211    /**
212     * Returns the {@link javolution.context.LocalContext local} number of 
213     * digits used during calculations (default 20 digits). 
214     * 
215     * @return the number of digits.
216     */
217    public static int getDigits() {
218        return DIGITS.get();
219    }
220
221    /**
222     * Sets the {@link javolution.context.LocalContext local} number of digits
223     * to be used during calculations.
224     * 
225     * @param digits the number of digits.
226     * @throws IllegalArgumentException if <code>digits &lt;= 0</code>
227     */
228    public static void setDigits(int digits) {
229        if (digits <= 0)
230            throw new IllegalArgumentException("digits: " + digits
231                    + " has to be greater than 0");
232        DIGITS.set(digits);
233    }
234
235    /**
236     * Returns the significand value.
237     * 
238     * @return this floating point significand.
239     */
240    public LargeInteger getSignificand() {
241        return _significand;
242    }
243
244    /**
245     * Returns the decimal exponent.
246     * 
247     * @return this floating point decimal exponent.
248     */
249    public int getExponent() {
250        return _exponent;
251    }
252
253    /**
254     * Returns the closest integer to this floating point number.
255     * 
256     * @return this floating point rounded to the nearest integer.
257     */
258    public LargeInteger round() {
259        if (this == NaN)
260            throw new ArithmeticException("Cannot convert NaN to integer value");
261        LargeInteger half = LargeInteger.FIVE.times10pow(_exponent - 1);
262        return isNegative() ? _significand.minus(half).times10pow(_exponent)
263                : _significand.plus(half).times10pow(_exponent);
264    }
265
266    /**
267     * Returns the opposite of this floating point number.
268     * 
269     * @return <code>-this</code>.
270     */
271    public FloatingPoint opposite() {
272        return FloatingPoint.valueOf(_significand.opposite(), _exponent);
273    }
274
275    /**
276     * Returns the sum of this floating point number with the one specified.
277     * 
278     * @param that the floating point number to be added.
279     * @return <code>this + that</code>.
280     */
281    public FloatingPoint plus(FloatingPoint that) {
282        if (this._exponent > that._exponent)
283            return that.plus(this);
284        int pow10Scaling = that._exponent - this._exponent;
285        LargeInteger thatScaled = that._significand.times10pow(pow10Scaling);
286        return FloatingPoint.valueOf(_significand.plus(thatScaled), _exponent)
287                .normalize();
288    }
289
290    /**
291     * Returns the difference between this FloatingPoint number and the one
292     * specified.
293     * 
294     * @param that the floating point number to be subtracted.
295     * @return <code>this - that</code>.
296     */
297    public FloatingPoint minus(FloatingPoint that) {
298        if (this._exponent > that._exponent)
299            return that.plus(this);
300        int pow10Scaling = that._exponent - this._exponent;
301        LargeInteger thatScaled = that._significand.times10pow(pow10Scaling);
302        return FloatingPoint.valueOf(_significand.minus(thatScaled), _exponent)
303                .normalize();
304    }
305
306    /**
307     * Returns the product of this floating point number with the specified 
308     * <code>long</code> multiplier.
309     * 
310     * @param multiplier the <code>long</code> multiplier.
311     * @return <code>this · multiplier</code>.
312     */
313    public FloatingPoint times(long multiplier) {
314        return this.times(FloatingPoint.valueOf(multiplier));
315    }
316
317    /**
318     * Returns the product of this floating point number with the one specified.
319     * 
320     * @param that the floating point number multiplier.
321     * @return <code>this · that</code>.
322     */
323    public FloatingPoint times(FloatingPoint that) {
324        return FloatingPoint.valueOf(
325                this._significand.times(that._significand),
326                this._exponent + that._exponent).normalize();
327    }
328
329    /**
330     * Returns the inverse of this floating point number.
331     * 
332     * @return <code>1 / this</code>.
333     * @throws ArithmeticException if <code>dividend.isZero()</code>
334     */
335    public FloatingPoint inverse() {
336        if (_significand.isZero())
337            return NaN;
338        int pow10 = DIGITS.get() + _significand.digitLength();
339        LargeInteger dividend = LargeInteger.ONE.times10pow(pow10);
340        return FloatingPoint.valueOf(dividend.divide(_significand),
341                -pow10 - _exponent).normalize();
342    }
343
344    /**
345     * Returns this floating point number divided by the one specified.
346     * 
347     * @param that the FloatingPoint number divisor.
348     * @return <code>this / that</code>.
349     * @throws ArithmeticException if <code>that.equals(ZERO)</code>
350     */
351    public FloatingPoint divide(FloatingPoint that) {
352        if (that._significand.isZero())
353            return NaN;
354        int pow10 = DIGITS.get() + that._significand.digitLength();
355        LargeInteger dividend = _significand.times10pow(pow10);
356        return FloatingPoint.valueOf(dividend.divide(that._significand),
357                this._exponent - pow10 - that._exponent).normalize();
358    }
359
360    /**
361     * Returns the absolute value of this floating point  number.
362     * 
363     * @return <code>|this|</code>.
364     */
365    public FloatingPoint abs() {
366        return FloatingPoint.valueOf(_significand.abs(), _exponent);
367    }
368
369    /**
370     * Returns the square root of this floating point number.
371     * 
372     * @return the positive square root of this floating point number.
373     */
374    public FloatingPoint sqrt() {
375        if (this == NaN)
376            return NaN;
377        int pow10 = DIGITS.get() * 2 - _significand.digitLength();
378        int exp = _exponent - pow10;
379        if ((exp & 1) == 1) { // Ensures that exp is even.
380            pow10++;
381            exp--;
382        }
383        LargeInteger scaledValue = _significand.times10pow(pow10);
384        return FloatingPoint.valueOf(scaledValue.sqrt(), exp >> 1)
385                .normalize();
386    }
387
388    /**
389     * Indicates if this floating point number is equal to zero.
390     * 
391     * @return <code>this == 0</code>
392     */
393    public boolean isZero() {
394        return _significand.isZero() && (this != NaN);
395    }
396
397    /**
398     * Indicates if this floating point number is greater than zero.
399     * 
400     * @return <code>this > 0</code>
401     */
402    public boolean isPositive() {
403        return _significand.isPositive();
404    }
405
406    /**
407     * Indicates if this rational number is less than zero.
408     * 
409     * @return <code>this < 0</code>
410     */
411    public boolean isNegative() {
412        return _significand.isNegative();
413    }
414
415    /**
416     * Indicates if this floating point is Not-a-Number.
417     * 
418     * @return <code>true</code> if this number has unbounded value;
419     *         <code>false</code> otherwise.
420     */
421    public boolean isNaN() {
422        return this == NaN;
423    }
424
425    /**
426     * Compares the absolute value of two FloatingPoint numbers.
427     *
428     * @param that the FloatingPoint number to be compared with.
429     * @return <code>|this| > |that|</code>
430     */
431    public boolean isLargerThan(FloatingPoint that) {
432        return this.abs().compareTo(that.abs()) > 0;
433    }
434
435    /**
436     * Returns the decimal text representation of this number.
437     *
438     * @return the text representation of this number.
439     */
440    public Text toText() {
441        if (this == NaN)
442            return Text.valueOf("NaN");
443        if (this._significand.isZero())
444            return Text.valueOf("0.0");
445        TextBuilder tb = TextBuilder.newInstance();
446        LargeInteger m = _significand;
447        if (isNegative()) {
448            tb.append('-');
449            m = m.opposite();
450        }
451        tb.append("0.");
452        LargeInteger.DECIMAL_FORMAT.format(m, tb);
453        int exp = _exponent + m.digitLength();
454        if (exp != 0) {
455            tb.append("E");
456            tb.append(_exponent + m.digitLength());
457        }
458        Text txt = tb.toText();
459        TextBuilder.recycle(tb);
460        return txt;
461    }
462
463    /**
464     * Compares this floating point number against the specified object.
465     * 
466     * @param that the object to compare with.
467     * @return <code>true</code> if the objects are the same;
468     *         <code>false</code> otherwise.
469     */
470    public boolean equals(Object that) {
471        if (that instanceof FloatingPoint) {
472            return this.minus((FloatingPoint) that).isZero();
473        } else {
474            return false;
475        }
476    }
477
478    /**
479     * Returns the hash code for this floating point number.
480     * 
481     * @return the hash code value.
482     */
483    public int hashCode() {
484        return _significand.hashCode() - _exponent;
485    }
486
487    /**
488     * Returns the value of this floating point number as a <code>long</code>.
489     * 
490     * @return the numeric value represented by this floating point 
491     *         after conversion to type <code>long</code>.
492     */
493    public long longValue() {
494        Real real = Real.valueOf(_significand, 0, _exponent);
495        return real.longValue();
496    }
497
498    /**
499     * Returns the value of this floating point number as a <code>double</code>.
500     * 
501     * @return the numeric value represented by this FloatingPoint after conversion
502     *         to type <code>double</code>.
503     */
504    public double doubleValue() {
505        Real real = Real.valueOf(_significand, 0, _exponent);
506        return real.doubleValue();
507    }
508
509    /**
510     * Compares two floating point number numerically.
511     * 
512     * @param that the floating point number to compare with.
513     * @return -1, 0 or 1 as this FloatingPoint number is numerically less than, 
514     *         equal to, or greater than <code>that</code>.
515     */
516    public int compareTo(FloatingPoint that) {
517        FloatingPoint diff = this.minus(that);
518        if (diff.isPositive()) {
519            return 1;
520        } else if (diff.isNegative()) {
521            return -1;
522        } else {
523            return 0;
524        }
525    }
526
527    /**
528     * Returns this floating point number after normalization based upon 
529     * the number of digits.
530     * 
531     * @return <code>this</code>
532     */
533    private FloatingPoint normalize() {
534        int digits = FloatingPoint.getDigits();
535        int thisDigits = this._significand.digitLength();
536        if (thisDigits > digits) { // Scale down.
537            int pow10 = digits - thisDigits; // Negative.
538            _significand = _significand.times10pow(pow10);
539            long exponent = ((long) _exponent) - pow10;
540            if (exponent > Integer.MAX_VALUE)
541                return NaN;
542            if (exponent < Integer.MIN_VALUE)
543                return ZERO;
544            _exponent = (int) exponent;
545        }
546        return this;
547    }
548
549    @Override
550    public FloatingPoint copy() {
551        if (this == NaN)
552            return NaN; // Maintains unicity.
553        FloatingPoint r = FACTORY.object();
554        r._significand = _significand.copy();
555        r._exponent = _exponent;
556        return r;
557    }
558
559    private static final long serialVersionUID = 1L;
560}