Sujet : Re: constexpr is really very smart!
De : already5chosen (at) *nospam* yahoo.com (Michael S)
Groupes : comp.lang.c++Date : 18. Dec 2024, 12:51:31
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <20241218135131.00000006@yahoo.com>
References : 1 2 3 4
User-Agent : Claws Mail 3.19.1 (GTK+ 2.24.33; x86_64-w64-mingw32)
On Wed, 18 Dec 2024 01:33:42 +0200
Michael S <
already5chosen@yahoo.com> wrote:
I am pretty sure that better variant exists, but for tonight it's
enough.
Morning fibs.
Recursive:
struct pair_t {
long long a,b;
};
// return .a=fib(n), .b=fib(n+1)
static struct pair_t fib2(long n)
{
if (n <= 0) {
struct pair_t ret = { .a = 0, .b = n==0 ? 1 : 0 };
return ret;
}
// for n > 0
// fib(n*2) = (fib(n-1)+fib(n+1))*fib(n)
// fib(n*2+1) = fib(n)*fib(n)+fib(n+1)*fib(n+1)
long m = (n-1) >> 1;
struct pair_t ret = fib2(m);
long long a = ret.a, b = ret.b;
long long c = a + b;
if ((n & 1)==0) { // (m,m+1) => ((m+1)*2,(m+1)*2*2+1)
ret.a = (a + c)*b;
ret.b = b*b + c*c;
} else { // (m,m+1) => (m*2+1,(m+1)*2)
ret.a = a*a + b*b;
ret.b = (a + c)*b;
}
return ret;
}
static long long fib(long n)
{
struct pair_t x = fib2(n-1);
return x.b;
}
Iterative:
static long long fib(long n)
{
if (n <= 0)
return 0;
// find MS bit
unsigned long tmp = n;
unsigned long bit = 1;
while (tmp > 1) {
bit += bit;
tmp /= 2;
}
// for n > 0
// fib(n*2) = (fib(n-1)+fib(n+1))*fib(n)
// fib(n*2+1) = fib(n)*fib(n)+fib(n+1)*fib(n+1)
long long a = 0, b = 1;
while (bit > 1) {
long long c = a + b; // fib(n+1)
bit /= 2;
if ((n & bit)==0) { // (n-1,n) => (n*2-1,n*2)
c += a;
a = a*a + b*b;
b = c*b;
} else { // (n-1,n) => (n*2,n*2+1)
a = (a + c)*b;
b = b*b + c*c;
}
}
return b;
}
Both variants above are O(log(n)).
In practice for n in range 0 to 92 my measurement gear does not detect
differences in speed vs simple loop. If anything, simple loop is a
little faster.