Class DoubleBits

  1  
  2 /*
  3  * Copyright (c) 2016 Vivid Solutions.
  4  *
  5  * All rights reserved. This program and the accompanying materials
  6  * are made available under the terms of the Eclipse Public License 2.0
  7  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  8  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  9  * and the Eclipse Distribution License is available at
 10  *
 11  * http://www.eclipse.org/org/documents/edl-v10.php.
 12  */
 13 package org.locationtech.jts.index.quadtree;
 14  
 15 /**
 16  * DoubleBits manipulates Double numbers
 17  * by using bit manipulation and bit-field extraction.
 18  * For some operations (such as determining the exponent)
 19  * this is more accurate than using mathematical operations
 20  * (which suffer from round-off error).
 21  * <p>
 22  * The algorithms and constants in this class
 23  * apply only to IEEE-754 double-precision floating point format.
 24  *
 25  * @version 1.7
 26  */
 27 public class DoubleBits {
 28  
 29   public static final int EXPONENT_BIAS = 1023;
 30  
 31   public static double powerOf2(int exp)
 32   {
 33     if (exp > 1023 || exp < -1022)
 34       throw new IllegalArgumentException("Exponent out of bounds");
 35     long expBias = exp + EXPONENT_BIAS;
 36     long bits = expBias << 52;
 37     return Double.longBitsToDouble(bits);
 38   }
 39  
 40   public static int exponent(double d)
 41   {
 42     DoubleBits db = new DoubleBits(d);
 43     return db.getExponent();
 44   }
 45  
 46   public static double truncateToPowerOfTwo(double d)
 47   {
 48     DoubleBits db = new DoubleBits(d);
 49     db.zeroLowerBits(52);
 50     return db.getDouble();
 51   }
 52  
 53   public static String toBinaryString(double d)
 54   {
 55     DoubleBits db = new DoubleBits(d);
 56     return db.toString();
 57   }
 58  
 59   public static double maximumCommonMantissa(double d1, double d2)
 60   {
 61     if (d1 == 0.0 || d2 == 0.0return 0.0;
 62  
 63     DoubleBits db1 = new DoubleBits(d1);
 64     DoubleBits db2 = new DoubleBits(d2);
 65  
 66     if (db1.getExponent() != db2.getExponent()) return 0.0;
 67  
 68     int maxCommon = db1.numCommonMantissaBits(db2);
 69     db1.zeroLowerBits(64 - (12 + maxCommon));
 70     return db1.getDouble();
 71   }
 72  
 73   private double x;
 74   private long xBits;
 75  
 76   public DoubleBits(double x)
 77   {
 78     this.x = x;
 79     xBits = Double.doubleToLongBits(x);
 80   }
 81  
 82   public double getDouble()
 83   {
 84     return Double.longBitsToDouble(xBits);
 85   }
 86  
 87   /**
 88    * Determines the exponent for the number
 89    */
 90   public int biasedExponent()
 91   {
 92     int signExp = (int) (xBits >> 52);
 93     int exp = signExp & 0x07ff;
 94     return exp;
 95   }
 96  
 97   /**
 98    * Determines the exponent for the number
 99    */
100   public int getExponent()
101   {
102     return biasedExponent() - EXPONENT_BIAS;
103   }
104  
105   public void zeroLowerBits(int nBits)
106   {
107     long invMask = (1L << nBits) - 1L;
108     long mask = ~ invMask;
109     xBits &= mask;
110   }
111  
112   public int getBit(int i)
113   {
114     long mask = (1L << i);
115     return (xBits & mask) != 0 ? 1 : 0;
116   }
117  
118   /**
119    * This computes the number of common most-significant bits in the mantissa.
120    * It does not count the hidden bit, which is always 1.
121    * It does not determine whether the numbers have the same exponent - if they do
122    * not, the value computed by this function is meaningless.
123    * @param db
124    * @return the number of common most-significant mantissa bits
125    */
126   public int numCommonMantissaBits(DoubleBits db)
127   {
128     for (int i = 0; i < 52; i++)
129     {
130       if (getBit(i) != db.getBit(i))
131         return i;
132     }
133     return 52;
134   }
135  
136   /**
137    * A representation of the Double bits formatted for easy readability
138    */
139   public String toString()
140   {
141     String numStr = Long.toBinaryString(xBits);
142     // 64 zeroes!
143     String zero64 = "0000000000000000000000000000000000000000000000000000000000000000";
144     String padStr =  zero64 + numStr;
145     String bitStr = padStr.substring(padStr.length() - 64);
146     String str = bitStr.substring(01) + "  "
147         + bitStr.substring(112) + "(" + getExponent() + ") "
148         + bitStr.substring(12)
149         + " [ " + x + " ]";
150     return str;
151   }
152 }
153