/** * @overload static bool AreEqual(float first, float second, float marginOfError, int ulpTolerance) * */ public static bool AreEqual(float first, float second, float marginOfError, int ulpTolerance) { // When numbers are very close to zero, this initial check of absolute values is needed. Otherwise // we can safely use the ULP difference. float absoluteDiff = Math.Abs(first - second); if (absoluteDiff <= marginOfError) { return(true); } SingleInfo firstInfo = new SingleInfo(first); SingleInfo secondInfo = new SingleInfo(second); // Different signs mean the numbers don't match, period. if (firstInfo.IsNegative != secondInfo.IsNegative) { return(false); } // Find the difference in ULPs (unit of least precision). int ulpDiff = Math.Abs(firstInfo.Bits - secondInfo.Bits); if (ulpDiff <= ulpTolerance) { return(true); } return(false); }
/** * @overload static int Boundary(float value, float marginOfError, int ulpTolerance, int boundaryScale) * */ public static int Boundary(float value, float marginOfError, int ulpTolerance, int boundaryScale) { SingleInfo valueInfo = new SingleInfo(Math.Abs(value)); SingleInfo valueWithErrorInfo = new SingleInfo(Math.Abs(value) + marginOfError); int ulpBoundary = ulpTolerance * boundaryScale; int marginBoundary = (valueWithErrorInfo.Bits - valueInfo.Bits) * boundaryScale; return(Math.Max(ulpBoundary, marginBoundary)); }
/** * @overload static int ULPDistance(float first, float second) * */ public static int ULPDistance(float first, float second) { SingleInfo firstInfo = new SingleInfo(first); SingleInfo secondInfo = new SingleInfo(second); if (firstInfo.IsNegative != secondInfo.IsNegative) { throw new ArgumentException("Numbers have mixed signs; cannot calculate the ULP distance across the 0 boundary."); } return(Math.Abs(firstInfo.Bits - secondInfo.Bits)); }
/** * @overload static float ULP(float value) * */ public static float ULP(float value) { if (Single.IsNaN(value)) { return(Single.NaN); } else if (Single.IsPositiveInfinity(value) || Single.IsNegativeInfinity(value)) { return(Single.PositiveInfinity); } else if (value == 0.0) { return(Single.Epsilon); } else if (Math.Abs(value) == Single.MaxValue) { return(MaxFloatULP); } SingleInfo info = new SingleInfo(value); return(Math.Abs((float)(info.Bits + 1) - value)); }
public SingleInfo(float value) { _value = value; _bits = SingleInfo.SingleToInt32Bits(value); }