Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f67b817
Add tanh_eq
YuvalFilmus Dec 10, 2025
b1471dc
Skeleton of artanh
YuvalFilmus Dec 10, 2025
b8e9898
Show the PartialEquiv
YuvalFilmus Dec 10, 2025
fff1c74
Update Mathlib/Analysis/SpecialFunctions/Artanh.lean
YuvalFilmus Dec 10, 2025
8bce88a
Add alternative formula for artanh
YuvalFilmus Dec 10, 2025
a326306
Merge branch 'master' into artanh
YuvalFilmus Dec 10, 2025
39f0d38
Update Mathlib/Analysis/SpecialFunctions/Artanh.lean
YuvalFilmus Dec 11, 2025
56b5a58
Update Mathlib/Analysis/SpecialFunctions/Artanh.lean
YuvalFilmus Dec 11, 2025
e723cb2
Update Mathlib/Analysis/SpecialFunctions/Artanh.lean
YuvalFilmus Dec 11, 2025
c0652db
Update Mathlib/Analysis/SpecialFunctions/Artanh.lean
YuvalFilmus Dec 11, 2025
b8853f0
Update Mathlib/Analysis/SpecialFunctions/Artanh.lean
YuvalFilmus Dec 11, 2025
7b3d7d0
Golfed artanh_tanh
YuvalFilmus Dec 11, 2025
59a96e0
Extended range of validity of artanh_eq_half_log
YuvalFilmus Dec 11, 2025
27a9273
Monotonicity
YuvalFilmus Dec 11, 2025
c30804f
Positivity and nonnegativity
YuvalFilmus Dec 11, 2025
9c4e3eb
Merge branch 'master' into artanh
YuvalFilmus Dec 11, 2025
4f76d66
Strengthened strictMonoOn_sqrt and moved it to its proper place
YuvalFilmus Dec 11, 2025
69fc9fd
Merge branch 'master' into artanh
YuvalFilmus Dec 11, 2025
adef478
Merge branch 'leanprover-community:master' into artanh
YuvalFilmus Dec 12, 2025
9f4fcec
bijectivity, injectivity, surjectivity
YuvalFilmus Dec 12, 2025
47fcac0
Fixed docstring of artanh
YuvalFilmus Dec 12, 2025
bd8cff6
Remove Real.tanh_injOn
YuvalFilmus Dec 16, 2025
65e86ef
Add artanh_le_artanh_iff, artanh_lt_artanh_iff
YuvalFilmus Dec 16, 2025
9bf0e9f
Moved auxiliary results to Trigonometric.lean
YuvalFilmus Dec 16, 2025
82cbcc3
Fixed bug in proof
YuvalFilmus Dec 16, 2025
445057e
Strengthened artanh_nonneg and added artanh_neg and artanh_nonpos
YuvalFilmus Dec 17, 2025
b17ecf9
Update Mathlib/Analysis/SpecialFunctions/Artanh.lean
YuvalFilmus Dec 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Mathlib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -2076,6 +2076,7 @@ public import Mathlib.Analysis.Real.Spectrum
public import Mathlib.Analysis.Seminorm
public import Mathlib.Analysis.SpecialFunctions.Arcosh
public import Mathlib.Analysis.SpecialFunctions.Arsinh
public import Mathlib.Analysis.SpecialFunctions.Artanh
public import Mathlib.Analysis.SpecialFunctions.Bernstein
public import Mathlib.Analysis.SpecialFunctions.BinaryEntropy
public import Mathlib.Analysis.SpecialFunctions.Choose
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/Analysis/SpecialFunctions/Arcosh.lean
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ theorem tanh_arcosh {x : ℝ} (hx : 1 ≤ x) : tanh (arcosh x) = √(x ^ 2 - 1)

/-- `arcosh` is the left inverse of `cosh` over [0, ∞). -/
theorem arcosh_cosh {x : ℝ} (hx : 0 ≤ x) : arcosh (cosh x) = x := by
rw [arcosh, ← exp_eq_exp, exp_log (by positivity), ← eq_sub_iff_add_eq', exp_sub_cosh,
rw [arcosh, ← exp_eq_exp, exp_log (by positivity), ← eq_sub_iff_add_eq', exp_sub_cosh,
← sq_eq_sq₀ (sqrt_nonneg _) (sinh_nonneg_iff.mpr hx), ← sinh_sq, sq_sqrt (pow_two_nonneg _)]

theorem arcosh_nonneg {x : ℝ} (hx : 1 ≤ x) : 0 ≤ arcosh x := by
Expand Down
124 changes: 124 additions & 0 deletions Mathlib/Analysis/SpecialFunctions/Artanh.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/-
Copyright (c) 2025 Yuval Filmus. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yuval Filmus
-/
module

public import Mathlib.Analysis.SpecialFunctions.Log.Basic

/-!
# Inverse of the tanh function

In this file we define an inverse of tanh as a function from ℝ to (-1, 1).

## Main definitions

- `Real.artanh`: An inverse function of `Real.tanh` as a function from ℝ to (-1, 1).

- `Real.tanhPartialEquiv`: `Real.tanh` as a `PartialEquiv`.

## Main Results

- `Real.tanh_artanh`, `Real.artanh_tanh`: tanh and artanh are inverse in the appropriate domains.

## Tags

artanh, arctanh, argtanh, atanh
-/

@[expose] public section


noncomputable section

open Function Filter Set

open scoped Topology

namespace Real

variable {x y : ℝ}

/-- `artanh` is defined using a logarithm, `arcosh x = log √((1 + x) / (1 - x))`. -/
@[pp_nodot]
def artanh (x : ℝ) :=
log √((1 + x) / (1 - x))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean uses the expression 1 / 2 * log ((1 + x) / (1 - x)) a few times (see #31487) as a stand-in for artanh.

I agree with the choice to go with sqrt so that the junk values outside of the domain will all be zero, but perhaps you should add a lemma for 1 / 2 * log ((1 + x) / (1 - x)) = artanh x for all 0 ≤ x (using Real.log_sqrt and one_div_mul_eq_div). That file should probably import this file and use the new artanh in those places.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a theorem artanh_eq_half_log.
Perhaps the name could be improved.
I don't immediately see how to prove it for all 0 ≤ x.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is quite annoying that positivity doesn't work here (as well as elsewhere in this file).
Why is that the case?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't immediately see how to prove it for all 0 ≤ x.

Oh yes sorry I meant for all x where the thing inside the square root is non-negative.
You can extend the Ioo to Icc:

theorem artanh_eq_half_log {x : ℝ} (hx : x ∈ Icc (-1) 1) :
    artanh x = 1 / 2 * log ((1 + x) / (1 - x)) := by
  rw [artanh, log_sqrt <| div_nonneg (by grind) (by grind), one_div_mul_eq_div]

It is quite annoying that positivity doesn't work here (as well as elsewhere in this file).
Why is that the case?

I think that positivity won't do ring operations, but I'm not sure. It does know how to handle the division if you help it:

theorem artanh_eq_half_log {x : ℝ} (hx : x ∈ Icc (-1) 1) :
    artanh x = 1 / 2 * log ((1 + x) / (1 - x)) := by
  rw [artanh, log_sqrt, one_div_mul_eq_div]
  have : 01 + x := by grind
  have : 01 - x := by grind
  positivity

it just doesn't know how to convert -1 ≤ x to 0 ≤ 1 + x and x ≤ 1 to 0 ≤ 1 - x.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably it doesn't matter, but I'll mention that if one instead chooses artanh x := 1 / 2 * log ((1 + x) / (1 - x)), then the junk values for Real.log guarantee that artanh x⁻¹ = (artanh x)⁻¹ for all x.


theorem artanh_eq_half_log {x : ℝ} (hx : x ∈ Ioo (-1 : ℝ) 1) :
artanh x = 1 / 2 * log ((1 + x) / (1 - x)) := by
rw [artanh, log_sqrt <| le_of_lt <| div_pos (neg_lt_iff_pos_add'.mp hx.1) (sub_pos.mpr hx.2),
one_div_mul_eq_div]

theorem exp_artanh {x : ℝ} (hx : x ∈ Ioo (-1 : ℝ) 1) : exp (artanh x) = √((1 + x) / (1 - x)) :=
exp_log <| sqrt_pos_of_pos <| div_pos (neg_lt_iff_pos_add'.mp hx.1) (sub_pos.mpr hx.2)

@[simp]
theorem artanh_zero : artanh 0 = 0 := by simp [artanh]

theorem sinh_artanh {x : ℝ} (hx : x ∈ Ioo (-1 : ℝ) 1) : sinh (artanh x) = x / √(1 - x ^ 2) := by
have : 1 - x ^ 2 = (1 + x) * (1 - x) := by ring
rw [this, artanh, sinh_eq, exp_neg, exp_log, sqrt_div, sqrt_mul]
· field_simp
rw [sq_sqrt, sq_sqrt]
· ring
· exact le_of_lt <| sub_pos.mpr hx.2
· exact le_of_lt <| neg_lt_iff_pos_add'.mp hx.1
· exact le_of_lt <| neg_lt_iff_pos_add'.mp hx.1
· exact le_of_lt <| neg_lt_iff_pos_add'.mp hx.1
· exact sqrt_pos_of_pos <| div_pos (neg_lt_iff_pos_add'.mp hx.1) (sub_pos.mpr hx.2)

theorem cosh_artanh {x : ℝ} (hx : x ∈ Ioo (-1 : ℝ) 1) : cosh (artanh x) = 1 / √(1 - x ^ 2) := by
have : 1 - x ^ 2 = (1 + x) * (1 - x) := by ring
rw [this, artanh, cosh_eq, exp_neg, exp_log, sqrt_div, sqrt_mul]
· field_simp
rw [sq_sqrt, sq_sqrt]
· ring
· exact le_of_lt <| sub_pos.mpr hx.2
· exact le_of_lt <| neg_lt_iff_pos_add'.mp hx.1
· exact le_of_lt <| neg_lt_iff_pos_add'.mp hx.1
· exact le_of_lt <| neg_lt_iff_pos_add'.mp hx.1
· exact sqrt_pos_of_pos <| div_pos (neg_lt_iff_pos_add'.mp hx.1) (sub_pos.mpr hx.2)

/-- `artanh` is the right inverse of `tanh` over (-1, 1). -/
theorem tanh_artanh {x : ℝ} (hx : x ∈ Ioo (-1 : ℝ) 1) : tanh (artanh x) = x := by
rw [tanh_eq_sinh_div_cosh, sinh_artanh hx, cosh_artanh hx, div_div_div_cancel_right₀, div_one]
apply sqrt_ne_zero'.mpr
rw [show 1 - x ^ 2 = (1 + x) * (1 - x) by ring]
exact mul_pos (neg_lt_iff_pos_add'.mp hx.1) (sub_pos.mpr hx.2)

theorem tanh_lt_one (x : ℝ) : tanh x < 1 := by
rw [tanh_eq]
field_simp
suffices 0 < rexp (-x) by linarith
positivity

theorem neg_one_lt_tanh (x : ℝ) : -1 < tanh x := by
rw [tanh_eq]
field_simp
suffices 0 < rexp x by linarith
positivity

/-- `artanh` is the left inverse of `tanh`. -/
theorem artanh_tanh (x : ℝ) : artanh (tanh x) = x := by
rw [artanh, ← exp_eq_exp, exp_log, ← sq_eq_sq₀, sq_sqrt, tanh_eq, exp_neg]
· field
· exact le_of_lt <| div_pos
(neg_lt_iff_pos_add'.mp (neg_one_lt_tanh x)) (sub_pos.mpr (tanh_lt_one x))
· positivity
· positivity
· exact sqrt_pos_of_pos <| div_pos
(neg_lt_iff_pos_add'.mp (neg_one_lt_tanh x)) (sub_pos.mpr (tanh_lt_one x))

/-- `Real.tanh` as a `PartialEquiv`. -/
def tanhPartialEquiv : PartialEquiv ℝ ℝ where
toFun := tanh
invFun := artanh
source := univ
target := Ioo (-1 : ℝ) 1
map_source' r _ := mem_Ioo.mpr ⟨neg_one_lt_tanh r, tanh_lt_one r⟩
map_target' _ _ := trivial
left_inv' r _ := artanh_tanh r
right_inv' _ hr := tanh_artanh hr

end Real