1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 4851777 27 * @summary Tests of BigDecimal.sqrt(). 28 */ 29 30 import java.math.*; 31 import java.util.*; 32 33 public class SquareRootTests { 34 35 public static void main(String... args) { 36 int failures = 0; 37 38 failures += negativeTests(); 39 failures += zeroTests(); 40 failures += evenPowersOfTenTests(); 41 failures += squareRootTwoTests(); 42 43 // Add trickier rounding cases -- try to find examples of 44 45 // When setting the precision to use inside the loop, take 46 // care to avoid the case where the precision of the input 47 // exceeds the requested precision and rounding the input 48 // value too soon. 49 50 51 if (failures > 0 ) { 52 throw new RuntimeException("Incurred " + failures + " failures" + 53 " testing BigDecimal.sqrt()."); 54 } 55 } 56 57 private static int negativeTests() { 58 int failures = 0; 59 60 for (long i = -10; i < 0; i++) { 61 for (int j = -5; j < 5; j++) { 62 try { 63 BigDecimal input = BigDecimal.valueOf(i, j); 64 BigDecimal result = input.sqrt(MathContext.DECIMAL64); 65 System.err.println("Unexpected sqrt of negative: (" + 66 input + ").sqrt() = " + result ); 67 failures += 1; 68 } catch (ArithmeticException e) { 69 ; // Expected 70 } 71 } 72 } 73 74 return failures; 75 } 76 77 private static int zeroTests() { 78 int failures = 0; 79 80 for (int i = -100; i < 100; i++) { 81 BigDecimal expected = BigDecimal.valueOf(0L, i/2); 82 // These results are independent of rounding mode 83 failures += compare(BigDecimal.valueOf(0L, i).sqrt(MathContext.UNLIMITED), 84 expected, true, "zeros"); 85 86 failures += compare(BigDecimal.valueOf(0L, i).sqrt(MathContext.DECIMAL64), 87 expected, true, "zeros"); 88 } 89 90 return failures; 91 } 92 93 /** 94 * sqrt(10^2N) is 10^N 95 * Both numerical value and representation should be verified 96 */ 97 private static int evenPowersOfTenTests() { 98 int failures = 0; 99 MathContext oneDigitExactly = new MathContext(1, RoundingMode.UNNECESSARY); 100 101 for (int scale = -100; scale <= 100; scale++) { 102 BigDecimal testValue = BigDecimal.valueOf(1, 2*scale); 103 BigDecimal expectedNumericalResult = BigDecimal.valueOf(1, scale); 104 105 BigDecimal result; 106 107 108 failures += equalNumerically(expectedNumericalResult, 109 result = testValue.sqrt(MathContext.DECIMAL64), 110 "Even powers of 10, DECIMAL64"); 111 112 // Can round to one digit of precision exactly 113 failures += equalNumerically(expectedNumericalResult, 114 result = testValue.sqrt(oneDigitExactly), 115 "even powers of 10, 1 digit"); 116 if (result.precision() > 1) { 117 failures += 1; 118 System.err.println("Excess precision for " + result); 119 } 120 121 122 // If rounding to more than one digit, do precision / scale checking... 123 124 } 125 126 return failures; 127 } 128 129 private static int squareRootTwoTests() { 130 int failures = 0; 131 BigDecimal TWO = new BigDecimal(2); 132 133 // Square root of 2 truncated to 65 digits 134 BigDecimal highPrecisionRoot2 = 135 new BigDecimal("1.41421356237309504880168872420969807856967187537694807317667973799"); 136 137 138 RoundingMode[] modes = { 139 RoundingMode.UP, RoundingMode.DOWN, 140 RoundingMode.CEILING, RoundingMode.FLOOR, 141 RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN 142 }; 143 144 // For each iteresting rounding mode, for precisions 1 to, say 145 // 63 numerically compare TWO.sqrt(mc) to 146 // highPrecisionRoot2.round(mc) 147 148 for (RoundingMode mode : modes) { 149 for (int precision = 1; precision < 63; precision++) { 150 MathContext mc = new MathContext(precision, mode); 151 BigDecimal expected = highPrecisionRoot2.round(mc); 152 BigDecimal computed = TWO.sqrt(mc); 153 154 equalNumerically(expected, computed, "sqrt(2)"); 155 } 156 } 157 158 return failures; 159 } 160 161 162 163 private static int compare(BigDecimal a, BigDecimal b, boolean expected, String prefix) { 164 boolean result = a.equals(b); 165 int failed = (result==expected) ? 0 : 1; 166 if (failed == 1) { 167 System.err.println("Testing " + prefix + 168 "(" + a + ").compareTo(" + b + ") => " + result + 169 "\n\tExpected " + expected); 170 } 171 return failed; 172 } 173 174 private static int equalNumerically(BigDecimal a, BigDecimal b, 175 String prefix) { 176 return compareNumerically(a, b, 0, prefix); 177 } 178 179 180 private static int compareNumerically(BigDecimal a, BigDecimal b, 181 int expected, String prefix) { 182 int result = a.compareTo(b); 183 int failed = (result==expected) ? 0 : 1; 184 if (failed == 1) { 185 System.err.println("Testing " + prefix + 186 "(" + a + ").compareTo(" + b + ") => " + result + 187 "\n\tExpected " + expected); 188 } 189 return failed; 190 } 191 192 }