Skip to content

Commit

Permalink
refactor: Don't require trait to invert element
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-ferdinand committed Jan 29, 2025
1 parent 511159c commit 2156207
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 38 deletions.
3 changes: 1 addition & 2 deletions twenty-first/benches/inverses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ use criterion::Criterion;
use itertools::Itertools;
use twenty_first::math::b_field_element::BFieldElement;
use twenty_first::math::other::random_elements;
use twenty_first::math::traits::Inverse;

/// Run with `cargo criterion --bench inverse`
fn inverse(c: &mut Criterion) {
let mut group = c.benchmark_group("Inverses");
group.sample_size(10); // runs
let count = 1024 * 1024; // count of elements to be inversed per run
let count = 1024 * 1024; // count of elements to be inverted per run

let rnd_elems: Vec<BFieldElement> = random_elements(count);

Expand Down
64 changes: 35 additions & 29 deletions twenty-first/src/math/b_field_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,40 @@ impl BFieldElement {
self.canonical_representation()
}

#[must_use]
#[inline]
pub fn inverse(&self) -> Self {
#[inline(always)]
const fn exp(base: BFieldElement, exponent: u64) -> BFieldElement {
let mut res = base;
let mut i = 0;
while i < exponent {
res = BFieldElement(BFieldElement::montyred(res.0 as u128 * res.0 as u128));
i += 1;
}
res
}

let x = *self;
assert_ne!(
x,
Self::zero(),
"Attempted to find the multiplicative inverse of zero."
);

let bin_2_ones = x.square() * x;
let bin_3_ones = bin_2_ones.square() * x;
let bin_6_ones = exp(bin_3_ones, 3) * bin_3_ones;
let bin_12_ones = exp(bin_6_ones, 6) * bin_6_ones;
let bin_24_ones = exp(bin_12_ones, 12) * bin_12_ones;
let bin_30_ones = exp(bin_24_ones, 6) * bin_6_ones;
let bin_31_ones = bin_30_ones.square() * x;
let bin_31_ones_1_zero = bin_31_ones.square();
let bin_32_ones = bin_31_ones.square() * x;

exp(bin_31_ones_1_zero, 32) * bin_32_ones
}

#[inline]
/// Square the base M times and multiply the result by the tail value
pub const fn power_accumulator<const N: usize, const M: usize>(
Expand Down Expand Up @@ -582,35 +616,7 @@ impl Inverse for BFieldElement {
#[must_use]
#[inline]
fn inverse(&self) -> Self {
let x = *self;
assert_ne!(
x,
Self::zero(),
"Attempted to find the multiplicative inverse of zero."
);

#[inline(always)]
const fn exp(base: BFieldElement, exponent: u64) -> BFieldElement {
let mut res = base;
let mut i = 0;
while i < exponent {
res = BFieldElement(BFieldElement::montyred(res.0 as u128 * res.0 as u128));
i += 1;
}
res
}

let bin_2_ones = x.square() * x;
let bin_3_ones = bin_2_ones.square() * x;
let bin_6_ones = exp(bin_3_ones, 3) * bin_3_ones;
let bin_12_ones = exp(bin_6_ones, 6) * bin_6_ones;
let bin_24_ones = exp(bin_12_ones, 12) * bin_12_ones;
let bin_30_ones = exp(bin_24_ones, 6) * bin_6_ones;
let bin_31_ones = bin_30_ones.square() * x;
let bin_31_ones_1_zero = bin_31_ones.square();
let bin_32_ones = bin_31_ones.square() * x;

exp(bin_31_ones_1_zero, 32) * bin_32_ones
self.inverse()
}
}

Expand Down
6 changes: 6 additions & 0 deletions twenty-first/src/math/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ pub trait Inverse
where
Self: Sized + Zero,
{
/// The multiplicative inverse: `a * a.inverse() == 1`
///
/// # Panics
///
/// Panics if `self` does not have a multiplicative inverse, for example, when
/// `self` is zero. (For fields, this is the only case.)
fn inverse(&self) -> Self;

fn inverse_or_zero(&self) -> Self {
Expand Down
19 changes: 12 additions & 7 deletions twenty-first/src/math/x_field_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,17 @@ impl XFieldElement {
Self::new([element, zero, zero])
}

#[must_use]
pub fn inverse(&self) -> Self {
assert!(
!self.is_zero(),
"Cannot invert the zero element in the extension field."
);
let self_as_poly: Polynomial<BFieldElement> = self.to_owned().into();
let (_, a, _) = Polynomial::<BFieldElement>::xgcd(self_as_poly, Self::shah_polynomial());
a.into()
}

pub fn unlift(&self) -> Option<BFieldElement> {
if self.coefficients[1].is_zero() && self.coefficients[2].is_zero() {
Some(self.coefficients[0])
Expand All @@ -299,13 +310,7 @@ impl XFieldElement {
impl Inverse for XFieldElement {
#[must_use]
fn inverse(&self) -> Self {
assert!(
!self.is_zero(),
"Cannot invert the zero element in the extension field."
);
let self_as_poly: Polynomial<BFieldElement> = self.to_owned().into();
let (_, a, _) = Polynomial::<BFieldElement>::xgcd(self_as_poly, Self::shah_polynomial());
a.into()
self.inverse()
}
}

Expand Down

0 comments on commit 2156207

Please sign in to comment.