< prev index next >

test/jdk/java/math/BigDecimal/SquareRootTests.java

Print this page


   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         failures += lowPrecisionPerfectSquares();


  43 
  44         if (failures > 0 ) {
  45             throw new RuntimeException("Incurred " + failures + " failures" +
  46                                        " testing BigDecimal.sqrt().");
  47         }
  48     }
  49 
  50     private static int negativeTests() {
  51         int failures = 0;
  52 
  53         for (long i = -10; i < 0; i++) {
  54             for (int j = -5; j < 5; j++) {
  55                 try {
  56                     BigDecimal input = BigDecimal.valueOf(i, j);
  57                     BigDecimal result = input.sqrt(MathContext.DECIMAL64);
  58                     System.err.println("Unexpected sqrt of negative: (" +
  59                                        input + ").sqrt()  = " + result );
  60                     failures += 1;
  61                 } catch (ArithmeticException e) {
  62                     ; // Expected


  80                                 expected, true, "zeros");
  81         }
  82 
  83         return failures;
  84     }
  85 
  86     /**
  87      * sqrt(10^2N) is 10^N
  88      * Both numerical value and representation should be verified
  89      */
  90     private static int evenPowersOfTenTests() {
  91         int failures = 0;
  92         MathContext oneDigitExactly = new MathContext(1, RoundingMode.UNNECESSARY);
  93 
  94         for (int scale = -100; scale <= 100; scale++) {
  95             BigDecimal testValue       = BigDecimal.valueOf(1, 2*scale);
  96             BigDecimal expectedNumericalResult = BigDecimal.valueOf(1, scale);
  97 
  98             BigDecimal result;
  99 
 100 
 101             failures += equalNumerically(expectedNumericalResult,
 102                                            result = testValue.sqrt(MathContext.DECIMAL64),
 103                                            "Even powers of 10, DECIMAL64");
 104 
 105             // Can round to one digit of precision exactly
 106             failures += equalNumerically(expectedNumericalResult,
 107                                            result = testValue.sqrt(oneDigitExactly),
 108                                            "even powers of 10, 1 digit");
 109             if (result.precision() > 1) {
 110                 failures += 1;
 111                 System.err.println("Excess precision for " + result);
 112             }
 113 
 114 
 115             // If rounding to more than one digit, do precision / scale checking...
 116 
 117         }
 118 
 119         return failures;
 120     }
 121 
 122     private static int squareRootTwoTests() {
 123         int failures = 0;
 124         BigDecimal TWO = new BigDecimal(2);
 125 
 126         // Square root of 2 truncated to 65 digits
 127         BigDecimal highPrecisionRoot2 =
 128             new BigDecimal("1.41421356237309504880168872420969807856967187537694807317667973799");
 129 
 130 
 131         RoundingMode[] modes = {
 132             RoundingMode.UP,       RoundingMode.DOWN,
 133             RoundingMode.CEILING, RoundingMode.FLOOR,
 134             RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN
 135         };
 136 
 137         // For each iteresting rounding mode, for precisions 1 to, say
 138         // 63 numerically compare TWO.sqrt(mc) to
 139         // highPrecisionRoot2.round(mc)
 140 




 141         for (RoundingMode mode : modes) {
 142             for (int precision = 1; precision < 63; precision++) {
 143                 MathContext mc = new MathContext(precision, mode);
 144                 BigDecimal expected = highPrecisionRoot2.round(mc);
 145                 BigDecimal computed = TWO.sqrt(mc);

 146 
 147                 equalNumerically(expected, computed, "sqrt(2)");

 148             }
 149         }
 150 
 151         return failures;
 152     }
 153 
 154     private static int lowPrecisionPerfectSquares() {
 155         int failures = 0;
 156 
 157         // For 5^2 through 9^2, if the input is rounded to one digit
 158         // first before the root is computed, the wrong answer will
 159         // result. Verify results and scale for different rounding
 160         // modes and precisions.
 161         long[][] squaresWithOneDigitRoot = {{ 4, 2},
 162                                             { 9, 3},
 163                                             {25, 5},
 164                                             {36, 6},
 165                                             {49, 7},
 166                                             {64, 8},
 167                                             {81, 9}};


 178                         MathContext mc = new MathContext(precision, rm);
 179                         BigDecimal computedRoot = scaledSquare.sqrt(mc);
 180                         failures += equalNumerically(expected, computedRoot, "simple squares");
 181                         int computedScale = computedRoot.scale();
 182                         if (precision >=  expectedScale + 1 &&
 183                             computedScale != expectedScale) {
 184                         System.err.printf("%s\tprecision=%d\trm=%s%n",
 185                                           computedRoot.toString(), precision, rm);
 186                             failures++;
 187                             System.err.printf("\t%s does not have expected scale of %d%n.",
 188                                               computedRoot, expectedScale);
 189                         }
 190                     }
 191                 }
 192             }
 193         }
 194 
 195         return failures;
 196     }
 197 










































 198     private static int compare(BigDecimal a, BigDecimal b, boolean expected, String prefix) {
 199         boolean result = a.equals(b);
 200         int failed = (result==expected) ? 0 : 1;
 201         if (failed == 1) {
 202             System.err.println("Testing " + prefix +
 203                                "(" + a + ").compareTo(" + b + ") => " + result +
 204                                "\n\tExpected " + expected);
 205         }
 206         return failed;
 207     }
 208 
 209     private static int equalNumerically(BigDecimal a, BigDecimal b,
 210                                         String prefix) {
 211         return compareNumerically(a, b, 0, prefix);
 212     }
 213 
 214 
 215     private static int compareNumerically(BigDecimal a, BigDecimal b,
 216                                           int expected, String prefix) {
 217         int result = a.compareTo(b);
 218         int failed = (result==expected) ? 0 : 1;
 219         if (failed == 1) {
 220             System.err.println("Testing " + prefix +
 221                                "(" + a + ").compareTo(" + b + ") => " + result +
 222                                "\n\tExpected " + expected);
 223         }
 224         return failed;
 225     }
 226 











































































































































































































 227 }
   1 /*
   2  * Copyright (c) 2016, 2019, 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 8233452
  27  * @summary Tests of BigDecimal.sqrt().
  28  */
  29 
  30 import java.math.*;
  31 import java.util.*;
  32 
  33 import static java.math.BigDecimal.TEN;
  34 import static java.math.BigDecimal.ZERO;
  35 import static java.math.BigDecimal.valueOf;
  36 
  37 public class SquareRootTests {
  38     private static BigDecimal TWO = new BigDecimal(2);
  39 
  40     public static void main(String... args) {
  41         int failures = 0;
  42 
  43         failures += negativeTests();
  44         failures += zeroTests();
  45         failures += evenPowersOfTenTests();
  46         failures += squareRootTwoTests();
  47         failures += lowPrecisionPerfectSquares();
  48         failures += almostFourRoundingDown();
  49         failures += almostFourRoundingUp();
  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


  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             failures += equalNumerically(expectedNumericalResult,
 108                                            result = testValue.sqrt(MathContext.DECIMAL64),
 109                                            "Even powers of 10, DECIMAL64");
 110 
 111             // Can round to one digit of precision exactly
 112             failures += equalNumerically(expectedNumericalResult,
 113                                            result = testValue.sqrt(oneDigitExactly),
 114                                            "even powers of 10, 1 digit");
 115             if (result.precision() > 1) {
 116                 failures += 1;
 117                 System.err.println("Excess precision for " + result);
 118             }
 119 

 120             // If rounding to more than one digit, do precision / scale checking...

 121         }
 122 
 123         return failures;
 124     }
 125 
 126     private static int squareRootTwoTests() {
 127         int failures = 0;

 128 
 129         // Square root of 2 truncated to 65 digits
 130         BigDecimal highPrecisionRoot2 =
 131             new BigDecimal("1.41421356237309504880168872420969807856967187537694807317667973799");
 132 

 133         RoundingMode[] modes = {
 134             RoundingMode.UP,       RoundingMode.DOWN,
 135             RoundingMode.CEILING, RoundingMode.FLOOR,
 136             RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN
 137         };
 138 



 139 
 140         // For each interesting rounding mode, for precisions 1 to, say
 141         // 63 numerically compare TWO.sqrt(mc) to
 142         // highPrecisionRoot2.round(mc) and the alternative internal high-precision
 143         // implementation of square root.
 144         for (RoundingMode mode : modes) {
 145             for (int precision = 1; precision < 63; precision++) {
 146                 MathContext mc = new MathContext(precision, mode);
 147                 BigDecimal expected = highPrecisionRoot2.round(mc);
 148                 BigDecimal computed = TWO.sqrt(mc);
 149                 BigDecimal altComputed = BigSquareRoot.sqrt(TWO, mc);
 150 
 151                 failures += equalNumerically(expected, computed, "sqrt(2)");
 152                 failures += equalNumerically(computed, altComputed, "computed & altComputed");
 153             }
 154         }
 155 
 156         return failures;
 157     }
 158 
 159     private static int lowPrecisionPerfectSquares() {
 160         int failures = 0;
 161 
 162         // For 5^2 through 9^2, if the input is rounded to one digit
 163         // first before the root is computed, the wrong answer will
 164         // result. Verify results and scale for different rounding
 165         // modes and precisions.
 166         long[][] squaresWithOneDigitRoot = {{ 4, 2},
 167                                             { 9, 3},
 168                                             {25, 5},
 169                                             {36, 6},
 170                                             {49, 7},
 171                                             {64, 8},
 172                                             {81, 9}};


 183                         MathContext mc = new MathContext(precision, rm);
 184                         BigDecimal computedRoot = scaledSquare.sqrt(mc);
 185                         failures += equalNumerically(expected, computedRoot, "simple squares");
 186                         int computedScale = computedRoot.scale();
 187                         if (precision >=  expectedScale + 1 &&
 188                             computedScale != expectedScale) {
 189                             System.err.printf("%s\tprecision=%d\trm=%s%n",
 190                                               computedRoot.toString(), precision, rm);
 191                             failures++;
 192                             System.err.printf("\t%s does not have expected scale of %d%n.",
 193                                               computedRoot, expectedScale);
 194                         }
 195                     }
 196                 }
 197             }
 198         }
 199 
 200         return failures;
 201     }
 202 
 203     /**
 204      * Test around 3.9999 that the result doesn't not improperly
 205      * round-up to a numerical value of 2.
 206      */
 207     private static int almostFourRoundingDown() {
 208         int failures = 0;
 209         BigDecimal nearFour = new BigDecimal("3.999999999999999999999999999999");
 210 
 211         // Sqrt root is 1.9999...
 212         
 213         for (int i = 1; i < 64; i++) {
 214             MathContext mc = new MathContext(i, RoundingMode.FLOOR);
 215             BigDecimal result = nearFour.sqrt(mc);
 216             BigDecimal expected = BigSquareRoot.sqrt(nearFour, mc);
 217             failures += equalNumerically(expected, result, "near four rounding down");
 218             failures += (result.compareTo(TWO) < 0) ? 0  : 1 ;
 219         }
 220 
 221         return failures;
 222     }
 223 
 224     /**
 225      * Test around 4.000...1 that the result doesn't not improperly
 226      * round-down to a numerical value of 2.
 227      */
 228     private static int almostFourRoundingUp() {
 229         int failures = 0;
 230         BigDecimal nearFour = new BigDecimal("4.000000000000000000000000000001");
 231 
 232         // Sqrt root is 2.0000....<non-zero digits>
 233         
 234         for (int i = 1; i < 64; i++) {
 235             MathContext mc = new MathContext(i, RoundingMode.CEILING);
 236             BigDecimal result = nearFour.sqrt(mc);
 237             BigDecimal expected = BigSquareRoot.sqrt(nearFour, mc);
 238             failures += equalNumerically(expected, result, "near four rounding down");
 239             failures += (result.compareTo(TWO) > 0) ? 0  : 1 ;
 240         }
 241 
 242         return failures;
 243     }
 244 
 245     private static int compare(BigDecimal a, BigDecimal b, boolean expected, String prefix) {
 246         boolean result = a.equals(b);
 247         int failed = (result==expected) ? 0 : 1;
 248         if (failed == 1) {
 249             System.err.println("Testing " + prefix +
 250                                "(" + a + ").compareTo(" + b + ") => " + result +
 251                                "\n\tExpected " + expected);
 252         }
 253         return failed;
 254     }
 255 
 256     private static int equalNumerically(BigDecimal a, BigDecimal b,
 257                                         String prefix) {
 258         return compareNumerically(a, b, 0, prefix);
 259     }
 260 
 261 
 262     private static int compareNumerically(BigDecimal a, BigDecimal b,
 263                                           int expected, String prefix) {
 264         int result = a.compareTo(b);
 265         int failed = (result==expected) ? 0 : 1;
 266         if (failed == 1) {
 267             System.err.println("Testing " + prefix +
 268                                "(" + a + ").compareTo(" + b + ") => " + result +
 269                                "\n\tExpected " + expected);
 270         }
 271         return failed;
 272     }
 273 
 274     /**
 275      * Alternative implementation of BigDecimal square root which uses
 276      * higher-precision for a simpler set of termination conditions
 277      * for the Newton iteration.
 278      */
 279     private static class BigSquareRoot {
 280         /**
 281          * The value 0.1, with a scale of 1.
 282          */
 283         private static final BigDecimal ONE_TENTH = valueOf(1L, 1);
 284 
 285         /**
 286          * The value 0.5, with a scale of 1.
 287          */
 288         private static final BigDecimal ONE_HALF = valueOf(5L, 1);
 289 
 290         private static boolean isPowerOfTen(BigDecimal bd) {
 291             return BigInteger.ONE.equals(bd.unscaledValue());
 292         }
 293 
 294         public static BigDecimal sqrt(BigDecimal bd, MathContext mc) {
 295             int signum = bd.signum();
 296             if (signum == 1) {
 297                 /*
 298                  * The following code draws on the algorithm presented in
 299                  * "Properly Rounded Variable Precision Square Root," Hull and
 300                  * Abrham, ACM Transactions on Mathematical Software, Vol 11,
 301                  * No. 3, September 1985, Pages 229-237.
 302                  *
 303                  * The BigDecimal computational model differs from the one
 304                  * presented in the paper in several ways: first BigDecimal
 305                  * numbers aren't necessarily normalized, second many more
 306                  * rounding modes are supported, including UNNECESSARY, and
 307                  * exact results can be requested.
 308                  *
 309                  * The main steps of the algorithm below are as follows,
 310                  * first argument reduce the value to the numerical range
 311                  * [1, 10) using the following relations:
 312                  *
 313                  * x = y * 10 ^ exp
 314                  * sqrt(x) = sqrt(y) * 10^(exp / 2) if exp is even
 315                  * sqrt(x) = sqrt(y/10) * 10 ^((exp+1)/2) is exp is odd
 316                  *
 317                  * Then use Newton's iteration on the reduced value to compute
 318                  * the numerical digits of the desired result.
 319                  *
 320                  * Finally, scale back to the desired exponent range and
 321                  * perform any adjustment to get the preferred scale in the
 322                  * representation.
 323                  */
 324 
 325                 // The code below favors relative simplicity over checking
 326                 // for special cases that could run faster.
 327 
 328                 int preferredScale = bd.scale()/2;
 329                 BigDecimal zeroWithFinalPreferredScale =
 330                     BigDecimal.valueOf(0L, preferredScale);
 331 
 332                 // First phase of numerical normalization, strip trailing
 333                 // zeros and check for even powers of 10.
 334                 BigDecimal stripped = bd.stripTrailingZeros();
 335                 int strippedScale = stripped.scale();
 336 
 337                 // Numerically sqrt(10^2N) = 10^N
 338                 if (isPowerOfTen(stripped) &&
 339                     strippedScale % 2 == 0) {
 340                     BigDecimal result = BigDecimal.valueOf(1L, strippedScale/2);
 341                     if (result.scale() != preferredScale) {
 342                         // Adjust to requested precision and preferred
 343                         // scale as appropriate.
 344                         result = result.add(zeroWithFinalPreferredScale, mc);
 345                     }
 346                     return result;
 347                 }
 348 
 349                 // After stripTrailingZeros, the representation is normalized as
 350                 //
 351                 // unscaledValue * 10^(-scale)
 352                 //
 353                 // where unscaledValue is an integer with the mimimum
 354                 // precision for the cohort of the numerical value. To
 355                 // allow binary floating-point hardware to be used to get
 356                 // approximately a 15 digit approximation to the square
 357                 // root, it is helpful to instead normalize this so that
 358                 // the significand portion is to right of the decimal
 359                 // point by roughly (scale() - precision() +1).
 360 
 361                 // Now the precision / scale adjustment
 362                 int scaleAdjust = 0;
 363                 int scale = stripped.scale() - stripped.precision() + 1;
 364                 if (scale % 2 == 0) {
 365                     scaleAdjust = scale;
 366                 } else {
 367                     scaleAdjust = scale - 1;
 368                 }
 369 
 370                 BigDecimal working = stripped.scaleByPowerOfTen(scaleAdjust);
 371 
 372                 assert  // Verify 0.1 <= working < 10
 373                     ONE_TENTH.compareTo(working) <= 0 && working.compareTo(TEN) < 0;
 374 
 375                 // Use good ole' Math.sqrt to get the initial guess for
 376                 // the Newton iteration, good to at least 15 decimal
 377                 // digits. This approach does incur the cost of a
 378                 //
 379                 // BigDecimal -> double -> BigDecimal
 380                 //
 381                 // conversion cycle, but it avoids the need for several
 382                 // Newton iterations in BigDecimal arithmetic to get the
 383                 // working answer to 15 digits of precision. If many fewer
 384                 // than 15 digits were needed, it might be faster to do
 385                 // the loop entirely in BigDecimal arithmetic.
 386                 //
 387                 // (A double value might have as much many as 17 decimal
 388                 // digits of precision; it depends on the relative density
 389                 // of binary and decimal numbers at different regions of
 390                 // the number line.)
 391                 //
 392                 // (It would be possible to check for certain special
 393                 // cases to avoid doing any Newton iterations. For
 394                 // example, if the BigDecimal -> double conversion was
 395                 // known to be exact and the rounding mode had a
 396                 // low-enough precision, the post-Newton rounding logic
 397                 // could be applied directly.)
 398 
 399                 BigDecimal guess = new BigDecimal(Math.sqrt(working.doubleValue()));
 400                 int guessPrecision = 15;
 401                 int originalPrecision = mc.getPrecision();
 402                 int targetPrecision;
 403 
 404                 // If an exact value is requested, it must only need about
 405                 // half of the input digits to represent since multiplying
 406                 // an N digit number by itself yield a 2N-1 digit or 2N
 407                 // digit result.
 408                 if (originalPrecision == 0) {
 409                     targetPrecision = stripped.precision()/2 + 1;
 410                 } else {
 411                     targetPrecision = originalPrecision;
 412                 }
 413 
 414                 // When setting the precision to use inside the Newton
 415                 // iteration loop, take care to avoid the case where the
 416                 // precision of the input exceeds the requested precision
 417                 // and rounding the input value too soon.
 418                 BigDecimal approx = guess;
 419                 int workingPrecision = working.precision();
 420                 int loopPrecision = Math.max(Math.max(2 * targetPrecision + 2, workingPrecision),
 421                                              34); // Force at least
 422                                                   // two Netwon
 423                                                   // iterations on the
 424                                                   // Math.sqrt result.
 425                 do {
 426                     int tmpPrecision = Math.max(Math.max(guessPrecision, targetPrecision + 2),
 427                                                 workingPrecision);
 428                     MathContext mcTmp = new MathContext(loopPrecision, RoundingMode.HALF_EVEN);
 429                     // approx = 0.5 * (approx + fraction / approx)
 430                     approx = ONE_HALF.multiply(approx.add(working.divide(approx, mcTmp), mcTmp));
 431                     guessPrecision *= 2;
 432                 } while (guessPrecision < loopPrecision);
 433 
 434                 BigDecimal result;
 435                 RoundingMode targetRm = mc.getRoundingMode();
 436                 if (targetRm == RoundingMode.UNNECESSARY || originalPrecision == 0) {
 437                     RoundingMode tmpRm =
 438                         (targetRm == RoundingMode.UNNECESSARY) ? RoundingMode.DOWN : targetRm;
 439                     MathContext mcTmp = new MathContext(targetPrecision, tmpRm);
 440                     result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mcTmp);
 441 
 442                     // If result*result != this numerically, the square
 443                     // root isn't exact
 444                     if (bd.subtract(result.multiply(result)).compareTo(ZERO) != 0) {
 445                         throw new ArithmeticException("Computed square root not exact.");
 446                     }
 447                 } else {
 448                     result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mc);
 449                 }
 450 
 451                 if (result.scale() != preferredScale) {
 452                     // The preferred scale of an add is
 453                     // max(addend.scale(), augend.scale()). Therefore, if
 454                     // the scale of the result is first minimized using
 455                     // stripTrailingZeros(), adding a zero of the
 456                     // preferred scale rounding the correct precision will
 457                     // perform the proper scale vs precision tradeoffs.
 458                     result = result.stripTrailingZeros().
 459                         add(zeroWithFinalPreferredScale,
 460                             new MathContext(originalPrecision, RoundingMode.UNNECESSARY));
 461                 }
 462                 return result;
 463             } else {
 464                 switch (signum) {
 465                 case -1:
 466                     throw new ArithmeticException("Attempted square root " +
 467                                                   "of negative BigDecimal");
 468                 case 0:
 469                     return valueOf(0L, bd.scale()/2);
 470 
 471                 default:
 472                     throw new AssertionError("Bad value from signum");
 473                 }
 474             }
 475         }
 476     }
 477 }
< prev index next >