42 lines
1.2 KiB
Python
42 lines
1.2 KiB
Python
# tiny class to hold a 2x2 matrix
|
|
class Matrix2x2:
|
|
def __init__(self, m00, m01, m10, m11):
|
|
self.m00 = m00
|
|
self.m01 = m01
|
|
self.m10 = m10
|
|
self.m11 = m11
|
|
|
|
# multiply two 2x2 matrices
|
|
def multiply(a, b):
|
|
return Matrix2x2(
|
|
a.m00 * b.m00 + a.m01 * b.m10, # top-left
|
|
a.m00 * b.m01 + a.m01 * b.m11, # top-right
|
|
a.m10 * b.m00 + a.m11 * b.m10, # bottom-left
|
|
a.m10 * b.m01 + a.m11 * b.m11 # bottom-right
|
|
)
|
|
|
|
# raise a matrix to the power n using binary exponentiation
|
|
def matrix_pow(base, n):
|
|
result = Matrix2x2(1, 0, 0, 1) # start with identity matrix
|
|
while n > 0:
|
|
if n % 2 == 1: # if n is odd, multiply once
|
|
result = multiply(result, base)
|
|
base = multiply(base, base) # square the base
|
|
n //= 2 # integer division
|
|
return result
|
|
|
|
# get nth fibonacci number using matrix exponentiation
|
|
def fibonacci_matrix(n):
|
|
if n == 0:
|
|
return 0 # edge case
|
|
base = Matrix2x2(1, 1, 1, 0) # Fibonacci Q-matrix
|
|
result = matrix_pow(base, n - 1)
|
|
return result.m00 # top-left is F(n)
|
|
|
|
# print first n fibonacci numbers
|
|
if __name__ == "__main__":
|
|
n = 50
|
|
for i in range(n):
|
|
print(fibonacci_matrix(i), end=" ")
|
|
print()
|