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/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..efb30081098 --- /dev/null +++ b/src/QirRuntime/test/QIR-static/qsharp/qir-test-other.qs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Testing.QIR.Other { + + open Microsoft.Quantum.Bitwise; + + function ParityTest() : Int { + //function Parity (a : Int) : Int + 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..8e2b5a40215 100644 --- a/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs +++ b/src/Simulation/QSharpFoundation/Bitwise/Bitwise.qs @@ -75,7 +75,13 @@ 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. + /// + /// # 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 @@ -83,7 +89,29 @@ namespace Microsoft.Quantum.Bitwise { /// let x = Parity(a); // x : Int = 1. /// ``` function Parity (a : Int) : Int { - body intrinsic; + 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 >>> 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 >>> 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), + // modulo 16. The LSB is 0. + return (v >>> 60) &&& 1; // Return the LSB of the most significant 4-bit nibble. } // Common implementation for XBits and ZBits.