Skip to content

Instantly share code, notes, and snippets.

@digama0
Created October 27, 2023 22:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save digama0/fd3be96cd82e92535dbb420e86a8b1be to your computer and use it in GitHub Desktop.
Save digama0/fd3be96cd82e92535dbb420e86a8b1be to your computer and use it in GitHub Desktop.
Approximation tactic in lean4
import Mathlib.Tactic.NormNum
import Mathlib.Data.Real.Basic
import Mathlib.Tactic.SlimCheck
namespace Tactic
namespace Approx
def RoundDown (a b : ℤ) : Prop := 2 * b ≤ a
#align tactic.approx.round_down Tactic.Approx.RoundDown
def RoundUp (a b : ℤ) : Prop := a ≤ 2 * b
#align tactic.approx.round_up Tactic.Approx.RoundUp
theorem RoundDown.weak {a b a' b'} (h : RoundDown a b) (ha : a ≤ a') (hb : b' ≤ b) :
RoundDown a' b' :=
((mul_le_mul_left two_pos (α := ℤ)).2 hb).trans <| le_trans h ha
#align tactic.approx.round_down.weak Tactic.Approx.RoundDown.weak
theorem RoundUp.weak {a b a' b'} (h : RoundUp a b) (ha : a' ≤ a) (hb : b ≤ b') : RoundUp a' b' :=
ha.trans <| le_trans h <| (mul_le_mul_left two_pos (α := ℤ)).2 hb
#align tactic.approx.round_up.weak Tactic.Approx.RoundUp.weak
theorem RoundDown.zero : RoundDown 0 0 := by unfold RoundDown; decide
#align tactic.approx.round_down.zero Tactic.Approx.RoundDown.zero
theorem RoundDown.one : RoundDown 1 0 := by unfold RoundDown; decide
#align tactic.approx.round_down.one Tactic.Approx.RoundDown.one
theorem RoundDown.neg_one : RoundDown (-1) (-1) := by unfold RoundDown; decide
#align tactic.approx.round_down.neg_one Tactic.Approx.RoundDown.neg_one
theorem RoundDown.bit0_pos (a) : RoundDown (bit0 a) a :=
(bit0_eq_two_mul _).ge
#align tactic.approx.round_down.bit0_pos Tactic.Approx.RoundDown.bit0_pos
theorem RoundDown.bit0_neg (a) : RoundDown (-bit0 a) (-a) := by
rw [← _root_.bit0_neg]; apply RoundDown.bit0_pos
#align tactic.approx.round_down.bit0_neg Tactic.Approx.RoundDown.bit0_neg
theorem RoundDown.bit1_pos (a) : RoundDown (bit1 a) a :=
sorry -- (RoundDown.bit0_pos a).weak (NormNum.le_bit0_bit1 _ _ le_rfl) le_rfl
#align tactic.approx.round_down.bit1_pos Tactic.Approx.RoundDown.bit1_pos
theorem RoundDown.bit1_neg {a b} (h : a + 1 = b) : RoundDown (-bit1 a) (-b) := by
simp [RoundDown, ← bit0_eq_two_mul, bit0_neg]
sorry -- apply NormNum.le_bit1_bit0; exact_mod_cast h.le
#align tactic.approx.round_down.bit1_neg Tactic.Approx.RoundDown.bit1_neg
theorem RoundUp.zero : RoundUp 0 0 := by unfold RoundUp; decide
#align tactic.approx.round_up.zero Tactic.Approx.RoundUp.zero
theorem RoundUp.one : RoundUp 1 1 := by unfold RoundUp; decide
#align tactic.approx.round_up.one Tactic.Approx.RoundUp.one
theorem RoundUp.neg_one : RoundUp (-1) 0 := by unfold RoundUp; decide
#align tactic.approx.round_up.neg_one Tactic.Approx.RoundUp.neg_one
theorem RoundUp.bit0_pos (a) : RoundUp (bit0 a) a :=
(bit0_eq_two_mul _).le
#align tactic.approx.round_up.bit0_pos Tactic.Approx.RoundUp.bit0_pos
theorem RoundUp.bit0_neg (a) : RoundUp (-bit0 a) (-a) := by
rw [← _root_.bit0_neg]; apply RoundUp.bit0_pos
#align tactic.approx.round_up.bit0_neg Tactic.Approx.RoundUp.bit0_neg
theorem RoundUp.bit1_pos {a b} (h : a + 1 = b) : RoundUp (bit1 a) b :=
by
simp [RoundUp, ← bit0_eq_two_mul]
sorry -- apply NormNum.le_bit1_bit0; exact_mod_cast h.le
#align tactic.approx.round_up.bit1_pos Tactic.Approx.RoundUp.bit1_pos
theorem RoundUp.bit1_neg (a) : RoundUp (-bit1 a) (-a) :=
sorry -- (RoundUp.bit0_neg a).weak (neg_le_neg <| NormNum.le_bit0_bit1 _ _ le_rfl) le_rfl
#align tactic.approx.round_up.bit1_neg Tactic.Approx.RoundUp.bit1_neg
def Approx (n lo hi : ℤ) (x : ℝ) : Prop :=
(lo / 2 ^ n : ℝ) ≤ x ∧ x ≤ hi / 2 ^ n
#align tactic.approx.approx Tactic.Approx.Approx
theorem bit0_neg (a : ℤ) : bit0 (-a) = -bit0 a := _root_.bit0_neg _
#align tactic.approx.bit0_neg Tactic.Approx.bit0_neg
theorem Approx.up' {n lo hi lo' hi' : ℤ} {x : ℝ} (hlo : 2 * lo = lo') (hhi : 2 * hi = hi') :
Approx (n + 1) lo' hi' x ↔ Approx n lo hi x := by
simp [Approx, ← hlo, ← hhi, zpow_add_one₀ (two_ne_zero' ℝ), mul_comm, fun a b =>
mul_div_mul_left a b (two_ne_zero' ℝ)]
sorry
#align tactic.approx.approx.up' Tactic.Approx.Approx.up'
theorem Approx.le {n lo hi : ℤ} {x : ℝ} (h : Approx n lo hi x) : lo ≤ hi :=
by
rw [← @Int.cast_le ℝ, ← div_le_div_right (zpow_pos_of_pos (two_pos : 0 < (2 : ℝ)) n)]
exact h.1.trans h.2
#align tactic.approx.approx.le Tactic.Approx.Approx.le
theorem Approx.weak {n lo hi lo' hi' : ℤ} {x : ℝ} (h : Approx n lo hi x) (hlo : lo' ≤ lo)
(hhi : hi ≤ hi') : Approx n lo' hi' x :=
by
rw [← @Int.cast_le ℝ, ← div_le_div_right (zpow_pos_of_pos (two_pos : 0 < (2 : ℝ)) n)] at hlo hhi
exact ⟨hlo.trans h.1, h.2.trans hhi⟩
#align tactic.approx.approx.weak Tactic.Approx.Approx.weak
theorem Approx.to_le {n xlo xhi ylo yhi : ℤ} {x y : ℝ} (hx : Approx n xlo xhi x)
(hy : Approx n ylo yhi y) (h : xhi ≤ ylo) : x ≤ y :=
haveI n0 := zpow_pos_of_pos (two_pos : 0 < (2 : ℝ)) n
hx.2.trans (((div_le_div_right n0).2 (Int.cast_le.2 h)).trans hy.1)
#align tactic.approx.approx.to_le Tactic.Approx.Approx.to_le
theorem Approx.to_lt {n xlo xhi ylo yhi : ℤ} {x y : ℝ} (hx : Approx n xlo xhi x)
(hy : Approx n ylo yhi y) (h : xhi < ylo) : x < y :=
haveI n0 := zpow_pos_of_pos (two_pos : 0 < (2 : ℝ)) n
hx.2.trans_lt (((div_lt_div_right n0).2 (Int.cast_lt.2 h)).trans_le hy.1)
#align tactic.approx.approx.to_lt Tactic.Approx.Approx.to_lt
theorem Approx.to_lt₂ {n xlo xhi ylo yhi zlo zhi : ℤ} {x y z : ℝ} (hx : Approx n xlo xhi x)
(hy : Approx n ylo yhi y) (hz : Approx n zlo zhi z) (h₁ : xhi < ylo) (h₂ : yhi < zlo) :
x < y ∧ y < z :=
⟨hx.to_lt hy h₁, hy.to_lt hz h₂⟩
#align tactic.approx.approx.to_lt₂ Tactic.Approx.Approx.to_lt₂
theorem Approx.of_exact {n a : ℤ} {x x' : ℝ} (hx : Approx n a a x) (h : (a : ℝ) / 2 ^ n = x') :
x = x' :=
(le_antisymm hx.2 hx.1).trans h
#align tactic.approx.approx.of_exact Tactic.Approx.Approx.of_exact
theorem Approx.approx {n lo hi lo' hi' zlo zhi : ℤ} {x y z : ℝ} (hx : Approx n lo hi x)
(xy : |x - y| ≤ z) (hz : Approx n zlo zhi z) (hlo : lo - zhi = lo') (hhi : hi + zhi = hi') :
Approx n lo' hi' y :=
by
obtain ⟨h₁, h₂⟩ := abs_sub_le_iff.1 (xy.trans hz.2)
constructor
· rw [← hlo, Int.cast_sub, ← div_sub_div_same]
exact (sub_le_sub_right hx.1 _).trans (sub_le_comm.1 h₁)
· rw [← hhi, Int.cast_add, ← div_add_div_same]
refine' le_trans (sub_le_iff_le_add'.1 h₂) (add_le_add_right hx.2 _)
#align tactic.approx.approx.approx Tactic.Approx.Approx.approx
theorem Approx.of_integer {n ll lo hi hh z zl zr : ℤ} {x : ℝ} (hx : Approx n lo hi x)
(ezl : z - 1 = zl) (ezr : z + 1 = zr) (hzl : Approx n ll ll zl) (hzr : Approx n hh hh zr)
(h₁ : ll < lo) (h₂ : hi < hh) (h : ∃ z : ℤ, x = z) : x = z :=
by
obtain ⟨rfl, rfl, ⟨a, rfl⟩⟩ := ezl, ezr, h
congr;
exact
le_antisymm (Int.lt_add_one_iff.1 (Int.cast_lt.1 (hx.to_lt hzr h₂)))
(Int.sub_one_lt_iff.1 (Int.cast_lt.1 (hzl.to_lt hx h₁)))
#align tactic.approx.approx.of_integer Tactic.Approx.Approx.of_integer
theorem Approx.up {n lo hi lo' hi' : ℤ} {x : ℝ} (h : Approx n lo hi x) (hlo : bit0 lo = lo')
(hhi : bit0 hi = hi') : Approx (n + 1) lo' hi' x := by
rw [bit0_eq_two_mul] at hlo hhi; exact (Approx.up' hlo hhi).2 h
#align tactic.approx.approx.up Tactic.Approx.Approx.up
theorem Approx.down {n lo hi lo' hi' : ℤ} {x : ℝ} (h : Approx n lo hi x) (hlo : RoundDown lo lo')
(hhi : RoundUp hi hi') : Approx (n - 1) lo' hi' x :=
by
have := h.weak hlo hhi
rwa [← sub_add_cancel n 1, Approx.up' rfl rfl] at this
#align tactic.approx.approx.down Tactic.Approx.Approx.down
theorem Approx.assume {n ll lh hl hh : ℤ} {xl x xh : ℝ} (hxl : Approx n ll lh xl)
(hxh : Approx n hl hh xh) (hlo : xl ≤ x) (hhi : x ≤ xh) : Approx n ll hh x :=
⟨le_trans hxl.1 hlo, le_trans hhi hxh.2⟩
#align tactic.approx.approx.assume Tactic.Approx.Approx.assume
theorem Approx.eq_zero (n) {x} : Approx n 0 0 x ↔ x = 0 := by
simp [Approx, le_antisymm_iff, and_comm]
#align tactic.approx.approx.eq_zero Tactic.Approx.Approx.eq_zero
theorem Approx.zero (n) : Approx n 0 0 0 :=
(Approx.eq_zero _).2 rfl
#align tactic.approx.approx.zero Tactic.Approx.Approx.zero
theorem Approx.const {a : ℤ} {x : ℝ} (h : ↑a = x) : Approx 0 a a x := by simp [Approx, ← h]
#align tactic.approx.approx.const Tactic.Approx.Approx.const
theorem Approx.neg {n lo hi lo' hi' : ℤ} {x : ℝ} (h : Approx n lo hi x) (hlo : -lo = hi')
(hhi : -hi = lo') : Approx n lo' hi' (-x) := by
simpa [Approx, ← hlo, ← hhi, neg_div, and_comm] using h
#align tactic.approx.approx.neg Tactic.Approx.Approx.neg
theorem Approx.add {n xlo xhi ylo yhi lo hi : ℤ} {x y : ℝ} (hx : Approx n xlo xhi x)
(hy : Approx n ylo yhi y) (hlo : xlo + ylo = lo) (hhi : xhi + yhi = hi) :
Approx n lo hi (x + y) := by
simpa [Approx, ← hlo, ← hhi, add_div] using
And.intro (add_le_add hx.1 hy.1) (add_le_add hx.2 hy.2)
#align tactic.approx.approx.add Tactic.Approx.Approx.add
theorem Approx.sub {n xlo xhi ylo yhi lo hi : ℤ} {x y : ℝ} (hx : Approx n xlo xhi x)
(hy : Approx n ylo yhi y) (hlo : xlo - yhi = lo) (hhi : xhi - ylo = hi) :
Approx n lo hi (x - y) :=
Approx.add hx (Approx.neg hy rfl rfl) hlo hhi
#align tactic.approx.approx.sub Tactic.Approx.Approx.sub
def MulBound (xlo xhi ylo yhi lo hi : ℤ) : Prop :=
xlo ≤ xhi → ylo ≤ yhi →
(lo ≤ xlo * ylo ∧ xlo * ylo ≤ hi) ∧ (lo ≤ xlo * yhi ∧ xlo * yhi ≤ hi) ∧
(lo ≤ xhi * ylo ∧ xhi * ylo ≤ hi) ∧ (lo ≤ xhi * yhi ∧ xhi * yhi ≤ hi)
#align tactic.approx.mul_bound Tactic.Approx.MulBound
theorem MulBound.exact {x y z : ℤ} (h : x * y = z) : MulBound x x y y z z := fun hx hy => by
suffices h; exact ⟨h, h, h, h⟩; exact ⟨h.ge, h.le⟩
#align tactic.approx.mul_bound.exact Tactic.Approx.MulBound.exact
theorem MulBound.pos_pos {xlo xhi ylo yhi lo hi : ℤ} (x0 : 0 ≤ xlo) (y0 : 0 ≤ ylo)
(hlo : xlo * ylo = lo) (hhi : xhi * yhi = hi) : MulBound xlo xhi ylo yhi lo hi := fun hx hy =>
by
have lll := hlo.ge; have hhh := hhi.le
have llh := lll.trans (mul_le_mul_of_nonneg_left hy x0)
have lhl := lll.trans (mul_le_mul_of_nonneg_right hx y0)
have lhh := lhl.trans (mul_le_mul_of_nonneg_left hy (x0.trans hx))
have hhl := (mul_le_mul_of_nonneg_left hy (x0.trans hx)).trans hhh
have hlh := (mul_le_mul_of_nonneg_right hx (y0.trans hy)).trans hhh
have hll := (mul_le_mul_of_nonneg_right hx y0).trans hhl
exact ⟨⟨lll, hll⟩, ⟨llh, hlh⟩, ⟨lhl, hhl⟩, ⟨lhh, hhh⟩⟩
#align tactic.approx.mul_bound.pos_pos Tactic.Approx.MulBound.pos_pos
theorem MulBound.pos_neg {xlo xhi ylo yhi lo hi : ℤ} (x0 : 0 ≤ xlo) (y0 : yhi ≤ 0)
(hlo : xhi * ylo = lo) (hhi : xlo * yhi = hi) : MulBound xlo xhi ylo yhi lo hi := fun hx hy =>
by
have lhl := hlo.ge; have hlh := hhi.le
have lll := lhl.trans (mul_le_mul_of_nonpos_right hx (hy.trans y0))
have llh := lll.trans (mul_le_mul_of_nonneg_left hy x0)
have lhh := lhl.trans (mul_le_mul_of_nonneg_left hy (x0.trans hx))
have hhh := (mul_le_mul_of_nonpos_right hx y0).trans hlh
have hhl := (mul_le_mul_of_nonneg_left hy (x0.trans hx)).trans hhh
have hll := (mul_le_mul_of_nonneg_left hy x0).trans hlh
exact ⟨⟨lll, hll⟩, ⟨llh, hlh⟩, ⟨lhl, hhl⟩, ⟨lhh, hhh⟩⟩
#align tactic.approx.mul_bound.pos_neg Tactic.Approx.MulBound.pos_neg
theorem MulBound.neg_pos {xlo xhi ylo yhi lo hi : ℤ} (x0 : xhi ≤ 0) (y0 : 0 ≤ ylo)
(hlo : xlo * yhi = lo) (hhi : xhi * ylo = hi) : MulBound xlo xhi ylo yhi lo hi := fun hx hy =>
by
have llh := hlo.ge; have hhl := hhi.le
have lll := llh.trans (mul_le_mul_of_nonpos_left hy (hx.trans x0))
have lhl := lll.trans (mul_le_mul_of_nonneg_right hx y0)
have lhh := llh.trans (mul_le_mul_of_nonneg_right hx (y0.trans hy))
have hhh := (mul_le_mul_of_nonpos_left hy x0).trans hhl
have hlh := (mul_le_mul_of_nonneg_right hx (y0.trans hy)).trans hhh
have hll := (mul_le_mul_of_nonneg_right hx y0).trans hhl
exact ⟨⟨lll, hll⟩, ⟨llh, hlh⟩, ⟨lhl, hhl⟩, ⟨lhh, hhh⟩⟩
#align tactic.approx.mul_bound.neg_pos Tactic.Approx.MulBound.neg_pos
theorem MulBound.neg_neg {xlo xhi ylo yhi lo hi : ℤ} (x0 : xhi ≤ 0) (y0 : yhi ≤ 0)
(hlo : xhi * yhi = lo) (hhi : xlo * ylo = hi) : MulBound xlo xhi ylo yhi lo hi := fun hx hy =>
by
have lhh := hlo.ge; have hll := hhi.le
have lhl := lhh.trans (mul_le_mul_of_nonpos_left hy x0)
have llh := lhh.trans (mul_le_mul_of_nonpos_right hx y0)
have lll := llh.trans (mul_le_mul_of_nonpos_left hy (hx.trans x0))
have hlh := (mul_le_mul_of_nonpos_left hy (hx.trans x0)).trans hll
have hhl := (mul_le_mul_of_nonpos_right hx (hy.trans y0)).trans hll
have hhh := (mul_le_mul_of_nonpos_right hx y0).trans hlh
exact ⟨⟨lll, hll⟩, ⟨llh, hlh⟩, ⟨lhl, hhl⟩, ⟨lhh, hhh⟩⟩
#align tactic.approx.mul_bound.neg_neg Tactic.Approx.MulBound.neg_neg
theorem MulBound.mk {xlo xhi ylo yhi ll lh hl hh lo hi : ℤ} (ell : xlo * ylo = ll)
(elh : xlo * yhi = lh) (ehl : xhi * ylo = hl) (ehh : xhi * yhi = hh) (lll : lo ≤ ll)
(hll : ll ≤ hi) (llh : lo ≤ lh) (hlh : lh ≤ hi) (lhl : lo ≤ hl) (hhl : hl ≤ hi) (lhh : lo ≤ hh)
(hhh : hh ≤ hi) : MulBound xlo xhi ylo yhi lo hi := fun hx hy => by
rw [ell, elh, ehl, ehh]
exact ⟨⟨lll, hll⟩, ⟨llh, hlh⟩, ⟨lhl, hhl⟩, ⟨lhh, hhh⟩⟩
#align tactic.approx.mul_bound.mk Tactic.Approx.MulBound.mk
theorem Approx.mul {m n xlo xhi ylo yhi lo hi : ℤ} {x y : ℝ} (hx : Approx m xlo xhi x)
(hy : Approx n ylo yhi y) (hbd : MulBound xlo xhi ylo yhi lo hi) :
Approx (m + n) lo hi (x * y) := by
obtain ⟨⟨lll, hll⟩, ⟨llh, hlh⟩, ⟨lhl, hhl⟩, ⟨lhh, hhh⟩⟩ := hbd hx.le hy.le
have : ∀ a b : ℤ, (↑(a * b) : ℝ) / 2 ^ (m + n) = a / 2 ^ m * (b / 2 ^ n) := by
intros; rw [zpow_add₀ (two_ne_zero' ℝ), Int.cast_mul, mul_div_mul_comm]
rw [← @Int.cast_le ℝ, ← div_le_div_right (zpow_pos_of_pos (two_pos : 0 < (2 : ℝ)) (m + n)),
this] at lll hll llh hlh lhl hhl lhh hhh
obtain x0 | x0 := le_total x 0 <;> constructor
· refine' le_trans _ (mul_le_mul_of_nonpos_left hy.2 x0)
obtain y0 | y0 := le_total ((yhi : ℝ) / 2 ^ n) 0
· exact le_trans lhh (mul_le_mul_of_nonpos_right hx.2 y0)
· exact le_trans llh (mul_le_mul_of_nonneg_right hx.1 y0)
· refine' le_trans (mul_le_mul_of_nonpos_left hy.1 x0) _
obtain y0 | y0 := le_total ((ylo : ℝ) / 2 ^ n) 0
· exact le_trans (mul_le_mul_of_nonpos_right hx.1 y0) hll
· exact le_trans (mul_le_mul_of_nonneg_right hx.2 y0) hhl
· refine' le_trans _ (mul_le_mul_of_nonneg_left hy.1 x0)
obtain y0 | y0 := le_total ((ylo : ℝ) / 2 ^ n) 0
· exact le_trans lhl (mul_le_mul_of_nonpos_right hx.2 y0)
· exact le_trans lll (mul_le_mul_of_nonneg_right hx.1 y0)
· refine' le_trans (mul_le_mul_of_nonneg_left hy.2 x0) _
obtain y0 | y0 := le_total ((yhi : ℝ) / 2 ^ n) 0
· exact le_trans (mul_le_mul_of_nonpos_right hx.1 y0) hlh
· exact le_trans (mul_le_mul_of_nonneg_right hx.2 y0) hhh
#align tactic.approx.approx.mul Tactic.Approx.Approx.mul
theorem Approx.div {m n xlo xhi ylo yhi lo hi : ℤ} {x y : ℝ} (hx : Approx m xlo xhi x)
(hy : Approx n ylo yhi y⁻¹) (hbd : MulBound xlo xhi ylo yhi lo hi) :
Approx (m + n) lo hi (x / y) :=
Approx.mul hx hy hbd
#align tactic.approx.approx.div Tactic.Approx.Approx.div
theorem Approx.inv_lem {m n lo hi lo' hi' : ℤ} {x p : ℝ} (hx : Approx m lo hi x)
(hp : p = 2 ^ (m + n))
(H : 0 < lo ∧ p ≤ ↑(lo * hi') ∧ ↑(hi * lo') ≤ p ∨ hi < 0 ∧ p ≤ ↑(hi * lo') ∧ ↑(lo * hi') ≤ p) :
Approx n lo' hi' x⁻¹ := by
have two_pos := (two_pos : 0 < (2 : ℝ))
rw [zpow_add₀ two_pos.ne'] at hp
have mn0 : (0 : ℝ) < 2 ^ m * 2 ^ n :=
mul_pos (zpow_pos_of_pos two_pos _) (zpow_pos_of_pos two_pos _)
obtain ⟨x0, hlo, hhi⟩ | ⟨x0, hlo, hhi⟩ := H <;> rw [Int.cast_mul, hp] at hlo hhi <;>
rw [← div_le_one mn0, ← div_mul_div_comm] at hhi <;>
rw [← one_le_div mn0, ← div_mul_div_comm] at hlo <;>
rw [← @Int.cast_lt ℝ, ← div_lt_div_right (zpow_pos_of_pos two_pos m), Int.cast_zero,
zero_div] at x0
· have x0' := x0.trans_le hx.1; constructor
· obtain lo0 | lo0 := le_total ((lo' : ℝ) / 2 ^ n) 0
· exact le_trans lo0 (inv_pos.2 x0').le
rw [← one_div, le_div_iff' x0']
exact le_trans (mul_le_mul_of_nonneg_right hx.2 lo0) hhi
· have hi0 : 0 ≤ (hi' : ℝ) / 2 ^ n :=
by
rw [← div_le_iff' x0, one_div] at hlo
exact le_trans (inv_nonneg.2 x0.le) hlo
rw [← one_div, div_le_iff' x0']
exact le_trans hlo (mul_le_mul_of_nonneg_right hx.1 hi0)
· have x0' := hx.2.trans_lt x0; constructor
· have lo0 : (lo' : ℝ) / 2 ^ n ≤ 0 :=
by
rw [← le_div_iff_of_neg' x0, one_div] at hlo
exact le_trans hlo (inv_nonpos.2 x0.le)
rw [← one_div, le_div_iff_of_neg' x0']
refine' le_trans hlo (mul_le_mul_of_nonpos_right hx.2 lo0)
· obtain hi0 | hi0 := le_total 0 ((hi' : ℝ) / 2 ^ n)
· exact le_trans (inv_lt_zero.2 x0').le hi0
rw [← one_div, div_le_iff_of_neg' x0']
exact le_trans (mul_le_mul_of_nonpos_right hx.1 hi0) hhi
#align tactic.approx.approx.inv_lem Tactic.Approx.Approx.inv_lem
theorem Approx.inv_lem' {m n lo hi lo' hi' lh hl p2 : ℤ} {x : ℝ} {p : ℕ} (hx : Approx m lo hi x)
(hp : (p : ℤ) = m + n) (hp2 : 2 ^ p = p2) (hlh : lo * hi' = lh) (hhl : hi * lo' = hl)
(H : 0 < lo ∧ p2 ≤ lh ∧ hl ≤ p2 ∨ hi < 0 ∧ p2 ≤ hl ∧ lh ≤ p2) : Approx n lo' hi' x⁻¹ :=
by
substs hp2 hlh hhl
have : ((2 ^ p : ℤ) : ℝ) = 2 ^ (m + n) := by rw [← hp]; norm_cast
exact Approx.inv_lem hx this (by simpa only [Int.cast_le] using H)
#align tactic.approx.approx.inv_lem' Tactic.Approx.Approx.inv_lem'
nonrec theorem Approx.inv_zero {m n : ℤ} {x : ℝ} (hx : Approx m 0 0 x) : Approx n 0 0 x⁻¹ := by
simp only [(Approx.eq_zero _).1 hx, inv_zero, Approx.zero]
#align tactic.approx.approx.inv_zero Tactic.Approx.Approx.inv_zero
theorem Approx.inv_pos {m n lo hi lo' hi' lh hl p2 : ℤ} {x : ℝ} {p : ℕ} (hx : Approx m lo hi x)
(hp : (p : ℤ) = m + n) (x0 : 0 < lo) (hp2 : 2 ^ p = p2) (hlh : lo * hi' = lh)
(hhl : hi * lo' = hl) (hlo : p2 ≤ lh) (hhi : hl ≤ p2) : Approx n lo' hi' x⁻¹ :=
Approx.inv_lem' hx hp hp2 hlh hhl (Or.inl ⟨x0, hlo, hhi⟩)
#align tactic.approx.approx.inv_pos Tactic.Approx.Approx.inv_pos
theorem Approx.inv_neg {m n lo hi lo' hi' lh hl p2 : ℤ} {x : ℝ} {p : ℕ} (hx : Approx m lo hi x)
(hp : (p : ℤ) = m + n) (x0 : hi < 0) (hp2 : 2 ^ p = p2) (hlh : lo * hi' = lh)
(hhl : hi * lo' = hl) (hlo : p2 ≤ hl) (hhi : lh ≤ p2) : Approx n lo' hi' x⁻¹ :=
Approx.inv_lem' hx hp hp2 hlh hhl (Or.inr ⟨x0, hlo, hhi⟩)
#align tactic.approx.approx.inv_neg Tactic.Approx.Approx.inv_neg
theorem Approx.inv_triv_pos {m n lo hi : ℤ} {x : ℝ} (hx : Approx m lo hi x)
(hp : decide (m + n ≤ 0) = true) (x0 : 0 < lo) : Approx n 0 1 x⁻¹ :=
by
replace hp := Bool.of_decide_true hp
refine' Approx.inv_lem hx rfl (Or.inl ⟨x0, _, _⟩) <;> simp
· refine' le_trans _ (Int.cast_le.2 (Int.add_one_le_iff.2 x0))
simpa only [zpow_zero, Int.cast_one, zero_add] using zpow_le_of_le one_le_two hp
· exact (zpow_pos_of_pos (two_pos : 0 < (2 : ℝ)) _).le
#align tactic.approx.approx.inv_triv_pos Tactic.Approx.Approx.inv_triv_pos
theorem Approx.inv_triv_neg {m n lo hi : ℤ} {x : ℝ} (hx : Approx m lo hi x)
(hp : decide (m + n ≤ 0) = true) (x0 : hi < 0) : Approx n (-1) 0 x⁻¹ :=
by
replace hp := Bool.of_decide_true hp
refine' Approx.inv_lem hx rfl (Or.inr ⟨x0, _, _⟩) <;> simp
· rw [← Int.cast_neg]; rw [← neg_pos] at x0
refine' le_trans _ (Int.cast_le.2 (Int.add_one_le_iff.2 x0))
simpa only [zpow_zero, Int.cast_one, zero_add] using zpow_le_of_le one_le_two hp
· exact (zpow_pos_of_pos (two_pos : 0 < (2 : ℝ)) _).le
#align tactic.approx.approx.inv_triv_neg Tactic.Approx.Approx.inv_triv_neg
open Tactic Mathlib.Meta.NormNum
-- /-- Given `a`, proves `(b, |- round_down a b)` -/
-- unsafe def prove_round_down (ic : instance_cache) (a : expr) :
-- tactic (instance_cache × expr × expr) :=
-- match match_neg a with
-- | some a =>
-- match match_numeral a with
-- | match_numeral_result.one => pure (ic, q((-1 : ℤ)), q(RoundDown.neg_one))
-- | match_numeral_result.bit0 a =>
-- pure (ic, q((Neg.neg : ℤ → ℤ)).mk_app [a], q(RoundDown.bit0_neg).mk_app [a])
-- | match_numeral_result.bit1 a => do
-- let (ic, b, h) ← prove_succ' ic a
-- pure (ic, q((Neg.neg : ℤ → ℤ)).mk_app [b], q(@RoundDown.bit1_neg).mk_app [a, b, h])
-- | _ => failed
-- | none =>
-- match match_numeral a with
-- | match_numeral_result.zero => pure (ic, q((0 : ℤ)), q(RoundDown.zero))
-- | match_numeral_result.one => pure (ic, q((0 : ℤ)), q(RoundDown.one))
-- | match_numeral_result.bit0 a => pure (ic, a, q(RoundDown.bit0_pos).mk_app [a])
-- | match_numeral_result.bit1 a => pure (ic, a, q(@RoundDown.bit1_pos).mk_app [a])
-- | _ => failed
-- #align tactic.approx.prove_round_down Tactic.Approx.prove_round_down
-- /-- Given `a`, proves `(b, |- round_up a b)` -/
-- unsafe def prove_round_up (ic : instance_cache) (a : expr) :
-- tactic (instance_cache × expr × expr) :=
-- match match_neg a with
-- | some a =>
-- match match_numeral a with
-- | match_numeral_result.one => pure (ic, q((0 : ℤ)), q(RoundUp.neg_one))
-- | match_numeral_result.bit0 a =>
-- pure (ic, q((Neg.neg : ℤ → ℤ)).mk_app [a], q(RoundUp.bit0_neg).mk_app [a])
-- | match_numeral_result.bit1 a =>
-- pure (ic, q((Neg.neg : ℤ → ℤ)).mk_app [a], q(RoundUp.bit1_neg).mk_app [a])
-- | _ => failed
-- | none =>
-- match match_numeral a with
-- | match_numeral_result.zero => pure (ic, q((0 : ℤ)), q(RoundUp.zero))
-- | match_numeral_result.one => pure (ic, q((1 : ℤ)), q(RoundUp.one))
-- | match_numeral_result.bit0 a => pure (ic, a, q(RoundUp.bit0_pos).mk_app [a])
-- | match_numeral_result.bit1 a => do
-- let (ic, b, h) ← prove_succ' ic a
-- pure (ic, b, q(@RoundUp.bit1_pos).mk_app [a, b, h])
-- | _ => failed
-- #align tactic.approx.prove_round_up Tactic.Approx.prove_round_up
inductive ApproxExtra
| mk
#align tactic.approx.approx_extra Tactic.Approx.ApproxExtra
inductive ApproxArgs
| nil : ApproxArgs
| prec : ℤ → ApproxArgs → ApproxArgs
| unop : ApproxArgs → ApproxArgs
| binop : ApproxArgs → ApproxArgs → ApproxArgs
| extra : ApproxExtra → ApproxArgs
#align tactic.approx.approx_args Tactic.Approx.ApproxArgs
def ApproxArgs.getPrec : ApproxArgs → Option ℤ
| ApproxArgs.prec n _ => some n
| ApproxArgs.nil => none
| ApproxArgs.unop _ => none
| ApproxArgs.binop _ _ => none
| ApproxArgs.extra _ => none
#align tactic.approx.approx_args.get_prec Tactic.Approx.ApproxArgs.getPrec
def ApproxArgs.getBinop : ApproxArgs → ApproxArgs × ApproxArgs
| ApproxArgs.prec n p => p.getBinop
| ApproxArgs.binop a b => (a, b)
| _ => (ApproxArgs.nil, ApproxArgs.nil)
#align tactic.approx.approx_args.get_binop Tactic.Approx.ApproxArgs.getBinop
def ApproxArgs.getUnop : ApproxArgs → ApproxArgs
| ApproxArgs.prec n p => p.getUnop
| ApproxArgs.unop p => p
| _ => ApproxArgs.nil
#align tactic.approx.approx_args.get_unop Tactic.Approx.ApproxArgs.getUnop
-- /-- Given `a : ℤ` proves `(b, |- bit0 a = b)` -/
-- unsafe def prove_bit0 : expr → expr × expr
-- | a =>
-- match match_neg a with
-- | some a => (q((Neg.neg : ℤ → ℤ)).mk_app [a], q(bit0_neg).mk_app [a])
-- | none =>
-- let b0 := q((bit0 : ℤ → ℤ)).mk_app [a]
-- (b0, q(@rfl ℤ).mk_app [b0])
-- #align tactic.approx.prove_bit0 Tactic.Approx.prove_bit0
-- /-- `set_prec tgt ic n en lo hi x hx`:
-- * `en` is the expression for `n`
-- * `hx : approx n lo hi x`
-- returns `(ic, lo', hi', |- approx tgt lo' hi' x)` -/
-- unsafe def set_prec (tgt : ℤ) :
-- instance_cache →
-- ℤ → expr → expr → expr → expr → expr → tactic (instance_cache × expr × expr × expr)
-- | ic, n, en, lo, hi, x, hx =>
-- if n < tgt then do
-- let (ic, en') ← ic.ofInt (n + 1)
-- let (lo', hlo) := prove_bit0 lo
-- let (hi', hhi) := prove_bit0 hi
-- set_prec ic (n + 1) en' lo' hi' x <|
-- q(@Approx.up).mk_app [en, lo, hi, lo', hi', x, hx, hlo, hhi]
-- else
-- if tgt < n then do
-- let (ic, en') ← ic.ofInt (n - 1)
-- let (ic, lo', hlo) ← prove_round_down ic lo
-- let (ic, hi', hhi) ← prove_round_up ic hi
-- set_prec ic (n - 1) en' lo' hi' x <|
-- q(@Approx.down).mk_app [en, lo, hi, lo', hi', x, hx, hlo, hhi]
-- else pure (ic, lo, hi, hx)
-- #align tactic.approx.set_prec tactic.approx.set_prec
-- unsafe def approx_fn :=
-- instance_cache → ℤ → expr → expr → tactic (instance_cache × expr × expr × expr)
-- #align tactic.approx.approx_fn tactic.approx.approx_fn
-- unsafe def eval_approx_neg (xfn : approx_fn) (n' : ℤ) (x : expr) : approx_fn
-- | ic, n, en, e => do
-- let (ic, en') ← ic.ofInt n'
-- let (ic, lo, hi, hx) ← xfn ic n' en' x
-- let (ic, hi', hlo) ← prove_neg ic lo
-- let (ic, lo', hhi) ← prove_neg ic hi
-- set_prec n ic n' en' lo' hi' e <| q(@Approx.neg).mk_app [en', lo, hi, lo', hi', x, hx, hlo, hhi]
-- #align tactic.approx.eval_approx_neg tactic.approx.eval_approx_neg
-- unsafe def eval_approx_add (xfn yfn : approx_fn) (n' : ℤ) (x y : expr) : approx_fn
-- | ic, n, en, e => do
-- let (ic, en') ← ic.ofInt n'
-- let (ic, xlo, xhi, hx) ← xfn ic n' en' x
-- let (ic, ylo, yhi, hy) ← yfn ic n' en' y
-- let (ic, lo, hlo) ← prove_add_rat' ic xlo ylo
-- let (ic, hi, hhi) ← prove_add_rat' ic xhi yhi
-- set_prec n ic n' en' lo hi e <|
-- q(@Approx.add).mk_app [en', xlo, xhi, ylo, yhi, lo, hi, x, y, hx, hy, hlo, hhi]
-- #align tactic.approx.eval_approx_add tactic.approx.eval_approx_add
-- unsafe def eval_approx_sub (xfn yfn : approx_fn) (n' : ℤ) (x y : expr) : approx_fn
-- | ic, n, en, e => do
-- let (ic, en') ← ic.ofInt n'
-- let (ic, xlo, xhi, hx) ← xfn ic n' en' x
-- let (ic, ylo, yhi, hy) ← yfn ic n' en' y
-- let (ic, lo, hlo) ← prove_sub ic xlo yhi
-- let (ic, hi, hhi) ← prove_sub ic xhi ylo
-- set_prec n ic n' en' lo hi e <|
-- q(@Approx.sub).mk_app [en', xlo, xhi, ylo, yhi, lo, hi, x, y, hx, hy, hlo, hhi]
-- #align tactic.approx.eval_approx_sub tactic.approx.eval_approx_sub
-- /-- Given `xlo, xhi, ylo, yhi` proves `(lo, hi, |- mul_bound xlo xhi ylo yhi lo hi)` -/
-- unsafe def eval_mul_bound (ic : instance_cache) (exlo exhi eylo eyhi : expr) :
-- tactic (instance_cache × expr × expr × expr) := do
-- let xlo ← exlo.toInt
-- let xhi ← exhi.toInt
-- let ylo ← eylo.toInt
-- let yhi ← eyhi.toInt
-- let rxlo := Rat.ofInt xlo
-- let rxhi := Rat.ofInt xhi
-- let rylo := Rat.ofInt ylo
-- let ryhi := Rat.ofInt yhi
-- (if 0 ≤ xlo then do
-- let (ic, x0) ← prove_nonneg ic exlo
-- if 0 ≤ ylo then do
-- let (ic, y0) ← prove_nonneg ic eylo
-- let (ic, lo, hlo) ← prove_mul_rat ic exlo eylo rxlo rylo
-- let (ic, hi, hhi) ← prove_mul_rat ic exhi eyhi rxhi ryhi
-- pure
-- (ic, lo, hi,
-- q(@MulBound.pos_pos).mk_app [exlo, exhi, eylo, eyhi, lo, hi, x0, y0, hlo, hhi])
-- else
-- if yhi ≤ 0 then do
-- let (ic, y0) ← prove_le_rat ic eyhi q((0 : ℤ)) ryhi 0
-- let (ic, lo, hlo) ← prove_mul_rat ic exhi eylo rxhi rylo
-- let (ic, hi, hhi) ← prove_mul_rat ic exlo eyhi rxlo ryhi
-- pure
-- (ic, lo, hi,
-- q(@MulBound.pos_neg).mk_app [exlo, exhi, eylo, eyhi, lo, hi, x0, y0, hlo, hhi])
-- else failed
-- else
-- if xhi ≤ 0 then do
-- let (ic, x0) ← prove_le_rat ic exhi q((0 : ℤ)) rxhi 0
-- if 0 ≤ ylo then do
-- let (ic, y0) ← prove_nonneg ic eylo
-- let (ic, lo, hlo) ← prove_mul_rat ic exlo eyhi rxlo ryhi
-- let (ic, hi, hhi) ← prove_mul_rat ic exhi eylo rxhi rylo
-- pure
-- (ic, lo, hi,
-- q(@MulBound.neg_pos).mk_app [exlo, exhi, eylo, eyhi, lo, hi, x0, y0, hlo, hhi])
-- else
-- if yhi ≤ 0 then do
-- let (ic, y0) ← prove_le_rat ic eyhi q((0 : ℤ)) ryhi 0
-- let (ic, lo, hlo) ← prove_mul_rat ic exhi eyhi rxhi ryhi
-- let (ic, hi, hhi) ← prove_mul_rat ic exlo eylo rxlo rylo
-- pure
-- (ic, lo, hi,
-- q(@MulBound.neg_neg).mk_app
-- [exlo, exhi, eylo, eyhi, lo, hi, x0, y0, hlo, hhi])
-- else failed
-- else failed) <|>
-- do
-- let (ic, ell, hell) ← prove_mul_rat ic exlo eylo rxlo rylo
-- let ll := xlo * ylo
-- let rll := Rat.ofInt ll
-- let (ic, elh, helh) ← prove_mul_rat ic exlo eyhi rxlo ryhi
-- let lh := xlo * yhi
-- let rlh := Rat.ofInt lh
-- let (ic, ehl, hehl) ← prove_mul_rat ic exhi eylo rxhi rylo
-- let hl := xhi * ylo
-- let rhl := Rat.ofInt hl
-- let (ic, ehh, hehh) ← prove_mul_rat ic exhi eyhi rxhi ryhi
-- let hh := xhi * yhi
-- let rhh := Rat.ofInt hh
-- let lo := min ll <| min lh <| min hl hh
-- let hi := max ll <| max lh <| max hl hh
-- let (ic, elo) ← ic lo
-- let (ic, ehi) ← ic hi
-- let rlo := Rat.ofInt lo
-- let rhi := Rat.ofInt hi
-- let (ic, lll) ← prove_le_rat ic elo ell rlo rll
-- let (ic, hll) ← prove_le_rat ic ell ehi rll rhi
-- let (ic, llh) ← prove_le_rat ic elo elh rlo rlh
-- let (ic, hlh) ← prove_le_rat ic elh ehi rlh rhi
-- let (ic, lhl) ← prove_le_rat ic elo ehl rlo rhl
-- let (ic, hhl) ← prove_le_rat ic ehl ehi rhl rhi
-- let (ic, lhh) ← prove_le_rat ic elo ehh rlo rhh
-- let (ic, hhh) ← prove_le_rat ic ehh ehi rhh rhi
-- pure
-- (ic, elo, ehi,
-- q(@MulBound.mk).mk_app
-- [exlo, exhi, eylo, eyhi, ell, elh, ehl, ehh, elo, ehi, hell, helh, hehl, hehh, lll,
-- hll, llh, hlh, lhl, hhl, lhh, hhh])
-- #align tactic.approx.eval_mul_bound tactic.approx.eval_mul_bound
-- unsafe def eval_approx_mul (xfn yfn : approx_fn) (xp yp : ℤ) (x y : expr) : approx_fn
-- | ic, n, en, e => do
-- let (ic, exp) ← ic.ofInt xp
-- let (ic, eyp) ← ic.ofInt yp
-- let (ic, xlo, xhi, hx) ← xfn ic xp exp x
-- let (ic, ylo, yhi, hy) ← yfn ic yp eyp y
-- let (ic, lo, hi, hbd) ← eval_mul_bound ic xlo xhi ylo yhi
-- let n' := xp + yp
-- let (ic, en') ← ic.ofInt n'
-- set_prec n ic n' en' lo hi e <|
-- q(@Approx.mul).mk_app [exp, eyp, xlo, xhi, ylo, yhi, lo, hi, x, y, hx, hy, hbd]
-- #align tactic.approx.eval_approx_mul tactic.approx.eval_approx_mul
-- unsafe def inv_expr : expr :=
-- q((Inv.inv : ℝ → ℝ))
-- #align tactic.approx.inv_expr tactic.approx.inv_expr
-- unsafe def eval_approx_div (xfn iyfn : approx_fn) (xp yp : ℤ) (x y : expr) : approx_fn
-- | ic, n, en, e => do
-- let (ic, exp) ← ic.ofInt xp
-- let (ic, eyp) ← ic.ofInt yp
-- let (ic, xlo, xhi, hx) ← xfn ic xp exp x
-- let (ic, ylo, yhi, hy) ← iyfn ic yp eyp (inv_expr y)
-- let (ic, lo, hi, hbd) ← eval_mul_bound ic xlo xhi ylo yhi
-- pure
-- (ic, lo, hi,
-- q(@Approx.div).mk_app [exp, eyp, xlo, xhi, ylo, yhi, lo, hi, x, y, hx, hy, hbd])
-- #align tactic.approx.eval_approx_div tactic.approx.eval_approx_div
-- unsafe def eval_approx_inv (xfn : approx_fn) (m : ℤ) (x : expr) : approx_fn
-- | ic, n, en, e => do
-- let (ic, em) ← ic.ofInt m
-- let (ic, elo, ehi, hx) ← xfn ic m em x
-- let lo ← elo.toInt
-- let hi ← ehi.toInt
-- if lo = 0 ∧ hi = 0 then
-- pure (ic, q((0 : ℤ)), q((0 : ℤ)), q(@Approx.inv_zero).mk_app [em, en, x, hx])
-- else
-- if m + n ≤ 0 then
-- if 0 < lo then do
-- let (ic, x0) ← prove_pos ic elo
-- pure
-- (ic, q((0 : ℤ)), q((1 : ℤ)),
-- q(@Approx.inv_triv_pos).mk_app [em, en, elo, ehi, x, hx, q(@rfl _ true), x0])
-- else
-- if hi < 0 then do
-- let (ic, x0) ← prove_lt_rat ic ehi q((0 : ℤ)) (Rat.ofInt hi) 0
-- pure
-- (ic, q((-1 : ℤ)), q((0 : ℤ)),
-- q(@Approx.inv_triv_neg).mk_app [em, en, elo, ehi, x, hx, q(@rfl _ true), x0])
-- else fail f! "at {x}⁻¹: Failed to bound away from zero. Try increasing the precision"
-- else do
-- let nc ← mk_instance_cache q(ℕ)
-- let p := (m + n).toNat
-- let (nc, ep) ← nc p
-- let hp := q(@rfl _ (($(ep) : ℕ) : ℤ))
-- let (ic, ep2, hp2) ← prove_pow q((2 : ℤ)) 2 ic ep
-- let p2 : ℤ := 2 ^ p
-- let rp2 := Rat.ofInt p2
-- let rlo := Rat.ofInt lo
-- let rhi := Rat.ofInt hi
-- if 0 < lo then do
-- let (ic, x0) ← prove_pos ic elo
-- let lo' := p2 / hi
-- let hi' := (p2 - 1) / lo + 1
-- let (ic, elo') ← ic lo'
-- let (ic, ehi') ← ic hi'
-- let (ic, elh, hlh) ← prove_mul_rat ic elo ehi' rlo (Rat.ofInt hi')
-- let (ic, ehl, hhl) ← prove_mul_rat ic ehi elo' rhi (Rat.ofInt lo')
-- let (ic, hlo) ← prove_le_rat ic ep2 elh p2 (Rat.ofInt (lo * hi'))
-- let (ic, hhi) ← prove_le_rat ic ehl ep2 (Rat.ofInt (hi * lo')) p2
-- pure
-- (ic, elo, ehi,
-- q(@Approx.inv_pos).mk_app
-- [em, en, elo, ehi, elo', ehi', elh, ehl, ep2, x, ep, hx, hp, x0, hp2, hlh,
-- hhl, hlo, hhi])
-- else
-- if hi < 0 then do
-- let (ic, x0) ← prove_lt_rat ic ehi q((0 : ℤ)) rhi 0
-- let lo' := (p2 - 1) / hi - 1
-- let hi' := p2 / lo
-- let (ic, elo') ← ic lo'
-- let (ic, ehi') ← ic hi'
-- let (ic, elh, hlh) ← prove_mul_rat ic elo ehi' rlo (Rat.ofInt hi')
-- let (ic, ehl, hhl) ← prove_mul_rat ic ehi elo' rhi (Rat.ofInt lo')
-- let (ic, hlo) ← prove_le_rat ic ep2 ehl p2 (Rat.ofInt (hi * lo'))
-- let (ic, hhi) ← prove_le_rat ic elh ep2 (Rat.ofInt (lo * hi')) p2
-- pure
-- (ic, elo, ehi,
-- q(@Approx.inv_neg).mk_app
-- [em, en, elo, ehi, elo', ehi', elh, ehl, ep2, x, ep, hx, hp, x0, hp2, hlh,
-- hhl, hlo, hhi])
-- else fail f! "at {x}⁻¹: Failed to bound away from zero. Try increasing the precision"
-- #align tactic.approx.eval_approx_inv tactic.approx.eval_approx_inv
-- -- PLEASE REPORT THIS TO MATHPORT DEVS, THIS SHOULD NOT HAPPEN.
-- -- failed to format: unknown constant 'term.pseudo.antiquot'
-- unsafe
-- def
-- eval_approx
-- : ApproxArgs → approx_fn
-- | approx_args.extra args , ic , n , en , e => failed
-- |
-- approx_args.prec n' args , ic , n , en , e
-- =>
-- do
-- let ( ic , en' ) ← ic . ofInt n'
-- let ( ic , lo , hi , hx ) ← eval_approx args ic n' en' e
-- set_prec n ic n' en' lo hi e hx
-- |
-- args , ic , n , en , e
-- =>
-- do
-- let
-- r
-- ←
-- try_core
-- (
-- match
-- e . toNat
-- with
-- | some 0 => pure none
-- |
-- some _
-- =>
-- do let rc ← mk_instance_cache q( ℝ ) some <$> prove_int_uncast rc ic e
-- | _ => failed
-- )
-- match
-- r
-- with
-- |
-- some none
-- =>
-- pure ( ic , q( ( 0 : ℤ ) ) , q( ( 0 : ℤ ) ) , q( Approx.zero ) . mk_app [ en ] )
-- |
-- some ( some ( _ , ic , a , ha ) )
-- =>
-- do
-- set_prec n ic 0 q( ( 0 : ℤ ) ) a a e
-- <|
-- q( @ Approx.const ) . mk_app [ a , e , ha ]
-- |
-- none
-- =>
-- match
-- e
-- with
-- |
-- q( - $ ( x ) )
-- =>
-- do
-- let xargs := args
-- let n' := ( match xargs with | some xp => min n xp | _ => n : ℤ )
-- eval_approx_neg ( eval_approx xargs ) n' x ic n en e
-- |
-- q( $ ( x ) + $ ( y ) )
-- =>
-- do
-- let ( xargs , yargs ) := args
-- let
-- n'
-- :=
-- (
-- match
-- xargs , yargs
-- with
-- | some xp , some yp => min n ( max xp yp ) | _ , _ => n
-- :
-- ℤ
-- )
-- eval_approx_add
-- ( eval_approx xargs ) ( eval_approx yargs ) n' x y ic n en e
-- |
-- q( $ ( x ) - $ ( y ) )
-- =>
-- do
-- let ( xargs , yargs ) := args
-- let
-- n'
-- :=
-- (
-- match
-- xargs , yargs
-- with
-- | some xp , some yp => min n ( max xp yp ) | _ , _ => n
-- :
-- ℤ
-- )
-- eval_approx_sub
-- ( eval_approx xargs ) ( eval_approx yargs ) n' x y ic n en e
-- |
-- q( $ ( x ) * $ ( y ) )
-- =>
-- do
-- let ( xargs , yargs ) := args
-- let
-- ( xp , yp )
-- :=
-- (
-- match
-- xargs , yargs
-- with
-- | some xp , some yp => ( xp , yp )
-- | none , some yp => ( n - yp , yp )
-- | some xp , none => ( xp , n - xp )
-- | none , none => let xp := n / 2 ( xp , n - xp )
-- :
-- ℤ × ℤ
-- )
-- eval_approx_mul
-- ( eval_approx xargs ) ( eval_approx yargs ) xp yp x y ic n en e
-- |
-- q( $ ( x ) / $ ( y ) )
-- =>
-- do
-- let ( xargs , yargs ) := args
-- let xp := xargs ( n / 2 )
-- let yp := n - xp
-- eval_approx_div
-- ( eval_approx xargs )
-- ( eval_approx ( approx_args.unop yargs ) )
-- xp
-- yp
-- x
-- y
-- ic
-- n
-- en
-- e
-- |
-- q( $ ( x ) ⁻¹ )
-- =>
-- do
-- let xargs := args
-- let m := xargs ( abs n )
-- eval_approx_inv ( eval_approx xargs ) m x ic n en e
-- | _ => failed
-- #align tactic.approx.eval_approx tactic.approx.eval_approx
end Approx
end Tactic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment