mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-06 20:20:34 +00:00
Introduce DeferredField trait with eager implementations
Add the `deferred` module with a `DeferredField` trait that enables accumulating multiple unreduced products before performing a single reduction. The trait uses an accumulation-based API: callers feed factor pairs into an `Accumulator` via `mul_accumulate` / `square_accumulate`, then call `reduce` once at the end. For now, both Fp and Fq implement the trait with `Accumulator = Self`, performing eager reduction on each accumulation. A later commit will swap in a wide accumulator that defers reduction for real. The module is feature-gated behind the `deferred` feature flag.
This commit is contained in:
parent
03d9e212b5
commit
c1ec4b7830
5 changed files with 77 additions and 0 deletions
|
|
@ -71,4 +71,5 @@ gpu = ["alloc", "ec-gpu"]
|
||||||
sqrt-table = ["alloc", "lazy_static"]
|
sqrt-table = ["alloc", "lazy_static"]
|
||||||
repr-c = []
|
repr-c = []
|
||||||
uninline-portable = []
|
uninline-portable = []
|
||||||
|
deferred = []
|
||||||
serde = ["hex", "serde_crate"]
|
serde = ["hex", "serde_crate"]
|
||||||
|
|
|
||||||
29
src/deferred.rs
Normal file
29
src/deferred.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
//! Deferred normalization for field arithmetic.
|
||||||
|
//!
|
||||||
|
//! This module provides the [`DeferredField`] trait, which enables accumulating
|
||||||
|
//! multiple unreduced products before performing a single expensive reduction.
|
||||||
|
//! This is useful for operations like inner products where many multiplications
|
||||||
|
//! feed into a sum.
|
||||||
|
|
||||||
|
use core::fmt::Debug;
|
||||||
|
|
||||||
|
/// A trait for fields that support deferred reduction of products.
|
||||||
|
///
|
||||||
|
/// Instead of reducing each multiplication result immediately, callers
|
||||||
|
/// accumulate products into an [`Accumulator`](Self::Accumulator) via
|
||||||
|
/// [`mul_accumulate`](Self::mul_accumulate) and
|
||||||
|
/// [`square_accumulate`](Self::square_accumulate), then perform a single
|
||||||
|
/// reduction at the end with [`reduce`](Self::reduce).
|
||||||
|
pub trait DeferredField: ff::Field {
|
||||||
|
/// A wide accumulator for unreduced products.
|
||||||
|
type Accumulator: Copy + Clone + Debug + Default;
|
||||||
|
|
||||||
|
/// Multiplies `a` by `b` and adds the result into `acc`.
|
||||||
|
fn mul_accumulate(acc: &mut Self::Accumulator, a: &Self, b: &Self);
|
||||||
|
|
||||||
|
/// Squares `a` and adds the result into `acc`.
|
||||||
|
fn square_accumulate(acc: &mut Self::Accumulator, a: &Self);
|
||||||
|
|
||||||
|
/// Reduces the accumulator to a canonical field element.
|
||||||
|
fn reduce(acc: Self::Accumulator) -> Self;
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,8 @@ use lazy_static::lazy_static;
|
||||||
use ff::{FieldBits, PrimeFieldBits};
|
use ff::{FieldBits, PrimeFieldBits};
|
||||||
|
|
||||||
use crate::arithmetic::{adc, mac, sbb, SqrtTableHelpers};
|
use crate::arithmetic::{adc, mac, sbb, SqrtTableHelpers};
|
||||||
|
#[cfg(feature = "deferred")]
|
||||||
|
use crate::deferred::DeferredField;
|
||||||
|
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use crate::arithmetic::SqrtTables;
|
use crate::arithmetic::SqrtTables;
|
||||||
|
|
@ -477,6 +479,26 @@ impl Fp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "deferred")]
|
||||||
|
impl DeferredField for Fp {
|
||||||
|
type Accumulator = Fp;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul_accumulate(acc: &mut Fp, a: &Fp, b: &Fp) {
|
||||||
|
*acc += *a * *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn square_accumulate(acc: &mut Fp, a: &Fp) {
|
||||||
|
*acc += a.square();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn reduce(acc: Fp) -> Fp {
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Fp> for [u8; 32] {
|
impl From<Fp> for [u8; 32] {
|
||||||
fn from(value: Fp) -> [u8; 32] {
|
fn from(value: Fp) -> [u8; 32] {
|
||||||
value.to_repr()
|
value.to_repr()
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ use lazy_static::lazy_static;
|
||||||
use ff::{FieldBits, PrimeFieldBits};
|
use ff::{FieldBits, PrimeFieldBits};
|
||||||
|
|
||||||
use crate::arithmetic::{adc, mac, sbb, SqrtTableHelpers};
|
use crate::arithmetic::{adc, mac, sbb, SqrtTableHelpers};
|
||||||
|
#[cfg(feature = "deferred")]
|
||||||
|
use crate::deferred::DeferredField;
|
||||||
|
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use crate::arithmetic::SqrtTables;
|
use crate::arithmetic::SqrtTables;
|
||||||
|
|
@ -477,6 +479,26 @@ impl Fq {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "deferred")]
|
||||||
|
impl DeferredField for Fq {
|
||||||
|
type Accumulator = Fq;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul_accumulate(acc: &mut Fq, a: &Fq, b: &Fq) {
|
||||||
|
*acc += *a * *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn square_accumulate(acc: &mut Fq, a: &Fq) {
|
||||||
|
*acc += a.square();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn reduce(acc: Fq) -> Fq {
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Fq> for [u8; 32] {
|
impl From<Fq> for [u8; 32] {
|
||||||
fn from(value: Fq) -> [u8; 32] {
|
fn from(value: Fq) -> [u8; 32] {
|
||||||
value.to_repr()
|
value.to_repr()
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ mod curves;
|
||||||
mod fields;
|
mod fields;
|
||||||
|
|
||||||
pub mod arithmetic;
|
pub mod arithmetic;
|
||||||
|
#[cfg(feature = "deferred")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "deferred")))]
|
||||||
|
pub mod deferred;
|
||||||
pub mod pallas;
|
pub mod pallas;
|
||||||
pub mod vesta;
|
pub mod vesta;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue