@@ -47,6 +47,37 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) {
47
47
(* p )-- ;
48
48
}
49
49
50
+ void max_fe_for_magnitude (secp256k1_fe * r , int m ) {
51
+ secp256k1_fe_clear (r );
52
+
53
+ #if defined(SECP256K1_WIDEMUL_INT128 )
54
+ r -> n [0 ] = 0xFFFFFFFFFFFFFULL * 2 * m ;
55
+ r -> n [1 ] = 0xFFFFFFFFFFFFFULL * 2 * m ;
56
+ r -> n [2 ] = 0xFFFFFFFFFFFFFULL * 2 * m ;
57
+ r -> n [3 ] = 0xFFFFFFFFFFFFFULL * 2 * m ;
58
+ r -> n [4 ] = 0x0FFFFFFFFFFFFULL * 2 * m ;
59
+ #elif defined(SECP256K1_WIDEMUL_INT64 )
60
+ r -> n [0 ] = 0x3FFFFFFUL * 2 * m ;
61
+ r -> n [1 ] = 0x3FFFFFFUL * 2 * m ;
62
+ r -> n [2 ] = 0x3FFFFFFUL * 2 * m ;
63
+ r -> n [3 ] = 0x3FFFFFFUL * 2 * m ;
64
+ r -> n [4 ] = 0x3FFFFFFUL * 2 * m ;
65
+ r -> n [5 ] = 0x3FFFFFFUL * 2 * m ;
66
+ r -> n [6 ] = 0x3FFFFFFUL * 2 * m ;
67
+ r -> n [7 ] = 0x3FFFFFFUL * 2 * m ;
68
+ r -> n [8 ] = 0x3FFFFFFUL * 2 * m ;
69
+ r -> n [9 ] = 0x03FFFFFUL * 2 * m ;
70
+ #else
71
+ #error "Please select wide multiplication implementation"
72
+ #endif
73
+
74
+ #ifdef VERIFY
75
+ r -> magnitude = m ;
76
+ r -> normalized = (m == 0 );
77
+ secp256k1_fe_verify (r );
78
+ #endif
79
+ }
80
+
50
81
void random_field_element_test (secp256k1_fe * fe ) {
51
82
do {
52
83
unsigned char b32 [32 ];
@@ -2460,6 +2491,55 @@ int fe_secp256k1_memcmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
2460
2491
return secp256k1_memcmp_var (a , & t , sizeof (secp256k1_fe ));
2461
2492
}
2462
2493
2494
+ void run_field_half (void ) {
2495
+ secp256k1_fe t , u ;
2496
+ int m ;
2497
+
2498
+ /* Check magnitude 0 input */
2499
+ secp256k1_fe_clear (& t );
2500
+ secp256k1_fe_half (& t );
2501
+ #ifdef VERIFY
2502
+ CHECK (t .magnitude == 1 );
2503
+ CHECK (t .normalized == 0 );
2504
+ #endif
2505
+ CHECK (secp256k1_fe_normalizes_to_zero (& t ));
2506
+
2507
+ /* Check non-zero magnitudes in the supported range */
2508
+ for (m = 1 ; m < 32 ; m ++ ) {
2509
+ /* Check max-value input */
2510
+ max_fe_for_magnitude (& t , m );
2511
+
2512
+ u = t ;
2513
+ secp256k1_fe_half (& u );
2514
+ #ifdef VERIFY
2515
+ CHECK (u .magnitude == (m >> 1 ) + 1 );
2516
+ CHECK (u .normalized == 0 );
2517
+ #endif
2518
+ secp256k1_fe_normalize_weak (& u );
2519
+ secp256k1_fe_add (& u , & u );
2520
+ CHECK (check_fe_equal (& t , & u ));
2521
+
2522
+ /* Check worst-case input: ensure the LSB is 1 so that P will be added,
2523
+ * which will also cause all carries to be 1, since all limbs that can
2524
+ * generate a carry are initially even and all limbs of P are odd in
2525
+ * every existing field implementation. */
2526
+ max_fe_for_magnitude (& t , m );
2527
+ CHECK (t .n [0 ] > 0 );
2528
+ CHECK ((t .n [0 ] & 1 ) == 0 );
2529
+ -- t .n [0 ];
2530
+
2531
+ u = t ;
2532
+ secp256k1_fe_half (& u );
2533
+ #ifdef VERIFY
2534
+ CHECK (u .magnitude == (m >> 1 ) + 1 );
2535
+ CHECK (u .normalized == 0 );
2536
+ #endif
2537
+ secp256k1_fe_normalize_weak (& u );
2538
+ secp256k1_fe_add (& u , & u );
2539
+ CHECK (check_fe_equal (& t , & u ));
2540
+ }
2541
+ }
2542
+
2463
2543
void run_field_misc (void ) {
2464
2544
secp256k1_fe x ;
2465
2545
secp256k1_fe y ;
@@ -6809,6 +6889,7 @@ int main(int argc, char **argv) {
6809
6889
run_scalar_tests ();
6810
6890
6811
6891
/* field tests */
6892
+ run_field_half ();
6812
6893
run_field_misc ();
6813
6894
run_field_convert ();
6814
6895
run_fe_mul ();
0 commit comments