Skip to main content

31_fibonacci_matrix_power/
31_fibonacci_matrix_power.rs

1//! # Example: Fibonacci by Matrix Power
2//!
3//! Run: cargo run --example 31_fibonacci_matrix_power
4//!
5//! ## Problem
6//! Compute Fibonacci numbers using matrix multiplication instead of the usual
7//! additive recurrence.
8//!
9//! ## Math idea
10//! With `Q = [[1, 1], [1, 0]]`, raising `Q` to the n-th power gives
11//! ```text
12//! Q^n = [[F(n+1), F(n)],
13//!        [F(n),   F(n-1)]]
14//! ```
15//! so `F(n)` is the top-right entry of `Q^n` (with `F(0) = 0`, `F(1) = 1`).
16//!
17//! ## Tensor representation
18//! `Q` and the running product are 2×2 `Tensor`s. Each power step is a single
19//! `Tensor::matmul` call; the result entry is read with `Tensor::get(&[0, 1])`.
20//!
21//! ## What this demonstrates
22//! - 2×2 matrix construction;
23//! - repeated matrix multiplication via `Tensor::matmul` (note: `*` is
24//!   element-wise, never a matrix product);
25//! - reading a single matrix element with `Tensor::get`.
26//!
27//! ## Expected output
28//! ```text
29//! F(1..=10) via matrix power = 1 1 2 3 5 8 13 21 34 55
30//! Fibonacci by matrix power: OK
31//! ```
32//!
33//! Note: this is a demonstration of the matrix identity, not a big-integer
34//! Fibonacci routine — `f64` stays exact only for modest `n`.
35
36use matten::Tensor;
37
38/// `n`-th Fibonacci number via the matrix identity `Q^n`, with `F(0) = 0`.
39fn fib(n: u32) -> u64 {
40    let q = Tensor::new(vec![1.0, 1.0, 1.0, 0.0], &[2, 2]);
41    // Start from the 2×2 identity so that `fib(0)` returns 0.
42    let mut acc = Tensor::new(vec![1.0, 0.0, 0.0, 1.0], &[2, 2]);
43    for _ in 0..n {
44        acc = acc.matmul(&q);
45    }
46    // F(n) is the top-right entry of Q^n.
47    acc.get(&[0, 1]).expect("index in bounds") as u64
48}
49
50fn main() {
51    let expected = [1u64, 1, 2, 3, 5, 8, 13, 21, 34, 55];
52
53    print!("F(1..=10) via matrix power =");
54    for n in 1..=10u32 {
55        let f = fib(n);
56        print!(" {f}");
57        assert_eq!(f, expected[(n - 1) as usize]);
58    }
59    println!();
60
61    assert_eq!(fib(0), 0);
62    println!("Fibonacci by matrix power: OK");
63}