1use crate::BigNumber;
6
7use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
8
9pub struct Group {
12 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 pub fn neg(&self, rhs: &BigNumber) -> BigNumber {
123 rhs.modneg(&self.modulus)
124 }
125
126 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 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}