qir_stdlib/
math.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4// TODO: transition math functions to `__quantum__rt` once compiler support is ready (https://github.com/microsoft/qsharp-compiler/issues/1557).
5
6use rand::Rng;
7use std::ffi::c_double;
8
9use crate::strings::convert;
10
11#[cfg(not(feature = "fail-support"))]
12#[allow(improper_ctypes)]
13extern "C" {
14    fn __quantum__rt__fail(str: *const std::ffi::CString);
15}
16
17#[cfg(feature = "fail-support")]
18use crate::__quantum__rt__fail;
19
20#[no_mangle]
21pub extern "C" fn __quantum__qis__nan__body() -> c_double {
22    c_double::NAN
23}
24
25#[no_mangle]
26pub extern "C" fn __quantum__qis__isnan__body(val: c_double) -> bool {
27    val.is_nan()
28}
29
30#[no_mangle]
31pub extern "C" fn __quantum__qis__infinity__body() -> c_double {
32    c_double::INFINITY
33}
34
35#[no_mangle]
36pub extern "C" fn __quantum__qis__isinf__body(val: c_double) -> bool {
37    val.is_infinite() && val.is_sign_positive()
38}
39
40#[no_mangle]
41pub extern "C" fn __quantum__qis__isnegativeinfinity__body(val: c_double) -> bool {
42    val.is_infinite() && val.is_sign_negative()
43}
44
45#[no_mangle]
46pub extern "C" fn __quantum__qis__sin__body(val: c_double) -> c_double {
47    val.sin()
48}
49
50#[no_mangle]
51pub extern "C" fn __quantum__qis__cos__body(val: c_double) -> c_double {
52    val.cos()
53}
54#[no_mangle]
55pub extern "C" fn __quantum__qis__tan__body(val: c_double) -> c_double {
56    val.tan()
57}
58
59#[no_mangle]
60pub extern "C" fn __quantum__qis__arctan2__body(y: c_double, x: c_double) -> c_double {
61    y.atan2(x)
62}
63
64#[no_mangle]
65pub extern "C" fn __quantum__qis__sinh__body(val: c_double) -> c_double {
66    val.sinh()
67}
68
69#[no_mangle]
70pub extern "C" fn __quantum__qis__cosh__body(val: c_double) -> c_double {
71    val.cosh()
72}
73
74#[no_mangle]
75pub extern "C" fn __quantum__qis__tanh__body(val: c_double) -> c_double {
76    val.tanh()
77}
78
79#[no_mangle]
80pub extern "C" fn __quantum__qis__arcsin__body(val: c_double) -> c_double {
81    val.asin()
82}
83
84#[no_mangle]
85pub extern "C" fn __quantum__qis__arccos__body(val: c_double) -> c_double {
86    val.acos()
87}
88
89#[no_mangle]
90pub extern "C" fn __quantum__qis__arctan__body(val: c_double) -> c_double {
91    val.atan()
92}
93
94#[no_mangle]
95pub extern "C" fn __quantum__qis__sqrt__body(val: c_double) -> c_double {
96    val.sqrt()
97}
98
99#[no_mangle]
100pub extern "C" fn __quantum__qis__log__body(val: c_double) -> c_double {
101    val.ln()
102}
103
104#[no_mangle]
105pub extern "C" fn __quantum__qis__ieeeremainder__body(x: c_double, y: c_double) -> c_double {
106    x - y * (x / y).round()
107}
108
109#[no_mangle]
110pub extern "C" fn __quantum__qis__drawrandomint__body(min: i64, max: i64) -> i64 {
111    if min > max {
112        unsafe {
113            __quantum__rt__fail(convert(&"Invalid Argument: minimum > maximum".to_string()));
114        }
115    }
116    rand::thread_rng().gen_range(min..=max)
117}
118
119#[no_mangle]
120pub extern "C" fn __quantum__qis__drawrandomdouble__body(min: c_double, max: c_double) -> f64 {
121    if min > max {
122        unsafe {
123            __quantum__rt__fail(convert(&"Invalid Argument: minimum > maximum".to_string()));
124        }
125    }
126    rand::thread_rng().gen_range(min..=max)
127}