Skip to content

Commit

Permalink
elliptic-curve: remove references from batch generic params (#1403)
Browse files Browse the repository at this point in the history
Previously the traits were generic around a reference type. The problem
with that is reference types have lifetimes, which requires notating
them in generic code, in this case requiring an HRTB per generic
parameter.

HRTBs work because the output has no lifetime dependencies on the input,
but if that's the case we can just explicitly borrow in the trait, which
means no HRTB is needed in generic code, which makes notating the trait
bounds significantly simpler.
  • Loading branch information
tarcieri authored Nov 15, 2023
1 parent 2af0350 commit 4a66334
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 11 deletions.
4 changes: 2 additions & 2 deletions elliptic-curve/src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ pub trait PrimeCurveArithmetic:
}

/// Normalize point(s) in projective representation by converting them to their affine ones.
pub trait BatchNormalize<Points>: group::Curve {
pub trait BatchNormalize<Points: ?Sized>: group::Curve {
/// The output of the batch normalization; a container of affine points.
type Output: AsRef<[Self::AffineRepr]>;

/// Perform a batched conversion to affine representation on a sequence of projective points
/// at an amortized cost that should be practically as efficient as a single conversion.
/// Internally, implementors should rely upon `InvertBatch`.
fn batch_normalize(points: Points) -> <Self as BatchNormalize<Points>>::Output;
fn batch_normalize(points: &Points) -> <Self as BatchNormalize<Points>>::Output;
}
20 changes: 11 additions & 9 deletions elliptic-curve/src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,27 @@ pub trait Invert {

/// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars)
/// at an amortized cost that should be practically as efficient as a single inversion.
pub trait BatchInvert<FieldElements>: Invert {
pub trait BatchInvert<FieldElements: ?Sized>: Invert + Sized {
/// The output of batch inversion. A container of field elements.
type Output;
type Output: AsRef<[Self]>;

/// Invert a batch of field elements.
fn batch_invert(field_elements: FieldElements) -> <Self as BatchInvert<FieldElements>>::Output;
fn batch_invert(
field_elements: &FieldElements,
) -> CtOption<<Self as BatchInvert<FieldElements>>::Output>;
}

impl<const N: usize, T> BatchInvert<&[T; N]> for T
impl<const N: usize, T> BatchInvert<[T; N]> for T
where
T: Invert<Output = CtOption<Self>>
+ Mul<Self, Output = Self>
+ Copy
+ Default
+ ConditionallySelectable,
{
type Output = CtOption<[Self; N]>;
type Output = [Self; N];

fn batch_invert(field_elements: &[Self; N]) -> <Self as BatchInvert<&[T; N]>>::Output {
fn batch_invert(field_elements: &[Self; N]) -> CtOption<[Self; N]> {
let mut field_elements_multiples = [Self::default(); N];
let mut field_elements_multiples_inverses = [Self::default(); N];
let mut field_elements_inverses = [Self::default(); N];
Expand All @@ -66,17 +68,17 @@ where
}

#[cfg(feature = "alloc")]
impl<T> BatchInvert<&[T]> for T
impl<T> BatchInvert<[T]> for T
where
T: Invert<Output = CtOption<Self>>
+ Mul<Self, Output = Self>
+ Copy
+ Default
+ ConditionallySelectable,
{
type Output = CtOption<Vec<Self>>;
type Output = Vec<Self>;

fn batch_invert(field_elements: &[Self]) -> <Self as BatchInvert<&[T]>>::Output {
fn batch_invert(field_elements: &[Self]) -> CtOption<Vec<Self>> {
let mut field_elements_multiples: Vec<Self> = vec![Self::default(); field_elements.len()];
let mut field_elements_multiples_inverses: Vec<Self> =
vec![Self::default(); field_elements.len()];
Expand Down

0 comments on commit 4a66334

Please sign in to comment.