Returns the square root of x, rounded with the specified rounding mode. @throws IllegalArgumentException if x < 0 @throws ArithmeticException if mode is RoundingMode#UNNECESSARY and sqrt(x) is not an integer
(BigInteger x, RoundingMode mode)
| 223 | */ |
| 224 | |
| 225 | @GwtIncompatible // TODO |
| 226 | @SuppressWarnings("fallthrough") |
| 227 | public static BigInteger sqrt(BigInteger x, RoundingMode mode) { |
| 228 | checkNonNegative("x", x); |
| 229 | if (fitsInLong(x)) { |
| 230 | return BigInteger.valueOf(LongMath.sqrt(x.longValue(), mode)); |
| 231 | } |
| 232 | BigInteger sqrtFloor = sqrtFloor(x); |
| 233 | switch (mode) { |
| 234 | case UNNECESSARY: |
| 235 | checkRoundingUnnecessary(sqrtFloor.pow(2).equals(x)); // fall through |
| 236 | case FLOOR: |
| 237 | case DOWN: |
| 238 | return sqrtFloor; |
| 239 | case CEILING: |
| 240 | case UP: |
| 241 | int sqrtFloorInt = sqrtFloor.intValue(); |
| 242 | boolean sqrtFloorIsExact = |
| 243 | (sqrtFloorInt * sqrtFloorInt == x.intValue()) // fast check mod 2^32 |
| 244 | && sqrtFloor.pow(2).equals(x); // slow exact check |
| 245 | return sqrtFloorIsExact ? sqrtFloor : sqrtFloor.add(BigInteger.ONE); |
| 246 | case HALF_DOWN: |
| 247 | case HALF_UP: |
| 248 | case HALF_EVEN: |
| 249 | BigInteger halfSquare = sqrtFloor.pow(2).add(sqrtFloor); |
| 250 | /* |
| 251 | * We wish to test whether or not x <= (sqrtFloor + 0.5)^2 = halfSquare + 0.25. Since both x |
| 252 | * and halfSquare are integers, this is equivalent to testing whether or not x <= |
| 253 | * halfSquare. |
| 254 | */ |
| 255 | return (halfSquare.compareTo(x) >= 0) ? sqrtFloor : sqrtFloor.add(BigInteger.ONE); |
| 256 | default: |
| 257 | throw new AssertionError(); |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | @GwtIncompatible // TODO |
| 262 | private static BigInteger sqrtFloor(BigInteger x) { |
no test coverage detected