diff --git a/src/QirRuntime/test/QIR-static/qir-test-other.cpp b/src/QirRuntime/test/QIR-static/qir-test-other.cpp index 41bd6b4b530..d77225ed86d 100644 --- a/src/QirRuntime/test/QIR-static/qir-test-other.cpp +++ b/src/QirRuntime/test/QIR-static/qir-test-other.cpp @@ -3,7 +3,20 @@ #include "catch.hpp" -extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Other__ParityTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Other__ParityTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Other__PauliArrayAsIntTest__body(); // NOLINT +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Other__PauliArrayAsIntFailTest__body(); // NOLINT + +TEST_CASE("QIR: Other.PauliArrayAsIntFail", "[qir.Other][qir.Other.PauliArrayAsIntFail]") +{ + REQUIRE_THROWS(Microsoft__Quantum__Testing__QIR__Other__PauliArrayAsIntFailTest__body()); +} + +TEST_CASE("QIR: Other.PauliArrayAsInt", "[qir.Other][qir.Other.PauliArrayAsInt]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Other__PauliArrayAsIntTest__body()); +} + TEST_CASE("QIR: Other.Parity", "[qir.Other][qir.Other.Parity]") { 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 195e9905ec1..efe2e706db7 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs @@ -55,6 +55,8 @@ namespace Microsoft.Quantum.Testing.QIR { let res17 = ArcCosTest(); let res18 = ArcTanTest(); let res19 = ParityTest(); + let res20 = PauliArrayAsIntTest(); + let res21 = PauliArrayAsIntFailTest(); MessageTest("Test"); // Conditionals: diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs index efb30081098..88150a8da11 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs @@ -4,10 +4,32 @@ namespace Microsoft.Quantum.Testing.QIR.Other { open Microsoft.Quantum.Bitwise; + open Microsoft.Quantum.Convert; + + function PauliArrayAsIntTest() : Int { + if 0 != PauliArrayAsInt([PauliI]) { return 1; } // The return value indicates which test case has failed. + if 1 != PauliArrayAsInt([PauliX]) { return 2; } + if 3 != PauliArrayAsInt([PauliY]) { return 3; } + if 2 != PauliArrayAsInt([PauliZ]) { return 4; } + + if 0x2310 != PauliArrayAsInt( + [PauliI, PauliI, PauliX, PauliI, PauliY, PauliI, PauliZ, PauliI]) { return 5; } + + // The Pauli array items are default-initialized to PauliI. + if 0 != PauliArrayAsInt(new Pauli[31]) { return 6; } // Todo: Replace `new Pauli[31]` with `[PauliI, size=31]` when that is implemented. + + if 0x3000000000000000 != PauliArrayAsInt(new Pauli[31] w/ 30 <- PauliY) { return 7; } + + return 0; + } + + function PauliArrayAsIntFailTest() : Int { + return PauliArrayAsInt(new Pauli[32]); // Must fail/throw. + } function ParityTest() : Int { //function Parity (a : Int) : Int - if 0 != Parity(0) { return 1; } + if 0 != Parity(0) { return 1; } // The return value indicates which test case has failed. if 1 != Parity(1) { return 2; } if 1 != Parity(2) { return 3; } if 0 != Parity(3) { return 4; } @@ -23,5 +45,4 @@ namespace Microsoft.Quantum.Testing.QIR.Other { return 0; } - } diff --git a/src/Simulation/QSharpFoundation/Convert/Convert.cs b/src/Simulation/QSharpFoundation/Convert/Convert.cs index a86ac9dfa39..ffcc86d8b55 100644 --- a/src/Simulation/QSharpFoundation/Convert/Convert.cs +++ b/src/Simulation/QSharpFoundation/Convert/Convert.cs @@ -159,42 +159,4 @@ public Native(IOperationFactory m) : base(m) { } } } - public partial class PauliArrayAsInt - { - public class Native : PauliArrayAsInt - { - static long PauliBitsFunc(IQArray pauli) - { - if (pauli.Length > 31) { throw new ExecutionFailException("Cannot pack bits of Pauli array longer than 31"); } - ulong res = 0; - for (long i = pauli.Length - 1; i >= 0; --i) - { - res <<= 2; - if (pauli[i] == Pauli.PauliZ) - { - res |= 2; - } - else if (pauli[i] == Pauli.PauliX) - { - res |= 1; - } - else if (pauli[i] == Pauli.PauliY) - { - res |= 3; - } - else if (pauli[i] == Pauli.PauliI) - { - } - else - { - System.Diagnostics.Debug.Assert(false, "this line should never be reached"); - } - } - return System.Convert.ToInt64(res); - } - - public Native(IOperationFactory m) : base(m) { } - public override Func, long> __Body__ => PauliBitsFunc; - } - } } diff --git a/src/Simulation/QSharpFoundation/Convert/Convert.qs b/src/Simulation/QSharpFoundation/Convert/Convert.qs index 2a7451174fc..fb501496b73 100644 --- a/src/Simulation/QSharpFoundation/Convert/Convert.qs +++ b/src/Simulation/QSharpFoundation/Convert/Convert.qs @@ -164,7 +164,21 @@ namespace Microsoft.Quantum.Convert { /// the mappings of each Pauli operator in big-endian order /// `bits(Pn) ... bits(P0)`. function PauliArrayAsInt(paulis : Pauli[]) : Int { - body intrinsic; + let len = Length(paulis); + if len > 31 { + fail $"Cannot pack bits of Pauli array longer than 31 (got {len})."; + } + + mutable result = 0; + for p in paulis[(len-1)..-1..0] { + set result <<<= 2; + if p == PauliI { set result += 0; } + elif p == PauliX { set result += 1; } + elif p == PauliY { set result += 3; } + elif p == PauliZ { set result += 2; } + else { fail $"Unexpected Pauli value {p}."; } + } + return result; } }