The built-in JavaScript Math library is used in virtually every Node.js application, from generating random ids to calculating exponential back-off times to computing basic performance metrics. When using the Math library, most developers simply assume that the underlying implementations are accurate, performant, and correctly implemented. In this presentation, Athan Reines will discuss why this assumption is often false and show the various ways in which the standard library is broken.
The presentation will present the algorithms used, their performance and accuracy, and how they have downstream effects on users of these libraries. The presentation will conclude by highlighting how community solutions are stepping up to fix these problems and identity opportunities for additional improvements.
12. Math.sin/Math.cos
var x = Math.pow( 2, 120 );
// returns 1.329227995784916e+36
var y = Math.sin( x );
// returns: -0.8783788442551665
// expected: 0.377820109360752
y = Math.cos( x );
// returns: 0.47796506772457525
// expected: -0.9258790228548378
Node v0.10
13. NaN
var nan1 = 0.0 / 0.0;
var nan2 = Number.POSITIVE_INFINITY / Number.POSITIVE_INFINITY;
var arr = [ nan1, nan2 ];
var FLOAT64_VIEW = new Float64Array( arr );
var INT32_VIEW = new Int32Array( FLOAT64_VIEW.buffer );
var isnan1 = ( FLOAT64_VIEW[0] !== FLOAT64_VIEW[0] );
// returns true
var isnan2 = ( FLOAT64_VIEW[1] !== FLOAT64_VIEW[1] );
// returns true
var bool = ( nan1 !== nan2 );
// returns true
Node v0.12 Node v4 Node v6 Node v7
Node v0.10*
14. Math.pow
var x = Math.pow( 10, 308 );
// returns: 1.0000000000000006e+308
// expected: 1.0e+308
Node v0.10+
15. Algorithm
function pow( x, y ) {
var m = x;
var n = y;
var p = 1;
while ( n !== 0 ) {
if ( ( n & 1 ) !== 0 ) {
p *= m;
}
m *= m;
if ( ( n & 2 ) !== 0 ) {
p *= m;
}
m *= m;
n >>= 2;
}
return p;
16. Math.atanh
var y = Math.atanh( 1.0e-10 );
// returns: 1.000000082640371e-10
// expected: 1.0e-10
Node v0.12 Node v4 Node v6
19. Algorithm
function asinh( x ) {
if ( x === 0 || !isFinite( x ) ) {
return x;
}
if ( x > 0 ) {
return Math.log( x + Math.sqrt( x*x + 1 ) );
}
return -Math.log( -x + Math.sqrt( x*x + 1 ) );
}
20. Algorithm
function asinh( x ) {
var sgn;
var xx;
var t;
if ( isnan( x ) || isinfinite( x ) ) {
return x;
}
if ( x < 0.0 ) {
x = -x;
sgn = true;
}
// Case: |x| < 2**-28
if ( x < NEAR_ZERO ) {
t = x;
}
// Case: |x| > 2**28
21. Math.exp
var y = Math.exp( 100.0 );
// returns: 2.6881171418161485e+43
// expected: 2.6881171418161356e+43
Node v0.12 Node v4 Node v6