This question is related to this, but because I try to optimize the function for speed, I ask this question as a new one.
I'm translating new floats Clipper library from Angus Johnson to Javascript, and there is a function IsAlmostEqual
, which compares doubles for equality using Ulps technique.
The original C# function is here:
public static bool IsAlmostEqual(double A, double B)
{
//http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
const int maxUlps = 10000;
Int64 aInt = BitConverter.DoubleToInt64Bits(A);
if (aInt < 0) aInt = Int64.MinValue - aInt;
Int64 bInt = BitConverter.DoubleToInt64Bits(B);
if (bInt < 0) bInt = Int64.MinValue - bInt;
Int64 sub = unchecked(aInt - bInt);
if (sub > aInt != bInt < 0) return false;
return (sub <= 0 && sub > -maxUlps) || (sub > 0 && sub < maxUlps);
}
And my translation of it (in JSBIN):
var IsAlmostEqual_Ulps = function(A, B)
{
DoubleToInt64Bits(A, aInt);
if(aInt.hi < 0) aInt = subtract(Int64_MinValue, aInt);
DoubleToInt64Bits(B, bInt);
if(bInt.hi < 0) bInt = subtract(Int64_MinValue, bInt);
var sub = subtract(aInt, bInt);
if (sub.hi < 0) sub = negate(sub);
if (lessthan(sub, maxUlps)) return true;
return false;
}
My Javascript version seems to work OK according to 83 sample values, but the problem is the slowness, which mainly comes from DoubleToInt64Bits
function. When the code is executed as a standalone html (outside JSBIN), the total run time is about 2267 ms, of which DoubleToInt64Bits
takes 983 ms.
The problematic (=slow) DoubleToInt64Bits
is here:
function DoubleToInt64Bits(A, xInt)
{
(new Float64Array(buf))[0] = A;
xInt.lo = (new Uint32Array(buf))[0] | 0;
xInt.hi = (new Int32Array(buf))[1] | 0;
}
Is there any way to make DoubleToInt64Bits
faster?