1#[macro_export]
2macro_rules! abstract_int {
3 ($name:ident, $bits:literal, $signed:literal) => {
4 #[derive(Clone, Copy)]
5 pub struct $name {
6 b: [u8; ($bits + 7) / 8],
7 sign: Sign,
8 signed: bool,
9 }
10
11 impl $name {
12 fn max() -> BigInt {
13 BigInt::from(1u32).shl($bits) - BigInt::one()
14 }
15
16 pub fn max_value() -> Self {
17 Self::from(Self::max())
18 }
19
20 fn hex_string_to_bytes(s: &str) -> Vec<u8> {
21 let s = if s.len() % 2 != 0 {
22 let mut x = "0".to_string();
23 x.push_str(s);
24 x
25 } else {
26 s.to_string()
27 };
28 assert!(s.len() % 2 == 0, "length of hex string {}: {}",s, s.len());
29 let b: Result<Vec<u8>, ParseIntError> = (0..s.len())
30 .step_by(2)
31 .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
32 .collect();
33 b.expect("Error parsing hex string")
34 }
35
36 #[allow(dead_code)]
37 pub fn from_literal(x: u128) -> Self {
38 let big_x = BigInt::from(x);
39 if big_x > $name::max().into() {
40 panic!("literal {} too big for type {}", x, stringify!($name));
41 }
42 big_x.into()
43 }
44
45 #[allow(dead_code)]
46 pub fn from_signed_literal(x: i128) -> Self {
47 let big_x = BigInt::from(x as u128);
48 if big_x > $name::max().into() {
49 panic!("literal {} too big for type {}", x, stringify!($name));
50 }
51 big_x.into()
52 }
53
54 #[allow(dead_code)]
56 pub fn pow2(x: usize) -> $name {
57 BigInt::from(1u32).shl(x).into()
58 }
59
60 #[allow(dead_code)]
62 pub fn bit(self, i: usize) -> bool {
63 assert!(
64 i < self.b.len() * 8,
65 "the bit queried should be lower than the size of the integer representation: {} < {}",
66 i,
67 self.b.len() * 8
68 );
69 let bigint : BigInt = self.into();
70 let tmp: BigInt = bigint >> i;
71 (tmp & BigInt::one()).to_bytes_le().1[0] == 1
72 }
73 }
74
75 impl From<BigUint> for $name {
76 fn from(x: BigUint) -> $name {
77 Self::from(BigInt::from(x))
78 }
79 }
80
81 impl From<BigInt> for $name {
82 fn from(x: BigInt) -> $name {
83 let max_value = Self::max();
84 assert!(x <= max_value, "{} is too large for type {}!", x, stringify!($name));
85 let (sign, repr) = x.to_bytes_be();
86 if sign == Sign::Minus && (!$signed) {
87 panic!("Trying to convert a negative number into an unsigned integer!")
88 }
89 if repr.len() > ($bits + 7) / 8 {
90 panic!("{} is too large for type {}", x, stringify!($name))
91 }
92 let mut out = [0u8; ($bits + 7) / 8];
93 let upper = out.len();
94 let lower = upper - repr.len();
95 out[lower..upper].copy_from_slice(&repr);
96 $name {
97 b: out,
98 sign: sign,
99 signed: $signed,
100 }
101 }
102 }
103
104 impl Default for $name {
105 fn default() -> $name {
106 $name {
107 b: [0u8; ($bits + 7) / 8],
108 sign: Sign::Plus,
109 signed: $signed,
110 }
111 }
112 }
113
114 impl Into<BigInt> for $name {
115 fn into(self) -> BigInt {
116 BigInt::from_bytes_be(self.sign, &self.b)
117 }
118 }
119
120 impl Into<BigUint> for $name {
121 fn into(self) -> BigUint {
122 BigUint::from_bytes_be(&self.b)
123 }
124 }
125
126 impl core::fmt::Display for $name {
127 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
128 let uint: BigInt = (*self).into();
129 write!(f, "{}", uint)
130 }
131 }
132
133 impl core::fmt::Debug for $name {
134 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
135 let uint: BigInt = (*self).into();
136 write!(f, "{}", uint)
137 }
138 }
139
140 impl core::fmt::LowerHex for $name {
141 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
142 let val: BigInt = (*self).into();
143 core::fmt::LowerHex::fmt(&val, f)
144 }
145 }
146 };
147}
148
149#[macro_export]
150macro_rules! abstract_public {
151 ($name:ident) => {
152 impl $name {
153 #[allow(dead_code)]
154 pub fn inv(self, modval: Self) -> Self {
155 let biguintmodval: BigInt = modval.into();
156 let m = &biguintmodval - BigInt::from(2u32);
157 let s: BigInt = (self).into();
158 s.modpow(&m, &biguintmodval).into()
159 }
160
161 #[allow(dead_code)]
162 pub fn pow_felem(self, exp: Self, modval: Self) -> Self {
163 let a: BigInt = self.into();
164 let b: BigInt = exp.into();
165 let m: BigInt = modval.into();
166 let c: BigInt = a.modpow(&b, &m);
167 c.into()
168 }
169 #[allow(dead_code)]
172 pub fn pow(self, exp: u128, modval: Self) -> Self {
173 self.pow_felem(BigInt::from(exp).into(), modval)
174 }
175
176 fn rem(self, n: Self) -> Self {
177 self % n
178 }
179 }
180
181 impl Add for $name {
183 type Output = $name;
184 fn add(self, rhs: $name) -> $name {
185 let a: BigInt = self.into();
186 let b: BigInt = rhs.into();
187 let c = a + b;
188 if c > $name::max() {
189 panic!("bounded addition overflow for type {}", stringify!($name));
190 }
191 c.into()
192 }
193 }
194
195 impl Sub for $name {
197 type Output = $name;
198 fn sub(self, rhs: $name) -> $name {
199 let a: BigInt = self.into();
200 let b: BigInt = rhs.into();
201 let c = if self.signed {
202 a - b
203 } else {
204 a.checked_sub(&b).unwrap_or_else(|| {
205 panic!(
206 "bounded substraction underflow for type {}",
207 stringify!($name)
208 )
209 })
210 };
211 c.into()
212 }
213 }
214
215 impl Mul for $name {
217 type Output = $name;
218 fn mul(self, rhs: $name) -> $name {
219 let a: BigInt = self.into();
220 let b: BigInt = rhs.into();
221 let c = a * b;
222 if c > $name::max() {
223 panic!(
224 "bounded multiplication overflow for type {}",
225 stringify!($name)
226 );
227 }
228 c.into()
229 }
230 }
231
232 impl Div for $name {
234 type Output = $name;
235 fn div(self, rhs: $name) -> $name {
236 let a: BigInt = self.into();
237 let b: BigInt = rhs.into();
238 if b == BigInt::zero() {
239 panic!("dividing by zero in type {}", stringify!($name));
240 }
241 let c = a / b;
242 c.into()
243 }
244 }
245
246 impl Rem for $name {
248 type Output = $name;
249 fn rem(self, rhs: $name) -> $name {
250 let a: BigInt = self.into();
251 let b: BigInt = rhs.into();
252 if b == BigInt::zero() {
253 panic!("dividing by zero in type {}", stringify!($name));
254 }
255 let c = a % b;
256 c.into()
257 }
258 }
259
260 impl Not for $name {
261 type Output = $name;
262 fn not(self) -> Self::Output {
263 unimplemented!();
264 }
265 }
266
267 impl BitOr for $name {
268 type Output = $name;
269 fn bitor(self, rhs: Self) -> Self::Output {
270 let a: BigInt = self.into();
271 let b: BigInt = rhs.into();
272 (a | b).into()
273 }
274 }
275
276 impl BitXor for $name {
277 type Output = $name;
278 fn bitxor(self, rhs: Self) -> Self::Output {
279 let a: BigInt = self.into();
280 let b: BigInt = rhs.into();
281 (a ^ b).into()
282 }
283 }
284
285 impl BitAnd for $name {
286 type Output = $name;
287 fn bitand(self, rhs: Self) -> Self::Output {
288 let a: BigInt = self.into();
289 let b: BigInt = rhs.into();
290 (a & b).into()
291 }
292 }
293
294 impl Shr<usize> for $name {
295 type Output = $name;
296 fn shr(self, rhs: usize) -> Self::Output {
297 let a: BigInt = self.into();
298 let b = rhs as usize;
299 (a >> b).into()
300 }
301 }
302
303 impl Shl<usize> for $name {
304 type Output = $name;
305 fn shl(self, rhs: usize) -> Self::Output {
306 let a: BigInt = self.into();
307 let b = rhs as usize;
308 (a << b).into()
309 }
310 }
311
312 impl PartialEq for $name {
313 fn eq(&self, rhs: &$name) -> bool {
314 let a: BigInt = (*self).into();
315 let b: BigInt = (*rhs).into();
316 a == b
317 }
318 }
319
320 impl Eq for $name {}
321
322 impl PartialOrd for $name {
323 fn partial_cmp(&self, other: &$name) -> Option<core::cmp::Ordering> {
324 let a: BigInt = (*self).into();
325 let b: BigInt = (*other).into();
326 a.partial_cmp(&b)
327 }
328 }
329
330 impl Ord for $name {
331 fn cmp(&self, other: &$name) -> core::cmp::Ordering {
332 self.partial_cmp(other).unwrap()
333 }
334 }
335 };
336}
337
338#[macro_export]
339macro_rules! abstract_unsigned {
340 ($name:ident, $bits:literal) => {
341 abstract_int!($name, $bits, false);
342
343 impl $name {
344 #[allow(dead_code)]
345 pub fn from_hex(s: &str) -> Self {
346 BigInt::from_bytes_be(Sign::Plus, &Self::hex_string_to_bytes(s)).into()
347 }
348
349 #[allow(dead_code)]
350 pub fn from_be_bytes(v: &[u8]) -> Self {
351 debug_assert!(
352 v.len() <= ($bits + 7) / 8,
353 "from_be_bytes: lenght of bytes should be lesser than the lenght of the canvas"
354 );
355 let mut repr = [0u8; ($bits + 7) / 8];
356 let upper = repr.len();
357 let lower = upper - v.len();
358 repr[lower..upper].copy_from_slice(&v);
359 $name {
360 b: repr,
361 sign: Sign::Plus,
362 signed: false,
363 }
364 }
365
366 #[allow(dead_code)]
367 pub fn from_le_bytes(v: &[u8]) -> Self {
368 debug_assert!(
369 v.len() <= ($bits + 7) / 8,
370 "from_be_bytes: lenght of bytes should be lesser than the lenght of the canvas"
371 );
372 let mut repr = [0u8; ($bits + 7) / 8];
373 let upper = repr.len();
374 let lower = upper - v.len();
375 repr[lower..upper].copy_from_slice(&v);
376 BigInt::from_bytes_le(Sign::Plus, &repr).into()
377 }
378
379 #[allow(dead_code)]
380 pub fn to_be_bytes(self) -> [u8; ($bits + 7) / 8] {
381 self.b
382 }
383
384 #[allow(dead_code)]
385 pub fn to_le_bytes(self) -> [u8; ($bits + 7) / 8] {
386 let x = BigInt::from_bytes_be(Sign::Plus, &self.b);
387 let (_, x_s) = x.to_bytes_le();
388 let mut repr = [0u8; ($bits + 7) / 8];
389 repr[0..x_s.len()].copy_from_slice(&x_s);
390 repr
391 }
392
393 #[inline]
397 pub fn comp_eq(self, rhs: Self) -> Self {
398 let a: BigInt = self.into();
399 let b: BigInt = rhs.into();
400 if a == b {
401 let one = Self::from_literal(1);
402 (one << ($bits - 1)) - one
403 } else {
404 Self::default()
405 }
406 }
407
408 #[inline]
412 pub fn comp_ne(self, rhs: Self) -> Self {
413 let a: BigInt = self.into();
414 let b: BigInt = rhs.into();
415 if a != b {
416 let one = Self::from_literal(1);
417 (one << ($bits - 1)) - one
418 } else {
419 Self::default()
420 }
421 }
422
423 #[inline]
427 pub fn comp_gte(self, rhs: Self) -> Self {
428 let a: BigInt = self.into();
429 let b: BigInt = rhs.into();
430 if a >= b {
431 let one = Self::from_literal(1);
432 (one << ($bits - 1)) - one
433 } else {
434 Self::default()
435 }
436 }
437
438 #[inline]
442 pub fn comp_gt(self, rhs: Self) -> Self {
443 let a: BigInt = self.into();
444 let b: BigInt = rhs.into();
445 if a > b {
446 let one = Self::from_literal(1);
447 (one << ($bits - 1)) - one
448 } else {
449 Self::default()
450 }
451 }
452
453 #[inline]
457 pub fn comp_lte(self, rhs: Self) -> Self {
458 let a: BigInt = self.into();
459 let b: BigInt = rhs.into();
460 if a <= b {
461 let one = Self::from_literal(1);
462 (one << ($bits - 1)) - one
463 } else {
464 Self::default()
465 }
466 }
467
468 #[inline]
472 pub fn comp_lt(self, rhs: Self) -> Self {
473 let a: BigInt = self.into();
474 let b: BigInt = rhs.into();
475 if a < b {
476 let one = Self::from_literal(1);
477 (one << ($bits - 1)) - one
478 } else {
479 Self::default()
480 }
481 }
482 }
483 };
484}
485
486#[macro_export]
487macro_rules! abstract_signed {
488 ($name:ident, $bits:literal) => {
489 abstract_int!($name, $bits, true);
490
491 impl $name {
492 #[allow(dead_code)]
493 pub fn from_hex(sign: &str, s: &str) -> Self {
494 let sign = match sign {
495 "+" => Sign::Plus,
496 "-" => Sign::Minus,
497 "" => Sign::NoSign,
498 _ => panic!("from_hex requires the first argument to be + or -"),
499 };
500 BigInt::from_bytes_be(sign, &Self::hex_string_to_bytes(s)).into()
501 }
502 }
503 };
504}
505
506#[macro_export]
507macro_rules! abstract_unsigned_public_integer {
508 ($name:ident, $bits:literal) => {
509 abstract_unsigned!($name, $bits);
510 abstract_public!($name);
511 };
512}
513
514#[macro_export]
515macro_rules! abstract_signed_public_integer {
516 ($name:ident, $bits:literal) => {
517 abstract_signed!($name, $bits);
518 abstract_public!($name);
519 };
520}
521
522#[macro_export]
524macro_rules! abstract_secret {
525 ($name:ident, $bits:literal) => {
526 impl $name {
527 pub fn declassify(self) -> BigInt {
528 self.into()
529 }
530
531 fn rem(self, n: Self) -> Self {
532 let a: BigInt = self.into();
533 let b: BigInt = n.into();
534 if b == BigInt::zero() {
535 panic!("dividing by zero in type {}", stringify!($name));
536 }
537 let c = a % b;
538 c.into()
539 }
540 }
541
542 impl Add for $name {
544 type Output = $name;
545 fn add(self, rhs: $name) -> $name {
546 let a: BigInt = self.into();
547 let b: BigInt = rhs.into();
548 let c = a + b;
549 if c > $name::max() {
550 panic!("bounded addition overflow for type {}", stringify!($name));
551 }
552 c.into()
553 }
554 }
555
556 impl Sub for $name {
558 type Output = $name;
559 fn sub(self, rhs: $name) -> $name {
560 let a: BigInt = self.into();
561 let b: BigInt = rhs.into();
562 let c = a.checked_sub(&b).unwrap_or_else(|| {
563 panic!(
564 "bounded substraction underflow for type {}",
565 stringify!($name)
566 )
567 });
568 c.into()
569 }
570 }
571
572 impl Mul for $name {
574 type Output = $name;
575 fn mul(self, rhs: $name) -> $name {
576 let a: BigInt = self.into();
577 let b: BigInt = rhs.into();
578 let c = a * b;
579 if c > $name::max() {
580 panic!(
581 "bounded multiplication overflow for type {}",
582 stringify!($name)
583 );
584 }
585 c.into()
586 }
587 }
588
589 impl Not for $name {
590 type Output = $name;
591 fn not(self) -> Self::Output {
592 unimplemented!();
593 }
594 }
595
596 impl BitOr for $name {
597 type Output = $name;
598 fn bitor(self, rhs: Self) -> Self::Output {
599 let a: BigInt = self.into();
600 let b: BigInt = rhs.into();
601 (a | b).into()
602 }
603 }
604
605 impl BitXor for $name {
606 type Output = $name;
607 fn bitxor(self, rhs: Self) -> Self::Output {
608 let a: BigInt = self.into();
609 let b: BigInt = rhs.into();
610 (a ^ b).into()
611 }
612 }
613
614 impl BitAnd for $name {
615 type Output = $name;
616 fn bitand(self, rhs: Self) -> Self::Output {
617 let a: BigInt = self.into();
618 let b: BigInt = rhs.into();
619 (a & b).into()
620 }
621 }
622
623 impl Shr<usize> for $name {
624 type Output = $name;
625 fn shr(self, rhs: usize) -> Self::Output {
626 let a: BigInt = self.into();
627 (a >> rhs).into()
628 }
629 }
630
631 impl Shl<usize> for $name {
632 type Output = $name;
633 fn shl(self, rhs: usize) -> Self::Output {
634 let a: BigInt = self.into();
635 (a << rhs).into()
636 }
637 }
638 };
639}
640
641#[macro_export]
642macro_rules! abstract_unsigned_secret_integer {
643 ($name:ident, $bits:literal) => {
644 abstract_unsigned!($name, $bits);
645 abstract_secret!($name, $bits);
646 };
647}
648
649#[macro_export]
650macro_rules! abstract_signed_secret_integer {
651 ($name:ident, $bits:literal) => {
652 abstract_signed!($name, $bits);
653 abstract_secret!($name, $bits);
654 };
655}
656
657#[macro_export]
662macro_rules! define_abstract_integer_checked {
663 ($name:ident, $bits:literal) => {
664 abstract_unsigned_public_integer!($name, $bits);
665 };
666}