Skip to content

Commit 31c5645

Browse files
committed
Done with the required changes
1 parent 3ad4b6a commit 31c5645

File tree

1 file changed

+68
-28
lines changed

1 file changed

+68
-28
lines changed

maths/fibonacci.py

+68-28
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from collections.abc import Iterator
1919
from math import sqrt
2020
from time import time
21+
import numpy as np
2122

2223

2324
def time_func(func, *args, **kwargs):
@@ -232,38 +233,77 @@ def fib_binet(n: int) -> list[int]:
232233
return [round(phi**i / sqrt_5) for i in range(n + 1)]
233234

234235

235-
def fib_matrix(n: int) -> int:
236-
# https://www.nayuki.io/page/fast-fibonacci-algorithms#:~:text=
237-
# Summary:%20The%20two%20fast%20Fibonacci%20algorithms%20are%20matrix
238-
def matrix_mult(a, b):
239-
return [
240-
[
241-
a[0][0] * b[0][0] + a[0][1] * b[1][0],
242-
a[0][0] * b[0][1] + a[0][1] * b[1][1],
243-
],
244-
[
245-
a[1][0] * b[0][0] + a[1][1] * b[1][0],
246-
a[1][0] * b[0][1] + a[1][1] * b[1][1],
247-
],
248-
]
249-
250-
def matrix_pow(m, power):
251-
result = [[1, 0], [0, 1]] # Identity matrix
252-
base = m
253-
while power:
254-
if power % 2 == 1:
255-
result = matrix_mult(result, base)
256-
base = matrix_mult(base, base)
257-
power //= 2
258-
return result
236+
def matrix_mult_np(a, b):
237+
"""
238+
Multiplies two matrices using numpy's dot product.
239+
240+
Args:
241+
a: First matrix as a numpy array
242+
b: Second matrix as a numpy array
243+
244+
Returns:
245+
The product of matrices a and b.
246+
"""
247+
return np.dot(a, b)
248+
249+
250+
def matrix_pow_np(m, power):
251+
"""
252+
Raises a matrix to the power of 'power' using binary exponentiation.
253+
254+
Args:
255+
m: Matrix as a numpy array.
256+
power: The power to which the matrix is to be raised.
257+
258+
Returns:
259+
The matrix raised to the power.
260+
"""
261+
result = np.identity(2, dtype=int) # Identity matrix
262+
base = m
263+
while power:
264+
if power % 2 == 1:
265+
result = matrix_mult_np(result, base)
266+
base = matrix_mult_np(base, base)
267+
power //= 2
268+
return result
259269

270+
271+
def fib_matrix_np(n: int) -> int:
272+
"""
273+
Calculates the n-th Fibonacci number using matrix exponentiation.
274+
https://www.nayuki.io/page/fast-fibonacci-algorithms#:~:text=
275+
Summary:%20The%20two%20fast%20Fibonacci%20algorithms%20are%20matrix
276+
277+
Args:
278+
n: Fibonacci sequence index
279+
280+
Returns:
281+
The n-th Fibonacci number.
282+
283+
Raises:
284+
ValueError: If n is negative.
285+
286+
>>> fib_matrix_np(0)
287+
0
288+
>>> fib_matrix_np(1)
289+
1
290+
>>> fib_matrix_np(10)
291+
55
292+
>>> fib_matrix_np(-1)
293+
Traceback (most recent call last):
294+
...
295+
ValueError: n is negative
296+
"""
260297
if n < 0:
261298
raise ValueError("n is negative")
262299
if n == 0:
263300
return 0
264-
m = [[1, 1], [1, 0]]
265-
result = matrix_pow(m, n - 1)
266-
return result[0][0]
301+
302+
m = np.array([[1, 1], [1, 0]], dtype=int)
303+
result = matrix_pow_np(m, n - 1)
304+
return result[0, 0]
305+
306+
267307

268308

269309
if __name__ == "__main__":
@@ -278,4 +318,4 @@ def matrix_pow(m, power):
278318
time_func(fib_memoization, num) # 0.0100 ms
279319
time_func(fib_recursive_cached, num) # 0.0153 ms
280320
time_func(fib_recursive, num) # 257.0910 ms
281-
time_func(fib_matrix, num) # 0.0000 ms
321+
time_func(fib_matrix_np, num) # 0.0000 ms

0 commit comments

Comments
 (0)