1#![allow(clippy::module_inception)]
17#![forbid(unsafe_code)]
18
19#[macro_use]
20extern crate thiserror;
21
22#[macro_use]
23mod macros;
24
25pub mod errors;
26pub use errors::*;
27
28mod fp_256;
29pub use fp_256::*;
30
31mod fp_384;
32pub use fp_384::*;
33
34mod fp2;
35pub use fp2::*;
36
37pub mod fp6_3over2;
38
39mod fp12_2over3over2;
40pub use fp12_2over3over2::*;
41
42mod legendre;
43pub use legendre::*;
44
45mod to_field_vec;
46#[allow(unused_imports)]
47pub use to_field_vec::*;
48
49pub mod traits;
50pub use traits::*;
51
52use snarkvm_utilities::{
53 FromBytes,
54 ToBytes,
55 biginteger::*,
56 serialize::{CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize, CanonicalSerializeWithFlags},
57};
58
59impl_field_to_biginteger!(Fp256, BigInteger256, Fp256Parameters);
60impl_field_to_biginteger!(Fp384, BigInteger384, Fp384Parameters);
61
62impl_primefield_serializer!(Fp256, Fp256Parameters, 32);
63impl_primefield_serializer!(Fp384, Fp384Parameters, 48);
64
65pub fn batch_inversion<F: Field>(v: &mut [F]) {
67 batch_inversion_and_mul(v, &F::one());
68}
69
70#[cfg(feature = "serial")]
71pub fn batch_inversion_and_mul<F: Field>(v: &mut [F], coeff: &F) {
73 serial_batch_inversion_and_mul(v, coeff);
74}
75
76#[cfg(not(feature = "serial"))]
77pub fn batch_inversion_and_mul<F: Field>(v: &mut [F], coeff: &F) {
79 use rayon::prelude::*;
80 let min_elements_per_thread = 1;
82 let num_cpus_available = snarkvm_utilities::parallel::max_available_threads();
83 let num_elems = v.len();
84 let num_elem_per_thread = min_elements_per_thread.max(num_elems / num_cpus_available);
85
86 v.par_chunks_mut(num_elem_per_thread).for_each(|chunk| {
88 serial_batch_inversion_and_mul(chunk, coeff);
89 });
90}
91
92fn serial_batch_inversion_and_mul<F: Field>(v: &mut [F], coeff: &F) {
95 let mut prod = Vec::with_capacity(v.len());
103 let mut tmp = F::one();
104 for f in v.iter().filter(|f| !f.is_zero()) {
105 tmp.mul_assign(f);
106 prod.push(tmp);
107 }
108
109 tmp = tmp.inverse().unwrap(); tmp *= coeff;
114
115 for (f, s) in v.iter_mut()
117 .rev()
119 .filter(|f| !f.is_zero())
121 .zip(prod.into_iter().rev().skip(1).chain(Some(F::one())))
123 {
124 let new_tmp = tmp * *f;
126 *f = tmp * s;
127 tmp = new_tmp;
128 }
129}