// fib.cpp: several routines to compute the n'th Fibonacci number // usage: fib i n, where i is from 1 to 4, which picks an algorithm // and n is the order of the Fibonacci number we want to compute #include #include #include using namespace std; struct Matrix { // a 2x2 matrix unsigned long long a11; unsigned long long a12; unsigned long long a21; unsigned long long a22; }; const Matrix base = {1, 1, 1, 0}; unsigned long long fib1(unsigned long); // straightforward implementation unsigned long long fib2(unsigned long); unsigned long long fib3(unsigned long); unsigned long long fib4(unsigned long); int main(int argc, char* argv[]) { if (argc != 3) return 0; int algo = atoi(argv[1]); unsigned long long (*fib)(unsigned long); // pointer to a fibi switch (algo) { case 1: fib = &fib1; break; case 2: fib = &fib2; break; case 3: fib = &fib3; break; case 4: fib = &fib4; break; default: return 0; } stringstream ss(argv[2]); unsigned long n; ss >> n; cout << "Fib[" << n << "] = " << fib(n) << endl; return 0; } /** * ----------------------------------------------------------------------- * the most straightforward algorithm of Fibonacci comp. algo. * ----------------------------------------------------------------------- */ unsigned long long fib1(unsigned long n) { if (n <= 1) return n; return fib1(n-1) + fib1(n-2); } /** * ----------------------------------------------------------------------- * a better algorithm with a linear time/space * ----------------------------------------------------------------------- */ unsigned long long fib2(unsigned long n) { if (n <= 1) return n; unsigned long long* A = new unsigned long long[n]; A[0] = 0; A[1] = 1; for (unsigned long i=2; i<=n; i++) { A[i] = A[i-1]+A[i-2]; } unsigned long long ret = A[n]; delete [] A; return ret; } /** * ----------------------------------------------------------------------- * a better algorithm with a linear time, constant space * ----------------------------------------------------------------------- */ unsigned long long fib3(unsigned long n) { if (n <= 1) return n; unsigned long long a=0, b=1, temp; unsigned long i; for (unsigned long i=2; i<= n; i++) { temp = a + b; // F[i] = F[i-2] + F[i-1] a = b; // a = F[i-1] b = temp; // b = F[i] } return temp; } /** * ----------------------------------------------------------------------- * multiply two matrices * ----------------------------------------------------------------------- */ Matrix matrix_mult(Matrix x, Matrix y) { Matrix temp; temp.a11 = x.a11*y.a11 + x.a12*y.a21; temp.a12 = x.a11*y.a12 + x.a12*y.a22; temp.a21 = x.a21*y.a11 + x.a22*y.a21; temp.a22 = x.a21*y.a12 + x.a22*y.a22; return temp; } /** * ----------------------------------------------------------------------- * compute base^n using repeated squaring * ----------------------------------------------------------------------- */ Matrix matrix_power(unsigned long n) { Matrix unit = {1, 0, 0, 1}; Matrix temp; if (n == 0) return unit; if (n%2 == 0) { temp = matrix_power(n/2); return matrix_mult(temp, temp); } else { temp = matrix_power((n-1)/2); return matrix_mult(temp, matrix_mult(temp, base)); } } /** * ----------------------------------------------------------------------- * a better implementation with a logarithmic time, constant space * ----------------------------------------------------------------------- */ unsigned long long fib4(unsigned long n) { if (n <= 1) return n; Matrix mat = matrix_power(n-1); return mat.a11; }