@@ -159,7 +159,6 @@ private static unsafe bool SetB32(byte* pt, uint* r)
159
159
uint of = GetOverflow ( r ) ;
160
160
Debug . Assert ( of == 0 || of == 1 ) ;
161
161
Reduce ( r , of ) ;
162
- Debug . Assert ( GetOverflow ( r ) == 0 ) ;
163
162
return of != 0 ;
164
163
}
165
164
@@ -238,22 +237,48 @@ private static unsafe bool SetB32(byte* pt, uint* r)
238
237
/// <summary>
239
238
/// Returns if the value is equal to zero
240
239
/// </summary>
241
- public bool IsZero => ( b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 ) == 0 ;
240
+ public bool IsZero
241
+ {
242
+ get
243
+ {
244
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
245
+ return ( b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 ) == 0 ;
246
+ }
247
+ }
248
+
242
249
/// <summary>
243
250
/// Returns if the value is equal to one
244
251
/// </summary>
245
- public bool IsOne => ( ( b0 ^ 1 ) | b1 | b2 | b3 | b4 | b5 | b6 | b7 ) == 0 ;
252
+ public bool IsOne
253
+ {
254
+ get
255
+ {
256
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
257
+ return ( ( b0 ^ 1 ) | b1 | b2 | b3 | b4 | b5 | b6 | b7 ) == 0 ;
258
+ }
259
+ }
260
+
246
261
/// <summary>
247
262
/// Returns if the value is even
248
263
/// </summary>
249
- public bool IsEven => ( b0 & 1 ) == 0 ;
264
+ public bool IsEven
265
+ {
266
+ get
267
+ {
268
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
269
+ return ( b0 & 1 ) == 0 ;
270
+ }
271
+ }
272
+
250
273
/// <summary>
251
274
/// Returns if this scalar is higher than the group order divided by 2
252
275
/// </summary>
253
276
public bool IsHigh
254
277
{
255
278
get
256
279
{
280
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
281
+
257
282
int yes = 0 ;
258
283
int no = 0 ;
259
284
no |= ( b7 < NH7 ? 1 : 0 ) ;
@@ -350,6 +375,8 @@ private static unsafe void Reduce(uint* r, uint overflow)
350
375
r [ 6 ] = ( uint ) t ; t >>= 32 ;
351
376
t += r [ 7 ] ;
352
377
r [ 7 ] = ( uint ) t ;
378
+
379
+ Debug . Assert ( GetOverflow ( r ) == 0 ) ;
353
380
}
354
381
355
382
/// <summary>
@@ -360,6 +387,9 @@ private static unsafe void Reduce(uint* r, uint overflow)
360
387
/// <returns>Result</returns>
361
388
public unsafe Scalar8x32 Add ( in Scalar8x32 other , out bool overflow )
362
389
{
390
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
391
+ Debug . Assert ( GetOverflow ( other ) == 0 ) ;
392
+
363
393
uint * r = stackalloc uint [ 8 ] ;
364
394
365
395
ulong t = ( ulong ) b0 + other . b0 ;
@@ -397,7 +427,9 @@ public unsafe Scalar8x32 Add(in Scalar8x32 other, out bool overflow)
397
427
/// <returns></returns>
398
428
public Scalar8x32 CAddBit ( uint bit , uint flag )
399
429
{
430
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
400
431
Debug . Assert ( bit < 256 ) ;
432
+
401
433
bit += ( flag - 1 ) & 0x100 ; // forcing (bit >> 5) > 7 makes this a noop
402
434
ulong t = ( ulong ) b0 + ( ( ( bit >> 5 ) == 0 ? 1U : 0 ) << ( ( int ) bit & 0x1F ) ) ;
403
435
uint r0 = ( uint ) t ; t >>= 32 ;
@@ -424,12 +456,14 @@ public Scalar8x32 CAddBit(uint bit, uint flag)
424
456
425
457
public static unsafe uint GetBits ( uint * pt , int offset , int count )
426
458
{
459
+ Debug . Assert ( GetOverflow ( pt ) == 0 ) ;
427
460
Debug . Assert ( ( offset + count - 1 ) >> 5 == offset >> 5 ) ;
428
461
return ( pt [ offset >> 5 ] >> ( offset & 0x1F ) ) & ( ( 1U << count ) - 1 ) ;
429
462
}
430
463
431
464
public static unsafe uint GetBitsVar ( uint * pt , int offset , int count )
432
465
{
466
+ Debug . Assert ( GetOverflow ( pt ) == 0 ) ;
433
467
Debug . Assert ( count < 32 ) ;
434
468
Debug . Assert ( offset + count <= 256 ) ;
435
469
if ( ( offset + count - 1 ) >> 5 == offset >> 5 )
@@ -630,6 +664,8 @@ public Scalar8x32 Inverse_old()
630
664
631
665
public Scalar8x32 InverseVar_old ( )
632
666
{
667
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
668
+
633
669
return Inverse_old ( ) ;
634
670
}
635
671
@@ -641,6 +677,9 @@ public Scalar8x32 InverseVar_old()
641
677
/// <returns></returns>
642
678
public unsafe Scalar8x32 Multiply ( in Scalar8x32 b )
643
679
{
680
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
681
+ Debug . Assert ( GetOverflow ( b ) == 0 ) ;
682
+
644
683
uint * l = stackalloc uint [ 16 ] ;
645
684
Mult512 ( l , this , b ) ;
646
685
return Reduce512 ( l ) ;
@@ -987,6 +1026,7 @@ private static Scalar8x32 Reduce(in Scalar8x32 r, uint overflow)
987
1026
/// <returns>Shifted scalar</returns>
988
1027
public unsafe Scalar8x32 Shr16 ( int shift , out uint ret )
989
1028
{
1029
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
990
1030
Debug . Assert ( shift > 0 ) ;
991
1031
Debug . Assert ( shift < 16 ) ;
992
1032
@@ -1004,26 +1044,36 @@ public unsafe Scalar8x32 Shr16(int shift, out uint ret)
1004
1044
}
1005
1045
1006
1046
1047
+ /// <summary>
1048
+ /// Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer.
1049
+ /// Shift must be at least 256
1050
+ /// </summary>
1051
+ /// <param name="a">A</param>
1052
+ /// <param name="b">B</param>
1053
+ /// <param name="shift">Shift must be at least 256</param>
1054
+ /// <returns>Result</returns>
1007
1055
public static unsafe Scalar8x32 MulShiftVar ( in Scalar8x32 a , in Scalar8x32 b , int shift )
1008
1056
{
1057
+ Debug . Assert ( GetOverflow ( a ) == 0 ) ;
1058
+ Debug . Assert ( GetOverflow ( b ) == 0 ) ;
1009
1059
Debug . Assert ( shift >= 256 ) ;
1010
1060
1011
1061
uint * l = stackalloc uint [ 16 ] ;
1012
1062
Mult512 ( l , a , b ) ;
1013
1063
1014
- int shiftlimbs = shift >> 5 ;
1064
+ int shLimbs = shift >> 5 ;
1015
1065
int shiftlow = shift & 0x1F ;
1016
1066
int shifthigh = 32 - shiftlow ;
1017
1067
bool sb = shiftlow != 0 ;
1018
1068
1019
- uint r0 = shift < 512 ? ( l [ 0 + shiftlimbs ] >> shiftlow | ( shift < 480 && sb ? ( l [ 1 + shiftlimbs ] << shifthigh ) : 0 ) ) : 0 ;
1020
- uint r1 = shift < 480 ? ( l [ 1 + shiftlimbs ] >> shiftlow | ( shift < 448 && sb ? ( l [ 2 + shiftlimbs ] << shifthigh ) : 0 ) ) : 0 ;
1021
- uint r2 = shift < 448 ? ( l [ 2 + shiftlimbs ] >> shiftlow | ( shift < 416 && sb ? ( l [ 3 + shiftlimbs ] << shifthigh ) : 0 ) ) : 0 ;
1022
- uint r3 = shift < 416 ? ( l [ 3 + shiftlimbs ] >> shiftlow | ( shift < 384 && sb ? ( l [ 4 + shiftlimbs ] << shifthigh ) : 0 ) ) : 0 ;
1023
- uint r4 = shift < 384 ? ( l [ 4 + shiftlimbs ] >> shiftlow | ( shift < 352 && sb ? ( l [ 5 + shiftlimbs ] << shifthigh ) : 0 ) ) : 0 ;
1024
- uint r5 = shift < 352 ? ( l [ 5 + shiftlimbs ] >> shiftlow | ( shift < 320 && sb ? ( l [ 6 + shiftlimbs ] << shifthigh ) : 0 ) ) : 0 ;
1025
- uint r6 = shift < 320 ? ( l [ 6 + shiftlimbs ] >> shiftlow | ( shift < 288 && sb ? ( l [ 7 + shiftlimbs ] << shifthigh ) : 0 ) ) : 0 ;
1026
- uint r7 = shift < 288 ? ( l [ 7 + shiftlimbs ] >> shiftlow ) : 0 ;
1069
+ uint r0 = shift < 512 ? ( l [ 0 + shLimbs ] >> shiftlow | ( shift < 480 && sb ? ( l [ 1 + shLimbs ] << shifthigh ) : 0 ) ) : 0 ;
1070
+ uint r1 = shift < 480 ? ( l [ 1 + shLimbs ] >> shiftlow | ( shift < 448 && sb ? ( l [ 2 + shLimbs ] << shifthigh ) : 0 ) ) : 0 ;
1071
+ uint r2 = shift < 448 ? ( l [ 2 + shLimbs ] >> shiftlow | ( shift < 416 && sb ? ( l [ 3 + shLimbs ] << shifthigh ) : 0 ) ) : 0 ;
1072
+ uint r3 = shift < 416 ? ( l [ 3 + shLimbs ] >> shiftlow | ( shift < 384 && sb ? ( l [ 4 + shLimbs ] << shifthigh ) : 0 ) ) : 0 ;
1073
+ uint r4 = shift < 384 ? ( l [ 4 + shLimbs ] >> shiftlow | ( shift < 352 && sb ? ( l [ 5 + shLimbs ] << shifthigh ) : 0 ) ) : 0 ;
1074
+ uint r5 = shift < 352 ? ( l [ 5 + shLimbs ] >> shiftlow | ( shift < 320 && sb ? ( l [ 6 + shLimbs ] << shifthigh ) : 0 ) ) : 0 ;
1075
+ uint r6 = shift < 320 ? ( l [ 6 + shLimbs ] >> shiftlow | ( shift < 288 && sb ? ( l [ 7 + shLimbs ] << shifthigh ) : 0 ) ) : 0 ;
1076
+ uint r7 = shift < 288 ? ( l [ 7 + shLimbs ] >> shiftlow ) : 0 ;
1027
1077
1028
1078
Scalar8x32 r = new Scalar8x32 ( r0 , r1 , r2 , r3 , r4 , r5 , r6 , r7 ) ;
1029
1079
return r . CAddBit ( 0 , ( l [ ( shift - 1 ) >> 5 ] >> ( ( shift - 1 ) & 0x1f ) ) & 1 ) ;
@@ -1035,6 +1085,8 @@ public static unsafe Scalar8x32 MulShiftVar(in Scalar8x32 a, in Scalar8x32 b, in
1035
1085
/// <returns></returns>
1036
1086
public Scalar8x32 Negate ( )
1037
1087
{
1088
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
1089
+
1038
1090
// uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0);
1039
1091
// Instead of a branch to get 1/0 then multiply it by the constant we use branch to get the resulting constant directly
1040
1092
// ie. we skip multiplication (optimization effect is minuscule though!)
@@ -1067,6 +1119,8 @@ public Scalar8x32 Negate()
1067
1119
/// <returns>-1 if the number was negated; otherwise 1.</returns>
1068
1120
public int NegateConditional ( int flag , out Scalar8x32 result )
1069
1121
{
1122
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
1123
+
1070
1124
// If flag = 0 then mask = 00...00 so this is a no-op
1071
1125
// if flag = 1 then mask = 11...11 so this is identical Negate()
1072
1126
uint mask = ( uint ) - flag ;
@@ -1094,6 +1148,27 @@ public int NegateConditional(int flag, out Scalar8x32 result)
1094
1148
}
1095
1149
1096
1150
1151
+
1152
+ public static Scalar8x32 CMov ( in Scalar8x32 r , in Scalar8x32 a , uint flag )
1153
+ {
1154
+ Debug . Assert ( GetOverflow ( r ) == 0 ) ;
1155
+ Debug . Assert ( GetOverflow ( a ) == 0 ) ;
1156
+
1157
+ uint mask0 = flag + ~ 0U ;
1158
+ uint mask1 = ~ mask0 ;
1159
+ uint r0 = ( r . b0 & mask0 ) | ( a . b0 & mask1 ) ;
1160
+ uint r1 = ( r . b1 & mask0 ) | ( a . b1 & mask1 ) ;
1161
+ uint r2 = ( r . b2 & mask0 ) | ( a . b2 & mask1 ) ;
1162
+ uint r3 = ( r . b3 & mask0 ) | ( a . b3 & mask1 ) ;
1163
+ uint r4 = ( r . b4 & mask0 ) | ( a . b4 & mask1 ) ;
1164
+ uint r5 = ( r . b5 & mask0 ) | ( a . b5 & mask1 ) ;
1165
+ uint r6 = ( r . b6 & mask0 ) | ( a . b6 & mask1 ) ;
1166
+ uint r7 = ( r . b7 & mask0 ) | ( a . b7 & mask1 ) ;
1167
+
1168
+ return new Scalar8x32 ( r0 , r1 , r2 , r3 , r4 , r5 , r6 , r7 ) ;
1169
+ }
1170
+
1171
+
1097
1172
/// <summary>
1098
1173
/// Find r1 and r2 such that r1+r2*2^128 = k
1099
1174
/// </summary>
@@ -1102,6 +1177,8 @@ public int NegateConditional(int flag, out Scalar8x32 result)
1102
1177
/// <param name="r2"></param>
1103
1178
internal static void Split128 ( in Scalar8x32 k , out Scalar8x32 r1 , out Scalar8x32 r2 )
1104
1179
{
1180
+ Debug . Assert ( GetOverflow ( k ) == 0 ) ;
1181
+
1105
1182
r1 = new Scalar8x32 ( k . b0 , k . b1 , k . b2 , k . b3 , 0 , 0 , 0 , 0 ) ;
1106
1183
r2 = new Scalar8x32 ( k . b4 , k . b5 , k . b6 , k . b7 , 0 , 0 , 0 , 0 ) ;
1107
1184
}
@@ -1178,6 +1255,8 @@ private static int MemCmpVar(Span<byte> s1, Span<byte> s2, int n)
1178
1255
/// <returns>32 bytes</returns>
1179
1256
public byte [ ] ToByteArray ( )
1180
1257
{
1258
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
1259
+
1181
1260
return new byte [ 32 ]
1182
1261
{
1183
1262
( byte ) ( b7 >> 24 ) , ( byte ) ( b7 >> 16 ) , ( byte ) ( b7 >> 8 ) , ( byte ) b7 ,
@@ -1197,6 +1276,8 @@ public void WriteToSpan(Span<byte> stream)
1197
1276
if ( stream . Length < 32 )
1198
1277
throw new ArgumentOutOfRangeException ( ) ;
1199
1278
1279
+ Debug . Assert ( GetOverflow ( this ) == 0 ) ;
1280
+
1200
1281
stream [ 0 ] = ( byte ) ( b7 >> 24 ) ; stream [ 1 ] = ( byte ) ( b7 >> 16 ) ; stream [ 2 ] = ( byte ) ( b7 >> 8 ) ; stream [ 3 ] = ( byte ) b7 ;
1201
1282
stream [ 4 ] = ( byte ) ( b6 >> 24 ) ; stream [ 5 ] = ( byte ) ( b6 >> 16 ) ; stream [ 6 ] = ( byte ) ( b6 >> 8 ) ; stream [ 7 ] = ( byte ) b6 ;
1202
1283
stream [ 8 ] = ( byte ) ( b5 >> 24 ) ; stream [ 9 ] = ( byte ) ( b5 >> 16 ) ; stream [ 10 ] = ( byte ) ( b5 >> 8 ) ; stream [ 11 ] = ( byte ) b5 ;
@@ -1223,9 +1304,14 @@ public void WriteToSpan(Span<byte> stream)
1223
1304
/// <param name="left">First scalar</param>
1224
1305
/// <param name="right">Second scalar</param>
1225
1306
/// <returns>True if the two scalars are equal; otherwise false.</returns>
1226
- public static bool operator == ( in Scalar8x32 left , in Scalar8x32 right ) =>
1227
- ( ( left . b0 ^ right . b0 ) | ( left . b1 ^ right . b1 ) | ( left . b2 ^ right . b2 ) | ( left . b3 ^ right . b3 ) |
1228
- ( left . b4 ^ right . b4 ) | ( left . b5 ^ right . b5 ) | ( left . b6 ^ right . b6 ) | ( left . b7 ^ right . b7 ) ) == 0 ;
1307
+ public static bool operator == ( in Scalar8x32 left , in Scalar8x32 right )
1308
+ {
1309
+ Debug . Assert ( GetOverflow ( left ) == 0 ) ;
1310
+ Debug . Assert ( GetOverflow ( right ) == 0 ) ;
1311
+
1312
+ return ( ( left . b0 ^ right . b0 ) | ( left . b1 ^ right . b1 ) | ( left . b2 ^ right . b2 ) | ( left . b3 ^ right . b3 ) |
1313
+ ( left . b4 ^ right . b4 ) | ( left . b5 ^ right . b5 ) | ( left . b6 ^ right . b6 ) | ( left . b7 ^ right . b7 ) ) == 0 ;
1314
+ }
1229
1315
1230
1316
/// <summary>
1231
1317
/// Returns if the two scalars are not equal to each other
0 commit comments