Class CommonBits

  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.precision;
 14  
 15 /**
 16  * Determines the maximum number of common most-significant
 17  * bits in the mantissa of one or numbers.
 18  * Can be used to compute the double-precision number which
 19  * is represented by the common bits.
 20  * If there are no common bits, the number computed is 0.0.
 21  *
 22  * @version 1.7
 23  */
 24 public class CommonBits {
 25  
 26   /**
 27    * Computes the bit pattern for the sign and exponent of a
 28    * double-precision number.
 29    * 
 30    * @param num
 31    * @return the bit pattern for the sign and exponent
 32    */
 33   public static long signExpBits(long num)
 34   {
 35     return num >> 52;
 36   }
 37  
 38   /**
 39  * This computes the number of common most-significant bits in the mantissas
 40  * of two double-precision numbers.
 41  * It does not count the hidden bit, which is always 1.
 42  * It does not determine whether the numbers have the same exponent - if they do
 43  * not, the value computed by this function is meaningless.
 44  * 
 45  * @param num1 the first number
 46  * @param num2 the second number
 47  * @return the number of common most-significant mantissa bits
 48  */
 49   public static int numCommonMostSigMantissaBits(long num1, long num2)
 50   {
 51     int count = 0;
 52     for (int i = 52; i >= 0; i--)
 53     {
 54       if (getBit(num1, i) != getBit(num2, i))
 55         return count;
 56       count++;
 57     }
 58     return 52;
 59   }
 60  
 61   /**
 62    * Zeroes the lower n bits of a bitstring.
 63    * 
 64    * @param bits the bitstring to alter
 65    * @return the zeroed bitstring
 66    */
 67   public static long zeroLowerBits(long bits, int nBits)
 68   {
 69     long invMask = (1L << nBits) - 1L;
 70     long mask = ~ invMask;
 71     long zeroed = bits & mask;
 72     return zeroed;
 73   }
 74  
 75   /**
 76    * Extracts the i'th bit of a bitstring.
 77    * 
 78    * @param bits the bitstring to extract from
 79    * @param i the bit to extract
 80    * @return the value of the extracted bit
 81    */
 82   public static int getBit(long bits, int i)
 83   {
 84     long mask = (1L << i);
 85     return (bits & mask) != 0 ? 1 : 0;
 86   }
 87  
 88   private boolean isFirst = true;
 89   private int commonMantissaBitsCount = 53;
 90   private long commonBits = 0;
 91   private long commonSignExp;
 92  
 93   public CommonBits() {
 94   }
 95  
 96   public void add(double num)
 97   {
 98     long numBits = Double.doubleToLongBits(num);
 99     if (isFirst) {
100       commonBits = numBits;
101       commonSignExp = signExpBits(commonBits);
102       isFirst = false;
103       return;
104     }
105  
106     long numSignExp = signExpBits(numBits);
107     if (numSignExp != commonSignExp) {
108       commonBits = 0;
109       return;
110     }
111  
112 //    System.out.println(toString(commonBits));
113 //    System.out.println(toString(numBits));
114     commonMantissaBitsCount = numCommonMostSigMantissaBits(commonBits, numBits);
115     commonBits = zeroLowerBits(commonBits, 64 - (12 + commonMantissaBitsCount));
116 //    System.out.println(toString(commonBits));
117   }
118  
119   public double getCommon()
120   {
121     return Double.longBitsToDouble(commonBits);
122   }
123   /**
124    * A representation of the Double bits formatted for easy readability
125    */
126   public String toString(long bits)
127   {
128     double x = Double.longBitsToDouble(bits);
129     String numStr = Long.toBinaryString(bits);
130     String padStr = "0000000000000000000000000000000000000000000000000000000000000000" + numStr;
131     String bitStr = padStr.substring(padStr.length() - 64);
132     String str = bitStr.substring(01) + "  "
133         + bitStr.substring(112) + "(exp) "
134         + bitStr.substring(12)
135         + " [ " + x + " ]";
136     return str;
137   }
138  
139 }
140