File: Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean

full_name: Real.Gamma_mul_add_mul_le_rpow_Gamma_mul_rpow_Gamma
code: /-- Log-convexity of the Gamma function on the positive reals (stated in multiplicative form),
proved using the Hölder inequality applied to Euler's integral. -/
theorem Gamma_mul_add_mul_le_rpow_Gamma_mul_rpow_Gamma {s t a b : ℝ} (hs : 0 < s) (ht : 0 < t)
    (ha : 0 < a) (hb : 0 < b) (hab : a + b = 1) :
    Gamma (a * s + b * t) ≤ Gamma s ^ a * Gamma t ^ b 
goal: Real.Gamma (a * s + b * t) ≤ Real.Gamma s ^ a * Real.Gamma t ^ b

full_name: Real.convexOn_log_Gamma
code: theorem convexOn_log_Gamma : ConvexOn ℝ (Ioi 0) (log ∘ Gamma) 
goal: ConvexOn ℝ (Set.Ioi 0) (Real.log ∘ Real.Gamma)

full_name: Real.convexOn_Gamma
code: theorem convexOn_Gamma : ConvexOn ℝ (Ioi 0) Gamma 
goal: ConvexOn ℝ (Set.Ioi 0) Real.Gamma

full_name: Real.BohrMollerup.logGammaSeq
code: /-- The function `n ↦ x log n + log n! - (log x + ... + log (x + n))`, which we will show tends to
`log (Gamma x)` as `n → ∞`. -/
def logGammaSeq (x : ℝ) (n : ℕ) : ℝ 
goal: ℝ

full_name: Real.BohrMollerup.f_nat_eq
code: theorem f_nat_eq (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = f y + log y) (hn : n ≠ 0) :
    f n = f 1 + log (n - 1)! 
goal: f ↑n = f 1 + Real.log ↑(n - 1)!

full_name: Real.BohrMollerup.f_add_nat_eq
code: theorem f_add_nat_eq (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = f y + log y) (hx : 0 < x) (n : ℕ) :
    f (x + n) = f x + ∑ m ∈ Finset.range n, log (x + m) 
goal: f (x + ↑n) = f x + ∑ m ∈ Finset.range n, Real.log (x + ↑m)

full_name: Real.BohrMollerup.f_add_nat_le
code: /-- Linear upper bound for `f (x + n)` on unit interval -/
theorem f_add_nat_le (hf_conv : ConvexOn ℝ (Ioi 0) f)
    (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = f y + log y) (hn : n ≠ 0) (hx : 0 < x) (hx' : x ≤ 1) :
    f (n + x) ≤ f n + x * log n 
goal: f (↑n + x) ≤ f ↑n + x * Real.log ↑n

full_name: Real.BohrMollerup.f_add_nat_ge
code: /-- Linear lower bound for `f (x + n)` on unit interval -/
theorem f_add_nat_ge (hf_conv : ConvexOn ℝ (Ioi 0) f)
    (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = f y + log y) (hn : 2 ≤ n) (hx : 0 < x) :
    f n + x * log (n - 1) ≤ f (n + x) 
goal: f ↑n + x * Real.log (↑n - 1) ≤ f (↑n + x)

full_name: Real.BohrMollerup.logGammaSeq_add_one
code: theorem logGammaSeq_add_one (x : ℝ) (n : ℕ) :
    logGammaSeq (x + 1) n = logGammaSeq x (n + 1) + log x - (x + 1) * (log (n + 1) - log n) 
goal: Real.BohrMollerup.logGammaSeq (x + 1) n =
  Real.BohrMollerup.logGammaSeq x (n + 1) + Real.log x - (x + 1) * (Real.log (↑n + 1) - Real.log ↑n)

full_name: Real.BohrMollerup.le_logGammaSeq
code: theorem le_logGammaSeq (hf_conv : ConvexOn ℝ (Ioi 0) f)
    (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = f y + log y) (hx : 0 < x) (hx' : x ≤ 1) (n : ℕ) :
    f x ≤ f 1 + x * log (n + 1) - x * log n + logGammaSeq x n 
goal: f x ≤ f 1 + x * Real.log (↑n + 1) - x * Real.log ↑n + Real.BohrMollerup.logGammaSeq x n

full_name: Real.BohrMollerup.ge_logGammaSeq
code: theorem ge_logGammaSeq (hf_conv : ConvexOn ℝ (Ioi 0) f)
    (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = f y + log y) (hx : 0 < x) (hn : n ≠ 0) :
    f 1 + logGammaSeq x n ≤ f x 
goal: f 1 + Real.BohrMollerup.logGammaSeq x n ≤ f x

full_name: Real.BohrMollerup.tendsto_logGammaSeq_of_le_one
code: theorem tendsto_logGammaSeq_of_le_one (hf_conv : ConvexOn ℝ (Ioi 0) f)
    (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = f y + log y) (hx : 0 < x) (hx' : x ≤ 1) :
    Tendsto (logGammaSeq x) atTop (𝓝 <| f x - f 1) 
goal: Filter.Tendsto (Real.BohrMollerup.logGammaSeq x) Filter.atTop (𝓝 (f x - f 1))

full_name: Real.BohrMollerup.tendsto_logGammaSeq
code: theorem tendsto_logGammaSeq (hf_conv : ConvexOn ℝ (Ioi 0) f)
    (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = f y + log y) (hx : 0 < x) :
    Tendsto (logGammaSeq x) atTop (𝓝 <| f x - f 1) 
goal: Filter.Tendsto (Real.BohrMollerup.logGammaSeq x) Filter.atTop (𝓝 (f x - f 1))

full_name: Real.BohrMollerup.tendsto_log_gamma
code: theorem tendsto_log_gamma {x : ℝ} (hx : 0 < x) :
    Tendsto (logGammaSeq x) atTop (𝓝 <| log (Gamma x)) 
goal: Filter.Tendsto (Real.BohrMollerup.logGammaSeq x) Filter.atTop (𝓝 (Real.log (Real.Gamma x)))

full_name: Real.eq_Gamma_of_log_convex
code: /-- The **Bohr-Mollerup theorem**: the Gamma function is the *unique* log-convex, positive-valued
function on the positive reals which satisfies `f 1 = 1` and `f (x + 1) = x * f x` for all `x`. -/
theorem eq_Gamma_of_log_convex {f : ℝ → ℝ} (hf_conv : ConvexOn ℝ (Ioi 0) (log ∘ f))
    (hf_feq : ∀ {y : ℝ}, 0 < y → f (y + 1) = y * f y) (hf_pos : ∀ {y : ℝ}, 0 < y → 0 < f y)
    (hf_one : f 1 = 1) : EqOn f Gamma (Ioi (0 : ℝ)) 
goal: Set.EqOn f Real.Gamma (Set.Ioi 0)

full_name: Real.Gamma_two
code: theorem Gamma_two : Gamma 2 = 1 
goal: Real.Gamma 2 = 1

full_name: Real.Gamma_three_div_two_lt_one
code: theorem Gamma_three_div_two_lt_one : Gamma (3 / 2) < 1 
goal: Real.Gamma (3 / 2) < 1

full_name: Real.Gamma_strictMonoOn_Ici
code: theorem Gamma_strictMonoOn_Ici : StrictMonoOn Gamma (Ici 2) 
goal: StrictMonoOn Real.Gamma (Set.Ici 2)

full_name: Real.doublingGamma
code: /-- Auxiliary definition for the doubling formula (we'll show this is equal to `Gamma s`) -/
def doublingGamma (s : ℝ) : ℝ 
goal: ℝ

full_name: Real.doublingGamma_add_one
code: theorem doublingGamma_add_one (s : ℝ) (hs : s ≠ 0) :
    doublingGamma (s + 1) = s * doublingGamma s 
goal: (s + 1).doublingGamma = s * s.doublingGamma

full_name: Real.doublingGamma_one
code: theorem doublingGamma_one : doublingGamma 1 = 1 
goal: Real.doublingGamma 1 = 1

full_name: Real.log_doublingGamma_eq
code: theorem log_doublingGamma_eq :
    EqOn (log ∘ doublingGamma)
      (fun s => log (Gamma (s / 2)) + log (Gamma (s / 2 + 1 / 2)) + s * log 2 - log (2 * √π))
      (Ioi 0) 
goal: Set.EqOn (Real.log ∘ Real.doublingGamma)
  (fun s => Real.log (Real.Gamma (s / 2)) + Real.log (Real.Gamma (s / 2 + 1 / 2)) + s * Real.log 2 - Real.log (2 * √π))
  (Set.Ioi 0)

full_name: Real.doublingGamma_log_convex_Ioi
code: theorem doublingGamma_log_convex_Ioi : ConvexOn ℝ (Ioi (0 : ℝ)) (log ∘ doublingGamma) 
goal: ConvexOn ℝ (Set.Ioi 0) (Real.log ∘ Real.doublingGamma)

full_name: Real.doublingGamma_eq_Gamma
code: theorem doublingGamma_eq_Gamma {s : ℝ} (hs : 0 < s) : doublingGamma s = Gamma s 
goal: s.doublingGamma = Real.Gamma s

full_name: Real.Gamma_mul_Gamma_add_half_of_pos
code: /-- Legendre's doubling formula for the Gamma function, for positive real arguments. Note that
we shall later prove this for all `s` as `Real.Gamma_mul_Gamma_add_half` (superseding this result)
but this result is needed as an intermediate step. -/
theorem Gamma_mul_Gamma_add_half_of_pos {s : ℝ} (hs : 0 < s) :
    Gamma s * Gamma (s + 1 / 2) = Gamma (2 * s) * 2 ^ (1 - 2 * s) * √π 
goal: Real.Gamma s * Real.Gamma (s + 1 / 2) = Real.Gamma (2 * s) * 2 ^ (1 - 2 * s) * √π