From c0095bfb65cd1ce90e747197088df2febac0d48a Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Tue, 23 Feb 2021 17:29:50 -0800 Subject: [PATCH 1/4] Cleanup, adding Parity(). --- src/QirRuntime/test/QIR-static/CMakeLists.txt | 1 + .../test/QIR-static/qir-test-other.cpp | 11 +++++ .../test/QIR-static/qsharp/qir-test-arrays.qs | 2 + .../test/QIR-static/qsharp/qir-test-math.qs | 44 ------------------- .../test/QIR-static/qsharp/qir-test-other.qs | 40 +++++++++++++++++ 5 files changed, 54 insertions(+), 44 deletions(-) create mode 100644 src/QirRuntime/test/QIR-static/qir-test-other.cpp create mode 100644 src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs diff --git a/src/QirRuntime/test/QIR-static/CMakeLists.txt b/src/QirRuntime/test/QIR-static/CMakeLists.txt index 9fc202a931a..f82e0b7a928 100644 --- a/src/QirRuntime/test/QIR-static/CMakeLists.txt +++ b/src/QirRuntime/test/QIR-static/CMakeLists.txt @@ -21,6 +21,7 @@ add_executable(qir-static-tests qir-test-math.cpp qir-test-strings.cpp qir-test-ouput.cpp + qir-test-other.cpp ) target_link_libraries(qir-static-tests PUBLIC diff --git a/src/QirRuntime/test/QIR-static/qir-test-other.cpp b/src/QirRuntime/test/QIR-static/qir-test-other.cpp new file mode 100644 index 00000000000..41bd6b4b530 --- /dev/null +++ b/src/QirRuntime/test/QIR-static/qir-test-other.cpp @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "catch.hpp" + +extern "C" uint64_t Microsoft__Quantum__Testing__QIR__Other__ParityTest__body(); // NOLINT + +TEST_CASE("QIR: Other.Parity", "[qir.Other][qir.Other.Parity]") +{ + REQUIRE(0 == Microsoft__Quantum__Testing__QIR__Other__ParityTest__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 58ced577cd5..195e9905ec1 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-arrays.qs @@ -2,6 +2,7 @@ // Licensed under the MIT License. namespace Microsoft.Quantum.Testing.QIR { + open Microsoft.Quantum.Testing.QIR.Other; open Microsoft.Quantum.Testing.QIR.Math; open Microsoft.Quantum.Testing.QIR.Str; open Microsoft.Quantum.Testing.QIR.Out; @@ -53,6 +54,7 @@ namespace Microsoft.Quantum.Testing.QIR { let res16 = ArcSinTest(); let res17 = ArcCosTest(); let res18 = ArcTanTest(); + let res19 = ParityTest(); MessageTest("Test"); // Conditionals: 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 b89d8777f8a..137718d76cd 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-math.qs @@ -273,49 +273,6 @@ 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 @@ -332,7 +289,6 @@ namespace Microsoft.Quantum.Testing.QIR.Math { // 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. diff --git a/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs b/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs new file mode 100644 index 00000000000..38be795a6ab --- /dev/null +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Bitwise { + + function MyParity(param : Int) : Int { + mutable tmpParam = param; + mutable result = false; + while tmpParam != 0 { + set tmpParam = tmpParam &&& (tmpParam - 1); + set result = not result; + } + return (result ? 1 | 0); + } +} + +namespace Microsoft.Quantum.Testing.QIR.Other { + + open Microsoft.Quantum.Bitwise; + + function ParityTest() : Int { + //function Parity (a : Int) : Int + if 0 != MyParity(0) { return 1; } + if 1 != MyParity(1) { return 2; } + if 1 != MyParity(2) { return 3; } + if 0 != MyParity(3) { return 4; } + if 0 != MyParity(0xFF) { return 5; } + if 1 != MyParity(0x100) { return 6; } + if 0 != MyParity(0xFFFF) { return 7; } + if 1 != MyParity(0x10000) { return 8; } + if 1 != MyParity(0x7F00000000000000) { return 9; } + if 0 != MyParity(0x0F00000000000000) { return 10; } + + if 0 != MyParity(-1) { return 11; } // 0xFFFFFFFFFFFFFFFF + if 1 != MyParity(-2) { return 12; } // 0xFFFFFFFFFFFFFFFE + + return 0; + } + +} From 64e9d8cd01ca5d1d3be5e8bb6e329eb26dc25bce Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Wed, 24 Feb 2021 14:04:09 -0800 Subject: [PATCH 2/4] Added Parity(). --- AdvantageBenchmark/privateBuild/host.csproj | 2 +- .../releasedBuild/quantum/quantum.csproj | 2 +- .../test/QIR-static/qsharp/qir-test-other.qs | 39 +++++++------------ .../QSharpFoundation/Bitwise/Bitwise.qs | 12 +++++- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/AdvantageBenchmark/privateBuild/host.csproj b/AdvantageBenchmark/privateBuild/host.csproj index 0af33ce55d9..c38a2e4750d 100644 --- a/AdvantageBenchmark/privateBuild/host.csproj +++ b/AdvantageBenchmark/privateBuild/host.csproj @@ -1,4 +1,4 @@ - + diff --git a/AdvantageBenchmark/releasedBuild/quantum/quantum.csproj b/AdvantageBenchmark/releasedBuild/quantum/quantum.csproj index e89bfdce2bb..d92408e6a0e 100644 --- a/AdvantageBenchmark/releasedBuild/quantum/quantum.csproj +++ b/AdvantageBenchmark/releasedBuild/quantum/quantum.csproj @@ -1,4 +1,4 @@ - + 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 38be795a6ab..efb30081098 100644 --- a/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs @@ -1,38 +1,25 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -namespace Microsoft.Quantum.Bitwise { - - function MyParity(param : Int) : Int { - mutable tmpParam = param; - mutable result = false; - while tmpParam != 0 { - set tmpParam = tmpParam &&& (tmpParam - 1); - set result = not result; - } - return (result ? 1 | 0); - } -} - namespace Microsoft.Quantum.Testing.QIR.Other { open Microsoft.Quantum.Bitwise; function ParityTest() : Int { //function Parity (a : Int) : Int - if 0 != MyParity(0) { return 1; } - if 1 != MyParity(1) { return 2; } - if 1 != MyParity(2) { return 3; } - if 0 != MyParity(3) { return 4; } - if 0 != MyParity(0xFF) { return 5; } - if 1 != MyParity(0x100) { return 6; } - if 0 != MyParity(0xFFFF) { return 7; } - if 1 != MyParity(0x10000) { return 8; } - if 1 != MyParity(0x7F00000000000000) { return 9; } - if 0 != MyParity(0x0F00000000000000) { return 10; } - - if 0 != MyParity(-1) { return 11; } // 0xFFFFFFFFFFFFFFFF - if 1 != MyParity(-2) { return 12; } // 0xFFFFFFFFFFFFFFFE + if 0 != Parity(0) { return 1; } + if 1 != Parity(1) { return 2; } + if 1 != Parity(2) { return 3; } + if 0 != Parity(3) { return 4; } + if 0 != Parity(0xFF) { return 5; } + if 1 != Parity(0x100) { return 6; } + if 0 != Parity(0xFFFF) { return 7; } + if 1 != Parity(0x10000) { return 8; } + if 1 != Parity(0x7F00000000000000) { return 9; } + if 0 != Parity(0x0F00000000000000) { return 10; } + + if 0 != Parity(-1) { return 11; } // 0xFFFFFFFFFFFFFFFF + if 1 != Parity(-2) { return 12; } // 0xFFFFFFFFFFFFFFFE return 0; } diff --git a/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs b/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs index 95b98b4e2d5..8e0ce067ce8 100644 --- a/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs +++ b/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs @@ -83,7 +83,17 @@ namespace Microsoft.Quantum.Bitwise { /// let x = Parity(a); // x : Int = 1. /// ``` function Parity (a : Int) : Int { - body intrinsic; + mutable tmpParam = a; + mutable result = false; + while tmpParam != 0 { + // Clear (to `0`) the least significant `1` (not to confuse with the least significant bit). E.g. + // x : 1101 0100 + // x-1 : 1101 0011 + // x &&& (x-1): 1101 0000 The least significant `1` has been cleared. + set tmpParam = tmpParam &&& (tmpParam - 1); + set result = not result; + } + return (result ? 1 | 0); } // Common implementation for XBits and ZBits. From cfa5d5606c941f15ed6846e25f8a7e40fb001e25 Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Wed, 24 Feb 2021 21:43:23 -0800 Subject: [PATCH 3/4] CR changes. --- .../QSharpFoundation/Bitwise/Bitwise.qs | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs b/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs index 8e0ce067ce8..7e30700c942 100644 --- a/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs +++ b/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs @@ -75,7 +75,9 @@ namespace Microsoft.Quantum.Bitwise { /// # Summary - /// Returns the bitwise PARITY of an integer (1 if its binary representation contains odd number of ones and 0 otherwise). + /// Returns the bitwise PARITY of an integer + /// (1 if its [two's complement](https://en.wikipedia.org/wiki/Signed_number_representations#Two's_complement) + /// representation contains odd number of ones and 0 otherwise). /// /// # Example /// ```qsharp @@ -83,17 +85,28 @@ namespace Microsoft.Quantum.Bitwise { /// let x = Parity(a); // x : Int = 1. /// ``` function Parity (a : Int) : Int { - mutable tmpParam = a; - mutable result = false; - while tmpParam != 0 { - // Clear (to `0`) the least significant `1` (not to confuse with the least significant bit). E.g. - // x : 1101 0100 - // x-1 : 1101 0011 - // x &&& (x-1): 1101 0000 The least significant `1` has been cleared. - set tmpParam = tmpParam &&& (tmpParam - 1); - set result = not result; - } - return (result ? 1 | 0); + mutable v = a; + // http://graphics.stanford.edu/~seander/bithacks.html#ParityMultiply + // XOR the bits in every 2-bit pair, save the result in the least significant bit (LSB) of the pair: + set v = v ^^^ (v >>> 1); // bit[0] = bit[0] ^ bit[1]; bit[2] = bit[2] ^ bit[3]; .. + // Now only the even bits contain the information. + // XOR the even bits in every 4-bit nibble, save the result in the LSB of the nibble: + set v = v ^^^ (v >>> 2); // bit[0] = bit[0] ^ bit[2]; bit[4] = bit[4] ^ bit[6]; .. + // Now only the LSB of each nibble contains the information. + set v = + (v &&& 0x1111111111111111) // In every 4-bit nibble clear (to '0') all the bits except the LSB. + * 0x1111111111111111; // Explanation with a 32-bit example: + // V (Down arrow) We are interested in the LSB of the most significant 4-bit nibble. + // 0x11111111 The multiplier `* 0x1111111111111111UL` above. + // * 0x10010011 The result of `(v & 0x1111111111111111UL)`, we will designate this value as (A). + // ---------- + // 0x11111111 + // + 0x11111111 + // 0x11111111 + // 0x1111111 + //----------------- + // 4 The value in the most significant 4-bit nibble is equal to the number of 1s in (A). The LSB is 0. + return (v >>> 60) &&& 1; // Return the LSB of the most significant 4-bit nibble. } // Common implementation for XBits and ZBits. From af54e1311921052899177f890b2c643a9fd7e469 Mon Sep 17 00:00:00 2001 From: Robin Kuzmin Date: Thu, 25 Feb 2021 10:58:41 -0800 Subject: [PATCH 4/4] CR changes. --- .../QSharpFoundation/Bitwise/Bitwise.qs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs b/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs index 7e30700c942..8e2b5a40215 100644 --- a/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs +++ b/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs @@ -75,9 +75,13 @@ namespace Microsoft.Quantum.Bitwise { /// # Summary - /// Returns the bitwise PARITY of an integer - /// (1 if its [two's complement](https://en.wikipedia.org/wiki/Signed_number_representations#Two's_complement) - /// representation contains odd number of ones and 0 otherwise). + /// Returns the bitwise PARITY of an integer. + /// + /// # Description + /// This function returns the bitwise parity of the + /// [two's complement](https://en.wikipedia.org/wiki/Signed_number_representations#Two's_complement) + /// representation of its input, returning `1` if that representation + /// contains an odd number of ones, and returning `0` otherwise. /// /// # Example /// ```qsharp @@ -88,10 +92,10 @@ namespace Microsoft.Quantum.Bitwise { mutable v = a; // http://graphics.stanford.edu/~seander/bithacks.html#ParityMultiply // XOR the bits in every 2-bit pair, save the result in the least significant bit (LSB) of the pair: - set v = v ^^^ (v >>> 1); // bit[0] = bit[0] ^ bit[1]; bit[2] = bit[2] ^ bit[3]; .. + set v ^^^= (v >>> 1); // bit[0] = bit[0] ^ bit[1]; bit[2] = bit[2] ^ bit[3]; .. // Now only the even bits contain the information. // XOR the even bits in every 4-bit nibble, save the result in the LSB of the nibble: - set v = v ^^^ (v >>> 2); // bit[0] = bit[0] ^ bit[2]; bit[4] = bit[4] ^ bit[6]; .. + set v ^^^= (v >>> 2); // bit[0] = bit[0] ^ bit[2]; bit[4] = bit[4] ^ bit[6]; .. // Now only the LSB of each nibble contains the information. set v = (v &&& 0x1111111111111111) // In every 4-bit nibble clear (to '0') all the bits except the LSB. @@ -105,7 +109,8 @@ namespace Microsoft.Quantum.Bitwise { // 0x11111111 // 0x1111111 //----------------- - // 4 The value in the most significant 4-bit nibble is equal to the number of 1s in (A). The LSB is 0. + // 4 The value in the most significant 4-bit nibble is equal to the number of 1s in (A), + // modulo 16. The LSB is 0. return (v >>> 60) &&& 1; // Return the LSB of the most significant 4-bit nibble. }