1
0
mirror of https://github.com/hashcat/hashcat.git synced 2024-11-24 17:08:17 +00:00
hashcat/OpenCL/inc_bignum_operations.cl

2403 lines
92 KiB
Common Lisp

/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#include "inc_bignum_operations.h"
// n[128], input and result, n = n % m
// m[128], modulo, we increased it from m[64] for speed (memory+comparison) purposes
// similar to mod_512 () for 512bit modulo from OpenCL/inc_ecc_secp256k1.cl:
DECLSPEC void mod_4096 (PRIVATE_AS u32 *n, PRIVATE_AS const u32 *m)
{
// we need to perform a modulo operation with 4096-bit % 2048-bit (bignum modulo):
// 512 bytes % 256 bytes (or 128 u32 % 64 u32)
// note: we increased the size of m to avoid further temp variables/copies of m
// but in general the modulo is just 256 bytes
// ATTENTION: least significant byte are at n[0] and m[0]
/*
the general modulo by shift and substract code (n = n % m):
x = m;
t = n >> 1;
while (x <= t) x <<= 1;
while (n >= m)
{
if (n >= x) n -= x;
x >>= 1;
}
return n; // remainder
*/
/*
* Start:
*/
// x = m;
u32 x[128];
// we use a shift trick similar to the mod_512 () shortcut from
// OpenCL/inc_ecc_secp256k1.cl
// for (u32 i = 0; i < 64; i++) x[i] = 0;
// for (u32 i = 64; i < 128; i++) x[i] = m[i - 64];
x[ 0] = 0; x[ 1] = 0; x[ 2] = 0; x[ 3] = 0;
x[ 4] = 0; x[ 5] = 0; x[ 6] = 0; x[ 7] = 0;
x[ 8] = 0; x[ 9] = 0; x[ 10] = 0; x[ 11] = 0;
x[ 12] = 0; x[ 13] = 0; x[ 14] = 0; x[ 15] = 0;
x[ 16] = 0; x[ 17] = 0; x[ 18] = 0; x[ 19] = 0;
x[ 20] = 0; x[ 21] = 0; x[ 22] = 0; x[ 23] = 0;
x[ 24] = 0; x[ 25] = 0; x[ 26] = 0; x[ 27] = 0;
x[ 28] = 0; x[ 29] = 0; x[ 30] = 0; x[ 31] = 0;
x[ 32] = 0; x[ 33] = 0; x[ 34] = 0; x[ 35] = 0;
x[ 36] = 0; x[ 37] = 0; x[ 38] = 0; x[ 39] = 0;
x[ 40] = 0; x[ 41] = 0; x[ 42] = 0; x[ 43] = 0;
x[ 44] = 0; x[ 45] = 0; x[ 46] = 0; x[ 47] = 0;
x[ 48] = 0; x[ 49] = 0; x[ 50] = 0; x[ 51] = 0;
x[ 52] = 0; x[ 53] = 0; x[ 54] = 0; x[ 55] = 0;
x[ 56] = 0; x[ 57] = 0; x[ 58] = 0; x[ 59] = 0;
x[ 60] = 0; x[ 61] = 0; x[ 62] = 0; x[ 63] = 0;
x[ 64] = m[ 0]; x[ 65] = m[ 1]; x[ 66] = m[ 2]; x[ 67] = m[ 3];
x[ 68] = m[ 4]; x[ 69] = m[ 5]; x[ 70] = m[ 6]; x[ 71] = m[ 7];
x[ 72] = m[ 8]; x[ 73] = m[ 9]; x[ 74] = m[ 10]; x[ 75] = m[ 11];
x[ 76] = m[ 12]; x[ 77] = m[ 13]; x[ 78] = m[ 14]; x[ 79] = m[ 15];
x[ 80] = m[ 16]; x[ 81] = m[ 17]; x[ 82] = m[ 18]; x[ 83] = m[ 19];
x[ 84] = m[ 20]; x[ 85] = m[ 21]; x[ 86] = m[ 22]; x[ 87] = m[ 23];
x[ 88] = m[ 24]; x[ 89] = m[ 25]; x[ 90] = m[ 26]; x[ 91] = m[ 27];
x[ 92] = m[ 28]; x[ 93] = m[ 29]; x[ 94] = m[ 30]; x[ 95] = m[ 31];
x[ 96] = m[ 32]; x[ 97] = m[ 33]; x[ 98] = m[ 34]; x[ 99] = m[ 35];
x[100] = m[ 36]; x[101] = m[ 37]; x[102] = m[ 38]; x[103] = m[ 39];
x[104] = m[ 40]; x[105] = m[ 41]; x[106] = m[ 42]; x[107] = m[ 43];
x[108] = m[ 44]; x[109] = m[ 45]; x[110] = m[ 46]; x[111] = m[ 47];
x[112] = m[ 48]; x[113] = m[ 49]; x[114] = m[ 50]; x[115] = m[ 51];
x[116] = m[ 52]; x[117] = m[ 53]; x[118] = m[ 54]; x[119] = m[ 55];
x[120] = m[ 56]; x[121] = m[ 57]; x[122] = m[ 58]; x[123] = m[ 59];
x[124] = m[ 60]; x[125] = m[ 61]; x[126] = m[ 62]; x[127] = m[ 63];
// n >= b
while (n[127] >= m[127])
{
u32 shift_needed = 1;
for (int i = 127; i >= 0; i--)
{
if (n[i] < m[i]) // FAIL case
{
shift_needed = 0;
break;
}
else
if (n[i] > m[i]) // definitely a SUCCESS case (otherwise continue to check if equal)
{
break;
}
}
if (shift_needed == 0) break;
// r = x (copy it to have the original values for the subtraction)
u32 r[128];
// for (u32 i = 0; i < 128; i++) r[i] = x[i];
r[ 0] = x[ 0]; r[ 1] = x[ 1]; r[ 2] = x[ 2]; r[ 3] = x[ 3];
r[ 4] = x[ 4]; r[ 5] = x[ 5]; r[ 6] = x[ 6]; r[ 7] = x[ 7];
r[ 8] = x[ 8]; r[ 9] = x[ 9]; r[ 10] = x[ 10]; r[ 11] = x[ 11];
r[ 12] = x[ 12]; r[ 13] = x[ 13]; r[ 14] = x[ 14]; r[ 15] = x[ 15];
r[ 16] = x[ 16]; r[ 17] = x[ 17]; r[ 18] = x[ 18]; r[ 19] = x[ 19];
r[ 20] = x[ 20]; r[ 21] = x[ 21]; r[ 22] = x[ 22]; r[ 23] = x[ 23];
r[ 24] = x[ 24]; r[ 25] = x[ 25]; r[ 26] = x[ 26]; r[ 27] = x[ 27];
r[ 28] = x[ 28]; r[ 29] = x[ 29]; r[ 30] = x[ 30]; r[ 31] = x[ 31];
r[ 32] = x[ 32]; r[ 33] = x[ 33]; r[ 34] = x[ 34]; r[ 35] = x[ 35];
r[ 36] = x[ 36]; r[ 37] = x[ 37]; r[ 38] = x[ 38]; r[ 39] = x[ 39];
r[ 40] = x[ 40]; r[ 41] = x[ 41]; r[ 42] = x[ 42]; r[ 43] = x[ 43];
r[ 44] = x[ 44]; r[ 45] = x[ 45]; r[ 46] = x[ 46]; r[ 47] = x[ 47];
r[ 48] = x[ 48]; r[ 49] = x[ 49]; r[ 50] = x[ 50]; r[ 51] = x[ 51];
r[ 52] = x[ 52]; r[ 53] = x[ 53]; r[ 54] = x[ 54]; r[ 55] = x[ 55];
r[ 56] = x[ 56]; r[ 57] = x[ 57]; r[ 58] = x[ 58]; r[ 59] = x[ 59];
r[ 60] = x[ 60]; r[ 61] = x[ 61]; r[ 62] = x[ 62]; r[ 63] = x[ 63];
r[ 64] = x[ 64]; r[ 65] = x[ 65]; r[ 66] = x[ 66]; r[ 67] = x[ 67];
r[ 68] = x[ 68]; r[ 69] = x[ 69]; r[ 70] = x[ 70]; r[ 71] = x[ 71];
r[ 72] = x[ 72]; r[ 73] = x[ 73]; r[ 74] = x[ 74]; r[ 75] = x[ 75];
r[ 76] = x[ 76]; r[ 77] = x[ 77]; r[ 78] = x[ 78]; r[ 79] = x[ 79];
r[ 80] = x[ 80]; r[ 81] = x[ 81]; r[ 82] = x[ 82]; r[ 83] = x[ 83];
r[ 84] = x[ 84]; r[ 85] = x[ 85]; r[ 86] = x[ 86]; r[ 87] = x[ 87];
r[ 88] = x[ 88]; r[ 89] = x[ 89]; r[ 90] = x[ 90]; r[ 91] = x[ 91];
r[ 92] = x[ 92]; r[ 93] = x[ 93]; r[ 94] = x[ 94]; r[ 95] = x[ 95];
r[ 96] = x[ 96]; r[ 97] = x[ 97]; r[ 98] = x[ 98]; r[ 99] = x[ 99];
r[100] = x[100]; r[101] = x[101]; r[102] = x[102]; r[103] = x[103];
r[104] = x[104]; r[105] = x[105]; r[106] = x[106]; r[107] = x[107];
r[108] = x[108]; r[109] = x[109]; r[110] = x[110]; r[111] = x[111];
r[112] = x[112]; r[113] = x[113]; r[114] = x[114]; r[115] = x[115];
r[116] = x[116]; r[117] = x[117]; r[118] = x[118]; r[119] = x[119];
r[120] = x[120]; r[121] = x[121]; r[122] = x[122]; r[123] = x[123];
r[124] = x[124]; r[125] = x[125]; r[126] = x[126]; r[127] = x[127];
// x >>= 1 (half it):
// for (u32 i = 0; i < 127; i++) x[i] = (x[i + 1] << 31) | (x[i] >> 1);
// x[127] >>= 1;
x[ 0] = (x[ 1] << 31) | (x[ 0] >> 1);
x[ 1] = (x[ 2] << 31) | (x[ 1] >> 1);
x[ 2] = (x[ 3] << 31) | (x[ 2] >> 1);
x[ 3] = (x[ 4] << 31) | (x[ 3] >> 1);
x[ 4] = (x[ 5] << 31) | (x[ 4] >> 1);
x[ 5] = (x[ 6] << 31) | (x[ 5] >> 1);
x[ 6] = (x[ 7] << 31) | (x[ 6] >> 1);
x[ 7] = (x[ 8] << 31) | (x[ 7] >> 1);
x[ 8] = (x[ 9] << 31) | (x[ 8] >> 1);
x[ 9] = (x[ 10] << 31) | (x[ 9] >> 1);
x[ 10] = (x[ 11] << 31) | (x[ 10] >> 1);
x[ 11] = (x[ 12] << 31) | (x[ 11] >> 1);
x[ 12] = (x[ 13] << 31) | (x[ 12] >> 1);
x[ 13] = (x[ 14] << 31) | (x[ 13] >> 1);
x[ 14] = (x[ 15] << 31) | (x[ 14] >> 1);
x[ 15] = (x[ 16] << 31) | (x[ 15] >> 1);
x[ 16] = (x[ 17] << 31) | (x[ 16] >> 1);
x[ 17] = (x[ 18] << 31) | (x[ 17] >> 1);
x[ 18] = (x[ 19] << 31) | (x[ 18] >> 1);
x[ 19] = (x[ 20] << 31) | (x[ 19] >> 1);
x[ 20] = (x[ 21] << 31) | (x[ 20] >> 1);
x[ 21] = (x[ 22] << 31) | (x[ 21] >> 1);
x[ 22] = (x[ 23] << 31) | (x[ 22] >> 1);
x[ 23] = (x[ 24] << 31) | (x[ 23] >> 1);
x[ 24] = (x[ 25] << 31) | (x[ 24] >> 1);
x[ 25] = (x[ 26] << 31) | (x[ 25] >> 1);
x[ 26] = (x[ 27] << 31) | (x[ 26] >> 1);
x[ 27] = (x[ 28] << 31) | (x[ 27] >> 1);
x[ 28] = (x[ 29] << 31) | (x[ 28] >> 1);
x[ 29] = (x[ 30] << 31) | (x[ 29] >> 1);
x[ 30] = (x[ 31] << 31) | (x[ 30] >> 1);
x[ 31] = (x[ 32] << 31) | (x[ 31] >> 1);
x[ 32] = (x[ 33] << 31) | (x[ 32] >> 1);
x[ 33] = (x[ 34] << 31) | (x[ 33] >> 1);
x[ 34] = (x[ 35] << 31) | (x[ 34] >> 1);
x[ 35] = (x[ 36] << 31) | (x[ 35] >> 1);
x[ 36] = (x[ 37] << 31) | (x[ 36] >> 1);
x[ 37] = (x[ 38] << 31) | (x[ 37] >> 1);
x[ 38] = (x[ 39] << 31) | (x[ 38] >> 1);
x[ 39] = (x[ 40] << 31) | (x[ 39] >> 1);
x[ 40] = (x[ 41] << 31) | (x[ 40] >> 1);
x[ 41] = (x[ 42] << 31) | (x[ 41] >> 1);
x[ 42] = (x[ 43] << 31) | (x[ 42] >> 1);
x[ 43] = (x[ 44] << 31) | (x[ 43] >> 1);
x[ 44] = (x[ 45] << 31) | (x[ 44] >> 1);
x[ 45] = (x[ 46] << 31) | (x[ 45] >> 1);
x[ 46] = (x[ 47] << 31) | (x[ 46] >> 1);
x[ 47] = (x[ 48] << 31) | (x[ 47] >> 1);
x[ 48] = (x[ 49] << 31) | (x[ 48] >> 1);
x[ 49] = (x[ 50] << 31) | (x[ 49] >> 1);
x[ 50] = (x[ 51] << 31) | (x[ 50] >> 1);
x[ 51] = (x[ 52] << 31) | (x[ 51] >> 1);
x[ 52] = (x[ 53] << 31) | (x[ 52] >> 1);
x[ 53] = (x[ 54] << 31) | (x[ 53] >> 1);
x[ 54] = (x[ 55] << 31) | (x[ 54] >> 1);
x[ 55] = (x[ 56] << 31) | (x[ 55] >> 1);
x[ 56] = (x[ 57] << 31) | (x[ 56] >> 1);
x[ 57] = (x[ 58] << 31) | (x[ 57] >> 1);
x[ 58] = (x[ 59] << 31) | (x[ 58] >> 1);
x[ 59] = (x[ 60] << 31) | (x[ 59] >> 1);
x[ 60] = (x[ 61] << 31) | (x[ 60] >> 1);
x[ 61] = (x[ 62] << 31) | (x[ 61] >> 1);
x[ 62] = (x[ 63] << 31) | (x[ 62] >> 1);
x[ 63] = (x[ 64] << 31) | (x[ 63] >> 1);
x[ 64] = (x[ 65] << 31) | (x[ 64] >> 1);
x[ 65] = (x[ 66] << 31) | (x[ 65] >> 1);
x[ 66] = (x[ 67] << 31) | (x[ 66] >> 1);
x[ 67] = (x[ 68] << 31) | (x[ 67] >> 1);
x[ 68] = (x[ 69] << 31) | (x[ 68] >> 1);
x[ 69] = (x[ 70] << 31) | (x[ 69] >> 1);
x[ 70] = (x[ 71] << 31) | (x[ 70] >> 1);
x[ 71] = (x[ 72] << 31) | (x[ 71] >> 1);
x[ 72] = (x[ 73] << 31) | (x[ 72] >> 1);
x[ 73] = (x[ 74] << 31) | (x[ 73] >> 1);
x[ 74] = (x[ 75] << 31) | (x[ 74] >> 1);
x[ 75] = (x[ 76] << 31) | (x[ 75] >> 1);
x[ 76] = (x[ 77] << 31) | (x[ 76] >> 1);
x[ 77] = (x[ 78] << 31) | (x[ 77] >> 1);
x[ 78] = (x[ 79] << 31) | (x[ 78] >> 1);
x[ 79] = (x[ 80] << 31) | (x[ 79] >> 1);
x[ 80] = (x[ 81] << 31) | (x[ 80] >> 1);
x[ 81] = (x[ 82] << 31) | (x[ 81] >> 1);
x[ 82] = (x[ 83] << 31) | (x[ 82] >> 1);
x[ 83] = (x[ 84] << 31) | (x[ 83] >> 1);
x[ 84] = (x[ 85] << 31) | (x[ 84] >> 1);
x[ 85] = (x[ 86] << 31) | (x[ 85] >> 1);
x[ 86] = (x[ 87] << 31) | (x[ 86] >> 1);
x[ 87] = (x[ 88] << 31) | (x[ 87] >> 1);
x[ 88] = (x[ 89] << 31) | (x[ 88] >> 1);
x[ 89] = (x[ 90] << 31) | (x[ 89] >> 1);
x[ 90] = (x[ 91] << 31) | (x[ 90] >> 1);
x[ 91] = (x[ 92] << 31) | (x[ 91] >> 1);
x[ 92] = (x[ 93] << 31) | (x[ 92] >> 1);
x[ 93] = (x[ 94] << 31) | (x[ 93] >> 1);
x[ 94] = (x[ 95] << 31) | (x[ 94] >> 1);
x[ 95] = (x[ 96] << 31) | (x[ 95] >> 1);
x[ 96] = (x[ 97] << 31) | (x[ 96] >> 1);
x[ 97] = (x[ 98] << 31) | (x[ 97] >> 1);
x[ 98] = (x[ 99] << 31) | (x[ 98] >> 1);
x[ 99] = (x[100] << 31) | (x[ 99] >> 1);
x[100] = (x[101] << 31) | (x[100] >> 1);
x[101] = (x[102] << 31) | (x[101] >> 1);
x[102] = (x[103] << 31) | (x[102] >> 1);
x[103] = (x[104] << 31) | (x[103] >> 1);
x[104] = (x[105] << 31) | (x[104] >> 1);
x[105] = (x[106] << 31) | (x[105] >> 1);
x[106] = (x[107] << 31) | (x[106] >> 1);
x[107] = (x[108] << 31) | (x[107] >> 1);
x[108] = (x[109] << 31) | (x[108] >> 1);
x[109] = (x[110] << 31) | (x[109] >> 1);
x[110] = (x[111] << 31) | (x[110] >> 1);
x[111] = (x[112] << 31) | (x[111] >> 1);
x[112] = (x[113] << 31) | (x[112] >> 1);
x[113] = (x[114] << 31) | (x[113] >> 1);
x[114] = (x[115] << 31) | (x[114] >> 1);
x[115] = (x[116] << 31) | (x[115] >> 1);
x[116] = (x[117] << 31) | (x[116] >> 1);
x[117] = (x[118] << 31) | (x[117] >> 1);
x[118] = (x[119] << 31) | (x[118] >> 1);
x[119] = (x[120] << 31) | (x[119] >> 1);
x[120] = (x[121] << 31) | (x[120] >> 1);
x[121] = (x[122] << 31) | (x[121] >> 1);
x[122] = (x[123] << 31) | (x[122] >> 1);
x[123] = (x[124] << 31) | (x[123] >> 1);
x[124] = (x[125] << 31) | (x[124] >> 1);
x[125] = (x[126] << 31) | (x[125] >> 1);
x[126] = (x[127] << 31) | (x[126] >> 1);
x[127] = (x[127] >> 1);
/*
* if (n >= r) n -= r;
*/
// check if (n >= r):
u32 sub_needed = 1;
for (int i = 127; i >= 0; i--)
{
if (n[i] < r[i]) // FAIL case
{
sub_needed = 0;
break;
}
else
if (n[i] > r[i]) // definitely a SUCCESS case (otherwise continue to check if equal)
{
break;
}
}
if (sub_needed == 0) continue;
// n -= r;
// u32 res = 0; for (u32 i = 0; i < 128; i++) res |= r[i]; if (res == 0) break;
if ((r[ 0] == 0) && (r[ 1] == 0) && (r[ 2] == 0) && (r[ 3] == 0) &&
(r[ 4] == 0) && (r[ 5] == 0) && (r[ 6] == 0) && (r[ 7] == 0) &&
(r[ 8] == 0) && (r[ 9] == 0) && (r[ 10] == 0) && (r[ 11] == 0) &&
(r[ 12] == 0) && (r[ 13] == 0) && (r[ 14] == 0) && (r[ 15] == 0) &&
(r[ 16] == 0) && (r[ 17] == 0) && (r[ 18] == 0) && (r[ 19] == 0) &&
(r[ 20] == 0) && (r[ 21] == 0) && (r[ 22] == 0) && (r[ 23] == 0) &&
(r[ 24] == 0) && (r[ 25] == 0) && (r[ 26] == 0) && (r[ 27] == 0) &&
(r[ 28] == 0) && (r[ 29] == 0) && (r[ 30] == 0) && (r[ 31] == 0) &&
(r[ 32] == 0) && (r[ 33] == 0) && (r[ 34] == 0) && (r[ 35] == 0) &&
(r[ 36] == 0) && (r[ 37] == 0) && (r[ 38] == 0) && (r[ 39] == 0) &&
(r[ 40] == 0) && (r[ 41] == 0) && (r[ 42] == 0) && (r[ 43] == 0) &&
(r[ 44] == 0) && (r[ 45] == 0) && (r[ 46] == 0) && (r[ 47] == 0) &&
(r[ 48] == 0) && (r[ 49] == 0) && (r[ 50] == 0) && (r[ 51] == 0) &&
(r[ 52] == 0) && (r[ 53] == 0) && (r[ 54] == 0) && (r[ 55] == 0) &&
(r[ 56] == 0) && (r[ 57] == 0) && (r[ 58] == 0) && (r[ 59] == 0) &&
(r[ 60] == 0) && (r[ 61] == 0) && (r[ 62] == 0) && (r[ 63] == 0) &&
(r[ 64] == 0) && (r[ 65] == 0) && (r[ 66] == 0) && (r[ 67] == 0) &&
(r[ 68] == 0) && (r[ 69] == 0) && (r[ 70] == 0) && (r[ 71] == 0) &&
(r[ 72] == 0) && (r[ 73] == 0) && (r[ 74] == 0) && (r[ 75] == 0) &&
(r[ 76] == 0) && (r[ 77] == 0) && (r[ 78] == 0) && (r[ 79] == 0) &&
(r[ 80] == 0) && (r[ 81] == 0) && (r[ 82] == 0) && (r[ 83] == 0) &&
(r[ 84] == 0) && (r[ 85] == 0) && (r[ 86] == 0) && (r[ 87] == 0) &&
(r[ 88] == 0) && (r[ 89] == 0) && (r[ 90] == 0) && (r[ 91] == 0) &&
(r[ 92] == 0) && (r[ 93] == 0) && (r[ 94] == 0) && (r[ 95] == 0) &&
(r[ 96] == 0) && (r[ 97] == 0) && (r[ 98] == 0) && (r[ 99] == 0) &&
(r[100] == 0) && (r[101] == 0) && (r[102] == 0) && (r[103] == 0) &&
(r[104] == 0) && (r[105] == 0) && (r[106] == 0) && (r[107] == 0) &&
(r[108] == 0) && (r[109] == 0) && (r[110] == 0) && (r[111] == 0) &&
(r[112] == 0) && (r[113] == 0) && (r[114] == 0) && (r[115] == 0) &&
(r[116] == 0) && (r[117] == 0) && (r[118] == 0) && (r[119] == 0) &&
(r[120] == 0) && (r[121] == 0) && (r[122] == 0) && (r[123] == 0) &&
(r[124] == 0) && (r[125] == 0) && (r[126] == 0) && (r[127] == 0)) break; // error if r == 0
// for (u32 i = 0; i < 128; i++) r[i] = n[i] - r[i];
r[ 0] = n[ 0] - r[ 0];
r[ 1] = n[ 1] - r[ 1];
r[ 2] = n[ 2] - r[ 2];
r[ 3] = n[ 3] - r[ 3];
r[ 4] = n[ 4] - r[ 4];
r[ 5] = n[ 5] - r[ 5];
r[ 6] = n[ 6] - r[ 6];
r[ 7] = n[ 7] - r[ 7];
r[ 8] = n[ 8] - r[ 8];
r[ 9] = n[ 9] - r[ 9];
r[ 10] = n[ 10] - r[ 10];
r[ 11] = n[ 11] - r[ 11];
r[ 12] = n[ 12] - r[ 12];
r[ 13] = n[ 13] - r[ 13];
r[ 14] = n[ 14] - r[ 14];
r[ 15] = n[ 15] - r[ 15];
r[ 16] = n[ 16] - r[ 16];
r[ 17] = n[ 17] - r[ 17];
r[ 18] = n[ 18] - r[ 18];
r[ 19] = n[ 19] - r[ 19];
r[ 20] = n[ 20] - r[ 20];
r[ 21] = n[ 21] - r[ 21];
r[ 22] = n[ 22] - r[ 22];
r[ 23] = n[ 23] - r[ 23];
r[ 24] = n[ 24] - r[ 24];
r[ 25] = n[ 25] - r[ 25];
r[ 26] = n[ 26] - r[ 26];
r[ 27] = n[ 27] - r[ 27];
r[ 28] = n[ 28] - r[ 28];
r[ 29] = n[ 29] - r[ 29];
r[ 30] = n[ 30] - r[ 30];
r[ 31] = n[ 31] - r[ 31];
r[ 32] = n[ 32] - r[ 32];
r[ 33] = n[ 33] - r[ 33];
r[ 34] = n[ 34] - r[ 34];
r[ 35] = n[ 35] - r[ 35];
r[ 36] = n[ 36] - r[ 36];
r[ 37] = n[ 37] - r[ 37];
r[ 38] = n[ 38] - r[ 38];
r[ 39] = n[ 39] - r[ 39];
r[ 40] = n[ 40] - r[ 40];
r[ 41] = n[ 41] - r[ 41];
r[ 42] = n[ 42] - r[ 42];
r[ 43] = n[ 43] - r[ 43];
r[ 44] = n[ 44] - r[ 44];
r[ 45] = n[ 45] - r[ 45];
r[ 46] = n[ 46] - r[ 46];
r[ 47] = n[ 47] - r[ 47];
r[ 48] = n[ 48] - r[ 48];
r[ 49] = n[ 49] - r[ 49];
r[ 50] = n[ 50] - r[ 50];
r[ 51] = n[ 51] - r[ 51];
r[ 52] = n[ 52] - r[ 52];
r[ 53] = n[ 53] - r[ 53];
r[ 54] = n[ 54] - r[ 54];
r[ 55] = n[ 55] - r[ 55];
r[ 56] = n[ 56] - r[ 56];
r[ 57] = n[ 57] - r[ 57];
r[ 58] = n[ 58] - r[ 58];
r[ 59] = n[ 59] - r[ 59];
r[ 60] = n[ 60] - r[ 60];
r[ 61] = n[ 61] - r[ 61];
r[ 62] = n[ 62] - r[ 62];
r[ 63] = n[ 63] - r[ 63];
r[ 64] = n[ 64] - r[ 64];
r[ 65] = n[ 65] - r[ 65];
r[ 66] = n[ 66] - r[ 66];
r[ 67] = n[ 67] - r[ 67];
r[ 68] = n[ 68] - r[ 68];
r[ 69] = n[ 69] - r[ 69];
r[ 70] = n[ 70] - r[ 70];
r[ 71] = n[ 71] - r[ 71];
r[ 72] = n[ 72] - r[ 72];
r[ 73] = n[ 73] - r[ 73];
r[ 74] = n[ 74] - r[ 74];
r[ 75] = n[ 75] - r[ 75];
r[ 76] = n[ 76] - r[ 76];
r[ 77] = n[ 77] - r[ 77];
r[ 78] = n[ 78] - r[ 78];
r[ 79] = n[ 79] - r[ 79];
r[ 80] = n[ 80] - r[ 80];
r[ 81] = n[ 81] - r[ 81];
r[ 82] = n[ 82] - r[ 82];
r[ 83] = n[ 83] - r[ 83];
r[ 84] = n[ 84] - r[ 84];
r[ 85] = n[ 85] - r[ 85];
r[ 86] = n[ 86] - r[ 86];
r[ 87] = n[ 87] - r[ 87];
r[ 88] = n[ 88] - r[ 88];
r[ 89] = n[ 89] - r[ 89];
r[ 90] = n[ 90] - r[ 90];
r[ 91] = n[ 91] - r[ 91];
r[ 92] = n[ 92] - r[ 92];
r[ 93] = n[ 93] - r[ 93];
r[ 94] = n[ 94] - r[ 94];
r[ 95] = n[ 95] - r[ 95];
r[ 96] = n[ 96] - r[ 96];
r[ 97] = n[ 97] - r[ 97];
r[ 98] = n[ 98] - r[ 98];
r[ 99] = n[ 99] - r[ 99];
r[100] = n[100] - r[100];
r[101] = n[101] - r[101];
r[102] = n[102] - r[102];
r[103] = n[103] - r[103];
r[104] = n[104] - r[104];
r[105] = n[105] - r[105];
r[106] = n[106] - r[106];
r[107] = n[107] - r[107];
r[108] = n[108] - r[108];
r[109] = n[109] - r[109];
r[110] = n[110] - r[110];
r[111] = n[111] - r[111];
r[112] = n[112] - r[112];
r[113] = n[113] - r[113];
r[114] = n[114] - r[114];
r[115] = n[115] - r[115];
r[116] = n[116] - r[116];
r[117] = n[117] - r[117];
r[118] = n[118] - r[118];
r[119] = n[119] - r[119];
r[120] = n[120] - r[120];
r[121] = n[121] - r[121];
r[122] = n[122] - r[122];
r[123] = n[123] - r[123];
r[124] = n[124] - r[124];
r[125] = n[125] - r[125];
r[126] = n[126] - r[126];
r[127] = n[127] - r[127];
// take care of the "borrow":
// for (u32 i = 0; i < 127; i++) if (r[i] > n[i]) r[i + 1]--;
// if (r[ 0] > n[ 0]) r[ 1]--;
// if (r[ 1] > n[ 1]) r[ 2]--;
// if (r[ 2] > n[ 2]) r[ 3]--;
// if (r[ 3] > n[ 3]) r[ 4]--;
// if (r[ 4] > n[ 4]) r[ 5]--;
// if (r[ 5] > n[ 5]) r[ 6]--;
// if (r[ 6] > n[ 6]) r[ 7]--;
// if (r[ 7] > n[ 7]) r[ 8]--;
// if (r[ 8] > n[ 8]) r[ 9]--;
// if (r[ 9] > n[ 9]) r[ 10]--;
// if (r[ 10] > n[ 10]) r[ 11]--;
// if (r[ 11] > n[ 11]) r[ 12]--;
// if (r[ 12] > n[ 12]) r[ 13]--;
// if (r[ 13] > n[ 13]) r[ 14]--;
// if (r[ 14] > n[ 14]) r[ 15]--;
// if (r[ 15] > n[ 15]) r[ 16]--;
// if (r[ 16] > n[ 16]) r[ 17]--;
// if (r[ 17] > n[ 17]) r[ 18]--;
// if (r[ 18] > n[ 18]) r[ 19]--;
// if (r[ 19] > n[ 19]) r[ 20]--;
// if (r[ 20] > n[ 20]) r[ 21]--;
// if (r[ 21] > n[ 21]) r[ 22]--;
// if (r[ 22] > n[ 22]) r[ 23]--;
// if (r[ 23] > n[ 23]) r[ 24]--;
// if (r[ 24] > n[ 24]) r[ 25]--;
// if (r[ 25] > n[ 25]) r[ 26]--;
// if (r[ 26] > n[ 26]) r[ 27]--;
// if (r[ 27] > n[ 27]) r[ 28]--;
// if (r[ 28] > n[ 28]) r[ 29]--;
// if (r[ 29] > n[ 29]) r[ 30]--;
// if (r[ 30] > n[ 30]) r[ 31]--;
// if (r[ 31] > n[ 31]) r[ 32]--;
// if (r[ 32] > n[ 32]) r[ 33]--;
// if (r[ 33] > n[ 33]) r[ 34]--;
// if (r[ 34] > n[ 34]) r[ 35]--;
// if (r[ 35] > n[ 35]) r[ 36]--;
// if (r[ 36] > n[ 36]) r[ 37]--;
// if (r[ 37] > n[ 37]) r[ 38]--;
// if (r[ 38] > n[ 38]) r[ 39]--;
// if (r[ 39] > n[ 39]) r[ 40]--;
// if (r[ 40] > n[ 40]) r[ 41]--;
// if (r[ 41] > n[ 41]) r[ 42]--;
// if (r[ 42] > n[ 42]) r[ 43]--;
// if (r[ 43] > n[ 43]) r[ 44]--;
// if (r[ 44] > n[ 44]) r[ 45]--;
// if (r[ 45] > n[ 45]) r[ 46]--;
// if (r[ 46] > n[ 46]) r[ 47]--;
// if (r[ 47] > n[ 47]) r[ 48]--;
// if (r[ 48] > n[ 48]) r[ 49]--;
// if (r[ 49] > n[ 49]) r[ 50]--;
// if (r[ 50] > n[ 50]) r[ 51]--;
// if (r[ 51] > n[ 51]) r[ 52]--;
// if (r[ 52] > n[ 52]) r[ 53]--;
// if (r[ 53] > n[ 53]) r[ 54]--;
// if (r[ 54] > n[ 54]) r[ 55]--;
// if (r[ 55] > n[ 55]) r[ 56]--;
// if (r[ 56] > n[ 56]) r[ 57]--;
// if (r[ 57] > n[ 57]) r[ 58]--;
// if (r[ 58] > n[ 58]) r[ 59]--;
// if (r[ 59] > n[ 59]) r[ 60]--;
// if (r[ 60] > n[ 60]) r[ 61]--;
// if (r[ 61] > n[ 61]) r[ 62]--;
// if (r[ 62] > n[ 62]) r[ 63]--;
// if (r[ 63] > n[ 63]) r[ 64]--;
// if (r[ 64] > n[ 64]) r[ 65]--;
// if (r[ 65] > n[ 65]) r[ 66]--;
// if (r[ 66] > n[ 66]) r[ 67]--;
// if (r[ 67] > n[ 67]) r[ 68]--;
// if (r[ 68] > n[ 68]) r[ 69]--;
// if (r[ 69] > n[ 69]) r[ 70]--;
// if (r[ 70] > n[ 70]) r[ 71]--;
// if (r[ 71] > n[ 71]) r[ 72]--;
// if (r[ 72] > n[ 72]) r[ 73]--;
// if (r[ 73] > n[ 73]) r[ 74]--;
// if (r[ 74] > n[ 74]) r[ 75]--;
// if (r[ 75] > n[ 75]) r[ 76]--;
// if (r[ 76] > n[ 76]) r[ 77]--;
// if (r[ 77] > n[ 77]) r[ 78]--;
// if (r[ 78] > n[ 78]) r[ 79]--;
// if (r[ 79] > n[ 79]) r[ 80]--;
// if (r[ 80] > n[ 80]) r[ 81]--;
// if (r[ 81] > n[ 81]) r[ 82]--;
// if (r[ 82] > n[ 82]) r[ 83]--;
// if (r[ 83] > n[ 83]) r[ 84]--;
// if (r[ 84] > n[ 84]) r[ 85]--;
// if (r[ 85] > n[ 85]) r[ 86]--;
// if (r[ 86] > n[ 86]) r[ 87]--;
// if (r[ 87] > n[ 87]) r[ 88]--;
// if (r[ 88] > n[ 88]) r[ 89]--;
// if (r[ 89] > n[ 89]) r[ 90]--;
// if (r[ 90] > n[ 90]) r[ 91]--;
// if (r[ 91] > n[ 91]) r[ 92]--;
// if (r[ 92] > n[ 92]) r[ 93]--;
// if (r[ 93] > n[ 93]) r[ 94]--;
// if (r[ 94] > n[ 94]) r[ 95]--;
// if (r[ 95] > n[ 95]) r[ 96]--;
// if (r[ 96] > n[ 96]) r[ 97]--;
// if (r[ 97] > n[ 97]) r[ 98]--;
// if (r[ 98] > n[ 98]) r[ 99]--;
// if (r[ 99] > n[ 99]) r[100]--;
// if (r[100] > n[100]) r[101]--;
// if (r[101] > n[101]) r[102]--;
// if (r[102] > n[102]) r[103]--;
// if (r[103] > n[103]) r[104]--;
// if (r[104] > n[104]) r[105]--;
// if (r[105] > n[105]) r[106]--;
// if (r[106] > n[106]) r[107]--;
// if (r[107] > n[107]) r[108]--;
// if (r[108] > n[108]) r[109]--;
// if (r[109] > n[109]) r[110]--;
// if (r[110] > n[110]) r[111]--;
// if (r[111] > n[111]) r[112]--;
// if (r[112] > n[112]) r[113]--;
// if (r[113] > n[113]) r[114]--;
// if (r[114] > n[114]) r[115]--;
// if (r[115] > n[115]) r[116]--;
// if (r[116] > n[116]) r[117]--;
// if (r[117] > n[117]) r[118]--;
// if (r[118] > n[118]) r[119]--;
// if (r[119] > n[119]) r[120]--;
// if (r[120] > n[120]) r[121]--;
// if (r[121] > n[121]) r[122]--;
// if (r[122] > n[122]) r[123]--;
// if (r[123] > n[123]) r[124]--;
// if (r[124] > n[124]) r[125]--;
// if (r[125] > n[125]) r[126]--;
// if (r[126] > n[126]) r[127]--;
// for (u32 i = 1; i < 128; i++) r[i] -= r[i - 1] > n[i - 1];
r[ 1] -= r[ 0] > n[ 0];
r[ 2] -= r[ 1] > n[ 1];
r[ 3] -= r[ 2] > n[ 2];
r[ 4] -= r[ 3] > n[ 3];
r[ 5] -= r[ 4] > n[ 4];
r[ 6] -= r[ 5] > n[ 5];
r[ 7] -= r[ 6] > n[ 6];
r[ 8] -= r[ 7] > n[ 7];
r[ 9] -= r[ 8] > n[ 8];
r[ 10] -= r[ 9] > n[ 9];
r[ 11] -= r[ 10] > n[ 10];
r[ 12] -= r[ 11] > n[ 11];
r[ 13] -= r[ 12] > n[ 12];
r[ 14] -= r[ 13] > n[ 13];
r[ 15] -= r[ 14] > n[ 14];
r[ 16] -= r[ 15] > n[ 15];
r[ 17] -= r[ 16] > n[ 16];
r[ 18] -= r[ 17] > n[ 17];
r[ 19] -= r[ 18] > n[ 18];
r[ 20] -= r[ 19] > n[ 19];
r[ 21] -= r[ 20] > n[ 20];
r[ 22] -= r[ 21] > n[ 21];
r[ 23] -= r[ 22] > n[ 22];
r[ 24] -= r[ 23] > n[ 23];
r[ 25] -= r[ 24] > n[ 24];
r[ 26] -= r[ 25] > n[ 25];
r[ 27] -= r[ 26] > n[ 26];
r[ 28] -= r[ 27] > n[ 27];
r[ 29] -= r[ 28] > n[ 28];
r[ 30] -= r[ 29] > n[ 29];
r[ 31] -= r[ 30] > n[ 30];
r[ 32] -= r[ 31] > n[ 31];
r[ 33] -= r[ 32] > n[ 32];
r[ 34] -= r[ 33] > n[ 33];
r[ 35] -= r[ 34] > n[ 34];
r[ 36] -= r[ 35] > n[ 35];
r[ 37] -= r[ 36] > n[ 36];
r[ 38] -= r[ 37] > n[ 37];
r[ 39] -= r[ 38] > n[ 38];
r[ 40] -= r[ 39] > n[ 39];
r[ 41] -= r[ 40] > n[ 40];
r[ 42] -= r[ 41] > n[ 41];
r[ 43] -= r[ 42] > n[ 42];
r[ 44] -= r[ 43] > n[ 43];
r[ 45] -= r[ 44] > n[ 44];
r[ 46] -= r[ 45] > n[ 45];
r[ 47] -= r[ 46] > n[ 46];
r[ 48] -= r[ 47] > n[ 47];
r[ 49] -= r[ 48] > n[ 48];
r[ 50] -= r[ 49] > n[ 49];
r[ 51] -= r[ 50] > n[ 50];
r[ 52] -= r[ 51] > n[ 51];
r[ 53] -= r[ 52] > n[ 52];
r[ 54] -= r[ 53] > n[ 53];
r[ 55] -= r[ 54] > n[ 54];
r[ 56] -= r[ 55] > n[ 55];
r[ 57] -= r[ 56] > n[ 56];
r[ 58] -= r[ 57] > n[ 57];
r[ 59] -= r[ 58] > n[ 58];
r[ 60] -= r[ 59] > n[ 59];
r[ 61] -= r[ 60] > n[ 60];
r[ 62] -= r[ 61] > n[ 61];
r[ 63] -= r[ 62] > n[ 62];
r[ 64] -= r[ 63] > n[ 63];
r[ 65] -= r[ 64] > n[ 64];
r[ 66] -= r[ 65] > n[ 65];
r[ 67] -= r[ 66] > n[ 66];
r[ 68] -= r[ 67] > n[ 67];
r[ 69] -= r[ 68] > n[ 68];
r[ 70] -= r[ 69] > n[ 69];
r[ 71] -= r[ 70] > n[ 70];
r[ 72] -= r[ 71] > n[ 71];
r[ 73] -= r[ 72] > n[ 72];
r[ 74] -= r[ 73] > n[ 73];
r[ 75] -= r[ 74] > n[ 74];
r[ 76] -= r[ 75] > n[ 75];
r[ 77] -= r[ 76] > n[ 76];
r[ 78] -= r[ 77] > n[ 77];
r[ 79] -= r[ 78] > n[ 78];
r[ 80] -= r[ 79] > n[ 79];
r[ 81] -= r[ 80] > n[ 80];
r[ 82] -= r[ 81] > n[ 81];
r[ 83] -= r[ 82] > n[ 82];
r[ 84] -= r[ 83] > n[ 83];
r[ 85] -= r[ 84] > n[ 84];
r[ 86] -= r[ 85] > n[ 85];
r[ 87] -= r[ 86] > n[ 86];
r[ 88] -= r[ 87] > n[ 87];
r[ 89] -= r[ 88] > n[ 88];
r[ 90] -= r[ 89] > n[ 89];
r[ 91] -= r[ 90] > n[ 90];
r[ 92] -= r[ 91] > n[ 91];
r[ 93] -= r[ 92] > n[ 92];
r[ 94] -= r[ 93] > n[ 93];
r[ 95] -= r[ 94] > n[ 94];
r[ 96] -= r[ 95] > n[ 95];
r[ 97] -= r[ 96] > n[ 96];
r[ 98] -= r[ 97] > n[ 97];
r[ 99] -= r[ 98] > n[ 98];
r[100] -= r[ 99] > n[ 99];
r[101] -= r[100] > n[100];
r[102] -= r[101] > n[101];
r[103] -= r[102] > n[102];
r[104] -= r[103] > n[103];
r[105] -= r[104] > n[104];
r[106] -= r[105] > n[105];
r[107] -= r[106] > n[106];
r[108] -= r[107] > n[107];
r[109] -= r[108] > n[108];
r[110] -= r[109] > n[109];
r[111] -= r[110] > n[110];
r[112] -= r[111] > n[111];
r[113] -= r[112] > n[112];
r[114] -= r[113] > n[113];
r[115] -= r[114] > n[114];
r[116] -= r[115] > n[115];
r[117] -= r[116] > n[116];
r[118] -= r[117] > n[117];
r[119] -= r[118] > n[118];
r[120] -= r[119] > n[119];
r[121] -= r[120] > n[120];
r[122] -= r[121] > n[121];
r[123] -= r[122] > n[122];
r[124] -= r[123] > n[123];
r[125] -= r[124] > n[124];
r[126] -= r[125] > n[125];
r[127] -= r[126] > n[126];
// for (u32 i = 0; i < 128; i++) n[i] = r[i];
n[ 0] = r[ 0]; n[ 1] = r[ 1]; n[ 2] = r[ 2]; n[ 3] = r[ 3];
n[ 4] = r[ 4]; n[ 5] = r[ 5]; n[ 6] = r[ 6]; n[ 7] = r[ 7];
n[ 8] = r[ 8]; n[ 9] = r[ 9]; n[ 10] = r[ 10]; n[ 11] = r[ 11];
n[ 12] = r[ 12]; n[ 13] = r[ 13]; n[ 14] = r[ 14]; n[ 15] = r[ 15];
n[ 16] = r[ 16]; n[ 17] = r[ 17]; n[ 18] = r[ 18]; n[ 19] = r[ 19];
n[ 20] = r[ 20]; n[ 21] = r[ 21]; n[ 22] = r[ 22]; n[ 23] = r[ 23];
n[ 24] = r[ 24]; n[ 25] = r[ 25]; n[ 26] = r[ 26]; n[ 27] = r[ 27];
n[ 28] = r[ 28]; n[ 29] = r[ 29]; n[ 30] = r[ 30]; n[ 31] = r[ 31];
n[ 32] = r[ 32]; n[ 33] = r[ 33]; n[ 34] = r[ 34]; n[ 35] = r[ 35];
n[ 36] = r[ 36]; n[ 37] = r[ 37]; n[ 38] = r[ 38]; n[ 39] = r[ 39];
n[ 40] = r[ 40]; n[ 41] = r[ 41]; n[ 42] = r[ 42]; n[ 43] = r[ 43];
n[ 44] = r[ 44]; n[ 45] = r[ 45]; n[ 46] = r[ 46]; n[ 47] = r[ 47];
n[ 48] = r[ 48]; n[ 49] = r[ 49]; n[ 50] = r[ 50]; n[ 51] = r[ 51];
n[ 52] = r[ 52]; n[ 53] = r[ 53]; n[ 54] = r[ 54]; n[ 55] = r[ 55];
n[ 56] = r[ 56]; n[ 57] = r[ 57]; n[ 58] = r[ 58]; n[ 59] = r[ 59];
n[ 60] = r[ 60]; n[ 61] = r[ 61]; n[ 62] = r[ 62]; n[ 63] = r[ 63];
n[ 64] = r[ 64]; n[ 65] = r[ 65]; n[ 66] = r[ 66]; n[ 67] = r[ 67];
n[ 68] = r[ 68]; n[ 69] = r[ 69]; n[ 70] = r[ 70]; n[ 71] = r[ 71];
n[ 72] = r[ 72]; n[ 73] = r[ 73]; n[ 74] = r[ 74]; n[ 75] = r[ 75];
n[ 76] = r[ 76]; n[ 77] = r[ 77]; n[ 78] = r[ 78]; n[ 79] = r[ 79];
n[ 80] = r[ 80]; n[ 81] = r[ 81]; n[ 82] = r[ 82]; n[ 83] = r[ 83];
n[ 84] = r[ 84]; n[ 85] = r[ 85]; n[ 86] = r[ 86]; n[ 87] = r[ 87];
n[ 88] = r[ 88]; n[ 89] = r[ 89]; n[ 90] = r[ 90]; n[ 91] = r[ 91];
n[ 92] = r[ 92]; n[ 93] = r[ 93]; n[ 94] = r[ 94]; n[ 95] = r[ 95];
n[ 96] = r[ 96]; n[ 97] = r[ 97]; n[ 98] = r[ 98]; n[ 99] = r[ 99];
n[100] = r[100]; n[101] = r[101]; n[102] = r[102]; n[103] = r[103];
n[104] = r[104]; n[105] = r[105]; n[106] = r[106]; n[107] = r[107];
n[108] = r[108]; n[109] = r[109]; n[110] = r[110]; n[111] = r[111];
n[112] = r[112]; n[113] = r[113]; n[114] = r[114]; n[115] = r[115];
n[116] = r[116]; n[117] = r[117]; n[118] = r[118]; n[119] = r[119];
n[120] = r[120]; n[121] = r[121]; n[122] = r[122]; n[123] = r[123];
n[124] = r[124]; n[125] = r[125]; n[126] = r[126]; n[127] = r[127];
}
}
// r[128], result, r = x * y
// x[ 64], multiplier (1st factor)
// y[ 64], multiplicand (2nd factor)
DECLSPEC void mul (PRIVATE_AS u32 *r, PRIVATE_AS const u32 *x, PRIVATE_AS const u32 *y)
{
for (u32 i = 0; i < 64; i++)
{
u64 c = 0; // carry
for (u32 j = 0; j < 64; j++)
{
const u32 idx = i + j;
const u64 p = (u64) x[i] * y[j]; // main product
const u32 u = p >> 32;
const u32 l = p >> 0;
const u64 s = c + r[idx] + l; // sum
c = (s >> 32) + u;
r[idx] = (s >> 0);
}
r[i + 64] = (u32) c;
}
}
// r[64], result, r = lower_bits (x * y), r = (x * y) & mask
// x[64], multiplier (1st factor)
// y[64], multiplicand (2nd factor)
// only compute lower bits (because we exploit our Montgomery "mask")
DECLSPEC void mul_masked (PRIVATE_AS u32 *r, PRIVATE_AS const u32 *x, PRIVATE_AS const u32 *y)
{
for (u32 i = 0; i < 64; i++)
{
u64 c = 0; // carry
// for (u32 j = 0; j < 64; j++)
// {
// const u32 idx = i + j;
// if (idx >= 63) break;
// ...
// }
// or:
for (u32 j = 0; j < (64 - i); j++) // our implied "mask" (only lower 256 bytes for idx)
{
const u32 idx = i + j;
const u64 p = (u64) x[i] * y[j]; // product
const u32 u = p >> 32;
const u32 l = p >> 0;
const u64 s = c + r[idx] + l; // sum
c = (s >> 32) + u;
r[idx] = (s >> 0);
}
}
}
// x [ 64], multiplier, input and at the same time output, (x = (x * y) % m)
// y [ 64], multiplicand
// m [128], modulo
// fact[ 64], our m' (actually it is fact[65])
DECLSPEC void mul_mod128 (PRIVATE_AS u32 *x, PRIVATE_AS const u32 *y, PRIVATE_AS const u32 *m, PRIVATE_AS const u32 *fact)
{
// 1st multiplication
// p = x * y
u32 p[128] = { 0 };
mul (p, x, y);
// 2nd multiplication
// t = ((p & mask) * fact) & mask, (we optimize this in mul_masked ())
u32 t[64] = { 0 }; // or use t[128] here, but not needed
mul_masked (t, p, fact);
// 3rd multiplication
// z = t * m
u32 z[128] = { 0 };
mul (z, t, m);
// result:
// t = (p + z) >> bits
// u32 t[128] = { 0 }; // optimization, smaller t[] array:
// u32 t[ 64] = { 0 };
// for (u32 i = 0; i < 128; i++) t[i] = p[i] + z[i];
// t[ 0] = p[ 0] + z[ 0]; t[ 1] = p[ 1] + z[ 1];
// t[ 2] = p[ 2] + z[ 2]; t[ 3] = p[ 3] + z[ 3];
// t[ 4] = p[ 4] + z[ 4]; t[ 5] = p[ 5] + z[ 5];
// t[ 6] = p[ 6] + z[ 6]; t[ 7] = p[ 7] + z[ 7];
// t[ 8] = p[ 8] + z[ 8]; t[ 9] = p[ 9] + z[ 9];
// t[ 10] = p[ 10] + z[ 10]; t[ 11] = p[ 11] + z[ 11];
// t[ 12] = p[ 12] + z[ 12]; t[ 13] = p[ 13] + z[ 13];
// t[ 14] = p[ 14] + z[ 14]; t[ 15] = p[ 15] + z[ 15];
// t[ 16] = p[ 16] + z[ 16]; t[ 17] = p[ 17] + z[ 17];
// t[ 18] = p[ 18] + z[ 18]; t[ 19] = p[ 19] + z[ 19];
// t[ 20] = p[ 20] + z[ 20]; t[ 21] = p[ 21] + z[ 21];
// t[ 22] = p[ 22] + z[ 22]; t[ 23] = p[ 23] + z[ 23];
// t[ 24] = p[ 24] + z[ 24]; t[ 25] = p[ 25] + z[ 25];
// t[ 26] = p[ 26] + z[ 26]; t[ 27] = p[ 27] + z[ 27];
// t[ 28] = p[ 28] + z[ 28]; t[ 29] = p[ 29] + z[ 29];
// t[ 30] = p[ 30] + z[ 30]; t[ 31] = p[ 31] + z[ 31];
// t[ 32] = p[ 32] + z[ 32]; t[ 33] = p[ 33] + z[ 33];
// t[ 34] = p[ 34] + z[ 34]; t[ 35] = p[ 35] + z[ 35];
// t[ 36] = p[ 36] + z[ 36]; t[ 37] = p[ 37] + z[ 37];
// t[ 38] = p[ 38] + z[ 38]; t[ 39] = p[ 39] + z[ 39];
// t[ 40] = p[ 40] + z[ 40]; t[ 41] = p[ 41] + z[ 41];
// t[ 42] = p[ 42] + z[ 42]; t[ 43] = p[ 43] + z[ 43];
// t[ 44] = p[ 44] + z[ 44]; t[ 45] = p[ 45] + z[ 45];
// t[ 46] = p[ 46] + z[ 46]; t[ 47] = p[ 47] + z[ 47];
// t[ 48] = p[ 48] + z[ 48]; t[ 49] = p[ 49] + z[ 49];
// t[ 50] = p[ 50] + z[ 50]; t[ 51] = p[ 51] + z[ 51];
// t[ 52] = p[ 52] + z[ 52]; t[ 53] = p[ 53] + z[ 53];
// t[ 54] = p[ 54] + z[ 54]; t[ 55] = p[ 55] + z[ 55];
// t[ 56] = p[ 56] + z[ 56]; t[ 57] = p[ 57] + z[ 57];
// t[ 58] = p[ 58] + z[ 58]; t[ 59] = p[ 59] + z[ 59];
// t[ 60] = p[ 60] + z[ 60]; t[ 61] = p[ 61] + z[ 61];
// t[ 62] = p[ 62] + z[ 62]; t[ 63] = p[ 63] + z[ 63];
// t[ 64] = p[ 64] + z[ 64]; t[ 65] = p[ 65] + z[ 65];
// t[ 66] = p[ 66] + z[ 66]; t[ 67] = p[ 67] + z[ 67];
// t[ 68] = p[ 68] + z[ 68]; t[ 69] = p[ 69] + z[ 69];
// t[ 70] = p[ 70] + z[ 70]; t[ 71] = p[ 71] + z[ 71];
// t[ 72] = p[ 72] + z[ 72]; t[ 73] = p[ 73] + z[ 73];
// t[ 74] = p[ 74] + z[ 74]; t[ 75] = p[ 75] + z[ 75];
// t[ 76] = p[ 76] + z[ 76]; t[ 77] = p[ 77] + z[ 77];
// t[ 78] = p[ 78] + z[ 78]; t[ 79] = p[ 79] + z[ 79];
// t[ 80] = p[ 80] + z[ 80]; t[ 81] = p[ 81] + z[ 81];
// t[ 82] = p[ 82] + z[ 82]; t[ 83] = p[ 83] + z[ 83];
// t[ 84] = p[ 84] + z[ 84]; t[ 85] = p[ 85] + z[ 85];
// t[ 86] = p[ 86] + z[ 86]; t[ 87] = p[ 87] + z[ 87];
// t[ 88] = p[ 88] + z[ 88]; t[ 89] = p[ 89] + z[ 89];
// t[ 90] = p[ 90] + z[ 90]; t[ 91] = p[ 91] + z[ 91];
// t[ 92] = p[ 92] + z[ 92]; t[ 93] = p[ 93] + z[ 93];
// t[ 94] = p[ 94] + z[ 94]; t[ 95] = p[ 95] + z[ 95];
// t[ 96] = p[ 96] + z[ 96]; t[ 97] = p[ 97] + z[ 97];
// t[ 98] = p[ 98] + z[ 98]; t[ 99] = p[ 99] + z[ 99];
// t[100] = p[100] + z[100]; t[101] = p[101] + z[101];
// t[102] = p[102] + z[102]; t[103] = p[103] + z[103];
// t[104] = p[104] + z[104]; t[105] = p[105] + z[105];
// t[106] = p[106] + z[106]; t[107] = p[107] + z[107];
// t[108] = p[108] + z[108]; t[109] = p[109] + z[109];
// t[110] = p[110] + z[110]; t[111] = p[111] + z[111];
// t[112] = p[112] + z[112]; t[113] = p[113] + z[113];
// t[114] = p[114] + z[114]; t[115] = p[115] + z[115];
// t[116] = p[116] + z[116]; t[117] = p[117] + z[117];
// t[118] = p[118] + z[118]; t[119] = p[119] + z[119];
// t[120] = p[120] + z[120]; t[121] = p[121] + z[121];
// t[122] = p[122] + z[122]; t[123] = p[123] + z[123];
// t[124] = p[124] + z[124]; t[125] = p[125] + z[125];
// t[126] = p[126] + z[126]; t[127] = p[127] + z[127];
// optimization, we shift it down already here:
// for (u32 i = 0; i < 64; i++) t[i] = p[i + 64] + z[i + 64];
t[ 0] = p[ 64] + z[ 64]; t[ 1] = p[ 65] + z[ 65];
t[ 2] = p[ 66] + z[ 66]; t[ 3] = p[ 67] + z[ 67];
t[ 4] = p[ 68] + z[ 68]; t[ 5] = p[ 69] + z[ 69];
t[ 6] = p[ 70] + z[ 70]; t[ 7] = p[ 71] + z[ 71];
t[ 8] = p[ 72] + z[ 72]; t[ 9] = p[ 73] + z[ 73];
t[10] = p[ 74] + z[ 74]; t[11] = p[ 75] + z[ 75];
t[12] = p[ 76] + z[ 76]; t[13] = p[ 77] + z[ 77];
t[14] = p[ 78] + z[ 78]; t[15] = p[ 79] + z[ 79];
t[16] = p[ 80] + z[ 80]; t[17] = p[ 81] + z[ 81];
t[18] = p[ 82] + z[ 82]; t[19] = p[ 83] + z[ 83];
t[20] = p[ 84] + z[ 84]; t[21] = p[ 85] + z[ 85];
t[22] = p[ 86] + z[ 86]; t[23] = p[ 87] + z[ 87];
t[24] = p[ 88] + z[ 88]; t[25] = p[ 89] + z[ 89];
t[26] = p[ 90] + z[ 90]; t[27] = p[ 91] + z[ 91];
t[28] = p[ 92] + z[ 92]; t[29] = p[ 93] + z[ 93];
t[30] = p[ 94] + z[ 94]; t[31] = p[ 95] + z[ 95];
t[32] = p[ 96] + z[ 96]; t[33] = p[ 97] + z[ 97];
t[34] = p[ 98] + z[ 98]; t[35] = p[ 99] + z[ 99];
t[36] = p[100] + z[100]; t[37] = p[101] + z[101];
t[38] = p[102] + z[102]; t[39] = p[103] + z[103];
t[40] = p[104] + z[104]; t[41] = p[105] + z[105];
t[42] = p[106] + z[106]; t[43] = p[107] + z[107];
t[44] = p[108] + z[108]; t[45] = p[109] + z[109];
t[46] = p[110] + z[110]; t[47] = p[111] + z[111];
t[48] = p[112] + z[112]; t[49] = p[113] + z[113];
t[50] = p[114] + z[114]; t[51] = p[115] + z[115];
t[52] = p[116] + z[116]; t[53] = p[117] + z[117];
t[54] = p[118] + z[118]; t[55] = p[119] + z[119];
t[56] = p[120] + z[120]; t[57] = p[121] + z[121];
t[58] = p[122] + z[122]; t[59] = p[123] + z[123];
t[60] = p[124] + z[124]; t[61] = p[125] + z[125];
t[62] = p[126] + z[126]; t[63] = p[127] + z[127];
// take care of the carry for the addition above (i.e check for "overflows")
// for (u32 i = 1; i < 128; i++) t[i] += t[i - 1] < p[i - 1];
// t[ 1] += t[ 0] < p[ 0];
// t[ 2] += t[ 1] < p[ 1];
// t[ 3] += t[ 2] < p[ 2];
// t[ 4] += t[ 3] < p[ 3];
// t[ 5] += t[ 4] < p[ 4];
// t[ 6] += t[ 5] < p[ 5];
// t[ 7] += t[ 6] < p[ 6];
// t[ 8] += t[ 7] < p[ 7];
// t[ 9] += t[ 8] < p[ 8];
// t[ 10] += t[ 9] < p[ 9];
// t[ 11] += t[ 10] < p[ 10];
// t[ 12] += t[ 11] < p[ 11];
// t[ 13] += t[ 12] < p[ 12];
// t[ 14] += t[ 13] < p[ 13];
// t[ 15] += t[ 14] < p[ 14];
// t[ 16] += t[ 15] < p[ 15];
// t[ 17] += t[ 16] < p[ 16];
// t[ 18] += t[ 17] < p[ 17];
// t[ 19] += t[ 18] < p[ 18];
// t[ 20] += t[ 19] < p[ 19];
// t[ 21] += t[ 20] < p[ 20];
// t[ 22] += t[ 21] < p[ 21];
// t[ 23] += t[ 22] < p[ 22];
// t[ 24] += t[ 23] < p[ 23];
// t[ 25] += t[ 24] < p[ 24];
// t[ 26] += t[ 25] < p[ 25];
// t[ 27] += t[ 26] < p[ 26];
// t[ 28] += t[ 27] < p[ 27];
// t[ 29] += t[ 28] < p[ 28];
// t[ 30] += t[ 29] < p[ 29];
// t[ 31] += t[ 30] < p[ 30];
// t[ 32] += t[ 31] < p[ 31];
// t[ 33] += t[ 32] < p[ 32];
// t[ 34] += t[ 33] < p[ 33];
// t[ 35] += t[ 34] < p[ 34];
// t[ 36] += t[ 35] < p[ 35];
// t[ 37] += t[ 36] < p[ 36];
// t[ 38] += t[ 37] < p[ 37];
// t[ 39] += t[ 38] < p[ 38];
// t[ 40] += t[ 39] < p[ 39];
// t[ 41] += t[ 40] < p[ 40];
// t[ 42] += t[ 41] < p[ 41];
// t[ 43] += t[ 42] < p[ 42];
// t[ 44] += t[ 43] < p[ 43];
// t[ 45] += t[ 44] < p[ 44];
// t[ 46] += t[ 45] < p[ 45];
// t[ 47] += t[ 46] < p[ 46];
// t[ 48] += t[ 47] < p[ 47];
// t[ 49] += t[ 48] < p[ 48];
// t[ 50] += t[ 49] < p[ 49];
// t[ 51] += t[ 50] < p[ 50];
// t[ 52] += t[ 51] < p[ 51];
// t[ 53] += t[ 52] < p[ 52];
// t[ 54] += t[ 53] < p[ 53];
// t[ 55] += t[ 54] < p[ 54];
// t[ 56] += t[ 55] < p[ 55];
// t[ 57] += t[ 56] < p[ 56];
// t[ 58] += t[ 57] < p[ 57];
// t[ 59] += t[ 58] < p[ 58];
// t[ 60] += t[ 59] < p[ 59];
// t[ 61] += t[ 60] < p[ 60];
// t[ 62] += t[ 61] < p[ 61];
// t[ 63] += t[ 62] < p[ 62];
// t[ 64] += t; // we know that it overflows (due to the way Montgomery works)
// t[ 65] += t[ 64] < p[ 64];
// t[ 66] += t[ 65] < p[ 65];
// t[ 67] += t[ 66] < p[ 66];
// t[ 68] += t[ 67] < p[ 67];
// t[ 69] += t[ 68] < p[ 68];
// t[ 70] += t[ 69] < p[ 69];
// t[ 71] += t[ 70] < p[ 70];
// t[ 72] += t[ 71] < p[ 71];
// t[ 73] += t[ 72] < p[ 72];
// t[ 74] += t[ 73] < p[ 73];
// t[ 75] += t[ 74] < p[ 74];
// t[ 76] += t[ 75] < p[ 75];
// t[ 77] += t[ 76] < p[ 76];
// t[ 78] += t[ 77] < p[ 77];
// t[ 79] += t[ 78] < p[ 78];
// t[ 80] += t[ 79] < p[ 79];
// t[ 81] += t[ 80] < p[ 80];
// t[ 82] += t[ 81] < p[ 81];
// t[ 83] += t[ 82] < p[ 82];
// t[ 84] += t[ 83] < p[ 83];
// t[ 85] += t[ 84] < p[ 84];
// t[ 86] += t[ 85] < p[ 85];
// t[ 87] += t[ 86] < p[ 86];
// t[ 88] += t[ 87] < p[ 87];
// t[ 89] += t[ 88] < p[ 88];
// t[ 90] += t[ 89] < p[ 89];
// t[ 91] += t[ 90] < p[ 90];
// t[ 92] += t[ 91] < p[ 91];
// t[ 93] += t[ 92] < p[ 92];
// t[ 94] += t[ 93] < p[ 93];
// t[ 95] += t[ 94] < p[ 94];
// t[ 96] += t[ 95] < p[ 95];
// t[ 97] += t[ 96] < p[ 96];
// t[ 98] += t[ 97] < p[ 97];
// t[ 99] += t[ 98] < p[ 98];
// t[100] += t[ 99] < p[ 99];
// t[101] += t[100] < p[100];
// t[102] += t[101] < p[101];
// t[103] += t[102] < p[102];
// t[104] += t[103] < p[103];
// t[105] += t[104] < p[104];
// t[106] += t[105] < p[105];
// t[107] += t[106] < p[106];
// t[108] += t[107] < p[107];
// t[109] += t[108] < p[108];
// t[110] += t[109] < p[109];
// t[111] += t[110] < p[110];
// t[112] += t[111] < p[111];
// t[113] += t[112] < p[112];
// t[114] += t[113] < p[113];
// t[115] += t[114] < p[114];
// t[116] += t[115] < p[115];
// t[117] += t[116] < p[116];
// t[118] += t[117] < p[117];
// t[119] += t[118] < p[118];
// t[120] += t[119] < p[119];
// t[121] += t[120] < p[120];
// t[122] += t[121] < p[121];
// t[123] += t[122] < p[122];
// t[124] += t[123] < p[123];
// t[125] += t[124] < p[124];
// t[126] += t[125] < p[125];
// t[127] += t[126] < p[126];
t[ 0] += 1; // we know that it overflows (due to the way Montgomery works)
// for (u32 i = 1; i < 64; i++) t[i] += t[i - 1] < p[i + 63];
t[ 1] += t[ 0] < p[ 64];
t[ 2] += t[ 1] < p[ 65];
t[ 3] += t[ 2] < p[ 66];
t[ 4] += t[ 3] < p[ 67];
t[ 5] += t[ 4] < p[ 68];
t[ 6] += t[ 5] < p[ 69];
t[ 7] += t[ 6] < p[ 70];
t[ 8] += t[ 7] < p[ 71];
t[ 9] += t[ 8] < p[ 72];
t[10] += t[ 9] < p[ 73];
t[11] += t[10] < p[ 74];
t[12] += t[11] < p[ 75];
t[13] += t[12] < p[ 76];
t[14] += t[13] < p[ 77];
t[15] += t[14] < p[ 78];
t[16] += t[15] < p[ 79];
t[17] += t[16] < p[ 80];
t[18] += t[17] < p[ 81];
t[19] += t[18] < p[ 82];
t[20] += t[19] < p[ 83];
t[21] += t[20] < p[ 84];
t[22] += t[21] < p[ 85];
t[23] += t[22] < p[ 86];
t[24] += t[23] < p[ 87];
t[25] += t[24] < p[ 88];
t[26] += t[25] < p[ 89];
t[27] += t[26] < p[ 90];
t[28] += t[27] < p[ 91];
t[29] += t[28] < p[ 92];
t[30] += t[29] < p[ 93];
t[31] += t[30] < p[ 94];
t[32] += t[31] < p[ 95];
t[33] += t[32] < p[ 96];
t[34] += t[33] < p[ 97];
t[35] += t[34] < p[ 98];
t[36] += t[35] < p[ 99];
t[37] += t[36] < p[100];
t[38] += t[37] < p[101];
t[39] += t[38] < p[102];
t[40] += t[39] < p[103];
t[41] += t[40] < p[104];
t[42] += t[41] < p[105];
t[43] += t[42] < p[106];
t[44] += t[43] < p[107];
t[45] += t[44] < p[108];
t[46] += t[45] < p[109];
t[47] += t[46] < p[110];
t[48] += t[47] < p[111];
t[49] += t[48] < p[112];
t[50] += t[49] < p[113];
t[51] += t[50] < p[114];
t[52] += t[51] < p[115];
t[53] += t[52] < p[116];
t[54] += t[53] < p[117];
t[55] += t[54] < p[118];
t[56] += t[55] < p[119];
t[57] += t[56] < p[120];
t[58] += t[57] < p[121];
t[59] += t[58] < p[122];
t[60] += t[59] < p[123];
t[61] += t[60] < p[124];
t[62] += t[61] < p[125];
t[63] += t[62] < p[126];
// VERY IMPORTANT: if we have an overflow at the highest u32, we need to do the substraction
const u32 c = t[63] < p[127]; // carry / overflow
// x = t
// (x is actually already our result, but it's possible that we need to do the modulo/substract)
// for (u32 i = 0; i < 64; i++) x[i] = t[i];
x[ 0] = t[ 0]; x[ 1] = t[ 1]; x[ 2] = t[ 2]; x[ 3] = t[ 3];
x[ 4] = t[ 4]; x[ 5] = t[ 5]; x[ 6] = t[ 6]; x[ 7] = t[ 7];
x[ 8] = t[ 8]; x[ 9] = t[ 9]; x[10] = t[10]; x[11] = t[11];
x[12] = t[12]; x[13] = t[13]; x[14] = t[14]; x[15] = t[15];
x[16] = t[16]; x[17] = t[17]; x[18] = t[18]; x[19] = t[19];
x[20] = t[20]; x[21] = t[21]; x[22] = t[22]; x[23] = t[23];
x[24] = t[24]; x[25] = t[25]; x[26] = t[26]; x[27] = t[27];
x[28] = t[28]; x[29] = t[29]; x[30] = t[30]; x[31] = t[31];
x[32] = t[32]; x[33] = t[33]; x[34] = t[34]; x[35] = t[35];
x[36] = t[36]; x[37] = t[37]; x[38] = t[38]; x[39] = t[39];
x[40] = t[40]; x[41] = t[41]; x[42] = t[42]; x[43] = t[43];
x[44] = t[44]; x[45] = t[45]; x[46] = t[46]; x[47] = t[47];
x[48] = t[48]; x[49] = t[49]; x[50] = t[50]; x[51] = t[51];
x[52] = t[52]; x[53] = t[53]; x[54] = t[54]; x[55] = t[55];
x[56] = t[56]; x[57] = t[57]; x[58] = t[58]; x[59] = t[59];
x[60] = t[60]; x[61] = t[61]; x[62] = t[62]; x[63] = t[63];
// if (x >= m) x -= m
// (check if we need to substract, or do a "fast modulo")
u32 sub_needed = 1;
if (c == 0)
{
for (int i = 63; i >= 0; i--)
{
if (x[i] < m[i]) // FAIL case
{
sub_needed = 0;
break;
}
else
if (x[i] > m[i]) // definitely a SUCCESS case (otherwise continue to check if equal)
{
break;
}
}
}
if (sub_needed == 1)
{
// x -= m
// for (u32 i = 0; i < 64; i++) x[i] -= m[i];
x[ 0] -= m[ 0]; x[ 1] -= m[ 1]; x[ 2] -= m[ 2]; x[ 3] -= m[ 3];
x[ 4] -= m[ 4]; x[ 5] -= m[ 5]; x[ 6] -= m[ 6]; x[ 7] -= m[ 7];
x[ 8] -= m[ 8]; x[ 9] -= m[ 9]; x[10] -= m[10]; x[11] -= m[11];
x[12] -= m[12]; x[13] -= m[13]; x[14] -= m[14]; x[15] -= m[15];
x[16] -= m[16]; x[17] -= m[17]; x[18] -= m[18]; x[19] -= m[19];
x[20] -= m[20]; x[21] -= m[21]; x[22] -= m[22]; x[23] -= m[23];
x[24] -= m[24]; x[25] -= m[25]; x[26] -= m[26]; x[27] -= m[27];
x[28] -= m[28]; x[29] -= m[29]; x[30] -= m[30]; x[31] -= m[31];
x[32] -= m[32]; x[33] -= m[33]; x[34] -= m[34]; x[35] -= m[35];
x[36] -= m[36]; x[37] -= m[37]; x[38] -= m[38]; x[39] -= m[39];
x[40] -= m[40]; x[41] -= m[41]; x[42] -= m[42]; x[43] -= m[43];
x[44] -= m[44]; x[45] -= m[45]; x[46] -= m[46]; x[47] -= m[47];
x[48] -= m[48]; x[49] -= m[49]; x[50] -= m[50]; x[51] -= m[51];
x[52] -= m[52]; x[53] -= m[53]; x[54] -= m[54]; x[55] -= m[55];
x[56] -= m[56]; x[57] -= m[57]; x[58] -= m[58]; x[59] -= m[59];
x[60] -= m[60]; x[61] -= m[61]; x[62] -= m[62]; x[63] -= m[63];
// take care of the "borrow":
// for (u32 i = 0; i < 63; i++) if (x[i] > t[i]) x[i + 1]--;
// if (x[ 0] > t[ 0]) x[ 1]--;
// if (x[ 1] > t[ 1]) x[ 2]--;
// if (x[ 2] > t[ 2]) x[ 3]--;
// if (x[ 3] > t[ 3]) x[ 4]--;
// if (x[ 4] > t[ 4]) x[ 5]--;
// if (x[ 5] > t[ 5]) x[ 6]--;
// if (x[ 6] > t[ 6]) x[ 7]--;
// if (x[ 7] > t[ 7]) x[ 8]--;
// if (x[ 8] > t[ 8]) x[ 9]--;
// if (x[ 9] > t[ 9]) x[ 10]--;
// if (x[ 10] > t[ 10]) x[ 11]--;
// if (x[ 11] > t[ 11]) x[ 12]--;
// if (x[ 12] > t[ 12]) x[ 13]--;
// if (x[ 13] > t[ 13]) x[ 14]--;
// if (x[ 14] > t[ 14]) x[ 15]--;
// if (x[ 15] > t[ 15]) x[ 16]--;
// if (x[ 16] > t[ 16]) x[ 17]--;
// if (x[ 17] > t[ 17]) x[ 18]--;
// if (x[ 18] > t[ 18]) x[ 19]--;
// if (x[ 19] > t[ 19]) x[ 20]--;
// if (x[ 20] > t[ 20]) x[ 21]--;
// if (x[ 21] > t[ 21]) x[ 22]--;
// if (x[ 22] > t[ 22]) x[ 23]--;
// if (x[ 23] > t[ 23]) x[ 24]--;
// if (x[ 24] > t[ 24]) x[ 25]--;
// if (x[ 25] > t[ 25]) x[ 26]--;
// if (x[ 26] > t[ 26]) x[ 27]--;
// if (x[ 27] > t[ 27]) x[ 28]--;
// if (x[ 28] > t[ 28]) x[ 29]--;
// if (x[ 29] > t[ 29]) x[ 30]--;
// if (x[ 30] > t[ 30]) x[ 31]--;
// if (x[ 31] > t[ 31]) x[ 32]--;
// if (x[ 32] > t[ 32]) x[ 33]--;
// if (x[ 33] > t[ 33]) x[ 34]--;
// if (x[ 34] > t[ 34]) x[ 35]--;
// if (x[ 35] > t[ 35]) x[ 36]--;
// if (x[ 36] > t[ 36]) x[ 37]--;
// if (x[ 37] > t[ 37]) x[ 38]--;
// if (x[ 38] > t[ 38]) x[ 39]--;
// if (x[ 39] > t[ 39]) x[ 40]--;
// if (x[ 40] > t[ 40]) x[ 41]--;
// if (x[ 41] > t[ 41]) x[ 42]--;
// if (x[ 42] > t[ 42]) x[ 43]--;
// if (x[ 43] > t[ 43]) x[ 44]--;
// if (x[ 44] > t[ 44]) x[ 45]--;
// if (x[ 45] > t[ 45]) x[ 46]--;
// if (x[ 46] > t[ 46]) x[ 47]--;
// if (x[ 47] > t[ 47]) x[ 48]--;
// if (x[ 48] > t[ 48]) x[ 49]--;
// if (x[ 49] > t[ 49]) x[ 50]--;
// if (x[ 50] > t[ 50]) x[ 51]--;
// if (x[ 51] > t[ 51]) x[ 52]--;
// if (x[ 52] > t[ 52]) x[ 53]--;
// if (x[ 53] > t[ 53]) x[ 54]--;
// if (x[ 54] > t[ 54]) x[ 55]--;
// if (x[ 55] > t[ 55]) x[ 56]--;
// if (x[ 56] > t[ 56]) x[ 57]--;
// if (x[ 57] > t[ 57]) x[ 58]--;
// if (x[ 58] > t[ 58]) x[ 59]--;
// if (x[ 59] > t[ 59]) x[ 60]--;
// if (x[ 60] > t[ 60]) x[ 61]--;
// if (x[ 61] > t[ 61]) x[ 62]--;
// if (x[ 62] > t[ 62]) x[ 63]--;
// for (u32 i = 1; i < 64; i++) x[i] -= x[i - 1] > t[i - 1];
x[ 1] -= x[ 0] > t[ 0];
x[ 2] -= x[ 1] > t[ 1];
x[ 3] -= x[ 2] > t[ 2];
x[ 4] -= x[ 3] > t[ 3];
x[ 5] -= x[ 4] > t[ 4];
x[ 6] -= x[ 5] > t[ 5];
x[ 7] -= x[ 6] > t[ 6];
x[ 8] -= x[ 7] > t[ 7];
x[ 9] -= x[ 8] > t[ 8];
x[10] -= x[ 9] > t[ 9];
x[11] -= x[10] > t[10];
x[12] -= x[11] > t[11];
x[13] -= x[12] > t[12];
x[14] -= x[13] > t[13];
x[15] -= x[14] > t[14];
x[16] -= x[15] > t[15];
x[17] -= x[16] > t[16];
x[18] -= x[17] > t[17];
x[19] -= x[18] > t[18];
x[20] -= x[19] > t[19];
x[21] -= x[20] > t[20];
x[22] -= x[21] > t[21];
x[23] -= x[22] > t[22];
x[24] -= x[23] > t[23];
x[25] -= x[24] > t[24];
x[26] -= x[25] > t[25];
x[27] -= x[26] > t[26];
x[28] -= x[27] > t[27];
x[29] -= x[28] > t[28];
x[30] -= x[29] > t[29];
x[31] -= x[30] > t[30];
x[32] -= x[31] > t[31];
x[33] -= x[32] > t[32];
x[34] -= x[33] > t[33];
x[35] -= x[34] > t[34];
x[36] -= x[35] > t[35];
x[37] -= x[36] > t[36];
x[38] -= x[37] > t[37];
x[39] -= x[38] > t[38];
x[40] -= x[39] > t[39];
x[41] -= x[40] > t[40];
x[42] -= x[41] > t[41];
x[43] -= x[42] > t[42];
x[44] -= x[43] > t[43];
x[45] -= x[44] > t[44];
x[46] -= x[45] > t[45];
x[47] -= x[46] > t[46];
x[48] -= x[47] > t[47];
x[49] -= x[48] > t[48];
x[50] -= x[49] > t[49];
x[51] -= x[50] > t[50];
x[52] -= x[51] > t[51];
x[53] -= x[52] > t[52];
x[54] -= x[53] > t[53];
x[55] -= x[54] > t[54];
x[56] -= x[55] > t[55];
x[57] -= x[56] > t[56];
x[58] -= x[57] > t[57];
x[59] -= x[58] > t[58];
x[60] -= x[59] > t[59];
x[61] -= x[60] > t[60];
x[62] -= x[61] > t[61];
x[63] -= x[62] > t[62];
}
}
// r [ 64], input (reducer % m) and at the same time output, r = (y ^ x) % m
// u32 b_pre[10240], precomputed base powers (160 powers for each bit of SHA1 * 64 bytes)
// y [ 5], exponent (in standard form, not Montgomery)
// m [ 128], modulo
// fact [ 64], our m' (actually it is fact[65])
DECLSPEC void pow_mod_precomp_g (PRIVATE_AS u32 *r, PRIVATE_AS const u32 *b_pre, PRIVATE_AS const u32 *y, PRIVATE_AS const u32 *m, PRIVATE_AS const u32 *fact)
{
for (u32 i = 0; i < 160; i++)
{
const u32 div = i / 32;
const u32 mod = i % 32; // & 31
const u32 bit_set = (y[div] >> mod) & 1;
if (bit_set == 1) mul_mod128 (r, b_pre + i * 64, m, fact);
}
}
// r [ 64], input (reducer % m) and at the same time output, r = (y ^ x) % m
// x [ 64], our main Montgomery number (base, generator)
// y [ 5], our SHA1 vector, exponent (in standard form, not Montgomery)
// m [128], modulo
// fact[ 64], our m' (actually it is fact[65])
// we replaced this with pow_mod_precomp_g ()
DECLSPEC void pow_mod (PRIVATE_AS u32 *r, PRIVATE_AS u32 *x, PRIVATE_AS const u32 *y, PRIVATE_AS const u32 *m, PRIVATE_AS const u32 *fact)
{
u32 highest_bit = 0;
for (highest_bit = 159; highest_bit >= 1; highest_bit--)
{
const u32 div = highest_bit / 32;
const u32 mod = highest_bit % 32; // & 31
// if we find a bit that is set to 1:
const u32 bit_set = (y[div] >> mod) & 1;
if (bit_set == 1) break;
}
for (u32 i = 0; i <= highest_bit; i++)
{
const u32 div = i / 32;
const u32 mod = i % 32; // & 31
const u32 bit_set = (y[div] >> mod) & 1;
if (bit_set == 1) mul_mod128 (r, x, m, fact);
mul_mod128 (x, x, m, fact);
}
}
// u [ 64], rinv (r') output
// v [ 65], fact (m') output, we only set the first 256 bytes, but we need 1 extra u32 (or byte)
// m [128], modulo
DECLSPEC void simple_euclidean_gcd (PRIVATE_AS u32 *u, PRIVATE_AS u32 *v, PRIVATE_AS const u32 *m)
{
// outputs u and v must be initialized to ALL zeros
u[0] = 1;
// v[0] = 0;
// we skip this next step, since we know "r" in advance:
// u32 r[65] = { 0 };
// r[64] = 1;
//
// // t = r:
//
// u32 t[65] = { 0 };
//
// for (u32 i = 0; i < 65; i++) t[i] = r[i];
//
// t[ 0] = r[ 0]; t[ 1] = r[ 1]; t[ 2] = r[ 2]; t[ 3] = r[ 3];
// t[ 4] = r[ 4]; t[ 5] = r[ 5]; t[ 6] = r[ 6]; t[ 7] = r[ 7];
// t[ 8] = r[ 8]; t[ 9] = r[ 9]; t[10] = r[10]; t[11] = r[11];
// t[12] = r[12]; t[13] = r[13]; t[14] = r[14]; t[15] = r[15];
// t[16] = r[16]; t[17] = r[17]; t[18] = r[18]; t[19] = r[19];
// t[20] = r[20]; t[21] = r[21]; t[22] = r[22]; t[23] = r[23];
// t[24] = r[24]; t[25] = r[25]; t[26] = r[26]; t[27] = r[27];
// t[28] = r[28]; t[29] = r[29]; t[30] = r[30]; t[31] = r[31];
// t[32] = r[32]; t[33] = r[33]; t[34] = r[34]; t[35] = r[35];
// t[36] = r[36]; t[37] = r[37]; t[38] = r[38]; t[39] = r[39];
// t[40] = r[40]; t[41] = r[41]; t[42] = r[42]; t[43] = r[43];
// t[44] = r[44]; t[45] = r[45]; t[46] = r[46]; t[47] = r[47];
// t[48] = r[48]; t[49] = r[49]; t[50] = r[50]; t[51] = r[51];
// t[52] = r[52]; t[53] = r[53]; t[54] = r[54]; t[55] = r[55];
// t[56] = r[56]; t[57] = r[57]; t[58] = r[58]; t[59] = r[59];
// t[60] = r[60]; t[61] = r[61]; t[62] = r[62]; t[63] = r[63];
// t[64] = r[64];
//
// while ((t[ 0] != 0) || (t[ 1] != 0) || (t[ 2] != 0) || (t[ 3] != 0) ||
// (t[ 4] != 0) || (t[ 5] != 0) || (t[ 6] != 0) || (t[ 7] != 0) ||
// (t[ 8] != 0) || (t[ 9] != 0) || (t[10] != 0) || (t[11] != 0) ||
// (t[12] != 0) || (t[13] != 0) || (t[14] != 0) || (t[15] != 0) ||
// (t[16] != 0) || (t[17] != 0) || (t[18] != 0) || (t[19] != 0) ||
// (t[20] != 0) || (t[21] != 0) || (t[22] != 0) || (t[23] != 0) ||
// (t[24] != 0) || (t[25] != 0) || (t[26] != 0) || (t[27] != 0) ||
// (t[28] != 0) || (t[29] != 0) || (t[30] != 0) || (t[31] != 0) ||
// (t[32] != 0) || (t[33] != 0) || (t[34] != 0) || (t[35] != 0) ||
// (t[36] != 0) || (t[37] != 0) || (t[38] != 0) || (t[39] != 0) ||
// (t[40] != 0) || (t[41] != 0) || (t[42] != 0) || (t[43] != 0) ||
// (t[44] != 0) || (t[45] != 0) || (t[46] != 0) || (t[47] != 0) ||
// (t[48] != 0) || (t[49] != 0) || (t[50] != 0) || (t[51] != 0) ||
// (t[52] != 0) || (t[53] != 0) || (t[54] != 0) || (t[55] != 0) ||
// (t[56] != 0) || (t[57] != 0) || (t[58] != 0) || (t[59] != 0) ||
// (t[60] != 0) || (t[61] != 0) || (t[62] != 0) || (t[63] != 0) ||
// (t[64] != 0))
// {
// // t >>= 1:
//
// t[ 0] = (t[ 1] << 31) | (t[ 0] >> 1);
// t[ 1] = (t[ 2] << 31) | (t[ 1] >> 1);
// t[ 2] = (t[ 3] << 31) | (t[ 2] >> 1);
// t[ 3] = (t[ 4] << 31) | (t[ 3] >> 1);
// t[ 4] = (t[ 5] << 31) | (t[ 4] >> 1);
// t[ 5] = (t[ 6] << 31) | (t[ 5] >> 1);
// t[ 6] = (t[ 7] << 31) | (t[ 6] >> 1);
// t[ 7] = (t[ 8] << 31) | (t[ 7] >> 1);
// t[ 8] = (t[ 9] << 31) | (t[ 8] >> 1);
// t[ 9] = (t[ 10] << 31) | (t[ 9] >> 1);
// t[ 10] = (t[ 11] << 31) | (t[ 10] >> 1);
// t[ 11] = (t[ 12] << 31) | (t[ 11] >> 1);
// t[ 12] = (t[ 13] << 31) | (t[ 12] >> 1);
// t[ 13] = (t[ 14] << 31) | (t[ 13] >> 1);
// t[ 14] = (t[ 15] << 31) | (t[ 14] >> 1);
// t[ 15] = (t[ 16] << 31) | (t[ 15] >> 1);
// t[ 16] = (t[ 17] << 31) | (t[ 16] >> 1);
// t[ 17] = (t[ 18] << 31) | (t[ 17] >> 1);
// t[ 18] = (t[ 19] << 31) | (t[ 18] >> 1);
// t[ 19] = (t[ 20] << 31) | (t[ 19] >> 1);
// t[ 20] = (t[ 21] << 31) | (t[ 20] >> 1);
// t[ 21] = (t[ 22] << 31) | (t[ 21] >> 1);
// t[ 22] = (t[ 23] << 31) | (t[ 22] >> 1);
// t[ 23] = (t[ 24] << 31) | (t[ 23] >> 1);
// t[ 24] = (t[ 25] << 31) | (t[ 24] >> 1);
// t[ 25] = (t[ 26] << 31) | (t[ 25] >> 1);
// t[ 26] = (t[ 27] << 31) | (t[ 26] >> 1);
// t[ 27] = (t[ 28] << 31) | (t[ 27] >> 1);
// t[ 28] = (t[ 29] << 31) | (t[ 28] >> 1);
// t[ 29] = (t[ 30] << 31) | (t[ 29] >> 1);
// t[ 30] = (t[ 31] << 31) | (t[ 30] >> 1);
// t[ 31] = (t[ 32] << 31) | (t[ 31] >> 1);
// t[ 32] = (t[ 33] << 31) | (t[ 32] >> 1);
// t[ 33] = (t[ 34] << 31) | (t[ 33] >> 1);
// t[ 34] = (t[ 35] << 31) | (t[ 34] >> 1);
// t[ 35] = (t[ 36] << 31) | (t[ 35] >> 1);
// t[ 36] = (t[ 37] << 31) | (t[ 36] >> 1);
// t[ 37] = (t[ 38] << 31) | (t[ 37] >> 1);
// t[ 38] = (t[ 39] << 31) | (t[ 38] >> 1);
// t[ 39] = (t[ 40] << 31) | (t[ 39] >> 1);
// t[ 40] = (t[ 41] << 31) | (t[ 40] >> 1);
// t[ 41] = (t[ 42] << 31) | (t[ 41] >> 1);
// t[ 42] = (t[ 43] << 31) | (t[ 42] >> 1);
// t[ 43] = (t[ 44] << 31) | (t[ 43] >> 1);
// t[ 44] = (t[ 45] << 31) | (t[ 44] >> 1);
// t[ 45] = (t[ 46] << 31) | (t[ 45] >> 1);
// t[ 46] = (t[ 47] << 31) | (t[ 46] >> 1);
// t[ 47] = (t[ 48] << 31) | (t[ 47] >> 1);
// t[ 48] = (t[ 49] << 31) | (t[ 48] >> 1);
// t[ 49] = (t[ 50] << 31) | (t[ 49] >> 1);
// t[ 50] = (t[ 51] << 31) | (t[ 50] >> 1);
// t[ 51] = (t[ 52] << 31) | (t[ 51] >> 1);
// t[ 52] = (t[ 53] << 31) | (t[ 52] >> 1);
// t[ 53] = (t[ 54] << 31) | (t[ 53] >> 1);
// t[ 54] = (t[ 55] << 31) | (t[ 54] >> 1);
// t[ 55] = (t[ 56] << 31) | (t[ 55] >> 1);
// t[ 56] = (t[ 57] << 31) | (t[ 56] >> 1);
// t[ 57] = (t[ 58] << 31) | (t[ 57] >> 1);
// t[ 58] = (t[ 59] << 31) | (t[ 58] >> 1);
// t[ 59] = (t[ 60] << 31) | (t[ 59] >> 1);
// t[ 60] = (t[ 61] << 31) | (t[ 60] >> 1);
// t[ 61] = (t[ 62] << 31) | (t[ 61] >> 1);
// t[ 62] = (t[ 63] << 31) | (t[ 62] >> 1);
// t[ 63] = (t[ 64] << 31) | (t[ 63] >> 1);
// t[ 64] = (t[ 64] >> 1);
//
// ...
// }
// we use this optimization (we know "r" in advance, hard-coded/fixed)
for (u32 i = 0; i < 2049; i++)
{
if ((u[0] & 1) == 0)
{
// u >>= 1:
// for (u32 i = 0; i < 63; i++) u[i] = (u[i + 1] << 31) | (u[i] >> 1);
// u[63] >>= 1;
u[ 0] = (u[ 1] << 31) | (u[ 0] >> 1);
u[ 1] = (u[ 2] << 31) | (u[ 1] >> 1);
u[ 2] = (u[ 3] << 31) | (u[ 2] >> 1);
u[ 3] = (u[ 4] << 31) | (u[ 3] >> 1);
u[ 4] = (u[ 5] << 31) | (u[ 4] >> 1);
u[ 5] = (u[ 6] << 31) | (u[ 5] >> 1);
u[ 6] = (u[ 7] << 31) | (u[ 6] >> 1);
u[ 7] = (u[ 8] << 31) | (u[ 7] >> 1);
u[ 8] = (u[ 9] << 31) | (u[ 8] >> 1);
u[ 9] = (u[ 10] << 31) | (u[ 9] >> 1);
u[ 10] = (u[ 11] << 31) | (u[ 10] >> 1);
u[ 11] = (u[ 12] << 31) | (u[ 11] >> 1);
u[ 12] = (u[ 13] << 31) | (u[ 12] >> 1);
u[ 13] = (u[ 14] << 31) | (u[ 13] >> 1);
u[ 14] = (u[ 15] << 31) | (u[ 14] >> 1);
u[ 15] = (u[ 16] << 31) | (u[ 15] >> 1);
u[ 16] = (u[ 17] << 31) | (u[ 16] >> 1);
u[ 17] = (u[ 18] << 31) | (u[ 17] >> 1);
u[ 18] = (u[ 19] << 31) | (u[ 18] >> 1);
u[ 19] = (u[ 20] << 31) | (u[ 19] >> 1);
u[ 20] = (u[ 21] << 31) | (u[ 20] >> 1);
u[ 21] = (u[ 22] << 31) | (u[ 21] >> 1);
u[ 22] = (u[ 23] << 31) | (u[ 22] >> 1);
u[ 23] = (u[ 24] << 31) | (u[ 23] >> 1);
u[ 24] = (u[ 25] << 31) | (u[ 24] >> 1);
u[ 25] = (u[ 26] << 31) | (u[ 25] >> 1);
u[ 26] = (u[ 27] << 31) | (u[ 26] >> 1);
u[ 27] = (u[ 28] << 31) | (u[ 27] >> 1);
u[ 28] = (u[ 29] << 31) | (u[ 28] >> 1);
u[ 29] = (u[ 30] << 31) | (u[ 29] >> 1);
u[ 30] = (u[ 31] << 31) | (u[ 30] >> 1);
u[ 31] = (u[ 32] << 31) | (u[ 31] >> 1);
u[ 32] = (u[ 33] << 31) | (u[ 32] >> 1);
u[ 33] = (u[ 34] << 31) | (u[ 33] >> 1);
u[ 34] = (u[ 35] << 31) | (u[ 34] >> 1);
u[ 35] = (u[ 36] << 31) | (u[ 35] >> 1);
u[ 36] = (u[ 37] << 31) | (u[ 36] >> 1);
u[ 37] = (u[ 38] << 31) | (u[ 37] >> 1);
u[ 38] = (u[ 39] << 31) | (u[ 38] >> 1);
u[ 39] = (u[ 40] << 31) | (u[ 39] >> 1);
u[ 40] = (u[ 41] << 31) | (u[ 40] >> 1);
u[ 41] = (u[ 42] << 31) | (u[ 41] >> 1);
u[ 42] = (u[ 43] << 31) | (u[ 42] >> 1);
u[ 43] = (u[ 44] << 31) | (u[ 43] >> 1);
u[ 44] = (u[ 45] << 31) | (u[ 44] >> 1);
u[ 45] = (u[ 46] << 31) | (u[ 45] >> 1);
u[ 46] = (u[ 47] << 31) | (u[ 46] >> 1);
u[ 47] = (u[ 48] << 31) | (u[ 47] >> 1);
u[ 48] = (u[ 49] << 31) | (u[ 48] >> 1);
u[ 49] = (u[ 50] << 31) | (u[ 49] >> 1);
u[ 50] = (u[ 51] << 31) | (u[ 50] >> 1);
u[ 51] = (u[ 52] << 31) | (u[ 51] >> 1);
u[ 52] = (u[ 53] << 31) | (u[ 52] >> 1);
u[ 53] = (u[ 54] << 31) | (u[ 53] >> 1);
u[ 54] = (u[ 55] << 31) | (u[ 54] >> 1);
u[ 55] = (u[ 56] << 31) | (u[ 55] >> 1);
u[ 56] = (u[ 57] << 31) | (u[ 56] >> 1);
u[ 57] = (u[ 58] << 31) | (u[ 57] >> 1);
u[ 58] = (u[ 59] << 31) | (u[ 58] >> 1);
u[ 59] = (u[ 60] << 31) | (u[ 59] >> 1);
u[ 60] = (u[ 61] << 31) | (u[ 60] >> 1);
u[ 61] = (u[ 62] << 31) | (u[ 61] >> 1);
u[ 62] = (u[ 63] << 31) | (u[ 62] >> 1);
u[ 63] = (u[ 63] >> 1);
// v >>= 1
// for (u32 i = 0; i < 64; i++) v[i] = (v[i + 1] << 31) | (v[i] >> 1);
// v[64] >>= 1;
v[ 0] = (v[ 1] << 31) | (v[ 0] >> 1);
v[ 1] = (v[ 2] << 31) | (v[ 1] >> 1);
v[ 2] = (v[ 3] << 31) | (v[ 2] >> 1);
v[ 3] = (v[ 4] << 31) | (v[ 3] >> 1);
v[ 4] = (v[ 5] << 31) | (v[ 4] >> 1);
v[ 5] = (v[ 6] << 31) | (v[ 5] >> 1);
v[ 6] = (v[ 7] << 31) | (v[ 6] >> 1);
v[ 7] = (v[ 8] << 31) | (v[ 7] >> 1);
v[ 8] = (v[ 9] << 31) | (v[ 8] >> 1);
v[ 9] = (v[ 10] << 31) | (v[ 9] >> 1);
v[ 10] = (v[ 11] << 31) | (v[ 10] >> 1);
v[ 11] = (v[ 12] << 31) | (v[ 11] >> 1);
v[ 12] = (v[ 13] << 31) | (v[ 12] >> 1);
v[ 13] = (v[ 14] << 31) | (v[ 13] >> 1);
v[ 14] = (v[ 15] << 31) | (v[ 14] >> 1);
v[ 15] = (v[ 16] << 31) | (v[ 15] >> 1);
v[ 16] = (v[ 17] << 31) | (v[ 16] >> 1);
v[ 17] = (v[ 18] << 31) | (v[ 17] >> 1);
v[ 18] = (v[ 19] << 31) | (v[ 18] >> 1);
v[ 19] = (v[ 20] << 31) | (v[ 19] >> 1);
v[ 20] = (v[ 21] << 31) | (v[ 20] >> 1);
v[ 21] = (v[ 22] << 31) | (v[ 21] >> 1);
v[ 22] = (v[ 23] << 31) | (v[ 22] >> 1);
v[ 23] = (v[ 24] << 31) | (v[ 23] >> 1);
v[ 24] = (v[ 25] << 31) | (v[ 24] >> 1);
v[ 25] = (v[ 26] << 31) | (v[ 25] >> 1);
v[ 26] = (v[ 27] << 31) | (v[ 26] >> 1);
v[ 27] = (v[ 28] << 31) | (v[ 27] >> 1);
v[ 28] = (v[ 29] << 31) | (v[ 28] >> 1);
v[ 29] = (v[ 30] << 31) | (v[ 29] >> 1);
v[ 30] = (v[ 31] << 31) | (v[ 30] >> 1);
v[ 31] = (v[ 32] << 31) | (v[ 31] >> 1);
v[ 32] = (v[ 33] << 31) | (v[ 32] >> 1);
v[ 33] = (v[ 34] << 31) | (v[ 33] >> 1);
v[ 34] = (v[ 35] << 31) | (v[ 34] >> 1);
v[ 35] = (v[ 36] << 31) | (v[ 35] >> 1);
v[ 36] = (v[ 37] << 31) | (v[ 36] >> 1);
v[ 37] = (v[ 38] << 31) | (v[ 37] >> 1);
v[ 38] = (v[ 39] << 31) | (v[ 38] >> 1);
v[ 39] = (v[ 40] << 31) | (v[ 39] >> 1);
v[ 40] = (v[ 41] << 31) | (v[ 40] >> 1);
v[ 41] = (v[ 42] << 31) | (v[ 41] >> 1);
v[ 42] = (v[ 43] << 31) | (v[ 42] >> 1);
v[ 43] = (v[ 44] << 31) | (v[ 43] >> 1);
v[ 44] = (v[ 45] << 31) | (v[ 44] >> 1);
v[ 45] = (v[ 46] << 31) | (v[ 45] >> 1);
v[ 46] = (v[ 47] << 31) | (v[ 46] >> 1);
v[ 47] = (v[ 48] << 31) | (v[ 47] >> 1);
v[ 48] = (v[ 49] << 31) | (v[ 48] >> 1);
v[ 49] = (v[ 50] << 31) | (v[ 49] >> 1);
v[ 50] = (v[ 51] << 31) | (v[ 50] >> 1);
v[ 51] = (v[ 52] << 31) | (v[ 51] >> 1);
v[ 52] = (v[ 53] << 31) | (v[ 52] >> 1);
v[ 53] = (v[ 54] << 31) | (v[ 53] >> 1);
v[ 54] = (v[ 55] << 31) | (v[ 54] >> 1);
v[ 55] = (v[ 56] << 31) | (v[ 55] >> 1);
v[ 56] = (v[ 57] << 31) | (v[ 56] >> 1);
v[ 57] = (v[ 58] << 31) | (v[ 57] >> 1);
v[ 58] = (v[ 59] << 31) | (v[ 58] >> 1);
v[ 59] = (v[ 60] << 31) | (v[ 59] >> 1);
v[ 60] = (v[ 61] << 31) | (v[ 60] >> 1);
v[ 61] = (v[ 62] << 31) | (v[ 61] >> 1);
v[ 62] = (v[ 63] << 31) | (v[ 62] >> 1);
v[ 63] = (v[ 64] << 31) | (v[ 63] >> 1);
v[ 64] = (v[ 64] >> 1);
}
else
{
// s = u ^ m
u32 s[64];
// for (u32 i = 0; i < 64; i++) s[i] = u[i] ^ m[i];
s[ 0] = u[ 0] ^ m[ 0]; s[ 1] = u[ 1] ^ m[ 1];
s[ 2] = u[ 2] ^ m[ 2]; s[ 3] = u[ 3] ^ m[ 3];
s[ 4] = u[ 4] ^ m[ 4]; s[ 5] = u[ 5] ^ m[ 5];
s[ 6] = u[ 6] ^ m[ 6]; s[ 7] = u[ 7] ^ m[ 7];
s[ 8] = u[ 8] ^ m[ 8]; s[ 9] = u[ 9] ^ m[ 9];
s[10] = u[10] ^ m[10]; s[11] = u[11] ^ m[11];
s[12] = u[12] ^ m[12]; s[13] = u[13] ^ m[13];
s[14] = u[14] ^ m[14]; s[15] = u[15] ^ m[15];
s[16] = u[16] ^ m[16]; s[17] = u[17] ^ m[17];
s[18] = u[18] ^ m[18]; s[19] = u[19] ^ m[19];
s[20] = u[20] ^ m[20]; s[21] = u[21] ^ m[21];
s[22] = u[22] ^ m[22]; s[23] = u[23] ^ m[23];
s[24] = u[24] ^ m[24]; s[25] = u[25] ^ m[25];
s[26] = u[26] ^ m[26]; s[27] = u[27] ^ m[27];
s[28] = u[28] ^ m[28]; s[29] = u[29] ^ m[29];
s[30] = u[30] ^ m[30]; s[31] = u[31] ^ m[31];
s[32] = u[32] ^ m[32]; s[33] = u[33] ^ m[33];
s[34] = u[34] ^ m[34]; s[35] = u[35] ^ m[35];
s[36] = u[36] ^ m[36]; s[37] = u[37] ^ m[37];
s[38] = u[38] ^ m[38]; s[39] = u[39] ^ m[39];
s[40] = u[40] ^ m[40]; s[41] = u[41] ^ m[41];
s[42] = u[42] ^ m[42]; s[43] = u[43] ^ m[43];
s[44] = u[44] ^ m[44]; s[45] = u[45] ^ m[45];
s[46] = u[46] ^ m[46]; s[47] = u[47] ^ m[47];
s[48] = u[48] ^ m[48]; s[49] = u[49] ^ m[49];
s[50] = u[50] ^ m[50]; s[51] = u[51] ^ m[51];
s[52] = u[52] ^ m[52]; s[53] = u[53] ^ m[53];
s[54] = u[54] ^ m[54]; s[55] = u[55] ^ m[55];
s[56] = u[56] ^ m[56]; s[57] = u[57] ^ m[57];
s[58] = u[58] ^ m[58]; s[59] = u[59] ^ m[59];
s[60] = u[60] ^ m[60]; s[61] = u[61] ^ m[61];
s[62] = u[62] ^ m[62]; s[63] = u[63] ^ m[63];
// s >>= 1
// for (u32 i = 0; i < 63; i++) s[i] = (s[i + 1] << 31) | (s[i] >> 1);
// s[63] >>= 1;
s[ 0] = (s[ 1] << 31) | (s[ 0] >> 1);
s[ 1] = (s[ 2] << 31) | (s[ 1] >> 1);
s[ 2] = (s[ 3] << 31) | (s[ 2] >> 1);
s[ 3] = (s[ 4] << 31) | (s[ 3] >> 1);
s[ 4] = (s[ 5] << 31) | (s[ 4] >> 1);
s[ 5] = (s[ 6] << 31) | (s[ 5] >> 1);
s[ 6] = (s[ 7] << 31) | (s[ 6] >> 1);
s[ 7] = (s[ 8] << 31) | (s[ 7] >> 1);
s[ 8] = (s[ 9] << 31) | (s[ 8] >> 1);
s[ 9] = (s[ 10] << 31) | (s[ 9] >> 1);
s[ 10] = (s[ 11] << 31) | (s[ 10] >> 1);
s[ 11] = (s[ 12] << 31) | (s[ 11] >> 1);
s[ 12] = (s[ 13] << 31) | (s[ 12] >> 1);
s[ 13] = (s[ 14] << 31) | (s[ 13] >> 1);
s[ 14] = (s[ 15] << 31) | (s[ 14] >> 1);
s[ 15] = (s[ 16] << 31) | (s[ 15] >> 1);
s[ 16] = (s[ 17] << 31) | (s[ 16] >> 1);
s[ 17] = (s[ 18] << 31) | (s[ 17] >> 1);
s[ 18] = (s[ 19] << 31) | (s[ 18] >> 1);
s[ 19] = (s[ 20] << 31) | (s[ 19] >> 1);
s[ 20] = (s[ 21] << 31) | (s[ 20] >> 1);
s[ 21] = (s[ 22] << 31) | (s[ 21] >> 1);
s[ 22] = (s[ 23] << 31) | (s[ 22] >> 1);
s[ 23] = (s[ 24] << 31) | (s[ 23] >> 1);
s[ 24] = (s[ 25] << 31) | (s[ 24] >> 1);
s[ 25] = (s[ 26] << 31) | (s[ 25] >> 1);
s[ 26] = (s[ 27] << 31) | (s[ 26] >> 1);
s[ 27] = (s[ 28] << 31) | (s[ 27] >> 1);
s[ 28] = (s[ 29] << 31) | (s[ 28] >> 1);
s[ 29] = (s[ 30] << 31) | (s[ 29] >> 1);
s[ 30] = (s[ 31] << 31) | (s[ 30] >> 1);
s[ 31] = (s[ 32] << 31) | (s[ 31] >> 1);
s[ 32] = (s[ 33] << 31) | (s[ 32] >> 1);
s[ 33] = (s[ 34] << 31) | (s[ 33] >> 1);
s[ 34] = (s[ 35] << 31) | (s[ 34] >> 1);
s[ 35] = (s[ 36] << 31) | (s[ 35] >> 1);
s[ 36] = (s[ 37] << 31) | (s[ 36] >> 1);
s[ 37] = (s[ 38] << 31) | (s[ 37] >> 1);
s[ 38] = (s[ 39] << 31) | (s[ 38] >> 1);
s[ 39] = (s[ 40] << 31) | (s[ 39] >> 1);
s[ 40] = (s[ 41] << 31) | (s[ 40] >> 1);
s[ 41] = (s[ 42] << 31) | (s[ 41] >> 1);
s[ 42] = (s[ 43] << 31) | (s[ 42] >> 1);
s[ 43] = (s[ 44] << 31) | (s[ 43] >> 1);
s[ 44] = (s[ 45] << 31) | (s[ 44] >> 1);
s[ 45] = (s[ 46] << 31) | (s[ 45] >> 1);
s[ 46] = (s[ 47] << 31) | (s[ 46] >> 1);
s[ 47] = (s[ 48] << 31) | (s[ 47] >> 1);
s[ 48] = (s[ 49] << 31) | (s[ 48] >> 1);
s[ 49] = (s[ 50] << 31) | (s[ 49] >> 1);
s[ 50] = (s[ 51] << 31) | (s[ 50] >> 1);
s[ 51] = (s[ 52] << 31) | (s[ 51] >> 1);
s[ 52] = (s[ 53] << 31) | (s[ 52] >> 1);
s[ 53] = (s[ 54] << 31) | (s[ 53] >> 1);
s[ 54] = (s[ 55] << 31) | (s[ 54] >> 1);
s[ 55] = (s[ 56] << 31) | (s[ 55] >> 1);
s[ 56] = (s[ 57] << 31) | (s[ 56] >> 1);
s[ 57] = (s[ 58] << 31) | (s[ 57] >> 1);
s[ 58] = (s[ 59] << 31) | (s[ 58] >> 1);
s[ 59] = (s[ 60] << 31) | (s[ 59] >> 1);
s[ 60] = (s[ 61] << 31) | (s[ 60] >> 1);
s[ 61] = (s[ 62] << 31) | (s[ 61] >> 1);
s[ 62] = (s[ 63] << 31) | (s[ 62] >> 1);
s[ 63] = (s[ 63] >> 1);
// u &= m
// for (u32 i = 0; i < 64; i++) u[i] &= m[i];
u[ 0] &= m[ 0]; u[ 1] &= m[ 1]; u[ 2] &= m[ 2]; u[ 3] &= m[ 3];
u[ 4] &= m[ 4]; u[ 5] &= m[ 5]; u[ 6] &= m[ 6]; u[ 7] &= m[ 7];
u[ 8] &= m[ 8]; u[ 9] &= m[ 9]; u[10] &= m[10]; u[11] &= m[11];
u[12] &= m[12]; u[13] &= m[13]; u[14] &= m[14]; u[15] &= m[15];
u[16] &= m[16]; u[17] &= m[17]; u[18] &= m[18]; u[19] &= m[19];
u[20] &= m[20]; u[21] &= m[21]; u[22] &= m[22]; u[23] &= m[23];
u[24] &= m[24]; u[25] &= m[25]; u[26] &= m[26]; u[27] &= m[27];
u[28] &= m[28]; u[29] &= m[29]; u[30] &= m[30]; u[31] &= m[31];
u[32] &= m[32]; u[33] &= m[33]; u[34] &= m[34]; u[35] &= m[35];
u[36] &= m[36]; u[37] &= m[37]; u[38] &= m[38]; u[39] &= m[39];
u[40] &= m[40]; u[41] &= m[41]; u[42] &= m[42]; u[43] &= m[43];
u[44] &= m[44]; u[45] &= m[45]; u[46] &= m[46]; u[47] &= m[47];
u[48] &= m[48]; u[49] &= m[49]; u[50] &= m[50]; u[51] &= m[51];
u[52] &= m[52]; u[53] &= m[53]; u[54] &= m[54]; u[55] &= m[55];
u[56] &= m[56]; u[57] &= m[57]; u[58] &= m[58]; u[59] &= m[59];
u[60] &= m[60]; u[61] &= m[61]; u[62] &= m[62]; u[63] &= m[63];
// t = u (to have the original u)
u32 t[64]; // 65 would be needed for "r" (but we know "r" in advance)
// for (u32 i = 0; i < 64; i++) t[i] = u[i];
t[ 0] = u[ 0]; t[ 1] = u[ 1]; t[ 2] = u[ 2]; t[ 3] = u[ 3];
t[ 4] = u[ 4]; t[ 5] = u[ 5]; t[ 6] = u[ 6]; t[ 7] = u[ 7];
t[ 8] = u[ 8]; t[ 9] = u[ 9]; t[10] = u[10]; t[11] = u[11];
t[12] = u[12]; t[13] = u[13]; t[14] = u[14]; t[15] = u[15];
t[16] = u[16]; t[17] = u[17]; t[18] = u[18]; t[19] = u[19];
t[20] = u[20]; t[21] = u[21]; t[22] = u[22]; t[23] = u[23];
t[24] = u[24]; t[25] = u[25]; t[26] = u[26]; t[27] = u[27];
t[28] = u[28]; t[29] = u[29]; t[30] = u[30]; t[31] = u[31];
t[32] = u[32]; t[33] = u[33]; t[34] = u[34]; t[35] = u[35];
t[36] = u[36]; t[37] = u[37]; t[38] = u[38]; t[39] = u[39];
t[40] = u[40]; t[41] = u[41]; t[42] = u[42]; t[43] = u[43];
t[44] = u[44]; t[45] = u[45]; t[46] = u[46]; t[47] = u[47];
t[48] = u[48]; t[49] = u[49]; t[50] = u[50]; t[51] = u[51];
t[52] = u[52]; t[53] = u[53]; t[54] = u[54]; t[55] = u[55];
t[56] = u[56]; t[57] = u[57]; t[58] = u[58]; t[59] = u[59];
t[60] = u[60]; t[61] = u[61]; t[62] = u[62]; t[63] = u[63];
// u += s
// for (u32 i = 0; i < 64; i++) u[i] += s[i];
u[ 0] += s[ 0]; u[ 1] += s[ 1]; u[ 2] += s[ 2]; u[ 3] += s[ 3];
u[ 4] += s[ 4]; u[ 5] += s[ 5]; u[ 6] += s[ 6]; u[ 7] += s[ 7];
u[ 8] += s[ 8]; u[ 9] += s[ 9]; u[10] += s[10]; u[11] += s[11];
u[12] += s[12]; u[13] += s[13]; u[14] += s[14]; u[15] += s[15];
u[16] += s[16]; u[17] += s[17]; u[18] += s[18]; u[19] += s[19];
u[20] += s[20]; u[21] += s[21]; u[22] += s[22]; u[23] += s[23];
u[24] += s[24]; u[25] += s[25]; u[26] += s[26]; u[27] += s[27];
u[28] += s[28]; u[29] += s[29]; u[30] += s[30]; u[31] += s[31];
u[32] += s[32]; u[33] += s[33]; u[34] += s[34]; u[35] += s[35];
u[36] += s[36]; u[37] += s[37]; u[38] += s[38]; u[39] += s[39];
u[40] += s[40]; u[41] += s[41]; u[42] += s[42]; u[43] += s[43];
u[44] += s[44]; u[45] += s[45]; u[46] += s[46]; u[47] += s[47];
u[48] += s[48]; u[49] += s[49]; u[50] += s[50]; u[51] += s[51];
u[52] += s[52]; u[53] += s[53]; u[54] += s[54]; u[55] += s[55];
u[56] += s[56]; u[57] += s[57]; u[58] += s[58]; u[59] += s[59];
u[60] += s[60]; u[61] += s[61]; u[62] += s[62]; u[63] += s[63];
// take care of the carry for the addition above (i.e check for "overflows")
// for (u32 i = 0; i < 63; i++) if (u[i] < t[i]) u[i + 1]++;
// if (u[ 0] < t[ 0]) u[ 1]++;
// if (u[ 1] < t[ 1]) u[ 2]++;
// if (u[ 2] < t[ 2]) u[ 3]++;
// if (u[ 3] < t[ 3]) u[ 4]++;
// if (u[ 4] < t[ 4]) u[ 5]++;
// if (u[ 5] < t[ 5]) u[ 6]++;
// if (u[ 6] < t[ 6]) u[ 7]++;
// if (u[ 7] < t[ 7]) u[ 8]++;
// if (u[ 8] < t[ 8]) u[ 9]++;
// if (u[ 9] < t[ 9]) u[10]++;
// if (u[10] < t[10]) u[11]++;
// if (u[11] < t[11]) u[12]++;
// if (u[12] < t[12]) u[13]++;
// if (u[13] < t[13]) u[14]++;
// if (u[14] < t[14]) u[15]++;
// if (u[15] < t[15]) u[16]++;
// if (u[16] < t[16]) u[17]++;
// if (u[17] < t[17]) u[18]++;
// if (u[18] < t[18]) u[19]++;
// if (u[19] < t[19]) u[20]++;
// if (u[20] < t[20]) u[21]++;
// if (u[21] < t[21]) u[22]++;
// if (u[22] < t[22]) u[23]++;
// if (u[23] < t[23]) u[24]++;
// if (u[24] < t[24]) u[25]++;
// if (u[25] < t[25]) u[26]++;
// if (u[26] < t[26]) u[27]++;
// if (u[27] < t[27]) u[28]++;
// if (u[28] < t[28]) u[29]++;
// if (u[29] < t[29]) u[30]++;
// if (u[30] < t[30]) u[31]++;
// if (u[31] < t[31]) u[32]++;
// if (u[32] < t[32]) u[33]++;
// if (u[33] < t[33]) u[34]++;
// if (u[34] < t[34]) u[35]++;
// if (u[35] < t[35]) u[36]++;
// if (u[36] < t[36]) u[37]++;
// if (u[37] < t[37]) u[38]++;
// if (u[38] < t[38]) u[39]++;
// if (u[39] < t[39]) u[40]++;
// if (u[40] < t[40]) u[41]++;
// if (u[41] < t[41]) u[42]++;
// if (u[42] < t[42]) u[43]++;
// if (u[43] < t[43]) u[44]++;
// if (u[44] < t[44]) u[45]++;
// if (u[45] < t[45]) u[46]++;
// if (u[46] < t[46]) u[47]++;
// if (u[47] < t[47]) u[48]++;
// if (u[48] < t[48]) u[49]++;
// if (u[49] < t[49]) u[50]++;
// if (u[50] < t[50]) u[51]++;
// if (u[51] < t[51]) u[52]++;
// if (u[52] < t[52]) u[53]++;
// if (u[53] < t[53]) u[54]++;
// if (u[54] < t[54]) u[55]++;
// if (u[55] < t[55]) u[56]++;
// if (u[56] < t[56]) u[57]++;
// if (u[57] < t[57]) u[58]++;
// if (u[58] < t[58]) u[59]++;
// if (u[59] < t[59]) u[60]++;
// if (u[60] < t[60]) u[61]++;
// if (u[61] < t[61]) u[62]++;
// if (u[62] < t[62]) u[63]++;
// for (u32 i = 1; i < 64; i++) u[i] += u[i - 1] < t[i - 1];
u[ 1] += u[ 0] < t[ 0];
u[ 2] += u[ 1] < t[ 1];
u[ 3] += u[ 2] < t[ 2];
u[ 4] += u[ 3] < t[ 3];
u[ 5] += u[ 4] < t[ 4];
u[ 6] += u[ 5] < t[ 5];
u[ 7] += u[ 6] < t[ 6];
u[ 8] += u[ 7] < t[ 7];
u[ 9] += u[ 8] < t[ 8];
u[10] += u[ 9] < t[ 9];
u[11] += u[10] < t[10];
u[12] += u[11] < t[11];
u[13] += u[12] < t[12];
u[14] += u[13] < t[13];
u[15] += u[14] < t[14];
u[16] += u[15] < t[15];
u[17] += u[16] < t[16];
u[18] += u[17] < t[17];
u[19] += u[18] < t[18];
u[20] += u[19] < t[19];
u[21] += u[20] < t[20];
u[22] += u[21] < t[21];
u[23] += u[22] < t[22];
u[24] += u[23] < t[23];
u[25] += u[24] < t[24];
u[26] += u[25] < t[25];
u[27] += u[26] < t[26];
u[28] += u[27] < t[27];
u[29] += u[28] < t[28];
u[30] += u[29] < t[29];
u[31] += u[30] < t[30];
u[32] += u[31] < t[31];
u[33] += u[32] < t[32];
u[34] += u[33] < t[33];
u[35] += u[34] < t[34];
u[36] += u[35] < t[35];
u[37] += u[36] < t[36];
u[38] += u[37] < t[37];
u[39] += u[38] < t[38];
u[40] += u[39] < t[39];
u[41] += u[40] < t[40];
u[42] += u[41] < t[41];
u[43] += u[42] < t[42];
u[44] += u[43] < t[43];
u[45] += u[44] < t[44];
u[46] += u[45] < t[45];
u[47] += u[46] < t[46];
u[48] += u[47] < t[47];
u[49] += u[48] < t[48];
u[50] += u[49] < t[49];
u[51] += u[50] < t[50];
u[52] += u[51] < t[51];
u[53] += u[52] < t[52];
u[54] += u[53] < t[53];
u[55] += u[54] < t[54];
u[56] += u[55] < t[55];
u[57] += u[56] < t[56];
u[58] += u[57] < t[57];
u[59] += u[58] < t[58];
u[60] += u[59] < t[59];
u[61] += u[60] < t[60];
u[62] += u[61] < t[61];
u[63] += u[62] < t[62];
// v >>= 1
// for (u32 i = 0; i < 64; i++) v[i] = (v[i + 1] << 31) | (v[i] >> 1);
// v[64] >>= 1;
v[ 0] = (v[ 1] << 31) | (v[ 0] >> 1);
v[ 1] = (v[ 2] << 31) | (v[ 1] >> 1);
v[ 2] = (v[ 3] << 31) | (v[ 2] >> 1);
v[ 3] = (v[ 4] << 31) | (v[ 3] >> 1);
v[ 4] = (v[ 5] << 31) | (v[ 4] >> 1);
v[ 5] = (v[ 6] << 31) | (v[ 5] >> 1);
v[ 6] = (v[ 7] << 31) | (v[ 6] >> 1);
v[ 7] = (v[ 8] << 31) | (v[ 7] >> 1);
v[ 8] = (v[ 9] << 31) | (v[ 8] >> 1);
v[ 9] = (v[ 10] << 31) | (v[ 9] >> 1);
v[ 10] = (v[ 11] << 31) | (v[ 10] >> 1);
v[ 11] = (v[ 12] << 31) | (v[ 11] >> 1);
v[ 12] = (v[ 13] << 31) | (v[ 12] >> 1);
v[ 13] = (v[ 14] << 31) | (v[ 13] >> 1);
v[ 14] = (v[ 15] << 31) | (v[ 14] >> 1);
v[ 15] = (v[ 16] << 31) | (v[ 15] >> 1);
v[ 16] = (v[ 17] << 31) | (v[ 16] >> 1);
v[ 17] = (v[ 18] << 31) | (v[ 17] >> 1);
v[ 18] = (v[ 19] << 31) | (v[ 18] >> 1);
v[ 19] = (v[ 20] << 31) | (v[ 19] >> 1);
v[ 20] = (v[ 21] << 31) | (v[ 20] >> 1);
v[ 21] = (v[ 22] << 31) | (v[ 21] >> 1);
v[ 22] = (v[ 23] << 31) | (v[ 22] >> 1);
v[ 23] = (v[ 24] << 31) | (v[ 23] >> 1);
v[ 24] = (v[ 25] << 31) | (v[ 24] >> 1);
v[ 25] = (v[ 26] << 31) | (v[ 25] >> 1);
v[ 26] = (v[ 27] << 31) | (v[ 26] >> 1);
v[ 27] = (v[ 28] << 31) | (v[ 27] >> 1);
v[ 28] = (v[ 29] << 31) | (v[ 28] >> 1);
v[ 29] = (v[ 30] << 31) | (v[ 29] >> 1);
v[ 30] = (v[ 31] << 31) | (v[ 30] >> 1);
v[ 31] = (v[ 32] << 31) | (v[ 31] >> 1);
v[ 32] = (v[ 33] << 31) | (v[ 32] >> 1);
v[ 33] = (v[ 34] << 31) | (v[ 33] >> 1);
v[ 34] = (v[ 35] << 31) | (v[ 34] >> 1);
v[ 35] = (v[ 36] << 31) | (v[ 35] >> 1);
v[ 36] = (v[ 37] << 31) | (v[ 36] >> 1);
v[ 37] = (v[ 38] << 31) | (v[ 37] >> 1);
v[ 38] = (v[ 39] << 31) | (v[ 38] >> 1);
v[ 39] = (v[ 40] << 31) | (v[ 39] >> 1);
v[ 40] = (v[ 41] << 31) | (v[ 40] >> 1);
v[ 41] = (v[ 42] << 31) | (v[ 41] >> 1);
v[ 42] = (v[ 43] << 31) | (v[ 42] >> 1);
v[ 43] = (v[ 44] << 31) | (v[ 43] >> 1);
v[ 44] = (v[ 45] << 31) | (v[ 44] >> 1);
v[ 45] = (v[ 46] << 31) | (v[ 45] >> 1);
v[ 46] = (v[ 47] << 31) | (v[ 46] >> 1);
v[ 47] = (v[ 48] << 31) | (v[ 47] >> 1);
v[ 48] = (v[ 49] << 31) | (v[ 48] >> 1);
v[ 49] = (v[ 50] << 31) | (v[ 49] >> 1);
v[ 50] = (v[ 51] << 31) | (v[ 50] >> 1);
v[ 51] = (v[ 52] << 31) | (v[ 51] >> 1);
v[ 52] = (v[ 53] << 31) | (v[ 52] >> 1);
v[ 53] = (v[ 54] << 31) | (v[ 53] >> 1);
v[ 54] = (v[ 55] << 31) | (v[ 54] >> 1);
v[ 55] = (v[ 56] << 31) | (v[ 55] >> 1);
v[ 56] = (v[ 57] << 31) | (v[ 56] >> 1);
v[ 57] = (v[ 58] << 31) | (v[ 57] >> 1);
v[ 58] = (v[ 59] << 31) | (v[ 58] >> 1);
v[ 59] = (v[ 60] << 31) | (v[ 59] >> 1);
v[ 60] = (v[ 61] << 31) | (v[ 60] >> 1);
v[ 61] = (v[ 62] << 31) | (v[ 61] >> 1);
v[ 62] = (v[ 63] << 31) | (v[ 62] >> 1);
v[ 63] = (v[ 64] << 31) | (v[ 63] >> 1);
v[ 64] = (v[ 64] >> 1);
// t = v
//
// t[ 0] = v[ 0]; t[ 1] = v[ 1]; t[ 2] = v[ 2]; t[ 3] = v[ 3];
// t[ 4] = v[ 4]; t[ 5] = v[ 5]; t[ 6] = v[ 6]; t[ 7] = v[ 7];
// t[ 8] = v[ 8]; t[ 9] = v[ 9]; t[10] = v[10]; t[11] = v[11];
// t[12] = v[12]; t[13] = v[13]; t[14] = v[14]; t[15] = v[15];
// t[16] = v[16]; t[17] = v[17]; t[18] = v[18]; t[19] = v[19];
// t[20] = v[20]; t[21] = v[21]; t[22] = v[22]; t[23] = v[23];
// t[24] = v[24]; t[25] = v[25]; t[26] = v[26]; t[27] = v[27];
// t[28] = v[28]; t[29] = v[29]; t[30] = v[30]; t[31] = v[31];
// t[32] = v[32]; t[33] = v[33]; t[34] = v[34]; t[35] = v[35];
// t[36] = v[36]; t[37] = v[37]; t[38] = v[38]; t[39] = v[39];
// t[40] = v[40]; t[41] = v[41]; t[42] = v[42]; t[43] = v[43];
// t[44] = v[44]; t[45] = v[45]; t[46] = v[46]; t[47] = v[47];
// t[48] = v[48]; t[49] = v[49]; t[50] = v[50]; t[51] = v[51];
// t[52] = v[52]; t[53] = v[53]; t[54] = v[54]; t[55] = v[55];
// t[56] = v[56]; t[57] = v[57]; t[58] = v[58]; t[59] = v[59];
// t[60] = v[60]; t[61] = v[61]; t[62] = v[62]; t[63] = v[63];
// t[60] = v[60]; t[61] = v[61]; t[62] = v[62]; t[63] = v[63];
// t[64] = v[64];
// v += r (only r[64] has the value "1")
// we can skip the sum with r[x], since most are set to 0
// v[ 0] += r[ 0]; v[ 1] += r[ 1]; v[ 2] += r[ 2]; v[ 3] += r[ 3];
// v[ 4] += r[ 4]; v[ 5] += r[ 5]; v[ 6] += r[ 6]; v[ 7] += r[ 7];
// v[ 8] += r[ 8]; v[ 9] += r[ 9]; v[10] += r[10]; v[11] += r[11];
// v[12] += r[12]; v[13] += r[13]; v[14] += r[14]; v[15] += r[15];
// v[16] += r[16]; v[17] += r[17]; v[18] += r[18]; v[19] += r[19];
// v[20] += r[20]; v[21] += r[21]; v[22] += r[22]; v[23] += r[23];
// v[24] += r[24]; v[25] += r[25]; v[26] += r[26]; v[27] += r[27];
// v[28] += r[28]; v[29] += r[29]; v[30] += r[30]; v[31] += r[31];
// v[32] += r[32]; v[33] += r[33]; v[34] += r[34]; v[35] += r[35];
// v[36] += r[36]; v[37] += r[37]; v[38] += r[38]; v[39] += r[39];
// v[40] += r[40]; v[41] += r[41]; v[42] += r[42]; v[43] += r[43];
// v[44] += r[44]; v[45] += r[45]; v[46] += r[46]; v[47] += r[47];
// v[48] += r[48]; v[49] += r[49]; v[50] += r[50]; v[51] += r[51];
// v[52] += r[52]; v[53] += r[53]; v[54] += r[54]; v[55] += r[55];
// v[56] += r[56]; v[57] += r[57]; v[58] += r[58]; v[59] += r[59];
// v[60] += r[60]; v[61] += r[61]; v[62] += r[62]; v[63] += r[63];
// v[64] += r[64];
v[64] += 1; // hard-coded "r" value (r[64])
// take care of the carry for the addition above (i.e check for "overflows")
// for (u32 i = 1; i < 65; i++) v[i] += v[i - 1] < t[i - 1];
// v[ 1] += v[ 0] < t[ 0];
// v[ 2] += v[ 1] < t[ 1];
// v[ 3] += v[ 2] < t[ 2];
// v[ 4] += v[ 3] < t[ 3];
// v[ 5] += v[ 4] < t[ 4];
// v[ 6] += v[ 5] < t[ 5];
// v[ 7] += v[ 6] < t[ 6];
// v[ 8] += v[ 7] < t[ 7];
// v[ 9] += v[ 8] < t[ 8];
// v[10] += v[ 9] < t[ 9];
// v[11] += v[10] < t[10];
// v[12] += v[11] < t[11];
// v[13] += v[12] < t[12];
// v[14] += v[13] < t[13];
// v[15] += v[14] < t[14];
// v[16] += v[15] < t[15];
// v[17] += v[16] < t[16];
// v[18] += v[17] < t[17];
// v[19] += v[18] < t[18];
// v[20] += v[19] < t[19];
// v[21] += v[20] < t[20];
// v[22] += v[21] < t[21];
// v[23] += v[22] < t[22];
// v[24] += v[23] < t[23];
// v[25] += v[24] < t[24];
// v[26] += v[25] < t[25];
// v[27] += v[26] < t[26];
// v[28] += v[27] < t[27];
// v[29] += v[28] < t[28];
// v[30] += v[29] < t[29];
// v[31] += v[30] < t[30];
// v[32] += v[31] < t[31];
// v[33] += v[32] < t[32];
// v[34] += v[33] < t[33];
// v[35] += v[34] < t[34];
// v[36] += v[35] < t[35];
// v[37] += v[36] < t[36];
// v[38] += v[37] < t[37];
// v[39] += v[38] < t[38];
// v[40] += v[39] < t[39];
// v[41] += v[40] < t[40];
// v[42] += v[41] < t[41];
// v[43] += v[42] < t[42];
// v[44] += v[43] < t[43];
// v[45] += v[44] < t[44];
// v[46] += v[45] < t[45];
// v[47] += v[46] < t[46];
// v[48] += v[47] < t[47];
// v[49] += v[48] < t[48];
// v[50] += v[49] < t[49];
// v[51] += v[50] < t[50];
// v[52] += v[51] < t[51];
// v[53] += v[52] < t[52];
// v[54] += v[53] < t[53];
// v[55] += v[54] < t[54];
// v[56] += v[55] < t[55];
// v[57] += v[56] < t[56];
// v[58] += v[57] < t[57];
// v[59] += v[58] < t[58];
// v[60] += v[59] < t[59];
// v[61] += v[60] < t[60];
// v[62] += v[61] < t[61];
// v[63] += v[62] < t[62];
// v[64] += v[63] < t[63];
}
}
// v is fact and we skip v[64] in output ???
v[64] = 0;
}
// r[ 64], the result, r = (a << bits) % m
// a[ 64], the 256 byte number we want to convert
// m[128], modulo
DECLSPEC void to_montgomery (PRIVATE_AS u32 *r, PRIVATE_AS const u32 *a, PRIVATE_AS const u32 *m)
{
u32 t[128] = { 0 };
// shift by "bits" bits, i.e. 256 bytes (64 u32)
// for (u32 i = 0; i < 64; i++) t[i + 64] = a[i];
t[ 64] = a[ 0]; t[ 65] = a[ 1]; t[ 66] = a[ 2]; t[ 67] = a[ 3];
t[ 68] = a[ 4]; t[ 69] = a[ 5]; t[ 70] = a[ 6]; t[ 71] = a[ 7];
t[ 72] = a[ 8]; t[ 73] = a[ 9]; t[ 74] = a[10]; t[ 75] = a[11];
t[ 76] = a[12]; t[ 77] = a[13]; t[ 78] = a[14]; t[ 79] = a[15];
t[ 80] = a[16]; t[ 81] = a[17]; t[ 82] = a[18]; t[ 83] = a[19];
t[ 84] = a[20]; t[ 85] = a[21]; t[ 86] = a[22]; t[ 87] = a[23];
t[ 88] = a[24]; t[ 89] = a[25]; t[ 90] = a[26]; t[ 91] = a[27];
t[ 92] = a[28]; t[ 93] = a[29]; t[ 94] = a[30]; t[ 95] = a[31];
t[ 96] = a[32]; t[ 97] = a[33]; t[ 98] = a[34]; t[ 99] = a[35];
t[100] = a[36]; t[101] = a[37]; t[102] = a[38]; t[103] = a[39];
t[104] = a[40]; t[105] = a[41]; t[106] = a[42]; t[107] = a[43];
t[108] = a[44]; t[109] = a[45]; t[110] = a[46]; t[111] = a[47];
t[112] = a[48]; t[113] = a[49]; t[114] = a[50]; t[115] = a[51];
t[116] = a[52]; t[117] = a[53]; t[118] = a[54]; t[119] = a[55];
t[120] = a[56]; t[121] = a[57]; t[122] = a[58]; t[123] = a[59];
t[124] = a[60]; t[125] = a[61]; t[126] = a[62]; t[127] = a[63];
mod_4096 (t, m);
// for (u32 i = 0; i < 64; i++) r[i] = t[i];
r[ 0] = t[ 0]; r[ 1] = t[ 1]; r[ 2] = t[ 2]; r[ 3] = t[ 3];
r[ 4] = t[ 4]; r[ 5] = t[ 5]; r[ 6] = t[ 6]; r[ 7] = t[ 7];
r[ 8] = t[ 8]; r[ 9] = t[ 9]; r[10] = t[10]; r[11] = t[11];
r[12] = t[12]; r[13] = t[13]; r[14] = t[14]; r[15] = t[15];
r[16] = t[16]; r[17] = t[17]; r[18] = t[18]; r[19] = t[19];
r[20] = t[20]; r[21] = t[21]; r[22] = t[22]; r[23] = t[23];
r[24] = t[24]; r[25] = t[25]; r[26] = t[26]; r[27] = t[27];
r[28] = t[28]; r[29] = t[29]; r[30] = t[30]; r[31] = t[31];
r[32] = t[32]; r[33] = t[33]; r[34] = t[34]; r[35] = t[35];
r[36] = t[36]; r[37] = t[37]; r[38] = t[38]; r[39] = t[39];
r[40] = t[40]; r[41] = t[41]; r[42] = t[42]; r[43] = t[43];
r[44] = t[44]; r[45] = t[45]; r[46] = t[46]; r[47] = t[47];
r[48] = t[48]; r[49] = t[49]; r[50] = t[50]; r[51] = t[51];
r[52] = t[52]; r[53] = t[53]; r[54] = t[54]; r[55] = t[55];
r[56] = t[56]; r[57] = t[57]; r[58] = t[58]; r[59] = t[59];
r[60] = t[60]; r[61] = t[61]; r[62] = t[62]; r[63] = t[63];
}
// r [ 64], result, r = a * (rinv * 2) % m
// a [ 64], the 256 byte number we want to convert back
// m [128], modulo
// rinv[ 64], r', our euclidean inverse r
DECLSPEC void from_montgomery (PRIVATE_AS u32 *r, PRIVATE_AS const u32* a, PRIVATE_AS const u32 *m, PRIVATE_AS const u32 *rinv)
{
// (a * (rinv * 2)) % m = (a * rinv2) % m
// rinv2 = 2 * rinv (or rinv << 1)
u32 rinv2[128] = { 0 };
// rinv2[64] = rinv[63] >> 31;
// for (int i = 63; i > 0; i--) rinv2[i] = (rinv[i - 1] >> 31) | (rinv[i] << 1);
// rinv2[0] = rinv[0] << 1;
rinv2[64] = (rinv[63] >> 31);
rinv2[63] = (rinv[62] >> 31) | (rinv[63] << 1);
rinv2[62] = (rinv[61] >> 31) | (rinv[62] << 1);
rinv2[61] = (rinv[60] >> 31) | (rinv[61] << 1);
rinv2[60] = (rinv[59] >> 31) | (rinv[60] << 1);
rinv2[59] = (rinv[58] >> 31) | (rinv[59] << 1);
rinv2[58] = (rinv[57] >> 31) | (rinv[58] << 1);
rinv2[57] = (rinv[56] >> 31) | (rinv[57] << 1);
rinv2[56] = (rinv[55] >> 31) | (rinv[56] << 1);
rinv2[55] = (rinv[54] >> 31) | (rinv[55] << 1);
rinv2[54] = (rinv[53] >> 31) | (rinv[54] << 1);
rinv2[53] = (rinv[52] >> 31) | (rinv[53] << 1);
rinv2[52] = (rinv[51] >> 31) | (rinv[52] << 1);
rinv2[51] = (rinv[50] >> 31) | (rinv[51] << 1);
rinv2[50] = (rinv[49] >> 31) | (rinv[50] << 1);
rinv2[49] = (rinv[48] >> 31) | (rinv[49] << 1);
rinv2[48] = (rinv[47] >> 31) | (rinv[48] << 1);
rinv2[47] = (rinv[46] >> 31) | (rinv[47] << 1);
rinv2[46] = (rinv[45] >> 31) | (rinv[46] << 1);
rinv2[45] = (rinv[44] >> 31) | (rinv[45] << 1);
rinv2[44] = (rinv[43] >> 31) | (rinv[44] << 1);
rinv2[43] = (rinv[42] >> 31) | (rinv[43] << 1);
rinv2[42] = (rinv[41] >> 31) | (rinv[42] << 1);
rinv2[41] = (rinv[40] >> 31) | (rinv[41] << 1);
rinv2[40] = (rinv[39] >> 31) | (rinv[40] << 1);
rinv2[39] = (rinv[38] >> 31) | (rinv[39] << 1);
rinv2[38] = (rinv[37] >> 31) | (rinv[38] << 1);
rinv2[37] = (rinv[36] >> 31) | (rinv[37] << 1);
rinv2[36] = (rinv[35] >> 31) | (rinv[36] << 1);
rinv2[35] = (rinv[34] >> 31) | (rinv[35] << 1);
rinv2[34] = (rinv[33] >> 31) | (rinv[34] << 1);
rinv2[33] = (rinv[32] >> 31) | (rinv[33] << 1);
rinv2[32] = (rinv[31] >> 31) | (rinv[32] << 1);
rinv2[31] = (rinv[30] >> 31) | (rinv[31] << 1);
rinv2[30] = (rinv[29] >> 31) | (rinv[30] << 1);
rinv2[29] = (rinv[28] >> 31) | (rinv[29] << 1);
rinv2[28] = (rinv[27] >> 31) | (rinv[28] << 1);
rinv2[27] = (rinv[26] >> 31) | (rinv[27] << 1);
rinv2[26] = (rinv[25] >> 31) | (rinv[26] << 1);
rinv2[25] = (rinv[24] >> 31) | (rinv[25] << 1);
rinv2[24] = (rinv[23] >> 31) | (rinv[24] << 1);
rinv2[23] = (rinv[22] >> 31) | (rinv[23] << 1);
rinv2[22] = (rinv[21] >> 31) | (rinv[22] << 1);
rinv2[21] = (rinv[20] >> 31) | (rinv[21] << 1);
rinv2[20] = (rinv[19] >> 31) | (rinv[20] << 1);
rinv2[19] = (rinv[18] >> 31) | (rinv[19] << 1);
rinv2[18] = (rinv[17] >> 31) | (rinv[18] << 1);
rinv2[17] = (rinv[16] >> 31) | (rinv[17] << 1);
rinv2[16] = (rinv[15] >> 31) | (rinv[16] << 1);
rinv2[15] = (rinv[14] >> 31) | (rinv[15] << 1);
rinv2[14] = (rinv[13] >> 31) | (rinv[14] << 1);
rinv2[13] = (rinv[12] >> 31) | (rinv[13] << 1);
rinv2[12] = (rinv[11] >> 31) | (rinv[12] << 1);
rinv2[11] = (rinv[10] >> 31) | (rinv[11] << 1);
rinv2[10] = (rinv[ 9] >> 31) | (rinv[10] << 1);
rinv2[ 9] = (rinv[ 8] >> 31) | (rinv[ 9] << 1);
rinv2[ 8] = (rinv[ 7] >> 31) | (rinv[ 8] << 1);
rinv2[ 7] = (rinv[ 6] >> 31) | (rinv[ 7] << 1);
rinv2[ 6] = (rinv[ 5] >> 31) | (rinv[ 6] << 1);
rinv2[ 5] = (rinv[ 4] >> 31) | (rinv[ 5] << 1);
rinv2[ 4] = (rinv[ 3] >> 31) | (rinv[ 4] << 1);
rinv2[ 3] = (rinv[ 2] >> 31) | (rinv[ 3] << 1);
rinv2[ 2] = (rinv[ 1] >> 31) | (rinv[ 2] << 1);
rinv2[ 1] = (rinv[ 0] >> 31) | (rinv[ 1] << 1);
rinv2[ 0] = (rinv[ 0] << 1);
mod_4096 (rinv2, m);
// t = a * rinv2
u32 t[128] = { 0 };
mul (t, a, rinv2);
// t %= m
mod_4096 (t, m);
// for (u32 i = 0; i < 64; i++) r[i] = t[i];
r[ 0] = t[ 0]; r[ 1] = t[ 1]; r[ 2] = t[ 2]; r[ 3] = t[ 3];
r[ 4] = t[ 4]; r[ 5] = t[ 5]; r[ 6] = t[ 6]; r[ 7] = t[ 7];
r[ 8] = t[ 8]; r[ 9] = t[ 9]; r[10] = t[10]; r[11] = t[11];
r[12] = t[12]; r[13] = t[13]; r[14] = t[14]; r[15] = t[15];
r[16] = t[16]; r[17] = t[17]; r[18] = t[18]; r[19] = t[19];
r[20] = t[20]; r[21] = t[21]; r[22] = t[22]; r[23] = t[23];
r[24] = t[24]; r[25] = t[25]; r[26] = t[26]; r[27] = t[27];
r[28] = t[28]; r[29] = t[29]; r[30] = t[30]; r[31] = t[31];
r[32] = t[32]; r[33] = t[33]; r[34] = t[34]; r[35] = t[35];
r[36] = t[36]; r[37] = t[37]; r[38] = t[38]; r[39] = t[39];
r[40] = t[40]; r[41] = t[41]; r[42] = t[42]; r[43] = t[43];
r[44] = t[44]; r[45] = t[45]; r[46] = t[46]; r[47] = t[47];
r[48] = t[48]; r[49] = t[49]; r[50] = t[50]; r[51] = t[51];
r[52] = t[52]; r[53] = t[53]; r[54] = t[54]; r[55] = t[55];
r[56] = t[56]; r[57] = t[57]; r[58] = t[58]; r[59] = t[59];
r[60] = t[60]; r[61] = t[61]; r[62] = t[62]; r[63] = t[63];
}