1use std::{
2 hash::Hash,
3 ops::{Add, AddAssign, Deref, Div, Mul, MulAssign, Neg, Sub, SubAssign},
4};
5
6use super::{Field, field_internal::FieldInternal};
7
8pub trait FieldElementContainer:
11 std::fmt::Debug + std::fmt::Display + Clone + PartialEq + Eq + Hash
12{
13}
14
15#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
30pub struct FieldElement<F: FieldInternal> {
31 field: F,
32 pub(super) value: F::ElementContainer,
33}
34
35impl<F: FieldInternal> FieldElement<F> {
36 pub(super) fn new(field: F, value: F::ElementContainer) -> Self {
42 Self { field, value }
43 }
44
45 pub fn field(&self) -> F {
46 self.field
47 }
48
49 pub(crate) fn val(self) -> F::ElementContainer {
50 self.value
51 }
52
53 pub fn inv(self) -> Option<Self> {
54 self.field.inv(self)
55 }
56
57 pub fn frobenius(self) -> Self {
58 self.field.frobenius(self)
59 }
60}
61
62impl<F: FieldInternal> Deref for FieldElement<F> {
64 type Target = F::ElementContainer;
65
66 fn deref(&self) -> &Self::Target {
67 &self.value
68 }
69}
70
71macro_rules! impl_arith {
72 ($trait:ident, $trait_assign:ident, $method:ident, $method_assign:ident) => {
73 impl<F: Field> $trait for FieldElement<F> {
74 type Output = Self;
75
76 fn $method(self, rhs: Self) -> Self::Output {
77 self.field.$method(self, rhs)
78 }
79 }
80
81 impl<F: Field> $trait_assign for FieldElement<F> {
82 fn $method_assign(&mut self, rhs: Self) {
83 self.field.$method_assign(self, rhs);
84 }
85 }
86 };
87}
88
89impl_arith!(Add, AddAssign, add, add_assign);
90impl_arith!(Sub, SubAssign, sub, sub_assign);
91impl_arith!(Mul, MulAssign, mul, mul_assign);
92
93impl<F: Field> Div for FieldElement<F> {
94 type Output = Option<Self>;
95
96 fn div(self, rhs: Self) -> Self::Output {
97 self.field.div(self, rhs)
98 }
99}
100
101impl<F: Field> Neg for FieldElement<F> {
102 type Output = Self;
103
104 fn neg(self) -> Self::Output {
105 self.field.neg(self)
106 }
107}
108
109impl<F: Field> std::fmt::Display for FieldElement<F> {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 write!(f, "{}", self.value)
112 }
113}