File: Mathlib/Data/Nat/Fib/Basic.lean

full_name: Nat.fib
code: /-- Implementation of the fibonacci sequence satisfying
`fib 0 = 0, fib 1 = 1, fib (n + 2) = fib n + fib (n + 1)`.

*Note:* We use a stream iterator for better performance when compared to the naive recursive
implementation.
-/

@[pp_nodot]
def fib (n : ℕ) : ℕ 
goal: ℕ

full_name: Nat.fib_zero
code: @[simp]
theorem fib_zero : fib 0 = 0 
goal: Nat.fib 0 = 0

full_name: Nat.fib_one
code: @[simp]
theorem fib_one : fib 1 = 1 
goal: Nat.fib 1 = 1

full_name: Nat.fib_two
code: @[simp]
theorem fib_two : fib 2 = 1 
goal: Nat.fib 2 = 1

full_name: Nat.fib_add_two
code: /-- Shows that `fib` indeed satisfies the Fibonacci recurrence `Fₙ₊₂ = Fₙ + Fₙ₊₁.` -/
theorem fib_add_two {n : ℕ} : fib (n + 2) = fib n + fib (n + 1) 
goal: Nat.fib (n + 2) = Nat.fib n + Nat.fib (n + 1)

full_name: Nat.fib_add_one
code: lemma fib_add_one : ∀ {n}, n ≠ 0 → fib (n + 1) = fib (n - 1) + fib n
  
goal: n ≠ 0 → Nat.fib (n + 1) = Nat.fib (n - 1) + Nat.fib n

full_name: Nat.fib_le_fib_succ
code: theorem fib_le_fib_succ {n : ℕ} : fib n ≤ fib (n + 1) 
goal: Nat.fib n ≤ Nat.fib (n + 1)

full_name: Nat.fib_mono
code: @[mono]
theorem fib_mono : Monotone fib 
goal: Monotone Nat.fib

full_name: Nat.fib_eq_zero
code: @[simp] lemma fib_eq_zero : ∀ {n}, fib n = 0 ↔ n = 0

goal: Nat.fib n = 0 ↔ n = 0

full_name: Nat.fib_pos
code: @[simp] lemma fib_pos {n : ℕ} : 0 < fib n ↔ 0 < n 
goal: 0 < Nat.fib n ↔ 0 < n

full_name: Nat.fib_add_two_sub_fib_add_one
code: theorem fib_add_two_sub_fib_add_one {n : ℕ} : fib (n + 2) - fib (n + 1) = fib n 
goal: Nat.fib (n + 2) - Nat.fib (n + 1) = Nat.fib n

full_name: Nat.fib_lt_fib_succ
code: theorem fib_lt_fib_succ {n : ℕ} (hn : 2 ≤ n) : fib n < fib (n + 1) 
goal: Nat.fib n < Nat.fib (n + 1)

full_name: Nat.fib_add_two_strictMono
code: /-- `fib (n + 2)` is strictly monotone. -/
theorem fib_add_two_strictMono : StrictMono fun n => fib (n + 2) 
goal: StrictMono fun n => Nat.fib (n + 2)

full_name: Nat.fib_strictMonoOn
code: lemma fib_strictMonoOn : StrictMonoOn fib (Set.Ici 2)
  
goal: StrictMonoOn Nat.fib (Set.Ici 2)

full_name: Nat.fib_lt_fib
code: lemma fib_lt_fib {m : ℕ} (hm : 2 ≤ m) : ∀ {n}, fib m < fib n ↔ m < n
  
goal: Nat.fib m < Nat.fib n ↔ m < n

full_name: Nat.le_fib_self
code: theorem le_fib_self {n : ℕ} (five_le_n : 5 ≤ n) : n ≤ fib n 
goal: n ≤ Nat.fib n

full_name: Nat.le_fib_add_one
code: lemma le_fib_add_one : ∀ n, n ≤ fib n + 1
  
goal: n ≤ Nat.fib n + 1

full_name: Nat.fib_coprime_fib_succ
code: /-- Subsequent Fibonacci numbers are coprime,
  see https://proofwiki.org/wiki/Consecutive_Fibonacci_Numbers_are_Coprime -/
theorem fib_coprime_fib_succ (n : ℕ) : Nat.Coprime (fib n) (fib (n + 1)) 
goal: (Nat.fib n).Coprime (Nat.fib (n + 1))

full_name: Nat.fib_add
code: /-- See https://proofwiki.org/wiki/Fibonacci_Number_in_terms_of_Smaller_Fibonacci_Numbers -/
theorem fib_add (m n : ℕ) : fib (m + n + 1) = fib m * fib n + fib (m + 1) * fib (n + 1) 
goal: Nat.fib (m + n + 1) = Nat.fib m * Nat.fib n + Nat.fib (m + 1) * Nat.fib (n + 1)

full_name: Nat.fib_two_mul
code: theorem fib_two_mul (n : ℕ) : fib (2 * n) = fib n * (2 * fib (n + 1) - fib n) 
goal: Nat.fib (2 * n) = Nat.fib n * (2 * Nat.fib (n + 1) - Nat.fib n)

full_name: Nat.fib_two_mul_add_one
code: theorem fib_two_mul_add_one (n : ℕ) : fib (2 * n + 1) = fib (n + 1) ^ 2 + fib n ^ 2 
goal: Nat.fib (2 * n + 1) = Nat.fib (n + 1) ^ 2 + Nat.fib n ^ 2

full_name: Nat.fib_two_mul_add_two
code: theorem fib_two_mul_add_two (n : ℕ) :
    fib (2 * n + 2) = fib (n + 1) * (2 * fib n + fib (n + 1)) 
goal: Nat.fib (2 * n + 2) = Nat.fib (n + 1) * (2 * Nat.fib n + Nat.fib (n + 1))

full_name: Nat.fastFibAux
code: /-- Computes `(Nat.fib n, Nat.fib (n + 1))` using the binary representation of `n`.
Supports `Nat.fastFib`. -/
def fastFibAux : ℕ → ℕ × ℕ 
goal: ℕ → ℕ × ℕ

full_name: Nat.fastFib
code: /-- Computes `Nat.fib n` using the binary representation of `n`.
Proved to be equal to `Nat.fib` in `Nat.fast_fib_eq`. -/
def fastFib (n : ℕ) : ℕ 
goal: ℕ

full_name: Nat.fast_fib_aux_bit_ff
code: theorem fast_fib_aux_bit_ff (n : ℕ) :
    fastFibAux (bit false n) =
      let p := fastFibAux n
      (p.1 * (2 * p.2 - p.1), p.2 ^ 2 + p.1 ^ 2) 
goal: (Nat.bit false n).fastFibAux =
  let p := n.fastFibAux;
  (p.1 * (2 * p.2 - p.1), p.2 ^ 2 + p.1 ^ 2)

full_name: Nat.fast_fib_aux_bit_tt
code: theorem fast_fib_aux_bit_tt (n : ℕ) :
    fastFibAux (bit true n) =
      let p := fastFibAux n
      (p.2 ^ 2 + p.1 ^ 2, p.2 * (2 * p.1 + p.2)) 
goal: (Nat.bit true n).fastFibAux =
  let p := n.fastFibAux;
  (p.2 ^ 2 + p.1 ^ 2, p.2 * (2 * p.1 + p.2))

full_name: Nat.fast_fib_aux_eq
code: theorem fast_fib_aux_eq (n : ℕ) : fastFibAux n = (fib n, fib (n + 1)) 
goal: n.fastFibAux = (Nat.fib n, Nat.fib (n + 1))

full_name: Nat.fast_fib_eq
code: theorem fast_fib_eq (n : ℕ) : fastFib n = fib n 
goal: n.fastFib = Nat.fib n

full_name: Nat.gcd_fib_add_self
code: theorem gcd_fib_add_self (m n : ℕ) : gcd (fib m) (fib (n + m)) = gcd (fib m) (fib n) 
goal: (Nat.fib m).gcd (Nat.fib (n + m)) = (Nat.fib m).gcd (Nat.fib n)

full_name: Nat.gcd_fib_add_mul_self
code: theorem gcd_fib_add_mul_self (m n : ℕ) : ∀ k, gcd (fib m) (fib (n + k * m)) = gcd (fib m) (fib n)
  
goal: (Nat.fib m).gcd (Nat.fib (n + k * m)) = (Nat.fib m).gcd (Nat.fib n)

full_name: Nat.fib_gcd
code: /-- `fib n` is a strong divisibility sequence,
  see https://proofwiki.org/wiki/GCD_of_Fibonacci_Numbers -/
theorem fib_gcd (m n : ℕ) : fib (gcd m n) = gcd (fib m) (fib n) 
goal: Nat.fib (m.gcd n) = (Nat.fib m).gcd (Nat.fib n)

full_name: Nat.fib_dvd
code: theorem fib_dvd (m n : ℕ) (h : m ∣ n) : fib m ∣ fib n 
goal: Nat.fib m ∣ Nat.fib n

full_name: Nat.fib_succ_eq_sum_choose
code: theorem fib_succ_eq_sum_choose :
    ∀ n : ℕ, fib (n + 1) = ∑ p ∈ Finset.antidiagonal n, choose p.1 p.2 
goal: Nat.fib (n + 1) = ∑ p ∈ Finset.antidiagonal n, p.1.choose p.2

full_name: Nat.fib_succ_eq_succ_sum
code: theorem fib_succ_eq_succ_sum (n : ℕ) : fib (n + 1) = (∑ k ∈ Finset.range n, fib k) + 1 
goal: Nat.fib (n + 1) = ∑ k ∈ Finset.range n, Nat.fib k + 1