@@ -445,35 +445,92 @@ pub fn glvScalarMulG2WithBases(bases_in: [4]G2Point, scalar: Fr) G2Projective {
445445 return shamirMul4D (bases , decomp .k , decomp .max_bits );
446446}
447447
448- /// Shamir's trick for 4-point multi-scalar multiplication
448+ /// Shamir's trick for 4-point multi-scalar multiplication with precomputed table.
449449fn shamirMul4D (bases : [4 ]G2Point , coeffs : [4 ][4 ]u64 , max_bits : usize ) G2Projective {
450- var result = G2Projective .identity ();
450+ // Precompute table[0..16] where table[b3<<3|b2<<2|b1<<1|b0] = sum of bases[i] where bit i is set
451+ var table : [16 ]G2Point = undefined ;
452+ table [0 ] = G2Point .identity ();
453+ table [1 ] = bases [0 ];
454+ table [2 ] = bases [1 ];
455+ table [4 ] = bases [2 ];
456+ table [8 ] = bases [3 ];
457+ table [3 ] = G2Projective .fromAffine (bases [0 ]).addAffine (bases [1 ]).toAffine ();
458+ table [5 ] = G2Projective .fromAffine (bases [0 ]).addAffine (bases [2 ]).toAffine ();
459+ table [6 ] = G2Projective .fromAffine (bases [1 ]).addAffine (bases [2 ]).toAffine ();
460+ table [9 ] = G2Projective .fromAffine (bases [0 ]).addAffine (bases [3 ]).toAffine ();
461+ table [10 ] = G2Projective .fromAffine (bases [1 ]).addAffine (bases [3 ]).toAffine ();
462+ table [12 ] = G2Projective .fromAffine (bases [2 ]).addAffine (bases [3 ]).toAffine ();
463+ table [7 ] = G2Projective .fromAffine (table [3 ]).addAffine (bases [2 ]).toAffine ();
464+ table [11 ] = G2Projective .fromAffine (table [3 ]).addAffine (bases [3 ]).toAffine ();
465+ table [13 ] = G2Projective .fromAffine (table [5 ]).addAffine (bases [3 ]).toAffine ();
466+ table [14 ] = G2Projective .fromAffine (table [6 ]).addAffine (bases [3 ]).toAffine ();
467+ table [15 ] = G2Projective .fromAffine (table [7 ]).addAffine (bases [3 ]).toAffine ();
451468
469+ var result = G2Projective .identity ();
452470 var bit_idx : usize = max_bits ;
453- while (bit_idx > 0 ) {
471+
472+ // Handle odd top bit with 1-bit step
473+ if (max_bits % 2 == 1 ) {
454474 bit_idx -= 1 ;
475+ const idx = shamirTableIndex (coeffs , bit_idx );
476+ if (idx != 0 ) {
477+ result = G2Projective .fromAffine (table [idx ]);
478+ }
479+ }
455480
481+ // Process 2 bits at a time: double-add-double-add
482+ while (bit_idx >= 2 ) {
483+ bit_idx -= 2 ;
484+
485+ // Double for high bit position
456486 if (! result .isIdentity ()) {
457487 result = result .double ();
458488 }
459489
460- const limb_pos = bit_idx / 64 ;
461- const bit_pos : u6 = @intCast (bit_idx % 64 );
490+ // High bit contribution
491+ const idx_hi = shamirTableIndex (coeffs , bit_idx + 1 );
492+ if (idx_hi != 0 ) {
493+ if (result .isIdentity ()) {
494+ result = G2Projective .fromAffine (table [idx_hi ]);
495+ } else {
496+ result = result .addAffine (table [idx_hi ]);
497+ }
498+ }
462499
463- for (0.. 4) | i | {
464- if (limb_pos < 4 and (coeffs [i ][limb_pos ] >> bit_pos ) & 1 == 1 ) {
465- if (result .isIdentity ()) {
466- result = G2Projective .fromAffine (bases [i ]);
467- } else {
468- result = result .addAffine (bases [i ]);
469- }
500+ // Double for low bit position
501+ if (! result .isIdentity ()) {
502+ result = result .double ();
503+ }
504+
505+ // Low bit contribution
506+ const idx_lo = shamirTableIndex (coeffs , bit_idx );
507+ if (idx_lo != 0 ) {
508+ if (result .isIdentity ()) {
509+ result = G2Projective .fromAffine (table [idx_lo ]);
510+ } else {
511+ result = result .addAffine (table [idx_lo ]);
470512 }
471513 }
472514 }
473515
474516 return result ;
475517}
476518
519+ /// Compute 4-bit Shamir table index from bit position across 4 scalars.
520+ inline fn shamirTableIndex (coeffs : [4 ][4 ]u64 , bit_idx : usize ) u4 {
521+ const limb_pos = bit_idx / 64 ;
522+ const bit_pos : u6 = @intCast (bit_idx % 64 );
523+ var idx : u4 = 0 ;
524+ if (limb_pos < 4 ) {
525+ for (0.. 4) | i | {
526+ if ((coeffs [i ][limb_pos ] >> bit_pos ) & 1 == 1 ) {
527+ idx |= @as (u4 , 1 ) << @intCast (i );
528+ }
529+ }
530+ }
531+ return idx ;
532+ }
533+
477534// ============================================================================
478535// Utility functions
479536// ============================================================================
0 commit comments