
org.jgrasstools.gears.io.disktree.jtstmp.DoubleBits Maven / Gradle / Ivy
package org.jgrasstools.gears.io.disktree.jtstmp;
import java.io.Serializable;
/**
* DoubleBits manipulates Double numbers
* by using bit manipulation and bit-field extraction.
* For some operations (such as determining the exponent)
* this is more accurate than using mathematical operations
* (which suffer from round-off error).
*
* The algorithms and constants in this class
* apply only to IEEE-754 double-precision floating point format.
*
* @version 1.7
*/
public class DoubleBits implements Serializable {
private static final long serialVersionUID = 7426674216965508156L;
public static final int EXPONENT_BIAS = 1023;
public static double powerOf2( int exp ) {
if (exp > 1023 || exp < -1022)
throw new IllegalArgumentException("Exponent out of bounds");
long expBias = exp + EXPONENT_BIAS;
long bits = (long) expBias << 52;
return Double.longBitsToDouble(bits);
}
public static int exponent( double d ) {
DoubleBits db = new DoubleBits(d);
return db.getExponent();
}
public static double truncateToPowerOfTwo( double d ) {
DoubleBits db = new DoubleBits(d);
db.zeroLowerBits(52);
return db.getDouble();
}
public static String toBinaryString( double d ) {
DoubleBits db = new DoubleBits(d);
return db.toString();
}
public static double maximumCommonMantissa( double d1, double d2 ) {
if (d1 == 0.0 || d2 == 0.0)
return 0.0;
DoubleBits db1 = new DoubleBits(d1);
DoubleBits db2 = new DoubleBits(d2);
if (db1.getExponent() != db2.getExponent())
return 0.0;
int maxCommon = db1.numCommonMantissaBits(db2);
db1.zeroLowerBits(64 - (12 + maxCommon));
return db1.getDouble();
}
private double x;
private long xBits;
public DoubleBits( double x ) {
this.x = x;
xBits = Double.doubleToLongBits(x);
}
public double getDouble() {
return Double.longBitsToDouble(xBits);
}
/**
* Determines the exponent for the number
*/
public int biasedExponent() {
int signExp = (int) (xBits >> 52);
int exp = signExp & 0x07ff;
return exp;
}
/**
* Determines the exponent for the number
*/
public int getExponent() {
return biasedExponent() - EXPONENT_BIAS;
}
public void zeroLowerBits( int nBits ) {
long invMask = (1L << nBits) - 1L;
long mask = ~invMask;
xBits &= mask;
}
public int getBit( int i ) {
long mask = (1L << i);
return (xBits & mask) != 0 ? 1 : 0;
}
/**
* This computes the number of common most-significant bits in the mantissa.
* It does not count the hidden bit, which is always 1.
* It does not determine whether the numbers have the same exponent - if they do
* not, the value computed by this function is meaningless.
* @param db
* @return the number of common most-significant mantissa bits
*/
public int numCommonMantissaBits( DoubleBits db ) {
for( int i = 0; i < 52; i++ ) {
int bitIndex = i + 12;
if (getBit(i) != db.getBit(i))
return i;
}
return 52;
}
/**
* A representation of the Double bits formatted for easy readability
*/
public String toString() {
String numStr = Long.toBinaryString(xBits);
// 64 zeroes!
String zero64 = "0000000000000000000000000000000000000000000000000000000000000000";
String padStr = zero64 + numStr;
String bitStr = padStr.substring(padStr.length() - 64);
String str = bitStr.substring(0, 1) + " " + bitStr.substring(1, 12) + "(" + getExponent() + ") " + bitStr.substring(12)
+ " [ " + x + " ]";
return str;
}
}