Home | History | Annotate | Download | only in lang
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.lang;
     19 
     20 import libcore.math.MathUtils;
     21 
     22 final class RealToString {
     23     private static final ThreadLocal<RealToString> INSTANCE = new ThreadLocal<RealToString>() {
     24         @Override protected RealToString initialValue() {
     25             return new RealToString();
     26         }
     27     };
     28 
     29     private static final double invLogOfTenBaseTwo = Math.log(2.0) / Math.log(10.0);
     30 
     31     private int firstK;
     32 
     33     /**
     34      * An array of decimal digits, filled by longDigitGenerator or bigIntDigitGenerator.
     35      */
     36     private final int[] digits = new int[64];
     37 
     38     /**
     39      * Number of valid entries in 'digits'.
     40      */
     41     private int digitCount;
     42 
     43     private RealToString() {
     44     }
     45 
     46     public static RealToString getInstance() {
     47         return INSTANCE.get();
     48     }
     49 
     50     private static String resultOrSideEffect(AbstractStringBuilder sb, String s) {
     51         if (sb != null) {
     52             sb.append0(s);
     53             return null;
     54         }
     55         return s;
     56     }
     57 
     58     public String doubleToString(double d) {
     59         return convertDouble(null, d);
     60     }
     61 
     62     public void appendDouble(AbstractStringBuilder sb, double d) {
     63         convertDouble(sb, d);
     64     }
     65 
     66     private String convertDouble(AbstractStringBuilder sb, double inputNumber) {
     67         long inputNumberBits = Double.doubleToRawLongBits(inputNumber);
     68         boolean positive = (inputNumberBits & Double.SIGN_MASK) == 0;
     69         int e = (int) ((inputNumberBits & Double.EXPONENT_MASK) >> Double.MANTISSA_BITS);
     70         long f = inputNumberBits & Double.MANTISSA_MASK;
     71         boolean mantissaIsZero = f == 0;
     72 
     73         String quickResult = null;
     74         if (e == 2047) {
     75             if (mantissaIsZero) {
     76                 quickResult = positive ? "Infinity" : "-Infinity";
     77             } else {
     78                 quickResult = "NaN";
     79             }
     80         } else if (e == 0) {
     81             if (mantissaIsZero) {
     82                 quickResult = positive ? "0.0" : "-0.0";
     83             } else if (f == 1) {
     84                 // special case to increase precision even though 2 * Double.MIN_VALUE is 1.0e-323
     85                 quickResult = positive ? "4.9E-324" : "-4.9E-324";
     86             }
     87         }
     88         if (quickResult != null) {
     89             return resultOrSideEffect(sb, quickResult);
     90         }
     91 
     92         int p = Double.EXPONENT_BIAS + Double.MANTISSA_BITS; // the power offset (precision)
     93         int pow;
     94         int numBits = Double.MANTISSA_BITS;
     95         if (e == 0) {
     96             pow = 1 - p; // a denormalized number
     97             long ff = f;
     98             while ((ff & 0x0010000000000000L) == 0) {
     99                 ff = ff << 1;
    100                 numBits--;
    101             }
    102         } else {
    103             // 0 < e < 2047
    104             // a "normalized" number
    105             f = f | 0x0010000000000000L;
    106             pow = e - p;
    107         }
    108 
    109         firstK = digitCount = 0;
    110         if (-59 < pow && pow < 6 || (pow == -59 && !mantissaIsZero)) {
    111             longDigitGenerator(f, pow, e == 0, mantissaIsZero, numBits);
    112         } else {
    113             bigIntDigitGenerator(f, pow, e == 0, numBits);
    114         }
    115         AbstractStringBuilder dst = (sb != null) ? sb : new StringBuilder(26);
    116         if (inputNumber >= 1e7D || inputNumber <= -1e7D
    117                 || (inputNumber > -1e-3D && inputNumber < 1e-3D)) {
    118             freeFormatExponential(dst, positive);
    119         } else {
    120             freeFormat(dst, positive);
    121         }
    122         return (sb != null) ? null : dst.toString();
    123     }
    124 
    125     public String floatToString(float f) {
    126         return convertFloat(null, f);
    127     }
    128 
    129     public void appendFloat(AbstractStringBuilder sb, float f) {
    130         convertFloat(sb, f);
    131     }
    132 
    133     public String convertFloat(AbstractStringBuilder sb, float inputNumber) {
    134         int inputNumberBits = Float.floatToRawIntBits(inputNumber);
    135         boolean positive = (inputNumberBits & Float.SIGN_MASK) == 0;
    136         int e = (inputNumberBits & Float.EXPONENT_MASK) >> Float.MANTISSA_BITS;
    137         int f = inputNumberBits & Float.MANTISSA_MASK;
    138         boolean mantissaIsZero = f == 0;
    139 
    140         String quickResult = null;
    141         if (e == 255) {
    142             if (mantissaIsZero) {
    143                 quickResult = positive ? "Infinity" : "-Infinity";
    144             } else {
    145                 quickResult = "NaN";
    146             }
    147         } else if (e == 0 && mantissaIsZero) {
    148             quickResult = positive ? "0.0" : "-0.0";
    149         }
    150         if (quickResult != null) {
    151             return resultOrSideEffect(sb, quickResult);
    152         }
    153 
    154         int p = Float.EXPONENT_BIAS + Float.MANTISSA_BITS; // the power offset (precision)
    155         int pow;
    156         int numBits = Float.MANTISSA_BITS;
    157         if (e == 0) {
    158             pow = 1 - p; // a denormalized number
    159             if (f < 8) { // want more precision with smallest values
    160                 f = f << 2;
    161                 pow -= 2;
    162             }
    163             int ff = f;
    164             while ((ff & 0x00800000) == 0) {
    165                 ff = ff << 1;
    166                 numBits--;
    167             }
    168         } else {
    169             // 0 < e < 255
    170             // a "normalized" number
    171             f = f | 0x00800000;
    172             pow = e - p;
    173         }
    174 
    175         firstK = digitCount = 0;
    176         if (-59 < pow && pow < 35 || (pow == -59 && !mantissaIsZero)) {
    177             longDigitGenerator(f, pow, e == 0, mantissaIsZero, numBits);
    178         } else {
    179             bigIntDigitGenerator(f, pow, e == 0, numBits);
    180         }
    181         AbstractStringBuilder dst = (sb != null) ? sb : new StringBuilder(26);
    182         if (inputNumber >= 1e7f || inputNumber <= -1e7f
    183                 || (inputNumber > -1e-3f && inputNumber < 1e-3f)) {
    184             freeFormatExponential(dst, positive);
    185         } else {
    186             freeFormat(dst, positive);
    187         }
    188         return (sb != null) ? null : dst.toString();
    189     }
    190 
    191     private void freeFormatExponential(AbstractStringBuilder sb, boolean positive) {
    192         int digitIndex = 0;
    193         if (!positive) {
    194             sb.append0('-');
    195         }
    196         sb.append0((char) ('0' + digits[digitIndex++]));
    197         sb.append0('.');
    198 
    199         int k = firstK;
    200         int exponent = k;
    201         while (true) {
    202             k--;
    203             if (digitIndex >= digitCount) {
    204                 break;
    205             }
    206             sb.append0((char) ('0' + digits[digitIndex++]));
    207         }
    208 
    209         if (k == exponent - 1) {
    210             sb.append0('0');
    211         }
    212         sb.append0('E');
    213         IntegralToString.appendInt(sb, exponent);
    214     }
    215 
    216     private void freeFormat(AbstractStringBuilder sb, boolean positive) {
    217         int digitIndex = 0;
    218         if (!positive) {
    219             sb.append0('-');
    220         }
    221         int k = firstK;
    222         if (k < 0) {
    223             sb.append0('0');
    224             sb.append0('.');
    225             for (int i = k + 1; i < 0; ++i) {
    226                 sb.append0('0');
    227             }
    228         }
    229         int U = digits[digitIndex++];
    230         do {
    231             if (U != -1) {
    232                 sb.append0((char) ('0' + U));
    233             } else if (k >= -1) {
    234                 sb.append0('0');
    235             }
    236             if (k == 0) {
    237                 sb.append0('.');
    238             }
    239             k--;
    240             U = digitIndex < digitCount ? digits[digitIndex++] : -1;
    241         } while (U != -1 || k >= -1);
    242     }
    243 
    244     private native void bigIntDigitGenerator(long f, int e, boolean isDenormalized, int p);
    245 
    246     private void longDigitGenerator(long f, int e, boolean isDenormalized,
    247             boolean mantissaIsZero, int p) {
    248         long R, S, M;
    249         if (e >= 0) {
    250             M = 1l << e;
    251             if (!mantissaIsZero) {
    252                 R = f << (e + 1);
    253                 S = 2;
    254             } else {
    255                 R = f << (e + 2);
    256                 S = 4;
    257             }
    258         } else {
    259             M = 1;
    260             if (isDenormalized || !mantissaIsZero) {
    261                 R = f << 1;
    262                 S = 1l << (1 - e);
    263             } else {
    264                 R = f << 2;
    265                 S = 1l << (2 - e);
    266             }
    267         }
    268 
    269         int k = (int) Math.ceil((e + p - 1) * invLogOfTenBaseTwo - 1e-10);
    270 
    271         if (k > 0) {
    272             S = S * MathUtils.LONG_POWERS_OF_TEN[k];
    273         } else if (k < 0) {
    274             long scale = MathUtils.LONG_POWERS_OF_TEN[-k];
    275             R = R * scale;
    276             M = M == 1 ? scale : M * scale;
    277         }
    278 
    279         if (R + M > S) { // was M_plus
    280             firstK = k;
    281         } else {
    282             firstK = k - 1;
    283             R = R * 10;
    284             M = M * 10;
    285         }
    286 
    287         boolean low, high;
    288         int U;
    289         while (true) {
    290             // Set U to floor(R/S) and R to the remainder, using *unsigned* 64-bit division
    291             U = 0;
    292             for (int i = 3; i >= 0; i--) {
    293                 long remainder = R - (S << i);
    294                 if (remainder >= 0) {
    295                     R = remainder;
    296                     U += 1 << i;
    297                 }
    298             }
    299 
    300             low = R < M; // was M_minus
    301             high = R + M > S; // was M_plus
    302 
    303             if (low || high) {
    304                 break;
    305             }
    306             R = R * 10;
    307             M = M * 10;
    308             digits[digitCount++] = U;
    309         }
    310         if (low && !high) {
    311             digits[digitCount++] = U;
    312         } else if (high && !low) {
    313             digits[digitCount++] = U + 1;
    314         } else if ((R << 1) < S) {
    315             digits[digitCount++] = U;
    316         } else {
    317             digits[digitCount++] = U + 1;
    318         }
    319     }
    320 }
    321