static unsafe void fcontract(byte *output, UInt64 *input) { UInt128 *t = stackalloc UInt128[5]; t[0] = (UInt128)input[0]; t[1] = (UInt128)input[1]; t[2] = (UInt128)input[2]; t[3] = (UInt128)input[3]; t[4] = (UInt128)input[4]; t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; t[0] += (t[4] >> 51) * 19; t[4] &= 0x7ffffffffffff; t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; t[0] += (t[4] >> 51) * 19; t[4] &= 0x7ffffffffffff; /* now t is between 0 and 2^255-1, properly carried. */ /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ t[0] += 19; t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; t[0] += (t[4] >> 51) * 19; t[4] &= 0x7ffffffffffff; /* now between 19 and 2^255-1 in both cases, and offset by 19. */ t[0] += 0x8000000000000 - 19; t[1] += 0x8000000000000 - 1; t[2] += 0x8000000000000 - 1; t[3] += 0x8000000000000 - 1; t[4] += 0x8000000000000 - 1; /* now between 2^255 and 2^256-20, and offset by 2^255. */ t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; t[4] &= 0x7ffffffffffff; *((UInt64 *)(output)) = (UInt64)(t[0] | (t[1] << 51)); *((UInt64 *)(output + 8)) = (UInt64)((t[1] >> 13) | (t[2] << 38)); *((UInt64 *)(output + 16)) = (UInt64)((t[2] >> 26) | (t[3] << 25)); *((UInt64 *)(output + 24)) = (UInt64)((t[3] >> 39) | (t[4] << 12)); }
public UInt128(UInt128 *ptr) : this(*ptr) { }
static unsafe void fsquare_times(UInt64 *output, UInt64 *input, UInt64 count) { UInt128 *t = stackalloc UInt128[5]; UInt64 r0, r1, r2, r3, r4, c; UInt64 d0, d1, d2, d4, d419; r0 = input[0]; r1 = input[1]; r2 = input[2]; r3 = input[3]; r4 = input[4]; do { d0 = r0 * 2; d1 = r1 * 2; d2 = r2 * 2 * 19; d419 = r4 * 19; d4 = d419 * 2; t[0] = UInt128.MultiplyUInt64(r0, r0); t[0].Add(UInt128.MultiplyUInt64(d4, r1)); t[0].Add(UInt128.MultiplyUInt64(d2, r3)); t[1] = UInt128.MultiplyUInt64(d0, r1); t[1].Add(UInt128.MultiplyUInt64(d4, r2)); t[1].Add(UInt128.MultiplyUInt64(r3, r3 * 19)); t[2] = UInt128.MultiplyUInt64(d0, r2); t[2].Add(UInt128.MultiplyUInt64(r1, r1)); t[2].Add(UInt128.MultiplyUInt64(d4, r3)); t[3] = UInt128.MultiplyUInt64(d0, r3); t[3].Add(UInt128.MultiplyUInt64(d1, r2)); t[3].Add(UInt128.MultiplyUInt64(r4, d419)); t[4] = UInt128.MultiplyUInt64(d0, r4); t[4].Add(UInt128.MultiplyUInt64(d1, r3)); t[4].Add(UInt128.MultiplyUInt64(r2, r2)); r0 = (UInt64)t[0] & 0x7ffffffffffff; c = (UInt64)(t[0] >> 51); t[1].Add(c); r1 = (UInt64)t[1] & 0x7ffffffffffff; c = (UInt64)(t[1] >> 51); t[2].Add(c); r2 = (UInt64)t[2] & 0x7ffffffffffff; c = (UInt64)(t[2] >> 51); t[3].Add(c); r3 = (UInt64)t[3] & 0x7ffffffffffff; c = (UInt64)(t[3] >> 51); t[4].Add(c); r4 = (UInt64)t[4] & 0x7ffffffffffff; c = (UInt64)(t[4] >> 51); r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff; r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff; r2 += c; } while ((--count) != 0); output[0] = r0; output[1] = r1; output[2] = r2; output[3] = r3; output[4] = r4; }
static unsafe void fmul(UInt64 *output, UInt64 *in2, UInt64 *input) { UInt128 *t = stackalloc UInt128[5]; UInt64 r0, r1, r2, r3, r4, s0, s1, s2, s3, s4, c; r0 = input[0]; r1 = input[1]; r2 = input[2]; r3 = input[3]; r4 = input[4]; s0 = in2[0]; s1 = in2[1]; s2 = in2[2]; s3 = in2[3]; s4 = in2[4]; t[0] = UInt128.MultiplyUInt64(r0, s0); t[1] = UInt128.MultiplyUInt64(r0, s1); t[1].Add(UInt128.MultiplyUInt64(r1, s0)); t[2] = UInt128.MultiplyUInt64(r0, s2); t[2].Add(UInt128.MultiplyUInt64(r2, s0)); t[2].Add(UInt128.MultiplyUInt64(r1, s1)); t[3] = UInt128.MultiplyUInt64(r0, s3); t[3].Add(UInt128.MultiplyUInt64(r3, s0)); t[3].Add(UInt128.MultiplyUInt64(r1, s2)); t[3].Add(UInt128.MultiplyUInt64(r2, s1)); t[4] = UInt128.MultiplyUInt64(r0, s4); t[4].Add(UInt128.MultiplyUInt64(r4, s0)); t[4].Add(UInt128.MultiplyUInt64(r3, s1)); t[4].Add(UInt128.MultiplyUInt64(r1, s3)); t[4].Add(UInt128.MultiplyUInt64(r2, s2)); r4 *= 19; r1 *= 19; r2 *= 19; r3 *= 19; t[0].Add(UInt128.MultiplyUInt64(r4, s1)); t[0].Add(UInt128.MultiplyUInt64(r1, s4)); t[0].Add(UInt128.MultiplyUInt64(r2, s3)); t[0].Add(UInt128.MultiplyUInt64(r3, s2)); t[1].Add(UInt128.MultiplyUInt64(r4, s2)); t[1].Add(UInt128.MultiplyUInt64(r2, s4)); t[1].Add(UInt128.MultiplyUInt64(r3, s3)); t[2].Add(UInt128.MultiplyUInt64(r4, s3)); t[2].Add(UInt128.MultiplyUInt64(r3, s4)); t[3].Add(UInt128.MultiplyUInt64(r4, s4)); r0 = (UInt64)t[0] & 0x7ffffffffffff; c = (UInt64)(t[0] >> 51); t[1] += c; r1 = (UInt64)t[1] & 0x7ffffffffffff; c = (UInt64)(t[1] >> 51); t[2] += c; r2 = (UInt64)t[2] & 0x7ffffffffffff; c = (UInt64)(t[2] >> 51); t[3] += c; r3 = (UInt64)t[3] & 0x7ffffffffffff; c = (UInt64)(t[3] >> 51); t[4] += c; r4 = (UInt64)t[4] & 0x7ffffffffffff; c = (UInt64)(t[4] >> 51); r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff; r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff; r2 += c; output[0] = r0; output[1] = r1; output[2] = r2; output[3] = r3; output[4] = r4; }
public static extern UInt128 AddUInt128s(UInt128 *pValues, int count);
public static extern void GetUInt128Out(ulong upper, ulong lower, UInt128 *value);