public Projective EcTwinMult(BigInt d0, Projective S, BigInt d1, Projective T) { var d = new BigInt[2] { d0, d1 }; var SpT = EcFullAdd(S, T); var SmT = EcFullSub(S, T); var m0 = d0.BitCount(); var m1 = d1.BitCount(); var m = Math.Max(m0, m1); var c = new int[2][]; c[0] = new int[6] { 0, 0, d0.BitAt(m - 1) ? 1 : 0, d0.BitAt(m - 2) ? 1 : 0, d0.BitAt(m - 3) ? 1 : 0, d0.BitAt(m - 4) ? 1 : 0 }; c[1] = new int[6] { 0, 0, d1.BitAt(m - 1) ? 1 : 0, d1.BitAt(m - 2) ? 1 : 0, d1.BitAt(m - 3) ? 1 : 0, d1.BitAt(m - 4) ? 1 : 0 }; var R = new Projective() { x = new BigInt(1, S.x.Length), y = new BigInt(1, S.x.Length), z = new BigInt(0, S.x.Length) }; int[] h = new int[2], u = new int[2]; for (var k = m; k >= 0; k--) { for (var i = 0; i <= 1; i++) { h[i] = (c[i][1] << 4) + (c[i][2] << 3) + (c[i][3] << 2) + (c[i][4] << 1) + c[i][5]; if (c[i][0] == 1) h[i] = 31 - h[i]; } for (var i = 0; i <= 1; i++) { var t = h[1 - i]; int f; if (18 <= t && t < 22) f = 9; else if (14 <= t && t < 18) f = 10; else if (22 <= t && t < 24) f = 11; else if (4 <= t && t < 12) f = 14; else f = 12; if (h[i] < f) u[i] = 0; else u[i] = (c[i][0] & 1) != 0 ? -1 : 1; } for (var i = 0; i < 2; i++) { c[i][0] = ((u[i] != 0) ^ (c[i][1] != 0)) ? 1 : 0; c[i][1] = c[i][2]; c[i][2] = c[i][3]; c[i][3] = c[i][4]; c[i][4] = c[i][5]; c[i][5] = d[i].BitAt(k - 5) ? 1 : 0; } R = EcDouble(R); if (u[0] == -1) { if (u[1] == -1) R = EcFullSub(R, SpT); else if (u[1] == 0) R = EcFullSub(R, S); else R = EcFullSub(R, SmT); } else if (u[0] == 0) { if (u[1] == -1) R = EcFullSub(R, T); else if (u[1] == 1) R = EcFullAdd(R, T); } else if (u[0] == 1) { if (u[1] == -1) R = EcFullAdd(R, SmT); else if (u[1] == 0) R = EcFullAdd(R, S); else R = EcFullAdd(R, SpT); } } return R; }