use of com.google_voltpatches.common.annotations.GwtIncompatible in project voltdb by VoltDB.
the class DoubleMath method log2.
/**
* Returns the base 2 logarithm of a double value, rounded with the specified rounding mode to an
* {@code int}.
*
* <p>Regardless of the rounding mode, this is faster than {@code (int) log2(x)}.
*
* @throws IllegalArgumentException if {@code x <= 0.0}, {@code x} is NaN, or {@code x} is
* infinite
*/
// java.lang.Math.getExponent, com.google_voltpatches.common.math.DoubleUtils
@GwtIncompatible
@SuppressWarnings("fallthrough")
public static int log2(double x, RoundingMode mode) {
checkArgument(x > 0.0 && isFinite(x), "x must be positive and finite");
int exponent = getExponent(x);
if (!isNormal(x)) {
return log2(x * IMPLICIT_BIT, mode) - SIGNIFICAND_BITS;
// Do the calculation on a normal value.
}
// x is positive, finite, and normal
boolean increment;
switch(mode) {
case UNNECESSARY:
checkRoundingUnnecessary(isPowerOfTwo(x));
// fall through
case FLOOR:
increment = false;
break;
case CEILING:
increment = !isPowerOfTwo(x);
break;
case DOWN:
increment = exponent < 0 & !isPowerOfTwo(x);
break;
case UP:
increment = exponent >= 0 & !isPowerOfTwo(x);
break;
case HALF_DOWN:
case HALF_EVEN:
case HALF_UP:
double xScaled = scaleNormalize(x);
// sqrt(2) is irrational, and the spec is relative to the "exact numerical result,"
// so log2(x) is never exactly exponent + 0.5.
increment = (xScaled * xScaled) > 2.0;
break;
default:
throw new AssertionError();
}
return increment ? exponent + 1 : exponent;
}
use of com.google_voltpatches.common.annotations.GwtIncompatible in project voltdb by VoltDB.
the class DoubleMath method roundToBigInteger.
/**
* Returns the {@code BigInteger} value that is equal to {@code x} rounded with the specified
* rounding mode, if possible.
*
* @throws ArithmeticException if
* <ul>
* <li>{@code x} is infinite or NaN
* <li>{@code x} is not a mathematical integer and {@code mode} is
* {@link RoundingMode#UNNECESSARY}
* </ul>
*/
// #roundIntermediate, java.lang.Math.getExponent, com.google_voltpatches.common.math.DoubleUtils
@GwtIncompatible
public static BigInteger roundToBigInteger(double x, RoundingMode mode) {
x = roundIntermediate(x, mode);
if (MIN_LONG_AS_DOUBLE - x < 1.0 & x < MAX_LONG_AS_DOUBLE_PLUS_ONE) {
return BigInteger.valueOf((long) x);
}
int exponent = getExponent(x);
long significand = getSignificand(x);
BigInteger result = BigInteger.valueOf(significand).shiftLeft(exponent - SIGNIFICAND_BITS);
return (x < 0) ? result.negate() : result;
}
use of com.google_voltpatches.common.annotations.GwtIncompatible in project voltdb by VoltDB.
the class BigIntegerMath method sqrt.
/**
* Returns the square root of {@code x}, rounded with the specified rounding mode.
*
* @throws IllegalArgumentException if {@code x < 0}
* @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and
* {@code sqrt(x)} is not an integer
*/
// TODO
@GwtIncompatible
@SuppressWarnings("fallthrough")
public static BigInteger sqrt(BigInteger x, RoundingMode mode) {
checkNonNegative("x", x);
if (fitsInLong(x)) {
return BigInteger.valueOf(LongMath.sqrt(x.longValue(), mode));
}
BigInteger sqrtFloor = sqrtFloor(x);
switch(mode) {
case UNNECESSARY:
// fall through
checkRoundingUnnecessary(sqrtFloor.pow(2).equals(x));
case FLOOR:
case DOWN:
return sqrtFloor;
case CEILING:
case UP:
int sqrtFloorInt = sqrtFloor.intValue();
boolean sqrtFloorIsExact = // fast check mod 2^32
(sqrtFloorInt * sqrtFloorInt == x.intValue()) && // slow exact check
sqrtFloor.pow(2).equals(x);
return sqrtFloorIsExact ? sqrtFloor : sqrtFloor.add(BigInteger.ONE);
case HALF_DOWN:
case HALF_UP:
case HALF_EVEN:
BigInteger halfSquare = sqrtFloor.pow(2).add(sqrtFloor);
/*
* We wish to test whether or not x <= (sqrtFloor + 0.5)^2 = halfSquare + 0.25. Since both x
* and halfSquare are integers, this is equivalent to testing whether or not x <=
* halfSquare.
*/
return (halfSquare.compareTo(x) >= 0) ? sqrtFloor : sqrtFloor.add(BigInteger.ONE);
default:
throw new AssertionError();
}
}
use of com.google_voltpatches.common.annotations.GwtIncompatible in project voltdb by VoltDB.
the class BigIntegerMath method sqrtFloor.
// TODO
@GwtIncompatible
private static BigInteger sqrtFloor(BigInteger x) {
/*
* Adapted from Hacker's Delight, Figure 11-1.
*
* Using DoubleUtils.bigToDouble, getting a double approximation of x is extremely fast, and
* then we can get a double approximation of the square root. Then, we iteratively improve this
* guess with an application of Newton's method, which sets guess := (guess + (x / guess)) / 2.
* This iteration has the following two properties:
*
* a) every iteration (except potentially the first) has guess >= floor(sqrt(x)). This is
* because guess' is the arithmetic mean of guess and x / guess, sqrt(x) is the geometric mean,
* and the arithmetic mean is always higher than the geometric mean.
*
* b) this iteration converges to floor(sqrt(x)). In fact, the number of correct digits doubles
* with each iteration, so this algorithm takes O(log(digits)) iterations.
*
* We start out with a double-precision approximation, which may be higher or lower than the
* true value. Therefore, we perform at least one Newton iteration to get a guess that's
* definitely >= floor(sqrt(x)), and then continue the iteration until we reach a fixed point.
*/
BigInteger sqrt0;
int log2 = log2(x, FLOOR);
if (log2 < Double.MAX_EXPONENT) {
sqrt0 = sqrtApproxWithDoubles(x);
} else {
// even!
int shift = (log2 - DoubleUtils.SIGNIFICAND_BITS) & ~1;
/*
* We have that x / 2^shift < 2^54. Our initial approximation to sqrtFloor(x) will be
* 2^(shift/2) * sqrtApproxWithDoubles(x / 2^shift).
*/
sqrt0 = sqrtApproxWithDoubles(x.shiftRight(shift)).shiftLeft(shift >> 1);
}
BigInteger sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1);
if (sqrt0.equals(sqrt1)) {
return sqrt0;
}
do {
sqrt0 = sqrt1;
sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1);
} while (sqrt1.compareTo(sqrt0) < 0);
return sqrt0;
}
Aggregations