/// <summary>
        ///   Reinterprets the memory contents of an integer value as a double precision
        ///   floating point value
        /// </summary>
        /// <param name="value">Integer whose memory contents to reinterpret</param>
        /// <returns>
        ///   The memory contents of the integer interpreted as a double precision
        ///   floating point value
        /// </returns>
        public static double ReinterpretAsDouble(long value)
        {
            DoubleLongUnion union = new DoubleLongUnion();

            union.Long = value;
            return(union.Double);
        }
Exemple #2
0
        /// <summary>
        /// Compares two numbers given some amount of allowed distance.
        /// https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
        /// </summary>
        /// <param name="x">The first number.</param>
        /// <param name="y">The second number.</param>
        /// <param name="maxUlp">The number of discreet floating point values that are allowed between the two values.</param>
        /// <returns><c>true</c> if the two values are equal, otherwise false.</returns>
        public static bool Equals(double x, double y, int maxUlp)
        {
            if (maxUlp <= 0)
            {
                throw new ArgumentOutOfRangeException("Max Ulp must be greater than 0.");
            }

            DoubleLongUnion xUnion = new DoubleLongUnion
            {
                Double = x
            };
            DoubleLongUnion yUnion = new DoubleLongUnion
            {
                Double = y
            };

            // Convert to 2s complement if negative.
            ulong xSignMask = xUnion.ULong >> Precision.DOUBLE_SHIFT_BITS;
            ulong ySignMask = yUnion.ULong >> Precision.DOUBLE_SHIFT_BITS;

            ulong xTemp = ((Precision.DOUBLE_BIT_MASK - xUnion.ULong) & xSignMask);

            xUnion.ULong = xTemp | (xUnion.ULong & ~xSignMask);

            // Convert to 2s complement if negative.
            ulong yTemp = ((Precision.DOUBLE_BIT_MASK - yUnion.ULong) & ySignMask);

            yUnion.ULong = yTemp | (yUnion.ULong & ~ySignMask);

            // Return if the difference <= maxUlp
            return(Math.Abs(xUnion.Long - yUnion.Long) <= maxUlp);
        }
        /// <summary>
        ///   Reinterprets the memory contents of a double precision floating point
        ///   value as an integer value
        /// </summary>
        /// <param name="value">
        ///   Double precision floating point value whose memory contents to reinterpret
        /// </param>
        /// <returns>
        ///   The memory contents of the double precision floating point value
        ///   interpreted as an integer
        /// </returns>
        public static long ReinterpretAsLong(double value)
        {
            DoubleLongUnion union = new DoubleLongUnion();

            union.Double = value;
            return(union.Long);
        }
        public static double ReinterpretAsDouble(long value)
        {
            DoubleLongUnion doubleLongUnion = default(DoubleLongUnion);

            doubleLongUnion.Long = value;
            return(doubleLongUnion.Double);
        }
        public static long ReinterpretAsLong(double value)
        {
            DoubleLongUnion doubleLongUnion = default(DoubleLongUnion);

            doubleLongUnion.Double = value;
            return(doubleLongUnion.Long);
        }
        /// <summary>Compares two double precision floating point values for equality</summary>
        /// <param name="left">First double precision floating point value to be compared</param>
        /// <param name="right">Second double precision floating point value t be compared</param>
        /// <param name="maxUlps">
        ///   Maximum number of representable double precision floating point values that are
        ///   allowed to be between the left and the right double precision floating point values
        /// </param>
        /// <returns>True if both numbers are equal or close to being equal</returns>
        /// <remarks>
        ///   <para>
        ///     Double precision floating point values can only represent a limited series of
        ///     natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004
        ///     can be stored in a double, but nothing between them.
        ///   </para>
        ///   <para>
        ///     This comparison will count how many possible double precision floating point
        ///     values are between the left and the right number. If the number of possible
        ///     values between both numbers is less than or equal to maxUlps, then the numbers
        ///     are considered as being equal.
        ///   </para>
        ///   <para>
        ///     Implementation partially follows the code outlined here:
        ///     http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/
        ///   </para>
        /// </remarks>
        public static bool AreAlmostEqualUlps(double left, double right, long maxUlps)
        {
            DoubleLongUnion leftUnion  = new DoubleLongUnion();
            DoubleLongUnion rightUnion = new DoubleLongUnion();

            leftUnion.Double  = left;
            rightUnion.Double = right;

            ulong leftSignMask  = (leftUnion.ULong >> 63);
            ulong rightSignMask = (rightUnion.ULong >> 63);

            ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask);

            leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask);

            ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask);

            rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask);

            if (leftSignMask != rightSignMask) // Overflow possible, check each against zero
            {
                if (Math.Abs(leftUnion.Long) > maxUlps || Math.Abs(rightUnion.Long) > maxUlps)
                {
                    return(false);
                }
            }

            // Either they have the same sign or both are very close to zero
            return(Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps);
        }
        static double Int64BitsToDouble(long value)
        {
            var union = new DoubleLongUnion {
                Int64 = value
            };

            return(union.Double);
        }
        static long DoubleToInt64Bits(double value)
        {
            var union = new DoubleLongUnion {
                Double = value
            };

            return(union.Int64);
        }
        /// <summary>
        /// Gets the binary representation of <see cref="double"/> <paramref name="number"/>.
        /// </summary>
        public static string GetBinaryRepresentation(this double number)
        {
            DoubleLongUnion union = new DoubleLongUnion {
                Double = number
            };
            ulong bits = union.Ulong;

            return(ConvertToString(bits));
        }
        public static bool AreAlmostEqualUlps(double left, double right, long maxUlps)
        {
            DoubleLongUnion doubleLongUnion  = default(DoubleLongUnion);
            DoubleLongUnion doubleLongUnion2 = default(DoubleLongUnion);

            doubleLongUnion.Double  = left;
            doubleLongUnion2.Double = right;
            ulong num  = doubleLongUnion.ULong >> 63;
            ulong num2 = doubleLongUnion2.ULong >> 63;
            ulong num3 = (9223372036854775808uL - doubleLongUnion.ULong) & num;

            doubleLongUnion.ULong = num3 | (doubleLongUnion.ULong & ~num);
            ulong num4 = (9223372036854775808uL - doubleLongUnion2.ULong) & num2;

            doubleLongUnion2.ULong = num4 | (doubleLongUnion2.ULong & ~num2);
            return(Math.Abs(doubleLongUnion.Long - doubleLongUnion2.Long) <= maxUlps);
        }
Exemple #11
0
        public static bool AreAlmostEqualUlps(double left, double right, long maxUlps)
        {
            DoubleLongUnion doubleLongUnion1 = new DoubleLongUnion();
            DoubleLongUnion doubleLongUnion2 = new DoubleLongUnion();

            doubleLongUnion1.Double = left;
            doubleLongUnion2.Double = right;
            ulong num1 = doubleLongUnion1.ULong >> 63;
            ulong num2 = doubleLongUnion2.ULong >> 63;
            ulong num3 = 9223372036854775808UL - doubleLongUnion1.ULong & num1;

            doubleLongUnion1.ULong = num3 | doubleLongUnion1.ULong & ~num1;
            ulong num4 = 9223372036854775808UL - doubleLongUnion2.ULong & num2;

            doubleLongUnion2.ULong = num4 | doubleLongUnion2.ULong & ~num2;
            return(Math.Abs(doubleLongUnion1.Long - doubleLongUnion2.Long) <= maxUlps);
        }
        /// <summary>Compares two double precision floating point values for equality</summary>
        /// <param name="left">First double precision floating point value to be compared</param>
        /// <param name="right">Second double precision floating point value t be compared</param>
        /// <param name="maxUlps">
        ///   Maximum number of representable double precision floating point values that are
        ///   allowed to be between the left and the right double precision floating point values
        /// </param>
        /// <returns>True if both numbers are equal or close to being equal</returns>
        /// <remarks>
        ///   <para>
        ///     Double precision floating point values can only represent a limited series of
        ///     natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004
        ///     can be stored in a double, but nothing inbetween them.
        ///   </para>
        ///   <para>
        ///     This comparison will count how many possible double precision floating point
        ///     values are between the left and the right number. If the number of possible
        ///     values between both numbers is less than or equal to maxUlps, then the numbers
        ///     are considered as being equal.
        ///   </para>
        ///   <para>
        ///     Implementation partially follows the code outlined here:
        ///     http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/
        ///   </para>
        /// </remarks>
        public static bool AreAlmostEqualUlps(double left, double right, long maxUlps)
        {
            DoubleLongUnion leftUnion  = new DoubleLongUnion();
            DoubleLongUnion rightUnion = new DoubleLongUnion();

            leftUnion.Double  = left;
            rightUnion.Double = right;

            ulong leftSignMask  = (leftUnion.ULong >> 63);
            ulong rightSignMask = (rightUnion.ULong >> 63);

            ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask);

            leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask);

            ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask);

            rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask);

            return(Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps);
        }
Exemple #13
0
        /// <summary>
        /// Convert double number to binary string
        /// </summary>
        /// <param name="number"></param>
        /// <returns>Binary string</returns>
        public static string GetBinaryString(this double number)
        {
            long longBytes = new DoubleLongUnion {
                Double = number
            }.Long;
            string resultString = string.Empty;

            for (int i = 0; i < DoubleBits; i++)
            {
                if (longBytes == longBytes >> 1 << 1)
                {
                    resultString = "0" + resultString;
                }
                else
                {
                    resultString = "1" + resultString;
                }

                longBytes >>= 1;
            }

            return(resultString);
        }
        /// <summary>Compares two double precision floating point values for equality</summary>
        /// <param name="left">First double precision floating point value to be compared</param>
        /// <param name="right">Second double precision floating point value t be compared</param>
        /// <param name="maxUlps">
        ///   Maximum number of representable double precision floating point values that are
        ///   allowed to be between the left and the right double precision floating point values
        /// </param>
        /// <returns>True if both numbers are equal or close to being equal</returns>
        /// <remarks>
        ///   <para>
        ///     Double precision floating point values can only represent a limited series of
        ///     natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004
        ///     can be stored in a double, but nothing between them.
        ///   </para>
        ///   <para>
        ///     This comparison will count how many possible double precision floating point
        ///     values are between the left and the right number. If the number of possible
        ///     values between both numbers is less than or equal to maxUlps, then the numbers
        ///     are considered as being equal.
        ///   </para>
        ///   <para>
        ///     Implementation partially follows the code outlined here:
        ///     http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/
        ///   </para>
        /// </remarks>
        public static bool AreAlmostEqualUlps(double left, double right, long maxUlps)
        {
            DoubleLongUnion leftUnion  = new DoubleLongUnion();
            DoubleLongUnion rightUnion = new DoubleLongUnion();

            leftUnion.Double  = left;
            rightUnion.Double = right;

            ulong leftSignMask  = (leftUnion.ULong >> 63);
            ulong rightSignMask = (rightUnion.ULong >> 63);

            ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask);

            leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask);

            ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask);

            rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask);

            if (leftSignMask != rightSignMask) // Overflow possible, check each against zero
            {
                // This check is specifically used to trap the case of 0 == -0
                // In IEEE floating point maths, -0 is converted to Double.MinValue, which cannot be used with
                // Math.Abs(...) below due to overflow issues. This should only match the 0 == -0 condition.
                if (left == right)
                {
                    return(true);
                }
                if (Math.Abs(leftUnion.Long) > maxUlps || Math.Abs(rightUnion.Long) > maxUlps)
                {
                    return(false);
                }
            }

            // Either they have the same sign or both are very close to zero
            return(Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps);
        }
 /// <summary>
 ///   Reinterprets the memory contents of an integer value as a double precision
 ///   floating point value
 /// </summary>
 /// <param name="value">Integer whose memory contents to reinterpret</param>
 /// <returns>
 ///   The memory contents of the integer interpreted as a double precision
 ///   floating point value
 /// </returns>
 public static double ReinterpretAsDouble(long value)
 {
     DoubleLongUnion union = new DoubleLongUnion();
     union.Long = value;
     return union.Double;
 }
 /// <summary>
 ///   Reinterprets the memory contents of a double precision floating point
 ///   value as an integer value
 /// </summary>
 /// <param name="value">
 ///   Double precision floating point value whose memory contents to reinterpret
 /// </param>
 /// <returns>
 ///   The memory contents of the double precision floating point value
 ///   interpreted as an integer
 /// </returns>
 public static long ReinterpretAsLong(double value)
 {
     DoubleLongUnion union = new DoubleLongUnion();
     union.Double = value;
     return union.Long;
 }
        /// <summary>Compares two double precision floating point values for equality</summary>
        /// <param name="left">First double precision floating point value to be compared</param>
        /// <param name="right">Second double precision floating point value t be compared</param>
        /// <param name="maxUlps">
        ///   Maximum number of representable double precision floating point values that are
        ///   allowed to be between the left and the right double precision floating point values
        /// </param>
        /// <returns>True if both numbers are equal or close to being equal</returns>
        /// <remarks>
        ///   <para>
        ///     Double precision floating point values can only represent a limited series of
        ///     natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004
        ///     can be stored in a double, but nothing inbetween them.
        ///   </para>
        ///   <para>
        ///     This comparison will count how many possible double precision floating point
        ///     values are between the left and the right number. If the number of possible
        ///     values between both numbers is less than or equal to maxUlps, then the numbers
        ///     are considered as being equal.
        ///   </para>
        ///   <para>
        ///     Implementation partially follows the code outlined here:
        ///     http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/
        ///   </para>
        /// </remarks>
        public static bool AreAlmostEqualUlps(double left, double right, long maxUlps)
        {
            DoubleLongUnion leftUnion = new DoubleLongUnion();
            DoubleLongUnion rightUnion = new DoubleLongUnion();

            leftUnion.Double = left;
            rightUnion.Double = right;

            ulong leftSignMask = (leftUnion.ULong >> 63);
            ulong rightSignMask = (rightUnion.ULong >> 63);

            ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask);
            leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask);

            ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask);
            rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask);

            return (Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps);
        }
Exemple #18
0
        /// <summary>Compares two double precision floating point _values for equality</summary>
        /// <param name="left">First double precision floating point value to be compared</param>
        /// <param name="right">Second double precision floating point value t be compared</param>
        /// <param name="maxUlps">
        ///   Maximum number of representable double precision floating point _values that are
        ///   allowed to be between the left and the right double precision floating point _values
        /// </param>
        /// <returns>True if both numbers are equal or close to being equal</returns>
        /// <remarks>
        ///   <para>
        ///     Double precision floating point _values can only represent a limited series of
        ///     natural numbers. For example, the _values 2.0000000000000000 and 2.0000000000000004
        ///     can be stored in a double, but nothing inbetween them.
        ///   </para>
        ///   <para>
        ///     This comparison will count how many possible double precision floating point
        ///     _values are between the left and the right number. If the number of possible
        ///     _values between both numbers is less than or equal to maxUlps, then the numbers
        ///     are considered as being equal.
        ///   </para>
        ///   <para>
        ///     Implementation partially follows the code outlined here:
        ///     http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/
        ///   </para>
        /// </remarks>
        public static bool AreAlmostEqualUlps(double left, double right, long maxUlps)
        {
            DoubleLongUnion leftUnion = new DoubleLongUnion();
            DoubleLongUnion rightUnion = new DoubleLongUnion();

            leftUnion.Double = left;
            rightUnion.Double = right;

            ulong leftSignMask = (leftUnion.ULong >> 63);
            ulong rightSignMask = (rightUnion.ULong >> 63);

            ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask);
            leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask);

            ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask);
            rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask);

            if (leftSignMask != rightSignMask) // Overflow possible, check each against zero
            {
                if (Math.Abs(leftUnion.Long) > maxUlps || Math.Abs(rightUnion.Long) > maxUlps)
                    return false;
            }

            // Either they have the same sign or both are very close to zero
            return Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps;
        }