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
18package java.lang;
19
20import libcore.math.MathUtils;
21
22final 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