1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughespackage java.lang; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughesimport libcore.math.MathUtils; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 22706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughesfinal class RealToString { 2330ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes private static final ThreadLocal<RealToString> INSTANCE = new ThreadLocal<RealToString>() { 2430ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes @Override protected RealToString initialValue() { 2530ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes return new RealToString(); 2630ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes } 2730ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes }; 2830ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes 2930ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes private static final double invLogOfTenBaseTwo = Math.log(2.0) / Math.log(10.0); 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3110a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes private int firstK; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3310a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes /** 3410a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes * An array of decimal digits, filled by longDigitGenerator or bigIntDigitGenerator. 3510a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes */ 3610a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes private final int[] digits = new int[64]; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3810a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes /** 3910a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes * Number of valid entries in 'digits'. 4010a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes */ 4110a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes private int digitCount; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4310a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes private RealToString() { 4410a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes } 4510a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes 4610a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes public static RealToString getInstance() { 4710a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes return INSTANCE.get(); 4810a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes } 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 50620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes private static String resultOrSideEffect(AbstractStringBuilder sb, String s) { 51620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes if (sb != null) { 52620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0(s); 53620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes return null; 54620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 55620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes return s; 56620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 57620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes 58620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes public String doubleToString(double d) { 59620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes return convertDouble(null, d); 60620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 61620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes 62620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes public void appendDouble(AbstractStringBuilder sb, double d) { 63620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes convertDouble(sb, d); 64620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 65620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes 66620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes private String convertDouble(AbstractStringBuilder sb, double inputNumber) { 6710a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes long inputNumberBits = Double.doubleToRawLongBits(inputNumber); 68706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes boolean positive = (inputNumberBits & Double.SIGN_MASK) == 0; 69706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes int e = (int) ((inputNumberBits & Double.EXPONENT_MASK) >> Double.MANTISSA_BITS); 70706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes long f = inputNumberBits & Double.MANTISSA_MASK; 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean mantissaIsZero = f == 0; 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 73620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes String quickResult = null; 74706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (e == 2047) { 75620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes if (mantissaIsZero) { 76620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes quickResult = positive ? "Infinity" : "-Infinity"; 77620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } else { 78620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes quickResult = "NaN"; 79620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 80620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } else if (e == 0) { 81620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes if (mantissaIsZero) { 82620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes quickResult = positive ? "0.0" : "-0.0"; 83620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } else if (f == 1) { 84620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes // special case to increase precision even though 2 * Double.MIN_VALUE is 1.0e-323 85620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes quickResult = positive ? "4.9E-324" : "-4.9E-324"; 86706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 87706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 88620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes if (quickResult != null) { 89620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes return resultOrSideEffect(sb, quickResult); 90620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 91620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes 92706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes int p = Double.EXPONENT_BIAS + Double.MANTISSA_BITS; // the power offset (precision) 9330ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes int pow; 9430ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes int numBits = Double.MANTISSA_BITS; 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (e == 0) { 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pow = 1 - p; // a denormalized number 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long ff = f; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((ff & 0x0010000000000000L) == 0) { 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ff = ff << 1; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project numBits--; 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 0 < e < 2047 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // a "normalized" number 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project f = f | 0x0010000000000000L; 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pow = e - p; 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 10910a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes firstK = digitCount = 0; 110706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (-59 < pow && pow < 6 || (pow == -59 && !mantissaIsZero)) { 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project longDigitGenerator(f, pow, e == 0, mantissaIsZero, numBits); 112706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } else { 113706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes bigIntDigitGenerator(f, pow, e == 0, numBits); 114706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 115620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes AbstractStringBuilder dst = (sb != null) ? sb : new StringBuilder(26); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (inputNumber >= 1e7D || inputNumber <= -1e7D 117706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes || (inputNumber > -1e-3D && inputNumber < 1e-3D)) { 118620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes freeFormatExponential(dst, positive); 119620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } else { 120620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes freeFormat(dst, positive); 121706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 122620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes return (sb != null) ? null : dst.toString(); 123620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 124620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes 125620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes public String floatToString(float f) { 126620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes return convertFloat(null, f); 127620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 128620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes 129620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes public void appendFloat(AbstractStringBuilder sb, float f) { 130620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes convertFloat(sb, f); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 133620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes public String convertFloat(AbstractStringBuilder sb, float inputNumber) { 13410a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes int inputNumberBits = Float.floatToRawIntBits(inputNumber); 135706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes boolean positive = (inputNumberBits & Float.SIGN_MASK) == 0; 136706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes int e = (inputNumberBits & Float.EXPONENT_MASK) >> Float.MANTISSA_BITS; 137706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes int f = inputNumberBits & Float.MANTISSA_MASK; 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean mantissaIsZero = f == 0; 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 140620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes String quickResult = null; 141706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (e == 255) { 142620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes if (mantissaIsZero) { 143620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes quickResult = positive ? "Infinity" : "-Infinity"; 144620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } else { 145620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes quickResult = "NaN"; 146706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 147620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } else if (e == 0 && mantissaIsZero) { 148620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes quickResult = positive ? "0.0" : "-0.0"; 149620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } 150620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes if (quickResult != null) { 151620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes return resultOrSideEffect(sb, quickResult); 152706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 153620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes 154706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes int p = Float.EXPONENT_BIAS + Float.MANTISSA_BITS; // the power offset (precision) 15530ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes int pow; 15630ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes int numBits = Float.MANTISSA_BITS; 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (e == 0) { 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pow = 1 - p; // a denormalized number 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (f < 8) { // want more precision with smallest values 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project f = f << 2; 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pow -= 2; 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int ff = f; 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((ff & 0x00800000) == 0) { 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ff = ff << 1; 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project numBits--; 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 0 < e < 255 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // a "normalized" number 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project f = f | 0x00800000; 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pow = e - p; 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17510a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes firstK = digitCount = 0; 176706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (-59 < pow && pow < 35 || (pow == -59 && !mantissaIsZero)) { 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project longDigitGenerator(f, pow, e == 0, mantissaIsZero, numBits); 178706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } else { 179706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes bigIntDigitGenerator(f, pow, e == 0, numBits); 180706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 181620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes AbstractStringBuilder dst = (sb != null) ? sb : new StringBuilder(26); 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (inputNumber >= 1e7f || inputNumber <= -1e7f 183706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes || (inputNumber > -1e-3f && inputNumber < 1e-3f)) { 184620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes freeFormatExponential(dst, positive); 185620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes } else { 186620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes freeFormat(dst, positive); 187706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 188620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes return (sb != null) ? null : dst.toString(); 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 191620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes private void freeFormatExponential(AbstractStringBuilder sb, boolean positive) { 19210a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes int digitIndex = 0; 193706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (!positive) { 194620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('-'); 195706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 196620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0((char) ('0' + digits[digitIndex++])); 197620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('.'); 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int k = firstK; 20010a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes int exponent = k; 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project k--; 20310a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes if (digitIndex >= digitCount) { 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 205706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 206620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0((char) ('0' + digits[digitIndex++])); 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20910a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes if (k == exponent - 1) { 210620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('0'); 211706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 212620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('E'); 213620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes IntegralToString.appendInt(sb, exponent); 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 216620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes private void freeFormat(AbstractStringBuilder sb, boolean positive) { 21710a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes int digitIndex = 0; 218706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (!positive) { 219620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('-'); 220706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int k = firstK; 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (k < 0) { 223620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('0'); 224620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('.'); 225706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes for (int i = k + 1; i < 0; ++i) { 226620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('0'); 227706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 22910a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes int U = digits[digitIndex++]; 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project do { 231706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (U != -1) { 232620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0((char) ('0' + U)); 233706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } else if (k >= -1) { 234620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('0'); 235706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 236706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (k == 0) { 237620666783267ed3a6f7f2b4309a66f1c1f18de53Elliott Hughes sb.append0('.'); 238706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project k--; 24010a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes U = digitIndex < digitCount ? digits[digitIndex++] : -1; 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } while (U != -1 || k >= -1); 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 244706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes private native void bigIntDigitGenerator(long f, int e, boolean isDenormalized, int p); 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void longDigitGenerator(long f, int e, boolean isDenormalized, 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean mantissaIsZero, int p) { 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long R, S, M; 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (e >= 0) { 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project M = 1l << e; 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!mantissaIsZero) { 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project R = f << (e + 1); 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project S = 2; 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project R = f << (e + 2); 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project S = 4; 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project M = 1; 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isDenormalized || !mantissaIsZero) { 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project R = f << 1; 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project S = 1l << (1 - e); 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project R = f << 2; 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project S = 1l << (2 - e); 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int k = (int) Math.ceil((e + p - 1) * invLogOfTenBaseTwo - 1e-10); 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (k > 0) { 272706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes S = S * MathUtils.LONG_POWERS_OF_TEN[k]; 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (k < 0) { 274706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes long scale = MathUtils.LONG_POWERS_OF_TEN[-k]; 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project R = R * scale; 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project M = M == 1 ? scale : M * scale; 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (R + M > S) { // was M_plus 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project firstK = k; 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project firstK = k - 1; 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project R = R * 10; 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project M = M * 10; 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean low, high; 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int U; 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 29030ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes // Set U to floor(R/S) and R to the remainder, using *unsigned* 64-bit division 29130ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes U = 0; 29230ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes for (int i = 3; i >= 0; i--) { 29330ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes long remainder = R - (S << i); 29430ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes if (remainder >= 0) { 29530ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes R = remainder; 29630ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes U += 1 << i; 29730ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes } 29830ae871abe462723f78b2981178a9d5a73f5e129Elliott Hughes } 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project low = R < M; // was M_minus 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project high = R + M > S; // was M_plus 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 303706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (low || high) { 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 305706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project R = R * 10; 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project M = M * 10; 30810a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes digits[digitCount++] = U; 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 310706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes if (low && !high) { 31110a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes digits[digitCount++] = U; 312706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } else if (high && !low) { 31310a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes digits[digitCount++] = U + 1; 314706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } else if ((R << 1) < S) { 31510a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes digits[digitCount++] = U; 316706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } else { 31710a17e23b22dc0ff6363d15bce67d668b6d44dd0Elliott Hughes digits[digitCount++] = U + 1; 318706de1164836051ab31cc69eb77a6bba1a723896Elliott Hughes } 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 321