Skip to content

Commit e151435

Browse files
committed
Added a new algorithm that is really just the same algorithm all along.
1 parent 77ac0e3 commit e151435

File tree

4 files changed

+61
-69
lines changed

4 files changed

+61
-69
lines changed

Makefile

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
all: fib_naive fib_bottomup fib_matrix
1+
all: fib_naive fib_bottomup fib_matrix fib_vector fib_gmpbuiltin
22

33
fib_naive: main.c fib_naive.c
44
gcc main.c fib_naive.c -lgmp -O3 -o fib_naive
@@ -9,7 +9,15 @@ fib_bottomup: main.c fib_bottomup.c
99
fib_matrix: main.c fib_matrix.c
1010
gcc main.c fib_matrix.c -lgmp -O3 -o fib_matrix
1111

12+
fib_vector: main.c fib_vector.c
13+
gcc main.c fib_vector.c -lgmp -O3 -o fib_vector
14+
15+
fib_vector: main.c fib_gmpbuiltin.c
16+
gcc main.c fib_gmpbuiltin.c -lgmp -O3 -o fib_gmpbuiltin
17+
1218
clean:
1319
rm -f fib_naive
1420
rm -f fib_bottomup
1521
rm -f fib_matrix
22+
rm -f fib_vector
23+
rm -f fib_gmpbuiltin

README.md

+19-7
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ Fibonacci Algorithms
44
This repository contains example programs of different algorithms used to calculate fibonacci numbers.
55

66

7-
Naive
8-
-----
7+
Naive (`fib_naive`)
8+
---------------------
99

1010
This algorithm is based directly on the mathematical definition. It has a running time of `Θ(ϕ^n)` where n is the term of the sequence. Exponential, not good.
1111

@@ -15,8 +15,8 @@ This algorithm is based directly on the mathematical definition. It has a runnin
1515
return fib (n - 1) + fib (n - 2);
1616

1717

18-
Bottom-up
19-
---------
18+
Bottom-up (`fib_bottomup`)
19+
----------------------------
2020

2121
This algorithm is called the bottom-up algorithm because it iterates from 0 to n adding as it goes along. It has a running time of `Θ(n)`. It's okay but we can do better.
2222

@@ -33,14 +33,26 @@ This algorithm is called the bottom-up algorithm because it iterates from 0 to n
3333
return b;
3434

3535

36-
Matrix multiplication
37-
---------------------
36+
Matrix multiplication (`fib_matrix`)
37+
------------------------------------
3838

39-
This uses exponentiation by squaring to compute the nth power of a 2x2 matrix. It has a running time of `Θ(log_2 n)`. It takes advantage of the theorem:
39+
This uses exponentiation by squaring to compute the nth power of a 2x2 matrix. It has a running time of `Θ(log n)`. It takes advantage of the theorem:
4040

4141
[[F_{n+1}, F_n], [F_n, F_{n-1}]] = [[1, 1], [1, 0]] ^ n;
4242

4343
function fib(n):
4444
matrix = [[1, 1], [1, 0]];
4545
matrix = matrix_pow (matrix, n); # Finding a power is O(log n) time with the exponentiation by squares method
4646
return matrix[1, 2];
47+
48+
49+
Phi Z-component vector multiplication (`fib_vector`)
50+
----------------------------------------------------
51+
52+
This is practically the same as above, but with fewer variables and simpler code. It has the same running time of `Θ(log n)`.
53+
54+
55+
GMP Built-in (`fib_gmpbuiltin`)
56+
-------------------------------
57+
58+
The GMP library comes with its own routine for finding the nth fibonacci sequence. However it only accepts an `unsigned long int` argument instead of its `mpz_t` integer type.

fib_gmpbuiltin.c

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <gmp.h>
2+
3+
void
4+
fib_compute (mpz_t result, mpz_t term)
5+
{
6+
mpz_fib_ui (result, mpz_get_ui (term));
7+
}

fib_vector.c

+26-61
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,32 @@
11
#include <gmp.h>
22

3-
void
4-
fib_matrix_mul (mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t e, mpz_t f, mpz_t g, mpz_t h)
3+
static inline void
4+
fib_component_mul (mpz_t a, mpz_t b, mpz_t c, mpz_t d)
55
{
6-
mpz_t r, s, t, u;
6+
mpz_t r, s, bd;
77

88
mpz_init (r);
99
mpz_init (s);
10-
mpz_init (t);
11-
mpz_init (u);
10+
mpz_init (bd);
1211

13-
mpz_mul (r, a, e);
14-
mpz_mul (s, a, f);
15-
mpz_mul (t, c, e);
16-
mpz_mul (u, c, f);
12+
mpz_mul (r, a, c);
13+
mpz_mul (s, b, c);
14+
mpz_mul (bd, b, d);
1715

18-
mpz_addmul (r, b, g);
19-
mpz_addmul (s, b, h);
20-
mpz_addmul (t, d, g);
21-
mpz_addmul (u, d, h);
16+
mpz_addmul (s, a, d);
17+
mpz_add (r, r, bd);
18+
mpz_add (s, s, bd);
2219

2320
mpz_set (a, r);
2421
mpz_set (b, s);
25-
mpz_set (c, t);
26-
mpz_set (d, u);
2722

2823
mpz_clear (r);
2924
mpz_clear (s);
30-
mpz_clear (t);
31-
mpz_clear (u);
32-
}
33-
34-
void
35-
fib_matrix_square (mpz_t a, mpz_t b, mpz_t c, mpz_t d)
36-
{
37-
fib_matrix_mul (a, b, c, d, a, b, c, d);
25+
mpz_clear (bd);
3826
}
3927

40-
void
41-
fib_matrix_pow (mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t term)
28+
static inline void
29+
fib_component_pow (mpz_t a, mpz_t b, mpz_t term)
4230
{
4331
mpz_t half_term;
4432

@@ -48,33 +36,27 @@ fib_matrix_pow (mpz_t a, mpz_t b, mpz_t c, mpz_t d, mpz_t term)
4836

4937
if (mpz_even_p (term)) {
5038
mpz_tdiv_q_2exp (half_term, term, 1);
51-
fib_matrix_pow (a, b, c, d, half_term);
52-
fib_matrix_square (a, b, c, d);
39+
fib_component_pow (a, b, half_term);
40+
fib_component_mul (a, b, a, b);
5341
} else {
54-
mpz_t e, f, g, h;
55-
mpz_init_set (e, a);
56-
mpz_init_set (f, b);
57-
mpz_init_set (g, c);
58-
mpz_init_set (h, d);
42+
mpz_t c, d;
43+
mpz_init_set (c, a);
44+
mpz_init_set (d, b);
5945

6046
mpz_sub_ui (half_term, term, 1);
6147
mpz_tdiv_q_2exp (half_term, half_term, 1);
6248

63-
fib_matrix_pow (a, b, c, d, half_term);
64-
fib_matrix_square (a, b, c, d);
65-
fib_matrix_mul (a, b, c, d, e, f, g, h);
49+
fib_component_pow (a, b, half_term);
50+
fib_component_mul (a, b, a, b);
51+
fib_component_mul (a, b, c, d);
6652

67-
mpz_clear (e);
68-
mpz_clear (f);
69-
mpz_clear (g);
70-
mpz_clear (h);
53+
mpz_clear (c);
54+
mpz_clear (d);
7155
}
7256

7357
mpz_clear (half_term);
7458
}
7559

76-
void fib_vector_pow (
77-
7860
void
7961
fib_compute (mpz_t result,
8062
mpz_t term)
@@ -84,31 +66,14 @@ fib_compute (mpz_t result,
8466
return;
8567
}
8668

87-
/* [F_n,0] = ([0,1]^n - [1,-1]^n) / [-1,2] */
88-
89-
mpz_t a, b, c, d, e, f;
69+
mpz_t a, b;
9070

9171
mpz_init_set_si (a, 0);
9272
mpz_init_set_si (b, 1);
9373

94-
mpz_init_set_si (c, 1);
95-
mpz_init_set_si (d, -1);
96-
97-
mpz_init_set_si (e, -1);
98-
mpz_init_set_si (f, 2);
99-
100-
fib_vector_pow (a, b, term);
101-
fib_vector_pow (c, d, term);
102-
103-
fib_vector_sub (a, b, c, d);
104-
105-
fib_vector_div (a, b, e, f);
106-
mpz_set (result, a);
74+
fib_component_pow (a, b, term);
75+
mpz_set (result, b);
10776

10877
mpz_clear (a);
10978
mpz_clear (b);
110-
mpz_clear (c);
111-
mpz_clear (d);
112-
mpz_clear (e);
113-
mpz_clear (f);
11479
}

0 commit comments

Comments
 (0)