| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --validate-asm --allow-natives-syntax |
| |
| function verbose(args) { |
| // print(...args); |
| } |
| |
| //============================================= |
| // Global count of failures |
| //============================================= |
| let numFailures = 0; |
| |
| function reportFailure(name, vals, m, w) { |
| print(' error: ' + name + '(' + vals + ') == ' + w + ', expected ' + m); |
| numFailures++; |
| } |
| |
| let inputs = [ |
| 1 / 0, |
| -1 / 0, |
| 0 / 0, |
| -2.70497e+38, |
| -1.4698e+37, |
| -1.22813e+35, |
| -1.34584e+34, |
| -1.0079e+32, |
| -6.49364e+26, |
| -3.06077e+25, |
| -1.46821e+25, |
| -1.17658e+23, |
| -1.9617e+22, |
| -2.7357e+20, |
| -9223372036854775808.0, // INT64_MIN |
| -1.48708e+13, |
| -1.89633e+12, |
| -4.66622e+11, |
| -2.22581e+11, |
| -1.45381e+10, |
| -2147483904.0, // First float32 after INT32_MIN |
| -2147483648.0, // INT32_MIN |
| -2147483520.0, // Last float32 before INT32_MIN |
| -1.3956e+09, |
| -1.32951e+09, |
| -1.30721e+09, |
| -1.19756e+09, |
| -9.26822e+08, |
| -5.09256e+07, |
| -964300.0, |
| -192446.0, |
| -28455.0, |
| -27194.0, |
| -20575.0, |
| -17069.0, |
| -9167.0, |
| -960.178, |
| -113.0, |
| -62.0, |
| -15.0, |
| -7.0, |
| -1.0, |
| -0.0256635, |
| -4.60374e-07, |
| -3.63759e-10, |
| -4.30175e-14, |
| -5.27385e-15, |
| -1.5707963267948966, |
| -1.48084e-15, |
| -2.220446049250313e-16, |
| -1.05755e-19, |
| -3.2995e-21, |
| -1.67354e-23, |
| -1.11885e-23, |
| -1.78506e-30, |
| -1.43718e-34, |
| -1.27126e-38, |
| -0.0, |
| 3e-88, |
| -2e66, |
| 0.0, |
| 2e66, |
| 1.17549e-38, |
| 1.56657e-37, |
| 4.08512e-29, |
| 6.25073e-22, |
| 4.1723e-13, |
| 1.44343e-09, |
| 1.5707963267948966, |
| 5.27004e-08, |
| 9.48298e-08, |
| 5.57888e-07, |
| 4.89988e-05, |
| 0.244326, |
| 1.0, |
| 12.4895, |
| 19.0, |
| 47.0, |
| 106.0, |
| 538.324, |
| 564.536, |
| 819.124, |
| 7048.0, |
| 12611.0, |
| 19878.0, |
| 20309.0, |
| 797056.0, |
| 1.77219e+09, |
| 2147483648.0, // INT32_MAX + 1 |
| 4294967296.0, // UINT32_MAX + 1 |
| 1.51116e+11, |
| 4.18193e+13, |
| 3.59167e+16, |
| 9223372036854775808.0, // INT64_MAX + 1 |
| 18446744073709551616.0, // UINT64_MAX + 1 |
| 3.38211e+19, |
| 2.67488e+20, |
| 1.78831e+21, |
| 9.20914e+21, |
| 8.35654e+23, |
| 1.4495e+24, |
| 5.94015e+25, |
| 4.43608e+30, |
| 2.44502e+33, |
| 1.38178e+37, |
| 1.71306e+37, |
| 3.31899e+38, |
| 3.40282e+38, |
| ]; |
| |
| let stdlib = this; |
| |
| // Module template for generating f64 unop functions. |
| function ModuleTemplate_f64_unop(stdlib) { |
| 'use asm'; |
| |
| var Stdlib = stdlib.Math.NAME; |
| |
| function NAME(a) { |
| a = +a; |
| return +Stdlib(a); |
| } |
| |
| return {NAME: NAME}; |
| } |
| |
| // Module template for generating f64 binop functions. |
| function ModuleTemplate_f64_binop(stdlib) { |
| 'use asm'; |
| |
| var Stdlib = stdlib.Math.NAME; |
| |
| function NAME(a, b) { |
| a = +a; |
| b = +b; |
| return +Stdlib(a, b); |
| } |
| |
| return {NAME: NAME}; |
| } |
| |
| // Module template for generating f64 unop functions. |
| function ModuleTemplate_f32_unop(stdlib) { |
| 'use asm'; |
| |
| var Stdlib = stdlib.Math.NAME; |
| var fround = stdlib.Math.fround; |
| |
| function NAME(a) { |
| a = fround(a); |
| return fround(Stdlib(a)); |
| } |
| |
| return {NAME: NAME}; |
| } |
| |
| // Module template for generating f64 binop functions. |
| function ModuleTemplate_f32_binop(stdlib) { |
| 'use asm'; |
| |
| var Stdlib = stdlib.Math.NAME; |
| var fround = stdlib.Math.fround; |
| |
| function NAME(a, b) { |
| a = fround(a); |
| b = fround(b); |
| return fround(Stdlib(a, b)); |
| } |
| |
| return {NAME: NAME}; |
| } |
| |
| function instantiateTemplate(func, name) { |
| let src = func.toString(); |
| src = src.replace(/NAME/g, name); |
| let module = eval('(' + src + ')'); |
| let instance = module(stdlib); |
| assertTrue(%IsAsmWasmCode(module)); |
| |
| let asm_func = instance[name]; |
| if (typeof asm_func != 'function') throw 'asm[' + full_name + '] not found'; |
| return asm_func; |
| } |
| |
| function genUnop(name, f32) { |
| return instantiateTemplate( |
| f32 ? ModuleTemplate_f32_unop : ModuleTemplate_f64_unop, name); |
| } |
| |
| function genBinop(name, f32) { |
| return instantiateTemplate( |
| f32 ? ModuleTemplate_f32_binop : ModuleTemplate_f64_binop, name); |
| } |
| |
| function assertUnop(name, math_func, asm_func) { |
| for (val of inputs) { |
| verbose(' ', val); |
| let m = math_func(val); |
| let w = asm_func(val); |
| if (!deepEquals(m, w)) reportFailure(name, [val], m, w); |
| } |
| } |
| |
| function assertBinop(name, math_func, asm_func) { |
| let inputs2 = [1, 0.5, -1, -0.5, 0, -0, 1 / 0, -1 / 0, 0 / 0]; |
| for (val of inputs) { |
| verbose(' ', val); |
| for (val2 of inputs2) { |
| verbose(' ', val2); |
| let m = math_func(val, val2); |
| let w = asm_func(val, val2); |
| if (!deepEquals(m, w)) reportFailure(name, [val, val2], m, w); |
| m = math_func(val2, val); |
| w = asm_func(val2, val); |
| if (!deepEquals(m, w)) reportFailure(name, [val2, val], m, w); |
| } |
| } |
| } |
| |
| (function TestF64() { |
| let f64_intrinsics = [ |
| 'acos', 'asin', 'atan', 'cos', 'sin', 'tan', 'exp', 'log', |
| 'atan2', 'pow', 'ceil', 'floor', 'sqrt', 'min', 'max', 'abs', |
| 'min', 'max', 'abs', 'ceil', 'floor', 'sqrt', |
| ]; |
| |
| for (name of f64_intrinsics) { |
| if (name == 'pow') continue; // TODO(8505): asm.js correctness |
| let math_func = Math[name]; |
| let f32 = false; |
| print('Testing (f64) Math.' + name); |
| switch (math_func.length) { |
| case 1: { |
| let asm_func = genUnop(name, false); |
| assertUnop('(f64)' + name, math_func, asm_func); |
| break; |
| } |
| case 2: { |
| let asm_func = genBinop(name, false); |
| assertBinop('(f64)' + name, math_func, asm_func); |
| break; |
| } |
| default: |
| throw 'Unexpected param count: ' + func.length; |
| } |
| } |
| })(); |
| |
| (function TestF32() { |
| let f32_intrinsics = ['min', 'max', 'abs', 'ceil', 'floor', 'sqrt']; |
| |
| for (name of f32_intrinsics) { |
| let r = Math.fround, f = Math[name]; |
| print('Testing (f32) Math.' + name); |
| switch (f.length) { |
| case 1: { |
| let asm_func = genUnop(name, true); |
| let math_func = (val) => r(f(r(val))); |
| assertUnop('(f32)' + name, math_func, asm_func); |
| break; |
| } |
| case 2: { |
| let asm_func = genBinop(name, true); |
| let math_func = (v1, v2) => r(f(r(v1), r(v2))); |
| assertBinop('(f32)' + name, math_func, asm_func); |
| break; |
| } |
| default: |
| throw 'Unexpected param count: ' + func.length; |
| } |
| } |
| })(); |
| |
| assertEquals(0, numFailures); |