Skip to content

Commit 2156207

Browse files
committed
refactor: Don't require trait to invert element
1 parent 511159c commit 2156207

File tree

4 files changed

+54
-38
lines changed

4 files changed

+54
-38
lines changed

twenty-first/benches/inverses.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ use criterion::Criterion;
55
use itertools::Itertools;
66
use twenty_first::math::b_field_element::BFieldElement;
77
use twenty_first::math::other::random_elements;
8-
use twenty_first::math::traits::Inverse;
98

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

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

twenty-first/src/math/b_field_element.rs

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,40 @@ impl BFieldElement {
234234
self.canonical_representation()
235235
}
236236

237+
#[must_use]
238+
#[inline]
239+
pub fn inverse(&self) -> Self {
240+
#[inline(always)]
241+
const fn exp(base: BFieldElement, exponent: u64) -> BFieldElement {
242+
let mut res = base;
243+
let mut i = 0;
244+
while i < exponent {
245+
res = BFieldElement(BFieldElement::montyred(res.0 as u128 * res.0 as u128));
246+
i += 1;
247+
}
248+
res
249+
}
250+
251+
let x = *self;
252+
assert_ne!(
253+
x,
254+
Self::zero(),
255+
"Attempted to find the multiplicative inverse of zero."
256+
);
257+
258+
let bin_2_ones = x.square() * x;
259+
let bin_3_ones = bin_2_ones.square() * x;
260+
let bin_6_ones = exp(bin_3_ones, 3) * bin_3_ones;
261+
let bin_12_ones = exp(bin_6_ones, 6) * bin_6_ones;
262+
let bin_24_ones = exp(bin_12_ones, 12) * bin_12_ones;
263+
let bin_30_ones = exp(bin_24_ones, 6) * bin_6_ones;
264+
let bin_31_ones = bin_30_ones.square() * x;
265+
let bin_31_ones_1_zero = bin_31_ones.square();
266+
let bin_32_ones = bin_31_ones.square() * x;
267+
268+
exp(bin_31_ones_1_zero, 32) * bin_32_ones
269+
}
270+
237271
#[inline]
238272
/// Square the base M times and multiply the result by the tail value
239273
pub const fn power_accumulator<const N: usize, const M: usize>(
@@ -582,35 +616,7 @@ impl Inverse for BFieldElement {
582616
#[must_use]
583617
#[inline]
584618
fn inverse(&self) -> Self {
585-
let x = *self;
586-
assert_ne!(
587-
x,
588-
Self::zero(),
589-
"Attempted to find the multiplicative inverse of zero."
590-
);
591-
592-
#[inline(always)]
593-
const fn exp(base: BFieldElement, exponent: u64) -> BFieldElement {
594-
let mut res = base;
595-
let mut i = 0;
596-
while i < exponent {
597-
res = BFieldElement(BFieldElement::montyred(res.0 as u128 * res.0 as u128));
598-
i += 1;
599-
}
600-
res
601-
}
602-
603-
let bin_2_ones = x.square() * x;
604-
let bin_3_ones = bin_2_ones.square() * x;
605-
let bin_6_ones = exp(bin_3_ones, 3) * bin_3_ones;
606-
let bin_12_ones = exp(bin_6_ones, 6) * bin_6_ones;
607-
let bin_24_ones = exp(bin_12_ones, 12) * bin_12_ones;
608-
let bin_30_ones = exp(bin_24_ones, 6) * bin_6_ones;
609-
let bin_31_ones = bin_30_ones.square() * x;
610-
let bin_31_ones_1_zero = bin_31_ones.square();
611-
let bin_32_ones = bin_31_ones.square() * x;
612-
613-
exp(bin_31_ones_1_zero, 32) * bin_32_ones
619+
self.inverse()
614620
}
615621
}
616622

twenty-first/src/math/traits.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ pub trait Inverse
2828
where
2929
Self: Sized + Zero,
3030
{
31+
/// The multiplicative inverse: `a * a.inverse() == 1`
32+
///
33+
/// # Panics
34+
///
35+
/// Panics if `self` does not have a multiplicative inverse, for example, when
36+
/// `self` is zero. (For fields, this is the only case.)
3137
fn inverse(&self) -> Self;
3238

3339
fn inverse_or_zero(&self) -> Self {

twenty-first/src/math/x_field_element.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,17 @@ impl XFieldElement {
278278
Self::new([element, zero, zero])
279279
}
280280

281+
#[must_use]
282+
pub fn inverse(&self) -> Self {
283+
assert!(
284+
!self.is_zero(),
285+
"Cannot invert the zero element in the extension field."
286+
);
287+
let self_as_poly: Polynomial<BFieldElement> = self.to_owned().into();
288+
let (_, a, _) = Polynomial::<BFieldElement>::xgcd(self_as_poly, Self::shah_polynomial());
289+
a.into()
290+
}
291+
281292
pub fn unlift(&self) -> Option<BFieldElement> {
282293
if self.coefficients[1].is_zero() && self.coefficients[2].is_zero() {
283294
Some(self.coefficients[0])
@@ -299,13 +310,7 @@ impl XFieldElement {
299310
impl Inverse for XFieldElement {
300311
#[must_use]
301312
fn inverse(&self) -> Self {
302-
assert!(
303-
!self.is_zero(),
304-
"Cannot invert the zero element in the extension field."
305-
);
306-
let self_as_poly: Polynomial<BFieldElement> = self.to_owned().into();
307-
let (_, a, _) = Polynomial::<BFieldElement>::xgcd(self_as_poly, Self::shah_polynomial());
308-
a.into()
313+
self.inverse()
309314
}
310315
}
311316

0 commit comments

Comments
 (0)