#include<stdio.h> /*------------------------------------------*/ typedef struct { unsigned long first; unsigned long second; }couple; /*------------------------------------------*/ typedef struct { unsigned long _11, _12, _21, _22; }quadruplet; /*------------------------------------------*/ couple applyF(couple (*f)(couple), int n, couple x) { if (n == 0) return x; return f(applyF(f, n - 1, x)); } /*------------------------------------------*/ couple applyFT(couple (*f)(couple), int n, couple x) { if (n == 0) return x; return applyF(f, n-1, f(x)); } /*------------------------------------------*/ unsigned long multiplie(unsigned long a, unsigned long b) { couple x = {0, a}; couple f(couple x) { couple y = {x.first + x.second, x.second}; return y; } return applyFT(f, b, x).first; } /*------------------------------------------*/ unsigned long factorielle(unsigned long n) { couple x = {n, 1}; couple f(couple x) { couple y = {x.first - 1, x.first*x.second}; return y; } return applyFT(f, n, x).second; } /*------------------------------------------*/ unsigned long puissance(unsigned long b, unsigned long n) { couple x = {1, b}; couple f(couple x) { couple y = {x.first * x.second, x.second}; return y; } return applyFT(f, n, x).first; } /*------------------------------------------*/ unsigned long fastPuissance(unsigned long b, unsigned long n) { if(n == 0) return 1; if (n % 2) return b * fastPuissance(b*b, n/2); return fastPuissance(b*b, n/2); } /*------------------------------------------*/ unsigned long applyFD(int (*delta)(int k), unsigned long (*f)(couple), int n, unsigned long x) { couple y; if (n == 0) return x; y.first = n; y.second = applyFD(delta, f, delta(n), x); return f(y); } /*------------------------------------------*/ unsigned long slowPuissanceIT(unsigned long b, unsigned long n) { unsigned long f(couple x) { return x.second*b; } int delta(int x) { return x - 1; } return applyFD(delta, f, n, 1); } /*------------------------------------------*/ unsigned long factorielleIT(unsigned long n) { unsigned long f(couple x) { return x.first * x.second; } int delta(int x) { return x - 1; } return applyFD(delta, f, n, 1); } /*------------------------------------------*/ unsigned long fastPuissanceIT(unsigned long b, unsigned long n) { unsigned long f(couple x) { if (x.first % 2) return b*x.second*x.second; return x.second*x.second; } int delta(int x) { return x/2; } return applyFD(delta, f, n, 1); } /*------------------------------------------*/ quadruplet fiboMat() { quadruplet q = {1, 1, 1, 0}; return q; } /*------------------------------------------*/ quadruplet identite() { quadruplet q = {1, 0, 0, 1}; return q; } /*------------------------------------------*/ quadruplet multMat(quadruplet x, quadruplet y) { quadruplet xy; xy._11 = x._11*y._11 + x._12*y._21; xy._21 = x._21*y._11 + x._22*y._21; xy._12 = x._11*y._12 + x._12*y._22; xy._22 = x._21*y._12 + x._22*y._22; return xy; } /*------------------------------------------*/ quadruplet applyFDQ(unsigned long (*delta)(unsigned long), quadruplet (*f)(unsigned long, quadruplet), unsigned long n, quadruplet x) { if (n == 0) return x; return f(n, applyFDQ(delta, f, delta(n), x)); } /*------------------------------------------*/ quadruplet matPow(quadruplet x, unsigned long n) { quadruplet f(unsigned long m, quadruplet q) { quadruplet qPrime = multMat(q, q); if (m % 2) return multMat(x, qPrime); return qPrime; } unsigned long delta(unsigned long x) { return x/2; } return applyFDQ(delta, f, n, identite()); } /*------------------------------------------*/ couple multMatVec(quadruplet x, couple y) { couple xy; xy.first = x._11*y.first + x._12*y.second; xy.second = x._21*y.first + x._22*y.second; return xy; } /*------------------------------------------*/ unsigned long fastFibonacciIT(unsigned long l) { quadruplet q = fiboMat(); couple c = {1, 0}; c = multMatVec(matPow(q, l), c); return c.second; } /*------------------------------------------*/ int main() { int i; for(i = 0 ; i <= 45 ; i++) { printf("F_%d = %ld\n", i, fastFibonacciIT(i)); } return 0; }