Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Restructured sqrt.
Browse files Browse the repository at this point in the history
  • Loading branch information
kuzminrobin committed Feb 6, 2021
1 parent 6b7665c commit 1527b19
Show file tree
Hide file tree
Showing 11 changed files with 493 additions and 167 deletions.
1 change: 1 addition & 0 deletions src/QirRuntime/lib/QIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ add_dependencies(qir-rt ${bridge_rt_target})
#
set(qis_sup_source_files
"intrinsics.cpp"
"intrinsicsMath.cpp"
)

add_library(qir-qis-support ${qis_sup_source_files})
Expand Down
45 changes: 39 additions & 6 deletions src/QirRuntime/lib/QIR/bridge-qis.ll
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,44 @@ define void @__quantum__qis__z__ctl(%Array* %.ctls, %Qubit* %.q) {
; quantum.qis math functions
;

; LLVM intrinsics:
; https://llvm.org/docs/LangRef.html
declare double @llvm.sqrt.f64(double %.val)
; LLVM intrinsics (https://llvm.org/docs/LangRef.html):
declare double @llvm.sqrt.f64(double %.val)
;declare double @llvm.ceil.f64(double %Val)

; Native implementations:
declare i1 @quantum__qis__isnan__body(double %d)
declare double @quantum__qis__infinity__body()
declare i1 @quantum__qis__isinf__body(double %d)

; API for the user code:
define double @__quantum__qis__nan__body() { ; http://www.cplusplus.com/reference/cmath/nan-function/
%result = call double @llvm.sqrt.f64(double -1.0) ; sqrt(<negative>) -> NaN
ret double %result
}

define i1 @__quantum__qis__isnan__body(double %d) { ; http://www.cplusplus.com/reference/cmath/isnan/
%result = call i1 @quantum__qis__isnan__body(double %d)
ret i1 %result
}

define double @__quantum__qis__infinity__body() { ; https://en.cppreference.com/w/c/numeric/math/INFINITY
%result = call double @quantum__qis__infinity__body()
ret double %result
}

define double @__quantum__qis__sqrt__body(double %.val) {
%value = call double @llvm.sqrt.f64(double %.val)
ret double %value
define i1 @__quantum__qis__isinf__body(double %d) { ; https://en.cppreference.com/w/cpp/numeric/math/isinf
%result = call i1 @quantum__qis__isinf__body(double %d)
ret i1 %result
}

define double @__quantum__qis__sqrt__body(double %d) { ; https://en.cppreference.com/w/cpp/numeric/math/sqrt
%result = call double @llvm.sqrt.f64(double %d)
ret double %result
}

;define i64 @__quantum__qis__ceiling__body(double %d) {
; %doubleResult = call double @llvm.ceil.f64(double %d)
; %result = call i64 @quantum__qis__doubleasint__body(double $doubleResult) ; Should be the same as DoubleAsInt in https://github.com/microsoft/qsharp-runtime/pull/497/files
; ret i64 %result
;}

30 changes: 30 additions & 0 deletions src/QirRuntime/lib/QIR/intrinsicsMath.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include <cmath>

extern "C"
{

// Declarations:
bool quantum__qis__isnan__body(double d);
double quantum__qis__inf__body();
bool quantum__qis__isinf__body(double d);

// Implementations:
bool quantum__qis__isnan__body(double d)
{
return isnan(d); // https://en.cppreference.com/w/cpp/numeric/math/isnan
}

double quantum__qis__infinity__body()
{
return INFINITY; // https://en.cppreference.com/w/c/numeric/math/INFINITY
}

bool quantum__qis__isinf__body(double d)
{
return isinf(d); // https://en.cppreference.com/w/cpp/numeric/math/isinf
}

} // extern "C"
1 change: 1 addition & 0 deletions src/QirRuntime/test/QIR-dynamic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ add_executable(qir-dynamic-tests
target_link_libraries(qir-dynamic-tests PUBLIC
${QIR_TESTS_LIBS}
qdk
qir-qis-support
)

target_include_directories(qir-dynamic-tests PUBLIC
Expand Down
20 changes: 20 additions & 0 deletions src/QirRuntime/test/QIR-static/compiler/QirTarget.qs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ namespace Microsoft.Quantum.Intrinsic {

open Microsoft.Quantum.Targeting;

function NAN() : Double {
body intrinsic;
}

function IsNan(d: Double) : Bool {
body intrinsic;
}

function INFINITY() : Double {
body intrinsic;
}

function IsInf(d: Double) : Bool {
body intrinsic;
}

function Sqrt(d : Double) : Double {
body intrinsic;
}

operation X(qb : Qubit) : Unit
is Adj + Ctl {
body intrinsic;
Expand Down
12 changes: 6 additions & 6 deletions src/QirRuntime/test/QIR-static/qir-driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ extern "C" int64_t Microsoft__Quantum__Testing__QIR__Test_Arrays( // NOLINT
int64_t index,
int64_t val,
bool dummy);
TEST_CASE("QIR: Using 1D arrays", "[qir]")
TEST_CASE("QIR: Using 1D arrays", "[qir][qir.arr1d]")
{
// re-enable tracking when https://github.com/microsoft/qsharp-compiler/issues/844 is fixed
QirContextScope qirctx(nullptr, false /*trackAllocatedObjects*/);
Expand Down Expand Up @@ -152,7 +152,7 @@ struct QubitsResultsTestSimulator : public Microsoft::Quantum::SimulatorStub
return reinterpret_cast<Result>(1);
}
};
TEST_CASE("QIR: allocating and releasing qubits and results", "[qir]")
TEST_CASE("QIR: allocating and releasing qubits and results", "[qir][qir.qubit][qir.result]")
{
unique_ptr<QubitsResultsTestSimulator> sim = make_unique<QubitsResultsTestSimulator>();
QirContextScope qirctx(sim.get(), true /*trackAllocatedObjects*/);
Expand Down Expand Up @@ -182,7 +182,7 @@ TEST_CASE("QIR: allocating and releasing qubits and results", "[qir]")
// that is written to the original array at [1,1,1] and then retrieved from [1,1].
// Thus, all three dimensions must be at least 2.
extern "C" int64_t TestMultidimArrays(char value, int64_t dim0, int64_t dim1, int64_t dim2);
TEST_CASE("QIR: multidimensional arrays", "[qir]")
TEST_CASE("QIR: multidimensional arrays", "[qir][qir.arrMultid]")
{
QirContextScope qirctx(nullptr, true /*trackAllocatedObjects*/);

Expand All @@ -195,7 +195,7 @@ TEST_CASE("QIR: multidimensional arrays", "[qir]")

// Manually authored QIR to test dumping range [0..2..6] into string and then raising a failure with it
extern "C" void TestFailWithRangeString(int64_t start, int64_t step, int64_t end);
TEST_CASE("QIR: Report range in a failure message", "[qir]")
TEST_CASE("QIR: Report range in a failure message", "[qir][qir.range]")
{
QirContextScope qirctx(nullptr, true /*trackAllocatedObjects*/);

Expand All @@ -215,7 +215,7 @@ TEST_CASE("QIR: Report range in a failure message", "[qir]")
#if 0 // TODO: Q# compiler crashes generating QIR for TestPartials
// TestPartials subtracts the second argument from the first and returns the result.
extern "C" int64_t Microsoft__Quantum__Testing__QIR__TestPartials__body(int64_t, int64_t); // NOLINT
TEST_CASE("QIR: Partial application of a callable", "[qir]")
TEST_CASE("QIR: Partial application of a callable", "[qir][qir.partCallable]")
{
QirContextScope qirctx(nullptr, true /*trackAllocatedObjects*/);

Expand Down Expand Up @@ -309,7 +309,7 @@ extern "C" void __quantum__qis__k__ctl(QirArray* controls, Qubit q) // NOLINT
{
g_ctrqapi->ControlledX(controls->count, reinterpret_cast<Qubit*>(controls->buffer), q);
}
TEST_CASE("QIR: application of nested controlled functor", "[qir]")
TEST_CASE("QIR: application of nested controlled functor", "[qir][qir.functor]")
{
unique_ptr<FunctorsTestSimulator> qapi = make_unique<FunctorsTestSimulator>();
QirContextScope qirctx(qapi.get(), true /*trackAllocatedObjects*/);
Expand Down
6 changes: 4 additions & 2 deletions src/QirRuntime/test/QIR-static/qir-test-arrays.qs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

namespace Microsoft.Quantum.Testing.QIR
{
open Microsoft.Quantum.Testing.QIR.Math;

@EntryPoint()
operation Test_Arrays(array : Int[], index : Int, val : Int, dummy : Bool) : Int
{
Expand Down Expand Up @@ -33,9 +35,9 @@ namespace Microsoft.Quantum.Testing.QIR
if (dummy)
{
let res1 = TestControlled();
//Q# compiler crashes if both TestControlled and TestPartials are enabled
//let res2 = TestPartials(17, 42);
let res2 = TestPartials(17, 42);
let res3 = Test_Qubit_Result_Management();
let res4 = TestSqrt();
}

return sum;
Expand Down
12 changes: 3 additions & 9 deletions src/QirRuntime/test/QIR-static/qir-test-math.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
#include <cmath>
#include <cstdint>

#include "catch.hpp"

extern "C" double __quantum__qis__sqrt__body(double); // NOLINT
extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Math__TestSqrt__body(); // NOLINT

TEST_CASE("QIR: math.sqrt", "[qir.math][qir.math.sqrt]")
{
REQUIRE(2.0 == __quantum__qis__sqrt__body((double)4.0));
REQUIRE(3.0 == __quantum__qis__sqrt__body((double)9.0));
REQUIRE(10.0 == __quantum__qis__sqrt__body((double)100.0));

REQUIRE( isnan(__quantum__qis__sqrt__body((double)-5.0)) ); // (double)NAN == sqrt((double)-5.0)
REQUIRE( isnan(__quantum__qis__sqrt__body(nan(""))) ); // (double)NAN == sqrt((double)<quiet NAN>)
REQUIRE( isinf(__quantum__qis__sqrt__body((double)INFINITY)) ); // +-infinity == sqrt((double) +infinity)
REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Math__TestSqrt__body());
}
24 changes: 24 additions & 0 deletions src/QirRuntime/test/QIR-static/qir-test-math.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.Quantum.Testing.QIR.Math
{
open Microsoft.Quantum.Intrinsic;

function TestSqrt() : Int
{
mutable testResult = 0;

if( 2.0 != Sqrt( 4.0) ) { set testResult = 1; }
else { if( 3.0 != Sqrt( 9.0) ) { set testResult = 2; }
else { if( 10.0 != Sqrt(100.0) ) { set testResult = 3; }

else { if( not IsNan(Sqrt(-5.0))) { set testResult = 4; }
else { if( not IsNan(Sqrt(NAN()))) { set testResult = 5; }
else { if( not IsInf(Sqrt(INFINITY()))) { set testResult = 6; }
}}}}}

return testResult;
}
}

Loading

0 comments on commit 1527b19

Please sign in to comment.