Skip to main content

unknown_order/
group.rs

1/*
2    Copyright Michael Lodder. All Rights Reserved.
3    SPDX-License-Identifier: Apache-2.0
4*/
5use crate::BigNumber;
6
7use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
8
9/// Represents a cyclic group where all operations are reduced by a modulus.
10/// Purely a convenience struct to avoid having to call mod{ops}
11pub struct Group {
12    /// The upper limit that all values in the group are to be reduced
13    pub modulus: BigNumber,
14}
15
16macro_rules! binops_group {
17    ($ops:ident, $func:ident, $opr:ident) => {
18        impl<'a, 'b, 'c> $ops<(&'a BigNumber, &'b BigNumber)> for &'c Group {
19            type Output = BigNumber;
20
21            fn $func(self, pair: (&'a BigNumber, &'b BigNumber)) -> Self::Output {
22                pair.0.$opr(pair.1, &self.modulus)
23            }
24        }
25
26        impl<'a, 'c> $ops<(&'a BigNumber, BigNumber)> for &'c Group {
27            type Output = BigNumber;
28
29            fn $func(self, pair: (&'a BigNumber, BigNumber)) -> Self::Output {
30                self.$func((pair.0, &pair.1))
31            }
32        }
33
34        impl<'b, 'c> $ops<(BigNumber, &'b BigNumber)> for &'c Group {
35            type Output = BigNumber;
36
37            fn $func(self, pair: (BigNumber, &'b BigNumber)) -> Self::Output {
38                self.$func((&pair.0, pair.1))
39            }
40        }
41
42        impl<'c> $ops<(BigNumber, BigNumber)> for &'c Group {
43            type Output = BigNumber;
44
45            fn $func(self, pair: (BigNumber, BigNumber)) -> Self::Output {
46                self.$func((&pair.0, &pair.1))
47            }
48        }
49
50        impl<'a, 'b> $ops<(&'a BigNumber, &'b BigNumber)> for Group {
51            type Output = BigNumber;
52
53            fn $func(self, pair: (&'a BigNumber, &'b BigNumber)) -> Self::Output {
54                (&self).$func(pair)
55            }
56        }
57
58        impl<'a> $ops<(&'a BigNumber, BigNumber)> for Group {
59            type Output = BigNumber;
60
61            fn $func(self, pair: (&'a BigNumber, BigNumber)) -> Self::Output {
62                (&self).$func((pair.0, &pair.1))
63            }
64        }
65
66        impl<'b> $ops<(BigNumber, &'b BigNumber)> for Group {
67            type Output = BigNumber;
68
69            fn $func(self, pair: (BigNumber, &'b BigNumber)) -> Self::Output {
70                (&self).$func((&pair.0, pair.1))
71            }
72        }
73
74        impl $ops<(BigNumber, BigNumber)> for Group {
75            type Output = BigNumber;
76
77            fn $func(self, pair: (BigNumber, BigNumber)) -> Self::Output {
78                (&self).$func((&pair.0, &pair.1))
79            }
80        }
81    };
82}
83macro_rules! binops_group_assign {
84    ($ops:ident, $func:ident, $opr:ident) => {
85        impl<'a, 'b, 'c> $ops<(&'a mut BigNumber, &'b BigNumber)> for &'c Group {
86            fn $func(&mut self, pair: (&'a mut BigNumber, &'b BigNumber)) {
87                *pair.0 = pair.0.$opr(pair.1, &self.modulus);
88            }
89        }
90
91        impl<'a, 'c> $ops<(&'a mut BigNumber, BigNumber)> for &'c Group {
92            fn $func(&mut self, pair: (&'a mut BigNumber, BigNumber)) {
93                (*self).$func((pair.0, &pair.1))
94            }
95        }
96
97        impl<'a, 'b> $ops<(&'a mut BigNumber, &'b BigNumber)> for Group {
98            fn $func(&mut self, pair: (&'a mut BigNumber, &'b BigNumber)) {
99                *pair.0 = pair.0.$opr(pair.1, &self.modulus);
100            }
101        }
102
103        impl<'a> $ops<(&'a mut BigNumber, BigNumber)> for Group {
104            fn $func(&mut self, pair: (&'a mut BigNumber, BigNumber)) {
105                (*self).$func((pair.0, &pair.1))
106            }
107        }
108    };
109}
110
111binops_group!(Add, add, modadd);
112binops_group!(Sub, sub, modsub);
113binops_group!(Mul, mul, modmul);
114binops_group!(Div, div, moddiv);
115binops_group_assign!(AddAssign, add_assign, modadd);
116binops_group_assign!(SubAssign, sub_assign, modsub);
117binops_group_assign!(MulAssign, mul_assign, modmul);
118binops_group_assign!(DivAssign, div_assign, moddiv);
119
120impl Group {
121    /// Compute -rhs mod self
122    pub fn neg(&self, rhs: &BigNumber) -> BigNumber {
123        rhs.modneg(&self.modulus)
124    }
125
126    /// Compute the sum of the the bignumbers in the group
127    pub fn sum<I>(&self, nums: I) -> BigNumber
128    where
129        I: AsRef<[BigNumber]>,
130    {
131        let mut r = BigNumber::zero();
132        for a in nums.as_ref() {
133            r = r.modadd(a, &self.modulus);
134        }
135        r
136    }
137
138    /// Compute the product of the the bignumbers in the group
139    pub fn product<I>(&self, nums: I) -> BigNumber
140    where
141        I: AsRef<[BigNumber]>,
142    {
143        let mut r = BigNumber::zero();
144        for a in nums.as_ref() {
145            r = r.modmul(a, &self.modulus);
146        }
147        r
148    }
149}