From b689a783511ea3e514a309e148ba91a63a215c44 Mon Sep 17 00:00:00 2001
From: Johannes Henninger <johannes@henninger.io>
Date: Tue, 3 Jul 2018 19:31:17 +0200
Subject: [PATCH] Bindings for Math.pow, round, sign, sin, sinh, sqrt, tan,
 tanh and trunc

---
 src/js.rs                    |  58 ++++++++
 tests/all/js_globals/Math.rs | 259 +++++++++++++++++++++++++++++++++++
 2 files changed, 317 insertions(+)

diff --git a/src/js.rs b/src/js.rs
index 38293d92..09826e6d 100644
--- a/src/js.rs
+++ b/src/js.rs
@@ -608,6 +608,64 @@ extern "C" {
     #[wasm_bindgen(static_method_of = Math)]
     pub fn log2(x: f64) -> Number;
 
+    /// The Math.pow() function returns the base to the exponent power, that is, base^exponent.
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn pow(base: f64, exponent: f64) -> Number;
+
+    /// The Math.round() function returns the value of a number rounded to the nearest integer.
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn round(x: f64) -> Number;
+
+    /// The Math.sign() function returns the sign of a number, indicating whether the number is
+    /// positive, negative or zero.
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn sign(x: f64) -> Number;
+
+    /// The Math.sin() function returns the sine of a number.
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sin
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn sin(x: f64) -> Number;
+
+    /// The Math.sinh() function returns the hyperbolic sine of a number, that can be expressed
+    /// using the constant e: Math.sinh(x) = (e^x - e^-x)/2
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sinh
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn sinh(x: f64) -> Number;
+
+    /// The Math.sqrt() function returns the square root of a number, that is
+    /// ∀x ≥ 0, Math.sqrt(x) = √x = the unique y ≥ 0 such that y^2 = x
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn sqrt(x: f64) -> Number;
+
+    /// The Math.tan() function returns the tangent of a number.
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/tan
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn tan(x: f64) -> Number;
+
+    /// The Math.tanh() function returns the hyperbolic tangent of a number, that is
+    /// tanh x = sinh x / cosh x = (e^x - e^-x)/(e^x + e^-x) = (e^2x - 1)/(e^2x + 1)
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/tanh
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn tanh(x: f64) -> Number;
+
+    /// The Math.trunc() function returns the integer part of a number by removing any fractional
+    /// digits.
+    /// 
+    /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
+    #[wasm_bindgen(static_method_of = Math)]
+    pub fn trunc(x: f64) -> Number;
 }
 
 // Number.
diff --git a/tests/all/js_globals/Math.rs b/tests/all/js_globals/Math.rs
index e85305b0..46788cb6 100644
--- a/tests/all/js_globals/Math.rs
+++ b/tests/all/js_globals/Math.rs
@@ -682,4 +682,263 @@ fn log2() {
             }
         "#)
         .test()
+}
+
+#[test]
+fn pow() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn pow(base: f64, exponent: f64) -> js::Number {
+                js::Math::pow(base, exponent)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.pow(7, 2), 49);
+                assert.equal(wasm.pow(3.8, 0.5), Math.pow(3.8, 0.5));
+                assert(Number.isNaN(wasm.pow(-2, 0.5)));
+            }
+        "#)
+        .test()
+}
+
+#[test]
+fn round() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn round(x: f64) -> js::Number {
+                js::Math::round(x)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.round(20.49), 20);
+                assert.equal(wasm.round(20.5), 21);
+                assert.equal(wasm.round(42), 42);
+                assert.equal(wasm.round(-20.5), -20);
+                assert.equal(wasm.round(-20.51), -21);
+            }
+        "#)
+        .test()
+}
+
+#[test]
+fn sign() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn sign(x: f64) -> js::Number {
+                js::Math::sign(x)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.sign(3), 1);
+                assert.equal(wasm.sign(-3), -1);
+                assert.equal(wasm.sign(2.3), 1);
+                assert.equal(wasm.sign(0), 0);
+                assert(Number.isNaN(wasm.sign(NaN)));
+            }
+        "#)
+        .test()
+}
+
+#[test]
+fn sin() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn sin(x: f64) -> js::Number {
+                js::Math::sin(x)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.sin(0), 0);
+                assert.equal(wasm.sin(1), Math.sin(1));
+                assert.equal(wasm.sin(Math.PI / 2), 1);
+            }
+        "#)
+        .test()
+}
+
+#[test]
+fn sinh() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn sinh(x: f64) -> js::Number {
+                js::Math::sinh(x)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.sinh(0), 0);
+                assert.equal(wasm.sinh(1), Math.sinh(1));
+                assert.equal(wasm.sinh(2.3), Math.sinh(2.3));
+            }
+        "#)
+        .test()
+}
+
+#[test]
+fn sqrt() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn sqrt(x: f64) -> js::Number {
+                js::Math::sqrt(x)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.sqrt(9), 3);
+                assert.equal(wasm.sqrt(2), Math.sqrt(2));
+                assert.equal(wasm.sqrt(42.42), Math.sqrt(42.42));
+                assert.equal(wasm.sqrt(1), 1);
+                assert(Number.isNaN(wasm.sqrt(-1)));
+            }
+        "#)
+        .test()
+}
+
+#[test]
+fn tan() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn tan(x: f64) -> js::Number {
+                js::Math::tan(x)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.tan(0), 0);
+                assert.equal(wasm.tan(1), Math.tan(1));
+                assert.equal(wasm.tan(0.5), Math.tan(0.5));
+            }
+        "#)
+        .test()
+}
+
+#[test]
+fn tanh() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn tanh(x: f64) -> js::Number {
+                js::Math::tanh(x)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.tanh(0), 0);
+                assert.equal(wasm.tanh(1), Math.tanh(1));
+                assert.equal(wasm.tanh(0.5), Math.tanh(0.5));
+            }
+        "#)
+        .test()
+}
+
+#[test]
+fn trunc() {
+    project()
+        .file("src/lib.rs", r#"
+            #![feature(proc_macro, wasm_custom_section)]
+
+            extern crate wasm_bindgen;
+            use wasm_bindgen::prelude::*;
+            use wasm_bindgen::js;
+
+            #[wasm_bindgen]
+            pub fn trunc(x: f64) -> js::Number {
+                js::Math::trunc(x)
+            }
+        "#)
+        .file("test.ts", r#"
+            import * as assert from "assert";
+            import * as wasm from "./out";
+
+            export function test() {
+                assert.equal(wasm.trunc(13.37), 13);
+                assert.equal(wasm.trunc(42.84), 42);
+                assert.equal(wasm.trunc(0.123), 0);
+                assert.equal(wasm.trunc(-0.123), 0);
+            }
+        "#)
+        .test()
 }
\ No newline at end of file