using GisSharpBlog.NetTopologySuite.Utilities; using BitConverter = System.BitConverter; namespace GisSharpBlog.NetTopologySuite.Precision { /// /// Determines the maximum number of common most-significant /// bits in the mantissa of one or numbers. /// Can be used to compute the double-precision number which /// is represented by the common bits. /// If there are no common bits, the number computed is 0.0. /// public class CommonBits { private bool isFirst = true; private int commonMantissaBitsCount = 53; private long commonBits = 0; private long commonSignExp; /// /// /// public double Common { get { return BitConverter.Int64BitsToDouble(commonBits); } } /// /// Computes the bit pattern for the sign and exponent of a /// double-precision number. /// /// /// The bit pattern for the sign and exponent. public static long SignExpBits(long num) { return num >> 52; } /// /// This computes the number of common most-significant bits in the mantissas /// of two double-precision numbers. /// 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. /// /// /// /// /// The number of common most-significant mantissa bits. public static int NumCommonMostSigMantissaBits(long num1, long num2) { int count = 0; for (int i = 52; i >= 0; i--) { if (GetBit(num1, i) != GetBit(num2, i)) { return count; } count++; } return 52; } /// /// Zeroes the lower n bits of a bitstring. /// /// The bitstring to alter. /// the number of bits to zero. /// The zeroed bitstring. public static long ZeroLowerBits(long bits, int nBits) { long invMask = (1L << nBits) - 1L; long mask = ~invMask; long zeroed = bits & mask; return zeroed; } /// /// Extracts the i'th bit of a bitstring. /// /// The bitstring to extract from. /// The bit to extract. /// The value of the extracted bit. public static int GetBit(long bits, int i) { long mask = (1L << i); return (bits & mask) != 0 ? 1 : 0; } /// /// /// /// public void Add(double num) { long numBits = BitConverter.DoubleToInt64Bits(num); if (isFirst) { commonBits = numBits; commonSignExp = SignExpBits(commonBits); isFirst = false; return; } long numSignExp = SignExpBits(numBits); if (numSignExp != commonSignExp) { commonBits = 0; return; } commonMantissaBitsCount = NumCommonMostSigMantissaBits(commonBits, numBits); commonBits = ZeroLowerBits(commonBits, 64 - (12 + commonMantissaBitsCount)); } /// /// A representation of the Double bits formatted for easy readability /// /// /// public string ToString(long bits) { double x = BitConverter.Int64BitsToDouble(bits); string numStr = HexConverter.ConvertAny2Any(bits.ToString(), 10, 2); string padStr = "0000000000000000000000000000000000000000000000000000000000000000" + numStr; string bitStr = padStr.Substring(padStr.Length - 64); string str = bitStr.Substring(0, 1) + " " + bitStr.Substring(1, 12) + "(exp) " + bitStr.Substring(12) + " [ " + x + " ]"; return str; } } }