1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/// basic operation reference macro
// TODO: integrate to field macro
#[macro_export]
macro_rules! ref_ops {
    ($t:ident) => {
        impl<'a, 'b> Add<&'b $t> for &'a $t {
            type Output = $t;

            fn add(self, rhs: &'b $t) -> $t {
                $t(add(self.0, rhs.0, $p))
            }
        }

        impl<'a> Add<$t> for &'a $t {
            type Output = $t;

            fn add(self, rhs: $t) -> $t {
                $t(add(self.0, rhs.0, $p))
            }
        }

        impl<'b> AddAssign<&'b $t> for $t {
            fn add_assign(&mut self, rhs: &'b $t) {
                *self = $t(add(self.0, rhs.0, $p))
            }
        }

        impl<'b> Add<&'b $t> for $t {
            type Output = $t;

            fn add(self, rhs: &'b $t) -> Self {
                $t(add(self.0, rhs.0, $p))
            }
        }

        impl<'b> MulAssign<&'b $t> for $t {
            fn mul_assign(&mut self, rhs: &'b $t) {
                *self = &*self * rhs;
            }
        }

        impl<'a, 'b> Mul<&'b $t> for &'a $t {
            type Output = $t;

            fn mul(self, rhs: &'b $t) -> $t {
                $t(mul(self.0, rhs.0, $p, $inv))
            }
        }

        impl<'b> Mul<&'b $t> for $t {
            type Output = $t;

            fn mul(self, rhs: &'b $t) -> $t {
                $t(mul(self.0, rhs.0, $p, $inv))
            }
        }

        impl<'a> Mul<$t> for &'a $t {
            type Output = $t;

            fn mul(self, rhs: $t) -> $t {
                $t(mul(self.0, rhs.0, $p, $inv))
            }
        }

        impl<'a> Neg for &'a $t {
            type Output = $t;

            fn neg(self) -> $t {
                -self
            }
        }

        impl<'b> SubAssign<&'b $t> for $t {
            fn sub_assign(&mut self, rhs: &'b $t) {
                *self = $t(sub(self.0, rhs.0, $p))
            }
        }

        impl<'a, 'b> Sub<&'b $t> for &'a $t {
            type Output = $t;

            fn sub(self, rhs: &'b $t) -> $t {
                $t(sub(self.0, rhs.0, $p))
            }
        }

        impl<'b> Sub<&'b $t> for $t {
            type Output = $t;

            fn sub(self, rhs: &'b $t) -> $t {
                $t(sub(self.0, rhs.0, $p))
            }
        }

        impl<'a> Sub<$t> for &'a $t {
            type Output = $t;

            fn sub(self, rhs: $t) -> $t {
                $t(sub(self.0, rhs.0, $p))
            }
        }
    };
}

pub use ref_ops;