// 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) {
    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);
