// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. import Std.Diagnostics.Fact; import Operations.Invert2sSI; import Measurement.MeasureSignedInteger; @Test() operation MeasureSignedIntTests() : Unit { let testCases = [ ("0b0001 == 1", 4, (qs) => X(qs[0]), (qs) => MeasureSignedInteger(qs, 6), 1), ("0b1111 == -1", 4, (qs) => { X(qs[0]); X(qs[1]); X(qs[2]); X(qs[3]); }, (qs) => MeasureSignedInteger(qs, 4), -1), ("0b01000 == 8", 5, (qs) => X(qs[3]), (qs) => MeasureSignedInteger(qs, 5), 8), ("0b11110 == -2", 5, (qs) => { X(qs[1]); X(qs[2]); X(qs[3]); X(qs[4]); }, (qs) => MeasureSignedInteger(qs, 5), -2), ("0b11000 == -8", 5, (qs) => { X(qs[3]); X(qs[4]); }, (qs) => MeasureSignedInteger(qs, 5), -8) ]; Fact(Qtest.Operations.CheckAllTestCases(testCases), "SignedInt tests failed"); } @Test() operation SignedOpTests() : Unit { use a = Qubit[32]; use b = Qubit[32]; use c = Qubit[64]; // 0b11111110 (-2 in twos complement) * 0b00000001 == 0b11111110 (-2) X(a[1]); Operations.Invert2sSI(a); X(b[0]); TestSignedIntOp(Operations.MultiplySI, a, b, c, -2); // 0b11111110 (-2 in twos complement) * 0b11111111 (-1 in twos complement) == 0b00000010 (2) X(a[1]); Operations.Invert2sSI(a); X(b[0]); Operations.Invert2sSI(b); TestSignedIntOp(Operations.MultiplySI, a, b, c, 2); // 0b11111110 (-2 in twos complement) squared is 0b00000100 (4) X(a[1]); Operations.Invert2sSI(a); TestSignedIntOp((a, b, _) => Operations.SquareSI(a, c), a, b, c, 4); } @Test() operation UnsignedOpTests() : Unit { use a = Qubit[2]; use b = Qubit[2]; use c = Qubit[4]; // 0b10 * 0b01 == 0b10 (1 * 2 = 2) X(a[0]); X(b[1]); TestIntOp(Operations.MultiplyI, a, b, c, 2); // 0b01 * 0b10 == 0b10 (1 * 2 = 2) X(a[1]); X(b[0]); TestIntOp(Operations.MultiplyI, a, b, c, 2); // 0b11 * 0b11 == 0b1001 (3 * 3 = 9) X(a[0]); X(b[0]); X(a[1]); X(b[1]); TestIntOp(Operations.MultiplyI, a, b, c, 9); use a = Qubit[8]; use b = Qubit[8]; use c = Qubit[16]; // 0b00001010 * 0b00001011 == 0b01100100 (10 * 11 = 110) X(a[1]); X(a[3]); X(b[1]); X(b[3]); X(b[0]); TestIntOp(Operations.MultiplyI, a, b, c, 110); // 0b00001010 ^ 2 = 0b01100100 (10 ^ 2 = 100) X(a[1]); X(a[3]); TestIntOp((a, b, _) => Operations.SquareI(a, c), a, b, c, 100); // 0b00001010 / 0b00000010 == 0b00000101 (10 / 2 = 5) X(a[1]); X(a[3]); X(b[1]); // need smaller result register for div, mod, etc use d = Qubit[8]; TestIntOp(Operations.DivideI, a, b, d, 5); } operation TestIntOp(op : (Qubit[], Qubit[], Qubit[]) => Unit, a : Qubit[], b : Qubit[], c : Qubit[], expect : Int) : Unit { op(a, b, c); let res = MeasureInteger(c); Fact(res == expect, $"Expected {expect}, got {res}"); ResetAll(a + b + c); } operation TestSignedIntOp(op : (Qubit[], Qubit[], Qubit[]) => Unit, a : Qubit[], b : Qubit[], c : Qubit[], expect : Int) : Unit { op(a, b, c); let res = MeasureSignedInteger(c, 64); Fact(res == expect, $"Expected {expect}, got {res}"); ResetAll(a + b + c); }