1use crate::update_counts;
5use num_bigint::BigInt;
6use std::{mem::ManuallyDrop, rc::Rc};
7
8#[no_mangle]
9pub extern "C" fn __quantum__rt__bigint_create_i64(input: i64) -> *const BigInt {
10 Rc::into_raw(Rc::new(input.into()))
11}
12
13#[no_mangle]
14pub unsafe extern "C" fn __quantum__rt__bigint_create_array(
15 size: u32,
16 input: *const u8,
17) -> *const BigInt {
18 Rc::into_raw(Rc::new(BigInt::from_signed_bytes_le(
19 std::slice::from_raw_parts(input, size as usize),
20 )))
21}
22
23#[no_mangle]
24pub unsafe extern "C" fn __quantum__rt__bigint_get_data(input: *const BigInt) -> *const u8 {
25 ManuallyDrop::new((*input).to_signed_bytes_le()).as_ptr()
26}
27
28#[no_mangle]
29pub unsafe extern "C" fn __quantum__rt__bigint_get_length(input: *const BigInt) -> u32 {
30 let size = (*input).to_signed_bytes_le().len();
31 size.try_into()
32 .expect("Length of bigint representation too large for 32-bit integer.")
33}
34
35#[no_mangle]
36pub unsafe extern "C" fn __quantum__rt__bigint_update_reference_count(
37 input: *const BigInt,
38 update: i32,
39) {
40 update_counts(input, update, false);
41}
42
43#[no_mangle]
44pub unsafe extern "C" fn __quantum__rt__bigint_negate(input: *const BigInt) -> *const BigInt {
45 Rc::into_raw(Rc::new(&(*input) * -1))
46}
47
48#[no_mangle]
49pub unsafe extern "C" fn __quantum__rt__bigint_add(
50 lhs: *const BigInt,
51 rhs: *const BigInt,
52) -> *const BigInt {
53 Rc::into_raw(Rc::new(&(*lhs) + &(*rhs)))
54}
55
56#[no_mangle]
57pub unsafe extern "C" fn __quantum__rt__bigint_subtract(
58 lhs: *const BigInt,
59 rhs: *const BigInt,
60) -> *const BigInt {
61 Rc::into_raw(Rc::new(&(*lhs) - &(*rhs)))
62}
63
64#[no_mangle]
65pub unsafe extern "C" fn __quantum__rt__bigint_multiply(
66 lhs: *const BigInt,
67 rhs: *const BigInt,
68) -> *const BigInt {
69 Rc::into_raw(Rc::new(&(*lhs) * &(*rhs)))
70}
71
72#[no_mangle]
73pub unsafe extern "C" fn __quantum__rt__bigint_divide(
74 lhs: *const BigInt,
75 rhs: *const BigInt,
76) -> *const BigInt {
77 Rc::into_raw(Rc::new(&(*lhs) / &(*rhs)))
78}
79
80#[no_mangle]
81pub unsafe extern "C" fn __quantum__rt__bigint_modulus(
82 lhs: *const BigInt,
83 rhs: *const BigInt,
84) -> *const BigInt {
85 Rc::into_raw(Rc::new(&(*lhs) % &(*rhs)))
86}
87
88#[no_mangle]
89pub unsafe extern "C" fn __quantum__rt__bigint_power(
90 base: *const BigInt,
91 exponent: u32,
92) -> *const BigInt {
93 Rc::into_raw(Rc::new((*base).pow(exponent)))
94}
95
96#[no_mangle]
97pub unsafe extern "C" fn __quantum__rt__bigint_bitand(
98 lhs: *const BigInt,
99 rhs: *const BigInt,
100) -> *const BigInt {
101 Rc::into_raw(Rc::new(&(*lhs) & &(*rhs)))
102}
103
104#[no_mangle]
105pub unsafe extern "C" fn __quantum__rt__bigint_bitor(
106 lhs: *const BigInt,
107 rhs: *const BigInt,
108) -> *const BigInt {
109 Rc::into_raw(Rc::new(&(*lhs) | &(*rhs)))
110}
111
112#[no_mangle]
113pub unsafe extern "C" fn __quantum__rt__bigint_bitxor(
114 lhs: *const BigInt,
115 rhs: *const BigInt,
116) -> *const BigInt {
117 Rc::into_raw(Rc::new(&(*lhs) ^ &(*rhs)))
118}
119
120#[no_mangle]
121pub unsafe extern "C" fn __quantum__rt__bigint_bitnot(input: *const BigInt) -> *const BigInt {
122 Rc::into_raw(Rc::new(!&(*input)))
123}
124
125#[no_mangle]
126pub unsafe extern "C" fn __quantum__rt__bigint_shiftleft(
127 input: *const BigInt,
128 amount: u64,
129) -> *const BigInt {
130 Rc::into_raw(Rc::new(&(*input) << amount))
131}
132
133#[no_mangle]
134pub unsafe extern "C" fn __quantum__rt__bigint_shiftright(
135 input: *const BigInt,
136 amount: u64,
137) -> *const BigInt {
138 Rc::into_raw(Rc::new(&(*input) >> amount))
139}
140
141#[no_mangle]
142pub unsafe extern "C" fn __quantum__rt__bigint_equal(
143 lhs: *const BigInt,
144 rhs: *const BigInt,
145) -> bool {
146 (*lhs) == (*rhs)
147}
148
149#[no_mangle]
150pub unsafe extern "C" fn __quantum__rt__bigint_greater(
151 lhs: *const BigInt,
152 rhs: *const BigInt,
153) -> bool {
154 (*lhs) > (*rhs)
155}
156
157#[no_mangle]
158pub unsafe extern "C" fn __quantum__rt__bigint_greater_eq(
159 lhs: *const BigInt,
160 rhs: *const BigInt,
161) -> bool {
162 (*lhs) >= (*rhs)
163}
164
165#[cfg(test)]
166mod tests {
167 use std::convert::TryInto;
168
169 use super::*;
170
171 #[test]
172 fn test_bigint_create_from_int() {
173 let bigint_0 = __quantum__rt__bigint_create_i64(42);
174 unsafe {
175 assert_eq!(*bigint_0, (42).into());
176 __quantum__rt__bigint_update_reference_count(bigint_0, -1);
179 }
180 }
181
182 #[test]
183 fn test_bigint_create_from_array() {
184 let bytes = 9_223_372_036_854_775_807_i64.to_le_bytes();
185 unsafe {
186 let bigint_1 =
187 __quantum__rt__bigint_create_array(bytes.len().try_into().unwrap(), bytes.as_ptr());
188 assert_eq!(*bigint_1, (9_223_372_036_854_775_807_i64).into());
189 __quantum__rt__bigint_update_reference_count(bigint_1, -1);
190 }
191 }
192
193 #[test]
194 fn test_bigint_arithmetic() {
195 let bigint_0 = __quantum__rt__bigint_create_i64(42);
196 let bigint_1 = __quantum__rt__bigint_create_i64(3);
197 unsafe {
198 let bigint_2 = __quantum__rt__bigint_add(bigint_0, bigint_1);
199 assert_eq!(*bigint_2, (45).into());
200 let bigint_3 = __quantum__rt__bigint_subtract(bigint_2, bigint_1);
201 assert_eq!(*bigint_3, (42).into());
202 let bigint_4 = __quantum__rt__bigint_divide(bigint_3, bigint_1);
203 assert_eq!(*bigint_4, (14).into());
204 let bigint_5 = __quantum__rt__bigint_multiply(bigint_4, bigint_1);
205 assert_eq!(*bigint_5, (42).into());
206 let bigint_6 = __quantum__rt__bigint_modulus(bigint_5, bigint_1);
207 assert_eq!(*bigint_6, (0).into());
208 let bigint_7 = __quantum__rt__bigint_negate(bigint_5);
209 assert_eq!(*bigint_7, (-42).into());
210 let bigint_8 = __quantum__rt__bigint_power(bigint_7, 3);
211 assert_eq!(*bigint_8, (-74088).into());
212 __quantum__rt__bigint_update_reference_count(bigint_8, -1);
213 __quantum__rt__bigint_update_reference_count(bigint_7, -1);
214 __quantum__rt__bigint_update_reference_count(bigint_6, -1);
215 __quantum__rt__bigint_update_reference_count(bigint_5, -1);
216 __quantum__rt__bigint_update_reference_count(bigint_4, -1);
217 __quantum__rt__bigint_update_reference_count(bigint_3, -1);
218 __quantum__rt__bigint_update_reference_count(bigint_2, -1);
219 __quantum__rt__bigint_update_reference_count(bigint_1, -1);
220 __quantum__rt__bigint_update_reference_count(bigint_0, -1);
221 }
222 }
223
224 #[test]
225 fn test_bigint_bitops() {
226 let bigint_0 = __quantum__rt__bigint_create_i64(42);
227 let bigint_1 = __quantum__rt__bigint_create_i64(3);
228 unsafe {
229 let bigint_2 = __quantum__rt__bigint_bitand(bigint_0, bigint_1);
230 assert_eq!(*bigint_2, (2).into());
231 let bigint_3 = __quantum__rt__bigint_bitor(bigint_0, bigint_1);
232 assert_eq!(*bigint_3, (43).into());
233 let bigint_4 = __quantum__rt__bigint_bitxor(bigint_0, bigint_3);
234 assert_eq!(*bigint_4, (1).into());
235 let bigint_5 = __quantum__rt__bigint_bitnot(bigint_4);
236 assert_eq!(*bigint_5, (-2).into());
237 let bigint_6 = __quantum__rt__bigint_shiftleft(bigint_0, 2);
238 assert_eq!(*bigint_6, (168).into());
239 let bigint_7 = __quantum__rt__bigint_shiftright(bigint_6, 3);
240 assert_eq!(*bigint_7, (21).into());
241 __quantum__rt__bigint_update_reference_count(bigint_7, -1);
242 __quantum__rt__bigint_update_reference_count(bigint_6, -1);
243 __quantum__rt__bigint_update_reference_count(bigint_5, -1);
244 __quantum__rt__bigint_update_reference_count(bigint_4, -1);
245 __quantum__rt__bigint_update_reference_count(bigint_3, -1);
246 __quantum__rt__bigint_update_reference_count(bigint_2, -1);
247 __quantum__rt__bigint_update_reference_count(bigint_1, -1);
248 __quantum__rt__bigint_update_reference_count(bigint_0, -1);
249 }
250 }
251
252 #[test]
253 fn test_bigint_comparisons() {
254 let bigint_0 = __quantum__rt__bigint_create_i64(42);
255 let bigint_1 = __quantum__rt__bigint_create_i64(43);
256 let bigint_2 = __quantum__rt__bigint_create_i64(42);
257 unsafe {
258 assert!(__quantum__rt__bigint_greater(bigint_1, bigint_0));
259 assert!(!__quantum__rt__bigint_greater(bigint_0, bigint_1));
260 assert!(__quantum__rt__bigint_equal(bigint_0, bigint_2));
261 assert!(__quantum__rt__bigint_greater_eq(bigint_0, bigint_2));
262 assert!(__quantum__rt__bigint_greater_eq(bigint_1, bigint_2));
263 assert!(!__quantum__rt__bigint_greater_eq(bigint_0, bigint_1));
264 __quantum__rt__bigint_update_reference_count(bigint_2, -1);
265 __quantum__rt__bigint_update_reference_count(bigint_1, -1);
266 __quantum__rt__bigint_update_reference_count(bigint_0, -1);
267 }
268 }
269}