From 5913fd71b91ba3dbaabc8bb00e30d164e9fb51ec Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Wed, 28 Apr 2021 13:46:33 -0700 Subject: [PATCH 1/2] Add methods for MDS matrices The defaults are quite slow, but we will override them with fast, precomputed, field-specific matrices; see #4. --- src/field/field.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/field/field.rs b/src/field/field.rs index b52045e4..181b6ac8 100644 --- a/src/field/field.rs +++ b/src/field/field.rs @@ -1,11 +1,12 @@ +use std::convert::TryInto; use std::fmt::{Debug, Display}; use std::hash::Hash; use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use num::Integer; -use rand::rngs::OsRng; use rand::Rng; +use rand::rngs::OsRng; use crate::util::bits_u64; @@ -232,6 +233,35 @@ pub trait Field: } } + /// Apply an MDS matrix to the given vector. Any MDS matrix can be used, as long as the same one + /// is used among calls with the same vector length. + /// + /// Note that the default implementation is quite slow. If speed is important, this should be + /// overridden with a field-specific implementation which applies a precomputed MDS matrix. + fn mds(vec: Vec) -> Vec { + // We use a Cauchy matrix with x_r = n + r, y_c = c. + let n = vec.len(); + let mut result = Vec::with_capacity(n); + for r in 0..n { + let mut sum = Self::ZERO; + for c in 0..n { + let x = Self::from_canonical_usize(n + r); + let y = Self::from_canonical_usize(c); + // This is the (r, c) entry of the Cauchy matrix. + let entry = (x - y).inverse(); + sum += entry * vec[c]; + } + result.push(sum); + } + result + } + + /// Like `mds`, but specialized to n=8. For specific fields, this can be overridden with an + /// impl which applies a fast, precomputed 8x8 MDS matrix. + fn mds_8(vec: [Self; 8]) -> [Self; 8] { + Self::mds(vec.to_vec()).try_into().unwrap() + } + fn rand_from_rng(rng: &mut R) -> Self { Self::from_canonical_u64(rng.gen_range(0, Self::ORDER)) } From 6db30c6db355e621374308cdfed34414d5ae7d42 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Wed, 28 Apr 2021 14:42:21 -0700 Subject: [PATCH 2/2] Precomputed MDS matrix for CrandallField --- src/field/crandall_field.rs | 95 +++++++++++++++++++++++++++++++++++++ src/field/field.rs | 2 +- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/field/crandall_field.rs b/src/field/crandall_field.rs index 1ff8d9d4..b874578d 100644 --- a/src/field/crandall_field.rs +++ b/src/field/crandall_field.rs @@ -11,6 +11,90 @@ use std::iter::{Product, Sum}; /// EPSILON = 9 * 2**28 - 1 const EPSILON: u64 = 2415919103; +/// A precomputed 8*8 Cauchy matrix, generated with `Field::mds_8`. +const CAUCHY_MDS_8: [[CrandallField; 8]; 8] = [ + [ + CrandallField(16140901062381928449), + CrandallField(2635249153041947502), + CrandallField(3074457345215605419), + CrandallField(11068046442776179508), + CrandallField(13835058053470224385), + CrandallField(6148914690431210838), + CrandallField(9223372035646816257), + CrandallField(1), + ], + [ + CrandallField(2049638230143736946), + CrandallField(16140901062381928449), + CrandallField(2635249153041947502), + CrandallField(3074457345215605419), + CrandallField(11068046442776179508), + CrandallField(13835058053470224385), + CrandallField(6148914690431210838), + CrandallField(9223372035646816257), + ], + [ + CrandallField(5534023221388089754), + CrandallField(2049638230143736946), + CrandallField(16140901062381928449), + CrandallField(2635249153041947502), + CrandallField(3074457345215605419), + CrandallField(11068046442776179508), + CrandallField(13835058053470224385), + CrandallField(6148914690431210838), + ], + [ + CrandallField(16769767337539665921), + CrandallField(5534023221388089754), + CrandallField(2049638230143736946), + CrandallField(16140901062381928449), + CrandallField(2635249153041947502), + CrandallField(3074457345215605419), + CrandallField(11068046442776179508), + CrandallField(13835058053470224385), + ], + [ + CrandallField(10760600708254618966), + CrandallField(16769767337539665921), + CrandallField(5534023221388089754), + CrandallField(2049638230143736946), + CrandallField(16140901062381928449), + CrandallField(2635249153041947502), + CrandallField(3074457345215605419), + CrandallField(11068046442776179508), + ], + [ + CrandallField(5675921252705733081), + CrandallField(10760600708254618966), + CrandallField(16769767337539665921), + CrandallField(5534023221388089754), + CrandallField(2049638230143736946), + CrandallField(16140901062381928449), + CrandallField(2635249153041947502), + CrandallField(3074457345215605419), + ], + [ + CrandallField(1317624576520973751), + CrandallField(5675921252705733081), + CrandallField(10760600708254618966), + CrandallField(16769767337539665921), + CrandallField(5534023221388089754), + CrandallField(2049638230143736946), + CrandallField(16140901062381928449), + CrandallField(2635249153041947502), + ], + [ + CrandallField(15987178195121148178), + CrandallField(1317624576520973751), + CrandallField(5675921252705733081), + CrandallField(10760600708254618966), + CrandallField(16769767337539665921), + CrandallField(5534023221388089754), + CrandallField(2049638230143736946), + CrandallField(16140901062381928449), + ], +]; + /// A field designed for use with the Crandall reduction algorithm. /// /// Its order is @@ -224,6 +308,17 @@ impl Field for CrandallField { let x74 = x73 * x39; x74 } + + fn mds_8(vec: [Self; 8]) -> [Self; 8] { + let mut result = [Self::ZERO; 8]; + for r in 0..8 { + for c in 0..8 { + let entry = CAUCHY_MDS_8[r][c]; + result[r] += entry * vec[c]; + } + } + result + } } impl Neg for CrandallField { diff --git a/src/field/field.rs b/src/field/field.rs index 181b6ac8..8497861f 100644 --- a/src/field/field.rs +++ b/src/field/field.rs @@ -5,8 +5,8 @@ use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use num::Integer; -use rand::Rng; use rand::rngs::OsRng; +use rand::Rng; use crate::util::bits_u64;