From a084a1fb6284725439eb2bcfcea9591c5ea8c4af Mon Sep 17 00:00:00 2001 From: Mathias Soeken Date: Fri, 22 Apr 2022 17:39:53 +0200 Subject: [PATCH] Implements fixed-point conversion functions (#575) * Implements #559. * Apply suggestions from code review Co-authored-by: Mariia Mykhailova * Use new UDT fields. Co-authored-by: Mariia Mykhailova --- Numerics/src/FixedPoint/Convert.qs | 54 ++++++++++++++++++++++++++++-- Numerics/src/FixedPoint/Init.qs | 28 +++------------- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/Numerics/src/FixedPoint/Convert.qs b/Numerics/src/FixedPoint/Convert.qs index a91ffe0ddb8..b8fa5f2368b 100644 --- a/Numerics/src/FixedPoint/Convert.qs +++ b/Numerics/src/FixedPoint/Convert.qs @@ -5,18 +5,66 @@ namespace Microsoft.Quantum.Convert { open Microsoft.Quantum.Arrays; open Microsoft.Quantum.Math; + /// # Summary + /// Computes fixed-point approximation for a double and returns it as `Bool` array. + /// + /// # Input + /// ## integerBits + /// Assumed number of integer bits (including the sign bit). + /// ## fractionalBits + /// Assumed number of fractional bits. + /// ## value + /// Value to be approximated. + function FixedPointAsBoolArray(integerBits : Int, fractionalBits : Int, value : Double) : Bool[] { + let numBits = integerBits + fractionalBits; + let sign = value < 0.0; + + mutable result = [false, size = numBits]; + mutable rescaledConstant = PowD(2.0, IntAsDouble(fractionalBits)) * AbsD(value) + 0.5; + mutable keepAdding = sign; + + for idx in 0..numBits - 1 { + let intConstant = Floor(rescaledConstant); + set rescaledConstant = rescaledConstant / 2.0; + mutable currentBit = (intConstant &&& 1) == (sign ? 0 | 1); + if keepAdding { + set keepAdding = currentBit; + set currentBit = not currentBit; + } + if currentBit { + set result w/= idx <- true; + } + } + + return result; + } + /// # 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) + /// Assumed number of integer bits (including the sign bit). /// ## bits - /// Bit-string representation of approximated number - internal function BoolArrayAsFixedPoint(integerBits : Int, bits : Bool[]) : Double { + /// Bit-string representation of approximated number. + 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)); } + /// # Summary + /// Discretizes a double value as a fixed-point approximation and returns its value as a double. + /// + /// # Input + /// ## integerBits + /// Assumed number of integer bits (including the sign bit). + /// ## fractionalBits + /// Assumed number of fractional bits. + /// ## value + /// Value to be approximated. + function DoubleAsFixedPoint(integerBits : Int, fractionalBits : Int, value : Double) : Double { + return BoolArrayAsFixedPoint(integerBits, FixedPointAsBoolArray(integerBits, fractionalBits, value)); + } + } diff --git a/Numerics/src/FixedPoint/Init.qs b/Numerics/src/FixedPoint/Init.qs index 0f4ec690ad5..e8fb63fbebb 100644 --- a/Numerics/src/FixedPoint/Init.qs +++ b/Numerics/src/FixedPoint/Init.qs @@ -2,6 +2,7 @@ // Licensed under the MIT License. namespace Microsoft.Quantum.Arithmetic { + open Microsoft.Quantum.Canon; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math; @@ -16,28 +17,7 @@ namespace Microsoft.Quantum.Arithmetic { /// Fixed-point number (of type FixedPoint) to initialize. operation PrepareFxP(constant : Double, fp : FixedPoint) : Unit is Adj + Ctl { - // NB: We can't omit the body (...) declaration here, as the `set` - // statements below prevent automatic adjoint generation. - body (...) { - let n = Length(fp::Register); - let sign = constant < 0.; - mutable rescaledConstant = PowD(2., IntAsDouble(n - fp::IntegerBits)) * AbsD(constant) + 0.5; - mutable keepAdding = sign; - for i in 0..n - 1 { - let intConstant = Floor(rescaledConstant); - set rescaledConstant = 0.5 * rescaledConstant; - mutable currentBit = (intConstant &&& 1) == (sign ? 0 | 1); - if keepAdding { - set keepAdding = currentBit; - set currentBit = not currentBit; - } - if currentBit { - X(fp::Register[i]); - } - } - } - controlled auto; - adjoint self; - adjoint controlled auto; + let bits = FixedPointAsBoolArray(fp::IntegerBits, Length(fp::Register) - fp::IntegerBits, constant); + ApplyPauliFromBitString(PauliX, true, bits, fp::Register); } -} \ No newline at end of file +}