jdk/src/share/classes/sun/misc/FormattedFloatingDecimal.java
author dl
Thu, 20 Dec 2012 12:24:52 -0800
changeset 14853 72f0bc58bb95
parent 11131 27747ee5a62a
child 18143 b6ef7bd945ce
permissions -rw-r--r--
8004330: Add missing Unsafe entry points for addAndGet() family Summary: Add Unsafe addAndGet() methods which have intrinsics in Hotspot (7023898) Reviewed-by: alanb, kvn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
9276
645e1a5c72f6 7021568: Double.parseDouble() returns architecture dependent results
darcy
parents: 5506
diff changeset
     2
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2278
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2278
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2278
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2278
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2278
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.misc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import sun.misc.DoubleConsts;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import sun.misc.FloatConsts;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.util.regex.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
9521
e18f95eadb3c 7039369: Limit range of strictfp in FloatingDecimal
darcy
parents: 9276
diff changeset
    32
public class FormattedFloatingDecimal{
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
    boolean     isExceptional;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
    boolean     isNegative;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
    int         decExponent;  // value set at construction, then immutable
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
    int         decExponentRounded;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
    char        digits[];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
    int         nDigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
    int         bigIntExp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
    int         bigIntNBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
    boolean     mustSetRoundDir = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
    boolean     fromHex = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
    int         roundDir = 0; // set by doubleValue
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    int         precision;    // number of digits to the right of decimal
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    private Form form;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
    private     FormattedFloatingDecimal( boolean negSign, int decExponent, char []digits, int n, boolean e, int precision, Form form )
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
        isNegative = negSign;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
        isExceptional = e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
        this.decExponent = decExponent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
        this.digits = digits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
        this.nDigits = n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
        this.precision = precision;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
        this.form = form;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
     * Constants of the implementation
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
     * Most are IEEE-754 related.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
     * (There are more really boring constants at the end.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    static final long   signMask = 0x8000000000000000L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    static final long   expMask  = 0x7ff0000000000000L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    static final long   fractMask= ~(signMask|expMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    static final int    expShift = 52;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    static final int    expBias  = 1023;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    static final long   fractHOB = ( 1L<<expShift ); // assumed High-Order bit
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    static final long   expOne   = ((long)expBias)<<expShift; // exponent of 1.0
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    static final int    maxSmallBinExp = 62;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    static final int    minSmallBinExp = -( 63 / 3 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    static final int    maxDecimalDigits = 15;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    static final int    maxDecimalExponent = 308;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    static final int    minDecimalExponent = -324;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    static final int    bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    static final long   highbyte = 0xff00000000000000L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    static final long   highbit  = 0x8000000000000000L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    static final long   lowbytes = ~highbyte;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    static final int    singleSignMask =    0x80000000;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    static final int    singleExpMask  =    0x7f800000;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    static final int    singleFractMask =   ~(singleSignMask|singleExpMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    static final int    singleExpShift  =   23;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    static final int    singleFractHOB  =   1<<singleExpShift;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    static final int    singleExpBias   =   127;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    static final int    singleMaxDecimalDigits = 7;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    static final int    singleMaxDecimalExponent = 38;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    static final int    singleMinDecimalExponent = -45;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    static final int    intDecimalDigits = 9;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * count number of bits from high-order 1 bit to low-order 1 bit,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     * inclusive.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    private static int
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    countBits( long v ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        // the strategy is to shift until we get a non-zero sign bit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        // then shift until we have no bits left, counting the difference.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
        // we do byte shifting as a hack. Hope it helps.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
        if ( v == 0L ) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        while ( ( v & highbyte ) == 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            v <<= 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
        while ( v > 0L ) { // i.e. while ((v&highbit) == 0L )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            v <<= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
        int n = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
        while (( v & lowbytes ) != 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
            v <<= 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
            n += 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
        while ( v != 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
            v <<= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
            n += 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
        return n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     * Keep big powers of 5 handy for future reference.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    private static FDBigInt b5p[];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    private static synchronized FDBigInt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    big5pow( int p ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
        assert p >= 0 : p; // negative power of 5
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
        if ( b5p == null ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            b5p = new FDBigInt[ p+1 ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        }else if (b5p.length <= p ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
            FDBigInt t[] = new FDBigInt[ p+1 ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            System.arraycopy( b5p, 0, t, 0, b5p.length );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            b5p = t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        if ( b5p[p] != null )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
            return b5p[p];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        else if ( p < small5pow.length )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
            return b5p[p] = new FDBigInt( small5pow[p] );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
        else if ( p < long5pow.length )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
            return b5p[p] = new FDBigInt( long5pow[p] );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            // construct the value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
            // recursively.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            int q, r;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            // in order to compute 5^p,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            // compute its square root, 5^(p/2) and square.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            // or, let q = p / 2, r = p -q, then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            // 5^p = 5^(q+r) = 5^q * 5^r
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
            q = p >> 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            r = p - q;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            FDBigInt bigq =  b5p[q];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            if ( bigq == null )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                bigq = big5pow ( q );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            if ( r < small5pow.length ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
                return (b5p[p] = bigq.mult( small5pow[r] ) );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
            }else{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                FDBigInt bigr = b5p[ r ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
                if ( bigr == null )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
                    bigr = big5pow( r );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
                return (b5p[p] = bigq.mult( bigr ) );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
    // a common operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    private static FDBigInt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    multPow52( FDBigInt v, int p5, int p2 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        if ( p5 != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            if ( p5 < small5pow.length ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                v = v.mult( small5pow[p5] );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                v = v.mult( big5pow( p5 ) );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        if ( p2 != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
            v.lshiftMe( p2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        return v;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
    // another common operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
    private static FDBigInt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
    constructPow52( int p5, int p2 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        FDBigInt v = new FDBigInt( big5pow( p5 ) );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        if ( p2 != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            v.lshiftMe( p2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        return v;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
     * Make a floating double into a FDBigInt.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
     * This could also be structured as a FDBigInt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
     * constructor, but we'd have to build a lot of knowledge
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
     * about floating-point representation into it, and we don't want to.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
     * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
     * bigIntExp and bigIntNBits
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
    private FDBigInt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
    doubleToBigInt( double dval ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        long lbits = Double.doubleToLongBits( dval ) & ~signMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        int binexp = (int)(lbits >>> expShift);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        lbits &= fractMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        if ( binexp > 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
            lbits |= fractHOB;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            assert lbits != 0L : lbits; // doubleToBigInt(0.0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
            binexp +=1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
            while ( (lbits & fractHOB ) == 0L){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                lbits <<= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                binexp -= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        binexp -= expBias;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        int nbits = countBits( lbits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
         * We now know where the high-order 1 bit is,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
         * and we know how many there are.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
        int lowOrderZeros = expShift+1-nbits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        lbits >>>= lowOrderZeros;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
        bigIntExp = binexp+1-nbits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        bigIntNBits = nbits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        return new FDBigInt( lbits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
     * Compute a number that is the ULP of the given value,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
     * for purposes of addition/subtraction. Generally easy.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
     * More difficult if subtracting and the argument
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     * is a normalized a power of 2, as the ULP changes at these points.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     */
9521
e18f95eadb3c 7039369: Limit range of strictfp in FloatingDecimal
darcy
parents: 9276
diff changeset
   249
    private static double ulp( double dval, boolean subtracting ){
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        long lbits = Double.doubleToLongBits( dval ) & ~signMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        int binexp = (int)(lbits >>> expShift);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        double ulpval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            // for subtraction from normalized, powers of 2,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
            // use next-smaller exponent
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
            binexp -= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        if ( binexp > expShift ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        } else if ( binexp == 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            ulpval = Double.MIN_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        if ( subtracting ) ulpval = - ulpval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        return ulpval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     * Round a double to a float.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
     * In addition to the fraction bits of the double,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
     * look at the class instance variable roundDir,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
     * which should help us avoid double-rounding error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
     * roundDir was set in hardValueOf if the estimate was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
     * close enough, but not exact. It tells us which direction
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     * of rounding is preferred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    float
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    stickyRound( double dval ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        long lbits = Double.doubleToLongBits( dval );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        long binexp = lbits & expMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        if ( binexp == 0L || binexp == expMask ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
            // what we have here is special.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            // don't worry, the right thing will happen.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
            return (float) dval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        lbits += (long)roundDir; // hack-o-matic.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        return (float)Double.longBitsToDouble( lbits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     * This is the easy subcase --
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
     * all the significant bits, after scaling, are held in lvalue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     * negSign and decExponent tell us what processing and scaling
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     * has already been done. Exceptional cases have already been
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     * stripped out.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     * In particular:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
     * lvalue is a finite number (not Inf, nor NaN)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
     * lvalue > 0L (not zero, nor negative).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
     * The only reason that we develop the digits here, rather than
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
     * calling on Long.toString() is that we can do it a little faster,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
     * and besides want to treat trailing 0s specially. If Long.toString
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
     * changes, we should re-evaluate this strategy!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
    private void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
    developLongDigits( int decExponent, long lvalue, long insignificant ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        char digits[];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        int  ndigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        int  digitno;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        int  c;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        // Discard non-significant low-order bits, while rounding,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        // up to insignificant value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
        for ( i = 0; insignificant >= 10L; i++ )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
            insignificant /= 10L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        if ( i != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
            long residue = lvalue % pow10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
            lvalue /= pow10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
            decExponent += i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
            if ( residue >= (pow10>>1) ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                // round up based on the low-order bits we're discarding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                lvalue++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        if ( lvalue <= Integer.MAX_VALUE ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
            assert lvalue > 0L : lvalue; // lvalue <= 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
            // even easier subcase!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            // can do int arithmetic rather than long!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
            int  ivalue = (int)lvalue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
            ndigits = 10;
11131
27747ee5a62a 7116857: Warnings in javax.security and some sun.misc
weijun
parents: 10598
diff changeset
   336
            digits = perThreadBuffer.get();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            digitno = ndigits-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            c = ivalue%10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            ivalue /= 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            while ( c == 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
                decExponent++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                c = ivalue%10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                ivalue /= 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
            while ( ivalue != 0){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
                digits[digitno--] = (char)(c+'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                decExponent++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                c = ivalue%10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                ivalue /= 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
            digits[digitno] = (char)(c+'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
            // same algorithm as above (same bugs, too )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
            // but using long arithmetic.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
            ndigits = 20;
11131
27747ee5a62a 7116857: Warnings in javax.security and some sun.misc
weijun
parents: 10598
diff changeset
   356
            digits = perThreadBuffer.get();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
            digitno = ndigits-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            c = (int)(lvalue%10L);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
            lvalue /= 10L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
            while ( c == 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
                decExponent++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                c = (int)(lvalue%10L);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
                lvalue /= 10L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
            while ( lvalue != 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                digits[digitno--] = (char)(c+'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
                decExponent++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
                c = (int)(lvalue%10L);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
                lvalue /= 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
            digits[digitno] = (char)(c+'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        char result [];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        ndigits -= digitno;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        result = new char[ ndigits ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        System.arraycopy( digits, digitno, result, 0, ndigits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        this.digits = result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        this.decExponent = decExponent+1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        this.nDigits = ndigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
    // add one to the least significant digit.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
    // in the unlikely event there is a carry out,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
    // deal with it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
    // assert that this will only happen where there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
    // is only one digit, e.g. (float)1e-44 seems to do it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
    private void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
    roundup(){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        int q = digits[ i = (nDigits-1)];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        if ( q == '9' ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            while ( q == '9' && i > 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
                digits[i] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
                q = digits[--i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            if ( q == '9' ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                // carryout! High-order 1, rest 0s, larger exp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
                decExponent += 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                digits[0] = '1';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            // else fall through.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        digits[i] = (char)(q+1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
    // Given the desired number of digits predict the result's exponent.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
    private int checkExponent(int length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        if (length >= nDigits || length < 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
            return decExponent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
        for (int i = 0; i < length; i++)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
            if (digits[i] != '9')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
                // a '9' anywhere in digits will absorb the round
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                return decExponent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        return decExponent + (digits[length] >= '5' ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
    // Unlike roundup(), this method does not modify digits.  It also
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
    // rounds at a particular precision.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    private char [] applyPrecision(int length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        char [] result = new char[nDigits];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        for (int i = 0; i < result.length; i++) result[i] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
        if (length >= nDigits || length < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
            // no rounding necessary
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
            System.arraycopy(digits, 0, result, 0, nDigits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
            return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        if (length == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
            // only one digit (0 or 1) is returned because the precision
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
            // excludes all significant digits
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            if (digits[0] >= '5') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
                result[0] = '1';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
            return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        int i = length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
        int q = digits[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
        if (q >= '5' && i > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
            q = digits[--i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
            if ( q == '9' ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                while ( q == '9' && i > 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                    q = digits[--i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                if ( q == '9' ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                    // carryout! High-order 1, rest 0s, larger exp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                    result[0] = '1';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
                    return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
            result[i] = (char)(q + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
        while (--i >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
            result[i] = digits[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
     * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
    public FormattedFloatingDecimal( double d )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
        this(d, Integer.MAX_VALUE, Form.COMPATIBLE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
    public FormattedFloatingDecimal( double d, int precision, Form form )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        long    dBits = Double.doubleToLongBits( d );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
        long    fractBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
        int     binExp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
        int     nSignificantBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
        this.precision = precision;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
        this.form      = form;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
        // discover and delete sign
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        if ( (dBits&signMask) != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
            isNegative = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
            dBits ^= signMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
            isNegative = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
        // Begin to unpack
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        // Discover obvious special cases of NaN and Infinity.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        binExp = (int)( (dBits&expMask) >> expShift );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
        fractBits = dBits&fractMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
        if ( binExp == (int)(expMask>>expShift) ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
            isExceptional = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            if ( fractBits == 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                digits =  infinity;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                digits = notANumber;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                isNegative = false; // NaN has no sign!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
            nDigits = digits.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        isExceptional = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
        // Finish unpacking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        // Normalize denormalized numbers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        // Insert assumed high-order bit for normalized numbers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
        // Subtract exponent bias.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
        if ( binExp == 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
            if ( fractBits == 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                // not a denorm, just a 0!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
                decExponent = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
                digits = zero;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
                nDigits = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
            while ( (fractBits&fractHOB) == 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
                fractBits <<= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
                binExp -= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
            nSignificantBits = expShift + binExp +1; // recall binExp is  - shift count.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
            binExp += 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
            fractBits |= fractHOB;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
            nSignificantBits = expShift+1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
        binExp -= expBias;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        // call the routine that actually does all the hard work.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
        dtoa( binExp, fractBits, nSignificantBits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
     * SECOND IMPORTANT CONSTRUCTOR: SINGLE
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
    public FormattedFloatingDecimal( float f )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
        this(f, Integer.MAX_VALUE, Form.COMPATIBLE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
    public FormattedFloatingDecimal( float f, int precision, Form form )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
        int     fBits = Float.floatToIntBits( f );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
        int     fractBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
        int     binExp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        int     nSignificantBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
        this.precision = precision;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        this.form      = form;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        // discover and delete sign
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
        if ( (fBits&singleSignMask) != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
            isNegative = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
            fBits ^= singleSignMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
            isNegative = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
        // Begin to unpack
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        // Discover obvious special cases of NaN and Infinity.
11131
27747ee5a62a 7116857: Warnings in javax.security and some sun.misc
weijun
parents: 10598
diff changeset
   557
        binExp = (fBits&singleExpMask) >> singleExpShift;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        fractBits = fBits&singleFractMask;
11131
27747ee5a62a 7116857: Warnings in javax.security and some sun.misc
weijun
parents: 10598
diff changeset
   559
        if ( binExp == (singleExpMask>>singleExpShift) ) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
            isExceptional = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
            if ( fractBits == 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
                digits =  infinity;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
                digits = notANumber;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
                isNegative = false; // NaN has no sign!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
            nDigits = digits.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        isExceptional = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
        // Finish unpacking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
        // Normalize denormalized numbers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        // Insert assumed high-order bit for normalized numbers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
        // Subtract exponent bias.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
        if ( binExp == 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
            if ( fractBits == 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                // not a denorm, just a 0!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
                decExponent = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
                digits = zero;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                nDigits = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            while ( (fractBits&singleFractHOB) == 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
                fractBits <<= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
                binExp -= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
            nSignificantBits = singleExpShift + binExp +1; // recall binExp is  - shift count.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
            binExp += 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            fractBits |= singleFractHOB;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
            nSignificantBits = singleExpShift+1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        binExp -= singleExpBias;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
        // call the routine that actually does all the hard work.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
    private void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
    dtoa( int binExp, long fractBits, int nSignificantBits )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        int     nFractBits; // number of significant bits of fractBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        int     nTinyBits;  // number of these to the right of the point.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
        int     decExp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
        // Examine number. Determine if it is an easy case,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
        // which we can do pretty trivially using float/long conversion,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
        // or whether we must do real work.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        nFractBits = countBits( fractBits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
        nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
        if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
            // Look more closely at the number to decide if,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
            // with scaling by 10^nTinyBits, the result will fit in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            // a long.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
            if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                 * We can do this:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
                 * take the fraction bits, which are normalized.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
                 * (a) nTinyBits == 0: Shift left or right appropriately
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                 *     to align the binary point at the extreme right, i.e.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                 *     where a long int point is expected to be. The integer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                 *     result is easily converted to a string.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                 * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                 *     which effectively converts to long and scales by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                 *     2^nTinyBits. Then multiply by 5^nTinyBits to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                 *     complete the scaling. We know this won't overflow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                 *     because we just counted the number of bits necessary
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                 *     in the result. The integer you get from this can
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                 *     then be converted to a string pretty easily.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
                long halfULP;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
                if ( nTinyBits == 0 ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
                    if ( binExp > nSignificantBits ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
                        halfULP = 1L << ( binExp-nSignificantBits-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
                        halfULP = 0L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                    if ( binExp >= expShift ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
                        fractBits <<= (binExp-expShift);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
                        fractBits >>>= (expShift-binExp) ;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
                    developLongDigits( 0, fractBits, halfULP );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
                 * The following causes excess digits to be printed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
                 * out in the single-float case. Our manipulation of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
                 * halfULP here is apparently not correct. If we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
                 * better understand how this works, perhaps we can
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
                 * use this special case again. But for the time being,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
                 * we do not.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
                 * else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
                 *     fractBits >>>= expShift+1-nFractBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
                 *     fractBits *= long5pow[ nTinyBits ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
                 *     halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
                 *     developLongDigits( -nTinyBits, fractBits, halfULP );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
                 *     return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
                 * }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
         * This is the hard case. We are going to compute large positive
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
         * integers B and S and integer decExp, s.t.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
         *      d = ( B / S ) * 10^decExp
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
         *      1 <= B / S < 10
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
         * Obvious choices are:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
         *      decExp = floor( log10(d) )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
         *      B      = d * 2^nTinyBits * 10^max( 0, -decExp )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
         *      S      = 10^max( 0, decExp) * 2^nTinyBits
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
         * (noting that nTinyBits has already been forced to non-negative)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
         * I am also going to compute a large positive integer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
         *      M      = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
         * i.e. M is (1/2) of the ULP of d, scaled like B.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
         * When we iterate through dividing B/S and picking off the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
         * quotient bits, we will know when to stop when the remainder
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
         * is <= M.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
         * We keep track of powers of 2 and powers of 5.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
         * Estimate decimal exponent. (If it is small-ish,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
         * we could double-check.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
         * First, scale the mantissa bits such that 1 <= d2 < 2.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
         * We are then going to estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
         *          log10(d2) ~=~  (d2-1.5)/1.5 + log(1.5)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
         * and so we can estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
         *      log10(d) ~=~ log10(d2) + binExp * log10(2)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
         * take the floor and call it decExp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
         * FIXME -- use more precise constants here. It costs no more.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        double d2 = Double.longBitsToDouble(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
            expOne | ( fractBits &~ fractHOB ) );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
        decExp = (int)Math.floor(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
            (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
        int B2, B5; // powers of 2 and powers of 5, respectively, in B
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
        int S2, S5; // powers of 2 and powers of 5, respectively, in S
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
        int M2, M5; // powers of 2 and powers of 5, respectively, in M
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
        int Bbits; // binary digits needed to represent B, approx.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        int tenSbits; // binary digits needed to represent 10*S, approx.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
        FDBigInt Sval, Bval, Mval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
        B5 = Math.max( 0, -decExp );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
        B2 = B5 + nTinyBits + binExp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
        S5 = Math.max( 0, decExp );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
        S2 = S5 + nTinyBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
        M5 = B5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
        M2 = B2 - nSignificantBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
         * the long integer fractBits contains the (nFractBits) interesting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
         * bits from the mantissa of d ( hidden 1 added if necessary) followed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
         * by (expShift+1-nFractBits) zeros. In the interest of compactness,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
         * I will shift out those zeros before turning fractBits into a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
         * FDBigInt. The resulting whole number will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
         *      d * 2^(nFractBits-1-binExp).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
        fractBits >>>= (expShift+1-nFractBits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
        B2 -= nFractBits-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        int common2factor = Math.min( B2, S2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
        B2 -= common2factor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
        S2 -= common2factor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
        M2 -= common2factor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
         * HACK!! For exact powers of two, the next smallest number
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
         * is only half as far away as we think (because the meaning of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
         * ULP changes at power-of-two bounds) for this reason, we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
         * hack M2. Hope this works.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
        if ( nFractBits == 1 )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
            M2 -= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
        if ( M2 < 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
            // oops.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
            // since we cannot scale M down far enough,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            // we must scale the other values up.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
            B2 -= M2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
            S2 -= M2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
            M2 =  0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
         * Construct, Scale, iterate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
         * Some day, we'll write a stopping test that takes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
         * account of the assymetry of the spacing of floating-point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
         * numbers below perfect powers of 2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
         * 26 Sept 96 is not that day.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
         * So we use a symmetric test.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
        char digits[] = this.digits = new char[18];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
        int  ndigit = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
        boolean low, high;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
        long lowDigitDifference;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
        int  q;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
         * Detect the special cases where all the numbers we are about
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
         * to compute will fit in int or long integers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
         * In these cases, we will avoid doing FDBigInt arithmetic.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
         * We use the same algorithms, except that we "normalize"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
         * our FDBigInts before iterating. This is to make division easier,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
         * as it makes our fist guess (quotient of high-order words)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
         * more accurate!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
         * Some day, we'll write a stopping test that takes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
         * account of the assymetry of the spacing of floating-point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
         * numbers below perfect powers of 2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
         * 26 Sept 96 is not that day.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
         * So we use a symmetric test.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
        Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
        tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
        if ( Bbits < 64 && tenSbits < 64){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
            if ( Bbits < 32 && tenSbits < 32){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
                // wa-hoo! They're all ints!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
                int b = ((int)fractBits * small5pow[B5] ) << B2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
                int s = small5pow[S5] << S2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
                int m = small5pow[M5] << M2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
                int tens = s * 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
                 * Unroll the first iteration. If our decExp estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
                 * was too high, our first quotient will be zero. In this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
                 * case, we discard it and decrement decExp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
                ndigit = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
                q = b / s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
                b = 10 * ( b % s );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
                m *= 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
                low  = (b <  m );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
                high = (b+m > tens );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
                assert q < 10 : q; // excessively large digit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
                if ( (q == 0) && ! high ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
                    // oops. Usually ignore leading zero.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
                    decExp--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
                    digits[ndigit++] = (char)('0' + q);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
                 * HACK! Java spec sez that we always have at least
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
                 * one digit after the . in either F- or E-form output.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
                 * Thus we will need more than one digit if we're using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
                 * E-form
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
                if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
                    high = low = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
                while( ! low && ! high ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
                    q = b / s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
                    b = 10 * ( b % s );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
                    m *= 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
                    assert q < 10 : q; // excessively large digit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
                    if ( m > 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
                        low  = (b <  m );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
                        high = (b+m > tens );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
                        // hack -- m might overflow!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
                        // in this case, it is certainly > b,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
                        // which won't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
                        // and b+m > tens, too, since that has overflowed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
                        // either!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
                        low = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
                        high = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
                    digits[ndigit++] = (char)('0' + q);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
                lowDigitDifference = (b<<1) - tens;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
                // still good! they're all longs!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
                long b = (fractBits * long5pow[B5] ) << B2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                long s = long5pow[S5] << S2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
                long m = long5pow[M5] << M2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
                long tens = s * 10L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
                 * Unroll the first iteration. If our decExp estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
                 * was too high, our first quotient will be zero. In this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
                 * case, we discard it and decrement decExp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
                ndigit = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
                q = (int) ( b / s );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
                b = 10L * ( b % s );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
                m *= 10L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
                low  = (b <  m );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
                high = (b+m > tens );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
                assert q < 10 : q; // excessively large digit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
                if ( (q == 0) && ! high ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
                    // oops. Usually ignore leading zero.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
                    decExp--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
                    digits[ndigit++] = (char)('0' + q);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
                 * HACK! Java spec sez that we always have at least
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
                 * one digit after the . in either F- or E-form output.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
                 * Thus we will need more than one digit if we're using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
                 * E-form
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
                if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
                    high = low = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
                while( ! low && ! high ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
                    q = (int) ( b / s );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
                    b = 10 * ( b % s );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
                    m *= 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
                    assert q < 10 : q;  // excessively large digit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
                    if ( m > 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
                        low  = (b <  m );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
                        high = (b+m > tens );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
                        // hack -- m might overflow!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
                        // in this case, it is certainly > b,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
                        // which won't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
                        // and b+m > tens, too, since that has overflowed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
                        // either!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
                        low = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
                        high = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
                    digits[ndigit++] = (char)('0' + q);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
                lowDigitDifference = (b<<1) - tens;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
            FDBigInt tenSval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
            int  shiftBias;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
             * We really must do FDBigInt arithmetic.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
             * Fist, construct our FDBigInt initial values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
            Bval = multPow52( new FDBigInt( fractBits  ), B5, B2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
            Sval = constructPow52( S5, S2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
            Mval = constructPow52( M5, M2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
            // normalize so that division works better
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
            Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
            Mval.lshiftMe( shiftBias );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
            tenSval = Sval.mult( 10 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
             * Unroll the first iteration. If our decExp estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
             * was too high, our first quotient will be zero. In this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
             * case, we discard it and decrement decExp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
            ndigit = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
            q = Bval.quoRemIteration( Sval );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
            Mval = Mval.mult( 10 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
            low  = (Bval.cmp( Mval ) < 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
            high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
            assert q < 10 : q; // excessively large digit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
            if ( (q == 0) && ! high ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
                // oops. Usually ignore leading zero.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
                decExp--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
                digits[ndigit++] = (char)('0' + q);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
             * HACK! Java spec sez that we always have at least
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
             * one digit after the . in either F- or E-form output.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
             * Thus we will need more than one digit if we're using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
             * E-form
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
            if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
                high = low = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
            while( ! low && ! high ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
                q = Bval.quoRemIteration( Sval );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
                Mval = Mval.mult( 10 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
                assert q < 10 : q;  // excessively large digit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
                low  = (Bval.cmp( Mval ) < 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
                high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
                digits[ndigit++] = (char)('0' + q);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
            if ( high && low ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
                Bval.lshiftMe(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
                lowDigitDifference = Bval.cmp(tenSval);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
            } else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
                lowDigitDifference = 0L; // this here only for flow analysis!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
        this.decExponent = decExp+1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
        this.digits = digits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
        this.nDigits = ndigit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
         * Last digit gets rounded based on stopping condition.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
        if ( high ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
            if ( low ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
                if ( lowDigitDifference == 0L ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
                    // it's a tie!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
                    // choose based on which digits we like.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
                    if ( (digits[nDigits-1]&1) != 0 ) roundup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
                } else if ( lowDigitDifference > 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
                    roundup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
                roundup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
    public String
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
    toString(){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
        // most brain-dead version
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
        StringBuffer result = new StringBuffer( nDigits+8 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
        if ( isNegative ){ result.append( '-' ); }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
        if ( isExceptional ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
            result.append( digits, 0, nDigits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
            result.append( "0.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
            result.append( digits, 0, nDigits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
            result.append('e');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
            result.append( decExponent );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
        return new String(result);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
    // returns the exponent before rounding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
    public int getExponent() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
        return decExponent - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
    // returns the exponent after rounding has been done by applyPrecision
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
    public int getExponentRounded() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
        return decExponentRounded - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
    public int getChars(char[] result) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
        assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
        int i = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
        if (isNegative) { result[0] = '-'; i = 1; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
        if (isExceptional) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
            System.arraycopy(digits, 0, result, i, nDigits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
            i += nDigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
            char digits [] = this.digits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
            int exp = decExponent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
            switch (form) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
            case COMPATIBLE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
            case DECIMAL_FLOAT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
                exp = checkExponent(decExponent + precision);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
                digits = applyPrecision(decExponent + precision);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
            case SCIENTIFIC:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
                exp = checkExponent(precision + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
                digits = applyPrecision(precision + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
            case GENERAL:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
                exp = checkExponent(precision);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
                digits = applyPrecision(precision);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
                // adjust precision to be the number of digits to right of decimal
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
                // the real exponent to be output is actually exp - 1, not exp
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
                if (exp - 1 < -4 || exp - 1 >= precision) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
                    form = Form.SCIENTIFIC;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
                    precision--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
                    form = Form.DECIMAL_FLOAT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
                    precision = precision - exp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
                assert false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
            decExponentRounded = exp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
            if (exp > 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
                && ((form == Form.COMPATIBLE && (exp < 8))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
                    || (form == Form.DECIMAL_FLOAT)))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
            {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
                // print digits.digits.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
                int charLength = Math.min(nDigits, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
                System.arraycopy(digits, 0, result, i, charLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
                i += charLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
                if (charLength < exp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
                    charLength = exp-charLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
                    for (int nz = 0; nz < charLength; nz++)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
                        result[i++] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
                    // Do not append ".0" for formatted floats since the user
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
                    // may request that it be omitted. It is added as necessary
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
                    // by the Formatter.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
                    if (form == Form.COMPATIBLE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
                        result[i++] = '.';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
                        result[i++] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
                    // Do not append ".0" for formatted floats since the user
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
                    // may request that it be omitted. It is added as necessary
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
                    // by the Formatter.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
                    if (form == Form.COMPATIBLE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
                        result[i++] = '.';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
                        if (charLength < nDigits) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
                            int t = Math.min(nDigits - charLength, precision);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
                            System.arraycopy(digits, charLength, result, i, t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
                            i += t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
                            result[i++] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
                        int t = Math.min(nDigits - charLength, precision);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
                        if (t > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
                            result[i++] = '.';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
                            System.arraycopy(digits, charLength, result, i, t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
                            i += t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
            } else if (exp <= 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
                       && ((form == Form.COMPATIBLE && exp > -3)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
                       || (form == Form.DECIMAL_FLOAT)))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
            {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
                // print 0.0* digits
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
                result[i++] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
                if (exp != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
                    // write '0' s before the significant digits
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
                    int t = Math.min(-exp, precision);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
                    if (t > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
                        result[i++] = '.';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
                        for (int nz = 0; nz < t; nz++)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
                            result[i++] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
                int t = Math.min(digits.length, precision + exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
                if (t > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
                    if (i == 1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
                        result[i++] = '.';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
                    // copy only when significant digits are within the precision
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
                    System.arraycopy(digits, 0, result, i, t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
                    i += t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
                result[i++] = digits[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
                if (form == Form.COMPATIBLE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
                    result[i++] = '.';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
                    if (nDigits > 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
                        System.arraycopy(digits, 1, result, i, nDigits-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
                        i += nDigits-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
                        result[i++] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
                    result[i++] = 'E';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
                    if (nDigits > 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
                        int t = Math.min(nDigits -1, precision);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
                        if (t > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
                            result[i++] = '.';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
                            System.arraycopy(digits, 1, result, i, t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
                            i += t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
                    result[i++] = 'e';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
                int e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
                if (exp <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
                    result[i++] = '-';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
                    e = -exp+1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
                    if (form != Form.COMPATIBLE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
                        result[i++] = '+';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
                    e = exp-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
                // decExponent has 1, 2, or 3, digits
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
                if (e <= 9) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
                    if (form != Form.COMPATIBLE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
                        result[i++] = '0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
                    result[i++] = (char)(e+'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
                } else if (e <= 99) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
                    result[i++] = (char)(e/10 +'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
                    result[i++] = (char)(e%10 + '0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
                    result[i++] = (char)(e/100+'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
                    e %= 100;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
                    result[i++] = (char)(e/10+'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
                    result[i++] = (char)(e%10 + '0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
        return i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
    // Per-thread buffer for string/stringbuffer conversion
11131
27747ee5a62a 7116857: Warnings in javax.security and some sun.misc
weijun
parents: 10598
diff changeset
  1143
    private static ThreadLocal<char[]> perThreadBuffer = new ThreadLocal<char[]>() {
27747ee5a62a 7116857: Warnings in javax.security and some sun.misc
weijun
parents: 10598
diff changeset
  1144
            protected synchronized char[] initialValue() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
                return new char[26];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
        };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
     * Take a FormattedFloatingDecimal, which we presumably just scanned in,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
     * and find out what its value is, as a double.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
     * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
     * ROUNDING DIRECTION in case the result is really destined
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
     * for a single-precision float.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
9521
e18f95eadb3c 7039369: Limit range of strictfp in FloatingDecimal
darcy
parents: 9276
diff changeset
  1158
    public strictfp double doubleValue(){
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
        int     kDigits = Math.min( nDigits, maxDecimalDigits+1 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
        long    lValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
        double  dValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
        double  rValue, tValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
        // First, check for NaN and Infinity values
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
        if(digits == infinity || digits == notANumber) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
            if(digits == notANumber)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
                return Double.NaN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
            else
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
                return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
            if (mustSetRoundDir) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
                roundDir = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
             * convert the lead kDigits to a long integer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
            // (special performance hack: start to do it using int)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
            int iValue = (int)digits[0]-(int)'0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
            int iDigits = Math.min( kDigits, intDecimalDigits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
            for ( int i=1; i < iDigits; i++ ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
                iValue = iValue*10 + (int)digits[i]-(int)'0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
            lValue = (long)iValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
            for ( int i=iDigits; i < kDigits; i++ ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
                lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
            dValue = (double)lValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
            int exp = decExponent-kDigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
             * lValue now contains a long integer with the value of
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
             * the first kDigits digits of the number.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
             * dValue contains the (double) of the same.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
            if ( nDigits <= maxDecimalDigits ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
                 * possibly an easy case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
                 * We know that the digits can be represented
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
                 * exactly. And if the exponent isn't too outrageous,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
                 * the whole thing can be done with one operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
                 * thus one rounding error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
                 * Note that all our constructors trim all leading and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
                 * trailing zeros, so simple values (including zero)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
                 * will always end up here
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
                if (exp == 0 || dValue == 0.0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
                    return (isNegative)? -dValue : dValue; // small floating integer
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
                else if ( exp >= 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
                    if ( exp <= maxSmallTen ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
                         * Can get the answer with one operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
                         * thus one roundoff.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
                        rValue = dValue * small10pow[exp];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
                        if ( mustSetRoundDir ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
                            tValue = rValue / small10pow[exp];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
                            roundDir = ( tValue ==  dValue ) ? 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
                                :( tValue < dValue ) ? 1
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
                                : -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
                        return (isNegative)? -rValue : rValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
                    int slop = maxDecimalDigits - kDigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
                    if ( exp <= maxSmallTen+slop ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
                         * We can multiply dValue by 10^(slop)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
                         * and it is still "small" and exact.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
                         * Then we can multiply by 10^(exp-slop)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
                         * with one rounding.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
                        dValue *= small10pow[slop];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
                        rValue = dValue * small10pow[exp-slop];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
                        if ( mustSetRoundDir ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
                            tValue = rValue / small10pow[exp-slop];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
                            roundDir = ( tValue ==  dValue ) ? 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
                                :( tValue < dValue ) ? 1
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
                                : -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
                        return (isNegative)? -rValue : rValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
                     * Else we have a hard case with a positive exp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
                    if ( exp >= -maxSmallTen ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
                         * Can get the answer in one division.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
                        rValue = dValue / small10pow[-exp];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
                        tValue = rValue * small10pow[-exp];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
                        if ( mustSetRoundDir ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
                            roundDir = ( tValue ==  dValue ) ? 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
                                :( tValue < dValue ) ? 1
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
                                : -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
                        return (isNegative)? -rValue : rValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
                     * Else we have a hard case with a negative exp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
             * Harder cases:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
             * The sum of digits plus exponent is greater than
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
             * what we think we can do with one error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
             * Start by approximating the right answer by,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1272
             * naively, scaling by powers of 10.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
            if ( exp > 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
                if ( decExponent > maxDecimalExponent+1 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
                     * Lets face it. This is going to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
                     * Infinity. Cut to the chase.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
                    return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
                if ( (exp&15) != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1283
                    dValue *= small10pow[exp&15];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1284
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1285
                if ( (exp>>=4) != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1286
                    int j;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1287
                    for( j = 0; exp > 1; j++, exp>>=1 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1288
                        if ( (exp&1)!=0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1289
                            dValue *= big10pow[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1290
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1291
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1292
                     * The reason for the weird exp > 1 condition
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1293
                     * in the above loop was so that the last multiply
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1294
                     * would get unrolled. We handle it here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1295
                     * It could overflow.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1296
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1297
                    double t = dValue * big10pow[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1298
                    if ( Double.isInfinite( t ) ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1299
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1300
                         * It did overflow.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1301
                         * Look more closely at the result.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1302
                         * If the exponent is just one too large,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1303
                         * then use the maximum finite as our estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1304
                         * value. Else call the result infinity
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1305
                         * and punt it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1306
                         * ( I presume this could happen because
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1307
                         * rounding forces the result here to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1308
                         * an ULP or two larger than
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1309
                         * Double.MAX_VALUE ).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1310
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1311
                        t = dValue / 2.0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1312
                        t *= big10pow[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1313
                        if ( Double.isInfinite( t ) ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1314
                            return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1315
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1316
                        t = Double.MAX_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1317
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1318
                    dValue = t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1319
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1320
            } else if ( exp < 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1321
                exp = -exp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1322
                if ( decExponent < minDecimalExponent-1 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1323
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1324
                     * Lets face it. This is going to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1325
                     * zero. Cut to the chase.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1326
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1327
                    return (isNegative)? -0.0 : 0.0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1328
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1329
                if ( (exp&15) != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1330
                    dValue /= small10pow[exp&15];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1331
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1332
                if ( (exp>>=4) != 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1333
                    int j;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1334
                    for( j = 0; exp > 1; j++, exp>>=1 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1335
                        if ( (exp&1)!=0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1336
                            dValue *= tiny10pow[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1337
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1338
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1339
                     * The reason for the weird exp > 1 condition
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1340
                     * in the above loop was so that the last multiply
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1341
                     * would get unrolled. We handle it here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1342
                     * It could underflow.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1343
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1344
                    double t = dValue * tiny10pow[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1345
                    if ( t == 0.0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1346
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1347
                         * It did underflow.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1348
                         * Look more closely at the result.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1349
                         * If the exponent is just one too small,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1350
                         * then use the minimum finite as our estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1351
                         * value. Else call the result 0.0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1352
                         * and punt it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1353
                         * ( I presume this could happen because
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1354
                         * rounding forces the result here to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1355
                         * an ULP or two less than
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1356
                         * Double.MIN_VALUE ).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1357
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1358
                        t = dValue * 2.0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1359
                        t *= tiny10pow[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1360
                        if ( t == 0.0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1361
                            return (isNegative)? -0.0 : 0.0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1362
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1363
                        t = Double.MIN_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1364
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1365
                    dValue = t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1366
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1367
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1368
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1369
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1370
             * dValue is now approximately the result.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1371
             * The hard part is adjusting it, by comparison
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1372
             * with FDBigInt arithmetic.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1373
             * Formulate the EXACT big-number result as
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1374
             * bigD0 * 10^exp
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1375
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1376
            FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1377
            exp   = decExponent - nDigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1378
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1379
            correctionLoop:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1380
            while(true){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1381
                /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1382
                 * bigIntExp and bigIntNBits
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1383
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1384
                FDBigInt bigB = doubleToBigInt( dValue );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1385
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1386
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1387
                 * Scale bigD, bigB appropriately for
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1388
                 * big-integer operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1389
                 * Naively, we multipy by powers of ten
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1390
                 * and powers of two. What we actually do
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1391
                 * is keep track of the powers of 5 and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1392
                 * powers of 2 we would use, then factor out
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1393
                 * common divisors before doing the work.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1394
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1395
                int B2, B5; // powers of 2, 5 in bigB
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1396
                int     D2, D5; // powers of 2, 5 in bigD
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1397
                int Ulp2;   // powers of 2 in halfUlp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1398
                if ( exp >= 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1399
                    B2 = B5 = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1400
                    D2 = D5 = exp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1401
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1402
                    B2 = B5 = -exp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1403
                    D2 = D5 = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1404
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1405
                if ( bigIntExp >= 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1406
                    B2 += bigIntExp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1407
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1408
                    D2 -= bigIntExp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1409
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1410
                Ulp2 = B2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1411
                // shift bigB and bigD left by a number s. t.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1412
                // halfUlp is still an integer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1413
                int hulpbias;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1414
                if ( bigIntExp+bigIntNBits <= -expBias+1 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1415
                    // This is going to be a denormalized number
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1416
                    // (if not actually zero).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1417
                    // half an ULP is at 2^-(expBias+expShift+1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1418
                    hulpbias = bigIntExp+ expBias + expShift;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1419
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1420
                    hulpbias = expShift + 2 - bigIntNBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1421
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1422
                B2 += hulpbias;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1423
                D2 += hulpbias;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1424
                // if there are common factors of 2, we might just as well
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1425
                // factor them out, as they add nothing useful.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1426
                int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1427
                B2 -= common2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1428
                D2 -= common2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1429
                Ulp2 -= common2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1430
                // do multiplications by powers of 5 and 2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1431
                bigB = multPow52( bigB, B5, B2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1432
                FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1433
                //
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1434
                // to recap:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1435
                // bigB is the scaled-big-int version of our floating-point
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1436
                // candidate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1437
                // bigD is the scaled-big-int version of the exact value
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1438
                // as we understand it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1439
                // halfUlp is 1/2 an ulp of bigB, except for special cases
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1440
                // of exact powers of 2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1441
                //
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1442
                // the plan is to compare bigB with bigD, and if the difference
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1443
                // is less than halfUlp, then we're satisfied. Otherwise,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1444
                // use the ratio of difference to halfUlp to calculate a fudge
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1445
                // factor to add to the floating value, then go 'round again.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1446
                //
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1447
                FDBigInt diff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1448
                int cmpResult;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1449
                boolean overvalue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1450
                if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1451
                    overvalue = true; // our candidate is too big.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1452
                    diff = bigB.sub( bigD );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1453
                    if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1454
                        // candidate is a normalized exact power of 2 and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1455
                        // is too big. We will be subtracting.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1456
                        // For our purposes, ulp is the ulp of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1457
                        // next smaller range.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1458
                        Ulp2 -= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1459
                        if ( Ulp2 < 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1460
                            // rats. Cannot de-scale ulp this far.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1461
                            // must scale diff in other direction.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1462
                            Ulp2 = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1463
                            diff.lshiftMe( 1 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1464
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1465
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1466
                } else if ( cmpResult < 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1467
                    overvalue = false; // our candidate is too small.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1468
                    diff = bigD.sub( bigB );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1469
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1470
                    // the candidate is exactly right!
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1471
                    // this happens with surprising fequency
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1472
                    break correctionLoop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1473
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1474
                FDBigInt halfUlp = constructPow52( B5, Ulp2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1475
                if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1476
                    // difference is small.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1477
                    // this is close enough
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1478
                    if (mustSetRoundDir) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1479
                        roundDir = overvalue ? -1 : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1480
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1481
                    break correctionLoop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1482
                } else if ( cmpResult == 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1483
                    // difference is exactly half an ULP
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1484
                    // round to some other value maybe, then finish
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1485
                    dValue += 0.5*ulp( dValue, overvalue );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1486
                    // should check for bigIntNBits == 1 here??
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1487
                    if (mustSetRoundDir) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1488
                        roundDir = overvalue ? -1 : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1489
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1490
                    break correctionLoop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1491
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1492
                    // difference is non-trivial.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1493
                    // could scale addend by ratio of difference to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1494
                    // halfUlp here, if we bothered to compute that difference.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1495
                    // Most of the time ( I hope ) it is about 1 anyway.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1496
                    dValue += ulp( dValue, overvalue );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1497
                    if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1498
                        break correctionLoop; // oops. Fell off end of range.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1499
                    continue; // try again.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1500
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1501
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1502
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1503
            return (isNegative)? -dValue : dValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1504
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1505
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1506
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1507
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1508
     * Take a FormattedFloatingDecimal, which we presumably just scanned in,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1509
     * and find out what its value is, as a float.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1510
     * This is distinct from doubleValue() to avoid the extremely
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1511
     * unlikely case of a double rounding error, wherein the converstion
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1512
     * to double has one rounding error, and the conversion of that double
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1513
     * to a float has another rounding error, IN THE WRONG DIRECTION,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1514
     * ( because of the preference to a zero low-order bit ).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1515
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1516
9521
e18f95eadb3c 7039369: Limit range of strictfp in FloatingDecimal
darcy
parents: 9276
diff changeset
  1517
    public strictfp float floatValue(){
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1518
        int     kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1519
        int     iValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1520
        float   fValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1521
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1522
        // First, check for NaN and Infinity values
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1523
        if(digits == infinity || digits == notANumber) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1524
            if(digits == notANumber)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1525
                return Float.NaN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1526
            else
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1527
                return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1528
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1529
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1530
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1531
             * convert the lead kDigits to an integer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1532
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1533
            iValue = (int)digits[0]-(int)'0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1534
            for ( int i=1; i < kDigits; i++ ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1535
                iValue = iValue*10 + (int)digits[i]-(int)'0';
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1536
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1537
            fValue = (float)iValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1538
            int exp = decExponent-kDigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1539
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1540
             * iValue now contains an integer with the value of
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1541
             * the first kDigits digits of the number.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1542
             * fValue contains the (float) of the same.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1543
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1544
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1545
            if ( nDigits <= singleMaxDecimalDigits ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1546
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1547
                 * possibly an easy case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1548
                 * We know that the digits can be represented
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1549
                 * exactly. And if the exponent isn't too outrageous,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1550
                 * the whole thing can be done with one operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1551
                 * thus one rounding error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1552
                 * Note that all our constructors trim all leading and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1553
                 * trailing zeros, so simple values (including zero)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1554
                 * will always end up here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1555
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1556
                if (exp == 0 || fValue == 0.0f)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1557
                    return (isNegative)? -fValue : fValue; // small floating integer
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1558
                else if ( exp >= 0 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1559
                    if ( exp <= singleMaxSmallTen ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1560
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1561
                         * Can get the answer with one operation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1562
                         * thus one roundoff.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1563
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1564
                        fValue *= singleSmall10pow[exp];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1565
                        return (isNegative)? -fValue : fValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1566
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1567
                    int slop = singleMaxDecimalDigits - kDigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1568
                    if ( exp <= singleMaxSmallTen+slop ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1569
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1570
                         * We can multiply dValue by 10^(slop)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1571
                         * and it is still "small" and exact.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1572
                         * Then we can multiply by 10^(exp-slop)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1573
                         * with one rounding.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1574
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1575
                        fValue *= singleSmall10pow[slop];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1576
                        fValue *= singleSmall10pow[exp-slop];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1577
                        return (isNegative)? -fValue : fValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1578
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1579
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1580
                     * Else we have a hard case with a positive exp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1581
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1582
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1583
                    if ( exp >= -singleMaxSmallTen ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1584
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1585
                         * Can get the answer in one division.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1586
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1587
                        fValue /= singleSmall10pow[-exp];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1588
                        return (isNegative)? -fValue : fValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1589
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1590
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1591
                     * Else we have a hard case with a negative exp.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1592
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1593
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1594
            } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1595
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1596
                 * In double-precision, this is an exact floating integer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1597
                 * So we can compute to double, then shorten to float
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1598
                 * with one round, and get the right answer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1599
                 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1600
                 * First, finish accumulating digits.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1601
                 * Then convert that integer to a double, multiply
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1602
                 * by the appropriate power of ten, and convert to float.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1603
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1604
                long lValue = (long)iValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1605
                for ( int i=kDigits; i < nDigits; i++ ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1606
                    lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1607
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1608
                double dValue = (double)lValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1609
                exp = decExponent-nDigits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1610
                dValue *= small10pow[exp];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1611
                fValue = (float)dValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1612
                return (isNegative)? -fValue : fValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1613
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1614
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1615
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1616
             * Harder cases:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1617
             * The sum of digits plus exponent is greater than
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1618
             * what we think we can do with one error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1619
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1620
             * Start by weeding out obviously out-of-range
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1621
             * results, then convert to double and go to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1622
             * common hard-case code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1623
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1624
            if ( decExponent > singleMaxDecimalExponent+1 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1625
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1626
                 * Lets face it. This is going to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1627
                 * Infinity. Cut to the chase.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1628
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1629
                return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1630
            } else if ( decExponent < singleMinDecimalExponent-1 ){
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1631
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1632
                 * Lets face it. This is going to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1633
                 * zero. Cut to the chase.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1634
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1635
                return (isNegative)? -0.0f : 0.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1636
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1637
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1638
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1639
             * Here, we do 'way too much work, but throwing away
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1640
             * our partial results, and going and doing the whole
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1641
             * thing as double, then throwing away half the bits that computes
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1642
             * when we convert back to float.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1643
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1644
             * The alternative is to reproduce the whole multiple-precision
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1645
             * algorythm for float precision, or to try to parameterize it
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1646
             * for common usage. The former will take about 400 lines of code,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1647
             * and the latter I tried without success. Thus the semi-hack
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1648
             * answer here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1649
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1650
            mustSetRoundDir = !fromHex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1651
            double dValue = doubleValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1652
            return stickyRound( dValue );
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1653
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1654
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1655
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1656
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1657
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1658
     * All the positive powers of 10 that can be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1659
     * represented exactly in double/float.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1660
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1661
    private static final double small10pow[] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1662
        1.0e0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1663
        1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1664
        1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1665
        1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1666
        1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1667
        1.0e21, 1.0e22
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1668
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1669
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1670
    private static final float singleSmall10pow[] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1671
        1.0e0f,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1672
        1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1673
        1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1674
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1675
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1676
    private static final double big10pow[] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1677
        1e16, 1e32, 1e64, 1e128, 1e256 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1678
    private static final double tiny10pow[] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1679
        1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1680
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1681
    private static final int maxSmallTen = small10pow.length-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1682
    private static final int singleMaxSmallTen = singleSmall10pow.length-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1683
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1684
    private static final int small5pow[] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1685
        1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1686
        5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1687
        5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1688
        5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1689
        5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1690
        5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1691
        5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1692
        5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1693
        5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1694
        5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1695
        5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1696
        5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1697
        5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1698
        5*5*5*5*5*5*5*5*5*5*5*5*5
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1699
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1700
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1701
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1702
    private static final long long5pow[] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1703
        1L,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1704
        5L,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1705
        5L*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1706
        5L*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1707
        5L*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1708
        5L*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1709
        5L*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1710
        5L*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1711
        5L*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1712
        5L*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1713
        5L*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1714
        5L*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1715
        5L*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1716
        5L*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1717
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1718
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1719
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1720
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1721
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1722
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1723
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1724
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1725
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1726
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1727
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1728
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1729
        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1730
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1731
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1732
    // approximately ceil( log2( long5pow[i] ) )
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1733
    private static final int n5bits[] = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1734
        0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1735
        3,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1736
        5,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1737
        7,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1738
        10,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1739
        12,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1740
        14,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1741
        17,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1742
        19,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1743
        21,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1744
        24,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1745
        26,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1746
        28,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1747
        31,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1748
        33,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1749
        35,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1750
        38,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1751
        40,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1752
        42,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1753
        45,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1754
        47,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1755
        49,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1756
        52,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1757
        54,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1758
        56,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1759
        59,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1760
        61,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1761
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1762
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1763
    private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1764
    private static final char notANumber[] = { 'N', 'a', 'N' };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1765
    private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1766
}