decaf377/fields/fp/u64/
wrapper.rs

1use ark_bls12_377::Fq as ArkworksFp;
2use ark_ff::{BigInt, Field, PrimeField};
3use ark_serialize::CanonicalSerialize;
4
5use super::super::{N_64, N_8};
6
7const N: usize = N_64;
8
9#[derive(Copy, Clone)]
10pub struct Fp(ArkworksFp);
11
12impl PartialEq for Fp {
13    fn eq(&self, other: &Self) -> bool {
14        self.0 == other.0
15    }
16}
17
18impl Eq for Fp {}
19
20impl zeroize::Zeroize for Fp {
21    fn zeroize(&mut self) {
22        self.0 .0.zeroize()
23    }
24}
25
26impl Fp {
27    pub(crate) fn from_le_limbs(limbs: [u64; N_64]) -> Fp {
28        let mut bytes = [0u8; N_8];
29        for i in 0..N_64 {
30            let this_byte = limbs[i].to_le_bytes();
31            for j in 0..8 {
32                bytes[8 * i + j] = this_byte[j];
33            }
34        }
35
36        Self::from_raw_bytes(&bytes)
37    }
38
39    pub(crate) fn from_raw_bytes(bytes: &[u8; N_8]) -> Fp {
40        Self(ArkworksFp::from_le_bytes_mod_order(bytes))
41    }
42
43    pub(crate) fn to_le_limbs(&self) -> [u64; N_64] {
44        let le_bytes = self.to_bytes_le();
45        let mut out = [0u64; N_64];
46        for i in 0..N_64 {
47            out[i] = u64::from_le_bytes([
48                le_bytes[8 * i],
49                le_bytes[8 * i + 1],
50                le_bytes[8 * i + 2],
51                le_bytes[8 * i + 3],
52                le_bytes[8 * i + 4],
53                le_bytes[8 * i + 5],
54                le_bytes[8 * i + 6],
55                le_bytes[8 * i + 7],
56            ]);
57        }
58        out
59    }
60
61    pub fn to_bytes_le(&self) -> [u8; N_8] {
62        let mut bytes = [0u8; 48];
63        self.0
64            .serialize_compressed(&mut bytes[..])
65            .expect("serialization into array should be infallible");
66        bytes
67    }
68
69    pub(crate) const fn from_montgomery_limbs(limbs: [u64; N]) -> Fp {
70        Self(ArkworksFp::new_unchecked(BigInt(limbs)))
71    }
72
73    pub const ZERO: Self = Self(ArkworksFp::new(BigInt::new([0; N])));
74    pub const ONE: Self = Self(ArkworksFp::new(BigInt::one()));
75
76    pub const MINUS_ONE: Self = Self::from_montgomery_limbs([
77        9384023879812382873,
78        14252412606051516495,
79        9184438906438551565,
80        11444845376683159689,
81        8738795276227363922,
82        81297770384137296,
83    ]);
84
85    pub const QUADRATIC_NON_RESIDUE: Self = Self::from_montgomery_limbs([
86        18161750659790013178,
87        10940260503947051403,
88        2338003791965605956,
89        14680817040264804354,
90        841925479686732267,
91        43193913801202386,
92    ]);
93
94    pub fn square(&self) -> Fp {
95        Fp(self.0.square())
96    }
97
98    pub fn inverse(&self) -> Option<Self> {
99        if self == &Self::ZERO {
100            return None;
101        }
102
103        Some(Fp(self.0.inverse()?))
104    }
105
106    pub fn add(self, other: &Fp) -> Fp {
107        Fp(self.0 + other.0)
108    }
109
110    pub fn sub(self, other: &Fp) -> Fp {
111        Fp(self.0 - other.0)
112    }
113
114    pub fn mul(self, other: &Fp) -> Fp {
115        Fp(self.0 * other.0)
116    }
117
118    pub fn neg(self) -> Fp {
119        Fp(-self.0)
120    }
121}