Skip to content

Commit

Permalink
Added classical functions to math library (#258)
Browse files Browse the repository at this point in the history
This adds a few classical functions to the math namespace. Added new
project for library testing (thanks @swernli!)

1. Simple functions that are very convenient and their I, D, L variants
for completeness: Sign, Abs, Min, Max.
2. Inverse hyperbolic functions: ArcCosh , ArcSinh, ArcTanh.
3. Intrinsic Sqrt.
4. Intrinsic Log (base e), and derived Log10 and Lg (base 2).
5. ModulusI and ModulusL to compute remainder in canonical way (always
non-negative).
6. ExpModI and ExpModL to compute exponentiation with respect to
modulus.
7. GCD and extended GCD.

Many of these functions are used in Shor and Grover.

Not including
[ModPowL](https://github.com/microsoft/qsharp-runtime/blob/4976e913cf007f14958f5ab9a09db3a49fc57698/src/Simulation/QSharpFoundation/Math/Math.qs#L317)
- same intended functionality as
[ExpModL](https://github.com/microsoft/QuantumLibraries/blob/2214d89925e732bd3a10c642885699834cb975fa/Standard/src/Math/Functions.qs#L244)
and no use found.

---------

Co-authored-by: Dmitry Vasilevsky <dmitryv@microsoft.com>
  • Loading branch information
DmitryVasilevsky and Dmitry Vasilevsky authored May 2, 2023
1 parent 6315a97 commit 3555242
Show file tree
Hide file tree
Showing 10 changed files with 677 additions and 35 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"compiler/qsc_hir",
"compiler/qsc_passes",
"katas",
"library/tests",
"pip",
"wasm",
]
Expand Down
5 changes: 4 additions & 1 deletion compiler/qsc/src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ mod debug;
pub mod stateful;
pub mod stateless;

pub use qsc_eval::{output, val::Value};
pub use qsc_eval::{
output::{self, GenericReceiver},
val::Value,
};
16 changes: 16 additions & 0 deletions compiler/qsc_eval/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
mod tests;

use crate::{output::Receiver, val::Value, Error, Reason, WithSpan};
use num_bigint::BigInt;
use qir_backend::{
__quantum__qis__ccx__body, __quantum__qis__cx__body, __quantum__qis__cy__body,
__quantum__qis__cz__body, __quantum__qis__h__body, __quantum__qis__m__body,
Expand Down Expand Up @@ -37,6 +38,11 @@ pub(crate) fn invoke_intrinsic(
Continue(Value::Double(val as f64))
}

"IntAsBigInt" => {
let val: i64 = args.try_into().with_span(args_span)?;
Continue(Value::BigInt(BigInt::from(val)))
}

"DumpMachine" => {
let (state, qubit_count) = capture_quantum_state();
match out.state(state, qubit_count) {
Expand Down Expand Up @@ -110,6 +116,16 @@ pub(crate) fn invoke_intrinsic(
Continue(Value::Double(val.tanh()))
}

"Sqrt" => {
let val: f64 = args.try_into().with_span(args_span)?;
Continue(Value::Double(val.sqrt()))
}

"Log" => {
let val: f64 = args.try_into().with_span(args_span)?;
Continue(Value::Double(val.ln()))
}

"DrawRandomInt" => match args.try_into_tuple().with_span(args_span)?.as_ref() {
[lo, hi] => invoke_draw_random_int(lo.clone(), hi.clone(), args_span),
args => Break(Reason::Error(Error::TupleArity(2, args.len(), args_span))),
Expand Down
39 changes: 16 additions & 23 deletions compiler/qsc_eval/src/intrinsic/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::f64::consts;

use expect_test::{expect, Expect};
use indoc::indoc;
use num_bigint::BigInt;
use qsc_frontend::compile::{self, compile, PackageStore, SourceMap};
use qsc_passes::run_default_passes;

Expand Down Expand Up @@ -286,40 +287,32 @@ fn draw_random_int() {
}

#[test]
fn check_bitsize_i() {
check_intrinsic_value("", "Microsoft.Quantum.Math.BitSizeI(0)", &Value::Int(0));
check_intrinsic_value("", "Microsoft.Quantum.Math.BitSizeI(1)", &Value::Int(1));
check_intrinsic_value("", "Microsoft.Quantum.Math.BitSizeI(2)", &Value::Int(2));
check_intrinsic_value("", "Microsoft.Quantum.Math.BitSizeI(3)", &Value::Int(2));
check_intrinsic_value(
"",
"Microsoft.Quantum.Math.BitSizeI(0x7FFFFFFFFFFFFFFF)",
&Value::Int(63),
);
fn sqrt() {
check_intrinsic_value("", "Microsoft.Quantum.Math.Sqrt(0.0)", &Value::Double(0.0));
check_intrinsic_value("", "Microsoft.Quantum.Math.Sqrt(81.0)", &Value::Double(9.0));
}

#[test]
fn check_fst_snd() {
check_intrinsic_value("", "Fst(7,6)", &Value::Int(7));
check_intrinsic_value("", "Snd(7,6)", &Value::Int(6));
}

#[test]
fn check_index_range() {
fn log() {
check_intrinsic_value("", "Microsoft.Quantum.Math.Log(1.0)", &Value::Double(0.0));
check_intrinsic_value(
"",
"Microsoft.Quantum.Arrays.IndexRange([7,6,5,4])::Start",
&Value::Int(0),
"Microsoft.Quantum.Math.Log(Microsoft.Quantum.Math.E())",
&Value::Double(1.0),
);
}

#[test]
fn int_as_bigint() {
check_intrinsic_value(
"",
"Microsoft.Quantum.Arrays.IndexRange([7,6,5,4])::Step",
&Value::Int(1),
"Microsoft.Quantum.Convert.IntAsBigInt(0)",
&Value::BigInt(BigInt::from(0)),
);
check_intrinsic_value(
"",
"Microsoft.Quantum.Arrays.IndexRange([7,6,5,4])::End",
&Value::Int(3),
"Microsoft.Quantum.Convert.IntAsBigInt(-10000)",
&Value::BigInt(BigInt::from(-10000)),
);
}

Expand Down
7 changes: 7 additions & 0 deletions library/convert.qs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ namespace Microsoft.Quantum.Convert {
function IntAsDouble(a : Int) : Double {
body intrinsic;
}

/// # Summary
/// Converts a given integer to an equivalent big integer.
function IntAsBigInt(a : Int) : BigInt {
body intrinsic;
}

}
Loading

0 comments on commit 3555242

Please sign in to comment.