com.google.common.math.DoubleUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of guava Show documentation
Show all versions of guava Show documentation
Guava is a suite of core and expanded libraries that include
utility classes, google's collections, io classes, and much
much more.
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.math;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.Double.MAX_EXPONENT;
import static java.lang.Double.MIN_EXPONENT;
import static java.lang.Double.POSITIVE_INFINITY;
import static java.lang.Double.doubleToRawLongBits;
import static java.lang.Double.isNaN;
import static java.lang.Double.longBitsToDouble;
import static java.lang.Math.getExponent;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import java.math.BigInteger;
/**
* Utilities for {@code double} primitives.
*
* @author Louis Wasserman
*/
@GwtIncompatible
final class DoubleUtils {
private DoubleUtils() {}
static double nextDown(double d) {
return -Math.nextUp(-d);
}
// The mask for the significand, according to the {@link
// Double#doubleToRawLongBits(double)} spec.
static final long SIGNIFICAND_MASK = 0x000fffffffffffffL;
// The mask for the exponent, according to the {@link
// Double#doubleToRawLongBits(double)} spec.
static final long EXPONENT_MASK = 0x7ff0000000000000L;
// The mask for the sign, according to the {@link
// Double#doubleToRawLongBits(double)} spec.
static final long SIGN_MASK = 0x8000000000000000L;
static final int SIGNIFICAND_BITS = 52;
static final int EXPONENT_BIAS = 1023;
/** The implicit 1 bit that is omitted in significands of normal doubles. */
static final long IMPLICIT_BIT = SIGNIFICAND_MASK + 1;
static long getSignificand(double d) {
checkArgument(isFinite(d), "not a normal value");
int exponent = getExponent(d);
long bits = doubleToRawLongBits(d);
bits &= SIGNIFICAND_MASK;
return (exponent == MIN_EXPONENT - 1) ? bits << 1 : bits | IMPLICIT_BIT;
}
static boolean isFinite(double d) {
return getExponent(d) <= MAX_EXPONENT;
}
static boolean isNormal(double d) {
return getExponent(d) >= MIN_EXPONENT;
}
/*
* Returns x scaled by a power of 2 such that it is in the range [1, 2). Assumes x is positive,
* normal, and finite.
*/
static double scaleNormalize(double x) {
long significand = doubleToRawLongBits(x) & SIGNIFICAND_MASK;
return longBitsToDouble(significand | ONE_BITS);
}
static double bigToDouble(BigInteger x) {
// This is an extremely fast implementation of BigInteger.doubleValue(). JDK patch pending.
BigInteger absX = x.abs();
int exponent = absX.bitLength() - 1;
// exponent == floor(log2(abs(x)))
if (exponent < Long.SIZE - 1) {
return x.longValue();
} else if (exponent > MAX_EXPONENT) {
return x.signum() * POSITIVE_INFINITY;
}
/*
* We need the top SIGNIFICAND_BITS + 1 bits, including the "implicit" one bit. To make rounding
* easier, we pick out the top SIGNIFICAND_BITS + 2 bits, so we have one to help us round up or
* down. twiceSignifFloor will contain the top SIGNIFICAND_BITS + 2 bits, and signifFloor the
* top SIGNIFICAND_BITS + 1.
*
* It helps to consider the real number signif = absX * 2^(SIGNIFICAND_BITS - exponent).
*/
int shift = exponent - SIGNIFICAND_BITS - 1;
long twiceSignifFloor = absX.shiftRight(shift).longValue();
long signifFloor = twiceSignifFloor >> 1;
signifFloor &= SIGNIFICAND_MASK; // remove the implied bit
/*
* We round up if either the fractional part of signif is strictly greater than 0.5 (which is
* true if the 0.5 bit is set and any lower bit is set), or if the fractional part of signif is
* >= 0.5 and signifFloor is odd (which is true if both the 0.5 bit and the 1 bit are set).
*/
boolean increment =
(twiceSignifFloor & 1) != 0 && ((signifFloor & 1) != 0 || absX.getLowestSetBit() < shift);
long signifRounded = increment ? signifFloor + 1 : signifFloor;
long bits = (long) ((exponent + EXPONENT_BIAS)) << SIGNIFICAND_BITS;
bits += signifRounded;
/*
* If signifRounded == 2^53, we'd need to set all of the significand bits to zero and add 1 to
* the exponent. This is exactly the behavior we get from just adding signifRounded to bits
* directly. If the exponent is MAX_DOUBLE_EXPONENT, we round up (correctly) to
* Double.POSITIVE_INFINITY.
*/
bits |= x.signum() & SIGN_MASK;
return longBitsToDouble(bits);
}
/** Returns its argument if it is non-negative, zero if it is negative. */
static double ensureNonNegative(double value) {
checkArgument(!isNaN(value));
if (value > 0.0) {
return value;
} else {
return 0.0;
}
}
@VisibleForTesting static final long ONE_BITS = 0x3ff0000000000000L;
}