private static IBigInteger[] FastLucasSequence(IBigInteger p, IBigInteger P, IBigInteger Q, IBigInteger k) { // TODO Research and apply "common-multiplicand multiplication here" var n = k.BitLength; var s = k.GetLowestSetBit(); Debug.Assert(k.TestBit(s)); var uh = BigInteger.One; var vl = BigInteger.Two; var vh = P; var ql = BigInteger.One; var qh = BigInteger.One; for (var j = n - 1; j >= s + 1; --j) { ql = ql.Multiply(qh).Mod(p); if (k.TestBit(j)) { qh = ql.Multiply(Q).Mod(p); uh = uh.Multiply(vh).Mod(p); vl = vh.Multiply(vl).Subtract(P.Multiply(ql)).Mod(p); vh = vh.Multiply(vh).Subtract(qh.ShiftLeft(1)).Mod(p); } else { qh = ql; uh = uh.Multiply(vl).Subtract(ql).Mod(p); vh = vh.Multiply(vl).Subtract(P.Multiply(ql)).Mod(p); vl = vl.Multiply(vl).Subtract(ql.ShiftLeft(1)).Mod(p); } } ql = ql.Multiply(qh).Mod(p); qh = ql.Multiply(Q).Mod(p); uh = uh.Multiply(vl).Subtract(ql).Mod(p); vl = vh.Multiply(vl).Subtract(P.Multiply(ql)).Mod(p); ql = ql.Multiply(qh).Mod(p); for (var j = 1; j <= s; ++j) { uh = uh.Multiply(vl).Mod(p); vl = vl.Multiply(vl).Subtract(ql.ShiftLeft(1)).Mod(p); ql = ql.Multiply(ql).Mod(p); } return(new[] { uh, vl }); }
private static IBigInteger[] FastLucasSequence(IBigInteger p, IBigInteger P, IBigInteger Q, IBigInteger k) { // TODO Research and apply "common-multiplicand multiplication here" var n = k.BitLength; var s = k.GetLowestSetBit(); Debug.Assert(k.TestBit(s)); var uh = BigInteger.One; var vl = BigInteger.Two; var vh = P; var ql = BigInteger.One; var qh = BigInteger.One; for (var j = n - 1; j >= s + 1; --j) { ql = ql.Multiply(qh).Mod(p); if (k.TestBit(j)) { qh = ql.Multiply(Q).Mod(p); uh = uh.Multiply(vh).Mod(p); vl = vh.Multiply(vl).Subtract(P.Multiply(ql)).Mod(p); vh = vh.Multiply(vh).Subtract(qh.ShiftLeft(1)).Mod(p); } else { qh = ql; uh = uh.Multiply(vl).Subtract(ql).Mod(p); vh = vh.Multiply(vl).Subtract(P.Multiply(ql)).Mod(p); vl = vl.Multiply(vl).Subtract(ql.ShiftLeft(1)).Mod(p); } } ql = ql.Multiply(qh).Mod(p); qh = ql.Multiply(Q).Mod(p); uh = uh.Multiply(vl).Subtract(ql).Mod(p); vl = vh.Multiply(vl).Subtract(P.Multiply(ql)).Mod(p); ql = ql.Multiply(qh).Mod(p); for (var j = 1; j <= s; ++j) { uh = uh.Multiply(vl).Mod(p); vl = vl.Multiply(vl).Subtract(ql.ShiftLeft(1)).Mod(p); ql = ql.Multiply(ql).Mod(p); } return new[] { uh, vl }; }