MCPcopy Create free account
hub / github.com/antlr/codebuff / sqrtFloor

Method sqrtFloor

output/java_guava/1.4.17/BigIntegerMath.java:260–302  ·  view source on GitHub ↗
(BigInteger x)

Source from the content-addressed store, hash-verified

258 }
259
260 @GwtIncompatible // TODO
261 private static BigInteger sqrtFloor(BigInteger x) {
262 /*
263 * Adapted from Hacker's Delight, Figure 11-1.
264 *
265 * Using DoubleUtils.bigToDouble, getting a double approximation of x is extremely fast, and
266 * then we can get a double approximation of the square root. Then, we iteratively improve this
267 * guess with an application of Newton's method, which sets guess := (guess + (x / guess)) / 2.
268 * This iteration has the following two properties:
269 *
270 * a) every iteration (except potentially the first) has guess >= floor(sqrt(x)). This is
271 * because guess' is the arithmetic mean of guess and x / guess, sqrt(x) is the geometric mean,
272 * and the arithmetic mean is always higher than the geometric mean.
273 *
274 * b) this iteration converges to floor(sqrt(x)). In fact, the number of correct digits doubles
275 * with each iteration, so this algorithm takes O(log(digits)) iterations.
276 *
277 * We start out with a double-precision approximation, which may be higher or lower than the
278 * true value. Therefore, we perform at least one Newton iteration to get a guess that's
279 * definitely >= floor(sqrt(x)), and then continue the iteration until we reach a fixed point.
280 */
281 BigInteger sqrt0;
282 int log2 = log2(x, FLOOR);
283 if (log2 < Double.MAX_EXPONENT) {
284 sqrt0 = sqrtApproxWithDoubles(x);
285 } else {
286 int shift = (log2 - DoubleUtils.SIGNIFICAND_BITS) & ~1; // even!
287 /*
288 * We have that x / 2^shift < 2^54. Our initial approximation to sqrtFloor(x) will be
289 * 2^(shift/2) * sqrtApproxWithDoubles(x / 2^shift).
290 */
291 sqrt0 = sqrtApproxWithDoubles(x.shiftRight(shift)).shiftLeft(shift >> 1);
292 }
293 BigInteger sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1);
294 if (sqrt0.equals(sqrt1)) {
295 return sqrt0;
296 }
297 do {
298 sqrt0 = sqrt1;
299 sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1);
300 } while (sqrt1.compareTo(sqrt0) < 0);
301 return sqrt0;
302 }
303
304 @GwtIncompatible // TODO
305 private static BigInteger sqrtApproxWithDoubles(BigInteger x) {

Callers 1

sqrtMethod · 0.95

Calls 6

log2Method · 0.95
sqrtApproxWithDoublesMethod · 0.95
addMethod · 0.65
equalsMethod · 0.65
divideMethod · 0.45
compareToMethod · 0.45

Tested by

no test coverage detected