private static void MultiplyMonty(
int[] a,
int[] x,
int[] y,
int[] m,
long mQuote)
{
if (m.Length == 1)
{
x[0] = (int)MultiplyMontyNIsOne((uint)x[0], (uint)y[0], (uint)m[0], (ulong)mQuote);
return;
}
int n = m.Length;
int nMinus1 = n - 1;
long y_0 = y[nMinus1] & IMASK;
// 1. a = 0 (Notation: a = (a_{n} a_{n-1} ... a_{0})_{b} )
Array.Clear(a, 0, n + 1);
// 2. for i from 0 to (n - 1) do the following:
for (int i = n; i > 0; i--)
{
long x_i = x[i - 1] & IMASK;
// 2.1 u = ((a[0] + (x[i] * y[0]) * mQuote) mod b
long u = ((((a[n] & IMASK) + ((x_i * y_0) & IMASK)) & IMASK) * mQuote) & IMASK;
// 2.2 a = (a + x_i * y + u * m) / b
long prod1 = x_i * y_0;
long prod2 = u * (m[nMinus1] & IMASK);
long tmp = (a[n] & IMASK) + (prod1 & IMASK) + (prod2 & IMASK);
long carry = (long)((ulong)prod1 >> 32) + (long)((ulong)prod2 >> 32) + (long)((ulong)tmp >> 32);
for (int j = nMinus1; j > 0; j--)
{
prod1 = x_i * (y[j - 1] & IMASK);
prod2 = u * (m[j - 1] & IMASK);
tmp = (a[j] & IMASK) + (prod1 & IMASK) + (prod2 & IMASK) + (carry & IMASK);
carry = (long)((ulong)carry >> 32) + (long)((ulong)prod1 >> 32) +
(long)((ulong)prod2 >> 32) + (long)((ulong)tmp >> 32);
a[j + 1] = (int)tmp; // division by b
}
carry += (a[0] & IMASK);
a[1] = (int)carry;
a[0] = (int)((ulong)carry >> 32); // OJO!!!!!
}
// 3. if x >= m the x = x - m
if (CompareTo(0, a, 0, m) >= 0)
{
Subtract(0, a, 0, m);
}
// put the result in x
Array.Copy(a, 1, x, 0, n);
}