From 095fc4e65b87e6375ff54bc7c3b38ddf44de9711 Mon Sep 17 00:00:00 2001 From: Alon Titelman Date: Sun, 15 Sep 2024 15:58:14 +0300 Subject: [PATCH] Change Eval Framework `Copy` requirement to `Clone`. --- .../prover/src/constraint_framework/logup.rs | 22 ++-- crates/prover/src/constraint_framework/mod.rs | 11 +- crates/prover/src/core/backend/simd/circle.rs | 8 +- .../src/core/backend/simd/very_packed_m31.rs | 48 ++++++-- crates/prover/src/core/circle.rs | 26 ++-- crates/prover/src/core/fft.rs | 4 +- crates/prover/src/core/fields/m31.rs | 12 +- crates/prover/src/core/fields/mod.rs | 34 ++--- crates/prover/src/core/lookups/utils.rs | 53 +++++--- crates/prover/src/core/poly/line.rs | 2 +- crates/prover/src/core/poly/utils.rs | 4 +- crates/prover/src/core/utils.rs | 2 +- crates/prover/src/examples/blake/mod.rs | 7 +- .../src/examples/blake/round/constraints.rs | 116 ++++++++++++------ .../examples/blake/scheduler/constraints.rs | 18 +-- .../examples/blake/xor_table/constraints.rs | 8 +- crates/prover/src/examples/plonk/mod.rs | 7 +- crates/prover/src/examples/poseidon/mod.rs | 72 +++++------ .../prover/src/examples/wide_fibonacci/mod.rs | 2 +- .../src/examples/xor/gkr_lookups/mle_eval.rs | 6 +- crates/prover/src/math/matrix.rs | 6 +- 21 files changed, 276 insertions(+), 192 deletions(-) diff --git a/crates/prover/src/constraint_framework/logup.rs b/crates/prover/src/constraint_framework/logup.rs index 03f55bda5..387a8600f 100644 --- a/crates/prover/src/constraint_framework/logup.rs +++ b/crates/prover/src/constraint_framework/logup.rs @@ -64,9 +64,9 @@ impl LogupAtRow { pub fn write_frac(&mut self, eval: &mut E, fraction: Fraction) { // Add a constraint that num / denom = diff. - if let Some(cur_frac) = self.cur_frac { - let cur_cumsum = eval.next_extension_interaction_mask(self.interaction, [0])[0]; - let diff = cur_cumsum - self.prev_col_cumsum; + if let Some(cur_frac) = self.cur_frac.clone() { + let [cur_cumsum] = eval.next_extension_interaction_mask(self.interaction, [0]); + let diff = cur_cumsum.clone() - self.prev_col_cumsum.clone(); self.prev_col_cumsum = cur_cumsum; eval.add_constraint(diff * cur_frac.denominator - cur_frac.numerator); } @@ -76,7 +76,7 @@ impl LogupAtRow { pub fn finalize(mut self, eval: &mut E) { assert!(!self.is_finalized, "LogupAtRow was already finalized"); - let frac = self.cur_frac.unwrap(); + let frac = self.cur_frac.clone().unwrap(); // TODO(ShaharS): remove `claimed_row_index` interaction value and get the shifted offset // from the is_first column when constant columns are supported. @@ -89,7 +89,7 @@ impl LogupAtRow { ); // Constrain that the claimed_sum in case that it is not equal to the total_sum. - eval.add_constraint((claimed_cumsum - claimed_sum) * self.is_first); + eval.add_constraint((claimed_cumsum - claimed_sum) * self.is_first.clone()); (cur_cumsum, prev_row_cumsum) } None => { @@ -99,8 +99,8 @@ impl LogupAtRow { } }; // Fix `prev_row_cumsum` by subtracting `total_sum` if this is the first row. - let fixed_prev_row_cumsum = prev_row_cumsum - self.is_first * self.total_sum; - let diff = cur_cumsum - fixed_prev_row_cumsum - self.prev_col_cumsum; + let fixed_prev_row_cumsum = prev_row_cumsum - self.is_first.clone() * self.total_sum; + let diff = cur_cumsum - fixed_prev_row_cumsum - self.prev_col_cumsum.clone(); eval.add_constraint(diff * frac.denominator - frac.numerator); @@ -138,9 +138,9 @@ impl LookupElements { alpha_powers, } } - pub fn combine(&self, values: &[F]) -> EF + pub fn combine(&self, values: &[F]) -> EF where - EF: Copy + Zero + From + From + Mul + Sub, + EF: Clone + Zero + From + From + Mul + Sub, { assert!( self.alpha_powers.len() >= values.len(), @@ -149,8 +149,8 @@ impl LookupElements { values .iter() .zip(self.alpha_powers) - .fold(EF::zero(), |acc, (&value, power)| { - acc + EF::from(power) * value + .fold(EF::zero(), |acc, (value, power)| { + acc + EF::from(power) * value.clone() }) - EF::from(self.z) } diff --git a/crates/prover/src/constraint_framework/mod.rs b/crates/prover/src/constraint_framework/mod.rs index 6ca653708..b56c2b829 100644 --- a/crates/prover/src/constraint_framework/mod.rs +++ b/crates/prover/src/constraint_framework/mod.rs @@ -31,7 +31,7 @@ pub trait EvalAtRow { /// constraints. It might be [BaseField] packed types, or even [SecureField], when evaluating /// the columns out of domain. type F: FieldExpOps - + Copy + + Clone + Debug + Zero + Neg @@ -48,7 +48,7 @@ pub trait EvalAtRow { /// A field type representing the closure of `F` with multiplying by [SecureField]. Constraints /// usually get multiplied by [SecureField] values for security. type EF: One - + Copy + + Clone + Debug + Zero + From @@ -84,8 +84,11 @@ pub trait EvalAtRow { interaction: usize, offsets: [isize; N], ) -> [Self::EF; N] { - let res_col_major = array::from_fn(|_| self.next_interaction_mask(interaction, offsets)); - array::from_fn(|i| Self::combine_ef(res_col_major.map(|c| c[i]))) + let mut res_col_major = + array::from_fn(|_| self.next_interaction_mask(interaction, offsets).into_iter()); + array::from_fn(|_| { + Self::combine_ef(res_col_major.each_mut().map(|iter| iter.next().unwrap())) + }) } /// Adds a constraint to the component. diff --git a/crates/prover/src/core/backend/simd/circle.rs b/crates/prover/src/core/backend/simd/circle.rs index 1adb5e18e..d8e803f4c 100644 --- a/crates/prover/src/core/backend/simd/circle.rs +++ b/crates/prover/src/core/backend/simd/circle.rs @@ -35,9 +35,9 @@ impl SimdBackend { ); let mut product = F::one(); - for &num in mappings.iter() { + for num in mappings.iter() { if index & 1 == 1 { - product *= num; + product *= *num; } index >>= 1; if index == 0 { @@ -108,8 +108,8 @@ impl SimdBackend { .iter() .skip(1) .zip(denom_inverses.iter()) - .for_each(|(&m, &d)| { - steps.push(m * d); + .for_each(|(m, d)| { + steps.push(*m * *d); }); steps.push(F::one()); steps diff --git a/crates/prover/src/core/backend/simd/very_packed_m31.rs b/crates/prover/src/core/backend/simd/very_packed_m31.rs index 29f3d68a8..e7617b020 100644 --- a/crates/prover/src/core/backend/simd/very_packed_m31.rs +++ b/crates/prover/src/core/backend/simd/very_packed_m31.rs @@ -14,11 +14,11 @@ use crate::core::fields::FieldExpOps; pub const LOG_N_VERY_PACKED_ELEMS: u32 = 1; pub const N_VERY_PACKED_ELEMS: usize = 1 << LOG_N_VERY_PACKED_ELEMS; -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug, Copy)] #[repr(transparent)] -pub struct Vectorized(pub [A; N]); +pub struct Vectorized(pub [A; N]); -impl Vectorized { +impl Vectorized { pub fn from_fn(cb: F) -> Self where F: FnMut(usize) -> A, @@ -27,17 +27,18 @@ impl Vectorized { } } -impl From<[A; N]> for Vectorized { +impl From<[A; N]> for Vectorized { fn from(array: [A; N]) -> Self { Vectorized(array) } } -unsafe impl Zeroable for Vectorized { +unsafe impl Zeroable for Vectorized { fn zeroed() -> Self { unsafe { core::mem::zeroed() } } } + unsafe impl Pod for Vectorized {} pub type VeryPackedM31 = Vectorized; @@ -121,7 +122,10 @@ impl Scalar for PackedM31 {} impl Scalar for PackedCM31 {} impl Scalar for PackedQM31 {} -impl + Copy, B: Copy, const N: usize> Add> for Vectorized { +impl + Copy, B: Copy, const N: usize> Add> for Vectorized +where + >::Output: Copy, +{ type Output = Vectorized; fn add(self, other: Vectorized) -> Self::Output { @@ -129,7 +133,10 @@ impl + Copy, B: Copy, const N: usize> Add> for Vector } } -impl + Copy, B: Scalar + Copy, const N: usize> Add for Vectorized { +impl + Copy, B: Scalar + Copy, const N: usize> Add for Vectorized +where + >::Output: Copy, +{ type Output = Vectorized; fn add(self, other: B) -> Self::Output { @@ -137,7 +144,10 @@ impl + Copy, B: Scalar + Copy, const N: usize> Add for Vectorized + Copy, B: Copy, const N: usize> Sub> for Vectorized { +impl + Copy, B: Copy, const N: usize> Sub> for Vectorized +where + >::Output: Copy, +{ type Output = Vectorized; fn sub(self, other: Vectorized) -> Self::Output { @@ -145,7 +155,10 @@ impl + Copy, B: Copy, const N: usize> Sub> for Vector } } -impl + Copy, B: Scalar + Copy, const N: usize> Sub for Vectorized { +impl + Copy, B: Scalar + Copy, const N: usize> Sub for Vectorized +where + >::Output: Copy, +{ type Output = Vectorized; fn sub(self, other: B) -> Self::Output { @@ -153,7 +166,10 @@ impl + Copy, B: Scalar + Copy, const N: usize> Sub for Vectorized + Copy, B: Copy, const N: usize> Mul> for Vectorized { +impl + Copy, B: Copy, const N: usize> Mul> for Vectorized +where + >::Output: Copy, +{ type Output = Vectorized; fn mul(self, other: Vectorized) -> Self::Output { @@ -161,7 +177,10 @@ impl + Copy, B: Copy, const N: usize> Mul> for Vector } } -impl + Copy, B: Scalar + Copy, const N: usize> Mul for Vectorized { +impl + Copy, B: Scalar + Copy, const N: usize> Mul for Vectorized +where + >::Output: Copy, +{ type Output = Vectorized; fn mul(self, other: B) -> Self::Output { @@ -197,7 +216,10 @@ impl + Copy, B: Copy, const N: usize> MulAssign } } -impl Neg for Vectorized { +impl Neg for Vectorized +where + ::Output: Copy, +{ type Output = Vectorized; #[inline(always)] @@ -222,7 +244,7 @@ impl One for Vectorized { } } -impl FieldExpOps for Vectorized { +impl FieldExpOps for Vectorized { fn inverse(&self) -> Self { Vectorized::from_fn(|i| { assert!(!self.0[i].is_zero(), "0 has no inverse"); diff --git a/crates/prover/src/core/circle.rs b/crates/prover/src/core/circle.rs index 8804840fd..0fbdd64b4 100644 --- a/crates/prover/src/core/circle.rs +++ b/crates/prover/src/core/circle.rs @@ -25,7 +25,7 @@ impl + FieldExpOps + Sub + Neg } pub fn double(&self) -> Self { - *self + *self + self.clone() + self.clone() } /// Applies the circle's x-coordinate doubling map. @@ -40,7 +40,7 @@ impl + FieldExpOps + Sub + Neg /// ``` pub fn double_x(x: F) -> F { let sx = x.square(); - sx + sx - F::one() + sx.clone() + sx - F::one() } /// Returns the log order of a point. @@ -61,7 +61,7 @@ impl + FieldExpOps + Sub + Neg // we only need the x-coordinate to check order since the only point // with x=1 is the circle's identity let mut res = 0; - let mut cur = self.x; + let mut cur = self.x.clone(); while cur != F::one() { cur = Self::double_x(cur); res += 1; @@ -71,10 +71,10 @@ impl + FieldExpOps + Sub + Neg pub fn mul(&self, mut scalar: u128) -> CirclePoint { let mut res = Self::zero(); - let mut cur = *self; + let mut cur = self.clone(); while scalar > 0 { if scalar & 1 == 1 { - res = res + cur; + res = res + cur.clone(); } cur = cur.double(); scalar >>= 1; @@ -83,7 +83,7 @@ impl + FieldExpOps + Sub + Neg } pub fn repeated_double(&self, n: u32) -> Self { - let mut res = *self; + let mut res = self.clone(); for _ in 0..n { res = res.double(); } @@ -92,22 +92,22 @@ impl + FieldExpOps + Sub + Neg pub fn conjugate(&self) -> CirclePoint { Self { - x: self.x, - y: -self.y, + x: self.x.clone(), + y: -self.y.clone(), } } pub fn antipode(&self) -> CirclePoint { Self { - x: -self.x, - y: -self.y, + x: -self.x.clone(), + y: -self.y.clone(), } } pub fn into_ef>(&self) -> CirclePoint { CirclePoint { - x: self.x.into(), - y: self.y.into(), + x: self.x.clone().into(), + y: self.y.clone().into(), } } @@ -126,7 +126,7 @@ impl + FieldExpOps + Sub + Neg type Output = Self; fn add(self, rhs: Self) -> Self::Output { - let x = self.x * rhs.x - self.y * rhs.y; + let x = self.x.clone() * rhs.x.clone() - self.y.clone() * rhs.y.clone(); let y = self.x * rhs.y + self.y * rhs.x; Self { x, y } } diff --git a/crates/prover/src/core/fft.rs b/crates/prover/src/core/fft.rs index 630fbe738..47afbba95 100644 --- a/crates/prover/src/core/fft.rs +++ b/crates/prover/src/core/fft.rs @@ -4,7 +4,7 @@ use super::fields::m31::BaseField; pub fn butterfly(v0: &mut F, v1: &mut F, twid: BaseField) where - F: Copy + AddAssign + Sub + Mul, + F: AddAssign + Sub + Mul + Copy, { let tmp = *v1 * twid; *v1 = *v0 - tmp; @@ -13,7 +13,7 @@ where pub fn ibutterfly(v0: &mut F, v1: &mut F, itwid: BaseField) where - F: Copy + AddAssign + Add + Sub + Mul, + F: AddAssign + Add + Sub + Mul + Copy, { let tmp = *v0; *v0 = tmp + *v1; diff --git a/crates/prover/src/core/fields/m31.rs b/crates/prover/src/core/fields/m31.rs index 852f95909..a7c3c57a2 100644 --- a/crates/prover/src/core/fields/m31.rs +++ b/crates/prover/src/core/fields/m31.rs @@ -186,12 +186,12 @@ macro_rules! m31 { /// assert_eq!(pow2147483645(v), v.pow(2147483645)); /// ``` pub fn pow2147483645(v: T) -> T { - let t0 = sqn::<2, T>(v) * v; - let t1 = sqn::<1, T>(t0) * t0; - let t2 = sqn::<3, T>(t1) * t0; - let t3 = sqn::<1, T>(t2) * t0; - let t4 = sqn::<8, T>(t3) * t3; - let t5 = sqn::<8, T>(t4) * t3; + let t0 = sqn::<2, T>(v.clone()) * v.clone(); + let t1 = sqn::<1, T>(t0.clone()) * t0.clone(); + let t2 = sqn::<3, T>(t1.clone()) * t0.clone(); + let t3 = sqn::<1, T>(t2.clone()) * t0.clone(); + let t4 = sqn::<8, T>(t3.clone()) * t3.clone(); + let t5 = sqn::<8, T>(t4.clone()) * t3.clone(); sqn::<7, T>(t5) * t2 } diff --git a/crates/prover/src/core/fields/mod.rs b/crates/prover/src/core/fields/mod.rs index fbeefbb94..a7abaf799 100644 --- a/crates/prover/src/core/fields/mod.rs +++ b/crates/prover/src/core/fields/mod.rs @@ -16,18 +16,18 @@ pub trait FieldOps: ColumnOps { fn batch_inverse(column: &Self::Column, dst: &mut Self::Column); } -pub trait FieldExpOps: Mul + MulAssign + Sized + One + Copy { +pub trait FieldExpOps: Mul + MulAssign + Sized + One + Clone { fn square(&self) -> Self { - (*self) * (*self) + self.clone() * self.clone() } fn pow(&self, exp: u128) -> Self { let mut res = Self::one(); - let mut base = *self; + let mut base = self.clone(); let mut exp = exp; while exp > 0 { if exp & 1 == 1 { - res *= base; + res *= base.clone(); } base = base.square(); exp >>= 1; @@ -50,24 +50,24 @@ pub trait FieldExpOps: Mul + MulAssign + Sized + One + Copy { // First pass. Compute 'WIDTH' cumulative products in an interleaving fashion, reducing // instruction dependency and allowing better pipelining. - let mut cum_prod: [Self; WIDTH] = [Self::one(); WIDTH]; - dst[..WIDTH].copy_from_slice(&cum_prod); + let mut cum_prod: [Self; WIDTH] = std::array::from_fn(|_| Self::one()); + dst[..WIDTH].clone_from_slice(&cum_prod); for i in 0..n { - cum_prod[i % WIDTH] *= column[i]; - dst[i] = cum_prod[i % WIDTH]; + cum_prod[i % WIDTH] *= column[i].clone(); + dst[i] = cum_prod[i % WIDTH].clone(); } // Inverse cumulative products. // Use classic batch inversion. - let mut tail_inverses = [Self::one(); WIDTH]; + let mut tail_inverses: [Self; WIDTH] = std::array::from_fn(|_| Self::one()); batch_inverse_classic(&dst[n - WIDTH..], &mut tail_inverses); // Second pass. for i in (WIDTH..n).rev() { - dst[i] = dst[i - WIDTH] * tail_inverses[i % WIDTH]; - tail_inverses[i % WIDTH] *= column[i]; + dst[i] = dst[i - WIDTH].clone() * tail_inverses[i % WIDTH].clone(); + tail_inverses[i % WIDTH] *= column[i].clone(); } - dst[0..WIDTH].copy_from_slice(&tail_inverses); + dst[0..WIDTH].clone_from_slice(&tail_inverses); } } @@ -76,10 +76,10 @@ fn batch_inverse_classic(column: &[T], dst: &mut [T]) { let n = column.len(); debug_assert!(dst.len() >= n); - dst[0] = column[0]; + dst[0] = column[0].clone(); // First pass. for i in 1..n { - dst[i] = dst[i - 1] * column[i]; + dst[i] = dst[i - 1].clone() * column[i].clone(); } // Inverse cumulative product. @@ -87,8 +87,8 @@ fn batch_inverse_classic(column: &[T], dst: &mut [T]) { // Second pass. for i in (1..n).rev() { - dst[i] = dst[i - 1] * curr_inverse; - curr_inverse *= column[i]; + dst[i] = dst[i - 1].clone() * curr_inverse.clone(); + curr_inverse *= column[i].clone(); } dst[0] = curr_inverse; } @@ -113,7 +113,7 @@ pub trait Field: + for<'a> Sum<&'a Self> { fn double(&self) -> Self { - (*self) + (*self) + *self + *self } } diff --git a/crates/prover/src/core/lookups/utils.rs b/crates/prover/src/core/lookups/utils.rs index 85ea4c32a..035579e5f 100644 --- a/crates/prover/src/core/lookups/utils.rs +++ b/crates/prover/src/core/lookups/utils.rs @@ -27,20 +27,20 @@ impl UnivariatePoly { let mut coeffs = Self::zero(); - for (i, (&xi, &yi)) in zip(xs, ys).enumerate() { - let mut prod = yi; + for (i, (xi, yi)) in zip(xs, ys).enumerate() { + let mut prod = *yi; - for (j, &xj) in xs.iter().enumerate() { + for (j, xj) in xs.iter().enumerate() { if i != j { - prod /= xi - xj; + prod /= *xi - *xj; } } let mut term = Self::new(vec![prod]); - for (j, &xj) in xs.iter().enumerate() { + for (j, xj) in xs.iter().enumerate() { if i != j { - term = term * (Self::x() - Self::new(vec![xj])); + term = term * (Self::x() - Self::new(vec![*xj])); } } @@ -98,8 +98,8 @@ impl Mul for UnivariatePoly { let mut res = vec![F::zero(); self.0.len() + rhs.0.len() - 1]; for (i, coeff_a) in self.0.into_iter().enumerate() { - for (j, &coeff_b) in rhs.0.iter().enumerate() { - res[i + j] += coeff_a * coeff_b; + for (j, coeff_b) in rhs.0.iter().enumerate() { + res[i + j] += coeff_a * *coeff_b; } } @@ -116,8 +116,8 @@ impl Add for UnivariatePoly { for i in 0..n { res.push(match (self.0.get(i), rhs.0.get(i)) { - (Some(&a), Some(&b)) => a + b, - (Some(&a), None) | (None, Some(&a)) => a, + (Some(a), Some(b)) => *a + *b, + (Some(a), None) | (None, Some(a)) => *a, _ => unreachable!(), }) } @@ -166,7 +166,7 @@ impl Deref for UnivariatePoly { pub fn horner_eval(coeffs: &[F], x: F) -> F { coeffs .iter() - .rfold(F::zero(), |acc, &coeff| acc * x + coeff) + .rfold(F::zero(), |acc, coeff| acc * x + *coeff) } /// Returns `v_0 + alpha * v_1 + ... + alpha^(n-1) * v_{n-1}`. @@ -181,7 +181,7 @@ pub fn random_linear_combination(v: &[SecureField], alpha: SecureField) -> Secur pub fn eq(x: &[F], y: &[F]) -> F { assert_eq!(x.len(), y.len()); zip(x, y) - .map(|(&xi, &yi)| xi * yi + (F::one() - xi) * (F::one() - yi)) + .map(|(xi, yi)| *xi * *yi + (F::one() - *xi) * (F::one() - *yi)) .product() } @@ -195,12 +195,14 @@ where } /// Projective fraction. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct Fraction { pub numerator: N, pub denominator: D, } +impl Copy for Fraction {} + impl Fraction { pub fn new(numerator: N, denominator: D) -> Self { Self { @@ -210,14 +212,17 @@ impl Fraction { } } -impl + Add + Mul + Mul + Copy> Add - for Fraction +impl< + N: Clone, + D: Add + Add + Mul + Mul + Clone, + > Add for Fraction { type Output = Fraction; fn add(self, rhs: Self) -> Fraction { Fraction { - numerator: rhs.denominator * self.numerator + self.denominator * rhs.numerator, + numerator: rhs.denominator.clone() * self.numerator.clone() + + self.denominator.clone() * rhs.numerator.clone(), denominator: self.denominator * rhs.denominator, } } @@ -260,13 +265,25 @@ impl Reciprocal { } } -impl + Mul + Copy> Add for Reciprocal { +impl + Mul + Clone> Add for Reciprocal { type Output = Fraction; fn add(self, rhs: Self) -> Fraction { // `1/a + 1/b = (a + b)/(a * b)` Fraction { - numerator: self.x + rhs.x, + numerator: self.x.clone() + rhs.x.clone(), + denominator: self.x * rhs.x, + } + } +} + +impl + Mul + Clone> Sub for Reciprocal { + type Output = Fraction; + + fn sub(self, rhs: Self) -> Fraction { + // `1/a - 1/b = (b - a)/(a * b)` + Fraction { + numerator: rhs.x.clone() - self.x.clone(), denominator: self.x * rhs.x, } } diff --git a/crates/prover/src/core/poly/line.rs b/crates/prover/src/core/poly/line.rs index d5eb80980..62b24ac97 100644 --- a/crates/prover/src/core/poly/line.rs +++ b/crates/prover/src/core/poly/line.rs @@ -258,7 +258,7 @@ impl LineEvaluation { /// # Panics /// /// Panics if the number of values doesn't match the size of the domain. -fn line_ifft>(values: &mut [F], mut domain: LineDomain) { +fn line_ifft + Copy>(values: &mut [F], mut domain: LineDomain) { assert_eq!(values.len(), domain.size()); while domain.size() > 1 { for chunk in values.chunks_exact_mut(domain.size()) { diff --git a/crates/prover/src/core/poly/utils.rs b/crates/prover/src/core/poly/utils.rs index bc0dece77..fb2881a60 100644 --- a/crates/prover/src/core/poly/utils.rs +++ b/crates/prover/src/core/poly/utils.rs @@ -27,10 +27,10 @@ pub fn fold>(values: &[F], folding_factors: &[E]) -> return values[0].into(); } let (lhs_values, rhs_values) = values.split_at(n / 2); - let (&folding_factor, folding_factors) = folding_factors.split_first().unwrap(); + let (folding_factor, folding_factors) = folding_factors.split_first().unwrap(); let lhs_val = fold(lhs_values, folding_factors); let rhs_val = fold(rhs_values, folding_factors); - lhs_val + rhs_val * folding_factor + lhs_val + rhs_val * *folding_factor } /// Repeats each value sequentially `duplicity` many times. diff --git a/crates/prover/src/core/utils.rs b/crates/prover/src/core/utils.rs index 4532fa02a..628679d7c 100644 --- a/crates/prover/src/core/utils.rs +++ b/crates/prover/src/core/utils.rs @@ -254,7 +254,7 @@ mod tests { let n = 1 << log_size; let domain = CanonicCoset::new(log_size).circle_domain(); let values = (0..n).map(|i| m31!(i as u32)).collect_vec(); - let evaluation = CpuCircleEvaluation::<_, NaturalOrder>::new(domain, values.clone()); + let evaluation = CpuCircleEvaluation::<_, NaturalOrder>::new(domain, values); let bit_reversed_evaluation = evaluation.clone().bit_reverse(); // 2 ยท 14 diff --git a/crates/prover/src/examples/blake/mod.rs b/crates/prover/src/examples/blake/mod.rs index 6fbe6d81b..6bc504e61 100644 --- a/crates/prover/src/examples/blake/mod.rs +++ b/crates/prover/src/examples/blake/mod.rs @@ -88,11 +88,11 @@ impl BlakeXorElements { } /// Utility for representing a u32 as two field elements, for constraint evaluation. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] struct Fu32 where F: FieldExpOps - + Copy + + Clone + Debug + AddAssign + Add @@ -105,13 +105,14 @@ where impl Fu32 where F: FieldExpOps - + Copy + + Clone + Debug + AddAssign + Add + Sub + Mul, { + #[allow(clippy::wrong_self_convention)] fn to_felts(self) -> [F; 2] { [self.l, self.h] } diff --git a/crates/prover/src/examples/blake/round/constraints.rs b/crates/prover/src/examples/blake/round/constraints.rs index 0a2732d12..b5e415d14 100644 --- a/crates/prover/src/examples/blake/round/constraints.rs +++ b/crates/prover/src/examples/blake/round/constraints.rs @@ -5,7 +5,7 @@ use super::{BlakeXorElements, RoundElements}; use crate::constraint_framework::logup::LogupAtRow; use crate::constraint_framework::EvalAtRow; use crate::core::fields::m31::BaseField; -use crate::core::lookups::utils::Fraction; +use crate::core::lookups::utils::{Fraction, Reciprocal}; use crate::examples::blake::{Fu32, STATE_SIZE}; const INV16: BaseField = BaseField::from_u32_unchecked(1 << 15); @@ -20,17 +20,49 @@ pub struct BlakeRoundEval<'a, E: EvalAtRow> { impl<'a, E: EvalAtRow> BlakeRoundEval<'a, E> { pub fn eval(mut self) -> E { let mut v: [Fu32; STATE_SIZE] = std::array::from_fn(|_| self.next_u32()); - let input_v = v; + let input_v = v.clone(); let m: [Fu32; STATE_SIZE] = std::array::from_fn(|_| self.next_u32()); - self.g(v.get_many_mut([0, 4, 8, 12]).unwrap(), m[0], m[1]); - self.g(v.get_many_mut([1, 5, 9, 13]).unwrap(), m[2], m[3]); - self.g(v.get_many_mut([2, 6, 10, 14]).unwrap(), m[4], m[5]); - self.g(v.get_many_mut([3, 7, 11, 15]).unwrap(), m[6], m[7]); - self.g(v.get_many_mut([0, 5, 10, 15]).unwrap(), m[8], m[9]); - self.g(v.get_many_mut([1, 6, 11, 12]).unwrap(), m[10], m[11]); - self.g(v.get_many_mut([2, 7, 8, 13]).unwrap(), m[12], m[13]); - self.g(v.get_many_mut([3, 4, 9, 14]).unwrap(), m[14], m[15]); + self.g( + v.get_many_mut([0, 4, 8, 12]).unwrap(), + m[0].clone(), + m[1].clone(), + ); + self.g( + v.get_many_mut([1, 5, 9, 13]).unwrap(), + m[2].clone(), + m[3].clone(), + ); + self.g( + v.get_many_mut([2, 6, 10, 14]).unwrap(), + m[4].clone(), + m[5].clone(), + ); + self.g( + v.get_many_mut([3, 7, 11, 15]).unwrap(), + m[6].clone(), + m[7].clone(), + ); + self.g( + v.get_many_mut([0, 5, 10, 15]).unwrap(), + m[8].clone(), + m[9].clone(), + ); + self.g( + v.get_many_mut([1, 6, 11, 12]).unwrap(), + m[10].clone(), + m[11].clone(), + ); + self.g( + v.get_many_mut([2, 7, 8, 13]).unwrap(), + m[12].clone(), + m[13].clone(), + ); + self.g( + v.get_many_mut([3, 4, 9, 14]).unwrap(), + m[14].clone(), + m[15].clone(), + ); // Yield `Round(input_v, output_v, message)`. self.logup.write_frac( @@ -39,9 +71,9 @@ impl<'a, E: EvalAtRow> BlakeRoundEval<'a, E> { -E::EF::one(), self.round_lookup_elements.combine( &chain![ - input_v.iter().copied().flat_map(Fu32::to_felts), - v.iter().copied().flat_map(Fu32::to_felts), - m.iter().copied().flat_map(Fu32::to_felts) + input_v.iter().cloned().flat_map(Fu32::to_felts), + v.iter().cloned().flat_map(Fu32::to_felts), + m.iter().cloned().flat_map(Fu32::to_felts) ] .collect_vec(), ), @@ -59,14 +91,14 @@ impl<'a, E: EvalAtRow> BlakeRoundEval<'a, E> { fn g(&mut self, v: [&mut Fu32; 4], m0: Fu32, m1: Fu32) { let [a, b, c, d] = v; - *a = self.add3_u32_unchecked(*a, *b, m0); - *d = self.xor_rotr16_u32(*a, *d); - *c = self.add2_u32_unchecked(*c, *d); - *b = self.xor_rotr_u32(*b, *c, 12); - *a = self.add3_u32_unchecked(*a, *b, m1); - *d = self.xor_rotr_u32(*a, *d, 8); - *c = self.add2_u32_unchecked(*c, *d); - *b = self.xor_rotr_u32(*b, *c, 7); + *a = self.add3_u32_unchecked(a.clone(), b.clone(), m0); + *d = self.xor_rotr16_u32(a.clone(), d.clone()); + *c = self.add2_u32_unchecked(c.clone(), d.clone()); + *b = self.xor_rotr_u32(b.clone(), c.clone(), 12); + *a = self.add3_u32_unchecked(a.clone(), b.clone(), m1); + *d = self.xor_rotr_u32(a.clone(), d.clone(), 8); + *c = self.add2_u32_unchecked(c.clone(), d.clone()); + *b = self.xor_rotr_u32(b.clone(), c.clone(), 7); } /// Adds two u32s, returning the sum. @@ -77,11 +109,13 @@ impl<'a, E: EvalAtRow> BlakeRoundEval<'a, E> { let sl = self.eval.next_trace_mask(); let sh = self.eval.next_trace_mask(); - let carry_l = (a.l + b.l - sl) * E::F::from(INV16); - self.eval.add_constraint(carry_l * carry_l - carry_l); + let carry_l = (a.l + b.l - sl.clone()) * E::F::from(INV16); + self.eval + .add_constraint(carry_l.clone() * carry_l.clone() - carry_l.clone()); - let carry_h = (a.h + b.h + carry_l - sh) * E::F::from(INV16); - self.eval.add_constraint(carry_h * carry_h - carry_h); + let carry_h = (a.h + b.h + carry_l - sh.clone()) * E::F::from(INV16); + self.eval + .add_constraint(carry_h.clone() * carry_h.clone() - carry_h.clone()); Fu32 { l: sl, h: sh } } @@ -94,22 +128,27 @@ impl<'a, E: EvalAtRow> BlakeRoundEval<'a, E> { let sl = self.eval.next_trace_mask(); let sh = self.eval.next_trace_mask(); - let carry_l = (a.l + b.l + c.l - sl) * E::F::from(INV16); - self.eval - .add_constraint(carry_l * (carry_l - E::F::one()) * (carry_l - E::F::from(TWO))); + let carry_l = (a.l + b.l + c.l - sl.clone()) * E::F::from(INV16); + self.eval.add_constraint( + carry_l.clone() * (carry_l.clone() - E::F::one()) * (carry_l.clone() - E::F::from(TWO)), + ); - let carry_h = (a.h + b.h + c.h + carry_l - sh) * E::F::from(INV16); - self.eval - .add_constraint(carry_h * (carry_h - E::F::one()) * (carry_h - E::F::from(TWO))); + let carry_h = (a.h + b.h + c.h + carry_l - sh.clone()) * E::F::from(INV16); + self.eval.add_constraint( + carry_h.clone() * (carry_h.clone() - E::F::one()) * (carry_h.clone() - E::F::from(TWO)), + ); - Fu32 { l: sl, h: sh } + Fu32 { + l: sl, + h: sh.clone(), + } } /// Splits a felt at r. /// Caller is responsible for checking that the ranges of h * 2^r and l don't overlap. fn split_unchecked(&mut self, a: E::F, r: u32) -> (E::F, E::F) { let h = self.eval.next_trace_mask(); - let l = a - h * E::F::from(BaseField::from_u32_unchecked(1 << r)); + let l = a - h.clone() * E::F::from(BaseField::from_u32_unchecked(1 << r)); (l, h) } @@ -154,12 +193,11 @@ impl<'a, E: EvalAtRow> BlakeRoundEval<'a, E> { // TODO: Separate lookups by w. let c = [self.eval.next_trace_mask(), self.eval.next_trace_mask()]; let lookup_elements = self.xor_lookup_elements.get(w); - let comb0 = lookup_elements.combine::(&[a[0], b[0], c[0]]); - let comb1 = lookup_elements.combine::(&[a[1], b[1], c[1]]); - let frac = Fraction { - numerator: comb0 + comb1, - denominator: comb0 * comb1, - }; + let comb0 = + lookup_elements.combine::(&[a[0].clone(), b[0].clone(), c[0].clone()]); + let comb1 = + lookup_elements.combine::(&[a[1].clone(), b[1].clone(), c[1].clone()]); + let frac = Reciprocal::new(comb0) + Reciprocal::new(comb1); self.logup.write_frac(&mut self.eval, frac); c diff --git a/crates/prover/src/examples/blake/scheduler/constraints.rs b/crates/prover/src/examples/blake/scheduler/constraints.rs index 299a1e5b4..ea0ad2c34 100644 --- a/crates/prover/src/examples/blake/scheduler/constraints.rs +++ b/crates/prover/src/examples/blake/scheduler/constraints.rs @@ -4,7 +4,7 @@ use num_traits::Zero; use super::BlakeElements; use crate::constraint_framework::logup::LogupAtRow; use crate::constraint_framework::EvalAtRow; -use crate::core::lookups::utils::Fraction; +use crate::core::lookups::utils::{Fraction, Reciprocal}; use crate::core::vcs::blake2s_ref::SIGMA; use crate::examples::blake::round::RoundElements; use crate::examples::blake::{Fu32, N_ROUNDS, STATE_SIZE}; @@ -25,17 +25,17 @@ pub fn eval_blake_scheduler_constraints( let [denom_i, denom_j] = [i, j].map(|idx| { let input_state = &states[idx]; let output_state = &states[idx + 1]; - let round_messages = SIGMA[idx].map(|k| messages[k as usize]); + let round_messages = SIGMA[idx].map(|k| messages[k as usize].clone()); round_lookup_elements.combine::( &chain![ - input_state.iter().copied().flat_map(Fu32::to_felts), - output_state.iter().copied().flat_map(Fu32::to_felts), - round_messages.iter().copied().flat_map(Fu32::to_felts) + input_state.iter().cloned().flat_map(Fu32::to_felts), + output_state.iter().cloned().flat_map(Fu32::to_felts), + round_messages.iter().cloned().flat_map(Fu32::to_felts) ] .collect_vec(), ) }); - logup.write_frac(eval, Fraction::new(denom_i + denom_j, denom_i * denom_j)); + logup.write_frac(eval, Reciprocal::new(denom_i) + Reciprocal::new(denom_j)); } let input_state = &states[0]; @@ -48,9 +48,9 @@ pub fn eval_blake_scheduler_constraints( E::EF::zero(), blake_lookup_elements.combine( &chain![ - input_state.iter().copied().flat_map(Fu32::to_felts), - output_state.iter().copied().flat_map(Fu32::to_felts), - messages.iter().copied().flat_map(Fu32::to_felts) + input_state.iter().cloned().flat_map(Fu32::to_felts), + output_state.iter().cloned().flat_map(Fu32::to_felts), + messages.iter().cloned().flat_map(Fu32::to_felts) ] .collect_vec(), ), diff --git a/crates/prover/src/examples/blake/xor_table/constraints.rs b/crates/prover/src/examples/blake/xor_table/constraints.rs index f43d0088b..f1737e3f8 100644 --- a/crates/prover/src/examples/blake/xor_table/constraints.rs +++ b/crates/prover/src/examples/blake/xor_table/constraints.rs @@ -28,15 +28,15 @@ impl<'a, E: EvalAtRow, const ELEM_BITS: u32, const EXPAND_BITS: u32> let (i, j) = ((i >> EXPAND_BITS) as u32, (i % (1 << EXPAND_BITS)) as u32); let multiplicity = self.eval.next_trace_mask(); - let a = al + let a = al.clone() + E::F::from(BaseField::from_u32_unchecked( i << limb_bits::(), )); - let b = bl + let b = bl.clone() + E::F::from(BaseField::from_u32_unchecked( j << limb_bits::(), )); - let c = cl + let c = cl.clone() + E::F::from(BaseField::from_u32_unchecked( (i ^ j) << limb_bits::(), )); @@ -49,7 +49,7 @@ impl<'a, E: EvalAtRow, const ELEM_BITS: u32, const EXPAND_BITS: u32> .collect_vec(); for frac_chunk in frac_chunks.chunks(2) { - let sum_frac: Fraction = frac_chunk.iter().copied().sum(); + let sum_frac: Fraction = frac_chunk.iter().cloned().sum(); self.logup.write_frac(&mut self.eval, sum_frac); } self.logup.finalize(&mut self.eval); diff --git a/crates/prover/src/examples/plonk/mod.rs b/crates/prover/src/examples/plonk/mod.rs index 6d55cd484..db6502fc9 100644 --- a/crates/prover/src/examples/plonk/mod.rs +++ b/crates/prover/src/examples/plonk/mod.rs @@ -63,14 +63,17 @@ impl FrameworkEval for PlonkEval { let b_val = eval.next_trace_mask(); let c_val = eval.next_trace_mask(); - eval.add_constraint(c_val - op * (a_val + b_val) + (E::F::one() - op) * a_val * b_val); + eval.add_constraint( + c_val.clone() - op.clone() * (a_val.clone() + b_val.clone()) + + (E::F::one() - op) * a_val.clone() * b_val.clone(), + ); let denom_a: E::EF = self.lookup_elements.combine(&[a_wire, a_val]); let denom_b: E::EF = self.lookup_elements.combine(&[b_wire, b_val]); logup.write_frac( &mut eval, - Fraction::new(denom_a + denom_b, denom_a * denom_b), + Fraction::new(denom_a.clone() + denom_b.clone(), denom_a * denom_b), ); logup.write_frac( &mut eval, diff --git a/crates/prover/src/examples/poseidon/mod.rs b/crates/prover/src/examples/poseidon/mod.rs index 46c99dd92..0cbc3ebbd 100644 --- a/crates/prover/src/examples/poseidon/mod.rs +++ b/crates/prover/src/examples/poseidon/mod.rs @@ -19,7 +19,7 @@ use crate::core::channel::Blake2sChannel; use crate::core::fields::m31::BaseField; use crate::core::fields::qm31::SecureField; use crate::core::fields::FieldExpOps; -use crate::core::lookups::utils::Fraction; +use crate::core::lookups::utils::Reciprocal; use crate::core::pcs::{CommitmentSchemeProver, PcsConfig}; use crate::core::poly::circle::{CanonicCoset, CircleEvaluation, PolyOps}; use crate::core::poly::BitReversedOrder; @@ -71,18 +71,18 @@ impl FrameworkEval for PoseidonEval { /// Applies the M4 MDS matrix described in 5.1. fn apply_m4(x: [F; 4]) -> [F; 4] where - F: Copy + AddAssign + Add + Sub + Mul, + F: Clone + AddAssign + Add + Sub + Mul, { - let t0 = x[0] + x[1]; - let t02 = t0 + t0; - let t1 = x[2] + x[3]; - let t12 = t1 + t1; - let t2 = x[1] + x[1] + t1; - let t3 = x[3] + x[3] + t0; - let t4 = t12 + t12 + t3; - let t5 = t02 + t02 + t2; - let t6 = t3 + t5; - let t7 = t2 + t4; + let t0 = x[0].clone() + x[1].clone(); + let t02 = t0.clone() + t0.clone(); + let t1 = x[2].clone() + x[3].clone(); + let t12 = t1.clone() + t1.clone(); + let t2 = x[1].clone() + x[1].clone() + t1.clone(); + let t3 = x[3].clone() + x[3].clone() + t0.clone(); + let t4 = t12.clone() + t12.clone() + t3.clone(); + let t5 = t02.clone() + t02.clone() + t2.clone(); + let t6 = t3.clone() + t5.clone(); + let t7 = t2.clone() + t4.clone(); [t6, t5, t7, t4] } @@ -90,7 +90,7 @@ where /// See 5.1 and Appendix B. fn apply_external_round_matrix(state: &mut [F; 16]) where - F: Copy + AddAssign + Add + Sub + Mul, + F: Clone + AddAssign + Add + Sub + Mul, { // Applies circ(2M4, M4, M4, M4). for i in 0..4 { @@ -100,16 +100,17 @@ where state[4 * i + 2], state[4 * i + 3], ] = apply_m4([ - state[4 * i], - state[4 * i + 1], - state[4 * i + 2], - state[4 * i + 3], + state[4 * i].clone(), + state[4 * i + 1].clone(), + state[4 * i + 2].clone(), + state[4 * i + 3].clone(), ]); } for j in 0..4 { - let s = state[j] + state[j + 4] + state[j + 8] + state[j + 12]; + let s = + state[j].clone() + state[j + 4].clone() + state[j + 8].clone() + state[j + 12].clone(); for i in 0..4 { - state[4 * i + j] += s; + state[4 * i + j] += s.clone(); } } } @@ -119,21 +120,24 @@ where // See 5.2. fn apply_internal_round_matrix(state: &mut [F; 16]) where - F: Copy + AddAssign + Add + Sub + Mul, + F: Clone + AddAssign + Add + Sub + Mul, { // TODO(shahars): Check that these coefficients are good according to section 5.3 of Poseidon2 // paper. - let sum = state[1..].iter().fold(state[0], |acc, s| acc + *s); + let sum = state[1..] + .iter() + .cloned() + .fold(state[0].clone(), |acc, s| acc + s); state.iter_mut().enumerate().for_each(|(i, s)| { // TODO(andrew): Change to rotations. - *s = *s * BaseField::from_u32_unchecked(1 << (i + 1)) + sum; + *s = s.clone() * BaseField::from_u32_unchecked(1 << (i + 1)) + sum.clone(); }); } fn pow5(x: F) -> F { - let x2 = x * x; - let x4 = x2 * x2; - x4 * x + let x2 = x.clone() * x.clone(); + let x4 = x2.clone() * x2.clone(); + x4 * x.clone() } pub fn eval_poseidon_constraints( @@ -154,10 +158,10 @@ pub fn eval_poseidon_constraints( }); apply_external_round_matrix(&mut state); // TODO(andrew) Apply round matrix after the pow5, as is the order in the paper. - state = std::array::from_fn(|i| pow5(state[i])); + state = std::array::from_fn(|i| pow5(state[i].clone())); state.iter_mut().for_each(|s| { let m = eval.next_trace_mask(); - eval.add_constraint(*s - m); + eval.add_constraint(s.clone() - m.clone()); *s = m; }); }); @@ -166,9 +170,9 @@ pub fn eval_poseidon_constraints( (0..N_PARTIAL_ROUNDS).for_each(|round| { state[0] += INTERNAL_ROUND_CONSTS[round]; apply_internal_round_matrix(&mut state); - state[0] = pow5(state[0]); + state[0] = pow5(state[0].clone()); let m = eval.next_trace_mask(); - eval.add_constraint(state[0] - m); + eval.add_constraint(state[0].clone() - m.clone()); state[0] = m; }); @@ -178,23 +182,19 @@ pub fn eval_poseidon_constraints( state[i] += EXTERNAL_ROUND_CONSTS[round + N_HALF_FULL_ROUNDS][i]; }); apply_external_round_matrix(&mut state); - state = std::array::from_fn(|i| pow5(state[i])); + state = std::array::from_fn(|i| pow5(state[i].clone())); state.iter_mut().for_each(|s| { let m = eval.next_trace_mask(); - eval.add_constraint(*s - m); + eval.add_constraint(s.clone() - m.clone()); *s = m; }); }); // Provide state lookups. let final_state_denom: E::EF = lookup_elements.combine(&state); - // (1 / denom0) - (1 / denom1) = (denom1 - denom0) / (denom0 * denom1). logup.write_frac( eval, - Fraction::new( - final_state_denom - initial_state_denom, - initial_state_denom * final_state_denom, - ), + Reciprocal::new(initial_state_denom) - Reciprocal::new(final_state_denom), ); } diff --git a/crates/prover/src/examples/wide_fibonacci/mod.rs b/crates/prover/src/examples/wide_fibonacci/mod.rs index b8d9cb31e..2d9672b5e 100644 --- a/crates/prover/src/examples/wide_fibonacci/mod.rs +++ b/crates/prover/src/examples/wide_fibonacci/mod.rs @@ -35,7 +35,7 @@ impl FrameworkEval for WideFibonacciEval { let mut b = eval.next_trace_mask(); for _ in 2..N { let c = eval.next_trace_mask(); - eval.add_constraint(c - (a.square() + b.square())); + eval.add_constraint(c.clone() - (a.square() + b.square())); a = b; b = c; } diff --git a/crates/prover/src/examples/xor/gkr_lookups/mle_eval.rs b/crates/prover/src/examples/xor/gkr_lookups/mle_eval.rs index d11a9aaf0..b12da1350 100644 --- a/crates/prover/src/examples/xor/gkr_lookups/mle_eval.rs +++ b/crates/prover/src/examples/xor/gkr_lookups/mle_eval.rs @@ -108,12 +108,12 @@ fn eval_eq_constraints( // Check the initial value on half_coset0 and final value on half_coset1. // Combining these constraints is safe because `is_first` and `is_second` are never // non-zero at the same time on the trace. - let half_coset0_initial_check = (curr - mle_eval_point.eq_0_p) * is_first; - let half_coset1_final_check = (curr - mle_eval_point.eq_1_p) * is_second; + let half_coset0_initial_check = (curr.clone() - mle_eval_point.eq_0_p) * is_first; + let half_coset1_final_check = (curr.clone() - mle_eval_point.eq_1_p) * is_second; eval.add_constraint(half_coset0_initial_check + half_coset1_final_check); // Check all the steps. - eval.add_constraint(curr - next_next * carry_quotients_col_eval); + eval.add_constraint(curr.clone() - next_next * carry_quotients_col_eval); curr } diff --git a/crates/prover/src/math/matrix.rs b/crates/prover/src/math/matrix.rs index 697f862c3..c00e52b54 100644 --- a/crates/prover/src/math/matrix.rs +++ b/crates/prover/src/math/matrix.rs @@ -1,7 +1,7 @@ use crate::core::fields::m31::BaseField; use crate::core::fields::ExtensionOf; -pub trait SquareMatrix, const N: usize> { +pub trait SquareMatrix + Copy, const N: usize> { fn get_at(&self, i: usize, j: usize) -> F; fn mul(&self, v: [F; N]) -> [F; N] { (0..N) @@ -20,7 +20,7 @@ pub struct RowMajorMatrix, const N: usize> { values: [[F; N]; N], } -impl, const N: usize> RowMajorMatrix { +impl + Copy, const N: usize> RowMajorMatrix { pub fn new(values: Vec) -> Self { assert_eq!(values.len(), N * N); Self { @@ -34,7 +34,7 @@ impl, const N: usize> RowMajorMatrix { } } -impl, const N: usize> SquareMatrix for RowMajorMatrix { +impl + Copy, const N: usize> SquareMatrix for RowMajorMatrix { fn get_at(&self, i: usize, j: usize) -> F { self.values[i][j] }