Pregunta

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?

¿Fue útil?

Solución

A DataView is a more appropriate class to read out different types from a buffer rather than creating different typed arrays on the buffer. Here is your DoubleToInt64Bits method rewritten to use a DataView.

function DoubleToInt64Bits(A, xInt)
{
    var dataView = new DataView(buf);
    dataView.setFloat64(0, A);
    xInt.lo = dataView.getUint32(4) | 0;
    xInt.hi = dataView.getInt32(0) | 0;
}

This cuts my run time from ~1500ms to ~850ms.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top