public virtual Number Pow (Number x, Number y) { if (y.IsZero ()) return ToElement (Number.One); if (y.IsOne ()) return x; Number a = x; Number b = ToElement (Number.One); if (y.GetBit (0) == 1) b = a; for (int i = 1; i < y.BitCount (); i ++) { a = Multiply (a, a); if (y.GetBit (i) == 1) b = Multiply (a, b); } return b; }
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; }
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 }
static unsafe int ComputeSignedWindowDecomposition (Number scaler, int *b, int *e) { int l = scaler.BitCount () - 1; int pow2w = 1 << MultiplyWindowSize; int pow2whalf = 1 << (MultiplyWindowSize - 1); int d = 0, j = 0; while (j <= l) { if (scaler.GetBit (j) == 0) { j++; } else { int t = j + MultiplyWindowSize - 1; if (t > l) t = l; uint h = 0; for (int q = t; q >= j; q--) h = (h << 1) + scaler.GetBit (q); if (h > pow2whalf) { b[d] = (int)h - pow2w; scaler.PlusBit (t + 1); l = scaler.BitCount () - 1; } else { b[d] = (int)h; } e[d] = j; d++; j = t + 1; } } return d; }