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