KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > retrotranslator > runtime > format > FloatingPointConversion


1 /***
2  * Retrotranslator: a Java bytecode transformer that translates Java classes
3  * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
4  *
5  * Copyright (c) 2005 - 2007 Taras Puchko
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the copyright holders nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  */

32 package net.sf.retrotranslator.runtime.format;
33
34 import java.math.*;
35 import java.text.DecimalFormatSymbols JavaDoc;
36
37 /**
38  * @author Taras Puchko
39  */

40 abstract class FloatingPointConversion extends NumericConversion {
41
42     protected abstract void printf(FormatContext context, boolean negative, BigDecimal argument);
43
44     protected void printf(FormatContext context) {
45         Object JavaDoc argument = context.getArgument();
46         if (argument instanceof Double JavaDoc) {
47             printf(context, (Double JavaDoc) argument);
48         } else if (argument instanceof Float JavaDoc) {
49             printf(context, (Float JavaDoc) argument);
50         } else if (argument == null) {
51             context.writeRestricted(String.valueOf(argument));
52         } else if (argument instanceof BigDecimal) {
53             BigDecimal bigDecimal = (BigDecimal) argument;
54             printf(context, bigDecimal.signum() < 0, bigDecimal.abs());
55         } else {
56             throw context.getConversionException();
57         }
58     }
59
60     private void printf(FormatContext context, double argument) {
61         if (!printSpecialNumber(context, argument)) {
62             printf(context, Double.doubleToLongBits(argument) < 0, BigDecimal.valueOf(Math.abs(argument)));
63         }
64     }
65
66     protected static void printComputerizedScientificNumber(FormatContext context, boolean negative,
67                                                             BigDecimal argument, int precision) {
68         String JavaDoc unscaled = argument.unscaledValue().toString();
69         StringBuilder JavaDoc builder = new StringBuilder JavaDoc();
70         builder.append(unscaled.charAt(0));
71         if (precision > 0 || context.isFlag('#')) {
72             builder.append('.');
73         }
74         if (precision < unscaled.length()) {
75             builder.append(unscaled.substring(1, precision + 1));
76         } else {
77             builder.append(unscaled.substring(1));
78             appendZeros(builder, precision + 1 - unscaled.length());
79         }
80         int exponent = unscaled.equals("0") ? 0 : unscaled.length() - argument.scale() - 1;
81         builder.append('e').append(exponent < 0 ? '-' : '+');
82         int absoluteExponent = Math.abs(exponent);
83         if (absoluteExponent < 10) {
84             builder.append('0');
85         }
86         builder.append(absoluteExponent);
87         printNumber(context, negative, null, builder, context.getSymbols(false));
88     }
89
90     protected static void printDecimalNumber(FormatContext context, boolean negative,
91                                              BigDecimal argument, boolean localized) {
92         String JavaDoc unscaled = argument.unscaledValue().toString();
93         String JavaDoc integerPart = "0";
94         String JavaDoc fractionPart = "";
95         int separatorIndex = unscaled.length() - argument.scale();
96         if (separatorIndex < 0) {
97             fractionPart = appendZeros(new StringBuilder JavaDoc(), -separatorIndex).append(unscaled).toString();
98         } else if (separatorIndex == 0) {
99             fractionPart = unscaled;
100         } else if (separatorIndex < unscaled.length()) {
101             integerPart = unscaled.substring(0, separatorIndex);
102             fractionPart = unscaled.substring(separatorIndex);
103         } else if (separatorIndex == unscaled.length()) {
104             integerPart = unscaled;
105         } else {
106             integerPart = appendZeros(new StringBuilder JavaDoc(unscaled), separatorIndex - unscaled.length()).toString();
107         }
108         StringBuilder JavaDoc builder = new StringBuilder JavaDoc();
109         DecimalFormatSymbols JavaDoc symbols = context.getSymbols(localized);
110         appendNumber(builder, integerPart, context.isFlag(','), symbols);
111         if (fractionPart.length() > 0 || context.isFlag('#')) {
112             builder.append(symbols.getDecimalSeparator());
113         }
114         appendNumber(builder, fractionPart, false, symbols);
115         printNumber(context, negative, null, builder, symbols);
116     }
117
118     protected static StringBuilder JavaDoc appendZeros(StringBuilder JavaDoc builder, int count) {
119         for (int i = 0; i < count; i++) {
120             builder.append('0');
121         }
122         return builder;
123     }
124
125     protected static BigDecimal round(BigDecimal decimal, int shift) {
126         int scale = decimal.scale() - shift;
127         return scale >= 0 ?
128                 decimal.setScale(scale, BigDecimal.ROUND_HALF_UP) :
129                 decimal.movePointRight(scale).setScale(0, BigDecimal.ROUND_HALF_UP).movePointLeft(scale);
130     }
131
132     public static class ComputerizedScientificConversion extends FloatingPointConversion {
133
134         public void format(FormatContext context) {
135             context.checkFlags();
136             context.assertNoFlag(',');
137             printf(context);
138         }
139
140         protected void printf(FormatContext context, boolean negative, BigDecimal argument) {
141             int shift = argument.unscaledValue().toString().length() - context.getNumberPrecision() - 1;
142             printComputerizedScientificNumber(context, negative, round(argument, shift), context.getNumberPrecision());
143         }
144     }
145
146     public static class DecimalConversion extends FloatingPointConversion {
147
148         public void format(FormatContext context) {
149             context.checkWidth();
150             context.checkFlags();
151             printf(context);
152         }
153
154         protected void printf(FormatContext context, boolean negative, BigDecimal argument) {
155             BigDecimal roundedArgument = argument.setScale(context.getNumberPrecision(), BigDecimal.ROUND_HALF_UP);
156             printDecimalNumber(context, negative, roundedArgument, true);
157         }
158     }
159
160     public static class GeneralScientificConversion extends FloatingPointConversion {
161
162         public void format(FormatContext context) {
163             context.checkFlags();
164             context.assertNoFlag('#');
165             printf(context);
166         }
167
168         protected void printf(FormatContext context, boolean negative, BigDecimal argument) {
169             int precision = Math.max(context.getNumberPrecision(), 1);
170             BigDecimal roundedArgument = round(argument, argument.unscaledValue().toString().length() - precision);
171             if (roundedArgument.compareTo(new BigDecimal(BigInteger.ONE, 4)) >= 0 &&
172                     roundedArgument.compareTo(BigDecimal.ONE.movePointRight(precision)) < 0) {
173                 printDecimalNumber(context, negative, roundedArgument, context.getArgument() instanceof BigDecimal);
174             } else {
175                 printComputerizedScientificNumber(context, negative, roundedArgument, precision - 1);
176             }
177         }
178
179     }
180
181 }
182
Popular Tags