public static void Precompute() { if (precompBase != null) { return; } precompBase = new int[X25519Field.Size * 252]; int[] xs = precompBase; int[] zs = new int[X25519Field.Size * 251]; int[] x = X25519Field.Create(); x[0] = 9; int[] z = X25519Field.Create(); z[0] = 1; int[] n = X25519Field.Create(); int[] d = X25519Field.Create(); X25519Field.Apm(x, z, n, d); int[] c = X25519Field.Create(); X25519Field.Copy(d, 0, c, 0); int off = 0; for (;;) { X25519Field.Copy(n, 0, xs, off); if (off == (X25519Field.Size * 251)) { break; } PointDouble(x, z); X25519Field.Apm(x, z, n, d); X25519Field.Mul(n, c, n); X25519Field.Mul(c, d, c); X25519Field.Copy(d, 0, zs, off); off += X25519Field.Size; } int[] u = X25519Field.Create(); X25519Field.Inv(c, u); for (;;) { X25519Field.Copy(xs, off, x, 0); X25519Field.Mul(x, u, x); //X25519Field.Normalize(x); X25519Field.Copy(x, 0, precompBase, off); if (off == 0) { break; } off -= X25519Field.Size; X25519Field.Copy(zs, off, z, 0); X25519Field.Mul(u, z, u); } }