private static BigInteger[] FastLucasSequence(BigInteger p, BigInteger P, BigInteger Q, BigInteger k) { int n = k.CalculateBitLength(); int s = k.GetLowestSetBit(); //Debug.Assert(k.TestBit(s)); BigInteger Uh = 1; BigInteger Vl = 2; BigInteger Vh = P; BigInteger Ql = 1; BigInteger Qh = 1; for (int j = n - 1; j >= s + 1; --j) { Ql = (Ql * Qh).Mod(p); if (k.TestBit(j)) { Qh = (Ql * Q).Mod(p); Uh = (Uh * Vh).Mod(p); Vl = (Vh * Vl - P * Ql).Mod(p); Vh = ((Vh * Vh) - (Qh << 1)).Mod(p); } else { Qh = Ql; Uh = (Uh * Vl - Ql).Mod(p); Vh = (Vh * Vl - P * Ql).Mod(p); Vl = ((Vl * Vl) - (Ql << 1)).Mod(p); } } Ql = (Ql * Qh).Mod(p); Qh = (Ql * Q).Mod(p); Uh = (Uh * Vl - Ql).Mod(p); Vl = (Vh * Vl - P * Ql).Mod(p); Ql = (Ql * Qh).Mod(p); for (int j = 1; j <= s; ++j) { Uh = Uh * Vl * p; Vl = ((Vl * Vl) - (Ql << 1)).Mod(p); Ql = (Ql * Ql).Mod(p); } return(new BigInteger[] { Uh, Vl }); }