@@ -317,7 +317,9 @@ impl<Fq: FqTrait> Curve<Fq> {
317
317
318
318
// ============================================================
319
319
// Sqrt Velu functions for large ell-isogenies
320
- // WARNING: this is underperforming because of inefficienies absolutely everywhere!
320
+ // WARNING: this is underperforming currently due to missing optimisations in some
321
+ // specialised polynomial arithmetic to allow for fast scaled remainder trees and
322
+ // other smaller things.
321
323
322
324
/// Precompute the points in the three partitions I, J and K using x-only arithmetic.
323
325
// TODO: study Algorithm 1 of ia.cr/2024/584 and see if this still will lead to
@@ -390,7 +392,7 @@ impl<Fq: FqTrait> Curve<Fq> {
390
392
391
393
#[ inline]
392
394
fn precompute_eJ_values (
393
- eJ_coeffs : & mut [ ( Fq , Fq , Fq , Fq ) ] ,
395
+ eJ_coeffs : & mut [ ( Fq , Fq , Fq ) ] ,
394
396
hJ_points : & [ PointX < Fq > ] ,
395
397
A24 : & Fq ,
396
398
C24 : & Fq ,
@@ -407,29 +409,13 @@ impl<Fq: FqTrait> Curve<Fq> {
407
409
for ( i, P ) in hJ_points. iter ( ) . enumerate ( ) {
408
410
let ( X , Z ) = P . coords ( ) ;
409
411
let XZ = X * Z ;
410
- let XZ4neg = -XZ . mul4 ( ) ;
411
412
412
- let sub_sqr = ( X - Z ) . square ( ) ;
413
- let add_sqr = sub_sqr - XZ4neg ;
413
+ let add_sqr = ( X + Z ) . square ( ) ;
414
+ let XZ4neg = - XZ . mul4 ( ) ;
414
415
let AXZ4neg = A * XZ4neg ;
415
416
416
- debug_assert ! ( add_sqr. equals( & ( X + Z ) . square( ) ) == u32 :: MAX ) ;
417
-
418
- eJ_coeffs[ i] = ( add_sqr, sub_sqr, XZ4neg , AXZ4neg ) ;
419
- }
420
- }
421
-
422
- /// Understanding the polynomial hK = prod(x * PZ - PX) for the set in hK, then
423
- /// evaluate this polynomial at alpha = 1 and alpha = -1
424
- #[ inline]
425
- fn hK_codomain ( hK_points : & [ PointX < Fq > ] ) -> ( Fq , Fq ) {
426
- let mut h1 = Fq :: ONE ;
427
- let mut h2 = Fq :: ONE ;
428
- for P in hK_points. iter ( ) {
429
- h1 *= P . Z - P . X ;
430
- h2 *= -( P . Z + P . X ) ;
417
+ eJ_coeffs[ i] = ( add_sqr, XZ4neg , AXZ4neg ) ;
431
418
}
432
- ( h1, h2)
433
419
}
434
420
435
421
/// Compute the product of an array of Fq values using a product tree.
@@ -442,6 +428,27 @@ impl<Fq: FqTrait> Curve<Fq> {
442
428
Self :: product_tree_root_fq ( & v[ ..half] ) * Self :: product_tree_root_fq ( & v[ half..] )
443
429
}
444
430
431
+ /// Understanding the polynomial hK = prod(x * PZ - PX) for the set in hK, then
432
+ /// evaluate this polynomial at alpha = 1 and alpha = -1
433
+ #[ inline]
434
+ fn hK_codomain ( hK_points : & [ PointX < Fq > ] ) -> ( Fq , Fq ) {
435
+ // We have the factorisation of hK into linear pieces, so we evaluate
436
+ // each factor to get an Fq element and then compute the product of these
437
+ // with a product tree.
438
+ let mut h1_linear = Vec :: with_capacity ( hK_points. len ( ) ) ;
439
+ let mut h2_linear = Vec :: with_capacity ( hK_points. len ( ) ) ;
440
+
441
+ for P in hK_points. iter ( ) {
442
+ h1_linear. push ( P . Z - P . X ) ;
443
+ h2_linear. push ( -( P . Z + P . X ) ) ;
444
+ }
445
+
446
+ let h1 = Self :: product_tree_root_fq ( & h1_linear) ;
447
+ let h2 = Self :: product_tree_root_fq ( & h2_linear) ;
448
+
449
+ ( h1, h2)
450
+ }
451
+
445
452
/// Understanding the polynomial hK = prod(x * PZ - PX) for the set in hK, then
446
453
/// evaluate this polynomial at alpha and 1/alpha (projectively) where we have
447
454
/// alpha = (X : Z) and we take as input X + Z and X - Z.
@@ -507,17 +514,18 @@ impl<Fq: FqTrait> Curve<Fq> {
507
514
let hI_roots: Vec < Fq > = hI_points. iter ( ) . map ( |P | P . X ) . collect ( ) ;
508
515
509
516
// Precompute (X + Z)^2, (X - Z)^2, -4XZ and -4XZ*A
510
- let mut eJ_precomp = vec ! [ ( Fq :: ZERO , Fq :: ZERO , Fq :: ZERO , Fq :: ZERO ) ; size_J] ;
517
+ let mut eJ_precomp = vec ! [ ( Fq :: ZERO , Fq :: ZERO , Fq :: ZERO ) ; size_J] ;
511
518
Self :: precompute_eJ_values ( & mut eJ_precomp, & hJ_points, A24 , C24 ) ; // Cost: size_J * (1S + 2M)
512
519
513
520
let mut E0J_leaves : Vec < P > = Vec :: with_capacity ( size_J) ;
514
521
let mut E1J_leaves : Vec < P > = Vec :: with_capacity ( size_J) ;
515
- for ( sum_sqr, sub_sqr, _, AXZ4neg ) in eJ_precomp. iter ( ) {
516
- let c0_0 = * sub_sqr;
522
+ for ( sum_sqr, XZ4neg , AXZ4neg ) in eJ_precomp. iter ( ) {
523
+ // (X - Z)^2 = (X + Z)^2 - 4 * X * Z
524
+ let c0_0 = * sum_sqr + * XZ4neg ;
517
525
let c0_1 = * AXZ4neg - sum_sqr. mul2 ( ) ;
518
526
519
527
let c1_0 = * sum_sqr;
520
- let c1_1 = sub_sqr . mul2 ( ) - * AXZ4neg ;
528
+ let c1_1 = c0_0 . mul2 ( ) - * AXZ4neg ;
521
529
522
530
// Each quadratic factor here is a palindrome.
523
531
// TODO: we could write specialised polynomial arithmetic which
@@ -565,7 +573,7 @@ impl<Fq: FqTrait> Curve<Fq> {
565
573
let X2Z2 = XpZ . square ( ) - XZ2 ; // X^2 + Z^2
566
574
567
575
let mut E1J_leaves : Vec < P > = Vec :: with_capacity ( size_J) ;
568
- for ( i, ( sum_sqr, _ , XZ4neg , AXZ4neg ) ) in eJ_precomp. iter ( ) . enumerate ( ) {
576
+ for ( i, ( sum_sqr, XZ4neg , AXZ4neg ) ) in eJ_precomp. iter ( ) . enumerate ( ) {
569
577
let Pj = hJ_points[ i] ;
570
578
571
579
// Precompute some multiplications for later.
0 commit comments