public static unsafe ECPoint MultiplyAndAdd(ECPoint p1, Number scaler1, ECPoint p2, Number scaler2) { #if true int l = scaler1.BitCount(); if (l < scaler2.BitCount()) { l = scaler2.BitCount(); } int * b1 = stackalloc int[l >> 2]; int * b2 = stackalloc int[l >> 2]; int * e1 = stackalloc int[l >> 2]; int * e2 = stackalloc int[l >> 2]; int d1 = ComputeSignedWindowDecomposition(scaler1, b1, e1) - 1; int d2 = ComputeSignedWindowDecomposition(scaler2, b2, e2) - 1; ECPoint[] p1ary = p1.SetupMultiplyHelperPoints(); ECPoint[] p2ary = p2.SetupMultiplyHelperPoints(); int lastE; ECPoint Q; if (e1[d1] == e2[d2]) { Q = p1ary[b1[d1]].Add(p2ary[b2[d2--]]); lastE = e1[d1--]; } else if (e1[d1] > e2[d2]) { Q = p1ary[b1[d1]]; lastE = e1[d1--]; } else { Q = p2ary[b2[d2]]; lastE = e2[d2--]; } while (d1 >= 0 || d2 >= 0) { int nextE; int nextType = 0; if (d1 >= 0 && d2 >= 0 && e1[d1] == e2[d2]) { nextE = e1[d1]; nextType = 0; } else if ((d1 >= 0 && d2 < 0) || (d1 >= 0 && e1[d1] > e2[d2])) { nextE = e1[d1]; nextType = 1; } else { nextE = e2[d2]; nextType = 2; } for (int k = 0; k < lastE - nextE; k++) { Q = Q.Double(); } if (nextType == 0 || nextType == 1) { if (b1[d1] > 0) { Q = Q.Add(p1ary[b1[d1--]]); } else { Q = Q.Add(p1ary[-b1[d1--]].Invert()); } } if (nextType == 0 || nextType == 2) { if (b2[d2] > 0) { Q = Q.Add(p2ary[b2[d2--]]); } else { Q = Q.Add(p2ary[-b2[d2--]].Invert()); } } lastE = nextE; } for (int k = 0; k < lastE; k++) { Q = Q.Double(); } return(Q); #else int l = scaler1.BitCount(); if (l < scaler2.BitCount()) { l = scaler2.BitCount(); } ECPoint Z = p1.Add(p2); ECPoint R = p1._field.GetInfinityPoint(p1._group); for (int i = l - 1; i >= 0; i--) { R = R.Double(); uint ki = scaler1.GetBit(i); uint li = scaler2.GetBit(i); if (ki == 0) { if (li == 1) { R = R.Add(p2); } } else { if (li == 0) { R = R.Add(p1); } else { R = R.Add(Z); } } } return(R); #endif }
public unsafe ECPoint Multiply(Number scaler) { ECPoint[] P = SetupMultiplyHelperPoints(); #if true scaler = new Number(scaler, 1); int l = scaler.BitCount() - 1; int * b = stackalloc int [l >> 2]; int * e = stackalloc int[l >> 2]; int d = ComputeSignedWindowDecomposition(scaler, b, e); ECPoint Q = P[b[d - 1]]; for (int i = d - 2; i >= 0; i--) { for (int k = 0; k < e[i + 1] - e[i]; k++) { Q = Q.Double(); } if (b[i] > 0) { Q = Q.Add(P[b[i]]); } else { Q = Q.Add(P[-b[i]].Invert()); } } for (int k = 0; k < e[0]; k++) { Q = Q.Double(); } #else #if true if (P == null) { P = _multiplyHelperPoints = new ECPoint[16]; P[1] = this; P[2] = this.Double(); P[3] = P[1].Add(P[2]); P[5] = P[3].Add(P[2]); P[7] = P[5].Add(P[2]); P[9] = P[7].Add(P[2]); P[11] = P[9].Add(P[2]); P[13] = P[11].Add(P[2]); P[15] = P[13].Add(P[2]); } int j = scaler.BitCount() - 1; ECPoint Q = _field.GetInfinityPoint(_group); while (j >= 0) { if (scaler.GetBit(j) == 0) { Q = Q.Double(); j--; } else { int n = j - 1; uint h = (1 << 3) | (scaler.GetBit(n--) << 2) | (scaler.GetBit(n--) << 1) | scaler.GetBit(n); int t = j - 3; while ((h & 1) == 0) { h >>= 1; t++; } for (int i = 1; i <= j - t + 1; i++) { Q = Q.Double(); } Q = Q.Add(P[(int)h]); j = t - 1; } } #else ECPoint inv = Invert(); if (P == null) { P = _multiplyHelperPoints = new ECPoint[16]; P[1] = this; P[2] = this.Double(); P[3] = P[1].Add(P[2]); P[5] = P[3].Add(P[2]); P[7] = P[5].Add(P[2]); P[9] = P[7].Add(P[2]); P[11] = P[9].Add(P[2]); P[13] = P[11].Add(P[2]); P[15] = P[13].Add(P[2]); } int j = scaler.BitCount() - 1; ECPoint Q = _field.GetInfinityPoint(_group); while (j >= 0) { uint continuous = scaler.GetContinuousBitCount(j); if (continuous == 0) { Q = Q.Double(); j--; } else if (continuous <= 4) { int n = j - 1; uint h = (1 << 3) | (scaler.GetBit(n--) << 2) | (scaler.GetBit(n--) << 1) | scaler.GetBit(n); int t = j - 3; while ((h & 1) == 0) { h >>= 1; t++; } for (int i = 1; i <= j - t + 1; i++) { Q = Q.Double(); } Q = Q.Add(P[(int)h]); j = t - 1; } else { Q = Q.Add(this); for (uint i = 0; i < continuous; i++) { Q = Q.Double(); } Q = Q.Add(inv); j -= (int)continuous; } } #endif #endif return(Q); }