151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
2694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.misc;
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniakimport java.util.Arrays;
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class FormattedFloatingDecimal{
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
36694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        FloatingDecimal.BinaryToASCIIConverter fdConverter =
37694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
38694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        return new FormattedFloatingDecimal(precision,form, fdConverter);
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private int decExponentRounded;
42694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private char[] mantissa;
43694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private char[] exponent;
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private static final ThreadLocal<Object> threadLocalCharBuffer =
46694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            new ThreadLocal<Object>() {
47694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                @Override
48694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                protected Object initialValue() {
49694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    return new char[20];
50694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                }
51694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            };
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private static char[] getBuffer(){
54694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        return (char[]) threadLocalCharBuffer.get();
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
58694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (fdConverter.isExceptional()) {
59694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            this.mantissa = fdConverter.toJavaFormatString().toCharArray();
60694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            this.exponent = null;
61694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            return;
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
63694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        char[] digits = getBuffer();
64694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int nDigits = fdConverter.getDigits(digits);
65694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int decExp = fdConverter.getDecimalExponent();
66694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int exp;
67694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        boolean isNegative = fdConverter.isNegative();
68694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        switch (form) {
69694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            case COMPATIBLE:
70694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exp = decExp;
71694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                this.decExponentRounded = exp;
72694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                fillCompatible(precision, digits, nDigits, exp, isNegative);
73694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                break;
74694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            case DECIMAL_FLOAT:
75694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
76694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                fillDecimal(precision, digits, nDigits, exp, isNegative);
77694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                this.decExponentRounded = exp;
78694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                break;
79694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            case SCIENTIFIC:
80694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exp = applyPrecision(decExp, digits, nDigits, precision + 1);
81694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                fillScientific(precision, digits, nDigits, exp, isNegative);
82694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                this.decExponentRounded = exp;
83694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                break;
84694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            case GENERAL:
85694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exp = applyPrecision(decExp, digits, nDigits, precision);
86694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // adjust precision to be the number of digits to right of decimal
87694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // the real exponent to be output is actually exp - 1, not exp
88694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                if (exp - 1 < -4 || exp - 1 >= precision) {
89694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    // form = Form.SCIENTIFIC;
90694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    precision--;
91694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    fillScientific(precision, digits, nDigits, exp, isNegative);
92694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                } else {
93694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    // form = Form.DECIMAL_FLOAT;
94694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    precision = precision - exp;
95694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    fillDecimal(precision, digits, nDigits, exp, isNegative);
96694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                }
97694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                this.decExponentRounded = exp;
98694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                break;
99694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            default:
100694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                assert false;
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
104694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    // returns the exponent after rounding has been done by applyPrecision
105694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    public int getExponentRounded() {
106694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        return decExponentRounded - 1;
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
109694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    public char[] getMantissa(){
110694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        return mantissa;
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
113694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    public char[] getExponent(){
114694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        return exponent;
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
117694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    /**
118694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak     * Returns new decExp in case of overflow.
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
120694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
121694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (prec >= nDigits || prec < 0) {
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // no rounding necessary
123694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            return decExp;
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
125694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (prec == 0) {
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // only one digit (0 or 1) is returned because the precision
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // excludes all significant digits
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (digits[0] >= '5') {
129694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                digits[0] = '1';
130694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                Arrays.fill(digits, 1, nDigits, '0');
131694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                return decExp + 1;
132694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            } else {
133694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                Arrays.fill(digits, 0, nDigits, '0');
134694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                return decExp;
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
137694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int q = digits[prec];
138694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (q >= '5') {
139694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            int i = prec;
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            q = digits[--i];
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ( q == '9' ) {
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while ( q == '9' && i > 0 ){
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    q = digits[--i];
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if ( q == '9' ){
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // carryout! High-order 1, rest 0s, larger exp.
147694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    digits[0] = '1';
148694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    Arrays.fill(digits, 1, nDigits, '0');
149694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    return decExp+1;
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
152694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            digits[i] = (char)(q + 1);
153694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            Arrays.fill(digits, i+1, nDigits, '0');
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
155694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            Arrays.fill(digits, prec, nDigits, '0');
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
157694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        return decExp;
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
160694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    /**
161694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak     * Fills mantissa and exponent char arrays for compatible format.
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
163694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
164694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int startIndex = isNegative ? 1 : 0;
165694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (exp > 0 && exp < 8) {
166694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            // print digits.digits.
167694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            if (nDigits < exp) {
168694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                int extraZeros = exp - nDigits;
169694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, nDigits + extraZeros + 2);
170694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
171694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
172694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + nDigits + extraZeros] = '.';
173694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + nDigits + extraZeros+1] = '0';
174694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            } else if (exp < nDigits) {
175694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                int t = Math.min(nDigits - exp, precision);
176694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, exp + 1 + t);
177694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, 0, mantissa, startIndex, exp);
178694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + exp ] = '.';
179694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
180694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            } else { // exp == digits.length
181694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, nDigits + 2);
182694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
183694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + nDigits ] = '.';
184694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + nDigits +1] = '0';
185694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            }
186694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        } else if (exp <= 0 && exp > -3) {
187694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            int zeros = Math.max(0, Math.min(-exp, precision));
188694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            int t = Math.max(0, Math.min(nDigits, precision + exp));
189694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            // write '0' s before the significant digits
190694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            if (zeros > 0) {
191694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, zeros + 2 + t);
192694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex] = '0';
193694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex+1] = '.';
194694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
195694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                if (t > 0) {
196694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    // copy only when significant digits are within the precision
197694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
199694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            } else if (t > 0) {
200694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, zeros + 2 + t);
201694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex] = '0';
202694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + 1] = '.';
203694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // copy only when significant digits are within the precision
204694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
206694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                this.mantissa = create(isNegative, 1);
207694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                this.mantissa[startIndex] = '0';
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
210694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            if (nDigits > 1) {
211694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, nDigits + 1);
212694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex] = digits[0];
213694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + 1] = '.';
214694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
216694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, 3);
217694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex] = digits[0];
218694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + 1] = '.';
219694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + 2] = '0';
220694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            }
221694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            int e, expStartIntex;
222694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            boolean isNegExp = (exp <= 0);
223694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            if (isNegExp) {
224694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                e = -exp + 1;
225694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                expStartIntex = 1;
226694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            } else {
227694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                e = exp - 1;
228694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                expStartIntex = 0;
229694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            }
230694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            // decExponent has 1, 2, or 3, digits
231694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            if (e <= 9) {
232694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent = create(isNegExp,1);
233694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent[expStartIntex] = (char) (e + '0');
234694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            } else if (e <= 99) {
235694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent = create(isNegExp,2);
236694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent[expStartIntex] = (char) (e / 10 + '0');
237694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent[expStartIntex+1] = (char) (e % 10 + '0');
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
239694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent = create(isNegExp,3);
240694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent[expStartIntex] = (char) (e / 100 + '0');
241694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                e %= 100;
242694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent[expStartIntex+1] = (char) (e / 10 + '0');
243694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                exponent[expStartIntex+2] = (char) (e % 10 + '0');
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
248694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private static char[] create(boolean isNegative, int size) {
249694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if(isNegative) {
250694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            char[] r = new char[size +1];
251694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            r[0] = '-';
252694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            return r;
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
254694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            return new char[size];
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
258694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    /*
259694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak     * Fills mantissa char arrays for DECIMAL_FLOAT format.
260694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak     * Exponent should be equal to null.
261694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak     */
262694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
263694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int startIndex = isNegative ? 1 : 0;
264694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (exp > 0) {
265694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            // print digits.digits.
266694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            if (nDigits < exp) {
267694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative,exp);
268694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
269694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
270694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // Do not append ".0" for formatted floats since the user
271694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // may request that it be omitted. It is added as necessary
272694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // by the Formatter.
273694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            } else {
274694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                int t = Math.min(nDigits - exp, precision);
275694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
276694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, 0, mantissa, startIndex, exp);
277694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // Do not append ".0" for formatted floats since the user
278694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // may request that it be omitted. It is added as necessary
279694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // by the Formatter.
280694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                if (t > 0) {
281694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    mantissa[startIndex + exp] = '.';
282694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
285694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        } else if (exp <= 0) {
286694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            int zeros = Math.max(0, Math.min(-exp, precision));
287694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            int t = Math.max(0, Math.min(nDigits, precision + exp));
288694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            // write '0' s before the significant digits
289694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            if (zeros > 0) {
290694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, zeros + 2 + t);
291694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex] = '0';
292694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex+1] = '.';
293694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (t > 0) {
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // copy only when significant digits are within the precision
296694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
298694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            } else if (t > 0) {
299694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa = create(isNegative, zeros + 2 + t);
300694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex] = '0';
301694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                mantissa[startIndex + 1] = '.';
302694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                // copy only when significant digits are within the precision
303694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
305694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                this.mantissa = create(isNegative, 1);
306694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                this.mantissa[startIndex] = '0';
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
311694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    /**
312694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak     * Fills mantissa and exponent char arrays for SCIENTIFIC format.
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
314694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak    private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
315694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int startIndex = isNegative ? 1 : 0;
316694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int t = Math.max(0, Math.min(nDigits - 1, precision));
317694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (t > 0) {
318694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            mantissa = create(isNegative, t + 2);
319694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            mantissa[startIndex] = digits[0];
320694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            mantissa[startIndex + 1] = '.';
321694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
322694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        } else {
323694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            mantissa = create(isNegative, 1);
324694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            mantissa[startIndex] = digits[0];
325694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        }
326694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        char expSign;
327694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        int e;
328694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (exp <= 0) {
329694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            expSign = '-';
330694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            e = -exp + 1;
331694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        } else {
332694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            expSign = '+' ;
333694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            e = exp - 1;
334694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        }
335694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        // decExponent has 1, 2, or 3, digits
336694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        if (e <= 9) {
337694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            exponent = new char[] { expSign,
338694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    '0', (char) (e + '0') };
339694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        } else if (e <= 99) {
340694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            exponent = new char[] { expSign,
341694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    (char) (e / 10 + '0'), (char) (e % 10 + '0') };
342694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak        } else {
343694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            char hiExpChar = (char) (e / 100 + '0');
344694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            e %= 100;
345694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak            exponent = new char[] { expSign,
346694e617f54a7bfbdad24913ce96f5d56f1a1960aPrzemyslaw Szczepaniak                    hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
350