microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
library/fixed_point/src/Convert.qs
95lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | import Std.Convert.IntAsDouble, Std.Convert.BoolArrayAsInt; |
| 5 | import Std.Math.AbsD, Std.Math.Floor; |
| 6 | import Std.Arrays.Most, Std.Arrays.Tail; |
| 7 | |
| 8 | /// # Summary |
| 9 | /// Computes fixed-point approximation for a double and returns it as `Bool` array. |
| 10 | /// |
| 11 | /// # Input |
| 12 | /// ## integerBits |
| 13 | /// Assumed number of integer bits (including the sign bit). |
| 14 | /// ## fractionalBits |
| 15 | /// Assumed number of fractional bits. |
| 16 | /// ## value |
| 17 | /// Value to be approximated. |
| 18 | /// |
| 19 | /// # Example |
| 20 | /// Note that the first element in the Boolean array is the least-significant bit. |
| 21 | /// ```qsharp |
| 22 | /// let bits = FixedPointAsBoolArray(2, 2, 1.25); // bits = [true, false, true, false] |
| 23 | /// let bits = FixedPointAsBoolArray(2, 2, 1.3); // bits = [true, false, true, false], approximated |
| 24 | /// let bits = FixedPointAsBoolArray(2, 2, -1.75); // bits = [true, false, false, true], two's complement |
| 25 | /// ``` |
| 26 | function FixedPointAsBoolArray(integerBits : Int, fractionalBits : Int, value : Double) : Bool[] { |
| 27 | let numBits = integerBits + fractionalBits; |
| 28 | let sign = value < 0.0; |
| 29 | |
| 30 | mutable result = [false, size = numBits]; |
| 31 | mutable rescaledConstant = 2.0^IntAsDouble(fractionalBits) * AbsD(value) + 0.5; |
| 32 | mutable keepAdding = sign; |
| 33 | |
| 34 | for idx in 0..numBits - 1 { |
| 35 | let intConstant = Floor(rescaledConstant); |
| 36 | set rescaledConstant = rescaledConstant / 2.0; |
| 37 | mutable currentBit = (intConstant &&& 1) == (sign ? 0 | 1); |
| 38 | if keepAdding { |
| 39 | set keepAdding = currentBit; |
| 40 | set currentBit = not currentBit; |
| 41 | } |
| 42 | if currentBit { |
| 43 | set result w/= idx <- true; |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | return result; |
| 48 | } |
| 49 | |
| 50 | /// # Summary |
| 51 | /// Returns the double value of a fixed-point approximation from of a `Bool` array. |
| 52 | /// |
| 53 | /// # Input |
| 54 | /// ## integerBits |
| 55 | /// Assumed number of integer bits (including the sign bit). |
| 56 | /// ## bits |
| 57 | /// Bit-string representation of approximated number. |
| 58 | /// |
| 59 | /// # Example |
| 60 | /// Note that the first element in the Boolean array is the least-significant bit. |
| 61 | /// ```qsharp |
| 62 | /// let value = BoolArrayAsFixedPoint(2, [true, false, true, false]); // value = 1.25 |
| 63 | /// let value = BoolArrayAsFixedPoint(2, [true, false, false, true]); // value = -1.75 |
| 64 | /// ``` |
| 65 | |
| 66 | function BoolArrayAsFixedPoint(integerBits : Int, bits : Bool[]) : Double { |
| 67 | let numBits = Length(bits); |
| 68 | let intPart = (Tail(bits) ? -(1 <<< (numBits - 1)) | 0) + BoolArrayAsInt(Most(bits)); |
| 69 | return IntAsDouble(intPart) / (2.0^IntAsDouble(numBits - integerBits)); |
| 70 | } |
| 71 | |
| 72 | /// # Summary |
| 73 | /// Discretizes a double value as a fixed-point approximation and returns its value as a double. |
| 74 | /// |
| 75 | /// # Input |
| 76 | /// ## integerBits |
| 77 | /// Assumed number of integer bits (including the sign bit). |
| 78 | /// ## fractionalBits |
| 79 | /// Assumed number of fractional bits. |
| 80 | /// ## value |
| 81 | /// Value to be approximated. |
| 82 | /// |
| 83 | /// # Example |
| 84 | /// ```qsharp |
| 85 | /// let value = DoubleAsFixedPoint(2, 2, 1.3); // value = 1.25 |
| 86 | /// let value = DoubleAsFixedPoint(2, 2, 0.8); // value = 0.75 |
| 87 | /// ``` |
| 88 | function DoubleAsFixedPoint(integerBits : Int, fractionalBits : Int, value : Double) : Double { |
| 89 | return BoolArrayAsFixedPoint(integerBits, FixedPointAsBoolArray(integerBits, fractionalBits, value)); |
| 90 | } |
| 91 | |
| 92 | export |
| 93 | FixedPointAsBoolArray, |
| 94 | BoolArrayAsFixedPoint, |
| 95 | DoubleAsFixedPoint; |