public static unsafe void SquarePositive (BigInteger bi, ref uint [] wkSpace)
{
uint [] t = wkSpace;
wkSpace = bi.data;
uint [] d = bi.data;
uint dl = bi.length;
bi.data = t;
fixed (uint* dd = d, tt = t) {
uint* ttE = tt + t.Length;
// Clear the dest
for (uint* ttt = tt; ttt < ttE; ttt++)
*ttt = 0;
uint* dP = dd, tP = tt;
for (uint i = 0; i < dl; i++, dP++) {
if (*dP == 0)
continue;
ulong mcarry = 0;
uint bi1val = *dP;
uint* dP2 = dP + 1, tP2 = tP + 2*i + 1;
for (uint j = i + 1; j < dl; j++, tP2++, dP2++) {
// k = i + j
mcarry += ((ulong)bi1val * (ulong)*dP2) + *tP2;
*tP2 = (uint)mcarry;
mcarry >>= 32;
}
if (mcarry != 0)
*tP2 = (uint)mcarry;
}
// Double t. Inlined for speed.
tP = tt;
uint x, carry = 0;
while (tP < ttE) {
x = *tP;
*tP = (x << 1) | carry;
carry = x >> (32 - 1);
tP++;
}
if (carry != 0) *tP = carry;
// Add in the diagnals
dP = dd;
tP = tt;
for (uint* dE = dP + dl; (dP < dE); dP++, tP++) {
ulong val = (ulong)*dP * (ulong)*dP + *tP;
*tP = (uint)val;
val >>= 32;
*(++tP) += (uint)val;
if (*tP < (uint)val) {
uint* tP3 = tP;
// Account for the first carry
(*++tP3)++;
// Keep adding until no carry
while ((*tP3++) == 0x0)
(*tP3)++;
}
}
bi.length <<= 1;
// Normalize length
while (tt [bi.length-1] == 0 && bi.length > 1) bi.length--;
}
}