From d90911592153744d72a6c0e0011a934940f40fea Mon Sep 17 00:00:00 2001 From: Mathias Soeken Date: Tue, 12 Apr 2022 16:41:50 +0200 Subject: [PATCH 1/2] Fixes #560. --- Numerics/src/FixedPoint/Convert.qs | 22 ++++++++++++++++++++ Numerics/src/FixedPoint/Measurement.qs | 21 ++++++------------- Numerics/tests/FixedPointTests.qs | 28 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 Numerics/src/FixedPoint/Convert.qs diff --git a/Numerics/src/FixedPoint/Convert.qs b/Numerics/src/FixedPoint/Convert.qs new file mode 100644 index 00000000000..a91ffe0ddb8 --- /dev/null +++ b/Numerics/src/FixedPoint/Convert.qs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Convert { + open Microsoft.Quantum.Arrays; + open Microsoft.Quantum.Math; + + /// # Summary + /// Returns the double value of a fixed-point approximation from of a `Bool` array. + /// + /// # Input + /// ## integerBits + /// Assumed number of integerBits (including the sign big) + /// ## bits + /// Bit-string representation of approximated number + internal function BoolArrayAsFixedPoint(integerBits : Int, bits : Bool[]) : Double { + let numBits = Length(bits); + let intPart = (Tail(bits) ? -(1 <<< (numBits - 1)) | 0) + BoolArrayAsInt(Most(bits)); + return IntAsDouble(intPart) / PowD(2.0, IntAsDouble(numBits - integerBits)); + } + +} diff --git a/Numerics/src/FixedPoint/Measurement.qs b/Numerics/src/FixedPoint/Measurement.qs index e6b928dd624..e5426d7762e 100644 --- a/Numerics/src/FixedPoint/Measurement.qs +++ b/Numerics/src/FixedPoint/Measurement.qs @@ -2,9 +2,10 @@ // Licensed under the MIT License. namespace Microsoft.Quantum.Arithmetic { + open Microsoft.Quantum.Arrays; + open Microsoft.Quantum.Canon; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Measurement; - open Microsoft.Quantum.Math; /// # Summary /// Measure a fixed-point number, returns its value as Double, and resets @@ -15,18 +16,8 @@ namespace Microsoft.Quantum.Arithmetic { /// Fixed-point number to measure. operation MeasureFxP(fp : FixedPoint) : Double { let (p, xs) = fp!; - let n = Length(xs); - let sign = MResetZ(xs[n-1]) == One; - mutable keepAdding = sign; - mutable fpAsDouble = 0.; - for i in 0..n - 2 { - mutable currentRes = MResetZ(xs[i]) == (sign ? Zero | One); - if keepAdding { - set keepAdding = currentRes; - set currentRes = not currentRes; - } - set fpAsDouble = fpAsDouble * 0.5 + (currentRes == true ? 1. | 0.); - } - return (sign ? -1.0 | 1.0) * fpAsDouble * PowD(2.0, IntAsDouble(p-2)); + + let bits = Mapped(IsResultOne, ForEach(MResetZ, xs)); + return BoolArrayAsFixedPoint(p, bits); } -} \ No newline at end of file +} diff --git a/Numerics/tests/FixedPointTests.qs b/Numerics/tests/FixedPointTests.qs index b420cdf00f3..0ecf6254e1d 100644 --- a/Numerics/tests/FixedPointTests.qs +++ b/Numerics/tests/FixedPointTests.qs @@ -3,6 +3,7 @@ namespace Microsoft.Quantum.Numerics.ToffoliTests { open Microsoft.Quantum.Arrays; + open Microsoft.Quantum.Canon; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Math; open Microsoft.Quantum.Intrinsic; @@ -21,6 +22,33 @@ namespace Microsoft.Quantum.Numerics.ToffoliTests { } } + internal operation PrepareAsSignedAndMeasure(value : Int, fxp : FixedPoint) : Double { + ApplyXorInPlace(value, LittleEndian(Snd(fxp!))); + return MeasureFxP(fxp); + } + + operation MeasureFxPTest() : Unit { + use qs = Qubit[4]; + let qsFxP = FixedPoint(2, qs); + + NearEqualityFactD(PrepareAsSignedAndMeasure(0b0000, qsFxP), 0.0); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b0001, qsFxP), 0.25); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b0010, qsFxP), 0.5); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b0011, qsFxP), 0.75); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b0100, qsFxP), 1.0); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b0101, qsFxP), 1.25); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b0110, qsFxP), 1.5); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b0111, qsFxP), 1.75); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b1000, qsFxP), -2.0); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b1001, qsFxP), -1.75); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b1010, qsFxP), -1.5); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b1011, qsFxP), -1.25); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b1100, qsFxP), -1.00); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b1101, qsFxP), -0.75); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b1110, qsFxP), -0.5); + NearEqualityFactD(PrepareAsSignedAndMeasure(0b1111, qsFxP), -0.25); + } + operation CompareGreaterThanFxPTest() : Unit { for a in [1.2, 3.9, 3.14159, -0.6, -4.5, -3.1931, 0.0] { for b in [1.1, 3.95, 3.14259, -0.4, -4.6, -3.931, 0.1] { From a76563efe138b20be616e4f43d31be2496fd953b Mon Sep 17 00:00:00 2001 From: Mathias Soeken Date: Wed, 13 Apr 2022 00:33:58 -0700 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Cassandra Granade --- Numerics/src/FixedPoint/Measurement.qs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Numerics/src/FixedPoint/Measurement.qs b/Numerics/src/FixedPoint/Measurement.qs index e5426d7762e..e746c34c5b6 100644 --- a/Numerics/src/FixedPoint/Measurement.qs +++ b/Numerics/src/FixedPoint/Measurement.qs @@ -17,7 +17,7 @@ namespace Microsoft.Quantum.Arithmetic { operation MeasureFxP(fp : FixedPoint) : Double { let (p, xs) = fp!; - let bits = Mapped(IsResultOne, ForEach(MResetZ, xs)); + let bits = ForEach(q => MResetZ(q) == One, xs); return BoolArrayAsFixedPoint(p, bits); } }