Skip to main content
added 18 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11

n is treated as the sum of powers of 2: 2^a + 2^b + ... for each iteration ei (starting from 0), let p = 2^i, then

n is treated as the sum of powers of 2: 2^a + 2^b + ... for each iteration e, let p = 2^i, then

n is treated as the sum of powers of 2: 2^a + 2^b + ... for each iteration i (starting from 0), let p = 2^i, then

added 1114 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11

Note: older compilers may be missing <inttypes.h> or <stdint.h>. If <inttypes.h> is not present (Visual Studio 2010), use compiler specific format string for uint64_t. If <stdint.h> is not present (Visual Studio 2005), use typedef ... uint64_t (usually unsigned long long) and the appropriate format string.

During the calculation of a and b, let cm = current cumulative sum of bits of n:

b = F(cm)
a = F(c+1m+1)
a' = F(c+1+pm+1+p) = F(c+2m+2) F(p) + F(c+1m+1) F(p-1)
   = (F(c+1m+1)+F(cm)) F(p) + F(c+1m+1) F(p-1)
   = F(c+1m+1) F(p) + F(cm) F(p) + F(cm) F(p-1)
   = a d + b d + b c

b' = F(c+pm+p) = F(c+1m+1) F(p) + F(cm) F(p-1)
   = a d + b c

Note that if b' is the max value for uint64_t, a' will overflow, but it's not an issue. However, the algorithm can be modified so that when completed, a = fib(n-1):

a = fib(-1) = 1
b = fib(0)  = 0

a = fib(m-1)
b = fib(m)

b' = fib(m+p)
   = fib(m+1)fib(p) + fib(m)fib(p-1)
   = (fib(m) + fib(m-1))fib(p) + fib(m)fib(p-1)
   = fib(m)fib(p) + fib(m-1)fib(p) + fib(m)fib(p-1)
   = bd           + ad             + bc

a' = fib(m-1+p)
   = fib(m)fib(p) + fib(m-1)fib(p-1)
   = bd           + ac

uint64_t fib(uint64_t n)
{
    uint64_t a, b, c, d;
    a = d = 1;
    b = c = 0;
    while (1) {
        if (n & 1) {
            uint64_t bd = b*d;
            b = bd + a*d + b*c;
            a = bd + a*c;
        }
        n >>= 1;
        if (n == 0)
            break;
        {
            uint64_t dd = d*d;
            d = dd + 2*d*c;
            c = dd + c*c;
        }
    }
    return b;
}

Note: older compilers may be missing <inttypes.h> or <stdint.h>. If <inttypes.h> is not present, use compiler specific format string for uint64_t. If <stdint.h> is not present, use typedef ... uint64_t (usually unsigned long long) and the appropriate format string.

During the calculation of a and b, let c = current cumulative sum of bits of n:

b = F(c)
a = F(c+1)
a' = F(c+1+p) = F(c+2) F(p) + F(c+1) F(p-1)
   = (F(c+1)+F(c)) F(p) + F(c+1) F(p-1)
   = F(c+1) F(p) + F(c) F(p) + F(c) F(p-1)
   = a d + b d + b c

b' = F(c+p) = F(c+1) F(p) + F(c) F(p-1)
   = a d + b c

Note: older compilers may be missing <inttypes.h> or <stdint.h>. If <inttypes.h> is not present (Visual Studio 2010), use compiler specific format string for uint64_t. If <stdint.h> is not present (Visual Studio 2005), use typedef ... uint64_t (usually unsigned long long) and the appropriate format string.

During the calculation of a and b, let m = current cumulative sum of bits of n:

b = F(m)
a = F(m+1)
a' = F(m+1+p) = F(m+2) F(p) + F(m+1) F(p-1)
   = (F(m+1)+F(m)) F(p) + F(m+1) F(p-1)
   = F(m+1) F(p) + F(m) F(p) + F(m) F(p-1)
   = a d + b d + b c

b' = F(m+p) = F(m+1) F(p) + F(m) F(p-1)
   = a d + b c

Note that if b' is the max value for uint64_t, a' will overflow, but it's not an issue. However, the algorithm can be modified so that when completed, a = fib(n-1):

a = fib(-1) = 1
b = fib(0)  = 0

a = fib(m-1)
b = fib(m)

b' = fib(m+p)
   = fib(m+1)fib(p) + fib(m)fib(p-1)
   = (fib(m) + fib(m-1))fib(p) + fib(m)fib(p-1)
   = fib(m)fib(p) + fib(m-1)fib(p) + fib(m)fib(p-1)
   = bd           + ad             + bc

a' = fib(m-1+p)
   = fib(m)fib(p) + fib(m-1)fib(p-1)
   = bd           + ac

uint64_t fib(uint64_t n)
{
    uint64_t a, b, c, d;
    a = d = 1;
    b = c = 0;
    while (1) {
        if (n & 1) {
            uint64_t bd = b*d;
            b = bd + a*d + b*c;
            a = bd + a*c;
        }
        n >>= 1;
        if (n == 0)
            break;
        {
            uint64_t dd = d*d;
            d = dd + 2*d*c;
            c = dd + c*c;
        }
    }
    return b;
}
Formatting of the old-compiler paragraph
Source Link
Toby Speight
  • 88.7k
  • 14
  • 104
  • 327

Example code; c and d are used for the repeated squaring, while a and b are the cumulative results and end up as a = fib(n+1), b = fib(n). Older

Note: older compilers may not have include files for inttypes.hbe missing <inttypes.h> or stdint.h<stdint.h>. If inttypes.h<inttypes.h> is not present, use compiler specific format string for uint64_tuint64_t. If stdint.h<stdint.h> is not present, use typedef ... uint64_ttypedef ... uint64_t (usually unsigned long longunsigned long long) and the appropriate format string.

Example code; c and d are used for the repeated squaring, while a and b are the cumulative results and end up as a = fib(n+1), b = fib(n). Older compilers may not have include files for inttypes.h or stdint.h. If inttypes.h is not present, use compiler specific format string for uint64_t. If stdint.h is not present, use typedef ... uint64_t (usually unsigned long long).

Example code; c and d are used for the repeated squaring, while a and b are the cumulative results and end up as a = fib(n+1), b = fib(n).

Note: older compilers may be missing <inttypes.h> or <stdint.h>. If <inttypes.h> is not present, use compiler specific format string for uint64_t. If <stdint.h> is not present, use typedef ... uint64_t (usually unsigned long long) and the appropriate format string.

reverted code back to current C code, noted backwards compiler issues.
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
reverted code back to current C code, noted backwards compiler issues.
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 163 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 111 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
Allow code to compile with VS2010 (no inttypes.h). Variable dd needs to be in a separate block( { ... } ).
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
Convert to modern standard C
Source Link
Toby Speight
  • 88.7k
  • 14
  • 104
  • 327
Loading
deleted 2 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
deleted 176 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
deleted 176 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 42 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 11 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 190 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 133 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 4 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 1 character in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
edited body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 27 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
edited body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
edited body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 11 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
added 17 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading
deleted 76 characters in body
Source Link
rcgldr
  • 376
  • 2
  • 11
Loading