Skip to content

Instantly share code, notes, and snippets.

@imbcmdth
Last active June 26, 2021 05:54
Show Gist options
  • Save imbcmdth/6338194 to your computer and use it in GitHub Desktop.
Save imbcmdth/6338194 to your computer and use it in GitHub Desktop.
Fast Approximate Functions for JavaScript based on https://code.google.com/p/fastapprox/
var Approx = {
fastlog2: (function () {
var a = new ArrayBuffer(4),
i = new Int32Array(a),
f = new Float32Array(a);
return function fasterLog2 (number) {
f[0] = number;
var t = i[0] * 1.1920928955078125e-7;
return t - 126.94269504;
};
}()),
log2: (function () {
var a = new ArrayBuffer(8),
i = new Int32Array(a),
f = new Float32Array(a);
return function fastLog2 (number) {
f[0] = number;
i[1] = (i[0] & 0x007FFFFF) | 0x3f000000;
var t = i[0] * 1.1920928955078125e-7;
return t - 124.22551499 - 1.498030302 * f[1] - 1.72587999 / (0.3520887068 + f[1]);
};
}()),
log: function fastLog (number) {
return 0.6931471805599453 * Approx.log2(number);
},
log10: function fastLog10 (number) {
return 0.30102999566398114 * Approx.log2(number);
},
pow2: (function () {
var a = new ArrayBuffer(4),
i = new Int32Array(a),
f = new Float32Array(a);
return function fastPow2 (number) {
var offset = (number < 0) ? 1 : 0,
clipNumber = (number < -126) ? -126 : number,
w = clipNumber | 0,
z = clipNumber - w + offset;
i[0] = ( (1 << 23) * (clipNumber + 121.2740575 + 27.7280233 / (4.84252568 - z) - 1.49012907 * z) );
return f[0];
}
})(),
exp: function fastExp (number) {
return Approx.pow2(1.442695040 * number);
},
fastpow2: (function () {
var a = new ArrayBuffer(4),
i = new Int32Array(a),
f = new Float32Array(a);
return function fasterPow2 (number) {
var clipNumber = (number < -126) ? -126 : number;
i[0] = ( (1 << 23) * (clipNumber + 126.94269504) );
return f[0];
}
}()),
fastexp: function fasterExp (number) {
return Approx.fastpow2(1.442695040 * number);
},
sinh: function fastSinH (number) {
return 0.5 * (Approx.exp(number) - Approx.exp(-number));
},
fastsinh: function fasterSinH (number) {
return 0.5 * (Approx.fastexp(number) - Approx.fastexp(-number));
},
cosh: function fastCosH (number) {
return 0.5 * (Approx.exp(number) + Approx.exp(-number));
},
fastcosh: function fasterCosH (number) {
return 0.5 * (Approx.fastexp(number) + Approx.fastexp(-number));
},
tanh: function fastTanH (number) {
return -1.0 + 2.0 / (1.0 + Approx.exp(-2.0 * number));
},
fasttanh: function fasterTanH (number) {
return -1.0 + 2.0 / (1.0 + Approx.fastexp(-2.0 * number));
},
pi: Math.PI,
halfpi: Math.PI / 2,
twopi: 2 * Math.PI,
invtwopi: 1 / (2 * Math.PI),
twooverpi: 2 / Math.PI,
fouroverpi: 4 / Math.PI,
fouroverpisq: 4 / (Math.PI * Math.PI),
halfpiminustwopi: Math.PI / 2 - 2 * Math.PI,
fasthalfsin: (function () {
var q = 0.78444488374548933,
a = new ArrayBuffer(16),
i = new Int32Array(a),
f = new Float32Array(a);
return function fastHalfSin (number) {
f[0] = 0.20363937680730309;
f[1] = 0.015124940802184233;
f[2] = -0.0032225901625579573;
f[3] = number;
var sign = i[3] & 0x80000000;
i[3] = i[3] & 0x7FFFFFFF;
var qpprox = Approx.fouroverpi * number - Approx.fouroverpisq * number * f[3];
var qpproxsq = qpprox * qpprox;
i[0] |= sign;
i[1] |= sign;
i[2] ^= sign;
return q * qpprox + qpproxsq * (f[0] + qpproxsq * (f[1] + qpproxsq * f[2]));
};
}()),
fasterhalfsin: (function () {
var q = 0.78444488374548933,
a = new ArrayBuffer(8),
i = new Int32Array(a),
f = new Float32Array(a);
return function fasterHalfSin (number) {
f[0] = 0.22308510060189463;
f[1] = number;
var sign = i[1] & 0x80000000;
i[1] &= 0x7FFFFFFF;
var qpprox = Approx.fouroverpi * number - Approx.fouroverpisq * number * f[1];
i[0] |= sign;
return qpprox * (q + f[0] * qpprox);
}
}()),
sin: function fastSin (number) {
var k = (number * Approx.invtwopi) | 0,
half = (number < 0) ? -0.5 : 0.5;
return Approx.fasthalfsin((half + k) * Approx.twopi - number);
},
fastsin: function fasterSin (number) {
var k = (number * Approx.invtwopi) | 0,
half = (number < 0) ? -0.5 : 0.5;
return Approx.fasterhalfsin((half + k) * Approx.twopi - number);
},
fasthalfcos: function fastHalfCos (number) {
var offset = (number > Approx.halfpi) ? Approx.halfpiminustwopi : Approx.halfpi;
return Approx.fasthalfsin(number + offset);
},
fasterhalfcos: (function () {
var p = 0.54641335845679634,
a = new ArrayBuffer(4),
i = new Int32Array(a),
f = new Float32Array(a);
return function fasterHalfCos (number) {
f[0] = number;
i[0] &= 0x7FFFFFFF;
var qpprox = 1.0 - Approx.twooverpi * f[0];
return qpprox + p * qpprox * (1.0 - qpprox * qpprox);
};
}()),
cos: function fastCos (number) {
return Approx.sin(number + Approx.halfpi);
},
fastcos: function fasterCos (number) {
return Approx.fastsin(number + Approx.halfpi);
},
fasthalftan: function fastHalfTan (number) {
return Approx.fasthalfsin(number) / Approx.fasthalfsin(number + Approx.halfpi);
},
fasterhalftan: function fasterHalfTan (number) {
return Approx.fasterhalfsin(number) / Approx.fasterhalfsin(number);
},
tan: function fastTan (number) {
var k = (number * Approx.invtwopi) | 0,
half = (number < 0) ? -0.5 : 0.5,
newNumber = number - (half + k) * Approx.twopi;
return Approx.fasthalfsin(newNumber) / Approx.fasthalfcos(newNumber);
},
fasttan: function fasterTan (number) {
var k = (number * Approx.invtwopi) | 0,
half = (number < 0) ? -0.5 : 0.5,
newNumber = number - (half + k) * Approx.twopi;
return Approx.fasterhalfsin(newNumber) / Approx.fasterhalfcos(newNumber);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment