//! This module exercises the `ff_derive` procedural macros, to ensure that changes to the //! `ff_wasm_unknown_unknown` crate are reflected in `ff_derive`. It also uses the resulting field to test some //! of the APIs provided by `ff_wasm_unknown_unknown`, such as batch inversion. #[macro_use] extern crate ff_wasm_unknown_unknown; /// The BLS12-381 scalar field. #[derive(PrimeField)] #[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] #[PrimeFieldGenerator = "7"] #[PrimeFieldReprEndianness = "little"] struct Bls381K12Scalar([u64; 4]); mod fermat { /// The largest known Fermat prime, used to test the case `t = 1`. #[derive(PrimeField)] #[PrimeFieldModulus = "65537"] #[PrimeFieldGenerator = "3"] #[PrimeFieldReprEndianness = "little"] struct Fermat65537Field([u64; 1]); } #[test] fn batch_inversion() { use ff_wasm_unknown_unknown::{BatchInverter, Field}; let one = Bls381K12Scalar::one(); // [1, 2, 3, 4] let values: Vec<_> = (0..4) .scan(one, |acc, _| { let ret = *acc; *acc += &one; Some(ret) }) .collect(); // Test BatchInverter::invert_with_external_scratch { let mut elements = values.clone(); let mut scratch_space = vec![Bls381K12Scalar::zero(); elements.len()]; BatchInverter::invert_with_external_scratch(&mut elements, &mut scratch_space); for (a, a_inv) in values.iter().zip(elements.into_iter()) { assert_eq!(*a * a_inv, one); } } // Test BatchInverter::invert_with_internal_scratch { let mut items: Vec<_> = values.iter().cloned().map(|p| (p, one)).collect(); BatchInverter::invert_with_internal_scratch( &mut items, |item| &mut item.0, |item| &mut item.1, ); for (a, (a_inv, _)) in values.iter().zip(items.into_iter()) { assert_eq!(*a * a_inv, one); } } // Test BatchInvert trait #[cfg(feature = "alloc")] { use ff_wasm_unknown_unknown::BatchInvert; let mut elements = values.clone(); elements.iter_mut().batch_invert(); for (a, a_inv) in values.iter().zip(elements.into_iter()) { assert_eq!(*a * a_inv, one); } } }