blob: 828a7064f1b47d6cbf5c123f67a2a9b9aa3d5ede [file] [log] [blame]
darcy32db4492009-01-26 19:49:26 -08001/*
2 * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 6362557
27 * @summary Some tests of add(BigDecimal, mc)
28 * @author Joseph D. Darcy
29 */
30
31import java.math.*;
32import static java.math.BigDecimal.*;
33import java.util.Set;
34import java.util.EnumSet;
35
36public class AddTests {
37
38 private static Set<RoundingMode> nonExactRoundingModes =
39 EnumSet.complementOf(EnumSet.of(RoundingMode.UNNECESSARY));
40
41 /**
42 * Test for extreme value of scale and rounding precision that
43 * could cause integer overflow in right-shift-into-sticky-bit
44 * computations.
45 */
46 private static int extremaTests() {
47 int failures = 0;
48
49 failures += addWithoutException(valueOf(1, -Integer.MAX_VALUE),
50 valueOf(2, Integer.MAX_VALUE), null);
51 failures += addWithoutException(valueOf(1, -Integer.MAX_VALUE),
52 valueOf(-2, Integer.MAX_VALUE), null);
53 return failures;
54 }
55
56 /**
57 * Print sum of b1 and b2; correct result will not throw an
58 * exception.
59 */
60 private static int addWithoutException(BigDecimal b1, BigDecimal b2, MathContext mc) {
61 if (mc == null)
62 mc = new MathContext(2, RoundingMode.DOWN);
63
64 try {
65 BigDecimal sum = b1.add(b2, mc);
66 printAddition(b1, b2, sum.toString());
67 return 0;
68 } catch(ArithmeticException ae) {
69 printAddition(b1, b2, "Exception!");
70 return 1;
71 }
72 }
73
74 /**
75 * Test combinations of operands that may meet the condensation
76 * criteria when rounded to different precisions.
77 */
78 private static int roundingGradationTests() {
79 int failures = 0;
80
81 failures += roundAway(new BigDecimal("1234e100"),
82 new BigDecimal( "1234e97"));
83
84 failures += roundAway(new BigDecimal("1234e100"),
85 new BigDecimal( "1234e96"));
86
87 failures += roundAway(new BigDecimal("1234e100"),
88 new BigDecimal( "1234e95"));
89
90 failures += roundAway(new BigDecimal("1234e100"),
91 new BigDecimal( "1234e94"));
92
93 failures += roundAway(new BigDecimal("1234e100"),
94 new BigDecimal( "1234e93"));
95
96 failures += roundAway(new BigDecimal("1234e100"),
97 new BigDecimal( "1234e92"));
98
99 failures += roundAway(new BigDecimal("1234e100"),
100 new BigDecimal("1234e50"));
101
102
103 failures += roundAway(new BigDecimal("1000e100"),
104 new BigDecimal( "1234e97"));
105
106 failures += roundAway(new BigDecimal("1000e100"),
107 new BigDecimal( "1234e96"));
108
109 failures += roundAway(new BigDecimal("1000e100"),
110 new BigDecimal( "1234e95"));
111
112 failures += roundAway(new BigDecimal("1000e100"),
113 new BigDecimal( "1234e94"));
114
115 failures += roundAway(new BigDecimal("1000e100"),
116 new BigDecimal( "1234e93"));
117
118 failures += roundAway(new BigDecimal("1000e100"),
119 new BigDecimal( "1234e92"));
120
121 failures += roundAway(new BigDecimal("1000e100"),
122 new BigDecimal("1234e50"));
123
124
125
126 failures += roundAway(new BigDecimal("1999e100"),
127 new BigDecimal( "1234e97"));
128
129 failures += roundAway(new BigDecimal("1999e100"),
130 new BigDecimal( "1234e96"));
131
132 failures += roundAway(new BigDecimal("1999e100"),
133 new BigDecimal( "1234e95"));
134
135 failures += roundAway(new BigDecimal("1999e100"),
136 new BigDecimal( "1234e94"));
137
138 failures += roundAway(new BigDecimal("1999e100"),
139 new BigDecimal( "1234e93"));
140
141 failures += roundAway(new BigDecimal("1999e100"),
142 new BigDecimal( "1234e92"));
143
144 failures += roundAway(new BigDecimal("1999e100"),
145 new BigDecimal("1234e50"));
146
147
148
149 failures += roundAway(new BigDecimal("9999e100"),
150 new BigDecimal( "1234e97"));
151
152 failures += roundAway(new BigDecimal("9999e100"),
153 new BigDecimal( "1234e96"));
154
155 failures += roundAway(new BigDecimal("9999e100"),
156 new BigDecimal( "1234e95"));
157
158 failures += roundAway(new BigDecimal("9999e100"),
159 new BigDecimal( "1234e94"));
160
161 failures += roundAway(new BigDecimal("9999e100"),
162 new BigDecimal( "1234e93"));
163
164 failures += roundAway(new BigDecimal("9999e100"),
165 new BigDecimal( "1234e92"));
166
167 failures += roundAway(new BigDecimal("9999e100"),
168 new BigDecimal("1234e50"));
169
170 return failures;
171 }
172
173 private static void printAddition(BigDecimal b1, BigDecimal b2, String s) {
174 System.out.println("" + b1+ "\t+\t" + b2 + "\t=\t" + s);
175 }
176
177 private static int roundAway(BigDecimal b1, BigDecimal b2) {
178 int failures = 0;
179
180 b1.precision();
181 b2.precision();
182
183 BigDecimal b1_negate = b1.negate();
184 BigDecimal b2_negate = b2.negate();
185
186 b1_negate.precision();
187 b2_negate.precision();
188
189 failures += roundAway1(b1, b2);
190 failures += roundAway1(b1, b2_negate);
191 failures += roundAway1(b1_negate, b2);
192 failures += roundAway1(b1_negate, b2_negate);
193
194 return failures;
195 }
196
197 private static int roundAway1(BigDecimal b1, BigDecimal b2) {
198 int failures = 0;
199 failures += roundAway0(b1, b2);
200 failures += roundAway0(b2, b1);
201 return failures;
202 }
203
204 /**
205 * Compare b1.add(b2, mc) with b1.add(b2).round(mc) for a variety
206 * of MathContexts.
207 */
208 private static int roundAway0(BigDecimal b1, BigDecimal b2) {
209 int failures = 0;
210 BigDecimal exactSum = b1.add(b2);
211
212 for(int precision = 1 ; precision < exactSum.precision()+2; precision++) {
213 for(RoundingMode rm : nonExactRoundingModes) {
214 MathContext mc = new MathContext(precision, rm);
215 BigDecimal roundedExactSum = exactSum.round(mc);
216
217 try {
218 BigDecimal sum = b1.add(b2, mc);
219
220 if (!roundedExactSum.equals(sum) ) {
221 failures++;
222 System.out.println("Exact sum " + exactSum +
223 "\trounded by " + mc +
224 "\texpected: " + roundedExactSum + " got: ");
225 printAddition(b1, b2, sum.toString());
226 }
227// else {
228// System.out.print(mc + "\t");
229// printAddition(b1, b2, sum.toString());
230// }
231
232 } catch (ArithmeticException ae) {
233 printAddition(b1, b2, "Exception!");
234 failures++;
235 }
236 }
237 }
238
239 return failures;
240 }
241
242 /**
243 * Verify calling the precision method should not change the
244 * computed result.
245 */
246 private static int precisionConsistencyTest() {
247 int failures = 0;
248 MathContext mc = new MathContext(1,RoundingMode.DOWN);
249 BigDecimal a = BigDecimal.valueOf(1999, -1); //value is equivalent to 19990
250
251 BigDecimal sum1 = a.add(BigDecimal.ONE, mc);
252 a.precision();
253 BigDecimal sum2 = a.add(BigDecimal.ONE, mc);
254
255 if (!sum1.equals(sum2)) {
256 failures ++;
257 System.out.println("Unequal sums after calling precision!");
258 System.out.print("Before:\t");
259 printAddition(a, BigDecimal.ONE, sum1.toString());
260
261 System.out.print("After:\t");
262 printAddition(a, BigDecimal.ONE, sum2.toString());
263 }
264
265 return failures;
266 }
267
268 public static void main(String argv[]) {
269 int failures = 0;
270
271 failures += extremaTests();
272 failures += roundingGradationTests();
273 failures += precisionConsistencyTest();
274
275 if (failures > 0) {
276 throw new RuntimeException("Incurred " + failures +
277 " failures while testing rounding add.");
278 }
279 }
280}