microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
8a151f109cece83aeea78e74d62cd6f25e7996a3

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

library/fixed_point/src/Operations.qs

168lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4import Types.FixedPoint;
5import Init.PrepareFxP;
6import Operations.AddFxP;
7import Signed.Operations.Invert2sSI, Signed.Operations.MultiplySI, Signed.Operations.SquareSI;
8import Facts.AssertPointPositionsIdenticalFxP;
9import Std.Arrays.Zipped;
10import Std.Arithmetic.RippleCarryTTKIncByLE;
11
12/// # Summary
13/// Adds a classical constant to a quantum fixed-point number.
14///
15/// # Input
16/// ## constant
17/// Constant to add to the quantum fixed-point number.
18/// ## fp
19/// Fixed-point number to which the constant will
20/// be added.
21@Config(Unrestricted)
22operation AddConstantFxP(constant : Double, fp : FixedPoint) : Unit is Adj + Ctl {
23 let n = Length(fp::Register);
24 use ys = Qubit[n];
25 let tmpFp = FixedPoint(fp::IntegerBits, ys);
26 within {
27 PrepareFxP(constant, tmpFp);
28 } apply {
29 AddFxP(tmpFp, fp);
30 }
31}
32
33/// # Summary
34/// Adds two fixed-point numbers stored in quantum registers.
35///
36/// # Description
37/// Given two fixed-point registers respectively in states $\ket{f_1}$ and $\ket{f_2}$,
38/// performs the operation $\ket{f_1} \ket{f_2} \mapsto \ket{f_1} \ket{f_1 + f_2}$.
39///
40/// # Input
41/// ## fp1
42/// First fixed-point number
43/// ## fp2
44/// Second fixed-point number, will be updated to contain the sum of the
45/// two inputs.
46///
47/// # Remarks
48/// The current implementation requires the two fixed-point numbers
49/// to have the same point position counting from the least-significant
50/// bit, i.e., $n_i$ and $p_i$ must be equal.
51@Config(Unrestricted)
52operation AddFxP(fp1 : FixedPoint, fp2 : FixedPoint) : Unit is Adj + Ctl {
53 AssertPointPositionsIdenticalFxP([fp1, fp2]);
54
55 RippleCarryTTKIncByLE(fp1::Register, fp2::Register);
56}
57
58/// # Summary
59/// Computes the additive inverse of `fp`.
60///
61/// # Input
62/// ## fp
63/// Fixed-point number to invert.
64///
65/// # Remarks
66/// Numerical inaccuracies may occur depending on the
67/// bit-precision of the fixed-point number.
68@Config(Unrestricted)
69operation InvertFxP(fp : FixedPoint) : Unit is Adj + Ctl {
70 let (_, reg) = fp!;
71 Invert2sSI(reg);
72}
73
74/// # Summary
75/// Computes `minuend - subtrahend` and stores the difference in `minuend`.
76///
77/// # Input
78/// ## subtrahend
79/// The subtrahend of the subtraction - the number to be subtracted.
80/// ## minuend
81/// The minuend of the subtraction - the number from which the other is subtracted.
82///
83/// # Remarks
84/// Computes the difference by inverting `subtrahend` before and after adding
85/// it to `minuend`. Notice that `minuend`, the first argument is updated.
86@Config(Unrestricted)
87operation SubtractFxP(minuend : FixedPoint, subtrahend : FixedPoint) : Unit is Adj + Ctl {
88 within {
89 InvertFxP(subtrahend);
90 } apply {
91 AddFxP(subtrahend, minuend);
92 }
93}
94
95
96/// # Summary
97/// Multiplies two fixed-point numbers in quantum registers.
98///
99/// # Input
100/// ## fp1
101/// First fixed-point number.
102/// ## fp2
103/// Second fixed-point number.
104/// ## result
105/// Result fixed-point number, must be in state $\ket{0}$ initially.
106///
107/// # Remarks
108/// The current implementation requires the three fixed-point numbers
109/// to have the same point position and the same number of qubits.
110@Config(Unrestricted)
111operation MultiplyFxP(fp1 : FixedPoint, fp2 : FixedPoint, result : FixedPoint) : Unit is Adj {
112
113 body (...) {
114 Controlled MultiplyFxP([], (fp1, fp2, result));
115 }
116 controlled (controls, ...) {
117 Facts.AssertFormatsAreIdenticalFxP([fp1, fp2, result]);
118 let n = Length(fp1::Register);
119
120 use tmpResult = Qubit[2 * n];
121 let xsInt = ((fp1::Register));
122 let ysInt = ((fp2::Register));
123 let tmpResultInt = tmpResult;
124
125 within {
126 MultiplySI(xsInt, ysInt, tmpResultInt);
127 } apply {
128 Controlled ApplyToEachCA(controls, (CNOT, Zipped(tmpResult[n - fp1::IntegerBits..2 * n - fp1::IntegerBits - 1], result::Register)));
129 }
130 }
131}
132
133/// # Summary
134/// Squares a fixed-point number.
135///
136/// # Input
137/// ## fp
138/// Fixed-point number.
139/// ## result
140/// Result fixed-point number,
141/// must be in state $\ket{0}$ initially.
142@Config(Unrestricted)
143operation SquareFxP(fp : FixedPoint, result : FixedPoint) : Unit is Adj {
144 body (...) {
145 Controlled SquareFxP([], (fp, result));
146 }
147 controlled (controls, ...) {
148 Facts.AssertFormatsAreIdenticalFxP([fp, result]);
149 let n = Length(fp::Register);
150
151 use tmpResult = Qubit[2 * n];
152 let xsInt = fp::Register;
153 let tmpResultInt = tmpResult;
154 within {
155 SquareSI(xsInt, tmpResultInt);
156 } apply {
157 Controlled ApplyToEachCA(controls, (CNOT, Zipped(tmpResult[n - fp::IntegerBits..2 * n - fp::IntegerBits - 1], result::Register)));
158 }
159 }
160}
161
162export
163 AddConstantFxP,
164 AddFxP,
165 InvertFxP,
166 SubtractFxP,
167 MultiplyFxP,
168 SquareFxP;
169