diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index dd79f33e..4cb70602 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -30,7 +30,7 @@ jobs: args: --all lints: - name: Formatting + name: Formatting and Clippy runs-on: ubuntu-latest if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" steps: @@ -43,10 +43,17 @@ jobs: profile: minimal toolchain: nightly override: true - components: rustfmt + components: rustfmt, clippy - name: Run cargo fmt uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check + + - name: Run cargo clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --all-features --all-targets -- -D warnings -A incomplete-features + diff --git a/benches/ffts.rs b/benches/ffts.rs index 8492cfe9..745d53a8 100644 --- a/benches/ffts.rs +++ b/benches/ffts.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use plonky2::field::field_types::Field; use plonky2::field::goldilocks_field::GoldilocksField; -use plonky2::polynomial::polynomial::PolynomialCoeffs; +use plonky2::polynomial::PolynomialCoeffs; use tynm::type_name; pub(crate) fn bench_ffts(c: &mut Criterion) { diff --git a/src/bin/bench_ldes.rs b/src/bin/bench_ldes.rs index d121831b..dbcfa6df 100644 --- a/src/bin/bench_ldes.rs +++ b/src/bin/bench_ldes.rs @@ -2,7 +2,7 @@ use std::time::Instant; use plonky2::field::field_types::Field; use plonky2::field::goldilocks_field::GoldilocksField; -use plonky2::polynomial::polynomial::PolynomialValues; +use plonky2::polynomial::PolynomialValues; use rayon::prelude::*; type F = GoldilocksField; diff --git a/src/bin/generate_constants.rs b/src/bin/generate_constants.rs index 60028741..89630fc7 100644 --- a/src/bin/generate_constants.rs +++ b/src/bin/generate_constants.rs @@ -1,5 +1,7 @@ //! Generates random constants using ChaCha20, seeded with zero. +#![allow(clippy::needless_range_loop)] + use plonky2::field::field_types::PrimeField; use plonky2::field::goldilocks_field::GoldilocksField; use rand::{Rng, SeedableRng}; diff --git a/src/field/extension_field/target.rs b/src/field/extension_field/target.rs index 3f9b6684..97e926b4 100644 --- a/src/field/extension_field/target.rs +++ b/src/field/extension_field/target.rs @@ -35,6 +35,7 @@ impl ExtensionTarget { let arr = self.to_target_array(); let k = (F::order() - 1u32) / (D as u64); let z0 = F::Extension::W.exp_biguint(&(k * count as u64)); + #[allow(clippy::needless_collect)] let zs = z0 .powers() .take(D) diff --git a/src/field/fft.rs b/src/field/fft.rs index 17c29184..6f5155a4 100644 --- a/src/field/fft.rs +++ b/src/field/fft.rs @@ -6,7 +6,7 @@ use unroll::unroll_for_loops; use crate::field::field_types::Field; use crate::field::packable::Packable; use crate::field::packed_field::{PackedField, Singleton}; -use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; +use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::util::{log2_strict, reverse_index_bits}; pub(crate) type FftRootTable = Vec>; @@ -38,12 +38,12 @@ fn fft_dispatch( zero_factor: Option, root_table: Option<&FftRootTable>, ) -> Vec { - let computed_root_table = if let Some(_) = root_table { + let computed_root_table = if root_table.is_some() { None } else { Some(fft_root_table(input.len())) }; - let used_root_table = root_table.or(computed_root_table.as_ref()).unwrap(); + let used_root_table = root_table.or_else(|| computed_root_table.as_ref()).unwrap(); fft_classic(input, zero_factor.unwrap_or(0), used_root_table) } @@ -122,8 +122,8 @@ fn fft_classic_simd( // Set omega to root_table[lg_half_m][0..half_m] but repeated. let mut omega_vec = P::zero().to_vec(); - for j in 0..omega_vec.len() { - omega_vec[j] = root_table[lg_half_m][j % half_m]; + for (j, omega) in omega_vec.iter_mut().enumerate() { + *omega = root_table[lg_half_m][j % half_m]; } let omega = P::from_slice(&omega_vec[..]); @@ -201,9 +201,9 @@ pub(crate) fn fft_classic(input: &[F], r: usize, root_table: &FftRootT if lg_n <= lg_packed_width { // Need the slice to be at least the width of two packed vectors for the vectorized version // to work. Do this tiny problem in scalar. - fft_classic_simd::>(&mut values[..], r, lg_n, &root_table); + fft_classic_simd::>(&mut values[..], r, lg_n, root_table); } else { - fft_classic_simd::<::PackedType>(&mut values[..], r, lg_n, &root_table); + fft_classic_simd::<::PackedType>(&mut values[..], r, lg_n, root_table); } values } @@ -213,7 +213,7 @@ mod tests { use crate::field::fft::{fft, fft_with_options, ifft}; use crate::field::field_types::Field; use crate::field::goldilocks_field::GoldilocksField; - use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; + use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::util::{log2_ceil, log2_strict}; #[test] @@ -267,7 +267,7 @@ mod tests { let values = subgroup .into_iter() - .map(|x| evaluate_at_naive(&coefficients, x)) + .map(|x| evaluate_at_naive(coefficients, x)) .collect(); PolynomialValues::new(values) } @@ -276,8 +276,8 @@ mod tests { let mut sum = F::ZERO; let mut point_power = F::ONE; for &c in &coefficients.coeffs { - sum = sum + c * point_power; - point_power = point_power * point; + sum += c * point_power; + point_power *= point; } sum } diff --git a/src/field/field_testing.rs b/src/field/field_testing.rs index d15b712a..767a3cf2 100644 --- a/src/field/field_testing.rs +++ b/src/field/field_testing.rs @@ -88,6 +88,7 @@ macro_rules! test_field_arithmetic { }; } +#[allow(clippy::eq_op)] pub(crate) fn test_add_neg_sub_mul, const D: usize>() { let x = BF::Extension::rand(); let y = BF::Extension::rand(); diff --git a/src/field/field_types.rs b/src/field/field_types.rs index 45839bd9..036793cc 100644 --- a/src/field/field_types.rs +++ b/src/field/field_types.rs @@ -335,7 +335,7 @@ pub trait Field: } fn kth_root_u64(&self, k: u64) -> Self { - let p = Self::order().clone(); + let p = Self::order(); let p_minus_1 = &p - 1u32; debug_assert!( Self::is_monomial_permutation_u64(k), @@ -422,6 +422,7 @@ pub trait PrimeField: Field { unsafe { self.sub_canonical_u64(1) } } + /// # Safety /// Equivalent to *self + Self::from_canonical_u64(rhs), but may be cheaper. The caller must /// ensure that 0 <= rhs < Self::ORDER. The function may return incorrect results if this /// precondition is not met. It is marked unsafe for this reason. @@ -431,6 +432,7 @@ pub trait PrimeField: Field { *self + Self::from_canonical_u64(rhs) } + /// # Safety /// Equivalent to *self - Self::from_canonical_u64(rhs), but may be cheaper. The caller must /// ensure that 0 <= rhs < Self::ORDER. The function may return incorrect results if this /// precondition is not met. It is marked unsafe for this reason. diff --git a/src/field/interpolation.rs b/src/field/interpolation.rs index c4a49fe1..ad3ddf72 100644 --- a/src/field/interpolation.rs +++ b/src/field/interpolation.rs @@ -1,6 +1,6 @@ use crate::field::fft::ifft; use crate::field::field_types::Field; -use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; +use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::util::log2_ceil; /// Computes the unique degree < n interpolant of an arbitrary list of n (point, value) pairs. @@ -80,7 +80,7 @@ mod tests { use crate::field::extension_field::quartic::QuarticExtension; use crate::field::field_types::Field; use crate::field::goldilocks_field::GoldilocksField; - use crate::polynomial::polynomial::PolynomialCoeffs; + use crate::polynomial::PolynomialCoeffs; #[test] fn interpolant_random() { diff --git a/src/field/prime_field_testing.rs b/src/field/prime_field_testing.rs index 4febc3a8..9dae4896 100644 --- a/src/field/prime_field_testing.rs +++ b/src/field/prime_field_testing.rs @@ -24,7 +24,7 @@ where ExpectedOp: Fn(u64) -> u64, { let inputs = test_inputs(F::ORDER); - let expected: Vec<_> = inputs.iter().map(|x| expected_op(x.clone())).collect(); + let expected: Vec<_> = inputs.iter().map(|&x| expected_op(x)).collect(); let output: Vec<_> = inputs .iter() .cloned() diff --git a/src/fri/commitment.rs b/src/fri/commitment.rs index c8a13cac..c8506356 100644 --- a/src/fri/commitment.rs +++ b/src/fri/commitment.rs @@ -10,7 +10,7 @@ use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::proof::OpeningSet; -use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; +use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::timed; use crate::util::reducing::ReducingFactor; use crate::util::timing::TimingTree; @@ -216,7 +216,7 @@ impl PolynomialBatchCommitment { lde_final_poly, lde_final_values, challenger, - &common_data, + common_data, timing, ); diff --git a/src/fri/proof.rs b/src/fri/proof.rs index f6875fcc..72cf594a 100644 --- a/src/fri/proof.rs +++ b/src/fri/proof.rs @@ -15,7 +15,7 @@ use crate::iop::target::Target; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::plonk_common::PolynomialsIndexBlinding; use crate::plonk::proof::{FriInferredElements, ProofChallenges}; -use crate::polynomial::polynomial::PolynomialCoeffs; +use crate::polynomial::PolynomialCoeffs; /// Evaluations and Merkle proof produced by the prover in a FRI query step. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] diff --git a/src/fri/prover.rs b/src/fri/prover.rs index ec58fc14..90ef8cfe 100644 --- a/src/fri/prover.rs +++ b/src/fri/prover.rs @@ -10,7 +10,7 @@ use crate::hash::merkle_tree::MerkleTree; use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::plonk_common::reduce_with_powers; -use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; +use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::timed; use crate::util::reverse_index_bits_in_place; use crate::util::timing::TimingTree; diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index b31e01a8..91d0580a 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -407,7 +407,7 @@ impl, const D: usize> CircuitBuilder { arity_bits, evals, betas[i], - &common_data + common_data ) ); diff --git a/src/gadgets/biguint.rs b/src/gadgets/biguint.rs index fff97a6e..fa5aa0b6 100644 --- a/src/gadgets/biguint.rs +++ b/src/gadgets/biguint.rs @@ -142,9 +142,9 @@ impl, const D: usize> CircuitBuilder { let mut combined_limbs = vec![]; let mut carry = self.zero_u32(); - for i in 0..total_limbs { - to_add[i].push(carry); - let (new_result, new_carry) = self.add_many_u32(&to_add[i].clone()); + for summands in &mut to_add { + summands.push(carry); + let (new_result, new_carry) = self.add_many_u32(summands); combined_limbs.push(new_result); carry = new_carry; } @@ -172,9 +172,9 @@ impl, const D: usize> CircuitBuilder { _phantom: PhantomData, }); - let div_b = self.mul_biguint(&div, &b); + let div_b = self.mul_biguint(&div, b); let div_b_plus_rem = self.add_biguint(&div_b, &rem); - self.connect_biguint(&a, &div_b_plus_rem); + self.connect_biguint(a, &div_b_plus_rem); let cmp_rem_b = self.cmp_biguint(&rem, b); self.assert_one(cmp_rem_b.target); diff --git a/src/gadgets/permutation.rs b/src/gadgets/permutation.rs index 37169514..2d8c4f22 100644 --- a/src/gadgets/permutation.rs +++ b/src/gadgets/permutation.rs @@ -378,7 +378,7 @@ mod tests { let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); - let lst: Vec = (0..size * 2).map(|n| F::from_canonical_usize(n)).collect(); + let lst: Vec = (0..size * 2).map(F::from_canonical_usize).collect(); let a: Vec> = lst[..] .chunks(2) .map(|pair| vec![builder.constant(pair[0]), builder.constant(pair[1])]) diff --git a/src/gadgets/sorting.rs b/src/gadgets/sorting.rs index 2c52db23..2059a888 100644 --- a/src/gadgets/sorting.rs +++ b/src/gadgets/sorting.rs @@ -224,7 +224,7 @@ mod tests { izip!(is_write_vals, address_vals, timestamp_vals, value_vals) .zip(combined_vals_u64) .collect::>(); - input_ops_and_keys.sort_by_key(|(_, val)| val.clone()); + input_ops_and_keys.sort_by_key(|(_, val)| *val); let input_ops_sorted: Vec<_> = input_ops_and_keys.iter().map(|(x, _)| x).collect(); let output_ops = diff --git a/src/gates/arithmetic_u32.rs b/src/gates/arithmetic_u32.rs index 2bbbda6e..a5a63047 100644 --- a/src/gates/arithmetic_u32.rs +++ b/src/gates/arithmetic_u32.rs @@ -261,17 +261,11 @@ impl, const D: usize> SimpleGenerator fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); - let mut deps = Vec::with_capacity(3); - deps.push(local_target( - U32ArithmeticGate::::wire_ith_multiplicand_0(self.i), - )); - deps.push(local_target( - U32ArithmeticGate::::wire_ith_multiplicand_1(self.i), - )); - deps.push(local_target(U32ArithmeticGate::::wire_ith_addend( - self.i, - ))); - deps + vec![ + local_target(U32ArithmeticGate::::wire_ith_multiplicand_0(self.i)), + local_target(U32ArithmeticGate::::wire_ith_multiplicand_1(self.i)), + local_target(U32ArithmeticGate::::wire_ith_addend(self.i)), + ] } fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { @@ -307,23 +301,19 @@ impl, const D: usize> SimpleGenerator let num_limbs = U32ArithmeticGate::::num_limbs(); let limb_base = 1 << U32ArithmeticGate::::limb_bits(); - let output_limbs_u64: Vec<_> = unfold((), move |_| { + let output_limbs_u64 = unfold((), move |_| { let ret = output_u64 % limb_base; output_u64 /= limb_base; Some(ret) }) - .take(num_limbs) - .collect(); - let output_limbs_f: Vec<_> = output_limbs_u64 - .into_iter() - .map(F::from_canonical_u64) - .collect(); + .take(num_limbs); + let output_limbs_f = output_limbs_u64.map(F::from_canonical_u64); - for j in 0..num_limbs { + for (j, output_limb) in output_limbs_f.enumerate() { let wire = local_wire(U32ArithmeticGate::::wire_ith_output_jth_limb( self.i, j, )); - out_buffer.set_wire(wire, output_limbs_f[j]); + out_buffer.set_wire(wire, output_limb); } } } diff --git a/src/gates/assert_le.rs b/src/gates/assert_le.rs index ffbc043a..4da3c44b 100644 --- a/src/gates/assert_le.rs +++ b/src/gates/assert_le.rs @@ -340,10 +340,10 @@ impl, const D: usize> SimpleGenerator fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); - let mut deps = Vec::new(); - deps.push(local_target(self.gate.wire_first_input())); - deps.push(local_target(self.gate.wire_second_input())); - deps + vec![ + local_target(self.gate.wire_first_input()), + local_target(self.gate.wire_second_input()), + ] } fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { @@ -555,7 +555,7 @@ mod tests { }; let mut rng = rand::thread_rng(); - let max: u64 = 1 << num_bits - 1; + let max: u64 = 1 << (num_bits - 1); let first_input_u64 = rng.gen_range(0..max); let second_input_u64 = { let mut val = rng.gen_range(0..max); diff --git a/src/gates/comparison.rs b/src/gates/comparison.rs index a610c5e2..614a759e 100644 --- a/src/gates/comparison.rs +++ b/src/gates/comparison.rs @@ -151,10 +151,8 @@ impl, const D: usize> Gate for ComparisonGate .collect(); // Range-check the bits. - for i in 0..most_significant_diff_bits.len() { - constraints.push( - most_significant_diff_bits[i] * (F::Extension::ONE - most_significant_diff_bits[i]), - ); + for &bit in &most_significant_diff_bits { + constraints.push(bit * (F::Extension::ONE - bit)); } let bits_combined = reduce_with_powers(&most_significant_diff_bits, F::Extension::TWO); @@ -232,9 +230,8 @@ impl, const D: usize> Gate for ComparisonGate .collect(); // Range-check the bits. - for i in 0..most_significant_diff_bits.len() { - constraints - .push(most_significant_diff_bits[i] * (F::ONE - most_significant_diff_bits[i])); + for &bit in &most_significant_diff_bits { + constraints.push(bit * (F::ONE - bit)); } let bits_combined = reduce_with_powers(&most_significant_diff_bits, F::TWO); @@ -324,8 +321,7 @@ impl, const D: usize> Gate for ComparisonGate .collect(); // Range-check the bits. - for i in 0..most_significant_diff_bits.len() { - let this_bit = most_significant_diff_bits[i]; + for &this_bit in &most_significant_diff_bits { let inverse = builder.sub_extension(one, this_bit); constraints.push(builder.mul_extension(this_bit, inverse)); } @@ -388,10 +384,10 @@ impl, const D: usize> SimpleGenerator fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); - let mut deps = Vec::new(); - deps.push(local_target(self.gate.wire_first_input())); - deps.push(local_target(self.gate.wire_second_input())); - deps + vec![ + local_target(self.gate.wire_first_input()), + local_target(self.gate.wire_second_input()), + ] } fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { @@ -638,7 +634,7 @@ mod tests { }; let mut rng = rand::thread_rng(); - let max: u64 = 1 << num_bits - 1; + let max: u64 = 1 << (num_bits - 1); let first_input_u64 = rng.gen_range(0..max); let second_input_u64 = { let mut val = rng.gen_range(0..max); diff --git a/src/gates/exponentiation.rs b/src/gates/exponentiation.rs index 5087cebd..47e6cce5 100644 --- a/src/gates/exponentiation.rs +++ b/src/gates/exponentiation.rs @@ -335,9 +335,8 @@ mod tests { .map(|b| F::from_canonical_u64(*b)) .collect(); - let mut v = Vec::new(); - v.push(base); - v.extend(power_bits_f.clone()); + let mut v = vec![base]; + v.extend(power_bits_f); let mut intermediate_values = Vec::new(); let mut current_intermediate_value = F::ONE; diff --git a/src/gates/gate_testing.rs b/src/gates/gate_testing.rs index 9fe8e835..3fceded4 100644 --- a/src/gates/gate_testing.rs +++ b/src/gates/gate_testing.rs @@ -9,7 +9,7 @@ use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::verifier::verify; -use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; +use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::util::{log2_ceil, transpose}; const WITNESS_SIZE: usize = 1 << 5; diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index c55f53a9..3d2c1aa3 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -251,8 +251,7 @@ impl, const D: usize> SimpleGenerator for Insert let local_targets = |inputs: Range| inputs.map(local_target); - let mut deps = Vec::new(); - deps.push(local_target(self.gate.wires_insertion_index())); + let mut deps = vec![local_target(self.gate.wires_insertion_index())]; deps.extend(local_targets(self.gate.wires_element_to_insert())); for i in 0..self.gate.vec_size { deps.extend(local_targets(self.gate.wires_original_list_item(i))); @@ -291,7 +290,7 @@ impl, const D: usize> SimpleGenerator for Insert vec_size ); - let mut new_vec = orig_vec.clone(); + let mut new_vec = orig_vec; new_vec.insert(insertion_index, to_insert); let mut equality_dummy_vals = Vec::new(); @@ -372,14 +371,13 @@ mod tests { fn get_wires(orig_vec: Vec, insertion_index: usize, element_to_insert: FF) -> Vec { let vec_size = orig_vec.len(); - let mut v = Vec::new(); - v.push(F::from_canonical_usize(insertion_index)); + let mut v = vec![F::from_canonical_usize(insertion_index)]; v.extend(element_to_insert.0); for j in 0..vec_size { v.extend(orig_vec[j].0); } - let mut new_vec = orig_vec.clone(); + let mut new_vec = orig_vec; new_vec.insert(insertion_index, element_to_insert); let mut equality_dummy_vals = Vec::new(); for i in 0..=vec_size { diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index 0225ce59..d2142ee1 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -15,7 +15,7 @@ use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; -use crate::polynomial::polynomial::PolynomialCoeffs; +use crate::polynomial::PolynomialCoeffs; /// Interpolation gate with constraints of degree at most `1<, const D: usize> HighDegreeInterpolationGate>::partial_first_constant_layer(&mut state); - state = >::mds_partial_layer_init(&mut state); + state = >::mds_partial_layer_init(&state); for r in 0..(poseidon::N_PARTIAL_ROUNDS - 1) { let sbox_in = vars.local_wires[Self::wire_partial_sbox(r)]; constraints.push(state[0] - sbox_in); @@ -243,7 +243,7 @@ where // Partial rounds. >::partial_first_constant_layer(&mut state); - state = >::mds_partial_layer_init(&mut state); + state = >::mds_partial_layer_init(&state); for r in 0..(poseidon::N_PARTIAL_ROUNDS - 1) { let sbox_in = vars.local_wires[Self::wire_partial_sbox(r)]; constraints.push(state[0] - sbox_in); @@ -345,7 +345,7 @@ where } } else { >::partial_first_constant_layer_recursive(builder, &mut state); - state = >::mds_partial_layer_init_recursive(builder, &mut state); + state = >::mds_partial_layer_init_recursive(builder, &state); for r in 0..(poseidon::N_PARTIAL_ROUNDS - 1) { let sbox_in = vars.local_wires[Self::wire_partial_sbox(r)]; constraints.push(builder.sub_extension(state[0], sbox_in)); @@ -489,7 +489,7 @@ where } >::partial_first_constant_layer(&mut state); - state = >::mds_partial_layer_init(&mut state); + state = >::mds_partial_layer_init(&state); for r in 0..(poseidon::N_PARTIAL_ROUNDS - 1) { out_buffer.set_wire( local_wire(PoseidonGate::::wire_partial_sbox(r)), diff --git a/src/gates/random_access.rs b/src/gates/random_access.rs index cea4b079..2796cd01 100644 --- a/src/gates/random_access.rs +++ b/src/gates/random_access.rs @@ -263,8 +263,7 @@ impl, const D: usize> SimpleGenerator fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); - let mut deps = Vec::new(); - deps.push(local_target(self.gate.wire_access_index(self.copy))); + let mut deps = vec![local_target(self.gate.wire_access_index(self.copy))]; for i in 0..self.gate.vec_size() { deps.push(local_target(self.gate.wire_list_item(i, self.copy))); } diff --git a/src/gates/subtraction_u32.rs b/src/gates/subtraction_u32.rs index 225c09e4..26f6302e 100644 --- a/src/gates/subtraction_u32.rs +++ b/src/gates/subtraction_u32.rs @@ -244,17 +244,11 @@ impl, const D: usize> SimpleGenerator fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); - let mut deps = Vec::with_capacity(3); - deps.push(local_target(U32SubtractionGate::::wire_ith_input_x( - self.i, - ))); - deps.push(local_target(U32SubtractionGate::::wire_ith_input_y( - self.i, - ))); - deps.push(local_target( - U32SubtractionGate::::wire_ith_input_borrow(self.i), - )); - deps + vec![ + local_target(U32SubtractionGate::::wire_ith_input_x(self.i)), + local_target(U32SubtractionGate::::wire_ith_input_y(self.i)), + local_target(U32SubtractionGate::::wire_ith_input_borrow(self.i)), + ] } fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { diff --git a/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs b/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs index 5d9d9fba..0aaa13a6 100644 --- a/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs +++ b/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs @@ -1,3 +1,5 @@ +#![allow(clippy::assertions_on_constants)] + use std::arch::aarch64::*; use static_assertions::const_assert; @@ -171,9 +173,7 @@ unsafe fn multiply(x: u64, y: u64) -> u64 { let xy_hi_lo_mul_epsilon = mul_epsilon(xy_hi); // add_with_wraparound is safe, as xy_hi_lo_mul_epsilon <= 0xfffffffe00000001 <= ORDER. - let res1 = add_with_wraparound(res0, xy_hi_lo_mul_epsilon); - - res1 + add_with_wraparound(res0, xy_hi_lo_mul_epsilon) } // ==================================== STANDALONE CONST LAYER ===================================== @@ -266,9 +266,7 @@ unsafe fn mds_reduce( // Multiply by EPSILON and accumulate. let res_unadj = vmlal_laneq_u32::<0>(res_lo, res_hi_hi, mds_consts0); let res_adj = vcgtq_u64(res_lo, res_unadj); - let res = vsraq_n_u64::<32>(res_unadj, res_adj); - - res + vsraq_n_u64::<32>(res_unadj, res_adj) } #[inline(always)] @@ -968,8 +966,7 @@ unsafe fn partial_round( #[inline(always)] unsafe fn full_round(state: [u64; 12], round_constants: &[u64; WIDTH]) -> [u64; 12] { let state = sbox_layer_full(state); - let state = mds_const_layers_full(state, round_constants); - state + mds_const_layers_full(state, round_constants) } #[inline] diff --git a/src/hash/hashing.rs b/src/hash/hashing.rs index a4610495..4fd537f1 100644 --- a/src/hash/hashing.rs +++ b/src/hash/hashing.rs @@ -110,9 +110,7 @@ pub fn hash_n_to_m(mut inputs: Vec, num_outputs: usize, pad: bo // Absorb all input chunks. for input_chunk in inputs.chunks(SPONGE_RATE) { - for i in 0..input_chunk.len() { - state[i] = input_chunk[i]; - } + state[..input_chunk.len()].copy_from_slice(input_chunk); state = permute(state); } diff --git a/src/iop/target.rs b/src/iop/target.rs index 8d4cbcfb..de3e4911 100644 --- a/src/iop/target.rs +++ b/src/iop/target.rs @@ -41,6 +41,7 @@ impl Target { /// A `Target` which has already been constrained such that it can only be 0 or 1. #[derive(Copy, Clone, Debug)] +#[allow(clippy::manual_non_exhaustive)] pub struct BoolTarget { pub target: Target, /// This private field is here to force all instantiations to go through `new_unsafe`. diff --git a/src/lib.rs b/src/lib.rs index 46db2cf5..e76e312c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,9 @@ #![allow(incomplete_features)] #![allow(const_evaluatable_unchecked)] +#![allow(clippy::new_without_default)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::len_without_is_empty)] +#![allow(clippy::needless_range_loop)] #![feature(asm)] #![feature(asm_sym)] #![feature(destructuring_assignment)] diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 730699b9..3cb62cf3 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -40,7 +40,7 @@ use crate::plonk::circuit_data::{ use crate::plonk::copy_constraint::CopyConstraint; use crate::plonk::permutation_argument::Forest; use crate::plonk::plonk_common::PlonkPolynomials; -use crate::polynomial::polynomial::PolynomialValues; +use crate::polynomial::PolynomialValues; use crate::util::context_tree::ContextTree; use crate::util::marking::{Markable, MarkedTargets}; use crate::util::partial_products::num_partial_products; @@ -634,7 +634,7 @@ impl, const D: usize> CircuitBuilder { // Precompute FFT roots. let max_fft_points = - 1 << degree_bits + max(self.config.rate_bits, log2_ceil(quotient_degree_factor)); + 1 << (degree_bits + max(self.config.rate_bits, log2_ceil(quotient_degree_factor))); let fft_root_table = fft_root_table(max_fft_points); let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat(); @@ -669,7 +669,7 @@ impl, const D: usize> CircuitBuilder { let watch_rep_index = forest.parents[watch_index]; generator_indices_by_watches .entry(watch_rep_index) - .or_insert(vec![]) + .or_insert_with(Vec::new) .push(i); } } diff --git a/src/plonk/get_challenges.rs b/src/plonk/get_challenges.rs index ab361c76..a749f1c0 100644 --- a/src/plonk/get_challenges.rs +++ b/src/plonk/get_challenges.rs @@ -13,7 +13,7 @@ use crate::plonk::proof::{ CompressedProof, CompressedProofWithPublicInputs, FriInferredElements, OpeningSet, Proof, ProofChallenges, ProofWithPublicInputs, }; -use crate::polynomial::polynomial::PolynomialCoeffs; +use crate::polynomial::PolynomialCoeffs; use crate::util::reverse_bits; fn get_challenges, const D: usize>( diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index 28a07dff..ca3977ce 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -5,7 +5,7 @@ use rayon::prelude::*; use crate::field::field_types::Field; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::polynomial::polynomial::PolynomialValues; +use crate::polynomial::PolynomialValues; /// Disjoint Set Forest data-structure following https://en.wikipedia.org/wiki/Disjoint-set_data_structure. pub struct Forest { diff --git a/src/plonk/proof.rs b/src/plonk/proof.rs index 70e38588..94bc4714 100644 --- a/src/plonk/proof.rs +++ b/src/plonk/proof.rs @@ -138,11 +138,7 @@ impl, const D: usize> CompressedProof { plonk_zs_partial_products_cap, quotient_polys_cap, openings, - opening_proof: opening_proof.decompress( - &challenges, - fri_inferred_elements, - common_data, - ), + opening_proof: opening_proof.decompress(challenges, fri_inferred_elements, common_data), } } } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 3f8e607d..4f281f06 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -17,7 +17,7 @@ use crate::plonk::plonk_common::ZeroPolyOnCoset; use crate::plonk::proof::{Proof, ProofWithPublicInputs}; use crate::plonk::vanishing_poly::eval_vanishing_poly_base_batch; use crate::plonk::vars::EvaluationVarsBase; -use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; +use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::timed; use crate::util::partial_products::{partial_products_and_z_gx, quotient_chunk_products}; use crate::util::timing::TimingTree; diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 98c866f8..46ca5e6a 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -527,7 +527,7 @@ mod tests { &inner_vd.constants_sigmas_cap, ); - builder.add_recursive_verifier(pt, &inner_config, &inner_data, &inner_cd); + builder.add_recursive_verifier(pt, inner_config, &inner_data, &inner_cd); if print_gate_counts { builder.print_gate_counts(0); @@ -563,12 +563,12 @@ mod tests { ) -> Result<()> { let proof_bytes = proof.to_bytes()?; info!("Proof length: {} bytes", proof_bytes.len()); - let proof_from_bytes = ProofWithPublicInputs::from_bytes(proof_bytes, &cd)?; + let proof_from_bytes = ProofWithPublicInputs::from_bytes(proof_bytes, cd)?; assert_eq!(proof, &proof_from_bytes); let now = std::time::Instant::now(); - let compressed_proof = proof.clone().compress(&cd)?; - let decompressed_compressed_proof = compressed_proof.clone().decompress(&cd)?; + let compressed_proof = proof.clone().compress(cd)?; + let decompressed_compressed_proof = compressed_proof.clone().decompress(cd)?; info!("{:.4}s to compress proof", now.elapsed().as_secs_f64()); assert_eq!(proof, &decompressed_compressed_proof); @@ -578,7 +578,7 @@ mod tests { compressed_proof_bytes.len() ); let compressed_proof_from_bytes = - CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, &cd)?; + CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, cd)?; assert_eq!(compressed_proof, compressed_proof_from_bytes); Ok(()) diff --git a/src/polynomial/division.rs b/src/polynomial/division.rs index b5dad629..671b7715 100644 --- a/src/polynomial/division.rs +++ b/src/polynomial/division.rs @@ -1,5 +1,5 @@ use crate::field::field_types::Field; -use crate::polynomial::polynomial::PolynomialCoeffs; +use crate::polynomial::PolynomialCoeffs; use crate::util::log2_ceil; impl PolynomialCoeffs { @@ -129,7 +129,7 @@ mod tests { use crate::field::extension_field::quartic::QuarticExtension; use crate::field::field_types::Field; use crate::field::goldilocks_field::GoldilocksField; - use crate::polynomial::polynomial::PolynomialCoeffs; + use crate::polynomial::PolynomialCoeffs; #[test] #[ignore] diff --git a/src/polynomial/mod.rs b/src/polynomial/mod.rs index 2c7f7076..1a7b90fe 100644 --- a/src/polynomial/mod.rs +++ b/src/polynomial/mod.rs @@ -1,2 +1,616 @@ pub(crate) mod division; -pub mod polynomial; + +use std::cmp::max; +use std::iter::Sum; +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; + +use anyhow::{ensure, Result}; +use serde::{Deserialize, Serialize}; + +use crate::field::extension_field::{Extendable, FieldExtension}; +use crate::field::fft::{fft, fft_with_options, ifft, FftRootTable}; +use crate::field::field_types::Field; +use crate::util::log2_strict; + +/// A polynomial in point-value form. +/// +/// The points are implicitly `g^i`, where `g` generates the subgroup whose size equals the number +/// of points. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PolynomialValues { + pub values: Vec, +} + +impl PolynomialValues { + pub fn new(values: Vec) -> Self { + PolynomialValues { values } + } + + /// The number of values stored. + pub(crate) fn len(&self) -> usize { + self.values.len() + } + + pub fn ifft(&self) -> PolynomialCoeffs { + ifft(self) + } + + /// Returns the polynomial whose evaluation on the coset `shift*H` is `self`. + pub fn coset_ifft(&self, shift: F) -> PolynomialCoeffs { + let mut shifted_coeffs = self.ifft(); + shifted_coeffs + .coeffs + .iter_mut() + .zip(shift.inverse().powers()) + .for_each(|(c, r)| { + *c *= r; + }); + shifted_coeffs + } + + pub fn lde_multiple(polys: Vec, rate_bits: usize) -> Vec { + polys.into_iter().map(|p| p.lde(rate_bits)).collect() + } + + pub fn lde(&self, rate_bits: usize) -> Self { + let coeffs = ifft(self).lde(rate_bits); + fft_with_options(&coeffs, Some(rate_bits), None) + } + + pub fn degree(&self) -> usize { + self.degree_plus_one() + .checked_sub(1) + .expect("deg(0) is undefined") + } + + pub fn degree_plus_one(&self) -> usize { + self.ifft().degree_plus_one() + } +} + +impl From> for PolynomialValues { + fn from(values: Vec) -> Self { + Self::new(values) + } +} + +/// A polynomial in coefficient form. +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound = "")] +pub struct PolynomialCoeffs { + pub(crate) coeffs: Vec, +} + +impl PolynomialCoeffs { + pub fn new(coeffs: Vec) -> Self { + PolynomialCoeffs { coeffs } + } + + pub(crate) fn empty() -> Self { + Self::new(Vec::new()) + } + + pub(crate) fn zero(len: usize) -> Self { + Self::new(vec![F::ZERO; len]) + } + + pub(crate) fn is_zero(&self) -> bool { + self.coeffs.iter().all(|x| x.is_zero()) + } + + /// The number of coefficients. This does not filter out any zero coefficients, so it is not + /// necessarily related to the degree. + pub fn len(&self) -> usize { + self.coeffs.len() + } + + pub fn log_len(&self) -> usize { + log2_strict(self.len()) + } + + pub(crate) fn chunks(&self, chunk_size: usize) -> Vec { + self.coeffs + .chunks(chunk_size) + .map(|chunk| PolynomialCoeffs::new(chunk.to_vec())) + .collect() + } + + pub fn eval(&self, x: F) -> F { + self.coeffs + .iter() + .rev() + .fold(F::ZERO, |acc, &c| acc * x + c) + } + + /// Evaluate the polynomial at a point given its powers. The first power is the point itself, not 1. + pub fn eval_with_powers(&self, powers: &[F]) -> F { + debug_assert_eq!(self.coeffs.len(), powers.len() + 1); + let acc = self.coeffs[0]; + self.coeffs[1..] + .iter() + .zip(powers) + .fold(acc, |acc, (&x, &c)| acc + c * x) + } + + pub fn eval_base(&self, x: F::BaseField) -> F + where + F: FieldExtension, + { + self.coeffs + .iter() + .rev() + .fold(F::ZERO, |acc, &c| acc.scalar_mul(x) + c) + } + + /// Evaluate the polynomial at a point given its powers. The first power is the point itself, not 1. + pub fn eval_base_with_powers(&self, powers: &[F::BaseField]) -> F + where + F: FieldExtension, + { + debug_assert_eq!(self.coeffs.len(), powers.len() + 1); + let acc = self.coeffs[0]; + self.coeffs[1..] + .iter() + .zip(powers) + .fold(acc, |acc, (&x, &c)| acc + x.scalar_mul(c)) + } + + pub fn lde_multiple(polys: Vec<&Self>, rate_bits: usize) -> Vec { + polys.into_iter().map(|p| p.lde(rate_bits)).collect() + } + + pub fn lde(&self, rate_bits: usize) -> Self { + self.padded(self.len() << rate_bits) + } + + pub(crate) fn pad(&mut self, new_len: usize) -> Result<()> { + ensure!( + new_len >= self.len(), + "Trying to pad a polynomial of length {} to a length of {}.", + self.len(), + new_len + ); + self.coeffs.resize(new_len, F::ZERO); + Ok(()) + } + + pub(crate) fn padded(&self, new_len: usize) -> Self { + let mut poly = self.clone(); + poly.pad(new_len).unwrap(); + poly + } + + /// Removes leading zero coefficients. + pub fn trim(&mut self) { + self.coeffs.truncate(self.degree_plus_one()); + } + + /// Removes leading zero coefficients. + pub fn trimmed(&self) -> Self { + let coeffs = self.coeffs[..self.degree_plus_one()].to_vec(); + Self { coeffs } + } + + /// Degree of the polynomial + 1, or 0 for a polynomial with no non-zero coefficients. + pub(crate) fn degree_plus_one(&self) -> usize { + (0usize..self.len()) + .rev() + .find(|&i| self.coeffs[i].is_nonzero()) + .map_or(0, |i| i + 1) + } + + /// Leading coefficient. + pub fn lead(&self) -> F { + self.coeffs + .iter() + .rev() + .find(|x| x.is_nonzero()) + .map_or(F::ZERO, |x| *x) + } + + /// Reverse the order of the coefficients, not taking into account the leading zero coefficients. + pub(crate) fn rev(&self) -> Self { + Self::new(self.trimmed().coeffs.into_iter().rev().collect()) + } + + pub fn fft(&self) -> PolynomialValues { + fft(self) + } + + pub fn fft_with_options( + &self, + zero_factor: Option, + root_table: Option<&FftRootTable>, + ) -> PolynomialValues { + fft_with_options(self, zero_factor, root_table) + } + + /// Returns the evaluation of the polynomial on the coset `shift*H`. + pub fn coset_fft(&self, shift: F) -> PolynomialValues { + self.coset_fft_with_options(shift, None, None) + } + + /// Returns the evaluation of the polynomial on the coset `shift*H`. + pub fn coset_fft_with_options( + &self, + shift: F, + zero_factor: Option, + root_table: Option<&FftRootTable>, + ) -> PolynomialValues { + let modified_poly: Self = shift + .powers() + .zip(&self.coeffs) + .map(|(r, &c)| r * c) + .collect::>() + .into(); + modified_poly.fft_with_options(zero_factor, root_table) + } + + pub fn to_extension(&self) -> PolynomialCoeffs + where + F: Extendable, + { + PolynomialCoeffs::new(self.coeffs.iter().map(|&c| c.into()).collect()) + } + + pub fn mul_extension(&self, rhs: F::Extension) -> PolynomialCoeffs + where + F: Extendable, + { + PolynomialCoeffs::new(self.coeffs.iter().map(|&c| rhs.scalar_mul(c)).collect()) + } +} + +impl PartialEq for PolynomialCoeffs { + fn eq(&self, other: &Self) -> bool { + let max_terms = self.coeffs.len().max(other.coeffs.len()); + for i in 0..max_terms { + let self_i = self.coeffs.get(i).cloned().unwrap_or(F::ZERO); + let other_i = other.coeffs.get(i).cloned().unwrap_or(F::ZERO); + if self_i != other_i { + return false; + } + } + true + } +} + +impl Eq for PolynomialCoeffs {} + +impl From> for PolynomialCoeffs { + fn from(coeffs: Vec) -> Self { + Self::new(coeffs) + } +} + +impl Add for &PolynomialCoeffs { + type Output = PolynomialCoeffs; + + fn add(self, rhs: Self) -> Self::Output { + let len = max(self.len(), rhs.len()); + let a = self.padded(len).coeffs; + let b = rhs.padded(len).coeffs; + let coeffs = a.into_iter().zip(b).map(|(x, y)| x + y).collect(); + PolynomialCoeffs::new(coeffs) + } +} + +impl Sum for PolynomialCoeffs { + fn sum>(iter: I) -> Self { + iter.fold(Self::empty(), |acc, p| &acc + &p) + } +} + +impl Sub for &PolynomialCoeffs { + type Output = PolynomialCoeffs; + + fn sub(self, rhs: Self) -> Self::Output { + let len = max(self.len(), rhs.len()); + let mut coeffs = self.padded(len).coeffs; + for (i, &c) in rhs.coeffs.iter().enumerate() { + coeffs[i] -= c; + } + PolynomialCoeffs::new(coeffs) + } +} + +impl AddAssign for PolynomialCoeffs { + fn add_assign(&mut self, rhs: Self) { + let len = max(self.len(), rhs.len()); + self.coeffs.resize(len, F::ZERO); + for (l, r) in self.coeffs.iter_mut().zip(rhs.coeffs) { + *l += r; + } + } +} + +impl AddAssign<&Self> for PolynomialCoeffs { + fn add_assign(&mut self, rhs: &Self) { + let len = max(self.len(), rhs.len()); + self.coeffs.resize(len, F::ZERO); + for (l, &r) in self.coeffs.iter_mut().zip(&rhs.coeffs) { + *l += r; + } + } +} + +impl SubAssign for PolynomialCoeffs { + fn sub_assign(&mut self, rhs: Self) { + let len = max(self.len(), rhs.len()); + self.coeffs.resize(len, F::ZERO); + for (l, r) in self.coeffs.iter_mut().zip(rhs.coeffs) { + *l -= r; + } + } +} + +impl SubAssign<&Self> for PolynomialCoeffs { + fn sub_assign(&mut self, rhs: &Self) { + let len = max(self.len(), rhs.len()); + self.coeffs.resize(len, F::ZERO); + for (l, &r) in self.coeffs.iter_mut().zip(&rhs.coeffs) { + *l -= r; + } + } +} + +impl Mul for &PolynomialCoeffs { + type Output = PolynomialCoeffs; + + fn mul(self, rhs: F) -> Self::Output { + let coeffs = self.coeffs.iter().map(|&x| rhs * x).collect(); + PolynomialCoeffs::new(coeffs) + } +} + +impl MulAssign for PolynomialCoeffs { + fn mul_assign(&mut self, rhs: F) { + self.coeffs.iter_mut().for_each(|x| *x *= rhs); + } +} + +impl Mul for &PolynomialCoeffs { + type Output = PolynomialCoeffs; + + #[allow(clippy::suspicious_arithmetic_impl)] + fn mul(self, rhs: Self) -> Self::Output { + let new_len = (self.len() + rhs.len()).next_power_of_two(); + let a = self.padded(new_len); + let b = rhs.padded(new_len); + let a_evals = a.fft(); + let b_evals = b.fft(); + + let mul_evals: Vec = a_evals + .values + .into_iter() + .zip(b_evals.values) + .map(|(pa, pb)| pa * pb) + .collect(); + ifft(&mul_evals.into()) + } +} + +#[cfg(test)] +mod tests { + use std::time::Instant; + + use rand::{thread_rng, Rng}; + + use super::*; + use crate::field::goldilocks_field::GoldilocksField; + + #[test] + fn test_trimmed() { + type F = GoldilocksField; + + assert_eq!( + PolynomialCoeffs:: { coeffs: vec![] }.trimmed(), + PolynomialCoeffs:: { coeffs: vec![] } + ); + assert_eq!( + PolynomialCoeffs:: { + coeffs: vec![F::ZERO] + } + .trimmed(), + PolynomialCoeffs:: { coeffs: vec![] } + ); + assert_eq!( + PolynomialCoeffs:: { + coeffs: vec![F::ONE, F::TWO, F::ZERO, F::ZERO] + } + .trimmed(), + PolynomialCoeffs:: { + coeffs: vec![F::ONE, F::TWO] + } + ); + } + + #[test] + fn test_coset_fft() { + type F = GoldilocksField; + + let k = 8; + let n = 1 << k; + let poly = PolynomialCoeffs::new(F::rand_vec(n)); + let shift = F::rand(); + let coset_evals = poly.coset_fft(shift).values; + + let generator = F::primitive_root_of_unity(k); + let naive_coset_evals = F::cyclic_subgroup_coset_known_order(generator, shift, n) + .into_iter() + .map(|x| poly.eval(x)) + .collect::>(); + assert_eq!(coset_evals, naive_coset_evals); + + let ifft_coeffs = PolynomialValues::new(coset_evals).coset_ifft(shift); + assert_eq!(poly, ifft_coeffs); + } + + #[test] + fn test_coset_ifft() { + type F = GoldilocksField; + + let k = 8; + let n = 1 << k; + let evals = PolynomialValues::new(F::rand_vec(n)); + let shift = F::rand(); + let coeffs = evals.coset_ifft(shift); + + let generator = F::primitive_root_of_unity(k); + let naive_coset_evals = F::cyclic_subgroup_coset_known_order(generator, shift, n) + .into_iter() + .map(|x| coeffs.eval(x)) + .collect::>(); + assert_eq!(evals, naive_coset_evals.into()); + + let fft_evals = coeffs.coset_fft(shift); + assert_eq!(evals, fft_evals); + } + + #[test] + fn test_polynomial_multiplication() { + type F = GoldilocksField; + let mut rng = thread_rng(); + let (a_deg, b_deg) = (rng.gen_range(1..10_000), rng.gen_range(1..10_000)); + let a = PolynomialCoeffs::new(F::rand_vec(a_deg)); + let b = PolynomialCoeffs::new(F::rand_vec(b_deg)); + let m1 = &a * &b; + let m2 = &a * &b; + for _ in 0..1000 { + let x = F::rand(); + assert_eq!(m1.eval(x), a.eval(x) * b.eval(x)); + assert_eq!(m2.eval(x), a.eval(x) * b.eval(x)); + } + } + + #[test] + fn test_inv_mod_xn() { + type F = GoldilocksField; + let mut rng = thread_rng(); + let a_deg = rng.gen_range(1..1_000); + let n = rng.gen_range(1..1_000); + let a = PolynomialCoeffs::new(F::rand_vec(a_deg)); + let b = a.inv_mod_xn(n); + let mut m = &a * &b; + m.coeffs.drain(n..); + m.trim(); + assert_eq!( + m, + PolynomialCoeffs::new(vec![F::ONE]), + "a: {:#?}, b:{:#?}, n:{:#?}, m:{:#?}", + a, + b, + n, + m + ); + } + + #[test] + fn test_polynomial_long_division() { + type F = GoldilocksField; + let mut rng = thread_rng(); + let (a_deg, b_deg) = (rng.gen_range(1..10_000), rng.gen_range(1..10_000)); + let a = PolynomialCoeffs::new(F::rand_vec(a_deg)); + let b = PolynomialCoeffs::new(F::rand_vec(b_deg)); + let (q, r) = a.div_rem_long_division(&b); + for _ in 0..1000 { + let x = F::rand(); + assert_eq!(a.eval(x), b.eval(x) * q.eval(x) + r.eval(x)); + } + } + + #[test] + fn test_polynomial_division() { + type F = GoldilocksField; + let mut rng = thread_rng(); + let (a_deg, b_deg) = (rng.gen_range(1..10_000), rng.gen_range(1..10_000)); + let a = PolynomialCoeffs::new(F::rand_vec(a_deg)); + let b = PolynomialCoeffs::new(F::rand_vec(b_deg)); + let (q, r) = a.div_rem(&b); + for _ in 0..1000 { + let x = F::rand(); + assert_eq!(a.eval(x), b.eval(x) * q.eval(x) + r.eval(x)); + } + } + + #[test] + fn test_polynomial_division_by_constant() { + type F = GoldilocksField; + let mut rng = thread_rng(); + let a_deg = rng.gen_range(1..10_000); + let a = PolynomialCoeffs::new(F::rand_vec(a_deg)); + let b = PolynomialCoeffs::from(vec![F::rand()]); + let (q, r) = a.div_rem(&b); + for _ in 0..1000 { + let x = F::rand(); + assert_eq!(a.eval(x), b.eval(x) * q.eval(x) + r.eval(x)); + } + } + + // Test to see which polynomial division method is faster for divisions of the type + // `(X^n - 1)/(X - a) + #[test] + fn test_division_linear() { + type F = GoldilocksField; + let mut rng = thread_rng(); + let l = 14; + let n = 1 << l; + let g = F::primitive_root_of_unity(l); + let xn_minus_one = { + let mut xn_min_one_vec = vec![F::ZERO; n + 1]; + xn_min_one_vec[n] = F::ONE; + xn_min_one_vec[0] = F::NEG_ONE; + PolynomialCoeffs::new(xn_min_one_vec) + }; + + let a = g.exp_u64(rng.gen_range(0..(n as u64))); + let denom = PolynomialCoeffs::new(vec![-a, F::ONE]); + let now = Instant::now(); + xn_minus_one.div_rem(&denom); + println!("Division time: {:?}", now.elapsed()); + let now = Instant::now(); + xn_minus_one.div_rem_long_division(&denom); + println!("Division time: {:?}", now.elapsed()); + } + + #[test] + fn eq() { + type F = GoldilocksField; + assert_eq!( + PolynomialCoeffs::::new(vec![]), + PolynomialCoeffs::new(vec![]) + ); + assert_eq!( + PolynomialCoeffs::::new(vec![F::ZERO]), + PolynomialCoeffs::new(vec![F::ZERO]) + ); + assert_eq!( + PolynomialCoeffs::::new(vec![]), + PolynomialCoeffs::new(vec![F::ZERO]) + ); + assert_eq!( + PolynomialCoeffs::::new(vec![F::ZERO]), + PolynomialCoeffs::new(vec![]) + ); + assert_eq!( + PolynomialCoeffs::::new(vec![F::ZERO]), + PolynomialCoeffs::new(vec![F::ZERO, F::ZERO]) + ); + assert_eq!( + PolynomialCoeffs::::new(vec![F::ONE]), + PolynomialCoeffs::new(vec![F::ONE, F::ZERO]) + ); + assert_ne!( + PolynomialCoeffs::::new(vec![]), + PolynomialCoeffs::new(vec![F::ONE]) + ); + assert_ne!( + PolynomialCoeffs::::new(vec![F::ZERO]), + PolynomialCoeffs::new(vec![F::ZERO, F::ONE]) + ); + assert_ne!( + PolynomialCoeffs::::new(vec![F::ZERO]), + PolynomialCoeffs::new(vec![F::ONE, F::ZERO]) + ); + } +} diff --git a/src/polynomial/polynomial.rs b/src/polynomial/polynomial.rs index b5a7fabd..43e17823 100644 --- a/src/polynomial/polynomial.rs +++ b/src/polynomial/polynomial.rs @@ -441,7 +441,7 @@ mod tests { assert_eq!(coset_evals, naive_coset_evals); let ifft_coeffs = PolynomialValues::new(coset_evals).coset_ifft(shift); - assert_eq!(poly, ifft_coeffs.into()); + assert_eq!(poly, ifft_coeffs); } #[test] diff --git a/src/util/mod.rs b/src/util/mod.rs index 586033be..fca6b728 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,7 +1,7 @@ use core::hint::unreachable_unchecked; use crate::field::field_types::Field; -use crate::polynomial::polynomial::PolynomialValues; +use crate::polynomial::PolynomialValues; pub(crate) mod bimap; pub(crate) mod context_tree; diff --git a/src/util/partial_products.rs b/src/util/partial_products.rs index 0f3c9bfa..b5e805e9 100644 --- a/src/util/partial_products.rs +++ b/src/util/partial_products.rs @@ -13,7 +13,7 @@ pub(crate) fn quotient_chunk_products( max_degree: usize, ) -> Vec { debug_assert!(max_degree > 1); - assert!(quotient_values.len() > 0); + assert!(!quotient_values.is_empty()); let chunk_size = max_degree; quotient_values .chunks(chunk_size) @@ -24,7 +24,7 @@ pub(crate) fn quotient_chunk_products( /// Compute partial products of the original vector `v` such that all products consist of `max_degree` /// or less elements. This is done until we've computed the product `P` of all elements in the vector. pub(crate) fn partial_products_and_z_gx(z_x: F, quotient_chunk_products: &[F]) -> Vec { - assert!(quotient_chunk_products.len() > 0); + assert!(!quotient_chunk_products.is_empty()); let mut res = Vec::new(); let mut acc = z_x; for "ient_chunk_product in quotient_chunk_products { diff --git a/src/util/reducing.rs b/src/util/reducing.rs index f700a6ff..4fc15690 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -8,7 +8,7 @@ use crate::gates::reducing::ReducingGate; use crate::gates::reducing_extension::ReducingExtensionGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::polynomial::polynomial::PolynomialCoeffs; +use crate::polynomial::PolynomialCoeffs; /// When verifying the composition polynomial in FRI we have to compute sums of the form /// `(sum_0^k a^i * x_i)/d_0 + (sum_k^r a^i * y_i)/d_1` diff --git a/src/util/serialization.rs b/src/util/serialization.rs index 5ca4f691..b3a51b5f 100644 --- a/src/util/serialization.rs +++ b/src/util/serialization.rs @@ -15,7 +15,7 @@ use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::proof::{ CompressedProof, CompressedProofWithPublicInputs, OpeningSet, Proof, ProofWithPublicInputs, }; -use crate::polynomial::polynomial::PolynomialCoeffs; +use crate::polynomial::PolynomialCoeffs; #[derive(Debug)] pub struct Buffer(Cursor>); diff --git a/src/util/timing.rs b/src/util/timing.rs index cd9ea731..4250d688 100644 --- a/src/util/timing.rs +++ b/src/util/timing.rs @@ -92,7 +92,7 @@ impl TimingTree { fn duration(&self) -> Duration { self.exit_time - .unwrap_or(Instant::now()) + .unwrap_or_else(Instant::now) .duration_since(self.enter_time) }