setJitCompilerOption("ion.warmup.trigger", 50); var f32 = new Float32Array(10); function test(setup, f) { if (f === undefined) { f = setup; setup = function(){}; } setup(); for(var n = 200; n; --n) { f(); } } // Basic arithmetic function setupBasicArith() { f32[0] = -Infinity; f32[1] = -1; f32[2] = -0; f32[3] = 0; f32[4] = 1.337; f32[5] = 42; f32[6] = Infinity; f32[7] = NaN; } function basicArith() { for (var i = 0; i < 7; ++i) { var opf = Math.fround(f32[i] + f32[i+1]); var opd = (1 / (1 / f32[i])) + f32[i+1]; assertFloat32(opf, true); assertFloat32(opd, false); assertEq(opf, Math.fround(opd)); opf = Math.fround(f32[i] - f32[i+1]); opd = (1 / (1 / f32[i])) - f32[i+1]; assertFloat32(opf, true); assertFloat32(opd, false); assertEq(opf, Math.fround(opd)); opf = Math.fround(f32[i] * f32[i+1]); opd = (1 / (1 / f32[i])) * f32[i+1]; assertFloat32(opf, true); assertFloat32(opd, false); assertEq(opf, Math.fround(opd)); opf = Math.fround(f32[i] / f32[i+1]); opd = (1 / (1 / f32[i])) / f32[i+1]; assertFloat32(opf, true); assertFloat32(opd, false); assertEq(opf, Math.fround(opd)); } } test(setupBasicArith, basicArith); // MAbs function setupAbs() { f32[0] = -0; f32[1] = 0; f32[2] = -3.14159; f32[3] = 3.14159; f32[4] = -Infinity; f32[5] = Infinity; f32[6] = NaN; } function abs() { for(var i = 0; i < 7; ++i) { assertEq( Math.fround(Math.abs(f32[i])), Math.abs(f32[i]) ); } } test(setupAbs, abs); // MSqrt function setupSqrt() { f32[0] = 0; f32[1] = 1; f32[2] = 4; f32[3] = -1; f32[4] = Infinity; f32[5] = NaN; f32[6] = 13.37; } function sqrt() { for(var i = 0; i < 7; ++i) { var sqrtf = Math.fround(Math.sqrt(f32[i])); var sqrtd = 1 + Math.sqrt(f32[i]) - 1; // force no float32 by chaining arith ops assertEq( sqrtf, Math.fround(sqrtd) ); } } test(setupSqrt, sqrt); // MMinMax function setupMinMax() { f32[0] = -0; f32[1] = 0; f32[2] = 1; f32[3] = 4; f32[4] = -1; f32[5] = Infinity; f32[6] = NaN; f32[7] = 13.37; f32[8] = -Infinity; f32[9] = Math.pow(2,31) - 1; } function minMax() { for(var i = 0; i < 9; ++i) { for(var j = 0; j < 9; j++) { var minf = Math.fround(Math.min(f32[i], f32[j])); var mind = 1 / (1 / Math.min(f32[i], f32[j])); // force no float32 by chaining arith ops assertFloat32(minf, true); assertFloat32(mind, false); assertEq( minf, Math.fround(mind) ); var maxf = Math.fround(Math.max(f32[i], f32[j])); var maxd = 1 / (1 / Math.max(f32[i], f32[j])); // force no float32 by chaining arith ops assertFloat32(maxf, true); assertFloat32(maxd, false); assertEq( maxf, Math.fround(maxd) ); } } } test(setupMinMax, minMax); // MTruncateToInt32 // The only way to get a MTruncateToInt32 with a Float32 input is to use Math.imul function setupTruncateToInt32() { f32[0] = -1; f32[1] = 4; f32[2] = 5.13; } function truncateToInt32() { assertEq( Math.imul(f32[0], f32[1]), Math.imul(-1, 4) ); assertEq( Math.imul(f32[1], f32[2]), Math.imul(4, 5) ); } test(setupTruncateToInt32, truncateToInt32); // MCompare function comp() { for(var i = 0; i < 9; ++i) { assertEq( f32[i] < f32[i+1], true ); } } function setupComp() { f32[0] = -Infinity; f32[1] = -1; f32[2] = -0.01; f32[3] = 0; f32[4] = 0.01; f32[5] = 1; f32[6] = 10; f32[7] = 13.37; f32[8] = 42; f32[9] = Infinity; } test(setupComp, comp); // MNot function setupNot() { f32[0] = -0; f32[1] = 0; f32[2] = 1; f32[3] = NaN; f32[4] = Infinity; f32[5] = 42; f32[6] = -23; } function not() { assertEq( !f32[0], true ); assertEq( !f32[1], true ); assertEq( !f32[2], false ); assertEq( !f32[3], true ); assertEq( !f32[4], false ); assertEq( !f32[5], false ); assertEq( !f32[6], false ); } test(setupNot, not); // MToInt32 var str = "can haz cheezburger? okthxbye;"; function setupToInt32() { f32[0] = 0; f32[1] = 1; f32[2] = 2; f32[3] = 4; f32[4] = 5; } function testToInt32() { assertEq(str[f32[0]], 'c'); assertEq(str[f32[1]], 'a'); assertEq(str[f32[2]], 'n'); assertEq(str[f32[3]], 'h'); assertEq(str[f32[4]], 'a'); } test(setupToInt32, testToInt32); function setupBailoutToInt32() { f32[0] = .5; } function testBailoutToInt32() { assertEq(typeof str[f32[0]], 'undefined'); } test(setupBailoutToInt32, testBailoutToInt32); // MMath (no trigo - see also testFloat32-trigo.js function assertNear(a, b) { var r = (a != a && b != b) || Math.abs(a-b) < 1e-1 || a === b; if (!r) { print('Precision error: '); print(new Error().stack); print('Got', a, ', expected near', b); assertEq(false, true); } } function setupOtherMath() { setupComp(); f32[8] = 4.2; } function otherMath() { for (var i = 0; i < 9; ++i) { assertNear(Math.fround(Math.exp(f32[i])), Math.exp(f32[i])); assertNear(Math.fround(Math.log(f32[i])), Math.log(f32[i])); } }; test(setupOtherMath, otherMath); function setupFloor() { f32[0] = -5.5; f32[1] = -0.5; f32[2] = 0; f32[3] = 1.5; } function setupFloorDouble() { f32[4] = NaN; f32[5] = -0; f32[6] = Infinity; f32[7] = -Infinity; f32[8] = Math.pow(2,31); // too big to fit into a int } function testFloor() { for (var i = 0; i < 4; ++i) { var f = Math.floor(f32[i]); assertFloat32(f, false); // f is an int32 var g = Math.floor(-0 + f32[i]); assertFloat32(g, false); assertEq(f, g); } } function testFloorDouble() { for (var i = 4; i < 9; ++i) { var f = Math.fround(Math.floor(f32[i])); assertFloat32(f, true); var g = Math.floor(-0 + f32[i]); assertFloat32(g, false); assertEq(f, g); } } test(setupFloor, testFloor); test(setupFloorDouble, testFloorDouble); function setupRound() { f32[0] = -5.5; f32[1] = -0.6; f32[2] = 1.5; f32[3] = 1; } function setupRoundDouble() { f32[4] = NaN; f32[5] = -0.49; // rounded to -0 f32[6] = Infinity; f32[7] = -Infinity; f32[8] = Math.pow(2,31); // too big to fit into a int f32[9] = -0; } function testRound() { for (var i = 0; i < 4; ++i) { var r32 = Math.round(f32[i]); assertFloat32(r32, false); // r32 is an int32 var r64 = Math.round(-0 + f32[i]); assertFloat32(r64, false); assertEq(r32, r64); } } function testRoundDouble() { for (var i = 4; i < 10; ++i) { var r32 = Math.fround(Math.round(f32[i])); assertFloat32(r32, true); var r64 = Math.round(-0 + f32[i]); assertFloat32(r64, false); assertEq(r32, r64); } } test(setupRound, testRound); test(setupRoundDouble, testRoundDouble); function setupCeil() { f32[0] = -5.5; f32[1] = -1.5; f32[2] = 0; f32[3] = 1.5; } function setupCeilDouble() { f32[4] = NaN; f32[5] = -0; f32[6] = Infinity; f32[7] = -Infinity; f32[8] = Math.pow(2,31); // too big to fit into a int } function testCeil() { for(var i = 0; i < 2; ++i) { var f = Math.ceil(f32[i]); assertFloat32(f, false); var g = Math.ceil(-0 + f32[i]); assertFloat32(g, false); assertEq(f, g); } } function testCeilDouble() { for(var i = 4; i < 9; ++i) { var f = Math.fround(Math.ceil(f32[i])); assertFloat32(f, true); var g = Math.ceil(-0 + f32[i]); assertFloat32(g, false); assertEq(f, g); } } test(setupCeil, testCeil); test(setupCeilDouble, testCeilDouble);