diff --git a/Chemistry/tests/ChemistryTests/UnitaryCoupledClusterTests.qs b/Chemistry/tests/ChemistryTests/UnitaryCoupledClusterTests.qs index 77cb68926d3..753ed7b85d8 100644 --- a/Chemistry/tests/ChemistryTests/UnitaryCoupledClusterTests.qs +++ b/Chemistry/tests/ChemistryTests/UnitaryCoupledClusterTests.qs @@ -69,9 +69,9 @@ namespace Microsoft.Quantum.Chemistry.Tests { let s = sortedIndices[3]; Fact(p>> b; + /// let c = RightShiftedI(a, b); + /// ``` + function RightShiftedI(value : Int, amount : Int) : Int { + return value >>> amount; + } + + /// # Summary + /// Shifts the bitwise representation of a number right by a given number of + /// bits. + /// + /// # Input + /// ## value + /// The number whose bitwise representation is to be shifted to the right + /// (less significant). + /// ## amount + /// The number of bits by which `value` is to be shifted to the right. + /// + /// # Output + /// The value of `value`, shifted right by `amount` bits. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let c = a >>> b; + /// let c = RightShiftedL(a, b); + /// ``` + function RightShiftedL(value : BigInt, amount : Int) : BigInt { + return value >>> amount; + } +} diff --git a/Standard/src/Bitwise/Properties/NamespaceInfo.qs b/Standard/src/Bitwise/Properties/NamespaceInfo.qs new file mode 100644 index 00000000000..bf31ede816b --- /dev/null +++ b/Standard/src/Bitwise/Properties/NamespaceInfo.qs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/// # Summary +/// This namespace contains functions for acting on the bitwise representation of +/// classical data types. +namespace Microsoft.Quantum.Bitwise { } diff --git a/Standard/src/Diagnostics/Deprecated.qs b/Standard/src/Diagnostics/Deprecated.qs index 38cc1cd60e0..d31a30303d5 100644 --- a/Standard/src/Diagnostics/Deprecated.qs +++ b/Standard/src/Diagnostics/Deprecated.qs @@ -14,10 +14,17 @@ namespace Microsoft.Quantum.Canon { } /// # Deprecated - /// Please use @"Microsoft.Quantum.Diagnostics.NearEqualityFact" instead. + /// Please use @"Microsoft.Quantum.Diagnostics.NearEqualityFactD" instead. function AssertAlmostEqual(actual : Double, expected : Double) : Unit { - _Renamed("Microsoft.Quantum.Canon.AssertAlmostEqual", "Microsoft.Quantum.Diagnostics.NearEqualityFact"); - NearEqualityFact(actual, expected); + _Renamed("Microsoft.Quantum.Canon.AssertAlmostEqual", "Microsoft.Quantum.Diagnostics.NearEqualityFactD"); + NearEqualityFactD(actual, expected); + } + + /// # Deprecated + /// Please use @"Microsoft.Quantum.Diagnostics.NearEqualityFactD" instead. + function NearEqualityFact(actual : Double, expected : Double) : Unit { + _Renamed("Microsoft.Quantum.Diagnostics.NearEqualityFact", "Microsoft.Quantum.Diagnostics.NearEqualityFactD"); + NearEqualityFactD(actual, expected); } /// # Deprecated diff --git a/Standard/src/Diagnostics/Facts.qs b/Standard/src/Diagnostics/Facts.qs index 992bf856a7b..33224a98d85 100644 --- a/Standard/src/Diagnostics/Facts.qs +++ b/Standard/src/Diagnostics/Facts.qs @@ -3,7 +3,15 @@ namespace Microsoft.Quantum.Diagnostics { open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Math; open Microsoft.Quantum.Arrays; + open Microsoft.Quantum.Logical; + + /// # Summary + /// Private function used to generate meaningful error messages. + function _FormattedExpectation<'T>(actual : 'T, expected : 'T) : String { + return $"Expected: '{expected}'. Actual: '{actual}'"; + } /// # Summary /// Declares that a classical condition is true. @@ -33,12 +41,12 @@ namespace Microsoft.Quantum.Diagnostics { function EqualityWithinToleranceFact(actual : Double, expected : Double, tolerance : Double) : Unit { let delta = actual - expected; if (delta > tolerance or delta < -tolerance) { - fail $"Fact was false. Expected: '{expected}'. Actual: '{actual}'"; + fail _FormattedExpectation(actual, expected); } } /// # Summary - /// Asserts that a classical floating point variable has the expected value up to a + /// Asserts that a classical floating point value has the expected value up to a /// small tolerance of 1e-10. /// /// # Input @@ -50,8 +58,42 @@ namespace Microsoft.Quantum.Diagnostics { /// # Remarks /// This is equivalent to with /// hardcoded tolerance of $10^{-10}$. - function NearEqualityFact(actual : Double, expected : Double) : Unit { - EqualityWithinToleranceFact(actual, expected, 1E-10); + function NearEqualityFactD(actual : Double, expected : Double) : Unit { + EqualityWithinToleranceFact(actual, expected, 1e-10); + } + + /// # Summary + /// Asserts that a classical complex number has the expected value up to a + /// small tolerance of 1e-10. + /// + /// # Input + /// ## actual + /// The number to be checked. + /// ## expected + /// The expected value. + function NearEqualityFactC(actual : Complex, expected : Complex) : Unit { + // Don't reduce to the base case of Fact, since we need to check two + // conditions. + let ((reA, imA), (reE, imE)) = (actual!, expected!); + if (AbsD(reA - reE) >= 1e-10 or AbsD(imA - imE) >= 1e-10) { + fail _FormattedExpectation(actual, expected); + } + } + + /// # Summary + /// Asserts that a classical complex number has the expected value up to a + /// small tolerance of 1e-10. + /// + /// # Input + /// ## actual + /// The number to be checked. + /// ## expected + /// The expected value. + function NearEqualityFactCP(actual : ComplexPolar, expected : ComplexPolar) : Unit { + return NearEqualityFactC( + ComplexPolarAsComplex(actual), + ComplexPolarAsComplex(expected) + ); } /// # Summary @@ -65,12 +107,8 @@ namespace Microsoft.Quantum.Diagnostics { /// /// ## message /// Failure message string to be used when the assertion is triggered. - function EqualityFactI(actual : Int, expected : Int, message : String) : Unit - { - if (actual != expected) - { - fail message; - } + function EqualityFactI(actual : Int, expected : Int, message : String) : Unit { + Fact(actual == expected, $"{actual} ≠ {expected}: {message}"); } /// # Summary @@ -84,12 +122,8 @@ namespace Microsoft.Quantum.Diagnostics { /// /// ## message /// Failure message string to be used when the assertion is triggered. - function EqualityFactL(actual : BigInt, expected : BigInt, message : String) : Unit - { - if (actual != expected) - { - fail message; - } + function EqualityFactL(actual : BigInt, expected : BigInt, message : String) : Unit { + Fact(actual == expected, $"{actual} ≠ {expected}: {message}"); } /// # Summary @@ -104,12 +138,8 @@ namespace Microsoft.Quantum.Diagnostics { /// /// ## message /// Failure message string to be used when the assertion is triggered. - function EqualityFactB(actual : Bool, expected : Bool, message : String) : Unit - { - if (actual != expected) - { - fail message; - } + function EqualityFactB(actual : Bool, expected : Bool, message : String) : Unit { + Fact(actual == expected, $"{actual} ≠ {expected}: {message}"); } /// # Summary @@ -125,10 +155,39 @@ namespace Microsoft.Quantum.Diagnostics { /// ## message /// Failure message string to be used when the assertion is triggered. function EqualityFactR (actual : Result, expected : Result, message : String) : Unit { - if (actual != expected) - { - fail message; - } + Fact(actual == expected, $"{actual} ≠ {expected}: {message}"); + } + + /// # Summary + /// Asserts that a complex number has the expected value. + /// + /// # Input + /// ## actual + /// The value to be checked. + /// + /// ## expected + /// The expected value. + /// + /// ## message + /// Failure message string to be used when the assertion is triggered. + function EqualityFactC(actual : Complex, expected : Complex, message : String) : Unit { + Fact(EqualC(actual, expected), $"{actual} ≠ {expected}: {message}"); + } + + /// # Summary + /// Asserts that a complex number has the expected value. + /// + /// # Input + /// ## actual + /// The value to be checked. + /// + /// ## expected + /// The expected value. + /// + /// ## message + /// Failure message string to be used when the assertion is triggered. + function EqualityFactCP(actual : ComplexPolar, expected : ComplexPolar, message : String) : Unit { + Fact(EqualCP(actual, expected), $"{actual} ≠ {expected}: {message}"); } /// # Summary diff --git a/Standard/src/Logical/BooleanOperators.qs b/Standard/src/Logical/BooleanOperators.qs new file mode 100644 index 00000000000..a960f7898a7 --- /dev/null +++ b/Standard/src/Logical/BooleanOperators.qs @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Logical { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Canon; + + /// # Summary + /// Returns the Boolean negation of a value. + /// + /// # Input + /// ## value + /// The value to be negated. + /// + /// # Output + /// `true` if and only if `value` is `false`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let x = not value; + /// let x = Not(value); + /// ``` + function Not(value : Bool) : Bool { + return not value; + } + + /// # Summary + /// Returns the Boolean conjunction of two values. + /// + /// # Input + /// ## a + /// The first value to be considered. + /// ## b + /// The second value to be considered. + /// + /// # Output + /// `true` if and only if `a` and `b` are both `true`. + /// + /// # Remarks + /// Unlike the `and` operator, this function does not short-circuit, such that + /// both inputs are fully evaluated. + /// + /// Up to short-circuiting behavior, the following are equivalent: + /// ```Q# + /// let x = a and b; + /// let x = And(a, b); + /// ``` + function And(a : Bool, b : Bool) : Bool { + return a and b; + } + + /// # Summary + /// Returns the Boolean disjunction of two values. + /// + /// # Input + /// ## a + /// The first value to be considered. + /// ## b + /// The second value to be considered. + /// + /// # Output + /// `true` if and only if either `a` or `b` are `true`. + /// + /// # Remarks + /// Unlike the `or` operator, this function does not short-circuit, such that + /// both inputs are fully evaluated. + /// + /// Up to short-circuiting behavior, the following are equivalent: + /// ```Q# + /// let x = a or b; + /// let x = Or(a, b); + /// ``` + function Or(a : Bool, b : Bool) : Bool { + return a or b; + } + + /// # Summary + /// Returns the Boolean exclusive disjunction of two values. + /// + /// # Input + /// ## a + /// The first value to be considered. + /// ## b + /// The second value to be considered. + /// + /// # Output + /// `true` if and only if exactly one of `a` and `b` is `true`. + function Xor(a : Bool, b : Bool) : Bool { + return (a or b) and ((not a) or (not b)); + } + + /// # Summary + /// Returns one of two values, depending on the value of a Boolean condition. + /// + /// # Input + /// ## condition + /// A condition used to control which input is returned. + /// ## ifTrue + /// The value to be returned when `condition` is `true`. + /// ## ifFalse + /// The value to be returned when `condition` is `false`. + /// + /// # Output + /// `ifTrue` if `condition` is `true`, and `ifFalse` otherwise. + /// + /// # Remarks + /// Unlike the `?|` operator, this function does not short-circuit, such that + /// both inputs are fully evaluated. + /// + /// Up to short-circuiting behavior, the following are equivalent: + /// ```Q# + /// let x = condition ? ifTrue | ifFalse; + /// let x = Conditioned(condition, ifTrue, ifFalse); + /// ``` + function Conditioned<'T>(condition : Bool, ifTrue : 'T, ifFalse : 'T) : 'T { + return condition ? ifTrue | ifFalse; + } + +} diff --git a/Standard/src/Logical/Predicates.qs b/Standard/src/Logical/Predicates.qs new file mode 100644 index 00000000000..fb5a8fff4db --- /dev/null +++ b/Standard/src/Logical/Predicates.qs @@ -0,0 +1,558 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Logical { + open Microsoft.Quantum.Math; + + /// # Summary + /// Returns true if and only if two inputs are equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a == b; + /// let cond = EqualI(a, b); + /// ``` + function EqualI(a : Int, b : Int) : Bool { + return a == b; + } + + /// # Summary + /// Returns true if and only if two inputs are equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a == b; + /// let cond = EqualL(a, b); + /// ``` + function EqualL(a : BigInt, b : BigInt) : Bool { + return a == b; + } + + /// # Summary + /// Returns true if and only if two inputs are equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a == b; + /// let cond = EqualD(a, b); + /// ``` + function EqualD(a : Double, b : Double) : Bool { + return a == b; + } + + /// # Summary + /// Returns true if and only if two inputs are equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a == b; + /// let cond = EqualR(a, b); + /// ``` + function EqualR(a : Result, b : Result) : Bool { + return a == b; + } + + /// # Summary + /// Returns true if and only if two inputs are equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a == b; + /// let cond = EqualB(a, b); + /// ``` + function EqualB(a : Bool, b : Bool) : Bool { + return a == b; + } + + /// # Summary + /// Returns true if and only if two inputs are equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is equal to `b`. + function EqualC(a : Complex, b : Complex) : Bool { + let ((reA, imA), (reB, imB)) = (a!, b!); + return reA == reB and imA == imB; + } + + /// # Summary + /// Returns true if and only if two inputs are equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is equal to `b`. + function EqualCP(a : ComplexPolar, b : ComplexPolar) : Bool { + return EqualC(ComplexPolarAsComplex(a), ComplexPolarAsComplex(b)); + } + + /// # Summary + /// Returns true if and only if two inputs are not equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is not equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a != b; + /// let cond = NotEqualI(a, b); + /// ``` + function NotEqualI(a : Int, b : Int) : Bool { + return a != b; + } + + /// # Summary + /// Returns true if and only if two inputs are not equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is not equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a != b; + /// let cond = NotEqualL(a, b); + /// ``` + function NotEqualL(a : BigInt, b : BigInt) : Bool { + return a != b; + } + + /// # Summary + /// Returns true if and only if two inputs are not equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is not equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a != b; + /// let cond = NotEqualD(a, b); + /// ``` + function NotEqualD(a : Double, b : Double) : Bool { + return a != b; + } + + /// # Summary + /// Returns true if and only if two inputs are not equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is not equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a != b; + /// let cond = NotEqualR(a, b); + /// ``` + function NotEqualR(a : Result, b : Result) : Bool { + return a != b; + } + + /// # Summary + /// Returns true if and only if two inputs are not equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is not equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a != b; + /// let cond = NotEqualB(a, b); + /// ``` + function NotEqualB(a : Bool, b : Bool) : Bool { + return a != b; + } + + /// # Summary + /// Returns true if and only if two inputs are not equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is not equal to `b`. + function NotEqualC(a : Complex, b : Complex) : Bool { + return not EqualC(a, b); + } + + /// # Summary + /// Returns true if and only if two inputs are not equal. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is not equal to `b`. + function NotEqualCP(a : ComplexPolar, b : ComplexPolar) : Bool { + return not EqualCP(a, b); + } + + /// # Summary + /// Returns true if and only if a number is greater than another number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is strictly greater than `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a > b; + /// let cond = GreaterThanI(a, b); + /// ``` + function GreaterThanI(a : Int, b : Int) : Bool { + return a > b; + } + + /// # Summary + /// Returns true if and only if a number is greater than another number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is strictly greater than `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a > b; + /// let cond = GreaterThanL(a, b); + /// ``` + function GreaterThanL(a : BigInt, b : BigInt) : Bool { + return a > b; + } + + /// # Summary + /// Returns true if and only if a number is greater than another number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is strictly greater than `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a > b; + /// let cond = GreaterThanD(a, b); + /// ``` + function GreaterThanD(a : Double, b : Double) : Bool { + return a > b; + } + + /// # Summary + /// Returns true if and only if a number is greater than or equal to another + /// number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is greater than or is equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a >= b; + /// let cond = GreaterThanOrEqualI(a, b); + /// ``` + function GreaterThanOrEqualI(a : Int, b : Int) : Bool { + return a >= b; + } + + /// # Summary + /// Returns true if and only if a number is greater than or equal to another + /// number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is greater than or is equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a >= b; + /// let cond = GreaterThanOrEqualL(a, b); + /// ``` + function GreaterThanOrEqualL(a : BigInt, b : BigInt) : Bool { + return a >= b; + } + + /// # Summary + /// Returns true if and only if a number is greater than or equal to another + /// number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is greater than or is equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a >= b; + /// let cond = GreaterThanOrEqualD(a, b); + /// ``` + function GreaterThanOrEqualD(a : Double, b : Double) : Bool { + return a >= b; + } + + /// # Summary + /// Returns true if and only if a number is less than another number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is strictly less than `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a < b; + /// let cond = LessThanI(a, b); + /// ``` + function LessThanI(a : Int, b : Int) : Bool { + return a < b; + } + + /// # Summary + /// Returns true if and only if a number is less than another number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is strictly less than `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a < b; + /// let cond = LessThanL(a, b); + /// ``` + function LessThanL(a : BigInt, b : BigInt) : Bool { + return a < b; + } + + /// # Summary + /// Returns true if and only if a number is less than another number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is strictly less than `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a < b; + /// let cond = LessThanD(a, b); + /// ``` + function LessThanD(a : Double, b : Double) : Bool { + return a < b; + } + + /// # Summary + /// Returns true if and only if a number is less than or equal to another + /// number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is less than or equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a <= b; + /// let cond = LessThanOrEqualI(a, b); + /// ``` + function LessThanOrEqualI(a : Int, b : Int) : Bool { + return a <= b; + } + + /// # Summary + /// Returns true if and only if a number is less than or equal to another + /// number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is less than or equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a <= b; + /// let cond = LessThanOrEqualL(a, b); + /// ``` + function LessThanOrEqualL(a : BigInt, b : BigInt) : Bool { + return a <= b; + } + + /// # Summary + /// Returns true if and only if a number is less than or equal to another + /// number. + /// + /// # Input + /// ## a + /// The first value to be compared. + /// ## b + /// The second value to be compared. + /// + /// # Output + /// `true` if and only if `a` is less than or equal to `b`. + /// + /// # Remarks + /// The following are equivalent: + /// ```Q# + /// let cond = a <= b; + /// let cond = LessThanOrEqualD(a, b); + /// ``` + function LessThanOrEqualD(a : Double, b : Double) : Bool { + return a <= b; + } + +} diff --git a/Standard/src/Logical/Properties/NamespaceInfo.qs b/Standard/src/Logical/Properties/NamespaceInfo.qs new file mode 100644 index 00000000000..d6bdd2cc614 --- /dev/null +++ b/Standard/src/Logical/Properties/NamespaceInfo.qs @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/// # Summary +/// Contains functions for working with logical expressions and Boolean logic. +namespace Microsoft.Quantum.Logical { } diff --git a/Standard/src/Math/Complex.qs b/Standard/src/Math/Complex.qs index a3ff13fe307..e1e943350e6 100644 --- a/Standard/src/Math/Complex.qs +++ b/Standard/src/Math/Complex.qs @@ -13,7 +13,7 @@ namespace Microsoft.Quantum.Math { /// `Double` is absolute value $r \ge 0$. /// ## Second Parameter /// `Double` is the phase $t \in \mathbb R$. - newtype ComplexPolar = (Double, Double); + newtype ComplexPolar = (Magnitude: Double, Argument: Double); /// # Summary /// Returns the squared absolute value of a complex number of type @@ -69,8 +69,7 @@ namespace Microsoft.Quantum.Math { /// /// # Output /// Squared absolute value $|c|^2 = r^2$. - function AbsSquaredComplexPolar (input : ComplexPolar) : Double - { + function AbsSquaredComplexPolar (input : ComplexPolar) : Double { let (abs, arg) = input!; return abs * abs; } @@ -86,10 +85,8 @@ namespace Microsoft.Quantum.Math { /// /// # Output /// Absolute value $|c| = r$. - function AbsComplexPolar (input : ComplexPolar) : Double - { - let (abs, arg) = input!; - return abs; + function AbsComplexPolar (input : ComplexPolar) : Double { + return input::Magnitude; } @@ -103,45 +100,224 @@ namespace Microsoft.Quantum.Math { /// /// # Output /// Phase $\text{Arg}[c] = t$. - function ArgComplexPolar (input : ComplexPolar) : Double - { - let (abs, arg) = input!; - return arg; + function ArgComplexPolar (input : ComplexPolar) : Double { + return input::Argument; } - - + /// # Summary - /// Converts a complex number of type `ComplexPolar` to a complex - /// number of type `Complex`. + /// Returns the unary negation of an input. /// /// # Input /// ## input - /// Complex number $c = r e^{i t}$. + /// A value whose negation is to be returned. /// /// # Output - /// Complex number $c = x + i y$. - function ComplexPolarToComplex (input : ComplexPolar) : Complex - { - let (abs, arg) = input!; - return Complex(abs * Cos(arg), abs * Sin(arg)); + /// The unary negation of `input`. + function NegationC(input : Complex) : Complex { + let (re, im) = input!; + return Complex(-re, -im); } - - + /// # Summary - /// Converts a complex number of type `Complex` to a complex - /// number of type `ComplexPolar`. + /// Returns the unary negation of an input. /// /// # Input /// ## input - /// Complex number $c = x + i y$. + /// A value whose negation is to be returned. /// /// # Output - /// Complex number $c = r e^{i t}$. - function ComplexToComplexPolar (input : Complex) : ComplexPolar - { - return ComplexPolar(AbsComplex(input), ArgComplex(input)); + /// The unary negation of `input`. + function NegationCP(input : ComplexPolar) : ComplexPolar { + return ComplexPolar(input::Magnitude, input::Argument + PI()); + } + + /// # Summary + /// Returns the sum of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be summed. + /// ## b + /// The second input $b$ to be summed. + /// + /// # Output + /// The sum $a + b$. + function PlusC(a : Complex, b : Complex) : Complex { + let ((reA, imA), (reB, imB)) = (a!, b!); + return Complex(reA + reB, imA + imB); + } + + /// # Summary + /// Returns the sum of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be summed. + /// ## b + /// The second input $b$ to be summed. + /// + /// # Output + /// The sum $a + b$. + function PlusCP(a : ComplexPolar, b : ComplexPolar) : ComplexPolar { + return ComplexAsComplexPolar( + PlusC( + ComplexPolarAsComplex(a), + ComplexPolarAsComplex(b) + ) + ); + } + + /// # Summary + /// Returns the difference between two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be subtracted. + /// ## b + /// The second input $b$ to be subtracted. + /// + /// # Output + /// The difference $a - b$. + function MinusC(a : Complex, b : Complex) : Complex { + return PlusC(a, NegationC(b)); + } + + /// # Summary + /// Returns the difference between two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be subtracted. + /// ## b + /// The second input $b$ to be subtracted. + /// + /// # Output + /// The difference $a - b$. + function MinusCP(a : ComplexPolar, b : ComplexPolar) : ComplexPolar { + return PlusCP(a, NegationCP(b)); + } + + /// # Summary + /// Returns the product of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be multiplied. + /// ## b + /// The second input $b$ to be multiplied. + /// + /// # Output + /// The product $a \times b$. + function TimesC(a : Complex, b : Complex) : Complex { + let ((reA, imA), (reB, imB)) = (a!, b!); + return Complex( + reA * reB - imA * imB, + reA * imB + imA * reB + ); + } + + /// # Summary + /// Returns the product of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be multiplied. + /// ## b + /// The second input $b$ to be multiplied. + /// + /// # Output + /// The product $a \times b$. + function TimesCP(a : ComplexPolar, b : ComplexPolar) : ComplexPolar { + return ComplexPolar( + a::Magnitude * b::Magnitude, + a::Argument + b::Argument + ); + } + + /// # Summary + /// Private. Since it is easiest to define the power of two complex numbers + /// in cartesian form as returning in polar form, we define that here, then + /// convert as needed. + function _PowC(base_ : Complex, power : Complex) : ComplexPolar { + let ((a, b), (c, d)) = (base_!, power!); + // Re: https://www.wolframalpha.com/input/?i=simplify+re+%28%28a+%2B+b+i%29%5E%28c+%2B+d+i%29%29 + // Im: https://www.wolframalpha.com/input/?i=simplify+im+%28%28a+%2B+b+i%29%5E%28c+%2B+d+i%29%29 + let norm = PNorm(2.0, [a, b]); + let sqNorm = PowD(norm, 2.0); + let baseArg = ArgComplex(base_); + let prefactor = PowD(norm, c) * ExpD(-d * baseArg); + let angle = 0.5 * d * Log(sqNorm) + c * baseArg; + return ComplexPolar( + prefactor, angle + ); + } + + /// # Summary + /// Returns a number raised to a given power. + /// + /// # Input + /// ## base + /// The number $a$ that is to be raised. + /// ## power + /// The power $b$ to which $a$ should be raised. + /// + /// # Output + /// The power $a^b$ + function PowC(base_ : Complex, power : Complex) : Complex { + return ComplexPolarAsComplex( + _PowC(base_, power) + ); + } + + /// # Summary + /// Returns a number raised to a given power. + /// + /// # Input + /// ## base + /// The number $a$ that is to be raised. + /// ## power + /// The power $b$ to which $a$ should be raised. + /// + /// # Output + /// The power $a^b$ + function PowCP(a : ComplexPolar, power : ComplexPolar) : ComplexPolar { + return _PowC( + ComplexPolarAsComplex(a), + ComplexPolarAsComplex(power) + ); + } + + /// # Summary + /// Returns the quotient of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be divided. + /// ## b + /// The second input $b$ to be divided. + /// + /// # Output + /// The quotient $a / b$. + function DividedByC(a : Complex, b : Complex) : Complex { + return TimesC( + a, + PowC(b, Complex(-1.0, 0.0)) + ); } - -} + /// # Summary + /// Returns the quotient of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be divided. + /// ## b + /// The second input $b$ to be divided. + /// + /// # Output + /// The quotient $a / b$. + function DividedByCP(a : ComplexPolar, b : ComplexPolar) : ComplexPolar { + return TimesCP(a, PowCP(b, ComplexPolar(1.0, PI()))); + } +} diff --git a/Standard/src/Math/Convert.qs b/Standard/src/Math/Convert.qs new file mode 100644 index 00000000000..947601cdc75 --- /dev/null +++ b/Standard/src/Math/Convert.qs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Math { + + /// # Summary + /// Converts a complex number of type `ComplexPolar` to a complex + /// number of type `Complex`. + /// + /// # Input + /// ## input + /// Complex number $c = r e^{i t}$. + /// + /// # Output + /// Complex number $c = x + i y$. + function ComplexPolarAsComplex (input : ComplexPolar) : Complex { + return Complex( + input::Magnitude * Cos(input::Argument), + input::Magnitude * Sin(input::Argument) + ); + } + + /// # Summary + /// Converts a complex number of type `Complex` to a complex + /// number of type `ComplexPolar`. + /// + /// # Input + /// ## input + /// Complex number $c = x + i y$. + /// + /// # Output + /// Complex number $c = r e^{i t}$. + function ComplexAsComplexPolar (input : Complex) : ComplexPolar { + return ComplexPolar(AbsComplex(input), ArgComplex(input)); + } + +} diff --git a/Standard/src/Math/Deprecated.qs b/Standard/src/Math/Deprecated.qs index 3adbf0dd608..ca66b91a3cd 100644 --- a/Standard/src/Math/Deprecated.qs +++ b/Standard/src/Math/Deprecated.qs @@ -81,4 +81,24 @@ namespace Microsoft.Quantum.Canon { _Renamed("Microsoft.Quantum.Canon.BitSize", "Microsoft.Quantum.Math.BitSizeI"); return BitSizeI(a); } + } + +namespace Microsoft.Quantum.Math { + open Microsoft.Quantum.Warnings; + + /// # Deprecated. + /// Please use @"microsoft.quantum.math.complexpolarascomplex". + function ComplexPolarToComplex(input : ComplexPolar) : Complex { + _Renamed("Microsoft.Quantum.Math.ComplexPolarToComplex", "Microsoft.Quantum.Math.ComplexPolarAsComplex"); + return ComplexPolarAsComplex(input); + } + + /// # Deprecated. + /// Please use @"microsoft.quantum.math.complexascomplexpolar". + function ComplexToComplexPolar(input : Complex) : ComplexPolar { + _Renamed("Microsoft.Quantum.Math.ComplexToComplexPolar", "Microsoft.Quantum.Math.ComplexAsComplexPolar"); + return ComplexAsComplexPolar(input); + } + +} \ No newline at end of file diff --git a/Standard/src/Math/Operators.qs b/Standard/src/Math/Operators.qs new file mode 100644 index 00000000000..b7393b47a7b --- /dev/null +++ b/Standard/src/Math/Operators.qs @@ -0,0 +1,305 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Math { + + /// # Summary + /// Returns the unary negation of an input. + /// + /// # Input + /// ## input + /// A value whose negation is to be returned. + /// + /// # Output + /// The unary negation of `input`. + function NegationI(input : Int) : Int { + return -input; + } + + /// # Summary + /// Returns the unary negation of an input. + /// + /// # Input + /// ## input + /// A value whose negation is to be returned. + /// + /// # Output + /// The unary negation of `input`. + function NegationD(input : Double) : Double { + return -input; + } + + /// # Summary + /// Returns the unary negation of an input. + /// + /// # Input + /// ## input + /// A value whose negation is to be returned. + /// + /// # Output + /// The unary negation of `input`. + function NegationL(input : BigInt) : BigInt { + return -input; + } + + /// # Summary + /// Returns the sum of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be summed. + /// ## b + /// The second input $b$ to be summed. + /// + /// # Output + /// The sum $a + b$. + function PlusI(a : Int, b : Int) : Int { + return a + b; + } + + /// # Summary + /// Returns the sum of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be summed. + /// ## b + /// The second input $b$ to be summed. + /// + /// # Output + /// The sum $a + b$. + function PlusD(a : Double, b : Double) : Double { + return a + b; + } + + /// # Summary + /// Returns the sum of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be summed. + /// ## b + /// The second input $b$ to be summed. + /// + /// # Output + /// The sum $a + b$. + function PlusL(a : BigInt, b : BigInt) : BigInt { + return a + b; + } + + /// # Summary + /// Returns the sum (concatenation) of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be summed. + /// ## b + /// The second input $b$ to be summed. + /// + /// # Output + /// The sum $a + b$. + /// + /// # Type Parameters + /// ## 'Element + /// The type of each element in each of the two input arrays. + function PlusA<'Element>(a : 'Element[], b : 'Element[]) : 'Element[] { + return a + b; + } + + /// # Summary + /// Returns the difference between two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be subtracted. + /// ## b + /// The second input $b$ to be subtracted. + /// + /// # Output + /// The difference $a - b$. + function MinusI(a : Int, b : Int) : Int { + return a - b; + } + + /// # Summary + /// Returns the difference between two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be subtracted. + /// ## b + /// The second input $b$ to be subtracted. + /// + /// # Output + /// The difference $a - b$. + function MinusD(a : Double, b : Double) : Double { + return a - b; + } + + /// # Summary + /// Returns the difference between two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be subtracted. + /// ## b + /// The second input $b$ to be subtracted. + /// + /// # Output + /// The difference $a - b$. + function MinusL(a : BigInt, b : BigInt) : BigInt { + return a - b; + } + + /// # Summary + /// Returns the product of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be multiplied. + /// ## b + /// The second input $b$ to be multiplied. + /// + /// # Output + /// The product $a \times b$. + function TimesI(a : Int, b : Int) : Int { + return a * b; + } + + /// # Summary + /// Returns the product of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be multiplied. + /// ## b + /// The second input $b$ to be multiplied. + /// + /// # Output + /// The product $a \times b$. + function TimesD(a : Double, b : Double) : Double { + return a * b; + } + + /// # Summary + /// Returns the product of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be multiplied. + /// ## b + /// The second input $b$ to be multiplied. + /// + /// # Output + /// The product $a \times b$. + function TimesL(a : BigInt, b : BigInt) : BigInt { + return a * b; + } + + /// # Summary + /// Returns the quotient of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be divided. + /// ## b + /// The second input $b$ to be divided. + /// + /// # Output + /// The quotient $a / b$. + function DividedByI(a : Int, b : Int) : Int { + return a / b; + } + + /// # Summary + /// Returns the quotient of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be divided. + /// ## b + /// The second input $b$ to be divided. + /// + /// # Output + /// The quotient $a / b$. + function DividedByD(a : Double, b : Double) : Double { + return a / b; + } + + /// # Summary + /// Returns the quotient of two inputs. + /// + /// # Input + /// ## a + /// The first input $a$ to be divided. + /// ## b + /// The second input $b$ to be divided. + /// + /// # Output + /// The quotient $a / b$. + function DividedByL(a : BigInt, b : BigInt) : BigInt { + return a / b; + } + + + /// # Summary + /// Returns the modulus of a number with respect to another number. + /// + /// # Input + /// ## a + /// The input $a$ whose modulus is to be returned. + /// ## b + /// The number with respect to which the modulus of $a$ is to be returned. + /// + /// # Output + /// The modulus $a \bmod b$. + function ModI(a : Int, b : Int) : Int { + return a % b; + } + + /// # Summary + /// Returns the modulus of a number with respect to another number. + /// + /// # Input + /// ## a + /// The input $a$ whose modulus is to be returned. + /// ## b + /// The number with respect to which the modulus of $a$ is to be returned. + /// + /// # Output + /// The modulus $a \bmod b$. + function ModL(a : BigInt, b : BigInt) : BigInt { + return a % b; + } + + /// # Summary + /// Returns a number raised to a given power. + /// + /// # Input + /// ## a + /// The number $a$ that is to be raised. + /// ## power + /// The power $b$ to which $a$ should be raised. + /// + /// # Output + /// The power $a^b$ + function PowI(a : Int, power : Int) : Int { + return a ^ power; + } + + /// # Summary + /// Returns a number raised to a given power. + /// + /// # Input + /// ## a + /// The number $a$ that is to be raised. + /// ## power + /// The power $b$ to which $a$ should be raised. + /// + /// # Output + /// The power $a^b$ + function PowL(a : BigInt, power : Int) : BigInt { + return a ^ power; + } + +} diff --git a/Standard/tests/ArrayTests.qs b/Standard/tests/ArrayTests.qs index 9ce3d6d9c16..528c2f968ba 100644 --- a/Standard/tests/ArrayTests.qs +++ b/Standard/tests/ArrayTests.qs @@ -49,7 +49,7 @@ namespace Microsoft.Quantum.Tests { let dblArray = ConstantArray(71, 2.17); EqualityFactI(Length(dblArray), 71, $"ConstantArray(Int, Double) had the wrong length."); - let ignore = Mapped(NearEqualityFact(_, 2.17), dblArray); + let ignore = Mapped(NearEqualityFactD(_, 2.17), dblArray); // Stress test by making an array of Int -> Int. let fnArray = ConstantArray(7, ConstantArrayTestHelper); diff --git a/Standard/tests/AssertTests.qs b/Standard/tests/AssertTests.qs index 298783337fa..1d35be2a51b 100644 --- a/Standard/tests/AssertTests.qs +++ b/Standard/tests/AssertTests.qs @@ -27,7 +27,7 @@ namespace Microsoft.Quantum.Tests { } function AssertEqualTestShouldFail () : Unit { - NearEqualityFact(1.0, 0.0); + NearEqualityFactD(1.0, 0.0); } diff --git a/Standard/tests/BitwiseTests.qs b/Standard/tests/BitwiseTests.qs new file mode 100644 index 00000000000..f20aca9a954 --- /dev/null +++ b/Standard/tests/BitwiseTests.qs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Bitwise; + open Microsoft.Quantum.Diagnostics; + + function ShiftTest() : Unit { + let smallValue = 5; // 0b101 + EqualityFactI(20, LeftShiftedI(smallValue, 2), "Shifted values incorrect."); + EqualityFactI(2, RightShiftedI(smallValue, 1), "Shifted values incorrect."); + + // 0b‭1111111011011100101110101001100001110110010101000011001000010000‬ + let bigValue = 0xfedcba9876543210L; + EqualityFactL( + 0x1fdb97530eca864200L, + LeftShiftedL(bigValue, 5), + "LeftShfitedL returned wrong output." + ); + EqualityFactL( + 0x1fdb97530eca8642L, + RightShiftedL(bigValue, 3), + "RightShiftedL returned wrong output." + ); + } + +} diff --git a/Standard/tests/Logical/BooleanTests.qs b/Standard/tests/Logical/BooleanTests.qs new file mode 100644 index 00000000000..9900278fd75 --- /dev/null +++ b/Standard/tests/Logical/BooleanTests.qs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Logical; + open Microsoft.Quantum.Diagnostics; + + function NotTest() : Unit { + Fact(Not(false), "Not returned wrong output."); + } + + function AndTest() : Unit { + Fact(not And(false, false), "And returned wrong output."); + Fact(not And(false, true), "And returned wrong output."); + Fact(not And(true, false), "And returned wrong output."); + Fact(And(true, true), "And returned wrong output."); + } + + function OrTest() : Unit { + Fact(not Or(false, false), "Or returned wrong output."); + Fact(Or(false, true), "Or returned wrong output."); + Fact(Or(true, false), "Or returned wrong output."); + Fact(Or(true, true), "Or returned wrong output."); + } + + function XorTest() : Unit { + Fact(not Xor(false, false), "Xor returned wrong output."); + Fact(Xor(false, true), "Xor returned wrong output."); + Fact(Xor(true, false), "Xor returned wrong output."); + Fact(not Xor(true, true), "Xor returned wrong output."); + } + + function ConditionedTest() : Unit { + EqualityFactI(Conditioned(true, 42, -1), 42, "Conditioned returned wrong output."); + EqualityFactL(Conditioned(false, 42L, -1L), -1L, "Conditioned returned wrong output."); + } + +} diff --git a/Standard/tests/Logical/PredicateTests.qs b/Standard/tests/Logical/PredicateTests.qs new file mode 100644 index 00000000000..75270552c88 --- /dev/null +++ b/Standard/tests/Logical/PredicateTests.qs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Logical; + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Math; + + function EqualTest() : Unit { + Fact(EqualI(42, 42), "EqualI returned wrong output."); + Fact(not EqualI(42, 73), "EqualI returned wrong output."); + + Fact(EqualL(42L, 42L), "EqualL returned wrong output."); + Fact(not EqualL(42L, 730L), "EqualL returned wrong output."); + + Fact(EqualD(42.0, 42.0), "EqualD returned wrong output."); + Fact(not EqualD(42.0, 730.0), "EqualD returned wrong output."); + + Fact(EqualR(One, One), "EqualR returned wrong output."); + Fact(not EqualR(Zero, One), "EqualR returned wrong output."); + + Fact(EqualB(true, true), "EqualB returned wrong output."); + Fact(not EqualB(true, false), "EqualB returned wrong output."); + + Fact(EqualC(Complex(1.0, 2.0), Complex(1.0, 2.0)), "EqualC returned wrong output."); + Fact(not EqualC(Complex(1.0, 2.0), Complex(1.0, 73.0)), "EqualC returned wrong output."); + + Fact(EqualCP(ComplexPolar(1.0, 2.0), ComplexPolar(1.0, 2.0)), "EqualCP returned wrong output."); + Fact(not EqualCP(ComplexPolar(1.0, 2.0), ComplexPolar(1.0, 73.0)), "EqualCP returned wrong output."); + } + + function NotEqualTest() : Unit { + Fact(not NotEqualI(42, 42), "NotEqualI returned wrong output."); + Fact(NotEqualI(42, 73), "NotEqualI returned wrong output."); + + Fact(not NotEqualL(42L, 42L), "NotEqualL returned wrong output."); + Fact(NotEqualL(42L, 730L), "NotEqualL returned wrong output."); + + Fact(not NotEqualD(42.0, 42.0), "NotEqualD returned wrong output."); + Fact(NotEqualD(42.0, 730.0), "NotEqualD returned wrong output."); + + Fact(not NotEqualR(One, One), "NotEqualR returned wrong output."); + Fact(NotEqualR(Zero, One), "NotEqualR returned wrong output."); + + Fact(not NotEqualB(true, true), "NotEqualB returned wrong output."); + Fact(NotEqualB(true, false), "NotEqualB returned wrong output."); + + Fact(not NotEqualC(Complex(1.0, 2.0), Complex(1.0, 2.0)), "NotEqualC returned wrong output."); + Fact(NotEqualC(Complex(1.0, 2.0), Complex(1.0, 73.0)), "NotEqualC returned wrong output."); + + Fact(not NotEqualCP(ComplexPolar(1.0, 2.0), ComplexPolar(1.0, 2.0)), "NotEqualCP returned wrong output."); + Fact(NotEqualCP(ComplexPolar(1.0, 2.0), ComplexPolar(1.0, 73.0)), "NotEqualCP returned wrong output."); + } + + function GreaterThanTest() : Unit { + Fact(GreaterThanI(75, 32), "GreaterThanI returned wrong output."); + Fact(not GreaterThanI(-13, 32), "GreaterThanI returned wrong output."); + + Fact(GreaterThanD(75.0, 32.0), "GreaterThanD returned wrong output."); + Fact(not GreaterThanD(-13.0, 32.0), "GreaterThanD returned wrong output."); + + Fact(GreaterThanL(75L, 32L), "GreaterThanL returned wrong output."); + Fact(not GreaterThanL(-13L, 32L), "GreaterThanL returned wrong output."); + } + + function LessThanTest() : Unit { + Fact(not LessThanI(75, 32), "LessThanI returned wrong output."); + Fact(LessThanI(-13, 32), "LessThanI returned wrong output."); + + Fact(not LessThanD(75.0, 32.0), "LessThanD returned wrong output."); + Fact(LessThanD(-13.0, 32.0), "LessThanD returned wrong output."); + + Fact(not LessThanL(75L, 32L), "LessThanL returned wrong output."); + Fact(LessThanL(-13L, 32L), "LessThanL returned wrong output."); + } + + function GreaterThanOrEqualTest() : Unit { + Fact(GreaterThanOrEqualI(75, 75), "GreaterThanOrEqualI returned wrong output."); + Fact(not GreaterThanOrEqualI(-13, 32), "GreaterThanOrEqualI returned wrong output."); + + Fact(GreaterThanOrEqualD(75.0, 75.0), "GreaterThanOrEqualD returned wrong output."); + Fact(not GreaterThanOrEqualD(-13.0, 32.0), "GreaterThanOrEqualD returned wrong output."); + + Fact(GreaterThanOrEqualL(75L, 75L), "GreaterThanOrEqualL returned wrong output."); + Fact(not GreaterThanOrEqualL(-13L, 32L), "GreaterThanOrEqualL returned wrong output."); + } + + function LessThanOrEqualTest() : Unit { + Fact(LessThanOrEqualI(75, 75), "LessThanOrEqualI returned wrong output."); + Fact(not LessThanOrEqualI(32, -13), "LessThanOrEqualI returned wrong output."); + + Fact(LessThanOrEqualD(75.0, 75.0), "LessThanOrEqualD returned wrong output."); + Fact(not LessThanOrEqualD(32.0, -13.0), "LessThanOrEqualD returned wrong output."); + + Fact(LessThanOrEqualL(75L, 75L), "LessThanOrEqualL returned wrong output."); + Fact(not LessThanOrEqualL(32L, -13L), "LessThanOrEqualL returned wrong output."); + } + +} diff --git a/Standard/tests/Math/MathTests.qs b/Standard/tests/Math/MathTests.qs index 163155c8475..81705b3c815 100644 --- a/Standard/tests/Math/MathTests.qs +++ b/Standard/tests/Math/MathTests.qs @@ -9,18 +9,18 @@ namespace Microsoft.Quantum.Canon { function NativeFnsAreCallableTest () : Unit { let arg = PI() / 2.0; - NearEqualityFact(Sin(arg), 1.0); - NearEqualityFact(Cos(arg), 0.0); + NearEqualityFactD(Sin(arg), 1.0); + NearEqualityFactD(Cos(arg), 0.0); let arcArg = 1.0; - NearEqualityFact(ArcCos(arcArg), 0.0); - NearEqualityFact(ArcSin(arcArg), arg); + NearEqualityFactD(ArcCos(arcArg), 0.0); + NearEqualityFactD(ArcSin(arcArg), arg); } function RealModTest () : Unit { - NearEqualityFact(RealMod(5.5 * PI(), 2.0 * PI(), 0.0), 1.5 * PI()); - NearEqualityFact(RealMod(0.5 * PI(), 2.0 * PI(), -PI() / 2.0), 0.5 * PI()); + NearEqualityFactD(RealMod(5.5 * PI(), 2.0 * PI(), 0.0), 1.5 * PI()); + NearEqualityFactD(RealMod(0.5 * PI(), 2.0 * PI(), -PI() / 2.0), 0.5 * PI()); } @@ -28,9 +28,9 @@ namespace Microsoft.Quantum.Canon { // These tests were generated using NumPy's implementations // of the inverse hyperbolic functions. - NearEqualityFact(ArcTanh(0.3), 0.30951960420311175); - NearEqualityFact(ArcCosh(1.3), 0.75643291085695963); - NearEqualityFact(ArcSinh(-0.7), -0.65266656608235574); + NearEqualityFactD(ArcTanh(0.3), 0.30951960420311175); + NearEqualityFactD(ArcCosh(1.3), 0.75643291085695963); + NearEqualityFactD(ArcSinh(-0.7), -0.65266656608235574); } @@ -113,18 +113,18 @@ namespace Microsoft.Quantum.Canon { let complexArg = ArcTan2(complexIm, complexRe); let complex = Complex(complexRe, complexIm); let complexPolar = ComplexPolar(complexAbs, complexArg); - NearEqualityFact(AbsSquaredComplex(complex), complexAbs * complexAbs); - NearEqualityFact(AbsComplex(complex), complexAbs); - NearEqualityFact(ArgComplex(complex), complexArg); - NearEqualityFact(AbsSquaredComplexPolar(complexPolar), complexAbs * complexAbs); - NearEqualityFact(AbsComplexPolar(complexPolar), complexAbs); - NearEqualityFact(ArgComplexPolar(complexPolar), complexArg); + NearEqualityFactD(AbsSquaredComplex(complex), complexAbs * complexAbs); + NearEqualityFactD(AbsComplex(complex), complexAbs); + NearEqualityFactD(ArgComplex(complex), complexArg); + NearEqualityFactD(AbsSquaredComplexPolar(complexPolar), complexAbs * complexAbs); + NearEqualityFactD(AbsComplexPolar(complexPolar), complexAbs); + NearEqualityFactD(ArgComplexPolar(complexPolar), complexArg); let (x, y) = (ComplexPolarToComplex(complexPolar))!; - NearEqualityFact(x, complexRe); - NearEqualityFact(y, complexIm); + NearEqualityFactD(x, complexRe); + NearEqualityFactD(y, complexIm); let (r, t) = (ComplexToComplexPolar(complex))!; - NearEqualityFact(r, complexAbs); - NearEqualityFact(t, complexArg); + NearEqualityFactD(r, complexAbs); + NearEqualityFactD(t, complexArg); } } @@ -140,13 +140,13 @@ namespace Microsoft.Quantum.Canon { for (idxTest in IndexRange(testCases)) { let (p, array, pNormExpected) = testCases[idxTest]; - NearEqualityFact(PNorm(p, array), pNormExpected); + NearEqualityFactD(PNorm(p, array), pNormExpected); // if PNorm fails, PNormalized will fail. let arrayNormalized = PNormalized(p, array); for (idxCoeff in IndexRange(array)) { - NearEqualityFact(array[idxCoeff] / pNormExpected, arrayNormalized[idxCoeff]); + NearEqualityFactD(array[idxCoeff] / pNormExpected, arrayNormalized[idxCoeff]); } } } diff --git a/Standard/tests/Math/OperatorFunctionTests.qs b/Standard/tests/Math/OperatorFunctionTests.qs new file mode 100644 index 00000000000..10c36d3eb85 --- /dev/null +++ b/Standard/tests/Math/OperatorFunctionTests.qs @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Math; + + // Define some useful constants for complex arithmetic. + function ONE_C() : Complex { return Complex(1.0, 0.0); } + function ONE_CP() : ComplexPolar { return ComplexPolar(1.0, 0.0); } + function TWO_C() : Complex { return Complex(2.0, 0.0); } + function TWO_CP() : ComplexPolar { return ComplexPolar(2.0, 0.0); } + function PI_2_C() : Complex { return ComplexPolarAsComplex(PI_2_CP()); } + function PI_2_CP() : ComplexPolar { return ComplexPolar(1.0, PI() / 2.0); } + function PI_4_C() : Complex { return ComplexPolarAsComplex(PI_4_CP()); } + function PI_4_CP() : ComplexPolar { return ComplexPolar(1.0, PI() / 4.0); } + function TWO_PI_4_C() : Complex { return ComplexPolarAsComplex(TWO_PI_4_CP()); } + function TWO_PI_4_CP() : ComplexPolar { return ComplexPolar(2.0, PI() / 4.0); } + + // FIXME: expected and actual are flipped uniformly in this file. + // this has no effect other than making unit test failures slightly + // harder to read. + + function NegationTest() : Unit { + EqualityFactI(-42, NegationI(42), "NegationI returned wrong output."); + NearEqualityFactD(-42.0, NegationD(42.0)); + EqualityFactL(-42L, NegationL(42L), "NegationI returned wrong output."); + NearEqualityFactC(Complex(1.0, 2.0), NegationC(Complex(-1.0, -2.0))); + NearEqualityFactCP( + ComplexPolar(1.0, PI() / 4.0), + NegationCP(ComplexPolar(1.0, 5.0 * PI() / 4.0)) + ); + } + + function PlusTest() : Unit { + EqualityFactI(-40, PlusI(-72, 32), "PlusI returned wrong output."); + NearEqualityFactD(-40.0, PlusD(-72.0, 32.0)); + EqualityFactL(-40L, PlusL(-72L, 32L), "PlusL returned wrong output."); + NearEqualityFactC(TWO_C(), PlusC(ONE_C(), ONE_C())); + NearEqualityFactCP(TWO_CP(), PlusCP(ONE_CP(), ONE_CP())); + } + + function MinusTest() : Unit { + EqualityFactI(40, MinusI(72, 32), "MinusI returned wrong output."); + NearEqualityFactD(40.0, MinusD(72.0, 32.0)); + EqualityFactL(40L, MinusL(72L, 32L), "MinusL returned wrong output."); + NearEqualityFactC(ONE_C(), MinusC(TWO_C(), ONE_C())); + NearEqualityFactCP(ONE_CP(), MinusCP(TWO_CP(), ONE_CP())); + } + + function TimesTest() : Unit { + EqualityFactI(40, TimesI(-10, -4), "TimesI returned wrong output."); + NearEqualityFactD(40.0, TimesD(-10.0, -4.0)); + EqualityFactL(40L, TimesL(-10L, -4L), "TimesL returned wrong output."); + NearEqualityFactC(TWO_C(), TimesC(TWO_C(), ONE_C())); + NearEqualityFactCP(TWO_CP(), TimesCP(TWO_CP(), ONE_CP())); + } + + function DivdedByTest() : Unit { + EqualityFactI(10, DividedByI(-40, -4), "DividedByI returned wrong output."); + NearEqualityFactD(10.0, DividedByD(-40.0, -4.0)); + EqualityFactL(10L, DividedByL(-40L, -4L), "DividedByL returned wrong output."); + NearEqualityFactC(PI_4_C(), DividedByC(TWO_PI_4_C(), TWO_C())); + NearEqualityFactCP(PI_4_CP(), DividedByCP(TWO_PI_4_CP(), TWO_CP())); + } + + function ModTest() : Unit { + EqualityFactI(2, ModI(17, 5), "ModI returned wrong output."); + EqualityFactL(2L, ModL(17L, 5L), "ModL returned wrong output."); + } + + function PowTest() : Unit { + EqualityFactI(6561, PowI(3, 8), "PowI returned wrong output."); + NearEqualityFactD(157.58648490814928441592231285347, PowD(2.0, 7.3)); + EqualityFactL(239072435685151324847153L, PowL(17L, 19), "PowL returned wrong output."); + NearEqualityFactC(PI_2_C(), PowC(PI_4_C(), TWO_C())); + NearEqualityFactCP(PI_2_CP(), PowCP(PI_4_CP(), TWO_CP())); + } + +} diff --git a/Standard/tests/QcvvTests.qs b/Standard/tests/QcvvTests.qs index 7e353778f31..573e4116865 100644 --- a/Standard/tests/QcvvTests.qs +++ b/Standard/tests/QcvvTests.qs @@ -77,7 +77,7 @@ namespace Microsoft.Quantum.Tests { // Emulation is actually kicking in. operation EstimateFrequencyEmulationTest() : Unit { let freq = EstimateFrequencyA(_trivialStatePrepration, Measure([PauliZ, PauliZ, PauliZ], _), 3, 2000); - NearEqualityFact(freq, 1.0); + NearEqualityFactD(freq, 1.0); } operation _RobustPhaseEstimationTestOp (phase : Double, power : Int, qubits : Qubit[]) : Unit is Adj + Ctl {