1use std::mem::size_of;
10use std::ops::{Add, AddAssign};
11
12use crate::Group;
13
14macro_rules! decl_int_prime_group {
15 ($t:ty, $t_impl:ident) => {
16 #[derive(Debug, Clone, PartialEq, Eq)]
18 pub struct $t_impl<const MOD: $t>(
19 $t,
21 );
22
23 impl<const MOD: $t> $t_impl<MOD> {
24 pub fn new(x: $t) -> Self {
25 $t_impl(x % MOD)
26 }
27 }
28
29 impl<const MOD: $t> Add for $t_impl<MOD> {
30 type Output = Self;
31
32 fn add(self, rhs: Self) -> Self::Output {
33 $t_impl(match self.0.checked_add(rhs.0) {
34 Some(x) => x % MOD,
35 None => {
36 (self.0.wrapping_add(rhs.0) % MOD)
37 .wrapping_add(<$t>::MAX % MOD)
38 .wrapping_add(1)
39 % MOD
40 }
41 })
42 }
43 }
44
45 impl<const MOD: $t> AddAssign for $t_impl<MOD> {
46 fn add_assign(&mut self, rhs: Self) {
47 self.0 = match self.0.checked_add(rhs.0) {
48 Some(x) => x % MOD,
49 None => {
50 self.0
51 .wrapping_add(rhs.0)
52 .wrapping_add(<$t>::MAX % MOD)
53 .wrapping_add(1)
54 % MOD
55 }
56 };
57 }
58 }
59
60 impl<const LAMBDA: usize, const MOD: $t> Group<LAMBDA> for $t_impl<MOD> {
61 fn zero() -> Self {
62 $t_impl(0)
63 }
64
65 fn add_inverse(mut self) -> Self {
66 self.0 = match self.0.checked_add(MOD) {
67 Some(x) => x % MOD,
68 None => {
69 self.0
70 .wrapping_add(MOD)
71 .wrapping_add(<$t>::MAX % MOD)
72 .wrapping_add(1)
73 % MOD
74 }
75 };
76 self
77 }
78 }
79
80 impl<const LAMBDA: usize, const MOD: $t> From<[u8; LAMBDA]> for $t_impl<MOD> {
81 fn from(value: [u8; LAMBDA]) -> Self {
82 if cfg!(not(feature = "int-be")) {
83 $t_impl(<$t>::from_le_bytes(
84 (&value[..size_of::<$t>()]).clone().try_into().unwrap(),
85 ))
86 } else {
87 $t_impl(<$t>::from_be_bytes(
88 (&value[..size_of::<$t>()]).clone().try_into().unwrap(),
89 ))
90 }
91 }
92 }
93
94 impl<const LAMBDA: usize, const MOD: $t> From<$t_impl<MOD>> for [u8; LAMBDA] {
95 fn from(value: $t_impl<MOD>) -> Self {
96 let mut bs = [0; LAMBDA];
97 if cfg!(not(feature = "int-be")) {
98 bs[..size_of::<$t>()].copy_from_slice(&value.0.to_le_bytes());
99 } else {
100 bs[..size_of::<$t>()].copy_from_slice(&value.0.to_be_bytes());
101 }
102 bs
103 }
104 }
105 };
106}
107
108decl_int_prime_group!(u8, U8Group);
109decl_int_prime_group!(u16, U16Group);
110decl_int_prime_group!(u32, U32Group);
111decl_int_prime_group!(u64, U64Group);
112decl_int_prime_group!(u128, U128Group);
113
114pub const PRIME_MAX_LE_U8_MAX: u8 = u8::MAX - 5 + 1;
115pub const PRIME_MAX_LE_U16_MAX: u16 = u16::MAX - 15 + 1;
116pub const PRIME_MAX_LE_U32_MAX: u32 = u32::MAX - 5 + 1;
117pub const PRIME_MAX_LE_U64_MAX: u64 = u64::MAX - 59 + 1;
118pub const PRIME_MAX_LE_U128_MAX: u128 = u128::MAX - 159 + 1;