001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.luni.util;
019:
020: public final class NumberConverter {
021:
022: private int setCount; // number of times u and k have been gotten
023:
024: private int getCount; // number of times u and k have been set
025:
026: private int[] uArray = new int[64];
027:
028: private int firstK;
029:
030: private final static double invLogOfTenBaseTwo = Math.log(2.0)
031: / Math.log(10.0);
032:
033: private final static long[] TEN_TO_THE = new long[20];
034:
035: static {
036: TEN_TO_THE[0] = 1L;
037: for (int i = 1; i < TEN_TO_THE.length; ++i) {
038: long previous = TEN_TO_THE[i - 1];
039: TEN_TO_THE[i] = (previous << 1) + (previous << 3);
040: }
041: }
042:
043: private static NumberConverter getConverter() {
044: return new NumberConverter();
045: }
046:
047: public static String convert(double input) {
048: return getConverter().convertD(input);
049: }
050:
051: public static String convert(float input) {
052: return getConverter().convertF(input);
053: }
054:
055: public String convertD(double inputNumber) {
056: int p = 1023 + 52; // the power offset (precision)
057: long signMask = 0x8000000000000000L; // the mask to get the sign of
058: // the number
059: long eMask = 0x7FF0000000000000L; // the mask to get the power bits
060: long fMask = 0x000FFFFFFFFFFFFFL; // the mask to get the significand
061: // bits
062:
063: long inputNumberBits = Double.doubleToLongBits(inputNumber);
064: // the value of the sign... 0 is positive, ~0 is negative
065: String signString = (inputNumberBits & signMask) == 0 ? ""
066: : "-";
067: // the value of the 'power bits' of the inputNumber
068: int e = (int) ((inputNumberBits & eMask) >> 52);
069: // the value of the 'significand bits' of the inputNumber
070: long f = inputNumberBits & fMask;
071: boolean mantissaIsZero = f == 0;
072: int pow = 0, numBits = 52;
073:
074: if (e == 2047)
075: return mantissaIsZero ? signString + "Infinity" : "NaN";
076: if (e == 0) {
077: if (mantissaIsZero)
078: return signString + "0.0";
079: if (f == 1)
080: // special case to increase precision even though 2 *
081: // Double.MIN_VALUE is 1.0e-323
082: return signString + "4.9E-324";
083: pow = 1 - p; // a denormalized number
084: long ff = f;
085: while ((ff & 0x0010000000000000L) == 0) {
086: ff = ff << 1;
087: numBits--;
088: }
089: } else {
090: // 0 < e < 2047
091: // a "normalized" number
092: f = f | 0x0010000000000000L;
093: pow = e - p;
094: }
095:
096: if (-59 < pow && pow < 6 || (pow == -59 && !mantissaIsZero))
097: longDigitGenerator(f, pow, e == 0, mantissaIsZero, numBits);
098: else
099: bigIntDigitGeneratorInstImpl(f, pow, e == 0,
100: mantissaIsZero, numBits);
101:
102: if (inputNumber >= 1e7D || inputNumber <= -1e7D
103: || (inputNumber > -1e-3D && inputNumber < 1e-3D))
104: return signString + freeFormatExponential();
105:
106: return signString + freeFormat();
107: }
108:
109: public String convertF(float inputNumber) {
110: int p = 127 + 23; // the power offset (precision)
111: int signMask = 0x80000000; // the mask to get the sign of the number
112: int eMask = 0x7F800000; // the mask to get the power bits
113: int fMask = 0x007FFFFF; // the mask to get the significand bits
114:
115: int inputNumberBits = Float.floatToIntBits(inputNumber);
116: // the value of the sign... 0 is positive, ~0 is negative
117: String signString = (inputNumberBits & signMask) == 0 ? ""
118: : "-";
119: // the value of the 'power bits' of the inputNumber
120: int e = (inputNumberBits & eMask) >> 23;
121: // the value of the 'significand bits' of the inputNumber
122: int f = inputNumberBits & fMask;
123: boolean mantissaIsZero = f == 0;
124: int pow = 0, numBits = 23;
125:
126: if (e == 255)
127: return mantissaIsZero ? signString + "Infinity" : "NaN";
128: if (e == 0) {
129: if (mantissaIsZero)
130: return signString + "0.0";
131: pow = 1 - p; // a denormalized number
132: if (f < 8) { // want more precision with smallest values
133: f = f << 2;
134: pow -= 2;
135: }
136: int ff = f;
137: while ((ff & 0x00800000) == 0) {
138: ff = ff << 1;
139: numBits--;
140: }
141: } else {
142: // 0 < e < 255
143: // a "normalized" number
144: f = f | 0x00800000;
145: pow = e - p;
146: }
147:
148: if (-59 < pow && pow < 35 || (pow == -59 && !mantissaIsZero))
149: longDigitGenerator(f, pow, e == 0, mantissaIsZero, numBits);
150: else
151: bigIntDigitGeneratorInstImpl(f, pow, e == 0,
152: mantissaIsZero, numBits);
153: if (inputNumber >= 1e7f || inputNumber <= -1e7f
154: || (inputNumber > -1e-3f && inputNumber < 1e-3f))
155: return signString + freeFormatExponential();
156:
157: return signString + freeFormat();
158: }
159:
160: private String freeFormatExponential() {
161: // corresponds to process "Free-Format Exponential"
162: char[] formattedDecimal = new char[25];
163: formattedDecimal[0] = (char) ('0' + uArray[getCount++]);
164: formattedDecimal[1] = '.';
165: // the position the next character is to be inserted into
166: // formattedDecimal
167: int charPos = 2;
168:
169: int k = firstK;
170: int expt = k;
171: while (true) {
172: k--;
173: if (getCount >= setCount)
174: break;
175:
176: formattedDecimal[charPos++] = (char) ('0' + uArray[getCount++]);
177: }
178:
179: if (k == expt - 1)
180: formattedDecimal[charPos++] = '0';
181: formattedDecimal[charPos++] = 'E';
182: return new String(formattedDecimal, 0, charPos)
183: + Integer.toString(expt);
184: }
185:
186: private String freeFormat() {
187: // corresponds to process "Free-Format"
188: char[] formattedDecimal = new char[25];
189: // the position the next character is to be inserted into
190: // formattedDecimal
191: int charPos = 0;
192: int k = firstK;
193: if (k < 0) {
194: formattedDecimal[0] = '0';
195: formattedDecimal[1] = '.';
196: charPos += 2;
197: for (int i = k + 1; i < 0; i++)
198: formattedDecimal[charPos++] = '0';
199: }
200:
201: int U = uArray[getCount++];
202: do {
203: if (U != -1)
204: formattedDecimal[charPos++] = (char) ('0' + U);
205: else if (k >= -1)
206: formattedDecimal[charPos++] = '0';
207:
208: if (k == 0)
209: formattedDecimal[charPos++] = '.';
210:
211: k--;
212: U = getCount < setCount ? uArray[getCount++] : -1;
213: } while (U != -1 || k >= -1);
214: return new String(formattedDecimal, 0, charPos);
215: }
216:
217: private native void bigIntDigitGeneratorInstImpl(long f, int e,
218: boolean isDenormalized, boolean mantissaIsZero, int p);
219:
220: private void longDigitGenerator(long f, int e,
221: boolean isDenormalized, boolean mantissaIsZero, int p) {
222: long R, S, M;
223: if (e >= 0) {
224: M = 1l << e;
225: if (!mantissaIsZero) {
226: R = f << (e + 1);
227: S = 2;
228: } else {
229: R = f << (e + 2);
230: S = 4;
231: }
232: } else {
233: M = 1;
234: if (isDenormalized || !mantissaIsZero) {
235: R = f << 1;
236: S = 1l << (1 - e);
237: } else {
238: R = f << 2;
239: S = 1l << (2 - e);
240: }
241: }
242:
243: int k = (int) Math.ceil((e + p - 1) * invLogOfTenBaseTwo
244: - 1e-10);
245:
246: if (k > 0) {
247: S = S * TEN_TO_THE[k];
248: } else if (k < 0) {
249: long scale = TEN_TO_THE[-k];
250: R = R * scale;
251: M = M == 1 ? scale : M * scale;
252: }
253:
254: if (R + M > S) { // was M_plus
255: firstK = k;
256: } else {
257: firstK = k - 1;
258: R = R * 10;
259: M = M * 10;
260: }
261:
262: getCount = setCount = 0; // reset indices
263: boolean low, high;
264: int U;
265: long[] Si = new long[] { S, S << 1, S << 2, S << 3 };
266: while (true) {
267: // set U to be floor (R / S) and R to be the remainder
268: // using a kind of "binary search" to find the answer.
269: // It's a lot quicker than actually dividing since we know
270: // the answer will be between 0 and 10
271: U = 0;
272: long remainder;
273: for (int i = 3; i >= 0; i--) {
274: remainder = R - Si[i];
275: if (remainder >= 0) {
276: R = remainder;
277: U += 1 << i;
278: }
279: }
280:
281: low = R < M; // was M_minus
282: high = R + M > S; // was M_plus
283:
284: if (low || high)
285: break;
286:
287: R = R * 10;
288: M = M * 10;
289: uArray[setCount++] = U;
290: }
291: if (low && !high)
292: uArray[setCount++] = U;
293: else if (high && !low)
294: uArray[setCount++] = U + 1;
295: else if ((R << 1) < S)
296: uArray[setCount++] = U;
297: else
298: uArray[setCount++] = U + 1;
299: }
300: }
|