@@ -322,8 +322,9 @@ impl CurveGroup for EdwardsPoint {
322322 #[ inline]
323323 fn batch_normalize ( projective : & [ Self ] , affine : & mut [ Self :: Affine ] ) {
324324 assert_eq ! ( projective. len( ) , affine. len( ) ) ;
325- let mut zs = alloc:: vec![ FieldElement :: ONE ; projective. len( ) ] ;
326- batch_normalize_generic ( projective, zs. as_mut_slice ( ) , affine) ;
325+ let mut zs = vec ! [ FieldElement :: ZERO ; projective. len( ) ] ;
326+ let mut scratch = vec ! [ FieldElement :: ZERO ; projective. len( ) ] ;
327+ batch_normalize_generic ( projective, & mut zs, & mut scratch, affine) ;
327328 }
328329}
329330
@@ -768,9 +769,10 @@ impl<const N: usize> BatchNormalize<[EdwardsPoint; N]> for EdwardsPoint {
768769
769770 #[ inline]
770771 fn batch_normalize ( points : & [ Self ; N ] ) -> [ <Self as CurveGroup >:: Affine ; N ] {
771- let zs = [ FieldElement :: ONE ; N ] ;
772+ let mut zs = [ FieldElement :: ZERO ; N ] ;
773+ let mut scratch = [ FieldElement :: ZERO ; N ] ;
772774 let mut affine_points = [ AffinePoint :: IDENTITY ; N ] ;
773- batch_normalize_generic ( points, zs , & mut affine_points) ;
775+ batch_normalize_generic ( points, & mut zs , & mut scratch , & mut affine_points) ;
774776 affine_points
775777 }
776778}
@@ -783,43 +785,36 @@ impl BatchNormalize<[EdwardsPoint]> for EdwardsPoint {
783785 fn batch_normalize ( points : & [ Self ] ) -> Vec < <Self as CurveGroup >:: Affine > {
784786 use alloc:: vec;
785787
786- let mut zs = vec ! [ FieldElement :: ONE ; points. len( ) ] ;
788+ let mut zs = vec ! [ FieldElement :: ZERO ; points. len( ) ] ;
789+ let mut scratch = vec ! [ FieldElement :: ZERO ; points. len( ) ] ;
787790 let mut affine_points = vec ! [ AffinePoint :: IDENTITY ; points. len( ) ] ;
788- batch_normalize_generic ( points, zs . as_mut_slice ( ) , & mut affine_points) ;
791+ batch_normalize_generic ( points, & mut zs , & mut scratch , & mut affine_points) ;
789792 affine_points
790793 }
791794}
792795
793- /// Generic implementation of batch normalization.
794- fn batch_normalize_generic < P , Z , I , O > ( points : & P , mut zs : Z , out : & mut O )
795- where
796- FieldElement : BatchInvert < Z , Output = CtOption < I > > ,
797- P : AsRef < [ EdwardsPoint ] > + ?Sized ,
798- Z : AsMut < [ FieldElement ] > ,
799- I : AsRef < [ FieldElement ] > ,
800- O : AsMut < [ AffinePoint ] > + ?Sized ,
801- {
802- let points = points. as_ref ( ) ;
803- let out = out. as_mut ( ) ;
796+ fn batch_normalize_generic (
797+ points : & [ EdwardsPoint ] ,
798+ zs : & mut [ FieldElement ] ,
799+ scratch : & mut [ FieldElement ] ,
800+ out : & mut [ AffinePoint ] ,
801+ ) {
802+ debug_assert_eq ! ( points. len( ) , zs. len( ) ) ;
803+ debug_assert_eq ! ( points. len( ) , scratch. len( ) ) ;
804+ debug_assert_eq ! ( points. len( ) , out. len( ) ) ;
804805
805- for ( i, point) in points. iter ( ) . enumerate ( ) {
806- // Even a single zero value will fail inversion for the entire batch.
807- // Put a dummy value (above `FieldElement::ONE`) so inversion succeeds
808- // and treat that case specially later-on.
809- zs. as_mut ( ) [ i] . conditional_assign ( & point. Z , !point. Z . ct_eq ( & FieldElement :: ZERO ) ) ;
806+ for ( z, point) in zs. iter_mut ( ) . zip ( points) {
807+ * z = point. Z ;
810808 }
811809
812- // This is safe to unwrap since we assured that all elements are non-zero
813- let zs_inverses = <FieldElement as BatchInvert < Z > >:: batch_invert ( zs)
814- . expect ( "all elements should be non-zero" ) ;
810+ // Zero `zs` (identity) are handled explicitly below, so the `Choice` here is informational only
811+ let _ = FieldElement :: batch_invert_in_place ( zs, scratch) ;
815812
816813 for i in 0 ..out. len ( ) {
817- // If the `z` coordinate is non-zero, we can use it to invert;
818- // otherwise it defaults to the `IDENTITY` value.
819814 out[ i] = AffinePoint :: conditional_select (
820815 & AffinePoint {
821- x : points[ i] . X * zs_inverses . as_ref ( ) [ i] ,
822- y : points[ i] . Y * zs_inverses . as_ref ( ) [ i] ,
816+ x : points[ i] . X * zs [ i] ,
817+ y : points[ i] . Y * zs [ i] ,
823818 } ,
824819 & AffinePoint :: IDENTITY ,
825820 points[ i] . Z . ct_eq ( & FieldElement :: ZERO ) ,
0 commit comments