@@ -963,7 +963,7 @@ public UInt256_10x26 Negate(int m)
963
963
964
964
ulong u0 , u1 , u2 , u3 , u4 , u5 , u6 , u7 , u8 ;
965
965
uint t9 , t1 , t0 , t2 , t3 , t4 , t5 , t6 , t7 ;
966
- const uint M = 0x03FFFFFFU , R0 = 0x03D10U , R1 = 0x0400U ;
966
+ const uint M = 0x03FFFFFFU , R0 = 0x3D10U , R1 = 0x0400U ;
967
967
968
968
// [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n.
969
969
// for 0 <= x <= 9, px is a shorthand for sum(a[i]*b[x-i], i=0..x).
@@ -1276,21 +1276,21 @@ public UInt256_10x26 Negate(int m)
1276
1276
1277
1277
/// <summary>
1278
1278
/// Returns square (x^(2^n)) of this instance.
1279
- /// <para/>Useful to subsequently compute squares (ie. (((x^2)^2)2)^2)
1279
+ /// <para/>Useful to compute squares in a for loop (ie. (((x^2)^2)2)^2)
1280
1280
/// </summary>
1281
1281
/// <remarks>
1282
1282
/// Magnitude must be below 8.
1283
1283
/// Result's magnitude is 1 but is not normalized.
1284
1284
/// </remarks>
1285
- /// <param name="times">Number of times to repeat sauaring </param>
1285
+ /// <param name="times">Number of times to repeat squaring </param>
1286
1286
/// <returns>Result</returns>
1287
1287
public UInt256_10x26 Sqr ( int times )
1288
1288
{
1289
1289
#if DEBUG
1290
- Debug . Assert ( magnitude <= 8 ) ;
1291
1290
Verify ( ) ;
1291
+ VerifyMagnitude ( magnitude , 8 ) ;
1292
1292
#endif
1293
- const uint M = 0x03FFFFFFU , R0 = 0x03D10U , R1 = 0x0400U ;
1293
+ const uint M = 0x03FFFFFFU , R0 = 0x3D10U , R1 = 0x0400U ;
1294
1294
uint r0 = b0 ;
1295
1295
uint r1 = b1 ;
1296
1296
uint r2 = b2 ;
@@ -1328,7 +1328,7 @@ public UInt256_10x26 Sqr(int times)
1328
1328
+ ( ulong ) ( r3 * 2 ) * r6
1329
1329
+ ( ulong ) ( r4 * 2 ) * r5 ;
1330
1330
// [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0]
1331
- t9 = ( uint ) ( d & M ) ; d >>= 26 ;
1331
+ t9 = ( uint ) d & M ; d >>= 26 ;
1332
1332
Debug . Assert ( t9 >> 26 == 0 ) ;
1333
1333
Debug . Assert ( d >> 38 == 0 ) ;
1334
1334
// [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0]
@@ -1348,7 +1348,7 @@ public UInt256_10x26 Sqr(int times)
1348
1348
Debug . Assert ( d >> 37 == 0 ) ;
1349
1349
Debug . Assert ( c >> 61 == 0 ) ;
1350
1350
// [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
1351
- t0 = ( uint ) ( c & M ) ; c >>= 26 ; c += u0 * R1 ;
1351
+ t0 = ( uint ) c & M ; c >>= 26 ; c += u0 * R1 ;
1352
1352
Debug . Assert ( t0 >> 26 == 0 ) ;
1353
1353
Debug . Assert ( c >> 37 == 0 ) ;
1354
1354
// [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
@@ -1368,7 +1368,7 @@ public UInt256_10x26 Sqr(int times)
1368
1368
Debug . Assert ( d >> 37 == 0 ) ;
1369
1369
Debug . Assert ( c >> 63 == 0 ) ;
1370
1370
// [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
1371
- t1 = ( uint ) ( c & M ) ; c >>= 26 ; c += u1 * R1 ;
1371
+ t1 = ( uint ) c & M ; c >>= 26 ; c += u1 * R1 ;
1372
1372
Debug . Assert ( t1 >> 26 == 0 ) ;
1373
1373
Debug . Assert ( c >> 38 == 0 ) ;
1374
1374
// [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
@@ -1389,7 +1389,7 @@ public UInt256_10x26 Sqr(int times)
1389
1389
Debug . Assert ( d >> 37 == 0 ) ;
1390
1390
Debug . Assert ( c >> 63 == 0 ) ;
1391
1391
// [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
1392
- t2 = ( uint ) ( c & M ) ; c >>= 26 ; c += u2 * R1 ;
1392
+ t2 = ( uint ) c & M ; c >>= 26 ; c += u2 * R1 ;
1393
1393
Debug . Assert ( t2 >> 26 == 0 ) ;
1394
1394
Debug . Assert ( c >> 38 == 0 ) ;
1395
1395
// [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
@@ -1408,7 +1408,7 @@ public UInt256_10x26 Sqr(int times)
1408
1408
Debug . Assert ( u3 >> 26 == 0 ) ;
1409
1409
Debug . Assert ( d >> 37 == 0 ) ;
1410
1410
// [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
1411
- t3 = ( uint ) ( c & M ) ; c >>= 26 ; c += u3 * R1 ;
1411
+ t3 = ( uint ) c & M ; c >>= 26 ; c += u3 * R1 ;
1412
1412
Debug . Assert ( t3 >> 26 == 0 ) ;
1413
1413
Debug . Assert ( c >> 39 == 0 ) ;
1414
1414
// [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
@@ -1428,7 +1428,7 @@ public UInt256_10x26 Sqr(int times)
1428
1428
Debug . Assert ( u4 >> 26 == 0 ) ;
1429
1429
Debug . Assert ( d >> 36 == 0 ) ;
1430
1430
// [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
1431
- t4 = ( uint ) ( c & M ) ; c >>= 26 ; c += u4 * R1 ;
1431
+ t4 = ( uint ) c & M ; c >>= 26 ; c += u4 * R1 ;
1432
1432
Debug . Assert ( t4 >> 26 == 0 ) ;
1433
1433
Debug . Assert ( c >> 39 == 0 ) ;
1434
1434
// [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
@@ -1447,7 +1447,7 @@ public UInt256_10x26 Sqr(int times)
1447
1447
Debug . Assert ( u5 >> 26 == 0 ) ;
1448
1448
Debug . Assert ( d >> 36 == 0 ) ;
1449
1449
// [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
1450
- t5 = ( uint ) ( c & M ) ; c >>= 26 ; c += u5 * R1 ;
1450
+ t5 = ( uint ) c & M ; c >>= 26 ; c += u5 * R1 ;
1451
1451
Debug . Assert ( t5 >> 26 == 0 ) ;
1452
1452
Debug . Assert ( c >> 39 == 0 ) ;
1453
1453
// [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
@@ -1467,7 +1467,7 @@ public UInt256_10x26 Sqr(int times)
1467
1467
Debug . Assert ( u6 >> 26 == 0 ) ;
1468
1468
Debug . Assert ( d >> 35 == 0 ) ;
1469
1469
// [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
1470
- t6 = ( uint ) ( c & M ) ; c >>= 26 ; c += u6 * R1 ;
1470
+ t6 = ( uint ) c & M ; c >>= 26 ; c += u6 * R1 ;
1471
1471
Debug . Assert ( t6 >> 26 == 0 ) ;
1472
1472
Debug . Assert ( c >> 39 == 0 ) ;
1473
1473
// [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
@@ -1487,7 +1487,7 @@ public UInt256_10x26 Sqr(int times)
1487
1487
Debug . Assert ( d >> 32 == 0 ) ;
1488
1488
Debug . Assert ( c <= 0x800001703FFFC2F7UL ) ;
1489
1489
// [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
1490
- t7 = ( uint ) ( c & M ) ; c >>= 26 ; c += u7 * R1 ;
1490
+ t7 = ( uint ) c & M ; c >>= 26 ; c += u7 * R1 ;
1491
1491
Debug . Assert ( t7 >> 26 == 0 ) ;
1492
1492
Debug . Assert ( c >> 38 == 0 ) ;
1493
1493
// [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
@@ -1524,15 +1524,15 @@ public UInt256_10x26 Sqr(int times)
1524
1524
Debug . Assert ( r7 >> 26 == 0 ) ;
1525
1525
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1526
1526
1527
- r8 = ( uint ) ( c & M ) ; c >>= 26 ; c += u8 * R1 ;
1527
+ r8 = ( uint ) c & M ; c >>= 26 ; c += u8 * R1 ;
1528
1528
Debug . Assert ( r8 >> 26 == 0 ) ;
1529
1529
Debug . Assert ( c >> 39 == 0 ) ;
1530
1530
// [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1531
1531
// [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1532
1532
c += d * R0 + t9 ;
1533
1533
Debug . Assert ( c >> 45 == 0 ) ;
1534
1534
// [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1535
- r9 = ( uint ) ( c & ( M >> 4 ) ) ; c >>= 22 ; c += d * ( R1 << 4 ) ;
1535
+ r9 = ( uint ) c & ( M >> 4 ) ; c >>= 22 ; c += d * ( R1 << 4 ) ;
1536
1536
Debug . Assert ( r9 >> 22 == 0 ) ;
1537
1537
Debug . Assert ( c >> 46 == 0 ) ;
1538
1538
// [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
@@ -1542,7 +1542,7 @@ public UInt256_10x26 Sqr(int times)
1542
1542
d = c * ( R0 >> 4 ) + t0 ;
1543
1543
Debug . Assert ( d >> 56 == 0 ) ;
1544
1544
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1545
- r0 = ( uint ) ( d & M ) ; d >>= 26 ;
1545
+ r0 = ( uint ) d & M ; d >>= 26 ;
1546
1546
Debug . Assert ( r0 >> 26 == 0 ) ;
1547
1547
Debug . Assert ( d >> 30 == 0 ) ;
1548
1548
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
@@ -1551,7 +1551,7 @@ public UInt256_10x26 Sqr(int times)
1551
1551
Debug . Assert ( d <= 0x10000003FFFFBFUL ) ;
1552
1552
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1553
1553
// [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1554
- r1 = ( uint ) ( d & M ) ; d >>= 26 ;
1554
+ r1 = ( uint ) d & M ; d >>= 26 ;
1555
1555
Debug . Assert ( r1 >> 26 == 0 ) ;
1556
1556
Debug . Assert ( d >> 27 == 0 ) ;
1557
1557
Debug . Assert ( d <= 0x4000000UL ) ;
@@ -1573,12 +1573,21 @@ public UInt256_10x26 Sqr(int times)
1573
1573
1574
1574
1575
1575
/// <summary>
1576
- /// Return square root of this instance if it has a square root, otherwise returns square root of its negation.
1576
+ /// Return square root of this instance if it has a square root (returns true),
1577
+ /// otherwise returns square root of its negation (returns false).
1577
1578
/// </summary>
1579
+ /// <remarks>
1580
+ /// Magnitude must be below 8.
1581
+ /// Result will have a magnitude of 1 but will not be normalized.
1582
+ /// </remarks>
1578
1583
/// <param name="result">Square root result</param>
1579
1584
/// <returns>True if square root existed, otherwise false.</returns>
1580
1585
public bool Sqrt ( out UInt256_10x26 result )
1581
1586
{
1587
+ #if DEBUG
1588
+ Verify ( ) ;
1589
+ VerifyMagnitude ( magnitude , 8 ) ;
1590
+ #endif
1582
1591
// Given that p is congruent to 3 mod 4, we can compute the square root of
1583
1592
// a mod p as the (p+1)/4'th power of a.
1584
1593
//
@@ -1588,12 +1597,11 @@ public bool Sqrt(out UInt256_10x26 result)
1588
1597
// Also because (p+1)/4 is an even number, the computed square root is
1589
1598
// itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
1590
1599
1591
- UInt256_10x26 x2 , x3 , x6 , x9 , x11 , x22 , x44 , x88 , x176 , x220 , x223 , t1 ;
1592
-
1593
1600
// The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
1594
1601
// { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
1595
1602
// 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
1596
1603
1604
+ UInt256_10x26 x2 , x3 , x6 , x9 , x11 , x22 , x44 , x88 , x176 , x220 , x223 , t1 ;
1597
1605
x2 = Sqr ( ) ;
1598
1606
x2 *= this ;
1599
1607
@@ -1637,7 +1645,16 @@ public bool Sqrt(out UInt256_10x26 result)
1637
1645
1638
1646
// Check that a square root was actually calculated
1639
1647
t1 = result . Sqr ( ) ;
1640
- return t1 . Equals ( this ) ;
1648
+ bool b = t1 . Equals ( this ) ;
1649
+ #if DEBUG
1650
+ if ( ! b )
1651
+ {
1652
+ t1 = t1 . Negate ( 1 ) ;
1653
+ t1 = t1 . NormalizeVar ( ) ;
1654
+ Debug . Assert ( t1 . Equals ( this ) ) ;
1655
+ }
1656
+ #endif
1657
+ return b ;
1641
1658
}
1642
1659
1643
1660
@@ -1728,13 +1745,21 @@ public UInt256_10x26 Inverse_old()
1728
1745
/// <summary>
1729
1746
/// Conditional move. Sets <paramref name="r"/> equal to <paramref name="a"/> if flag is true (=1).
1730
1747
/// </summary>
1731
- /// <param name="r"></param>
1732
- /// <param name="a"></param>
1748
+ /// <remarks>
1749
+ /// This method is constant time.
1750
+ /// </remarks>
1751
+ /// <param name="r">Destination</param>
1752
+ /// <param name="a">Source</param>
1733
1753
/// <param name="flag">Zero or one. Sets <paramref name="r"/> equal to <paramref name="a"/> if flag is one.</param>
1734
- /// <returns>Result </returns>
1754
+ /// <returns><paramref name="a"/> if flag was one; otherwise r. </returns>
1735
1755
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
1736
1756
public static UInt256_10x26 CMov ( in UInt256_10x26 r , in UInt256_10x26 a , uint flag )
1737
1757
{
1758
+ #if DEBUG
1759
+ r . Verify ( ) ;
1760
+ a . Verify ( ) ;
1761
+ Debug . Assert ( flag == 0 || flag == 1 ) ;
1762
+ #endif
1738
1763
uint mask0 = flag + ~ 0U ;
1739
1764
uint mask1 = ~ mask0 ;
1740
1765
return new UInt256_10x26 (
@@ -1783,6 +1808,7 @@ public void Rescale(ref PointJacobian r)
1783
1808
public UInt256_8x32 ToUInt256_8x32 ( )
1784
1809
{
1785
1810
#if DEBUG
1811
+ Verify ( ) ;
1786
1812
Debug . Assert ( isNormalized ) ;
1787
1813
#endif
1788
1814
return new UInt256_8x32 ( this ) ;
@@ -1863,7 +1889,7 @@ public void WriteToSpan(Span<byte> ba)
1863
1889
/// Assumes both values are normalized.
1864
1890
/// </summary>
1865
1891
/// <remarks>
1866
- /// This method is constant time.
1892
+ /// This method is not constant time.
1867
1893
/// </remarks>
1868
1894
/// <param name="b">Other value to compare to</param>
1869
1895
/// <returns>1 if this is bigger than <paramref name="b"/>, -1 if smaller and 0 if equal.</returns>
0 commit comments