fp/vector/fp_wrapper/
macros_generic.rs

1/// Use all primes. It isn't possible to have this import when `odd-primes` is disabled because
2/// primes other than P2 and ValidPrime (which happen to be the same type) do not exist.
3macro_rules! use_primes {
4    () => {
5        use crate::{
6            field::fp::{F2, F3, F5, F7},
7            prime::{P2, P3, P5, P7, ValidPrime},
8        };
9    };
10}
11
12/// Define a struct that wraps some field-dependent type in an enum. Since `Fp<P2>` through `Fp<P7>`
13/// are all ZSTs, working with them under the hood is in theory much faster than working with an
14/// arbitrary prime field, let alone finite field.
15macro_rules! dispatch_struct {
16    ($(#[derive $derives:tt])? $vis:vis $name:ident $(<$life:lifetime>)? from $fq_name:ident) => {
17        $(#[derive $derives])*
18        $vis enum $name $(<$life>)? {
19            _2($fq_name<$($life,)? Fp<P2>>),
20            _3($fq_name<$($life,)? Fp<P3>>),
21            _5($fq_name<$($life,)? Fp<P5>>),
22            _7($fq_name<$($life,)? Fp<P7>>),
23            Big($fq_name<$($life,)? Fp<ValidPrime>>),
24        }
25    };
26}
27
28macro_rules! dispatch_vector_inner {
29    // other is a type, but marking it as a :ty instead of :tt means we cannot use it to access its
30    // enum variants.
31    ($vis:vis fn $method:ident $helper_method:ident(&self, other: &$other:tt $(, $arg:ident: $ty:ty )* ) $(-> $ret:ty)?) => {
32        $vis fn $method(&self, other: &$other, $($arg: $ty),* ) $(-> $ret)* {
33            match (self, other) {
34                (Self::_2(x), $other::_2(y)) => x.$helper_method(y, $($arg),*),
35                (Self::_3(x), $other::_3(y)) => x.$helper_method(y, $($arg),*),
36                (Self::_5(x), $other::_5(y)) => x.$helper_method(y, $($arg),*),
37                (Self::_7(x), $other::_7(y)) => x.$helper_method(y, $($arg),*),
38                (Self::Big(x), $other::Big(y)) if x.prime() == y.prime() => x.$helper_method(y, $($arg),*),
39                (l, r) => {
40                    panic!("Applying {} to vectors over different primes ({} and {})", stringify!($method), l.prime(), r.prime());
41                }
42            }
43        }
44    };
45    ($vis:vis fn $method:ident $helper_method:ident(&mut self, other: &$other:tt $(, $arg:ident: $ty:ty )* ) $(-> $ret:ty)?) => {
46        #[allow(unused_parens)]
47        $vis fn $method(&mut self, other: &$other, $($arg: $ty),* ) $(-> $ret)* {
48            match (self, other) {
49                (Self::_2(x), $other::_2(y)) => x.$helper_method(y, $($arg),*),
50                (Self::_3(x), $other::_3(y)) => x.$helper_method(y, $($arg),*),
51                (Self::_5(x), $other::_5(y)) => x.$helper_method(y, $($arg),*),
52                (Self::_7(x), $other::_7(y)) => x.$helper_method(y, $($arg),*),
53                (Self::Big(x), $other::Big(y)) if x.prime() == y.prime() => x.$helper_method(y, $($arg),*),
54                (l, r) => {
55                    panic!("Applying {} to vectors over different primes ({} and {})", stringify!($method), l.prime(), r.prime());
56                }
57            }
58        }
59    };
60    ($vis:vis fn $method:ident $helper_method:ident(&mut self, other: $other:tt $(, $arg:ident: $ty:ty )* ) $(-> $ret:ty)?) => {
61        $vis fn $method(&mut self, other: $other, $($arg: $ty),* ) $(-> $ret)* {
62            match (self, other) {
63                (Self::_2(x), $other::_2(y)) => x.$helper_method(y, $($arg),*),
64                (Self::_3(x), $other::_3(y)) => x.$helper_method(y, $($arg),*),
65                (Self::_5(x), $other::_5(y)) => x.$helper_method(y, $($arg),*),
66                (Self::_7(x), $other::_7(y)) => x.$helper_method(y, $($arg),*),
67                (Self::Big(x), $other::Big(y)) if x.prime() == y.prime() => x.$helper_method(y, $($arg),*),
68                (l, r) => {
69                    panic!("Applying {} to vectors over different primes ({} and {})", stringify!($method), l.prime(), r.prime());
70                }
71            }
72        }
73    };
74    ($vis:vis fn $method:ident $helper_method:ident(&mut self $(, $arg:ident: $ty:ty )*, @left: $other1:tt, right: $other2:tt ) $(-> $ret:ty)?) => {
75        #[allow(unused_parens)]
76        $vis fn $method(&mut self, $($arg: $ty),* , left: $other1, right: $other2 ) $(-> $ret)* {
77            match (self, left, right) {
78                (Self::_2(x), $other1::_2(y), $other2::_2(z)) => x.$helper_method($($arg),*, y, z),
79                (Self::_3(x), $other1::_3(y), $other2::_3(z)) => x.$helper_method($($arg),*, y, z),
80                (Self::_5(x), $other1::_5(y), $other2::_5(z)) => x.$helper_method($($arg),*, y, z),
81                (Self::_7(x), $other1::_7(y), $other2::_7(z)) => x.$helper_method($($arg),*, y, z),
82                (Self::Big(x), $other1::Big(y), $other2::Big(z)) if x.prime() == y.prime() && y.prime() == z.prime() => x.$helper_method($($arg),*, y, z),
83                _ => {
84                    panic!("Applying {} to vectors over different primes", stringify!($method));
85                }
86            }
87        }
88    };
89    ($vis:vis fn $method:ident $helper_method:ident(&mut self $(, $arg:ident: $ty:ty )* ) -> (dispatch $ret:path)) => {
90        #[must_use]
91        $vis fn $method(&mut self, $($arg: $ty),* ) -> $ret {
92            match self {
93                Self::_2(x) => <$ret>::_2(x.$helper_method($($arg),*)),
94                Self::_3(x) => <$ret>::_3(x.$helper_method($($arg),*)),
95                Self::_5(x) => <$ret>::_5(x.$helper_method($($arg),*)),
96                Self::_7(x) => <$ret>::_7(x.$helper_method($($arg),*)),
97                Self::Big(x) => <$ret>::Big(x.$helper_method($($arg),*)),
98            }
99        }
100    };
101    ($vis:vis fn $method:ident $helper_method:ident(&self $(, $arg:ident: $ty:ty )* ) -> (dispatch $ret:path)) => {
102        #[must_use]
103        $vis fn $method(&self, $($arg: $ty),* ) -> $ret {
104            match self {
105                Self::_2(x) => <$ret>::_2(x.$helper_method($($arg),*)),
106                Self::_3(x) => <$ret>::_3(x.$helper_method($($arg),*)),
107                Self::_5(x) => <$ret>::_5(x.$helper_method($($arg),*)),
108                Self::_7(x) => <$ret>::_7(x.$helper_method($($arg),*)),
109                Self::Big(x) => <$ret>::Big(x.$helper_method($($arg),*)),
110            }
111        }
112    };
113    ($vis:vis fn $method:ident $helper_method:ident(self $(, $arg:ident: $ty:ty )* ) -> (dispatch $ret:path)) => {
114        #[must_use]
115        $vis fn $method(self, $($arg: $ty),* ) -> $ret {
116            match self {
117                Self::_2(x) => <$ret>::_2(x.$helper_method($($arg),*)),
118                Self::_3(x) => <$ret>::_3(x.$helper_method($($arg),*)),
119                Self::_5(x) => <$ret>::_5(x.$helper_method($($arg),*)),
120                Self::_7(x) => <$ret>::_7(x.$helper_method($($arg),*)),
121                Self::Big(x) => <$ret>::Big(x.$helper_method($($arg),*)),
122            }
123        }
124    };
125    ($vis:vis fn $method:ident $helper_method:ident(&mut self $(, $arg:ident: $ty:ty )* ) $(-> $ret:ty)?) => {
126        #[allow(unused_parens)]
127        $vis fn $method(&mut self, $($arg: $ty),* ) $(-> $ret)* {
128            match self {
129                Self::_2(x) => x.$helper_method($($arg),*),
130                Self::_3(x) => x.$helper_method($($arg),*),
131                Self::_5(x) => x.$helper_method($($arg),*),
132                Self::_7(x) => x.$helper_method($($arg),*),
133                Self::Big(x) => x.$helper_method($($arg),*),
134            }
135        }
136    };
137    ($vis:vis fn $method:ident $helper_method:ident(&self $(, $arg:ident: $ty:ty )* ) $(-> $ret:ty)?) => {
138        #[allow(unused_parens)]
139        $vis fn $method(&self, $($arg: $ty),* ) $(-> $ret)* {
140            match self {
141                Self::_2(x) => x.$helper_method($($arg),*),
142                Self::_3(x) => x.$helper_method($($arg),*),
143                Self::_5(x) => x.$helper_method($($arg),*),
144                Self::_7(x) => x.$helper_method($($arg),*),
145                Self::Big(x) => x.$helper_method($($arg),*),
146            }
147        }
148    };
149    ($vis:vis fn $method:ident $helper_method:ident(self $(, $arg:ident: $ty:ty )* ) $(-> $ret:ty)?) => {
150        #[allow(unused_parens)]
151        $vis fn $method(self, $($arg: $ty),* ) $(-> $ret)* {
152            match self {
153                Self::_2(x) => x.$helper_method($($arg),*),
154                Self::_3(x) => x.$helper_method($($arg),*),
155                Self::_5(x) => x.$helper_method($($arg),*),
156                Self::_7(x) => x.$helper_method($($arg),*),
157                Self::Big(x) => x.$helper_method($($arg),*),
158            }
159        }
160    };
161}
162
163macro_rules! dispatch_vector {
164    () => {};
165    ($vis:vis fn $method:ident $tt:tt $(-> $ret:tt)?; $($tail:tt)*) => {
166        dispatch_vector_inner! {
167            $vis fn $method $method $tt $(-> $ret)*
168        }
169        dispatch_vector!{$($tail)*}
170    };
171    ($vis:vis fn @$method:ident $tt:tt $(-> $ret:tt)?; $($tail:tt)*) => {
172        paste::paste! {
173            dispatch_vector_inner! {
174                $vis fn $method [<$method _helper>] $tt $(-> $ret)*
175            }
176        }
177        dispatch_vector!{$($tail)*}
178    };
179    // Special-case the constructors
180    ($vis:vis fn $method:ident <P: Prime> (p: P $(, $arg:ident: $ty:ty )*) -> (from $fq_name:tt); $($tail:tt)*) => {
181        $vis fn $method<P: Prime>(p: P, $($arg: $ty),*) -> Self {
182            match p.as_u32() {
183                2 => Self::_2($fq_name::$method(F2, $($arg),*)),
184                3 => Self::_3($fq_name::$method(F3, $($arg),*)),
185                5 => Self::_5($fq_name::$method(F5, $($arg),*)),
186                7 => Self::_7($fq_name::$method(F7, $($arg),*)),
187                _ => Self::Big($fq_name::$method(Fp::new(p.to_dyn()), $($arg),*)),
188            }
189        }
190        dispatch_vector!{$($tail)*}
191    };
192    // Special-case update_from_bytes
193    ($vis:vis fn $method:ident <P: Prime> (p: P $(, $arg:ident: $ty:ty )*) -> (from io $fq_name:tt); $($tail:tt)*) => {
194        $vis fn $method<P: Prime>(p: P, $($arg: $ty),*) -> std::io::Result<Self> {
195            Ok(match p.as_u32() {
196                2 => Self::_2($fq_name::$method(F2, $($arg),*)?),
197                3 => Self::_3($fq_name::$method(F3, $($arg),*)?),
198                5 => Self::_5($fq_name::$method(F5, $($arg),*)?),
199                7 => Self::_7($fq_name::$method(F7, $($arg),*)?),
200                _ => Self::Big($fq_name::$method(Fp::new(p.to_dyn()), $($arg),*)?),
201            })
202        }
203        dispatch_vector!{$($tail)*}
204    }
205}
206
207macro_rules! impl_from_inner {
208    ($var:tt, $p:ty) => {
209        impl<'a> From<FqVector<Fp<$p>>> for FpVector {
210            fn from(x: FqVector<Fp<$p>>) -> Self {
211                FpVector::$var(x)
212            }
213        }
214    };
215}
216
217macro_rules! impl_from {
218    () => {
219        impl_from_inner!(_2, P2);
220        impl_from_inner!(_3, P3);
221        impl_from_inner!(_5, P5);
222        impl_from_inner!(_7, P7);
223        impl_from_inner!(Big, ValidPrime);
224    };
225}
226
227macro_rules! impl_try_into_inner {
228    ($var:tt, $p:ty) => {
229        impl<'a> TryInto<&'a mut FqVector<Fp<$p>>> for &'a mut FpVector {
230            type Error = ();
231
232            fn try_into(self) -> Result<&'a mut FqVector<Fp<$p>>, Self::Error> {
233                match self {
234                    FpVector::$var(x) => Ok(x),
235                    _ => Err(()),
236                }
237            }
238        }
239    };
240}
241
242macro_rules! impl_try_into {
243    () => {
244        impl_try_into_inner!(_2, P2);
245        impl_try_into_inner!(_3, P3);
246        impl_try_into_inner!(_5, P5);
247        impl_try_into_inner!(_7, P7);
248        impl_try_into_inner!(Big, ValidPrime);
249    };
250}
251
252pub(super) use dispatch_struct;
253pub(super) use dispatch_vector;
254pub(super) use impl_try_into;
255pub(super) use use_primes;