Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port signed integer math to modern QDK #1841

Merged
merged 16 commits into from
Aug 22, 2024
2 changes: 2 additions & 0 deletions library/signed/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Signed
The `signed` library defines signed quantum integer primitives and operations.
21 changes: 21 additions & 0 deletions library/signed/qsharp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"Unstable": {
"github": {
"owner": "Microsoft",
"repo": "qsharp",
"ref": "d1fb2a1",
"path": "library/unstable"
}
}
},
"files": [
"src/Comparison.qs",
"src/Measurement.qs",
"src/Operations.qs",
"src/Tests.qs",
"src/Utils.qs"
]
}
50 changes: 50 additions & 0 deletions library/signed/src/Comparison.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import Std.Arrays.Tail, Std.Arrays.Zipped, Std.Arrays.Most, Std.Arrays.Rest;
import Std.Diagnostics.Fact;
import Utils.ApplyCCNOTChain;

/// # Summary
/// Wrapper for signed integer comparison: `result = xs > ys`.
///
/// # Input
/// ## xs
/// First $n$-bit number
/// ## ys
/// Second $n$-bit number
/// ## result
/// Will be flipped if $xs > ys$
operation CompareGTSI(xs : Qubit[], ys : Qubit[], result : Qubit) : Unit is Adj + Ctl {
sezna marked this conversation as resolved.
Show resolved Hide resolved
use tmp = Qubit();
within {
CNOT(Tail(xs), tmp);
CNOT(Tail(ys), tmp);
} apply {
X(tmp);
Controlled CompareGTI([tmp], (xs, ys, result));
X(tmp);
CCNOT(tmp, Tail(ys), result);
}
}


/// # Summary
/// Wrapper for integer comparison: `result = x > y`.
///
/// # Input
/// ## xs
/// First $n$-bit number
/// ## ys
/// Second $n$-bit number
/// ## result
/// Will be flipped if $x > y$
operation CompareGTI(xs : Qubit[], ys : Qubit[], result : Qubit) : Unit is Adj + Ctl {
sezna marked this conversation as resolved.
Show resolved Hide resolved
GreaterThan(xs, ys, result);
}


export
CompareGTSI,
CompareGTI,
GreaterThan;
50 changes: 50 additions & 0 deletions library/signed/src/Measurement.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import Std.Diagnostics.Fact;
import Operations.Invert2sSI;

/// # Summary
/// Measures a signed integer of a given width.
/// If the width is 4, the qubit register will be measured as a 4-bit signed integer.
/// This means that bit n is the sign bit, and bits n-1 to 0 are the integer value.
/// If fewer than `width` qubits are provided, the remaining bits are assumed to be 0.
/// For example, if qubit register `[q1, q2, q3]` is passed in, but the width is 5,
/// the integer value will be measured as `[0, 0, q1, q2, q3]`, with the first 0 being
/// the sign bit (positive). This is in contrast to the standard library `MeasureInteger`,
/// which always measures unsigned integers up to and including 63 qubits in width.
/// If the length of the qubit register passed in is greater than the width, this operation
/// will throw an error.
///
/// # Input
/// ## target
/// A qubit register representing the signed integer to be measured.
///
/// ## width
/// The width of the signed integer to be measured.
operation MeasureSignedInteger(target : Qubit[], width : Int) : Int {
sezna marked this conversation as resolved.
Show resolved Hide resolved
let nBits = Length(target);
Fact(nBits <= 64, $"`Length(target)` must be less than or equal to 64, but was {nBits}.");
Fact(nBits <= width, $"`Length(target)` must be less than or equal to `width`, but was {nBits}.");
Fact(nBits > 0, $"`width` must be greater than 0, but was {width}.");

mutable coefficient = 1;
let signBit = MResetZ(target[nBits - 1]);
cesarzc marked this conversation as resolved.
Show resolved Hide resolved
if (signBit == One) {
Operations.Invert2sSI(target);
set coefficient = -1;
}

mutable number = 0;
for i in 0..nBits - 2 {
if (MResetZ(target[i]) == One) {
set number |||= 1 <<< i;
}
}

ResetAll(target);

number * coefficient
}

export MeasureSignedInteger;
Loading
Loading