• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RealToString()43     private RealToString() {
44     }
45 
getInstance()46     public static RealToString getInstance() {
47         return INSTANCE.get();
48     }
49 
resultOrSideEffect(AbstractStringBuilder sb, String s)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 
doubleToString(double d)58     public String doubleToString(double d) {
59         return convertDouble(null, d);
60     }
61 
appendDouble(AbstractStringBuilder sb, double d)62     public void appendDouble(AbstractStringBuilder sb, double d) {
63         convertDouble(sb, d);
64     }
65 
convertDouble(AbstractStringBuilder sb, double inputNumber)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 
floatToString(float f)125     public String floatToString(float f) {
126         return convertFloat(null, f);
127     }
128 
appendFloat(AbstractStringBuilder sb, float f)129     public void appendFloat(AbstractStringBuilder sb, float f) {
130         convertFloat(sb, f);
131     }
132 
convertFloat(AbstractStringBuilder sb, float inputNumber)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 
freeFormatExponential(AbstractStringBuilder sb, boolean positive)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 
freeFormat(AbstractStringBuilder sb, boolean positive)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 
longDigitGenerator(long f, int e, boolean isDenormalized, boolean mantissaIsZero, int p)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