From 64113590b2ea1275fe9373e2832b05c920b6891b Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Tue, 16 Feb 2021 16:47:42 -0800 Subject: [PATCH 1/8] Added Sin(). --- src/QirRuntime/lib/QIR/bridge-qis.ll | 8 +++++ .../test/QIR-static/qir-test-math.cpp | 7 ++++ .../test/QIR-static/qsharp/qir-test-arrays.qs | 1 + .../test/QIR-static/qsharp/qir-test-math.qs | 32 +++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/src/QirRuntime/lib/QIR/bridge-qis.ll b/src/QirRuntime/lib/QIR/bridge-qis.ll index 729b8c77e2e..2358ea00587 100644 --- a/src/QirRuntime/lib/QIR/bridge-qis.ll +++ b/src/QirRuntime/lib/QIR/bridge-qis.ll @@ -296,6 +296,7 @@ define void @__quantum__qis__message__body(%String* %.str) { ; LLVM intrinsics (https://llvm.org/docs/LangRef.html): declare double @llvm.sqrt.f64(double %.val) declare double @llvm.log.f64(double %Val) +declare double @llvm.sin.f64(double %Val) ; Native implementations: declare i1 @quantum__qis__isnan__body(double %d) @@ -348,6 +349,13 @@ define double @__quantum__qis__arctan2__body(double %y, double %x) { ; Q#: func ret double %result } +; function Sin (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.sin +define double @__quantum__qis__sin__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/sin + %result = call double @llvm.sin.f64(double %theta) ; https://llvm.org/docs/LangRef.html#llvm-sin-intrinsic + ret double %result +} + ; operation DrawRandomInt (min : Int, max : Int) : Int ; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.random.drawrandomint diff --git a/src/QirRuntime/test/QIR-static/qir-test-math.cpp b/src/QirRuntime/test/QIR-static/qir-test-math.cpp index f1007acd73e..703b81a194b 100644 --- a/src/QirRuntime/test/QIR-static/qir-test-math.cpp +++ b/src/QirRuntime/test/QIR-static/qir-test-math.cpp @@ -11,6 +11,7 @@ extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SqrtTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__LogTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ArcTan2Test__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TestDrawRandomInt__body(int64_t min, int64_t max); // NOLINT TEST_CASE("QIR: Math.Sqrt", "[qir.math][qir.Math.Sqrt]") @@ -28,6 +29,12 @@ TEST_CASE("QIR: Math.ArcTan2", "[qir.math][qir.Math.ArcTan2]") REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__ArcTan2Test__body()); } +TEST_CASE("QIR: Math.Sin", "[qir.math][qir.Math.Sin]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__SinTest__body()); +} + + TEST_CASE("QIR: Math.DrawRandomInt", "[qir.math][qir.Math.DrawRandomInt]") { // Test that the Q# random number generator is a wrapper around the C++ generator: diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs index 10154ba9a02..d4664572194 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs @@ -42,6 +42,7 @@ namespace Microsoft.Quantum.Testing.QIR { let res6 = ArcTan2Test(); let res7 = PauliToStringTest(); let res8 = TestDrawRandomInt(0, 1); + let res9 = SinTest(); MessageTest("Test"); } return sum; diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs index 2ad876a087c..dec5fa4d694 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs @@ -6,6 +6,7 @@ namespace Microsoft.Quantum.Testing.QIR.Math { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math; // E() open Microsoft.Quantum.Random; + open Microsoft.Quantum.Convert; // DoubleAsString() function SqrtTest() : Int { if 2.0 != Sqrt( 4.0) { return 1; } // The return value indicates which test case has failed. @@ -65,5 +66,36 @@ namespace Microsoft.Quantum.Testing.QIR.Math { return DrawRandomInt(min, max); } + function Close(expected : Double, actual : Double) : Bool { + let neighbourhood = 0.0000001; // On x86-64 + Win the error is in 16th digit after the decimal point. + // E.g. enstead of 0.0 there can be 0.00000000000000012. + // Thus 0.0000001 should be more than enough. + + return ((expected - neighbourhood) < actual) and (actual < (expected + neighbourhood)); + } + + function SinTest() : Int { + + // function Sin (theta : Double) : Double + + if not Close(0.0, Sin(0.0)) { return 1; } // The return value indicates which test case has failed. + if not Close(0.5, Sin(PI()/6.0)) { return 2; } + if not Close(1.0, Sin(PI()/2.0)) { return 3; } + if not Close(0.5, Sin(5.0*PI()/6.0)) { return 4; } + if not Close(0.0, Sin(PI())) { return 5; } + + if not Close(-0.5, Sin(-5.0*PI()/6.0)) { return 6; } + if not Close(-1.0, Sin(-PI()/2.0)) { return 7; } + if not Close(-0.5, Sin(-PI()/6.0)) { return 8; } + + if not Close(Sqrt(2.0)/2.0, Sin(PI()/4.0)) { return 9; } + + if NAN() != Sin(NAN()) { return 10; } + if NAN() != Sin(INFINITY()) { return 11; } + if NAN() != Sin(-INFINITY()) { return 11; } + + return 0; + } + } From b177a9929151eeb5194f3f86eb648d6d63d16ec9 Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Fri, 19 Feb 2021 13:37:21 -0800 Subject: [PATCH 2/8] Added Cos(). --- src/QirRuntime/lib/QIR/bridge-qis.ll | 10 ++++++++- .../test/QIR-static/qir-test-math.cpp | 6 +++++ .../test/QIR-static/qsharp/qir-test-arrays.qs | 1 + .../test/QIR-static/qsharp/qir-test-math.qs | 22 +++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/QirRuntime/lib/QIR/bridge-qis.ll b/src/QirRuntime/lib/QIR/bridge-qis.ll index 2358ea00587..10680331b26 100644 --- a/src/QirRuntime/lib/QIR/bridge-qis.ll +++ b/src/QirRuntime/lib/QIR/bridge-qis.ll @@ -297,6 +297,7 @@ define void @__quantum__qis__message__body(%String* %.str) { declare double @llvm.sqrt.f64(double %.val) declare double @llvm.log.f64(double %Val) declare double @llvm.sin.f64(double %Val) +declare double @llvm.cos.f64(double %Val) ; Native implementations: declare i1 @quantum__qis__isnan__body(double %d) @@ -351,11 +352,18 @@ define double @__quantum__qis__arctan2__body(double %y, double %x) { ; Q#: func ; function Sin (theta : Double) : Double ; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.sin -define double @__quantum__qis__sin__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/sin +define double @__quantum__qis__sin__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/sin %result = call double @llvm.sin.f64(double %theta) ; https://llvm.org/docs/LangRef.html#llvm-sin-intrinsic ret double %result } +; function Cos (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.cos +define double @__quantum__qis__cos__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/cos + %result = call double @llvm.cos.f64(double %theta) ; https://llvm.org/docs/LangRef.html#llvm-cos-intrinsic + ret double %result +} + ; operation DrawRandomInt (min : Int, max : Int) : Int ; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.random.drawrandomint diff --git a/src/QirRuntime/test/QIR-static/qir-test-math.cpp b/src/QirRuntime/test/QIR-static/qir-test-math.cpp index 703b81a194b..9f3d86c7ae7 100644 --- a/src/QirRuntime/test/QIR-static/qir-test-math.cpp +++ b/src/QirRuntime/test/QIR-static/qir-test-math.cpp @@ -12,6 +12,7 @@ extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SqrtTest__body(); extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__LogTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ArcTan2Test__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__CosTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TestDrawRandomInt__body(int64_t min, int64_t max); // NOLINT TEST_CASE("QIR: Math.Sqrt", "[qir.math][qir.Math.Sqrt]") @@ -34,6 +35,11 @@ TEST_CASE("QIR: Math.Sin", "[qir.math][qir.Math.Sin]") REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__SinTest__body()); } +TEST_CASE("QIR: Math.Cos", "[qir.math][qir.Math.Cos]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__CosTest__body()); +} + TEST_CASE("QIR: Math.DrawRandomInt", "[qir.math][qir.Math.DrawRandomInt]") { diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs index d4664572194..05371b9af3d 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs @@ -43,6 +43,7 @@ namespace Microsoft.Quantum.Testing.QIR { let res7 = PauliToStringTest(); let res8 = TestDrawRandomInt(0, 1); let res9 = SinTest(); + let res10 = CosTest(); MessageTest("Test"); } return sum; diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs index dec5fa4d694..e11ea5bdd69 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs @@ -97,5 +97,27 @@ namespace Microsoft.Quantum.Testing.QIR.Math { return 0; } + function CosTest() : Int { + + // function Cos (theta : Double) : Double + + if not Close( 1.0, Cos(0.0)) { return 1; } // The return value indicates which test case has failed. + if not Close( 0.5, Cos(PI()/3.0)) { return 2; } + if not Close( 0.0, Cos(PI()/2.0)) { return 3; } + if not Close(-0.5, Cos(2.0*PI()/3.0)) { return 4; } + if not Close(-1.0, Cos(PI())) { return 5; } + + if not Close(-0.5, Cos(-2.0*PI()/3.0)) { return 6; } + if not Close( 0.0, Cos(-PI()/2.0)) { return 7; } + if not Close( 0.5, Cos(-PI()/3.0)) { return 8; } + + if not Close(Sqrt(2.0)/2.0, Cos(PI()/4.0)) { return 9; } + + if NAN() != Cos(NAN()) { return 10; } + if NAN() != Cos(INFINITY()) { return 11; } + if NAN() != Cos(-INFINITY()) { return 11; } + + return 0; + } } From d2265be0813a0dc264aa91a0d49da2b15ad8fa72 Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Fri, 19 Feb 2021 14:33:34 -0800 Subject: [PATCH 3/8] Added Tan(). --- src/QirRuntime/lib/QIR/bridge-qis.ll | 9 +++++++ .../test/QIR-static/qir-test-math.cpp | 6 +++++ .../test/QIR-static/qsharp/qir-test-arrays.qs | 1 + .../test/QIR-static/qsharp/qir-test-math.qs | 25 +++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/src/QirRuntime/lib/QIR/bridge-qis.ll b/src/QirRuntime/lib/QIR/bridge-qis.ll index 10680331b26..6379fb98bec 100644 --- a/src/QirRuntime/lib/QIR/bridge-qis.ll +++ b/src/QirRuntime/lib/QIR/bridge-qis.ll @@ -364,6 +364,15 @@ define double @__quantum__qis__cos__body(double %theta) { ; https://en.cpp ret double %result } +; function Tan (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.tan +define double @__quantum__qis__tan__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/tan + %sin = call double @llvm.sin.f64(double %theta) + %cos = call double @llvm.cos.f64(double %theta) + %result = fdiv double %sin, %cos ; tg(x) = sin(x) / cos(x) + ret double %result +} + ; operation DrawRandomInt (min : Int, max : Int) : Int ; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.random.drawrandomint diff --git a/src/QirRuntime/test/QIR-static/qir-test-math.cpp b/src/QirRuntime/test/QIR-static/qir-test-math.cpp index 9f3d86c7ae7..25a8a81fdc1 100644 --- a/src/QirRuntime/test/QIR-static/qir-test-math.cpp +++ b/src/QirRuntime/test/QIR-static/qir-test-math.cpp @@ -13,6 +13,7 @@ extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__LogTest__body(); extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ArcTan2Test__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__CosTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TanTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TestDrawRandomInt__body(int64_t min, int64_t max); // NOLINT TEST_CASE("QIR: Math.Sqrt", "[qir.math][qir.Math.Sqrt]") @@ -40,6 +41,11 @@ TEST_CASE("QIR: Math.Cos", "[qir.math][qir.Math.Cos]") REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__CosTest__body()); } +TEST_CASE("QIR: Math.Tan", "[qir.math][qir.Math.Tan]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__TanTest__body()); +} + TEST_CASE("QIR: Math.DrawRandomInt", "[qir.math][qir.Math.DrawRandomInt]") { diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs index 05371b9af3d..43d1a1751f6 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs @@ -44,6 +44,7 @@ namespace Microsoft.Quantum.Testing.QIR { let res8 = TestDrawRandomInt(0, 1); let res9 = SinTest(); let res10 = CosTest(); + let res11 = TanTest(); MessageTest("Test"); } return sum; diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs index e11ea5bdd69..ae47f6502ca 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs @@ -119,5 +119,30 @@ namespace Microsoft.Quantum.Testing.QIR.Math { return 0; } + + function TanTest() : Int { + // function Tan (theta : Double) : Double + if not Close( 0.0, Tan(0.0)) { return 1; } // The return value indicates which test case has failed. + if not Close( 0.5/(Sqrt(3.0)/2.0), Tan( PI()/6.0)) { return 2; } // tg(Pi/6) = sin(Pi/6) / cos(Pi/6) = (1/2) / (sqrt(3)/2) + if not Close( 1.0, Tan( PI()/4.0)) { return 3; } + if not Close( (Sqrt(3.0)/2.0)/0.5, Tan( PI()/3.0)) { return 4; } + // https://en.cppreference.com/w/cpp/numeric/math/tan + // The function has mathematical poles at Pi(1/2 + n); however no common floating-point representation + // is able to represent Pi/2 exactly, thus there is no value of the argument for which a pole error occurs. + if not Close(-1.0, Tan(3.0*PI()/4.0)) { return 5; } + if not Close( 0.0, Tan(PI())) { return 6; } + + if not Close(-0.5/(Sqrt(3.0)/2.0), Tan(-PI()/6.0)) { return 7; } + if not Close(-1.0, Tan(-PI()/4.0)) { return 8; } + if not Close(-(Sqrt(3.0)/2.0)/0.5, Tan(-PI()/3.0)) { return 9; } + if not Close( 1.0, Tan(-3.0*PI()/4.0)) { return 10; } + + if NAN() != Tan(NAN()) { return 11; } + if NAN() != Tan(INFINITY()) { return 12; } + if NAN() != Tan(-INFINITY()) { return 13; } + + return 0; + } + } From c7ea3d8450c34cbab8de52fc740424a10bf35cfd Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Sun, 21 Feb 2021 16:21:52 -0800 Subject: [PATCH 4/8] Added Sinh(), Cosh(), Tanh(). --- src/QirRuntime/lib/QIR/bridge-qis.ll | 25 +++++++++++++++++++++++ src/QirRuntime/lib/QIR/intrinsicsMath.cpp | 10 +++++++++ src/QirRuntime/lib/QIR/quantum__qis.hpp | 2 ++ 3 files changed, 37 insertions(+) diff --git a/src/QirRuntime/lib/QIR/bridge-qis.ll b/src/QirRuntime/lib/QIR/bridge-qis.ll index 6379fb98bec..f4241980b9a 100644 --- a/src/QirRuntime/lib/QIR/bridge-qis.ll +++ b/src/QirRuntime/lib/QIR/bridge-qis.ll @@ -304,6 +304,8 @@ declare i1 @quantum__qis__isnan__body(double %d) declare double @quantum__qis__infinity__body() declare i1 @quantum__qis__isinf__body(double %d) declare double @quantum__qis__arctan2__body(double %y, double %x) +declare double @quantum__qis__sinh__body(double %theta) +declare double @quantum__qis__cosh__body(double %theta) declare i64 @quantum__qis__drawrandomint__body(i64 %min, i64 %max) ; API for the user code: @@ -373,6 +375,29 @@ define double @__quantum__qis__tan__body(double %theta) { ; https://en.cpp ret double %result } +; function Sinh (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.sinh +define double @__quantum__qis__sinh__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/sinh + %result = call double @quantum__qis__sinh__body(double %theta) + ret double %result +} + +; function Cosh (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.cosh +define double @__quantum__qis__cosh__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/cosh + %result = call double @quantum__qis__cosh__body(double %theta) + ret double %result +} + +; function Tanh (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.tanh +define double @__quantum__qis__tanh__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/tanh + %sin = call double @__quantum__qis__sinh__body(double %theta) + %cos = call double @__quantum__qis__cosh__body(double %theta) + %result = fdiv double %sin, %cos ; tanh(x) = sinh(x) / cosh(x) + ret double %result +} + ; operation DrawRandomInt (min : Int, max : Int) : Int ; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.random.drawrandomint diff --git a/src/QirRuntime/lib/QIR/intrinsicsMath.cpp b/src/QirRuntime/lib/QIR/intrinsicsMath.cpp index fedfbd6ba7b..7f46d84d75c 100644 --- a/src/QirRuntime/lib/QIR/intrinsicsMath.cpp +++ b/src/QirRuntime/lib/QIR/intrinsicsMath.cpp @@ -40,6 +40,16 @@ double quantum__qis__arctan2__body(double y, double x) return std::atan2(y, x); // https://en.cppreference.com/w/cpp/numeric/math/atan2 } +double quantum__qis__sinh__body(double theta) +{ + return std::sinh(theta); +} + +double quantum__qis__cosh__body(double theta) +{ + return std::cosh(theta); +} + int64_t quantum__qis__drawrandomint__body(int64_t minimum, int64_t maximum) { if(minimum > maximum) diff --git a/src/QirRuntime/lib/QIR/quantum__qis.hpp b/src/QirRuntime/lib/QIR/quantum__qis.hpp index 8e80cd80404..7d9efafe056 100644 --- a/src/QirRuntime/lib/QIR/quantum__qis.hpp +++ b/src/QirRuntime/lib/QIR/quantum__qis.hpp @@ -67,6 +67,8 @@ extern "C" QIR_SHARED_API double quantum__qis__infinity__body(); // NOLINT QIR_SHARED_API bool quantum__qis__isinf__body(double d); // NOLINT QIR_SHARED_API double quantum__qis__arctan2__body(double y, double x); // NOLINT + QIR_SHARED_API double quantum__qis__sinh__body(double theta); // NOLINT + QIR_SHARED_API double quantum__qis__cosh__body(double theta); // NOLINT QIR_SHARED_API int64_t quantum__qis__drawrandomint__body(int64_t minimum, int64_t maximum); // NOLINT } \ No newline at end of file From 259dd198ae089d1b2a87249321529ca88090b8c1 Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Sun, 21 Feb 2021 16:47:29 -0800 Subject: [PATCH 5/8] Added tests. --- .../test/QIR-static/qir-test-math.cpp | 17 +++++++ .../test/QIR-static/qsharp/qir-test-arrays.qs | 3 ++ .../test/QIR-static/qsharp/qir-test-math.qs | 51 +++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/QirRuntime/test/QIR-static/qir-test-math.cpp b/src/QirRuntime/test/QIR-static/qir-test-math.cpp index 25a8a81fdc1..c4d191e7174 100644 --- a/src/QirRuntime/test/QIR-static/qir-test-math.cpp +++ b/src/QirRuntime/test/QIR-static/qir-test-math.cpp @@ -14,6 +14,9 @@ extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ArcTan2Test__body(); extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__CosTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TanTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinhTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__CoshTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TanhTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TestDrawRandomInt__body(int64_t min, int64_t max); // NOLINT TEST_CASE("QIR: Math.Sqrt", "[qir.math][qir.Math.Sqrt]") @@ -46,6 +49,20 @@ TEST_CASE("QIR: Math.Tan", "[qir.math][qir.Math.Tan]") REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__TanTest__body()); } +TEST_CASE("QIR: Math.Sinh", "[qir.math][qir.Math.Sinh]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__SinhTest__body()); +} + +TEST_CASE("QIR: Math.Cosh", "[qir.math][qir.Math.Cosh]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__CoshTest__body()); +} + +TEST_CASE("QIR: Math.Tanh", "[qir.math][qir.Math.Tanh]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__TanhTest__body()); +} TEST_CASE("QIR: Math.DrawRandomInt", "[qir.math][qir.Math.DrawRandomInt]") { diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs index 43d1a1751f6..7dc776cc286 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs @@ -45,6 +45,9 @@ namespace Microsoft.Quantum.Testing.QIR { let res9 = SinTest(); let res10 = CosTest(); let res11 = TanTest(); + let res12 = SinhTest(); + let res13 = CoshTest(); + let res14 = TanhTest(); MessageTest("Test"); } return sum; diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs index ae47f6502ca..c94d03f3eb0 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs @@ -144,5 +144,56 @@ namespace Microsoft.Quantum.Testing.QIR.Math { return 0; } + function SinhTest() : Int { + + // function Sinh (theta : Double) : Double + + let xValues = [ -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, + 5.0, 4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0 ]; + for x in xValues { + if not Close( (ExpD(x) - ExpD(-x)) / 2.0, Sinh(x)) { return 1; } // The return value indicates which test case has failed. + } + + if NAN() != Sinh(NAN()) { return 2; } + if INFINITY() != Sinh(INFINITY()) { return 3; } + if -INFINITY() != Sinh(-INFINITY()) { return 4; } + + return 0; + } + + function CoshTest() : Int { + + // function Cosh (theta : Double) : Double + + let xValues = [ -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, + 5.0, 4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0 ]; + for x in xValues { + if not Close( (ExpD(x) + ExpD(-x)) / 2.0, Cosh(x)) { return 1; } // The return value indicates which test case has failed. + } + + if NAN() != Cosh(NAN()) { return 2; } + if INFINITY() != Cosh(INFINITY()) { return 3; } + if INFINITY() != Cosh(-INFINITY()) { return 4; } + + return 0; + } + + function TanhTest() : Int { + + // function Tanh (theta : Double) : Double + + let xValues = [ -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, + 5.0, 4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0 ]; + for x in xValues { + if not Close( Sinh(x) / Cosh(x), Tanh(x)) { return 1; } // The return value indicates which test case has failed. + } + + if NAN() != Tanh(NAN()) { return 2; } + if 1.0 != Tanh(INFINITY()) { return 3; } + if -1.0 != Tanh(-INFINITY()) { return 4; } + + return 0; + } + } From 30c194f4394ccea1875775136d97ab6793b043e6 Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Sun, 21 Feb 2021 17:12:19 -0800 Subject: [PATCH 6/8] Added IEEERemainder(). --- src/QirRuntime/lib/QIR/bridge-qis.ll | 7 +++++++ src/QirRuntime/lib/QIR/intrinsicsMath.cpp | 5 +++++ src/QirRuntime/lib/QIR/quantum__qis.hpp | 1 + 3 files changed, 13 insertions(+) diff --git a/src/QirRuntime/lib/QIR/bridge-qis.ll b/src/QirRuntime/lib/QIR/bridge-qis.ll index f4241980b9a..0c66aba3433 100644 --- a/src/QirRuntime/lib/QIR/bridge-qis.ll +++ b/src/QirRuntime/lib/QIR/bridge-qis.ll @@ -306,6 +306,7 @@ declare i1 @quantum__qis__isinf__body(double %d) declare double @quantum__qis__arctan2__body(double %y, double %x) declare double @quantum__qis__sinh__body(double %theta) declare double @quantum__qis__cosh__body(double %theta) +declare double @quantum__qis__ieeeremainder__body(double %y, double %x) declare i64 @quantum__qis__drawrandomint__body(i64 %min, i64 %max) ; API for the user code: @@ -398,6 +399,12 @@ define double @__quantum__qis__tanh__body(double %theta) { ; https://en.cpp ret double %result } +; function IEEERemainder(x : Double, y : Double) : Double +define double @__quantum__qis__ieeeremainder__body(double %x, double %y) { + %result = call double @quantum__qis__ieeeremainder__body(double %x, double %y) + ret double %result +} + ; operation DrawRandomInt (min : Int, max : Int) : Int ; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.random.drawrandomint diff --git a/src/QirRuntime/lib/QIR/intrinsicsMath.cpp b/src/QirRuntime/lib/QIR/intrinsicsMath.cpp index 7f46d84d75c..a99f575582b 100644 --- a/src/QirRuntime/lib/QIR/intrinsicsMath.cpp +++ b/src/QirRuntime/lib/QIR/intrinsicsMath.cpp @@ -50,6 +50,11 @@ double quantum__qis__cosh__body(double theta) return std::cosh(theta); } +double quantum__qis__ieeeremainder__body(double x, double y) +{ + return std::remainder(x, y); // https://en.cppreference.com/w/cpp/numeric/math/remainder +} + int64_t quantum__qis__drawrandomint__body(int64_t minimum, int64_t maximum) { if(minimum > maximum) diff --git a/src/QirRuntime/lib/QIR/quantum__qis.hpp b/src/QirRuntime/lib/QIR/quantum__qis.hpp index 7d9efafe056..dd774586447 100644 --- a/src/QirRuntime/lib/QIR/quantum__qis.hpp +++ b/src/QirRuntime/lib/QIR/quantum__qis.hpp @@ -69,6 +69,7 @@ extern "C" QIR_SHARED_API double quantum__qis__arctan2__body(double y, double x); // NOLINT QIR_SHARED_API double quantum__qis__sinh__body(double theta); // NOLINT QIR_SHARED_API double quantum__qis__cosh__body(double theta); // NOLINT + QIR_SHARED_API double quantum__qis__ieeeremainder__body(double x, double y); // NOLINT QIR_SHARED_API int64_t quantum__qis__drawrandomint__body(int64_t minimum, int64_t maximum); // NOLINT } \ No newline at end of file From 204af42156f4182f118874dc9ae7e167178cfc5d Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Mon, 22 Feb 2021 15:50:53 -0800 Subject: [PATCH 7/8] Added test. --- .../test/QIR-static/qir-test-math.cpp | 6 ++ .../test/QIR-static/qsharp/qir-gen.csproj | 2 +- .../test/QIR-static/qsharp/qir-test-arrays.qs | 1 + .../test/QIR-static/qsharp/qir-test-math.qs | 85 ++++++++++++++++++- 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/QirRuntime/test/QIR-static/qir-test-math.cpp b/src/QirRuntime/test/QIR-static/qir-test-math.cpp index c4d191e7174..4985c198f61 100644 --- a/src/QirRuntime/test/QIR-static/qir-test-math.cpp +++ b/src/QirRuntime/test/QIR-static/qir-test-math.cpp @@ -17,6 +17,7 @@ extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TanTest__body(); extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinhTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__CoshTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TanhTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__IeeeRemainderTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TestDrawRandomInt__body(int64_t min, int64_t max); // NOLINT TEST_CASE("QIR: Math.Sqrt", "[qir.math][qir.Math.Sqrt]") @@ -64,6 +65,11 @@ TEST_CASE("QIR: Math.Tanh", "[qir.math][qir.Math.Tanh]") REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__TanhTest__body()); } +TEST_CASE("QIR: Math.IeeeRemainder", "[qir.math][qir.Math.IeeeRemainder]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__IeeeRemainderTest__body()); +} + TEST_CASE("QIR: Math.DrawRandomInt", "[qir.math][qir.Math.DrawRandomInt]") { // Test that the Q# random number generator is a wrapper around the C++ generator: diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-gen.csproj b/src/QirRuntime/test/QIR-static/qsharp/qir-gen.csproj index 17f43b9b0c8..16a4473fd18 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-gen.csproj +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-gen.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs index 7dc776cc286..af1cbde29b2 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs @@ -48,6 +48,7 @@ namespace Microsoft.Quantum.Testing.QIR { let res12 = SinhTest(); let res13 = CoshTest(); let res14 = TanhTest(); + let res15 = IeeeRemainderTest(); MessageTest("Test"); } return sum; diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs index c94d03f3eb0..f686b63f18b 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs @@ -195,5 +195,88 @@ namespace Microsoft.Quantum.Testing.QIR.Math { return 0; } -} + // Remove when the Q# compiler bug https://github.com/microsoft/qsharp-compiler/issues/877 is resolved: + //function MyRound(value : Double) : Int { // 4.x 4.5 5.x 5.5 -4.x -4.5 -5.x -5.5 + // + // // Temporary piece of code to test a Q# compiler bug: + // + // let truncated = Truncate(value); // 4 4 5 5 -4 -4 -5 -5 + // if truncated >= 0 { + // let diff = value - IntAsDouble(truncated); // 0.x 0.5 0.x 0.5 diff + // if diff < 0.5 { return truncated; } // 4 5 return + // if diff > 0.5 { return (truncated + 1); } // 5 6 return + // if truncated % 2 == 0 { return truncated; } // 4 return + // else { return truncated + 1; } // 6 return + // } + // else { + // let diff = IntAsDouble(truncated) - value; // 0.x 0.5 0.x 0.5 diff + // if diff < 0.5 { return truncated; } // -4 -5 + // if diff > 0.5 { return (truncated - 1); } // -5 -6 + // if truncated % 2 == 0 { return truncated; } // -4 + // else { return truncated - 1; } // -6 + // } + // + // // End of temporary piece of code. + // + // + // // Temporary piece of code to work around the clang++ crash upon `Round()` (resolved in `0.15.2102129370-alpha`): + // + // //let truncated = Truncate(value); // 4 4 5 5 -4 -4 -5 -5 + // //if truncated >= 0 { + // // let diff = value - IntAsDouble(truncated); // 0.x 0.5 0.x 0.5 diff + // // if diff < 0.5 { return truncated; } // 4 5 return + // // if diff > 0.5 { return (truncated + 1); } // 5 6 return + // // if truncated % 2 == 0 { return truncated; } // 4 return + // // return truncated + 1; // 6 return + // //} + // //let diff2 = IntAsDouble(truncated) - value; // 0.x 0.5 0.x 0.5 diff + // //if diff2 < 0.5 { return truncated; } // -4 -5 + // //if diff2 > 0.5 { return (truncated - 1); } // -5 -6 + // //if truncated % 2 == 0 { return truncated; } // -4 + // //return truncated - 1; // -6 + // + // // End of temporary piece of code to work around the clang++ crash. + //} + + function IeeeRemainderTest() : Int { + + // function IeeeRemainder(x : Double, y : Double) : Double + + mutable dividend = -10.0; + while dividend <= 10.0 { + + mutable divisor = -20.0; + while divisor < 20.0 { + if divisor != 0.0 { + let absFractionalPart = AbsD(dividend / divisor) - IntAsDouble(AbsI(Truncate(dividend / divisor))); + if not Close(0.5, absFractionalPart) { // Because of the calculation errors the + // fractional part close to 0.5 causes very different result for + // the `remainder` and `IEEERemainder()` calculated below. + // That is normal but we avoid that. + let remainder = dividend - (divisor * IntAsDouble(Round(dividend / divisor))); + //MyRound(dividend / divisor))); // Remove when the https://github.com/microsoft/qsharp-compiler/issues/877 is resolved. + if not Close(remainder, IEEERemainder(dividend, divisor)) { + Message(DoubleAsString(remainder)); // The output for the test faiulure analysis, + Message(DoubleAsString(dividend)); // if the failure happens. + Message(DoubleAsString(divisor)); + Message(DoubleAsString(IEEERemainder(dividend, divisor))); + return 1; + } + } + } + set divisor = divisor + 0.3; + } + set dividend = dividend + 0.1; + } + if NAN() != IEEERemainder( INFINITY(), 1.0) { return 2; } + if NAN() != IEEERemainder(-INFINITY(), 1.0) { return 3; } + if NAN() != IEEERemainder(1.0, 0.0) { return 4; } + if NAN() != IEEERemainder(NAN(), 1.0) { return 5; } + if NAN() != IEEERemainder(1.0, NAN()) { return 6; } + if NAN() != IEEERemainder(NAN(), NAN()) { return 7; } + + return 0; + } + +} From 23213db76af720cf908ace1e751546fbb99b2cf9 Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Mon, 22 Feb 2021 18:58:42 -0800 Subject: [PATCH 8/8] Added ArcSin(), ArcCos(), ArcTan(), and tests. --- src/QirRuntime/lib/QIR/bridge-qis.ll | 25 ++++++ src/QirRuntime/lib/QIR/intrinsicsMath.cpp | 15 ++++ src/QirRuntime/lib/QIR/quantum__qis.hpp | 4 + .../test/QIR-static/qir-test-math.cpp | 18 +++++ .../test/QIR-static/qsharp/qir-test-arrays.qs | 3 + .../test/QIR-static/qsharp/qir-test-math.qs | 78 +++++++++++++++++++ 6 files changed, 143 insertions(+) diff --git a/src/QirRuntime/lib/QIR/bridge-qis.ll b/src/QirRuntime/lib/QIR/bridge-qis.ll index 0c66aba3433..6566d652351 100644 --- a/src/QirRuntime/lib/QIR/bridge-qis.ll +++ b/src/QirRuntime/lib/QIR/bridge-qis.ll @@ -306,6 +306,9 @@ declare i1 @quantum__qis__isinf__body(double %d) declare double @quantum__qis__arctan2__body(double %y, double %x) declare double @quantum__qis__sinh__body(double %theta) declare double @quantum__qis__cosh__body(double %theta) +declare double @quantum__qis__arcsin__body(double %theta) +declare double @quantum__qis__arccos__body(double %theta) +declare double @quantum__qis__arctan__body(double %theta) declare double @quantum__qis__ieeeremainder__body(double %y, double %x) declare i64 @quantum__qis__drawrandomint__body(i64 %min, i64 %max) @@ -399,6 +402,28 @@ define double @__quantum__qis__tanh__body(double %theta) { ; https://en.cpp ret double %result } +; function ArcSin (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.arcsin +define double @__quantum__qis__arcsin__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/asin + %result = call double @quantum__qis__arcsin__body(double %theta) + ret double %result +} + +; function ArcCos (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.arccos +define double @__quantum__qis__arccos__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/acos + %result = call double @quantum__qis__arccos__body(double %theta) + ret double %result +} + +; function ArcTan (theta : Double) : Double +; https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.math.arctan +define double @__quantum__qis__arctan__body(double %theta) { ; https://en.cppreference.com/w/cpp/numeric/math/atan + %result = call double @quantum__qis__arctan__body(double %theta) + ret double %result +} + + ; function IEEERemainder(x : Double, y : Double) : Double define double @__quantum__qis__ieeeremainder__body(double %x, double %y) { %result = call double @quantum__qis__ieeeremainder__body(double %x, double %y) diff --git a/src/QirRuntime/lib/QIR/intrinsicsMath.cpp b/src/QirRuntime/lib/QIR/intrinsicsMath.cpp index a99f575582b..41180ace397 100644 --- a/src/QirRuntime/lib/QIR/intrinsicsMath.cpp +++ b/src/QirRuntime/lib/QIR/intrinsicsMath.cpp @@ -50,6 +50,21 @@ double quantum__qis__cosh__body(double theta) return std::cosh(theta); } +double quantum__qis__arcsin__body(double theta) +{ + return std::asin(theta); // https://en.cppreference.com/w/cpp/numeric/math/asin +} + +double quantum__qis__arccos__body(double theta) +{ + return std::acos(theta); // https://en.cppreference.com/w/cpp/numeric/math/acos +} + +double quantum__qis__arctan__body(double theta) +{ + return std::atan(theta); // https://en.cppreference.com/w/cpp/numeric/math/atan +} + double quantum__qis__ieeeremainder__body(double x, double y) { return std::remainder(x, y); // https://en.cppreference.com/w/cpp/numeric/math/remainder diff --git a/src/QirRuntime/lib/QIR/quantum__qis.hpp b/src/QirRuntime/lib/QIR/quantum__qis.hpp index dd774586447..e22e1937f96 100644 --- a/src/QirRuntime/lib/QIR/quantum__qis.hpp +++ b/src/QirRuntime/lib/QIR/quantum__qis.hpp @@ -69,6 +69,10 @@ extern "C" QIR_SHARED_API double quantum__qis__arctan2__body(double y, double x); // NOLINT QIR_SHARED_API double quantum__qis__sinh__body(double theta); // NOLINT QIR_SHARED_API double quantum__qis__cosh__body(double theta); // NOLINT + QIR_SHARED_API double quantum__qis__arcsin__body(double theta); // NOLINT + QIR_SHARED_API double quantum__qis__arccos__body(double theta); // NOLINT + QIR_SHARED_API double quantum__qis__arctan__body(double theta); // NOLINT + QIR_SHARED_API double quantum__qis__ieeeremainder__body(double x, double y); // NOLINT QIR_SHARED_API int64_t quantum__qis__drawrandomint__body(int64_t minimum, int64_t maximum); // NOLINT diff --git a/src/QirRuntime/test/QIR-static/qir-test-math.cpp b/src/QirRuntime/test/QIR-static/qir-test-math.cpp index 4985c198f61..6995f4ac285 100644 --- a/src/QirRuntime/test/QIR-static/qir-test-math.cpp +++ b/src/QirRuntime/test/QIR-static/qir-test-math.cpp @@ -14,6 +14,9 @@ extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ArcTan2Test__body(); extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__CosTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TanTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ArcSinTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ArcCosTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__ArcTanTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__SinhTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__CoshTest__body(); // NOLINT extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TanhTest__body(); // NOLINT @@ -50,6 +53,21 @@ TEST_CASE("QIR: Math.Tan", "[qir.math][qir.Math.Tan]") REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__TanTest__body()); } +TEST_CASE("QIR: Math.ArcSin", "[qir.math][qir.Math.ArcSin]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__ArcSinTest__body()); +} + +TEST_CASE("QIR: Math.ArcCos", "[qir.math][qir.Math.ArcCos]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__ArcCosTest__body()); +} + +TEST_CASE("QIR: Math.ArcTan", "[qir.math][qir.Math.ArcTan]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__ArcTanTest__body()); +} + TEST_CASE("QIR: Math.Sinh", "[qir.math][qir.Math.Sinh]") { REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__SinhTest__body()); diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs index af1cbde29b2..0adc1cb96e1 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs @@ -49,6 +49,9 @@ namespace Microsoft.Quantum.Testing.QIR { let res13 = CoshTest(); let res14 = TanhTest(); let res15 = IeeeRemainderTest(); + let res16 = ArcSinTest(); + let res17 = ArcCosTest(); + let res18 = ArcTanTest(); MessageTest("Test"); } return sum; diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs index f686b63f18b..b89d8777f8a 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs @@ -144,6 +144,84 @@ namespace Microsoft.Quantum.Testing.QIR.Math { return 0; } + function ArcSinTest() : Int { + + // function ArcSin (theta : Double) : Double + + if not Close(0.0, ArcSin(0.0)) { return 1; } // The return value indicates which test case has failed. + + if not Close(PI()/6.0, ArcSin(0.5)) { return 2; } + if not Close(PI()/2.0, ArcSin(1.0)) { return 3; } + + if not Close(-PI()/6.0, ArcSin(-0.5)) { return 4; } + if not Close(-PI()/2.0, ArcSin(-1.0)) { return 5; } + + if not Close(PI()/4.0, ArcSin(Sqrt(2.0)/2.0)) { return 6; } + + if NAN() != ArcSin(NAN()) { return 7; } + if NAN() != ArcSin(1.1) { return 8; } + if NAN() != ArcSin(-1.1) { return 9; } + + mutable testVal = -1.0; + while testVal <= 1.0 { + if not Close(testVal, Sin(ArcSin(testVal))) { return 10; } + set testVal = testVal + 0.1; + } + + return 0; + } + + function ArcCosTest() : Int { + + // function ArcCos (theta : Double) : Double + + if not Close( 0.0, ArcCos(1.0)) { return 1; } // The return value indicates which test case has failed. + if not Close( PI()/3.0, ArcCos(0.5)) { return 2; } + if not Close( PI()/2.0, ArcCos(0.0)) { return 3; } + if not Close(2.0*PI()/3.0, ArcCos(-0.5)) { return 4; } + if not Close(PI(), ArcCos(-1.0)) { return 5; } + + if not Close(PI()/4.0, ArcCos(Sqrt(2.0)/2.0)) { return 6; } + + if NAN() != ArcCos(NAN()) { return 7; } + if NAN() != ArcCos(1.1) { return 8; } + if NAN() != ArcCos(-1.1) { return 9; } + + mutable testVal = -1.0; + while testVal <= 1.0 { + if not Close(testVal, Cos(ArcCos(testVal))) { return 10; } + set testVal = testVal + 0.1; + } + + return 0; + } + + function ArcTanTest() : Int { + + // function ArcTan (theta : Double) : Double + + if not Close( 0.0, ArcTan(0.0)) { return 1; } // The return value indicates which test case has failed. + if not Close( PI()/6.0, ArcTan(1.0/Sqrt(3.0))) { return 2; } // tg(Pi/6) = sin(Pi/6) / cos(Pi/6) = (1/2) / (sqrt(3)/2) = 1/sqrt(3) + if not Close( PI()/4.0, ArcTan(1.0)) { return 3; } + if not Close( PI()/3.0, ArcTan(Sqrt(3.0))) { return 4; } + + if not Close(-PI()/6.0, ArcTan(-1.0/Sqrt(3.0))) { return 5; } + if not Close(-PI()/4.0, ArcTan(-1.0)) { return 6; } + if not Close(-PI()/3.0, ArcTan(-Sqrt(3.0))) { return 7; } + + if NAN() != ArcTan(NAN()) { return 8; } + if not Close( PI()/2.0, ArcTan( INFINITY())) { return 9; } + if not Close(-PI()/2.0, ArcTan(-INFINITY())) { return 10; } + + mutable testVal = -10.0; + while testVal <= 10.0 { + if not Close(testVal, Tan(ArcTan(testVal))) { return 11; } + set testVal = testVal + 0.1; + } + + return 0; + } + function SinhTest() : Int { // function Sinh (theta : Double) : Double