// Pell(1000000) in 199 mS (Athlon X4 640, XP, 2GB) // Half Companion Pell Numbers are defined by: // H[0] = 1, H[1] = 1, H[n+2]= 2*H[n+1] + H[n] // The sequence is 1,1,3,7,17,41,99,239,... // Small values of n use a table. // Larger values use a binary powering approach. // HCPs(n) returns H[n] and H[n+1] // The most important formula used is: // // H[2n] = 2 * H[n]^2 - (-1)^n // // Each bit requires two squares. // HCP(n) returns H[n] // If n is odd the lowest 1 bit requires a multiply. // Trailing zero bits are done by a square each. // Pells(n) returns P[n] and P[n+1] // It derives a pair of Pell numbers // from a pair of HCP numbers: // // 2*P[n] = H[n+1] - H[n] // 2*P[n+1] = H[n+1] + H[n] // // Pell(n) returns P[n] // The least significant bit requires a multiply. using Xint = System.Numerics.BigInteger; using System.Threading.Tasks; using System.Diagnostics; using System; class Half_Companion_Pell_Numbers { private static int[] smallHCP = { 1, 1, 3, 7, 17, 41, 99, 239, 577, 1393, 3363, 8119, 19601, 47321, 114243, 275807, 665857 }; public static Xint[] HCPs(int n) { if (n < 16) return new Xint[2] { smallHCP[n++], smallHCP[n] }; int i = fL2(n) - 4; int m = (n >> i) / 2 & 7 + 8; Xint H0 = smallHCP[m++], H1 = smallHCP[m]; for (; i >= 0; i--) { H0 = SQ(H0); H1 = SQ(H1); switch (((3 << i) & n) >> i) { case 0: H1 = H1 - H0 + 1; H0 = 2 * H0 - 1; break; case 1: H0 = H1 - H0 + 1; H1 = 2 * H1 + 1; break; case 2: H1 = H1 - H0 - 1; H0 = 2 * H0 + 1; break; case 3: H0 = H1 - H0 - 1; H1 = 2 * H1 - 1; break; } } return new Xint[2] { H0, H1 }; } public static Xint HCP(int n) { if (n < 17) return smallHCP[n]; if ((n & 1) == 1) return HCP_n_is_odd(n); int z = fL2(n & -n); int y = fL2(n) - z - 3; if (y < 0) { z += y; Xint H = smallHCP[n >> z]; for (; z > 0; z--) H = 2 * SQ(H) - 1; return H; } else { Xint H = 2 * SQ(HCP_n_is_odd(n >> z)) + 1; for (; z > 1; z--) H = 2 * SQ(H) - 1; return H; } } private static Xint HCP_n_is_odd(int n) { Xint[] H = HCPs(n / 2); return (n & 2) - 1 + 2 * MTP(H[1], H[0]); } private static int[] smallPell = { 0, 1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, 33461, 80782, 195025, 470832 }; public static Xint[] Pells(int n) { if (n < 16) return new Xint[2] { smallPell[n++], smallPell[n] }; Xint[] H = HCPs(n); return new Xint[2] { (H[1] - H[0]) / 2, (H[1] + H[0]) / 2 }; } public static Xint Pell(int n) { if (n < 17) return smallPell[n]; Xint[] H = HCPs(n / 2); return (n & 1) == 0 ? MTP(H[1] - H[0], H[0]) : MTP(H[1] + H[0], H[0]) + ((n & 2) - 1); } // use the easy to copy faster versions: // http://bigintegers.blogspot.com/2011/fibonacci-numbers-part-1.html private static Xint MTP(Xint U, Xint V) { return U * V; } private static Xint SQ(Xint U) { return U * U; } private static int fL2(int n) { int i = -1; for (; n > 0; n /= 2) i++; return i; } private static Stopwatch sw = new Stopwatch(); static void Main() { Pell(1000000); sw.Restart(); for (int n = 0; n < 10; n++) Pell(1000000); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); Console.ReadLine(); } }
C# , System.Numerics, Multiplication, Karatsuba, Toom Cook, Division, Burnikel, Ziegler, Factorial, Luschny, Square Root, Zimmermann, Choose, Binomial Coefficient, Permutation, Combination, Eratosthenes, Primes, Fibonacci, Lucas, Pell, Catalan, Fast Random Number Generator, Overton
2011/10/11
Half Companion Pell Numbers
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment