Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Impressum Extended_Real.thy

  Sprache: Isabelle
 

(*  Title:      HOL/Library/Extended_Real.thy
  Author: Johannes Hölzl, TU München
  Author: Robert Himmelmann, TU München
  Author: Armin Heller, TU München
  Author: Bogdan Grechuk, University of Edinburgh
  Author: Manuel Eberl, TU München
*)

section Extended real number line

theory Extended_Real
imports Complex_Main Extended_Nat Liminf_Limsup
begin

text 
  This should be part of 🍋HOL-Library.Extended_Nat or 🍋HOL-Library.Order_Continuity, but then the AFP-entry Jinja_Thread fails, as it does overload
  certain named from 🍋Complex_Main.
 

lemma incseq_sumI2:
  fixes f :: "'i ==> nat ==> 'a::ordered_comm_monoid_add"
  shows "(n. n A ==> mono (f n)) ==> mono (λi. nA. f n i)"
  unfolding incseq_def by (auto intro: sum_mono)

lemma incseq_sumI:
  fixes f :: "nat ==> 'a::ordered_comm_monoid_add"
  assumes "i. 0 f i"
  shows "incseq (λi. sum f {..< i})"
proof (intro incseq_SucI)
  fix n
  have "sum f {..< n} + 0 sum f {..
    using assms by (rule add_left_mono)
  then show "sum f {..< n} sum f {..< Suc n}"
    by auto
qed

lemma continuous_at_left_imp_sup_continuous:
  fixes f :: "'a::{complete_linorder, linorder_topology} ==> 'b::{complete_linorder, linorder_topology}"
  assumes "mono f" "x. continuous (at_left x) f"
  shows "sup_continuous f"
  unfolding sup_continuous_def
proof safe
  fix M :: "nat ==> 'a" assume "incseq M" then show "f (SUP i. M i) = (SUP i. f (M i))"
    using continuous_at_Sup_mono [OF assms, of "range M"by (simp add: image_comp)
qed

lemma sup_continuous_at_left:
  fixes f :: "'a::{complete_linorder, linorder_topology, first_countable_topology} ==>

    'b::{complete_linorder, linorder_topology}"
  assumes f: "sup_continuous f"
  shows "continuous (at_left x) f"
proof cases
  assume "x = bot" then show ?thesis
    by (simp add: trivial_limit_at_left_bot)
next
  assume x: "x bot"
  show ?thesis
    unfolding continuous_within
  proof (intro tendsto_at_left_sequentially[of bot])
    fix S :: "nat ==> 'a" assume S: "incseq S" and S_x: "S <---- x"
    from S_x have x_eq: "x = (SUP i. S i)"
      by (rule LIMSEQ_unique) (intro LIMSEQ_SUP S)
    show "(λn. f (S n)) <---- f x"
      unfolding x_eq sup_continuousD[OF f S]
      using S sup_continuous_mono[OF f] by (intro LIMSEQ_SUP) (auto simp: mono_def)
  qed (insert x, auto simp: bot_less)
qed

lemma sup_continuous_iff_at_left:
  fixes f :: "'a::{complete_linorder, linorder_topology, first_countable_topology} ==>
             'b::{complete_linorder, linorder_topology}"
  shows "sup_continuous f (x. continuous (at_left x) f) mono f"
  using continuous_at_left_imp_sup_continuous sup_continuous_at_left sup_continuous_mono
  by blast

lemma continuous_at_right_imp_inf_continuous:
  fixes f :: "'a::{complete_linorder, linorder_topology} ==> 'b::{complete_linorder, linorder_topology}"
  assumes "mono f" "x. continuous (at_right x) f"
  shows "inf_continuous f"
  unfolding inf_continuous_def
proof safe
  fix M :: "nat ==> 'a" 
  assume "decseq M" 
    then show "f (INF i. M i) = (INF i. f (M i))"
      using continuous_at_Inf_mono [OF assms, of "range M"
      by (simp add: image_comp)
qed

lemma inf_continuous_at_right:
  fixes f :: "'a::{complete_linorder, linorder_topology, first_countable_topology} ==>
    'b::{complete_linorder, linorder_topology}"
  assumes f: "inf_continuous f"
  shows "continuous (at_right x) f"
proof cases
  assume "x = top" then show ?thesis
    by (simp add: trivial_limit_at_right_top)
next
  assume x: "x top"
  show ?thesis
    unfolding continuous_within
  proof (intro tendsto_at_right_sequentially[of _ top])
    fix S :: "nat ==> 'a" 
    assume S: "decseq S" and S_x: "S <---- x"
    then have x_eq: "x = (INF i. S i)"
      using INF_Lim by blast
    show "(λn. f (S n)) <---- f x"
      unfolding x_eq inf_continuousD[OF f S]
      using S inf_continuous_mono[OF f] by (intro LIMSEQ_INF) (auto simp: mono_def antimono_def)
  qed (insert x, auto simp: less_top)
qed

lemma inf_continuous_iff_at_right:
  fixes f :: "'a::{complete_linorder, linorder_topology, first_countable_topology} ==>
    'b::{complete_linorder, linorder_topology}"
  shows "inf_continuous f (x. continuous (at_right x) f) mono f"
  using continuous_at_right_imp_inf_continuous inf_continuous_at_right inf_continuous_mono
  by blast

instantiation enat :: linorder_topology
begin

definition open_enat :: "enat set ==> bool" where
  "open_enat = generate_topology (range lessThan range greaterThan)"

instance
  proof qed (rule open_enat_def)

end

lemma open_enat: "open {enat n}"
proof (cases n)
  case 0
  then have "{enat n} = {..< eSuc 0}"
    by (auto simp: enat_0)
  then show ?thesis
    by simp
next
  case (Suc n')
  then have "{enat n} = {enat n' <..< enat (Suc n)}"
    using enat_iless by (fastforce simp: set_eq_iff)
  then show ?thesis
    by simp
qed

lemma open_enat_iff:
  fixes A :: "enat set"
  shows "open A ( A (n::nat. {n <..} A))"
proof safe
  assume " A"
  then have "A = (n{n. enat n A}. {enat n})"
    by (simp add: set_eq_iff) (metis not_enat_eq)
  moreover have "open "
    by (auto intro: open_enat)
  ultimately show "open A"
    by simp
next
  fix n assume "{enat n <..} A"
  then have "A = (n{n. enat n A}. {enat n}) {enat n <..}"
    using enat_ile leI by (simp add: set_eq_iff) blast
  moreover have "open "
    by (intro open_Un open_UN ballI open_enat open_greaterThan)
  ultimately show "open A"
    by simp
next
  assume "open A" " A"
  then have "generate_topology (range lessThan range greaterThan) A" " A"
    unfolding open_enat_def by auto
  then show "n::nat. {n <..} A"
  proof induction
    case (Int A B)
    then obtain n m where "{enat n<..} A" "{enat m<..} B"
      by auto
    then have "{enat (max n m) <..} A B"
      by (auto simp: subset_eq Ball_def max_def simp flip: enat_ord_code(1))
    then show ?case
      by auto
  next
    case (UN K)
    then obtain k where "k K" " k"
      by auto
    with UN.IH[OF this] show ?case
      by auto
  qed auto
qed

lemma nhds_enat: "nhds x = (if x = then INF i. principal {enat i..} else principal {x})"
proof auto
  show "nhds = (INF i. principal {enat i..})"
  proof (rule antisym)
    show "nhds (INF i. principal {enat i..})"
      unfolding nhds_def
      using Ioi_le_Ico by (intro INF_greatest INF_lower) (auto simp: open_enat_iff)
    show "(INF i. principal {enat i..}) nhds "
      unfolding nhds_def
      by (intro INF_greatest) (force intro: INF_lower2[of "Suc _"] simp add: open_enat_iff Suc_ile_eq)
  qed
  show "nhds (enat i) = principal {enat i}" for i
    by (simp add: nhds_discrete_open open_enat)
qed

instance enat :: topological_comm_monoid_add
proof
  have [simp]: "enat i aa ==> enat i aa + ba" for aa ba i
    by (rule order_trans[OF _ add_mono[of aa aa 0 ba]]) auto
  then have [simp]: "enat i ba ==> enat i aa + ba" for aa ba i
    by (metis add.commute)
  fix a b :: enat 
  have "🪙F x in INF m n. principal ({enat n..} × {enat m..}). enat i fst x + snd x"
       "🪙F x in INF n. principal ({enat n..} × {enat j}). enat i fst x + snd x" 
       "🪙F x in INF n. principal ({enat j} × {enat n..}). enat i fst x + snd x" 
    for i j
    by (auto intro!: eventually_INF1[of i] simp: eventually_principal)
  then show "((λx. fst x + snd x) ---> a + b) (nhds a ×🪙F nhds b)"
    by (auto simp: nhds_enat filterlim_INF prod_filter_INF1 prod_filter_INF2
        filterlim_principal principal_prod_principal eventually_principal)
qed

text 
  For more lemmas about the extended real numbers see
  🍋~~/src/HOL/Analysis/Extended_Real_Limits.thy.
 

subsection Definition and basic properties

datatype ereal = ereal real | PInfty | MInfty

instantiation ereal :: uminus
begin

fun uminus_ereal where
  "- (ereal r) = ereal (- r)"
"- PInfty = MInfty"
"- MInfty = PInfty"

instance ..

end

instantiation ereal :: infinity
begin

definition "(::ereal) = PInfty"
instance ..

end

declare [[coercion "ereal :: real ==> ereal"]]

lemma ereal_uminus_uminus[simp]:
  fixes a :: ereal
  shows "- (- a) = a"
  by (cases a) simp_all

lemma
  shows PInfty_eq_infinity[simp]: "PInfty = "
    and MInfty_eq_minfinity[simp]: "MInfty = -"
    and MInfty_neq_PInfty[simp]: " - (::ereal)" "- (::ereal)"
    and MInfty_neq_ereal[simp]: "ereal r -" "- ereal r"
    and PInfty_neq_ereal[simp]: "ereal r " " ereal r"
    and PInfty_cases[simp]: "(case of ereal r ==> f r | PInfty ==> y | MInfty ==> z) = y"
    and MInfty_cases[simp]: "(case - of ereal r ==> f r | PInfty ==> y | MInfty ==> z) = z"
  by (simp_all add: infinity_ereal_def)

declare
  PInfty_eq_infinity[code_post]
  MInfty_eq_minfinity[code_post]

lemma [code_unfold]:
  " = PInfty"
  "- PInfty = MInfty"
  by simp_all

lemma inj_ereal[simp]: "inj_on ereal A"
  unfolding inj_on_def by auto

lemma ereal_cases[cases type: ereal]:
  obtains (real) r where "x = ereal r"
    | (PInf) "x = "
    | (MInf) "x = -"
  by (cases x) auto

lemmas ereal2_cases = ereal_cases[case_product ereal_cases]
lemmas ereal3_cases = ereal2_cases[case_product ereal_cases]

lemma ereal_all_split: "P. (x::ereal. P x) P (x. P (ereal x)) P (-)"
  by (metis ereal_cases)

lemma ereal_ex_split: "P. (x::ereal. P x) P (x. P (ereal x)) P (-)"
  by (metis ereal_cases)

lemma ereal_uminus_eq_iff[simp]:
  fixes a b :: ereal
  shows "-a = -b a = b"
  by (cases rule: ereal2_cases[of a b]) simp_all

function real_of_ereal :: "ereal ==> real" where
  "real_of_ereal (ereal r) = r"
"real_of_ereal = 0"
"real_of_ereal (-) = 0"
  by (auto intro: ereal_cases)
termination by standard (rule wf_on_bot)

lemma real_of_ereal[simp]:
  "real_of_ereal (- x :: ereal) = - (real_of_ereal x)"
  by (cases x) simp_all

lemma range_ereal[simp]: "range ereal = UNIV - {, -}"
proof safe
  fix x
  assume "x range ereal" "x "
  then show "x = -"
    by (cases x) auto
qed auto

lemma ereal_range_uminus[simp]: "range uminus = (UNIV::ereal set)"
proof safe
  fix x :: ereal
  show "x range uminus"
    by (intro image_eqI[of _ _ "-x"]) auto
qed auto

instantiation ereal :: abs
begin

function abs_ereal where
  "ereal r = ereal r"
"- = (::ereal)"
" = (::ereal)"
by (auto intro: ereal_cases)
termination proof qed (rule wf_on_bot)

instance ..

end

lemma abs_eq_infinity_cases[elim!]:
  fixes x :: ereal
  assumes "x = "
  obtains "x = " | "x = -"
  using assms by (cases x) auto

lemma abs_neq_infinity_cases[elim!]:
  fixes x :: ereal
  assumes "x "
  obtains r where "x = ereal r"
  using assms by (cases x) auto

lemma abs_ereal_uminus[simp]:
  fixes x :: ereal
  shows "- x = x"
  by (cases x) auto

lemma ereal_infinity_cases:
  fixes a :: ereal
  shows "a ==> a - ==> a "
  by auto

subsubsection "Addition"

instantiation ereal :: "{one,comm_monoid_add,zero_neq_one}"
begin

definition "0 = ereal 0"
definition "1 = ereal 1"

function plus_ereal where
  "ereal r + ereal p = ereal (r + p)"
" + a = (::ereal)"
"a + = (::ereal)"
"ereal r + - = -"
"- + ereal p = -(::ereal)"
"- + - = -(::ereal)"
proof goal_cases
  case prems: (1 P x)
  then obtain a b where "x = (a, b)"
    by (cases x) auto
  with prems show P
   by (cases rule: ereal2_cases[of a b]) auto
qed auto
termination by standard (rule wf_on_bot)

lemma Infty_neq_0[simp]:
  "(::ereal) 0" "0 (::ereal)"
  "-(::ereal) 0" "0 -(::ereal)"
  by (simp_all add: zero_ereal_def)

lemma ereal_eq_0[simp]:
  "ereal r = 0 r = 0"
  "0 = ereal r r = 0"
  unfolding zero_ereal_def by simp_all

lemma ereal_eq_1[simp]:
  "ereal r = 1 r = 1"
  "1 = ereal r r = 1"
  unfolding one_ereal_def by simp_all

instance
proof
  fix a b c :: ereal
  show "0 + a = a"
    by (cases a) (simp_all add: zero_ereal_def)
  show "a + b = b + a"
    by (cases rule: ereal2_cases[of a b]) simp_all
  show "a + b + c = a + (b + c)"
    by (cases rule: ereal3_cases[of a b c]) simp_all
  show "0 (1::ereal)"
    by (simp add: one_ereal_def zero_ereal_def)
qed

end

lemma ereal_0_plus [simp]: "ereal 0 + x = x"
  and plus_ereal_0 [simp]: "x + ereal 0 = x"
  by(simp_all flip: zero_ereal_def)

instance ereal :: numeral ..

lemma real_of_ereal_0[simp]: "real_of_ereal (0::ereal) = 0"
  unfolding zero_ereal_def by simp

lemma abs_ereal_zero[simp]: "0 = (0::ereal)"
  unfolding zero_ereal_def abs_ereal.simps by simp

lemma ereal_uminus_zero[simp]: "- 0 = (0::ereal)"
  by (simp add: zero_ereal_def)

lemma ereal_uminus_zero_iff[simp]:
  fixes a :: ereal
  shows "-a = 0 a = 0"
  by (cases a) simp_all

lemma ereal_plus_eq_PInfty[simp]:
  fixes a b :: ereal
  shows "a + b = a = b = "
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_plus_eq_MInfty[simp]:
  fixes a b :: ereal
  shows "a + b = - (a = - b = -) a b "
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_add_cancel_left:
  fixes a b :: ereal
  assumes "a -"
  shows "a + b = a + c a = b = c"
  using assms by (cases rule: ereal3_cases[of a b c]) auto

lemma ereal_add_cancel_right:
  fixes a b :: ereal
  assumes "a -"
  shows "b + a = c + a a = b = c"
  using assms by (cases rule: ereal3_cases[of a b c]) auto

lemma ereal_real: "ereal (real_of_ereal x) = (if x = then 0 else x)"
  by auto

lemma real_of_ereal_add:
  fixes a b :: ereal
  shows "real_of_ereal (a + b) =
    (if (a = ) (b = ) (a ) (b ) then real_of_ereal a + real_of_ereal b else 0)"
  by auto


subsubsection "Linear order on 🍋ereal"

instantiation ereal :: linorder
begin

function less_ereal
where
  "   ereal x < ereal y      x < y"
| "(::ereal) < a            False"
| "         a < -(::ereal)  False"
| "ereal x    <             True"
| "        - < ereal r      True"
| "        - < (::ereal)  True"
proof goal_cases
  case prems: (1 P x)
  then obtain a b where "x = (a,b)" by (cases x) auto
  with prems show P by (cases rule: ereal2_cases[of a b]) auto
qed simp_all
termination by (relation "{}") simp

definition " (y::ereal)  x < y  x = y"

lemma ereal_infty_less[simp]:
  fixes x :: ereal
  shows "x <   (x  )"
       "- < x  (x  -)"
  by (cases x, simp_all)+

lemma ereal_infty_less_eq[simp]:
  fixes x :: ereal
  shows "  x  x = "
    and " -  x = -"
  by (auto simp: less_eq_ereal_def)

lemma ereal_less[simp]:
  "ereal r < 0  (r < 0)"
  "0 < ereal r  (0 < r)"
  "ereal r < 1  (r < 1)"
  "1 < ereal r  (1 < r)"
  "0 < (::ereal)"
  "-(::ereal) < 0"
  by (simp_all add: zero_ereal_def one_ereal_def)

lemma ereal_less_eq[simp]:
  " (::ereal)"
  "-(::ereal)  x"
  "ereal r  ereal p  r  p"
  "ereal r  0  r  0"
  " ereal r  0  r"
  "ereal r  1  r  1"
  " ereal r  1  r"
  by (auto simp: less_eq_ereal_def zero_ereal_def one_ereal_def)

lemma ereal_infty_less_eq2:
  " b ==> a =  ==> b = (::ereal)"
  " b ==> b = - ==> a = -(::ereal)"
  by simp_all

instance
proof
  fix x y z :: ereal
  show " x"
    by (cases x) simp_all
  show "x < y  x  y  ¬ y  x"
    by (cases rule: ereal2_cases[of x y]) auto
  show " y  y  x "
    by (cases rule: ereal2_cases[of x y]) auto
  assume " y"
  then show " x ==> x = y"
    by (cases rule: ereal2_cases[of x y]) auto
  show " z ==> x  z"
    using x y
    by (cases rule: ereal3_cases[of x y z]) auto
qed

end

lemma ereal_dense2: "x < y ==> z. x < ereal z  ereal z < y"
  using lt_ex gt_ex dense by (cases x y rule: ereal2_cases) auto

instance ereal :: dense_linorder
  by standard (blast dest: ereal_dense2)

instance ereal :: ordered_comm_monoid_add
proof
  fix a b c :: ereal
  assume " b"
  then show "c + a  c + b"
    by (cases rule: ereal3_cases[of a b c]) auto
qed

lemma ereal_one_not_less_zero_ereal[simp]: "¬ 1 < (0::ereal)"
  by (simp add: zero_ereal_def)

lemma real_of_ereal_positive_mono:
  fixes x y :: ereal
  shows " x ==> x  y ==> y   ==> real_of_ereal x  real_of_ereal y"
  by (cases rule: ereal2_cases[of x y]) auto

lemma ereal_MInfty_lessI[intro, simp]:
  fixes a :: ereal
  shows " - ==> - < a"
  by simp

lemma ereal_less_PInfty[intro, simp]:
  fixes a :: ereal
  shows "  ==> a < "
  by simp

lemma ereal_less_ereal_Ex:
  fixes a b :: ereal
  shows "x < ereal r  x = -  (p. p < r  x = ereal p)"
  by (cases x) auto

lemma less_PInf_Ex_of_nat: "   (n::nat. x < ereal (real n))"
proof (cases x)
  case (real r)
  then show ?thesis
    using reals_Archimedean2[of r] by simp
qed simp_all

lemma ereal_add_strict_mono2:
  fixes a b c d :: ereal
  assumes "a < b" and "c < d"
  shows "a + c < b + d"
  using assms
  by (cases a; force simp: elim: less_ereal.elims)

lemma ereal_minus_le_minus[simp]:
  fixes a b :: ereal
  shows "- a  - b  b  a"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_minus_less_minus[simp]:
  fixes a b :: ereal
  shows "- a < - b  b < a"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_le_real_iff:
  " real_of_ereal y  (y    ereal x  y)  (y =   x  0)"
  by (cases y) auto

lemma real_le_ereal_iff:
  "real_of_ereal y  x  (y    y  ereal x)  (y =   0  x)"
  by (cases y) auto

lemma ereal_less_real_iff:
  "x < real_of_ereal y  (y    ereal x < y)  (y =   x < 0)"
  by (cases y) auto

lemma real_less_ereal_iff:
  "real_of_ereal y < x  (y    y < ereal x)  (y =   0 < x)"
  by (cases y) auto

text
  To help with inferences like 🍋a < ereal x ==> x < y ==> a < ereal y,
  where x and y are real.
 

lemma le_ereal_le: " ereal x ==> x  y ==> a  ereal y"
  using ereal_less_eq(3) order.trans by blast

lemma le_ereal_less: " ereal x ==> x < y ==> a < ereal y"
  by (simp add: le_less_trans)

lemma less_ereal_le: "a < ereal x ==> x  y ==> a < ereal y"
  using ereal_less_ereal_Ex by auto

lemma ereal_le_le: "ereal y  a ==> x  y ==> ereal x  a"
  by (simp add: order_subst2)

lemma ereal_le_less: "ereal y  a ==> x < y ==> ereal x < a"
  by (simp add: dual_order.strict_trans1)

lemma ereal_less_le: "ereal y < a ==> x  y ==> ereal x < a"
  using ereal_less_eq(3) le_less_trans by blast

lemma real_of_ereal_pos:
  fixes x :: ereal
  shows " x ==> 0  real_of_ereal x"
  by (cases x) auto

lemmas real_of_ereal_ord_simps =
  ereal_le_real_iff real_le_ereal_iff ereal_less_real_iff real_less_ereal_iff

lemma abs_ereal_ge0[simp]: " x ==> x :: ereal = x"
  by (cases x) auto

lemma abs_ereal_less0[simp]: "x < 0 ==> x :: ereal = -x"
  by (cases x) auto

lemma abs_ereal_pos[simp]: " x :: ereal"
  by (cases x) auto

lemma ereal_abs_leI:
  fixes x y :: ereal
  shows "[ x  y; -x  y ] ==> x  y"
  by(cases x y rule: ereal2_cases)(simp_all)

lemma ereal_abs_add:
  fixes a b::ereal
  shows "abs(a+b)  abs a + abs b"
  by (cases rule: ereal2_cases[of a b]) (auto)

lemma real_of_ereal_le_0[simp]: "real_of_ereal (x :: ereal)  0  x  0  x = "
  by (cases x) auto

lemma abs_real_of_ereal[simp]: "real_of_ereal (x :: ereal) = real_of_ereal x"
  by (cases x) auto

lemma zero_less_real_of_ereal:
  fixes x :: ereal
  shows "0 < real_of_ereal x  0 < x  x  "
  by (cases x) auto

lemma ereal_0_le_uminus_iff[simp]:
  fixes a :: ereal
  shows " - a  a  0"
  by (cases rule: ereal2_cases[of a]) auto

lemma ereal_uminus_le_0_iff[simp]:
  fixes a :: ereal
  shows "- a  0  0  a"
  by (cases rule: ereal2_cases[of a]) auto

lemma ereal_add_strict_mono:
  fixes a b c d :: ereal
  assumes " b"
    and " a"
    and " "
    and "c < d"
  shows "a + c < b + d"
  using assms
  by (cases rule: ereal3_cases[case_product ereal_cases, of a b c d]) auto

lemma ereal_less_add:
  fixes a b c :: ereal
  shows "a   ==> c < b ==> a + c < a + b"
  by (cases rule: ereal2_cases[of b c]) auto

lemma ereal_uminus_eq_reorder: "- a = b  a = (-b::ereal)"
  by auto

lemma ereal_uminus_less_reorder: "- a < b  -b < a"
  and ereal_less_uminus_reorder: "a < - b  b < - a"
  and ereal_uminus_le_reorder: "- a  b  -b  a" for a::ereal
  using ereal_minus_le_minus ereal_minus_less_minus by fastforce+

lemmas ereal_uminus_reorder =
  ereal_uminus_eq_reorder ereal_uminus_less_reorder ereal_uminus_le_reorder

lemma ereal_bot:
  fixes x :: ereal
  assumes "B. x  ereal B"
  shows "x = -"
proof (cases x)
  case (real r)
  with assms[of "r - 1"] show ?thesis
    by auto
next
  case PInf
  with assms[of 0] show ?thesis
    by auto
next
  case MInf
  then show ?thesis
    by simp
qed

lemma ereal_top:
  fixes x :: ereal
  assumes "B. x  ereal B"
  shows "x = "
proof (cases x)
  case (real r)
  with assms[of "r + 1"] show ?thesis
    by auto
next
  case MInf
  with assms[of 0] show ?thesis
    by auto
next
  case PInf
  then show ?thesis
    by simp
qed

lemma
  shows ereal_max[simp]: "ereal (max x y) = max (ereal x) (ereal y)"
    and ereal_min[simp]: "ereal (min x y) = min (ereal x) (ereal y)"
  by (simp_all add: min_def max_def)

lemma ereal_max_0: "max 0 (ereal r) = ereal (max 0 r)"
  by (auto simp: zero_ereal_def)

lemma
  fixes f :: "nat ==> ereal"
  shows ereal_incseq_uminus[simp]: "incseq (λx. - f x)  decseq f"
    and ereal_decseq_uminus[simp]: "decseq (λx. - f x)  incseq f"
  unfolding decseq_def incseq_def by auto

lemma incseq_ereal: "incseq f ==> incseq (λx. ereal (f x))"
  unfolding incseq_def by auto

lemma sum_ereal[simp]: "(xA. ereal (f x)) = ereal (xA. f x)"
  by (induction A rule: infinite_finite_induct) auto

lemma sum_list_ereal [simp]: "sum_list (map (λx. ereal (f x)) xs) = ereal (sum_list (map f xs))"
  by (induction xs) simp_all

lemma sum_Pinfty:
  fixes f :: "'a ==> ereal"
  shows "(xP. f x) =   finite P  (iP. f i = )"
proof safe
  assume *: "sum f P = "
  show "finite P"
    by (metis "*" Infty_neq_0(2) sum.infinite)
  show "iP. f i = "
  proof (rule ccontr)
    assume "¬ ?thesis"
    then have "i. i  P ==> f i  "
      by auto
    with finite P have "sum f P  "
      by induct auto
    with * show False
      by auto
  qed
next
  fix i
  assume "finite P" and " P" and "f i = "
  then show "sum f P = "
  proof induct
    case (insert x A)
    show ?case using insert by (cases "x = i") auto
  qed simp
qed

lemma sum_Inf:
  fixes f :: "'a ==> ereal"
  shows "sum f A =   finite A  (iA. f i = )"
proof
  assume *: "sum f A = "
  have "finite A"
    by (rule ccontr) (insert *, auto)
  moreover have "iA. f i = "
  proof (rule ccontr)
    assume "¬ ?thesis"
    then have "iA. r. f i = ereal r"
      by auto
    then obtain r where "xA. f x = ereal (r x)"
      by metis
    with * show False
      by auto
  qed
  ultimately show "finite A  (iA. f i = )"
    by auto
next
  assume "finite A  (iA. f i = )"
  then obtain i where "finite A" " A" and "f i = "
    by auto
  then show "sum f A = "
  proof induct
    case (insert j A)
    then show ?case
      by (cases rule: ereal3_cases[of "f i" "f j" "sum f A"]) auto
  qed simp
qed

lemma sum_real_of_ereal:
  fixes f :: "'i ==> ereal"
  assumes "x. x  S ==> f x  "
  shows "(xS. real_of_ereal (f x)) = real_of_ereal (sum f S)"
proof -
  have "xS. r. f x = ereal r"
    using assms by blast
  then obtain r where "xS. f x = ereal (r x)"
    by metis
  then show ?thesis
    by simp
qed

subsubsection "Multiplication"

instantiation ereal :: "{comm_monoid_mult,sgn}"
begin

function sgn_ereal :: "ereal ==> ereal" where
  "sgn (ereal r) = ereal (sgn r)"
| "sgn (::ereal) = 1"
| "sgn (-::ereal) = -1"
by (auto intro: ereal_cases)
termination by standard (rule wf_on_bot)

function times_ereal where
  "ereal r * ereal p = ereal (r * p)"
| "ereal r *  = (if r = 0 then 0 else if r > 0 then  else -)"
| " * ereal r = (if r = 0 then 0 else if r > 0 then  else -)"
| "ereal r * - = (if r = 0 then 0 else if r > 0 then - else )"
| "- * ereal r = (if r = 0 then 0 else if r > 0 then - else )"
| "(::ereal) *  = "
| "-(::ereal) *  = -"
| "(::ereal) * - = -"
| "-(::ereal) * - = "
proof goal_cases
  case prems: (1 P x)
  then obtain a b where "x = (a, b)"
    by (cases x) auto
  with prems show P
    by (cases rule: ereal2_cases[of a b]) auto
qed simp_all
termination by (relation "{}") simp

instance
proof
  fix a b c :: ereal
  show "1 * a = a"
    by (cases a) (simp_all add: one_ereal_def)
  show "a * b = b * a"
    by (cases rule: ereal2_cases[of a b]) simp_all
  show "a * b * c = a * (b * c)"
    by (cases rule: ereal3_cases[of a b c])
       (simp_all add: zero_ereal_def zero_less_mult_iff)
qed

end

lemma [simp]:
  shows ereal_1_times: "ereal 1 * x = x"
  and times_ereal_1: "x * ereal 1 = x"
by(simp_all flip: one_ereal_def)

lemma one_not_le_zero_ereal[simp]: "¬ (1  (0::ereal))"
  by (simp add: one_ereal_def zero_ereal_def)

lemma real_ereal_1[simp]: "real_of_ereal (1::ereal) = 1"
  unfolding one_ereal_def by simp

lemma real_of_ereal_le_1:
  fixes a :: ereal
  shows " 1 ==> real_of_ereal a  1"
  by (cases a) (auto simp: one_ereal_def)

lemma abs_ereal_one[simp]: "1 = (1::ereal)"
  unfolding one_ereal_def by simp

lemma ereal_mult_zero[simp]:
  fixes a :: ereal
  shows "a * 0 = 0"
  by (cases a) (simp_all add: zero_ereal_def)

lemma ereal_zero_mult[simp]:
  fixes a :: ereal
  shows "0 * a = 0"
  by (metis ereal_mult_zero mult.commute)

lemma ereal_m1_less_0[simp]: "-(1::ereal) < 0"
  by (simp add: zero_ereal_def one_ereal_def)

lemma ereal_times[simp]:
  " (::ereal)" "(::ereal)  1"
  " -(::ereal)" "-(::ereal)  1"
  by (auto simp: one_ereal_def)

lemma ereal_plus_1[simp]:
  "1 + ereal r = ereal (r + 1)"
  "ereal r + 1 = ereal (r + 1)"
  "1 + -(::ereal) = -"
  "-(::ereal) + 1 = -"
  unfolding one_ereal_def by auto

lemma ereal_zero_times[simp]:
  fixes a b :: ereal
  shows "a * b = 0  a = 0  b = 0"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_mult_eq_PInfty[simp]:
  "a * b = (::ereal) 
    (a =   b > 0)  (a > 0  b =  (a = -  b < 0)  (a < 0  b = -)"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_mult_eq_MInfty[simp]:
  "a * b = -(::ereal) 
    (a =   b < 0)  (a < 0  b =  (a = -  b > 0)  (a > 0  b = -)"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_abs_mult: "x * y :: ereal = x * y"
  by (cases x y rule: ereal2_cases) (auto simp: abs_mult)

lemma ereal_0_less_1[simp]: "0 < (1::ereal)"
  by (simp add: zero_ereal_def one_ereal_def)

lemma ereal_mult_minus_left[simp]:
  fixes a b :: ereal
  shows "-a * b = - (a * b)"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_mult_minus_right[simp]:
  fixes a b :: ereal
  shows "a * -b = - (a * b)"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_mult_infty[simp]:
  "a * (::ereal) = (if a = 0 then 0 else if 0 < a then  else -)"
  by (cases a) auto

lemma ereal_infty_mult[simp]:
  "(::ereal) * a = (if a = 0 then 0 else if 0 < a then  else -)"
  by (cases a) auto

lemma ereal_mult_strict_right_mono:
  assumes "a < b"
    and "0 < c"
    and "c < (::ereal)"
  shows "a * c < b * c"
  using assms
  by (cases rule: ereal3_cases[of a b c]) (auto simp: zero_le_mult_iff)

lemma ereal_mult_strict_left_mono:
  "a < b ==> 0 < c ==> c < (::ereal) ==> c * a < c * b"
  using ereal_mult_strict_right_mono
  by (simp add: mult.commute[of c])

lemma ereal_mult_right_mono:
  fixes a b c :: ereal
  assumes " b" " c"
  shows "a * c  b * c"
proof (cases "c = 0")
  case False
  with assms show ?thesis
    by (cases rule: ereal3_cases[of a b c]) auto
qed auto

lemma ereal_mult_left_mono:
  fixes a b c :: ereal
  shows " b ==> 0  c ==> c * a  c * b"
  by (simp add: ereal_mult_right_mono mult.commute)

lemma ereal_mult_mono:
  fixes a b c d::ereal
  assumes " 0" " 0" " b" " d"
  shows "a * c  b * d"
  by (metis ereal_mult_right_mono mult.commute order_trans assms)

lemma ereal_mult_mono':
  fixes a b c d::ereal
  assumes " 0" " 0" " b" " d"
  shows "a * c  b * d"
  by (metis ereal_mult_right_mono mult.commute order_trans assms)

lemma ereal_mult_mono_strict:
  fixes a b c d::ereal
  assumes "b > 0" "c > 0" "a < b" "c < d"
  shows "a * c < b * d"
proof -
  have "c < " using c < d
    by auto
  then have "a * c < b * c"
    by (metis ereal_mult_strict_left_mono[OF assms(3) assms(2)] mult.commute)
  moreover have "b * c  b * d"
    using assms(1,4) ereal_mult_left_mono by force
  ultimately show ?thesis by simp
qed

lemma ereal_mult_mono_strict':
  fixes a b c d::ereal
  assumes "a > 0" "c > 0" "a < b" "c < d"
  shows "a * c < b * d"
  using assms ereal_mult_mono_strict by auto

lemma zero_less_one_ereal[simp]: " (1::ereal)"
  by (simp add: one_ereal_def zero_ereal_def)

lemma ereal_0_le_mult[simp]: " a ==> 0  b ==> 0  a * (b :: ereal)"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_right_distrib:
  fixes r a b :: ereal
  shows " a ==> 0  b ==> r * (a + b) = r * a + r * b"
  by (cases rule: ereal3_cases[of r a b]) (simp_all add: field_simps)

lemma ereal_left_distrib:
  fixes r a b :: ereal
  shows " a ==> 0  b ==> (a + b) * r = a * r + b * r"
  by (cases rule: ereal3_cases[of r a b]) (simp_all add: field_simps)

lemma ereal_mult_le_0_iff:
  fixes a b :: ereal
  shows "a * b  0  (0  a  b  0)  (a  0  0  b)"
  by (cases rule: ereal2_cases[of a b]) (simp_all add: mult_le_0_iff)

lemma ereal_zero_le_0_iff:
  fixes a b :: ereal
  shows " a * b  (0  a  0  b)  (a  0  b  0)"
  by (cases rule: ereal2_cases[of a b]) (simp_all add: zero_le_mult_iff)

lemma ereal_mult_less_0_iff:
  fixes a b :: ereal
  shows "a * b < 0  (0 < a  b < 0)  (a < 0  0 < b)"
  by (cases rule: ereal2_cases[of a b]) (simp_all add: mult_less_0_iff)

lemma ereal_zero_less_0_iff:
  fixes a b :: ereal
  shows "0 < a * b  (0 < a  0 < b)  (a < 0  b < 0)"
  by (cases rule: ereal2_cases[of a b]) (simp_all add: zero_less_mult_iff)

lemma ereal_left_mult_cong:
  fixes a b c :: ereal
  shows "c = d ==> (d  0 ==> a = b) ==> a * c = b * d"
  by (cases "c = 0") simp_all

lemma ereal_right_mult_cong:
  fixes a b c :: ereal
  shows "c = d ==> (d  0 ==> a = b) ==> c * a = d * b"
  by (cases "c = 0") simp_all

lemma ereal_distrib:
  fixes a b c :: ereal
  assumes "   b  -"
    and " -  b  "
    and "c  "
  shows "(a + b) * c = a * c + b * c"
  using assms
  by (cases rule: ereal3_cases[of a b c]) (simp_all add: field_simps)

lemma numeral_eq_ereal [simp]: "numeral w = ereal (numeral w)"
proof (induct w rule: num_induct)
  case One
  then show ?case
    by simp
next
  case (inc x)
  then show ?case
    by (simp add: inc numeral_inc)
qed

lemma m1_ereal_less_iff [simp]:
  "((-1::ereal) < numeral a)  ((-1::real) < numeral a)"
  by (simp add: one_ereal_def)

lemma m1_ereal_le_iff [simp]:
  "((-1::ereal)  numeral a)  ((-1::real)  numeral a)"
  by (simp add: one_ereal_def)

lemma m1_ereal_eq_iff [simp]:
  "((-1::ereal) = numeral a)  ((-1::real) = numeral a)"
  by (simp add: one_ereal_def)

lemma ereal_less_m1_iff [simp]:
  "(numeral a < (-1::ereal))  (numeral a < (-1::real))"
  by (simp add: one_ereal_def)

lemma ereal_le_m1_iff [simp]:
  "(numeral a  (-1::ereal))  (numeral a  (-1::real))"
  by (simp add: one_ereal_def)

lemma ereal_eq_m1_iff [simp]:
  "(numeral a = (-1::ereal))  (numeral a = (-1::real))"
  by (simp add: one_ereal_def)

lemma distrib_left_ereal_nn:
  " 0 ==> (x + y) * ereal c = x * ereal c + y * ereal c"
  by(cases x y rule: ereal2_cases)(simp_all add: ring_distribs)

lemma sum_ereal_right_distrib:
  fixes f :: "'a ==> ereal"
  shows "(i. i  A ==> 0  f i) ==> r * sum f A = (nA. r * f n)"
  by (induct A rule: infinite_finite_induct) (auto simp: ereal_right_distrib sum_nonneg)

lemma sum_ereal_left_distrib:
  "(i. i  A ==> 0  f i) ==> sum f A * r = (nA. f n * r :: ereal)"
  using sum_ereal_right_distrib[of A f r] by (simp add: mult_ac)

lemma sum_distrib_right_ereal:
  " 0 ==> sum f A * ereal c = (xA. f x * c :: ereal)"
by(subst sum_comp_morphism[where h="λx. x * ereal c", symmetric])(simp_all add: distrib_left_ereal_nn)

lemma ereal_le_epsilon:
  fixes x y :: ereal
  assumes "e. 0 < e ==> x  y + e"
  shows " y"
proof (cases "x = -  x =   y = -  y = ")
  case True
  then show ?thesis
    using assms[of 1] by auto
next
  case False
  then obtain p q where "x = ereal p" "y = ereal q"
    by (metis MInfty_eq_minfinity ereal.distinct(3) uminus_ereal.elims)
  then show ?thesis
    by (metis assms field_le_epsilon ereal_less(2) ereal_less_eq(3) plus_ereal.simps(1))
qed

lemma ereal_le_epsilon2:
  fixes x y :: ereal
  assumes "e::real. 0 < e ==> x  y + ereal e"
  shows " y"
proof (rule ereal_le_epsilon)
  show "ε::ereal. 0 < ε ==> x  y + ε"
  using assms less_ereal.elims(2) zero_less_real_of_ereal by fastforce
qed

lemma ereal_le_real:
  fixes x y :: ereal
  assumes "z. x  ereal z ==> y  ereal z"
  shows " x"
  by (metis assms ereal_bot ereal_cases ereal_infty_less_eq(2) ereal_less_eq(1) linorder_le_cases)

lemma prod_ereal_0:
  fixes f :: "'a ==> ereal"
  shows "(iA. f i) = 0  finite A  (iA. f i = 0)"
  by (induction A rule: infinite_finite_induct) auto

lemma prod_ereal_pos:
  fixes f :: "'a ==> ereal"
  assumes "i. i  I ==> 0  f i"
  shows " (iI. f i)"
  using assms
  by (induction I rule: infinite_finite_induct) auto

lemma prod_PInf:
  fixes f :: "'a ==> ereal"
  assumes "i. i  I ==> 0  f i"
  shows "(iI. f i) =   finite I  (iI. f i =  (iI. f i  0)"
  using assms
proof (induction I rule: infinite_finite_induct)
  case (insert i I)
  then have pos: " f i" " prod f I"
    by (auto intro!: prod_ereal_pos)
  from insert have "(jinsert i I. f j) =   prod f I * f i = "
    by auto
  also have "  (prod f I =   f i =  f i  0  prod f I  0"
    using prod_ereal_pos[of I f] pos
    by (cases rule: ereal2_cases[of "f i" "prod f I"]) auto
  also have "  finite (insert i I)  (jinsert i I. f j =  (jinsert i I. f j  0)"
    using insert by (auto simp: prod_ereal_0)
  finally show ?case .
qed auto

lemma prod_ereal: "(iA. ereal (f i)) = ereal (prod f A)"
  by (induction A rule: infinite_finite_induct) (auto simp: one_ereal_def)


subsubsection Power

lemma ereal_power[simp]: "(ereal x) ^ n = ereal (x^n)"
  by (induct n) (auto simp: one_ereal_def)

lemma ereal_power_PInf[simp]: "(::ereal) ^ n = (if n = 0 then 1 else )"
  by (induct n) (auto simp: one_ereal_def)

lemma ereal_power_uminus[simp]:
  fixes x :: ereal
  shows "(- x) ^ n = (if even n then x ^ n else - (x^n))"
  by (induct n) (auto simp: one_ereal_def)

lemma ereal_power_numeral[simp]:
  "(numeral num :: ereal) ^ n = ereal (numeral num ^ n)"
  by (induct n) (auto simp: one_ereal_def)

lemma zero_le_power_ereal[simp]:
  fixes a :: ereal
  assumes " a"
  shows " a ^ n"
  using assms by (induct n) (auto simp: ereal_zero_le_0_iff)


subsubsection Subtraction

lemma ereal_minus_minus_image[simp]:
  fixes S :: "ereal set"
  shows "uminus ` uminus ` S = S"
  by (auto simp: image_iff)

lemma ereal_uminus_lessThan[simp]:
  fixes a :: ereal
  shows "uminus ` {..<a} = {-a<..}"
  by (force simp: ereal_uminus_less_reorder)

lemma ereal_uminus_greaterThan[simp]: "uminus ` {(a::ereal)<..} = {..<-a}"
  by (metis ereal_uminus_lessThan ereal_uminus_uminus ereal_minus_minus_image)

instantiation ereal :: minus
begin

definition "x - y = x + -(y::ereal)"
instance ..

end

lemma ereal_minus[simp]:
  "ereal r - ereal p = ereal (r - p)"
  "- - ereal r = -"
  "ereal r - = -"
  "(::ereal) - x = "
  "-(::ereal) - = -"
  "x - -y = x + y"
  "x - 0 = x"
  "0 - x = -x"
  by (simp_all add: minus_ereal_def)

lemma ereal_x_minus_x[simp]: "x - x = (if x =  then  else 0::ereal)"
  by auto

lemma ereal_eq_minus_iff:
  fixes x y z :: ereal
  shows "x = z - y 
    (y    x + y = z) 
    (y = -  x = 
    (y =   z =   x = 
    (y =   z    x = -)"
  by (cases rule: ereal3_cases[of x y z]) auto

lemma ereal_eq_minus:
  fixes x y z :: ereal
  shows "y   ==> x = z - y  x + y = z"
  by (auto simp: ereal_eq_minus_iff)

lemma ereal_less_minus_iff:
  fixes x y z :: ereal
  shows "x < z - y 
    (y =   z =   x  
    (y = -  x  
    (y   x + y < z)"
  by (cases rule: ereal3_cases[of x y z]) auto

lemma ereal_less_minus:
  fixes x y z :: ereal
  shows "y   ==> x < z - y  x + y < z"
  by (auto simp: ereal_less_minus_iff)

lemma ereal_le_minus_iff:
  fixes x y z :: ereal
  shows " z - y  (y =   z    x = - (y    x + y  z)"
  by (cases rule: ereal3_cases[of x y z]) auto

lemma ereal_le_minus:
  fixes x y z :: ereal
  shows "y   ==> x  z - y  x + y  z"
  by (auto simp: ereal_le_minus_iff)

lemma ereal_minus_less_iff:
  fixes x y z :: ereal
  shows "x - y < z  y  -  (y =   x    z  - (y    x < z + y)"
  by (cases rule: ereal3_cases[of x y z]) auto

lemma ereal_minus_less:
  fixes x y z :: ereal
  shows "y   ==> x - y < z  x < z + y"
  by (auto simp: ereal_minus_less_iff)

lemma ereal_minus_le_iff:
  fixes x y z :: ereal
  shows "x - y  z 
    (y = -  z = 
    (y =   x =   z = 
    (y    x  z + y)"
  by (cases rule: ereal3_cases[of x y z]) auto

lemma ereal_minus_le:
  fixes x y z :: ereal
  shows "y   ==> x - y  z  x  z + y"
  by (auto simp: ereal_minus_le_iff)

lemma ereal_minus_eq_minus_iff:
  fixes a b c :: ereal
  shows "a - b = a - c 
    b = c  a =   (a = -  b  -  c  -)"
  by (cases rule: ereal3_cases[of a b c]) auto

lemma ereal_add_le_add_iff:
  fixes a b c :: ereal
  shows "c + a  c + b 
    a  b  c =   (c = -  a    b  )"
  by (cases rule: ereal3_cases[of a b c]) (simp_all add: field_simps)

lemma ereal_add_le_add_iff2:
  fixes a b c :: ereal
  shows "a + c  b + c  a  b  c =   (c = -  a    b  )"
  by (metis (no_types, lifting) add.commute ereal_add_le_add_iff)

lemma ereal_mult_le_mult_iff:
  fixes a b c :: ereal
  shows "c   ==> c * a  c * b  (0 < c  a  b)  (c < 0  b  a)"
  by (cases rule: ereal3_cases[of a b c]) (simp_all add: mult_le_cancel_left)

lemma ereal_minus_mono:
  fixes A B C D :: ereal assumes " B" " C"
  shows "A - C  B - D"
  using assms
  by (cases rule: ereal3_cases[case_product ereal_cases, of A B C D]) simp_all

lemma ereal_mono_minus_cancel:
  fixes a b c :: ereal
  shows "c - a  c - b ==> 0  c ==> c <  ==> b  a"
  by (cases a b c rule: ereal3_cases) auto

lemma real_of_ereal_minus:
  fixes a b :: ereal
  shows "real_of_ereal (a - b) = (if a =   b =  then 0 else real_of_ereal a - real_of_ereal b)"
  by (cases rule: ereal2_cases[of a b]) auto

lemma real_of_ereal_minus': "x =   y =  ==> real_of_ereal x - real_of_ereal y = real_of_ereal (x - y :: ereal)"
by(subst real_of_ereal_minus) auto

lemma ereal_diff_positive:
  fixes a b :: ereal shows " b ==> 0  b - a"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_between:
  fixes x e :: ereal
  assumes "x  " and "0 < e"
  shows "x - e < x"
    and "x < x + e"
  using assms by (cases x, cases e, auto)+

lemma ereal_minus_eq_PInfty_iff:
  fixes x y :: ereal
  shows "x - y =   y = -  x = "
  by (cases x y rule: ereal2_cases) simp_all

lemma ereal_diff_add_eq_diff_diff_swap:
  fixes x y z :: ereal
  shows "y   ==> x - (y + z) = x - y - z"
  by(cases x y z rule: ereal3_cases) simp_all

lemma ereal_diff_add_assoc2:
  fixes x y z :: ereal
  shows "x + y - z = x - z + y"
  by(cases x y z rule: ereal3_cases) simp_all

lemma ereal_add_uminus_conv_diff: fixes x y z :: ereal shows "- x + y = y - x"
  by (simp add: add.commute minus_ereal_def)

lemma ereal_minus_diff_eq:
  fixes x y :: ereal
  shows "[ x =   y  ; x = -  y  - ] ==> - (x - y) = y - x"
  by(cases x y rule: ereal2_cases) simp_all

lemma ediff_le_self [simp]: "x - y  (x :: enat)"
  by(cases x y rule: enat.exhaust[case_product enat.exhaust]) simp_all

lemma ereal_abs_diff:
  fixes a b::ereal
  shows "abs(a-b)  abs a + abs b"
  by (cases rule: ereal2_cases[of a b]) (auto)


subsubsection Division

instantiation ereal :: inverse
begin

function inverse_ereal where
  "inverse (ereal r) = (if r = 0 then  else ereal (inverse r))"
| "inverse (::ereal) = 0"
| "inverse (-::ereal) = 0"
  by (auto intro: ereal_cases)
termination by (relation "{}") simp

definition "x div y = x * inverse (y :: ereal)"

instance ..

end

lemma real_of_ereal_inverse[simp]:
  fixes a :: ereal
  shows "real_of_ereal (inverse a) = 1 / real_of_ereal a"
  by (cases a) (auto simp: inverse_eq_divide)

lemma ereal_inverse[simp]:
  "inverse (0::ereal) = "
  "inverse (1::ereal) = 1"
  by (simp_all add: one_ereal_def zero_ereal_def)

lemma ereal_divide[simp]:
  "ereal r / ereal p = (if p = 0 then ereal r *  else ereal (r / p))"
  unfolding divide_ereal_def by (auto simp: divide_real_def)

lemma ereal_divide_same[simp]:
  fixes x :: ereal
  shows "x / x = (if x =   x = 0 then 0 else 1)"
  by (cases x) (simp_all add: divide_real_def divide_ereal_def one_ereal_def)

lemma ereal_inv_inv[simp]:
  fixes x :: ereal
  shows "inverse (inverse x) = (if x  - then x else )"
  by (cases x) auto

lemma ereal_inverse_minus[simp]:
  fixes x :: ereal
  shows "inverse (- x) = (if x = 0 then  else -inverse x)"
  by (cases x) simp_all

lemma ereal_uminus_divide[simp]:
  fixes x y :: ereal
  shows "- x / y = - (x / y)"
  unfolding divide_ereal_def by simp

lemma ereal_divide_Infty[simp]:
  fixes x :: ereal
  shows "x /  = 0" "x / - = 0"
  unfolding divide_ereal_def by simp_all

lemma ereal_divide_one[simp]: "x / 1 = (x::ereal)"
  unfolding divide_ereal_def by simp

lemma ereal_divide_ereal[simp]: " / ereal r = (if 0  r then  else -)"
  unfolding divide_ereal_def by simp

lemma ereal_inverse_nonneg_iff: " inverse (x :: ereal)  0  x  x = -"
  by (cases x) auto

lemma inverse_ereal_ge0I: " (x :: ereal) ==> 0  inverse x"
by(cases x) simp_all

lemma zero_le_divide_ereal[simp]:
  fixes a :: ereal
  assumes " a" and " b"
  shows " a / b"
  by (simp add: assms divide_ereal_def ereal_inverse_nonneg_iff)

lemma ereal_le_divide_pos:
  fixes x y z :: ereal
  shows "x > 0 ==> x   ==> y  z / x  x * y  z"
  by (cases rule: ereal3_cases[of x y z]) (auto simp: field_simps)

lemma ereal_divide_le_pos:
  fixes x y z :: ereal
  shows "x > 0 ==> x   ==> z / x  y  z  x * y"
  by (cases rule: ereal3_cases[of x y z]) (auto simp: field_simps)

lemma ereal_le_divide_neg:
  fixes x y z :: ereal
  shows "x < 0 ==> x  - ==> y  z / x  z  x * y"
  by (cases rule: ereal3_cases[of x y z]) (auto simp: field_simps)

lemma ereal_divide_le_neg:
  fixes x y z :: ereal
  shows "x < 0 ==> x  - ==> z / x  y  x * y  z"
  by (cases rule: ereal3_cases[of x y z]) (auto simp: field_simps)

lemma ereal_inverse_antimono_strict:
  fixes x y :: ereal
  shows " x ==> x < y ==> inverse y < inverse x"
  by (cases rule: ereal2_cases[of x y]) auto

lemma ereal_inverse_antimono:
  fixes x y :: ereal
  shows " x ==> x  y ==> inverse y  inverse x"
  by (cases rule: ereal2_cases[of x y]) auto

lemma inverse_inverse_Pinfty_iff[simp]:
  fixes x :: ereal
  shows "inverse x =   x = 0"
  by (cases x) auto

lemma ereal_inverse_eq_0:
  fixes x :: ereal
  shows "inverse x = 0  x =   x = -"
  by (cases x) auto

lemma ereal_0_gt_inverse:
  fixes x :: ereal
  shows "0 < inverse x  x    0  x"
  by (cases x) auto

lemma ereal_inverse_le_0_iff:
  fixes x :: ereal
  shows "inverse x  0  x < 0  x = "
  by(cases x) auto

lemma ereal_divide_eq_0_iff: "x / y = 0  x = 0  y :: ereal = "
by(cases x y rule: ereal2_cases) simp_all

lemma ereal_mult_less_right:
  fixes a b c :: ereal
  assumes "b * a < c * a" "0 < a" "a < "
  shows "b < c"
  using assms
  by (metis order.asym ereal_mult_strict_left_mono linorder_neqE mult.commute)

lemma ereal_mult_divide:
  fixes a b :: ereal
  shows "0 < b ==> b <  ==> b * (a / b) = a"
  by (cases a b rule: ereal2_cases) auto

lemma ereal_power_divide:
  fixes x y :: ereal
  shows " 0 ==> (x / y) ^ n = x^n / y^n"
  by (cases rule: ereal2_cases [of x y])
     (auto simp: one_ereal_def zero_ereal_def power_divide zero_le_power_eq)

lemma ereal_le_mult_one_interval:
  fixes x y :: ereal
  assumes y: " -"
  assumes z: "z. 0 < z ==> z < 1 ==> z * x  y"
  shows " y"
proof (cases x)
  case PInf
  with z[of "1 / 2"] show " y"
    by (simp add: one_ereal_def)
next
  case r: (real r)
  show " y"
  proof (cases y)
    case p: (real p)
    have " p"
    proof (rule field_le_mult_one_interval)
      fix z :: real
      assume "0 < z" and "z < 1"
      with z[of "ereal z"] show "z * r  p"
        using p r by (auto simp: zero_le_mult_iff one_ereal_def)
    qed
    then show " y"
      using p r by simp
  qed (use y in simp_all)
qed simp

lemma ereal_divide_right_mono[simp]:
  fixes x y z :: ereal
  assumes " y"
    and "0 < z"
  shows "x / z  y / z"
  using assms by (cases x y z rule: ereal3_cases) (auto intro: divide_right_mono)

lemma ereal_divide_left_mono[simp]:
  fixes x y z :: ereal
  assumes " x"
    and "0 < z"
    and "0 < x * y"
  shows "z / x  z / y"
  using assms
  by (cases x y z rule: ereal3_cases)
     (auto intro: divide_left_mono simp: field_simps zero_less_mult_iff mult_less_0_iff split: if_split_asm)

lemma ereal_divide_zero_left[simp]:
  fixes a :: ereal
  shows "0 / a = 0"
  using ereal_divide_eq_0_iff by blast

lemma ereal_times_divide_eq_left[simp]:
  fixes a b c :: ereal
  shows "b / c * a = b * a / c"
  by (metis divide_ereal_def mult.assoc mult.commute)

lemma ereal_times_divide_eq: "a * (b / c :: ereal) = a * b / c"
  by (metis ereal_times_divide_eq_left mult.commute)

lemma ereal_inverse_real [simp]: "z   ==> z  0 ==> ereal (inverse (real_of_ereal z)) = inverse z"
  by auto

lemma ereal_inverse_mult:
  " 0 ==> b  0 ==> inverse (a * (b::ereal)) = inverse a * inverse b"
  by (cases a; cases b) auto

lemma inverse_eq_infinity_iff_eq_zero [simp]:
  "1/(x::ereal) =   x = 0"
by (simp add: divide_ereal_def)

lemma ereal_distrib_left:
  fixes a b c :: ereal
  assumes "   b  -"
      and " -  b  "
      and "c  "
  shows "c * (a + b) = c * a + c * b"
  by (metis assms ereal_distrib mult.commute)

lemma ereal_distrib_minus_left:
  fixes a b c :: ereal
  assumes "   b  "
      and " -  b  -"
      and "c  "
  shows "c * (a - b) = c * a - c * b"
  using assms ereal_distrib_left ereal_uminus_eq_reorder minus_ereal_def by auto

lemma ereal_distrib_minus_right:
  fixes a b c :: ereal
  assumes "   b  "
      and " -  b  -"
      and "c  "
  shows "(a - b) * c = a * c - b * c"
  by (metis assms ereal_distrib_minus_left mult.commute)


subsection "Complete lattice"

instantiation ereal :: lattice
begin

definition [simp]: "sup x y = (max x y :: ereal)"
definition [simp]: "inf x y = (min x y :: ereal)"
instance by standard simp_all

end

instantiation ereal :: complete_lattice
begin

definition "bot = (-::ereal)"
definition "top = (::ereal)"

definition "Sup S = (SOME x :: ereal. (yS. y  x)  (z. (yS. y  z)  x  z))"
definition "Inf S = (SOME x :: ereal. (yS. x  y)  (z. (yS. z  y)  z  x))"

lemma ereal_complete_Sup:
  fixes S :: "ereal set"
  shows "x. (yS. y  x)  (z. (yS. y  z)  x  z)"
proof (cases "x. aS. a  ereal x")
  case True
  then obtain y where y: " ereal y" if "aS" for a
    by auto
  then have "  S"
    by force
  show ?thesis
  proof (cases " {- S  {}")
    case True
    with S obtain x where x: " S" "x  "
      by auto
    obtain s where s: "xereal -` S. x  s" "(xereal -` S. x  z) ==> s  z" for z
    proof (atomize_elim, rule complete_real)
      show "x. x  ereal -` S"
        using x by auto
      show "z. xereal -` S. x  z"
        by (auto dest: y intro!: exI[of _ y])
    qed
    show ?thesis
    proof (safe intro!: exI[of _ "ereal s"])
      fix y
      assume " S"
      with s S show " ereal s"
        by (cases y) auto
    next
      fix z
      assume "yS. y  z"
      with S {-} S {} show "ereal s  z"
        by (cases z) (auto intro!: s)
    qed
  next
    case False
    then show ?thesis
      by (auto intro!: exI[of _ "-"])
  qed
next
  case False
  then show ?thesis
    by (fastforce intro!: exI[of _ ] ereal_top intro: order_trans dest: less_imp_le simp: not_le)
qed

lemma ereal_complete_uminus_eq:
  fixes S :: "ereal set"
  shows "(yuminus`S. y  x)  (z. (yuminus`S. y  z)  x  z)
      (yS. -x  y)  (z. (yS. z  y)  z  -x)"
  by simp (metis ereal_minus_le_minus ereal_uminus_uminus)

lemma ereal_complete_Inf:
  "x. (yS::ereal set. x  y)  (z. (yS. z  y)  z  x)"
  using ereal_complete_Sup[of "uminus ` S"]
  unfolding ereal_complete_uminus_eq
  by auto

instance
proof
  show "Sup {} = (bot::ereal)"
    using ereal_bot by (auto simp: bot_ereal_def Sup_ereal_def)
  show "Inf {} = (top::ereal)"
    unfolding top_ereal_def Inf_ereal_def
    using ereal_infty_less_eq(1) ereal_less_eq(1) by blast
  show "x::ereal. A. x  A ==> Inf A  x"
       "A z. (x::ereal. x  A ==> z  x) ==> z  Inf A"
    by (auto intro: someI2_ex ereal_complete_Inf simp: Inf_ereal_def)
  show "x::ereal. A. x  A ==> x  Sup A"
       "A z. (x::ereal. x  A ==> x  z) ==> Sup A  z"
    by (auto intro: someI2_ex ereal_complete_Sup simp: Sup_ereal_def)
qed

end

instance ereal :: complete_linorder ..

instance ereal :: linear_continuum
proof
  show "a b::ereal. a  b"
    using zero_neq_one by blast
qed

lemma min_PInf [simp]: "min (::ereal) x = x"
  by (metis min_top top_ereal_def)

lemma min_PInf2 [simp]: "min x (::ereal) = x"
  by (metis min_top2 top_ereal_def)

lemma max_PInf [simp]: "max (::ereal) x = "
  by (metis max_top top_ereal_def)

lemma max_PInf2 [simp]: "max x (::ereal) = "
  by (metis max_top2 top_ereal_def)

lemma min_MInf [simp]: "min (-::ereal) x = -"
  by (metis min_bot bot_ereal_def)

lemma min_MInf2 [simp]: "min x (-::ereal) = -"
  by (metis min_bot2 bot_ereal_def)

lemma max_MInf [simp]: "max (-::ereal) x = x"
  by (metis max_bot bot_ereal_def)

lemma max_MInf2 [simp]: "max x (-::ereal) = x"
  by (metis max_bot2 bot_ereal_def)

subsection Extended real intervals

lemma real_greaterThanLessThan_infinity_eq:
  "real_of_ereal ` {N::ereal<..<} =
    (if N =  then {} else if N = - then UNIV else {real_of_ereal N<..})"
  by (force simp: real_less_ereal_iff intro!: image_eqI[where x="ereal _"] elim!: less_ereal.elims)

lemma real_greaterThanLessThan_minus_infinity_eq:
  "real_of_ereal ` {-<..<N::ereal} =
    (if N =  then UNIV else if N = - then {} else {..<real_of_ereal N})"
proof -
  have "real_of_ereal ` {-<..<N::ereal} = uminus ` real_of_ereal ` {-N<..<}"
    by (auto simp: ereal_uminus_less_reorder intro!: image_eqI[where x="-x" for x])
  also note real_greaterThanLessThan_infinity_eq
  finally show ?thesis by (auto intro!: image_eqI[where x="-x" for x])
qed

lemma real_greaterThanLessThan_inter:
  "real_of_ereal ` {N<..<M::ereal} = real_of_ereal ` {-<..<M}  real_of_ereal ` {N<..<}"
  by (force elim!: less_ereal.elims)

lemma real_atLeastGreaterThan_eq: "real_of_ereal ` {N<..<M::ereal} =
   (if N =  then {} else
   if N = - then
    (if M =  then UNIV
    else if M = - then {}
    else {..< real_of_ereal M})
  else if M = - then {}
  else if M =  then {real_of_ereal N<..}
  else {real_of_ereal N <..< real_of_ereal M})"
proof (cases "M = -  M =   N = -  N = ")
  case True
  then show ?thesis
    by (auto simp: real_greaterThanLessThan_minus_infinity_eq real_greaterThanLessThan_infinity_eq )
next
  case False
  then obtain p q where "M = ereal p" "N = ereal q"
    by (metis MInfty_eq_minfinity ereal.distinct(3) uminus_ereal.elims)
  moreover have "x. [q < x; x < p] ==> x  real_of_ereal ` {ereal q<..<ereal p}"
    by (metis greaterThanLessThan_iff imageI less_ereal.simps(1) real_of_ereal.simps(1))
  ultimately show ?thesis
    by (auto elim!: less_ereal.elims)
qed

lemma real_image_ereal_ivl:
  fixes a b::ereal
  shows
  "real_of_ereal ` {a<..<b} =
  (if a < b then (if a = - then if b =  then UNIV else {..<real_of_ereal b}
  else if b =  then {real_of_ereal a<..} else {real_of_ereal a <..< real_of_ereal b}) else {})"
  by (cases a; cases b; simp add: real_atLeastGreaterThan_eq not_less)

lemma fixes a b c::ereal
  shows not_inftyI: "a < b ==> b < c ==> abs b  "
  by force

context
  fixes r s t::real
begin

lemma interval_Ioo_neq_Ioi: "{r<..<s}  {t<..}"
  by (simp add: set_eq_iff) (meson linordered_field_no_ub nless_le order_less_trans)

lemma interval_Ioo_neq_Iio: "{r<..<s}  {..<t}"
  by (simp add: set_eq_iff) (meson linordered_field_no_lb order_less_irrefl order_less_trans)

lemma interval_neq_ioo_UNIV: "{r<..<s}  UNIV"
  and interval_Ioi_neq_UNIV: "{r<..}  UNIV"
  and interval_Iio_neq_UNIV: "{..<r}  UNIV"
  by auto

lemma interval_Ioi_neq_Iio: "{r<..}  {..<s}"
  by (simp add: set_eq_iff) (meson lt_ex order_less_irrefl order_less_trans)

lemma interval_empty_neq_Ioi: "{}  {r<..}"
  and interval_empty_neq_Iio: "{}  {..<r}"
  by (auto simp: set_eq_iff linordered_field_no_ub linordered_field_no_lb)

end

lemmas interval_neqs = interval_Ioo_neq_Ioi interval_Ioo_neq_Iio
                       interval_neq_ioo_UNIV interval_Ioi_neq_Iio
                       interval_Ioi_neq_UNIV interval_Iio_neq_UNIV
                       interval_empty_neq_Ioi interval_empty_neq_Iio

lemma greaterThanLessThan_eq_iff:
  fixes r s t u::real
  shows "({r<..<s} = {t<..<u}) = (r  s  u  t  r = t  s = u)"
  by (metis cInf_greaterThanLessThan cSup_greaterThanLessThan greaterThanLessThan_empty_iff not_le)

lemma real_of_ereal_image_greaterThanLessThan_iff:
  "real_of_ereal ` {a <..< b} = real_of_ereal ` {c <..< d}  (a  b  c  d  a = c  b = d)"
  unfolding real_atLeastGreaterThan_eq
  by (cases a; cases b; cases c; cases d;
    simp add: greaterThanLessThan_eq_iff interval_neqs interval_neqs[symmetric])

lemma uminus_image_real_of_ereal_image_greaterThanLessThan:
  "uminus ` real_of_ereal ` {l <..< u} = real_of_ereal ` {-u <..< -l}"
  by (force simp: algebra_simps ereal_less_uminus_reorder
    ereal_uminus_less_reorder intro: image_eqI[where x="-x" for x])

lemma add_image_real_of_ereal_image_greaterThanLessThan:
  "(+) c ` real_of_ereal ` {l <..< u} = real_of_ereal ` {c + l <..< c + u}"
  apply safe
  subgoal for x
    using ereal_less_add[of c]
    by (force simp: real_of_ereal_add add.commute)
  subgoal for _ x
    by (force simp: add.commute real_of_ereal_minus ereal_minus_less ereal_less_minus
      intro: image_eqI[where x="x - c"])
  done

lemma add2_image_real_of_ereal_image_greaterThanLessThan:
  "(λx. x + c) ` real_of_ereal ` {l <..< u} = real_of_ereal ` {l + c <..< u + c}"
  using add_image_real_of_ereal_image_greaterThanLessThan[of c l u]
  by (metis add.commute image_cong)

lemma minus_image_real_of_ereal_image_greaterThanLessThan:
  "(-) c ` real_of_ereal ` {l <..< u} = real_of_ereal ` {c - u <..< c - l}"
  (is "?l = ?r")
proof -
  have "?l = (+) c ` uminus ` real_of_ereal ` {l <..< u}" by auto
  also note uminus_image_real_of_ereal_image_greaterThanLessThan
  also note add_image_real_of_ereal_image_greaterThanLessThan
  finally show ?thesis by (simp add: minus_ereal_def)
qed

lemma real_ereal_bound_lemma_up:
  assumes " real_of_ereal ` {a<..<b}"
  assumes " real_of_ereal ` {a<..<b}"
  assumes " t"
  shows " "
proof (cases b)
  case PInf
  then show ?thesis
    using assms
    by (metis UNIV_I empty_iff greaterThan_iff order_less_le_trans real_image_ereal_ivl)
qed auto

lemma real_ereal_bound_lemma_down:
  assumes s: " real_of_ereal ` {a<..<b}"
  and t: " real_of_ereal ` {a<..<b}"
  and " s"
shows " -"
  by (metis UNIV_I assms empty_iff lessThan_iff order_le_less_trans
      real_greaterThanLessThan_minus_infinity_eq)


subsection "Topological space"

instantiation ereal :: linear_continuum_topology
begin

definition "open_ereal" :: "ereal set ==> bool" where
  open_ereal_generated: "open_ereal = generate_topology (range lessThan  range greaterThan)"

instance
  by standard (simp add: open_ereal_generated)

end

lemma continuous_on_ereal[continuous_intros]:
  assumes f: "continuous_on s f" shows "continuous_on s (λx. ereal (f x))"
  by (rule continuous_on_compose2 [OF continuous_onI_mono[of ereal UNIV] f]) auto

lemma tendsto_ereal[tendsto_intros, simp, intro]: "(f ---> x) F ==> ((λx. ereal (f x)) ---> ereal x) F"
  using isCont_tendsto_compose[of x ereal f F] continuous_on_ereal[of UNIV "λx. x"]
  by (simp add: continuous_on_eq_continuous_at)

lemma tendsto_uminus_ereal[tendsto_intros, simp, intro]:
  assumes "(f ---> x) F"
  shows "((λx. - f x::ereal) ---> - x) F"
proof (rule tendsto_compose[OF order_tendstoI assms])
  show "a. a < - x ==> 🪙F x in at x. a < - x"
    by (metis ereal_less_uminus_reorder eventually_at_topological lessThan_iff open_lessThan)
  show "a. - x < a ==> 🪙F x in at x. - x < a"
    by (metis ereal_uminus_reorder(2) eventually_at_topological greaterThan_iff open_greaterThan)
qed



lemma at_infty_ereal_eq_at_top: "at  = filtermap ereal at_top"
proof -
  have "P b. z. b  z  b  z  P (ereal z) ==> N. nN. P (ereal n)"
    by (metis gt_ex order_less_le order_less_le_trans)
  then show ?thesis
    unfolding filter_eq_iff eventually_at_filter eventually_at_top_linorder eventually_filtermap
      top_ereal_def[symmetric]
    apply (subst eventually_nhds_top[of 0])
     apply (auto simp: top_ereal_def less_le ereal_all_split ereal_ex_split)
    done
qed

lemma ereal_Lim_uminus: "(f ---> f0) net  ((λx. - f x::ereal) ---> - f0) net"
  using tendsto_uminus_ereal[of f f0 net] tendsto_uminus_ereal[of "λx. - f x" "- f0" net]
  by auto

lemma ereal_divide_less_iff: "0 < (c::ereal) ==> c <  ==> a / c < b  a < b * c"
  by (cases a b c rule: ereal3_cases) (auto simp: field_simps)

lemma ereal_less_divide_iff: "0 < (c::ereal) ==> c <  ==> a < b / c  a * c < b"
  by (cases a b c rule: ereal3_cases) (auto simp: field_simps)

lemma tendsto_cmult_ereal[tendsto_intros, simp, intro]:
  assumes c: "c  " and f: "(f ---> x) F"
  shows "((λx. c * f x::ereal) ---> c * x) F"
proof -
  have *: "((λx. c * f x::ereal) ---> c * x) F" if "0 < c" "c < " for c :: ereal
    using that
    apply (intro tendsto_compose[OF _ f])
    apply (auto intro!: order_tendstoI simp: eventually_at_topological)
     apply (rule_tac x="{a/c <..}" in exI)
     apply (auto split: ereal.split simp: ereal_divide_less_iff mult.commute) []
    apply (rule_tac x="{..< a/c}" in exI)
    apply (auto split: ereal.split simp: ereal_less_divide_iff mult.commute) []
    done
  have "((0 < c  c <  (- < c  c < 0)  c = 0)"
    using c by (cases c) auto
  then show ?thesis
  proof (elim disjE conjE)
    assume "- < c" "c < 0"
    then have "0 < - c" "- c < "
      by (auto simp: ereal_uminus_reorder ereal_less_uminus_reorder[of 0])
    then have "((λx. (- c) * f x) ---> (- c) * x) F"
      by (rule *)
    from tendsto_uminus_ereal[OF this] show ?thesis
      by simp
  qed (auto intro!: *)
qed

lemma tendsto_cmult_ereal_not_0[tendsto_intros, simp, intro]:
  assumes " 0" and f: "(f ---> x) F"
  shows "((λx. c * f x::ereal) ---> c * x) F"
proof cases
  assume "c = "
  show ?thesis
  proof (rule filterlim_cong[THEN iffD1, OF refl refl _ tendsto_const])
    have "0 < x  x < 0"
      using x 0 by (auto simp: neq_iff)
    then show "eventually (λx'. c * x = c * f x') F"
    proof
      assume "0 < x" from order_tendstoD(1)[OF f this] show ?thesis
        by eventually_elim (use 0 c = in auto)
    next
      assume "x < 0" from order_tendstoD(2)[OF f this] show ?thesis
        by eventually_elim (use x<0 c = in auto)
    qed
  qed
qed (rule tendsto_cmult_ereal[OF _ f])

lemma tendsto_cadd_ereal[tendsto_intros, simp, intro]:
  assumes c: " -" " -" and f: "(f ---> x) F"
  shows "((λx. f x + y::ereal) ---> x + y) F"
  apply (intro tendsto_compose[OF _ f])
  apply (auto intro!: order_tendstoI simp: eventually_at_topological)
  apply (rule_tac x="{a - y <..}" in exI)
  apply (auto split: ereal.split simp: ereal_minus_less_iff c) []
  apply (rule_tac x="{..< a - y}" in exI)
  apply (auto split: ereal.split simp: ereal_less_minus_iff c) []
  done

lemma tendsto_add_left_ereal[tendsto_intros, simp, intro]:
  assumes c: "y  " and f: "(f ---> x) F"
  shows "((λx. f x + y::ereal) ---> x + y) F"
  apply (intro tendsto_compose[OF _ f])
  apply (auto intro!: order_tendstoI simp: eventually_at_topological)
  apply (rule_tac x="{a - y <..}" in exI)
  apply (insert c, auto split: ereal.split simp: ereal_minus_less_iff) []
  apply (rule_tac x="{..< a - y}" in exI)
  apply (auto split: ereal.split simp: ereal_less_minus_iff c) []
  done

lemma continuous_at_ereal[continuous_intros]: "continuous F f ==> continuous F (λx. ereal (f x))"
  unfolding continuous_def by auto

lemma ereal_Sup:
  assumes *: "SUP aA. ereal a  "
  shows "ereal (Sup A) = (SUP aA. ereal a)"
proof (rule continuous_at_Sup_mono)
  obtain r where r: "ereal r = (SUP aA. ereal a)" " {}"
    using * by (force simp: bot_ereal_def)
  then show "bdd_above A" " {}"
    by (auto intro!: SUP_upper bdd_aboveI[of _ r] simp flip: ereal_less_eq)
qed (auto simp: mono_def continuous_at_imp_continuous_at_within continuous_at_ereal)

lemma ereal_SUP: "SUP aA. ereal (f a)   ==> ereal (SUP aA. f a) = (SUP aA. ereal (f a))"
  by (simp add: ereal_Sup image_comp)

lemma ereal_Inf:
  assumes *: "INF aA. ereal a  "
  shows "ereal (Inf A) = (INF aA. ereal a)"
proof (rule continuous_at_Inf_mono)
  obtain r where r: "ereal r = (INF aA. ereal a)" " {}"
    using * by (force simp: top_ereal_def)
  then show "bdd_below A" " {}"
    by (auto intro!: INF_lower bdd_belowI[of _ r] simp flip: ereal_less_eq)
qed (auto simp: mono_def continuous_at_imp_continuous_at_within continuous_at_ereal)

lemma ereal_Inf':
  assumes *: "bdd_below A" " {}"
  shows "ereal (Inf A) = (INF aA. ereal a)"
proof (rule ereal_Inf)
  from * obtain l u where " A ==> l  x" " A" for x
    by (auto simp: bdd_below_def)
  then have " (INF xA. ereal x)" "(INF xA. ereal x)  u"
    by (auto intro!: INF_greatest INF_lower)
  then show "INF aA. ereal a  "
    by auto
qed

lemma ereal_INF: "INF aA. ereal (f a)   ==> ereal (INF aA. f a) = (INF aA. ereal (f a))"
  by (simp add: ereal_Inf image_comp)

lemma ereal_Sup_uminus_image_eq: "Sup (uminus ` S::ereal set) = - Inf S"
  by (auto intro!: SUP_eqI
           simp: Ball_def[symmetric] ereal_uminus_le_reorder le_Inf_iff
           intro!: complete_lattice_class.Inf_lower2)

lemma ereal_SUP_uminus_eq:
  fixes f :: "'a ==> ereal"
  shows "(SUP xS. uminus (f x)) = - (INF xS. f x)"
  using ereal_Sup_uminus_image_eq [of "f ` S"] by (simp add: image_comp)

lemma ereal_inj_on_uminus[intro, simp]: "inj_on uminus (A :: ereal set)"
  by (auto intro!: inj_onI)

lemma ereal_Inf_uminus_image_eq: "Inf (uminus ` S::ereal set) = - Sup S"
  using ereal_Sup_uminus_image_eq[of "uminus ` S"] by simp

lemma ereal_INF_uminus_eq:
  fixes f :: "'a ==> ereal"
  shows "(INF xS. - f x) = - (SUP xS. f x)"
  using ereal_Inf_uminus_image_eq [of "f ` S"] by (simp add: image_comp)

lemma ereal_SUP_not_infty:
  fixes f :: "==> ereal"
  shows " {} ==> l  - ==> u   ==> aA. l  f a  f a  u ==> Sup (f ` A)  "
  using SUP_upper2[of _ A l f] SUP_least[of A f u]
  by (cases "Sup (f ` A)") auto

lemma ereal_INF_not_infty:
  fixes f :: "==> ereal"
  shows " {} ==> l  - ==> u   ==> aA. l  f a  f a  u ==> Inf (f ` A)  "
  using INF_lower2[of _ A f u] INF_greatest[of A l f]
  by (cases "Inf (f ` A)") auto

lemma ereal_image_uminus_shift:
  fixes X Y :: "ereal set"
  shows "uminus ` X = Y  X = uminus ` Y"
  by (metis ereal_minus_minus_image)

lemma Sup_eq_MInfty:
  fixes S :: "ereal set"
  shows "Sup S = -  S = {}  S = {-}"
  unfolding bot_ereal_def[symmetric] by auto

lemma Inf_eq_PInfty:
  fixes S :: "ereal set"
  shows "Inf S =   S = {}  S = {}"
  using Sup_eq_MInfty[of "uminus`S"]
  unfolding ereal_Sup_uminus_image_eq ereal_image_uminus_shift by simp

lemma Inf_eq_MInfty:
  fixes S :: "ereal set"
  shows "-  S ==> Inf S = -"
  unfolding bot_ereal_def[symmetric] by auto

lemma Sup_eq_PInfty:
  fixes S :: "ereal set"
  shows "  S ==> Sup S = "
  unfolding top_ereal_def[symmetric] by auto

lemma not_MInfty_nonneg[simp]: " (x::ereal) ==> x  -"
  by auto

lemma Sup_ereal_close:
  fixes e :: ereal
  assumes "0 < e"
    and S: "Sup S  " " {}"
  shows "xS. Sup S - e < x"
  using assms by (cases e) (auto intro!: less_Sup_iff[THEN iffD1])

lemma Inf_ereal_close:
  fixes e :: ereal
  assumes "Inf X  "
    and "0 < e"
  shows "xX. x < Inf X + e"
  by (meson Inf_less_iff assms ereal_between(2))

lemma SUP_PInfty:
  "(n::nat. iA. ereal (real n)  f i) ==> (SUP iA. f i :: ereal) = "
  by (meson SUP_upper2 less_PInf_Ex_of_nat linorder_not_less)

lemma SUP_nat_Infty: "(SUP i. ereal (real i)) = "
  by (rule SUP_PInfty) auto

lemma SUP_ereal_add_left:
  assumes " {}" " -"
  shows "(SUP iI. f i + c :: ereal) = (SUP iI. f i) + c"
proof (cases "(SUP iI. f i) = -")
  case True
  then have "i. i  I ==> f i = -"
    unfolding Sup_eq_MInfty by auto
  with True show ?thesis
    by (cases c) (auto simp: I {})
next
  case False
  then show ?thesis
    by (subst continuous_at_Sup_mono[where f="λx. x + c"])
      (auto simp: continuous_at_imp_continuous_at_within continuous_at mono_def add_mono I {}
      c - image_comp)
qed

lemma SUP_ereal_add_right:
  fixes c :: ereal
  shows " {} ==> c  - ==> (SUP iI. c + f i) = c + (SUP iI. f i)"
  using SUP_ereal_add_left[of I c f] by (simp add: add.commute)

lemma SUP_ereal_minus_right:
  assumes " {}" " -"
  shows "(SUP iI. c - f i :: ereal) = c - (INF iI. f i)"
  using SUP_ereal_add_right[OF assms, of "λi. - f i"]
  by (simp add: ereal_SUP_uminus_eq minus_ereal_def)

lemma SUP_ereal_minus_left:
  assumes " {}" " "
  shows "(SUP iI. f i - c:: ereal) = (SUP iI. f i) - c"
  using SUP_ereal_add_left[OF I {}, of "-c" f] by (simp add: c minus_ereal_def)

lemma INF_ereal_minus_right:
  assumes " {}" and "c  "
  shows "(INF iI. c - f i) = c - (SUP iI. f i::ereal)"
proof -
  have *: "(- c) + b = - (c - b)" for b
    using c by (cases c b rule: ereal2_cases) auto
  show ?thesis
    using SUP_ereal_add_right[OF I {}, of "-c" f] c
    by (auto simp: * ereal_SUP_uminus_eq)
qed

lemma SUP_ereal_le_addI:
  fixes f :: "'i ==> ereal"
  assumes "i. f i + y  z" and " -"
  shows "Sup (f ` UNIV) + y  z"
  by (metis SUP_ereal_add_left SUP_least UNIV_not_empty assms)

lemma SUP_combine:
  fixes f :: "'a::semilattice_sup ==> 'a::semilattice_sup ==> 'b::complete_lattice"
  assumes mono: "a b c d. a  b ==> c  d ==> f a c  f b d"
  shows "(SUP iUNIV. SUP jUNIV. f i j) = (SUP i. f i i)"
proof (rule antisym)
  show "(SUP i j. f i j)  (SUP i. f i i)"
    by (rule SUP_least SUP_upper2[where i="sup i j" for i j] UNIV_I mono sup_ge1 sup_ge2)+
  show "(SUP i. f i i)  (SUP i j. f i j)"
    by (rule SUP_least SUP_upper2 UNIV_I mono order_refl)+
qed

lemma SUP_ereal_add:
  fixes f g :: "nat ==> ereal"
  assumes inc: "incseq f" "incseq g"
    and pos: "i. f i  -" "i. g i  -"
  shows "(SUP i. f i + g i) = Sup (f ` UNIV) + Sup (g ` UNIV)"
proof -
  have "i j k l. [ j; k  l] ==> f i + g k  f j + g l"
    by (meson add_mono inc incseq_def)
  then have "(SUP i. f i + g i) = (SUP i j. f i + g j)"
    by (simp add: SUP_combine)
  also have "... = (SUP i j. g j + f i)"
    by (simp add: add.commute)
  also have "... = (SUP i. Sup (range g) + f i)"
    by (simp add: SUP_ereal_add_left pos(1))
  also have "... = (SUP i. f i + Sup (range g))"
    by (simp add: add.commute)
  also have "... =  Sup (f ` UNIV) + Sup (g ` UNIV)"
    by (simp add: SUP_eq_iff SUP_ereal_add_left pos(2))
  finally show ?thesis .
qed

lemma INF_eq_minf: "(INF iI. f i::ereal)  -  (b>-iI. b  f i)"
  unfolding bot_ereal_def[symmetric] INF_eq_bot_iff by (auto simp: not_less)

lemma INF_ereal_add_left:
  assumes " {}" " -" "x. x  I ==> 0  f x"
  shows "(INF iI. f i + c :: ereal) = (INF iI. f i) + c"
proof -
  have "(INF iI. f i)  -"
    unfolding INF_eq_minf using assms by (intro exI[of _ 0]) auto
  then show ?thesis
    by (subst continuous_at_Inf_mono[where f="λx. x + c"])
       (auto simp: mono_def add_mono I {} c - continuous_at_imp_continuous_at_within
        continuous_at image_comp)
qed

lemma INF_ereal_add_right:
  assumes " {}" " -" "x. x  I ==> 0  f x"
  shows "(INF iI. c + f i :: ereal) = c + (INF iI. f i)"
  using INF_ereal_add_left[OF assms] by (simp add: ac_simps)

lemma INF_ereal_add_directed:
  fixes f g :: "'a ==> ereal"
  assumes nonneg: "i. i  I ==> 0  f i" "i. i  I ==> 0  g i"
  assumes directed: "i j. i  I ==> j  I ==> kI. f i + g j  f k + g k"
  shows "(INF iI. f i + g i) = (INF iI. f i) + (INF iI. g i)"
proof (cases "I = {}")
  case False
  show ?thesis
  proof (rule antisym)
    show "(INF iI. f i) + (INF iI. g i)  (INF iI. f i + g i)"
      by (rule INF_greatest; intro add_mono INF_lower)
  next
    have "(INF iI. f i + g i)  (INF iI. (INF jI. f i + g j))"
      using directed by (intro INF_greatest) (blast intro: INF_lower2)
    also have " = (INF iI. f i + (INF iI. g i))"
      using nonneg I {} by (auto simp: INF_ereal_add_right)
    also have " = (INF iI. f i) + (INF iI. g i)"
      using nonneg by (intro INF_ereal_add_left I {}) (auto simp: INF_eq_minf intro!: exI[of _ 0])
    finally show "(INF iI. f i + g i)  (INF iI. f i) + (INF iI. g i)" .
  qed
qed (simp add: top_ereal_def)

lemma INF_ereal_add:
  fixes f :: "nat ==> ereal"
  assumes "decseq f" "decseq g"
    and fin: "i. f i  " "i. g i  "
  shows "(INF i. f i + g i) = Inf (f ` UNIV) + Inf (g ` UNIV)"
proof -
  have INF_less: "(INF i. f i) < " "(INF i. g i) < "
    using assms unfolding INF_less_iff by auto
  have *: "- ((- a) + (- b)) = a + b" if " " " " for a b :: ereal
    using that by (cases a b rule: ereal2_cases) auto
  have "(INF i. f i + g i) = (INF i. - ((- f i) + (- g i)))"
    by (simp add: fin *)
  also have " = Inf (f ` UNIV) + Inf (g ` UNIV)"
    unfolding ereal_INF_uminus_eq
    using assms INF_less
    by (subst SUP_ereal_add) (auto simp: ereal_SUP_uminus_eq fin *)
  finally show ?thesis .
qed

lemma SUP_ereal_add_pos:
  fixes f g :: "nat ==> ereal"
  assumes "incseq f" "incseq g"
    and "i. 0  f i" "i. 0  g i"
  shows "(SUP i. f i + g i) = Sup (f ` UNIV) + Sup (g ` UNIV)"
  by (simp add: SUP_ereal_add assms)

lemma SUP_ereal_sum:
  fixes f g :: "'a ==> nat ==> ereal"
  assumes "n. n  A ==> incseq (f n)"
    and pos: "n i. n  A ==> 0  f n i"
  shows "(SUP i. nA. f n i) = (nA. Sup ((f n) ` UNIV))"
  using assms
  by (induction A rule: infinite_finite_induct) (auto simp: incseq_sumI2 sum_nonneg SUP_ereal_add_pos)

lemma SUP_ereal_mult_left:
  fixes f :: "'a ==> ereal"
  assumes " {}"
  assumes f: "i. i  I ==> 0  f i" and c: " c"
  shows "(SUP iI. c * f i) = c * (SUP iI. f i)"
proof (cases "(SUP i  I. f i) = 0")
  case True
  then have "i. i  I ==> f i = 0"
    by (metis SUP_upper f antisym)
  with True show ?thesis
    by simp
next
  case False
  then show ?thesis
    by (subst continuous_at_Sup_mono[where f="λx. c * x"])
       (auto simp: mono_def continuous_at continuous_at_imp_continuous_at_within I {} image_comp
             intro!: ereal_mult_left_mono c)
qed

lemma countable_approach:
  fixes x :: ereal
  assumes " -"
  shows "f. incseq f  (i::nat. f i < x)  (f <---- x)"
proof (cases x)
  case (real r)
  moreover have "(λn. r - inverse (real (Suc n))) <---- r - 0"
    by (intro tendsto_intros LIMSEQ_inverse_real_of_nat)
  ultimately show ?thesis
    by (intro exI[of _ "λn. x - inverse (Suc n)"]) (auto simp: incseq_def)
next
  case PInf with LIMSEQ_SUP[of "λn::nat. ereal (real n)"] show ?thesis
    by (intro exI[of _ "λn. ereal (real n)"]) (auto simp: incseq_def SUP_nat_Infty)
qed (simp add: assms)

lemma Sup_countable_SUP:
  assumes " {}"
  shows "f::nat ==> ereal. incseq f  range f  A  Sup A = (SUP i. f i)"
proof cases
  assume "Sup A = -"
  with A {} have "A = {-}"
    by (auto simp: Sup_eq_MInfty)
  then show ?thesis
    by (auto intro!: exI[of _ "λ_. -"] simp: bot_ereal_def)
next
  assume "Sup A  -"
  then obtain l where "incseq l" and l: "l i < Sup A" and l_Sup: "<---- Sup A" for i :: nat
    by (auto dest: countable_approach)

  have "f. n. (f n  A  l n  f n)  (f n  f (Suc n))" (is "f. ?P f")
  proof (rule dependent_nat_choice)
    show "x. x  A  l 0  x"
      using l[of 0] by (auto simp: less_Sup_iff)
  next
    fix x n assume " A  l n  x"
    moreover from l[of "Suc n"] obtain y where " A" "l (Suc n) < y"
      by (auto simp: less_Sup_iff)
    ultimately show "y. (y  A  l (Suc n)  y)  x  y"
      by (auto intro!: exI[of _ "max x y"] split: split_max)
  qed
  then obtain f where f: "?P f" ..
  then have "range f  A" "incseq f"
    by (auto simp: incseq_Suc_iff)
  then have "(SUP i. f i) = Sup A"
    by (meson LIMSEQ_SUP LIMSEQ_le Sup_subset_mono f l_Sup
        order_class.order_eq_iff)
  then show ?thesis
    by (metis incseq f range f A)
qed

lemma Inf_countable_INF:
  assumes " {}" shows "f::nat ==> ereal. decseq f  range f  A  Inf A = (INF i. f i)"
proof -
  obtain f where "incseq f" "range f  uminus`A" "Sup (uminus`A) = (SUP i. f i)"
    using Sup_countable_SUP[of "uminus ` A"] A {} by auto
  then show ?thesis
    by (intro exI[of _ "λx. - f x"])
       (auto simp: ereal_Sup_uminus_image_eq ereal_INF_uminus_eq eq_commute[of "- _"])
qed

lemma SUP_countable_SUP:
  " {} ==> f::nat ==> ereal. range f  g`A  Sup (g ` A) = Sup (f ` UNIV)"
  using Sup_countable_SUP [of "g`A"] by auto

subsection "Relation to 🍋enat"

definition "ereal_of_enat n = (case n of enat n ==> ereal (real n) | ==> )"

declare [[coercion "ereal_of_enat :: enat ==> ereal"]]
declare [[coercion "(λn. ereal (real n)) :: nat ==> ereal"]]

lemma ereal_of_enat_simps[simp]:
  "ereal_of_enat (enat n) = ereal n"
  "ereal_of_enat = "
  by (simp_all add: ereal_of_enat_def)

lemma ereal_of_enat_le_iff[simp]: "ereal_of_enat m ereal_of_enat n m n"
  by (cases m n rule: enat2_cases) auto

lemma ereal_of_enat_less_iff[simp]: "ereal_of_enat m < ereal_of_enat n m < n"
  by (cases m n rule: enat2_cases) auto

lemma numeral_le_ereal_of_enat_iff[simp]: "numeral m ereal_of_enat n numeral m n"
by (cases n) (auto)

lemma numeral_less_ereal_of_enat_iff[simp]: "numeral m < ereal_of_enat n numeral m < n"
  by (cases n) auto

lemma ereal_of_enat_ge_zero_cancel_iff[simp]: "0 ereal_of_enat n 0 n"
  by (cases n) (auto simp flip: enat_0)

lemma ereal_of_enat_gt_zero_cancel_iff[simp]: "0 < ereal_of_enat n 0 < n"
  by (cases n) (auto simp flip: enat_0)

lemma ereal_of_enat_zero[simp]: "ereal_of_enat 0 = 0"
  by (auto simp flip: enat_0)

lemma ereal_of_enat_inf[simp]: "ereal_of_enat n = n = "
  by (cases n) auto

lemma ereal_of_enat_add: "ereal_of_enat (m + n) = ereal_of_enat m + ereal_of_enat n"
  by (cases m n rule: enat2_cases) auto

lemma ereal_of_enat_sub:
  assumes "n m"
  shows "ereal_of_enat (m - n) = ereal_of_enat m - ereal_of_enat n "
  using assms by (cases m n rule: enat2_cases) auto

lemma ereal_of_enat_mult:
  "ereal_of_enat (m * n) = ereal_of_enat m * ereal_of_enat n"
  by (cases m n rule: enat2_cases) auto

lemmas ereal_of_enat_pushin = ereal_of_enat_add ereal_of_enat_sub ereal_of_enat_mult
lemmas ereal_of_enat_pushout = ereal_of_enat_pushin[symmetric]

lemma ereal_of_enat_nonneg: "ereal_of_enat n 0"
  by simp

lemma ereal_of_enat_Sup:
  assumes "A {}" shows "ereal_of_enat (Sup A) = (SUP a A. ereal_of_enat a)"
proof (intro antisym mono_Sup)
  show "ereal_of_enat (Sup A) (SUP a A. ereal_of_enat a)"
  proof cases
    assume "finite A"
    with A {} obtain a where "a A" "ereal_of_enat (Sup A) = ereal_of_enat a"
      using Max_in[of A] by (auto simp: Sup_enat_def simp del: Max_in)
    then show ?thesis
      by (auto intro: SUP_upper)
  next
    assume "¬ finite A"
    have [simp]: "(SUP a A. ereal_of_enat a) = top"
      unfolding SUP_eq_top_iff
    proof safe
      fix x :: ereal assume "x < top"
      then obtain n :: nat where "x < n"
        using less_PInf_Ex_of_nat top_ereal_def by auto
      obtain a where "a A - enat ` {.. n}"
        by (metis ¬ finite A all_not_in_conv finite_Diff2 finite_atMost finite_imageI finite.emptyI)
      then have "a A" "ereal n ereal_of_enat a"
        by (auto simp: image_iff Ball_def)
           (metis enat_iless enat_ord_simps(1) ereal_of_enat_less_iff ereal_of_enat_simps(1) less_le not_less)
      with x 🚫 show "iA. x < ereal_of_enat i"
        by (auto intro!: bexI[of _ a])
    qed
    show ?thesis
      by simp
  qed
qed (simp add: mono_def)

lemma ereal_of_enat_SUP:
  "A {} ==> ereal_of_enat (SUP aA. f a) = (SUP a A. ereal_of_enat (f a))"
  by (simp add: ereal_of_enat_Sup image_comp)


subsection "Limits on 🍋ereal"

lemma open_PInfty: "open A ==>   A ==> (x. {ereal x<..}  A)"
  unfolding open_ereal_generated
proof (induct rule: generate_topology.induct)
  case (Int A B)
  then obtain x z where "  A ==> {ereal x <..}  A" "  B ==> {ereal z <..}  B"
    by auto
  with Int show ?case
    by (intro exI[of _ "max x z"]) fastforce
next
  case (Basis S)
  moreover have "  ==> t. x  ereal t" for x
    by (cases x) auto
  ultimately show ?case
    by (auto split: ereal.split)
qed (fastforce simp: vimage_Union)+

lemma open_MInfty: "open A ==> -  A ==> (x. {..<ereal x}  A)"
  unfolding open_ereal_generated
proof (induct rule: generate_topology.induct)
  case (Int A B)
  then obtain x z where "-  A ==> {..< ereal x}  A" "-  B ==> {..< ereal z}  B"
    by auto
  with Int show ?case
    by (intro exI[of _ "min x z"]) fastforce
next
  case (Basis S)
  moreover have " - ==> t. ereal t  x" for x
    by (cases x) auto
  ultimately show ?case
    by (auto split: ereal.split)
qed (fastforce simp: vimage_Union)+

lemma open_ereal_vimage: "open S ==> open (ereal -` S)"
  by (intro open_vimage continuous_intros)

lemma open_ereal: "open S ==> open (ereal ` S)"
  unfolding open_generated_order[where 'a=real]
proof (induct rule: generate_topology.induct)
  case (Basis S)
  moreover have "x. ereal ` {..< x} = { - <..< ereal x }"
    using ereal_less_ereal_Ex by auto
  moreover have "x. ereal ` {x <..} = { ereal x <..<  }"
    using less_ereal.elims(2) by fastforce
  ultimately show ?case
    by auto
qed (auto simp: image_Union image_Int)

lemma open_image_real_of_ereal:
  fixes X::"ereal set"
  assumes "open X"
  assumes infty: "  X" "-  X"
  shows "open (real_of_ereal ` X)"
proof -
  have "real_of_ereal ` X = ereal -` X"
    using infty ereal_real by (force simp: set_eq_iff)
  thus ?thesis
    by (auto intro!: open_ereal_vimage assms)
qed

lemma eventually_finite:
  fixes x :: ereal
  assumes "x  " "(f ---> x) F"
  shows "eventually (λx. f x  ) F"
proof -
  have "(f ---> ereal (real_of_ereal x)) F"
    using assms by (cases x) auto
  then have "eventually (λx. f x  ereal ` UNIV) F"
    by (rule topological_tendstoD) (auto intro: open_ereal)
  also have "(λx. f x  ereal ` UNIV) = (λx. f x  )"
    by auto
  finally show ?thesis .
qed


lemma open_ereal_def:
  "open A  open (ereal -` A)  (  A  (x. {ereal x <..}  A))  (-  A  (x. {..<ereal x}  A))"
  (is "open A  ?rhs")
proof
  assume "open A"
  then show ?rhs
    using open_PInfty open_MInfty open_ereal_vimage by auto
next
  assume "?rhs"
  then obtain x y where A: "open (ereal -` A)" "  A ==> {ereal x<..}  A" "-  A ==> {..< ereal y A"
    by auto
  have *: "A = ereal ` (ereal -` A)  (if   A then {ereal x<..} else {})  (if -  A then {..< ereal y} else {})"
    using A(2,3) by auto
  from open_ereal[OF A(1)] show "open A"
    by (subst *) (auto simp: open_Un)
qed

lemma open_PInfty2:
  assumes "open A" and "  A"
  obtains x where "{ereal x<..}  A"
  using open_PInfty[OF assms] by auto

lemma open_MInfty2:
  assumes "open A" and "-  A"
  obtains x where "{..<ereal x}  A"
  using open_MInfty[OF assms] by auto

lemma ereal_openE:
  assumes "open A"
  obtains x y where "open (ereal -` A)"
    and "  A ==> {ereal x<..}  A"
    and "-  A ==> {..<ereal y}  A"
  using assms open_ereal_def by auto

lemmas open_ereal_lessThan = open_lessThan[where 'a=ereal]
lemmas open_ereal_greaterThan = open_greaterThan[where 'a=ereal]
lemmas ereal_open_greaterThanLessThan = open_greaterThanLessThan[where 'a=ereal]
lemmas closed_ereal_atLeast = closed_atLeast[where 'a=ereal]
lemmas closed_ereal_atMost = closed_atMost[where 'a=ereal]
lemmas closed_ereal_atLeastAtMost = closed_atLeastAtMost[where 'a=ereal]
lemmas closed_ereal_singleton = closed_singleton[where 'a=ereal]

lemma ereal_open_cont_interval:
  fixes S :: "ereal set"
  assumes "open S"
    and " S"
    and "x  "
  obtains e where "e > 0" and "{x-e <..< x+e}  S"
proof -
  from open S
  have "open (ereal -` S)"
    by (rule ereal_openE)
  then obtain e where "e > 0" and e: "dist y (real_of_ereal x) < e ==> ereal y  S" for y
    using assms unfolding open_dist by force
  show thesis
  proof (intro that subsetI)
    show "0 < ereal e"
      using 0 < e by auto
    fix y
    assume " {x - ereal e<..<x + ereal e}"
    with assms obtain t where "y = ereal t" "dist t (real_of_ereal x) < e"
      by (cases y) (auto simp: dist_real_def)
    then show " S"
      using e[of t] by auto
  qed
qed

lemma ereal_open_cont_interval2:
  fixes S :: "ereal set"
  assumes "open S" and " S" and "x  "
  obtains a b where "a < x" and "x < b" and "{a <..< b}  S"
  by (meson assms ereal_between ereal_open_cont_interval)

subsubsection Convergent sequences

lemma lim_real_of_ereal[simp]:
  assumes lim: "(f ---> ereal x) net"
  shows "((λx. real_of_ereal (f x)) ---> x) net"
proof (intro topological_tendstoI)
  fix S
  assume "open S" and " S"
  then have S: "open S" "ereal x  ereal ` S"
    by (simp_all add: inj_image_mem_iff)
  show "eventually (λx. real_of_ereal (f x)  S) net"
    by (auto intro: eventually_mono [OF lim[THEN topological_tendstoD, OF open_ereal, OF S]])
qed

lemma lim_ereal[simp]: "((λn. ereal (f n)) ---> ereal x) net  (f ---> x) net"
  by (auto dest!: lim_real_of_ereal)

lemma convergent_real_imp_convergent_ereal:
  assumes "convergent a"
  shows "convergent (λn. ereal (a n))" and "lim (λn. ereal (a n)) = ereal (lim a)"
proof -
  from assms obtain L where L: "<---- L" unfolding convergent_def ..
  hence lim: "(λn. ereal (a n)) <---- ereal L" using lim_ereal by auto
  thus "convergent (λn. ereal (a n))" unfolding convergent_def ..
  thus "lim (λn. ereal (a n)) = ereal (lim a)" using lim L limI by metis
qed

lemma tendsto_PInfty: "(f ---> ) F  (r. eventually (λx. ereal r < f x) F)"
proof -
  { fix l :: ereal
    assume "r. eventually (λx. ereal r < f x) F"
    from this[THEN spec, of "real_of_ereal l"]
    have "  ==> eventually (λx. l < f x) F"
      by (cases l) (auto elim: eventually_mono)
  }
  then show ?thesis
    by (auto simp: order_tendsto_iff)
qed

lemma tendsto_PInfty': "(f ---> ) F = (r>c. eventually (λx. ereal r < f x) F)"
proof -
  { fix r :: real
    assume "r>c. eventually (λx. ereal r < f x) F"
    then have "eventually (λx. ereal r < f x) F"
      if "r > c" for r using that by blast
    then have "eventually (λx. ereal r < f x) F"
      by (smt (verit, del_insts) ereal_less_le eventually_mono gt_ex)
  } then show ?thesis
    using tendsto_PInfty by blast
qed

lemma tendsto_PInfty_eq_at_top:
  "((λz. ereal (f z)) ---> ) F  (LIM z F. f z :> at_top)"
  unfolding tendsto_PInfty filterlim_at_top_dense by simp

lemma tendsto_MInfty: "(f ---> -) F  (r. eventually (λx. f x < ereal r) F)"
  unfolding tendsto_def
proof safe
  fix S :: "ereal set"
  assume "open S" "-  S"
  from open_MInfty[OF this] obtain B where "{..<ereal B}  S" ..
  moreover
  assume "r::real. eventually (λz. f z < r) F"
  then have "eventually (λz. f z  {..< B}) F"
    by auto
  ultimately show "eventually (λz. f z  S) F"
    by (auto elim!: eventually_mono)
next
  fix x
  assume "S. open S  -  S  eventually (λx. f x  S) F"
  from this[rule_format, of "{..< ereal x}"] show "eventually (λy. f y < ereal x) F"
    by auto
qed

lemma tendsto_MInfty': "(f ---> -) F = (r<c. eventually (λx. ereal r > f x) F)"
proof (subst tendsto_MInfty, intro iffI allI impI)
  assume A: "r<c. eventually (λx. ereal r > f x) F"
  fix r :: real
  from A have A: "eventually (λx. ereal r > f x) F" if "r < c" for r using that by blast
  show "eventually (λx. ereal r > f x) F"
  proof (cases "r < c")
    case False
    hence B: "ereal r  ereal (c - 1)" by simp
    have "c > c - 1" by simp
    from A[OF this] show "eventually (λx. ereal r > f x) F"
      by eventually_elim (erule less_le_trans[OF _ B])
  qed (simp add: A)
qed simp

lemma Lim_PInfty: "<----   (B. N. nN. f n  ereal B)"
  unfolding tendsto_PInfty eventually_sequentially
proof safe
  fix r
  assume "r. N. nN. ereal r  f n"
  then obtain N where "nN. ereal (r + 1)  f n"
    by blast
  moreover have "ereal r < ereal (r + 1)"
    by auto
  ultimately show "N. nN. ereal r < f n"
    by (blast intro: less_le_trans)
qed (blast intro: less_imp_le)

lemma Lim_MInfty: "<---- -  (B. N. nN. ereal B  f n)"
  unfolding tendsto_MInfty eventually_sequentially
proof safe
  fix r
  assume "r. N. nN. f n  ereal r"
  then obtain N where "nN. f n  ereal (r - 1)"
    by blast
  moreover have "ereal (r - 1) < ereal r"
    by auto
  ultimately show "N. nN. f n < ereal r"
    by (blast intro: le_less_trans)
qed (blast intro: less_imp_le)

lemma Lim_bounded_PInfty: "<---- l ==> (n. f n  ereal B) ==> l  "
  using LIMSEQ_le_const2[of f l "ereal B"] by auto

lemma Lim_bounded_MInfty: "<---- l ==> (n. ereal B  f n) ==> l  -"
  using LIMSEQ_le_const[of f l "ereal B"] by auto

lemma tendsto_zero_erealI:
  assumes "e. e > 0 ==> eventually (λx. f x < ereal e) F"
  shows "(f ---> 0) F"
proof (subst filterlim_cong[OF refl refl])
  from assms[OF zero_less_one] show "eventually (λx. f x = ereal (real_of_ereal (f x))) F"
    by eventually_elim (auto simp: ereal_real)
  hence "eventually (λx. abs (real_of_ereal (f x)) < e) F" if "e > 0" for e using assms[OF that]
    by eventually_elim (simp add: real_less_ereal_iff that)
  hence "((λx. real_of_ereal (f x)) ---> 0) F" unfolding tendsto_iff
    by (auto simp: tendsto_iff dist_real_def)
  thus "((λx. ereal (real_of_ereal (f x))) ---> 0) F" by (simp add: zero_ereal_def)
qed

lemma Lim_bounded_PInfty2: "<---- l ==> nN. f n  ereal B ==> l  "
  using LIMSEQ_le_const2[of f l "ereal B"] by fastforce

lemma real_of_ereal_mult[simp]:
  fixes a b :: ereal
  shows "real_of_ereal (a * b) = real_of_ereal a * real_of_ereal b"
  by (cases rule: ereal2_cases[of a b]) auto

lemma real_of_ereal_eq_0:
  fixes x :: ereal
  shows "real_of_ereal x = 0  x =   x = -  x = 0"
  by (cases x) auto

lemma tendsto_ereal_realD:
  fixes f :: "'a ==> ereal"
  assumes " 0"
    and tendsto: "((λx. ereal (real_of_ereal (f x))) ---> x) net"
  shows "(f ---> x) net"
proof (intro topological_tendstoI)
  fix S
  assume S: "open S" " S"
  with x 0 have "open (S - {0})" " S - {0}"
    by auto
  from tendsto[THEN topological_tendstoD, OF this]
  show "eventually (λx. f x  S) net"
    by (rule eventually_rev_mp) (auto simp: ereal_real)
qed

lemma tendsto_ereal_realI:
  fixes f :: "'a ==> ereal"
  assumes x: "x  " and tendsto: "(f ---> x) net"
  shows "((λx. ereal (real_of_ereal (f x))) ---> x) net"
proof (intro topological_tendstoI)
  fix S
  assume "open S" and " S"
  with x have "open (S - {, -})" " S - {, -}"
    by auto
  from tendsto[THEN topological_tendstoD, OF this]
  show "eventually (λx. ereal (real_of_ereal (f x))  S) net"
    by (elim eventually_mono) (auto simp: ereal_real)
qed

lemma ereal_mult_cancel_left:
  fixes a b c :: ereal
  shows "a * b = a * c  (a =   0 < b * c)  a = 0  b = c"
  by (cases rule: ereal3_cases[of a b c]) (simp_all add: zero_less_mult_iff)

lemma tendsto_add_ereal:
  fixes x y :: ereal
  assumes x: "x  " and y: "y  "
  assumes f: "(f ---> x) F" and g: "(g ---> y) F"
  shows "((λx. f x + g x) ---> x + y) F"
proof -
  from x obtain r where x': "x = ereal r" by (cases x) auto
  with f have "((λi. real_of_ereal (f i)) ---> r) F" by simp
  moreover
  from y obtain p where y': "y = ereal p" by (cases y) auto
  with g have "((λi. real_of_ereal (g i)) ---> p) F" by simp
  ultimately have "((λi. real_of_ereal (f i) + real_of_ereal (g i)) ---> r + p) F"
    by (rule tendsto_add)
  moreover
  from eventually_finite[OF x f] eventually_finite[OF y g]
  have "eventually (λx. f x + g x = ereal (real_of_ereal (f x) + real_of_ereal (g x))) F"
    by eventually_elim auto
  ultimately show ?thesis
    by (simp add: x' y' cong: filterlim_cong)
qed

lemma tendsto_add_ereal_nonneg:
  fixes x y :: "ereal"
  assumes " -" " -" "(f ---> x) F" "(g ---> y) F"
  shows "((λx. f x + g x) ---> x + y) F"
proof (cases "x =   y = ")
  case True
  moreover
  { fix y :: ereal and f g :: "'a ==> ereal" assume " -" "(f ---> ) F" "(g ---> y) F"
    then obtain y' where "- < y'" "y' < y"
      using dense[of "-" y] by auto
    have "((λx. f x + g x) ---> ) F"
    proof (rule tendsto_sandwich)
      have "🪙F x in F. y' < g x"
        using order_tendstoD(1)[OF (g ---> y) F y' < y] by auto
      then show "🪙F x in F. f x + y'  f x + g x"
        by eventually_elim (auto intro!: add_mono)
      show "🪙F n in F. f n + g n  " "((λn. ---> ) F"
        by auto
      show "((λx. f x + y') ---> ) F"
        using tendsto_cadd_ereal[of y' f F] (f ---> ) F - < y' by auto
    qed }
  note this[of y f g] this[of x g f]
  ultimately show ?thesis
    using assms by (auto simp: add_ac)
next
  case False
  with assms tendsto_add_ereal[of x y f F g]
  show ?thesis
    by auto
qed

lemma ereal_inj_affinity:
  fixes m t :: ereal
  assumes "m  "
    and " 0"
    and "t  "
  shows "inj_on (λx. m * x + t) A"
  using assms
  by (cases rule: ereal2_cases[of m t])
     (auto intro!: inj_onI simp: ereal_add_cancel_right ereal_mult_cancel_left)

lemma ereal_PInfty_eq_plus[simp]:
  fixes a b :: ereal
  shows " = a + b  a =   b = "
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_MInfty_eq_plus[simp]:
  fixes a b :: ereal
  shows "- = a + b  (a = -  b   (b = -  a  )"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_less_divide_pos:
  fixes x y :: ereal
  shows "x > 0 ==> x   ==> y < z / x  x * y < z"
  by (simp add: ereal_less_divide_iff mult.commute)

lemma ereal_divide_less_pos:
  fixes x y z :: ereal
  shows "x > 0 ==> x   ==> y / x < z  y < x * z"
  by (simp add: ereal_divide_less_iff mult.commute)

lemma ereal_divide_eq:
  fixes a b c :: ereal
  shows " 0 ==> b   ==> a / b = c  a = b * c"
  by (metis ereal_divide_same ereal_times_divide_eq mult.commute
      mult.right_neutral)

lemma ereal_inverse_not_MInfty[simp]: "inverse (a::ereal)  -"
  by (cases a) auto

lemma ereal_mult_m1[simp]: "x * ereal (-1) = -x"
  by (cases x) auto

lemma ereal_real':
  assumes "x  "
  shows "ereal (real_of_ereal x) = x"
  using assms by auto

lemma real_ereal_id: "real_of_ereal  ereal = id"
  by auto

lemma open_image_ereal: "open(UNIV-{  , (- :: ereal)})"
  by (metis range_ereal open_ereal open_UNIV)

lemma ereal_le_distrib:
  fixes a b c :: ereal
  shows "c * (a + b)  c * a + c * b"
  by (cases rule: ereal3_cases[of a b c])
     (auto simp: field_simps not_le mult_le_0_iff mult_less_0_iff)

lemma ereal_pos_distrib:
  fixes a b c :: ereal
  assumes " c"
    and " "
  shows "c * (a + b) = c * a + c * b"
  using assms
  by (cases rule: ereal3_cases[of a b c])
     (auto simp: field_simps not_le mult_le_0_iff mult_less_0_iff)

lemma ereal_LimI_finite:
  fixes x :: ereal
  assumes "x  "
    and "r. 0 < r ==> N. nN. u n < x + r  x < u n + r"
  shows "<---- x"
proof (rule topological_tendstoI, unfold eventually_sequentially)
  obtain rx where rx: "x = ereal rx"
    using assms by (cases x) auto
  fix S
  assume "open S" and " S"
  then have "open (ereal -` S)"
    unfolding open_ereal_def by auto
  with x S obtain r where "0 < r" and dist: "dist y rx < r ==> ereal y  S" for y
    unfolding open_dist rx by auto
  then obtain n
    where upper: "u N < x + ereal r"
      and lower: "x < u N + ereal r"
      if " N" for N
    using assms(2)[of "ereal r"] by auto
  show "N. nN. u n  S"
  proof (safe intro!: exI[of _ n])
    fix N
    assume " N"
    from upper[OF this] lower[OF this] assms 0 < r
    have "u N  {,(-)}"
      by auto
    then obtain ra where ra_def: "(u N) = ereal ra"
      by (cases "u N") auto
    then have "rx < ra + r" and "ra < rx + r"
      using rx assms 0 < r lower[OF n N] upper[OF n N]
      by auto
    then have "dist (real_of_ereal (u N)) rx < r"
      using rx ra_def
      by (auto simp: dist_real_def abs_diff_less_iff field_simps)
    from dist[OF this] show "u N  S"
      using u N {, -}
      by (auto simp: ereal_real split: if_split_asm)
  qed
qed

lemma tendsto_obtains_N:
  assumes "<---- f0" "open S" "f0  S"
  obtains N where "nN. f n  S"
  using assms lim_explicit by blast

lemma ereal_LimI_finite_iff:
  fixes x :: ereal
  assumes "x  "
  shows "<---- x  (r. 0 < r  (N. nN. u n < x + r  x < u n + r))"
  (is "?lhs  ?rhs")
proof
  assume lim: "<---- x"
  {
    fix r :: ereal
    assume "r > 0"
    then obtain N where "nN. u n  {x - r <..< x + r}"
      using lim ereal_between[of x r] assms r > 0 tendsto_obtains_N[of u x "{x - r <..< x + r}"]
      by auto
    then have "N. nN. u n < x + r  x < u n + r"
      using ereal_minus_less[of r x]
      by (cases r) auto
  }
  then show ?rhs
    by auto
next
  assume ?rhs
  then show "<---- x"
    using ereal_LimI_finite[of x] assms by auto
qed

lemma ereal_Limsup_uminus:
  fixes f :: "'a ==> ereal"
  shows "Limsup net (λx. - (f x)) = - Liminf net f"
  unfolding Limsup_def Liminf_def ereal_SUP_uminus_eq ereal_INF_uminus_eq ..

lemma liminf_bounded_iff:
  fixes x :: "nat ==> ereal"
  shows " liminf x  (B<C. N. nN. B < x n)"
  (is "?lhs  ?rhs")
  unfolding le_Liminf_iff eventually_sequentially ..

lemma Liminf_add_le:
  fixes f g :: "==> ereal"
  assumes F: " bot"
  assumes ev: "eventually (λx. 0  f x) F" "eventually (λx. 0  g x) F"
  shows "Liminf F f + Liminf F g  Liminf F (λx. f x + g x)"
  unfolding Liminf_def
proof (subst SUP_ereal_add_left[symmetric])
  let ?F = "{P. eventually P F}"
  let ?INF = "λP g. Inf (g ` (Collect P))"
  show "?F  {}"
    by (auto intro: eventually_True)
  show "(SUP P?F. ?INF P g)  -"
    unfolding bot_ereal_def[symmetric] SUP_bot_conv INF_eq_bot_iff
    by (auto intro!: exI[of _ 0] ev simp: bot_ereal_def)
  have "(SUP P?F. ?INF P f + (SUP P?F. ?INF P g))  (SUP P?F. (SUP P'?F. ?INF P f + ?INF P' g))"
  proof (safe intro!: SUP_mono bexI[of _ "λx. P x  0  f x" for P])
    fix P let ?P' = "λx. P x  0  f x"
    assume "eventually P F"
    with ev show "eventually ?P' F"
      by eventually_elim auto
    have "?INF P f + (SUP P?F. ?INF P g)  ?INF ?P' f + (SUP P?F. ?INF P g)"
      by (intro add_mono INF_mono) auto
    also have " = (SUP P'?F. ?INF ?P' f + ?INF P' g)"
    proof (rule SUP_ereal_add_right[symmetric])
      show "Inf (f ` {x. P x  0  f x})  -"
        unfolding bot_ereal_def[symmetric] INF_eq_bot_iff
        by (auto intro!: exI[of _ 0] ev simp: bot_ereal_def)
    qed fact
    finally show "?INF P f + (SUP P?F. ?INF P g)  (SUP P'?F. ?INF ?P' f + ?INF P' g)" .
  qed
  also have "  (SUP P?F. INF xCollect P. f x + g x)"
  proof (safe intro!: SUP_least)
    fix P Q assume *: "eventually P F" "eventually Q F"
    show "?INF P f + ?INF Q g  (SUP P?F. INF xCollect P. f x + g x)"
    proof (rule SUP_upper2)
      show "(λx. P x  Q x)  ?F"
        using * by (auto simp: eventually_conj)
      show "?INF P f + ?INF Q g  (INF x{x. P x  Q x}. f x + g x)"
        by (intro INF_greatest add_mono) (auto intro: INF_lower)
    qed
  qed
  finally show "(SUP P?F. ?INF P f + (SUP P?F. ?INF P g))  (SUP P?F. INF xCollect P. f x + g x)" .
qed

lemma Sup_ereal_mult_right':
  assumes nonempty: " {}"
  and x: " 0"
  shows "(SUP iY. f i) * ereal x = (SUP iY. f i * ereal x)" (is "?lhs = ?rhs")
proof(cases "x = 0")
  case True thus ?thesis by(auto simp: nonempty zero_ereal_def[symmetric])
next
  case False
  show ?thesis
  proof(rule antisym)
    show "?rhs  ?lhs"
      by(rule SUP_least)(simp add: ereal_mult_right_mono SUP_upper x)
  next
    have "?lhs / ereal x = (SUP iY. f i) * (ereal x / ereal x)" by(simp only: ereal_times_divide_eq)
    also have " = (SUP iY. f i)" using False by simp
    also have "  ?rhs / x"
    proof(rule SUP_least)
      fix i
      assume " Y"
      have "f i = f i * (ereal x / ereal x)" using False by simp
      also have " = f i * x / x" by(simp only: ereal_times_divide_eq)
      also from i Y have "f i * x  ?rhs" by(rule SUP_upper)
      hence "f i * x / x  ?rhs / x" using x False by simp
      finally show "f i  ?rhs / x" .
    qed
    finally have "(?lhs / x) * x  (?rhs / x) * x"
      by(rule ereal_mult_right_mono)(simp add: x)
    also have " = ?rhs" using False ereal_divide_eq mult.commute by force
    also have "(?lhs / x) * x = ?lhs" using False ereal_divide_eq mult.commute by force
    finally show "?lhs  ?rhs" .
  qed
qed

lemma Sup_ereal_mult_left':
  "[ Y  {}; x  0 ] ==> ereal x * (SUP iY. f i) = (SUP iY. ereal x * f i)"
  by (smt (verit) Sup.SUP_cong Sup_ereal_mult_right' mult.commute)

lemma sup_continuous_add[order_continuous_intros]:
  fixes f g :: "'a::complete_lattice ==> ereal"
  assumes nn: "x. 0  f x" "x. 0  g x" and cont: "sup_continuous f" "sup_continuous g"
  shows "sup_continuous (λx. f x + g x)"
  unfolding sup_continuous_def
proof safe
  fix M :: "nat ==> 'a" assume "incseq M"
  then show "f (SUP i. M i) + g (SUP i. M i) = (SUP i. f (M i) + g (M i))"
    using SUP_ereal_add_pos[of "λi. f (M i)" "λi. g (M i)"] nn
      cont[THEN sup_continuous_mono] cont[THEN sup_continuousD]
    by (auto simp: mono_def)
qed

lemma sup_continuous_mult_right[order_continuous_intros]:
  " c ==> c <  ==> sup_continuous f ==> sup_continuous (λx. f x * c :: ereal)"
  by (cases c) (auto simp: sup_continuous_def fun_eq_iff Sup_ereal_mult_right')

lemma sup_continuous_mult_left[order_continuous_intros]:
  " c ==> c <  ==> sup_continuous f ==> sup_continuous (λx. c * f x :: ereal)"
  using sup_continuous_mult_right[of c f] by (simp add: mult_ac)

lemma sup_continuous_ereal_of_enat[order_continuous_intros]:
  assumes f: "sup_continuous f"
  shows "sup_continuous (λx. ereal_of_enat (f x))"
  by (metis UNIV_not_empty ereal_of_enat_SUP f sup_continuous_compose
      sup_continuous_def)

subsubsection Sums

lemma sums_ereal_positive:
  fixes f :: "nat ==> ereal"
  assumes "i. 0  f i"
  shows "f sums (SUP n. i<n. f i)"
  by (simp add: LIMSEQ_SUP assms incseq_sumI sums_def)

lemma summable_ereal_pos:
  fixes f :: "nat ==> ereal"
  assumes "i. 0  f i"
  shows "summable f"
  using sums_ereal_positive[of f, OF assms]
  unfolding summable_def
  by auto

lemma sums_ereal: "(λx. ereal (f x)) sums ereal x  f sums x"
  unfolding sums_def by simp

lemma suminf_ereal_eq_SUP:
  fixes f :: "nat ==> ereal"
  assumes "i. 0  f i"
  shows "(x. f x) = (SUP n. i<n. f i)"
  using sums_ereal_positive[of f, OF assms, THEN sums_unique]
  by simp

lemma suminf_bound:
  fixes f :: "nat ==> ereal"
  assumes "N. (n<N. f n)  x" "n. 0  f n"
  shows "suminf f  x"
  by (simp add: SUP_least assms suminf_ereal_eq_SUP)

lemma suminf_bound_add:
  fixes f :: "nat ==> ereal"
  assumes "N. (n<N. f n) + y  x"
    and "n. 0  f n"
    and " -"
  shows "suminf f + y  x"
  by (simp add: SUP_ereal_le_addI assms suminf_ereal_eq_SUP)

lemma suminf_upper:
  fixes f :: "nat ==> ereal"
  assumes "n. 0  f n"
  shows "(n<N. f n)  (n. f n)"
  unfolding suminf_ereal_eq_SUP [OF assms]
  by (auto intro: complete_lattice_class.SUP_upper)

lemma suminf_0_le:
  fixes f :: "nat ==> ereal"
  assumes "n. 0  f n"
  shows " (n. f n)"
  using suminf_upper[of f 0, OF assms]
  by simp

lemma suminf_le_pos:
  fixes f g :: "nat ==> ereal"
  assumes "N. f N  g N"
    and "N. 0  f N"
  shows "suminf f  suminf g"
  by (meson assms order_trans suminf_le summable_ereal_pos)

lemma suminf_half_series_ereal: "(n. (1/2 :: ereal) ^ Suc n) = 1"
  using sums_ereal[THEN iffD2, OF power_half_series, THEN sums_unique, symmetric]
  by (simp add: one_ereal_def)

lemma suminf_add_ereal:
  fixes f g :: "nat ==> ereal"
  assumes "i. 0  f i" "i. 0  g i"
  shows "(i. f i + g i) = suminf f + suminf g"
proof -
  have "(SUP n. i<n. f i + g i) = (SUP n. sum f {..<n}) + (SUP n. sum g {..<n})"
    unfolding sum.distrib
    by (intro assms add_nonneg_nonneg SUP_ereal_add_pos incseq_sumI sum_nonneg ballI)
  with assms show ?thesis
    by (simp add: suminf_ereal_eq_SUP)
qed

lemma suminf_cmult_ereal:
  fixes f g :: "nat ==> ereal"
  assumes "i. 0  f i" and " a"
  shows "(i. a * f i) = a * suminf f"
  by (simp add: assms sum_nonneg suminf_ereal_eq_SUP sum_ereal_right_distrib flip: SUP_ereal_mult_left)

lemma suminf_PInfty:
  fixes f :: "nat ==> ereal"
  assumes "i. 0  f i"
    and "suminf f  "
  shows "f i  "
proof -
  from suminf_upper[of f "Suc i", OF assms(1)] assms(2)
  have "(i<Suc i. f i)  "
    by auto
  then show ?thesis
    unfolding sum_Pinfty by simp
qed

lemma suminf_PInfty_fun:
  assumes "i. 0  f i"
    and "suminf f  "
  shows "f'. f = (λx. ereal (f' x))"
proof -
  have "i. r. f i = ereal r"
    by (metis abs_ereal_ge0 abs_neq_infinity_cases assms suminf_PInfty)
  then show ?thesis
    by metis
qed

lemma summable_ereal:
  assumes "i. 0  f i"
    and "(i. ereal (f i))  "
  shows "summable f"
proof -
  have " (i. ereal (f i))"
    using assms by (intro suminf_0_le) auto
  with assms obtain r where r: "(i. ereal (f i)) = ereal r"
    by (cases "i. ereal (f i)") auto
  from summable_ereal_pos[of "λx. ereal (f x)"]
  have "summable (λx. ereal (f x))"
    using assms by auto
  from summable_sums[OF this]
  have "(λx. ereal (f x)) sums (x. ereal (f x))"
    by auto
  then show "summable f"
    unfolding r sums_ereal summable_def ..
qed

lemma suminf_ereal:
  assumes "i. 0  f i"
    and "(i. ereal (f i))  "
  shows "(i. ereal (f i)) = ereal (suminf f)"
proof (rule sums_unique[symmetric])
  from summable_ereal[OF assms]
  show "(λx. ereal (f x)) sums (ereal (suminf f))"
    unfolding sums_ereal
    using assms
    by (intro summable_sums summable_ereal)
qed

lemma suminf_ereal_minus:
  fixes f g :: "nat ==> ereal"
  assumes ord: "i. g i  f i" "i. 0  g i"
    and fin: "suminf f  " "suminf g  "
  shows "(i. f i - g i) = suminf f - suminf g"
proof -
  have 0: " f i" for i
    using ord order_trans by blast
  moreover
  obtain f' where [simp]: "f = (λx. ereal (f' x))"
    using 0 fin(1) suminf_PInfty_fun by presburger
  obtain g' where [simp]: "g = (λx. ereal (g' x))"
    using fin(2) ord(2) suminf_PInfty_fun by presburger
  have " f i - g i" for i
    using ord(1) by auto
  moreover
  have "suminf (λi. f i - g i)  suminf f"
    using assms by (auto intro!: suminf_le_pos simp: field_simps)
  then have "suminf (λi. f i - g i)  "
    using fin by auto
  ultimately show ?thesis
    using assms i. 0 f i
    apply simp
    apply (subst (1 2 3) suminf_ereal)
    apply (auto intro!: suminf_diff[symmetric] summable_ereal)
    done
qed

lemma suminf_ereal_PInf [simp]: "(x. ::ereal) = "
  by (metis ereal_less_eq(1) suminf_PInfty)

lemma summable_real_of_ereal:
  fixes f :: "nat ==> ereal"
  assumes f: "i. 0  f i"
    and fin: "(i. f i)  "
  shows "summable (λi. real_of_ereal (f i))"
proof (rule summable_def[THEN iffD2])
  have " (i. f i)"
    using assms by (auto intro: suminf_0_le)
  with fin obtain r where r: "ereal r = (i. f i)"
    by (cases "(i. f i)") auto
  have fin: "f i  " for i
    by (simp add: assms(2) f suminf_PInfty)
  have "(λi. ereal (real_of_ereal (f i))) sums (i. ereal (real_of_ereal (f i)))"
    using f
    by (auto intro!: summable_ereal_pos simp: ereal_le_real_iff zero_ereal_def)
  also have " = ereal r"
    using fin r by (auto simp: ereal_real)
  finally show "r. (λi. real_of_ereal (f i)) sums r"
    by (auto simp: sums_ereal)
qed

lemma suminf_SUP_eq:
  fixes f :: "nat ==> nat ==> ereal"
  assumes "i. incseq (λn. f n i)"
    and "n i. 0  f n i"
  shows "(i. SUP n. f n i) = (SUP n. i. f n i)"
proof -
  have *: "n. (i<n. SUP k. f k i) = (SUP k. i<n. f k i)"
    using assms
    by (auto intro!: SUP_ereal_sum [symmetric])
  show ?thesis
    using assms
    by (auto simp: suminf_ereal_eq_SUP SUP_upper2 * intro!: SUP_commute)
qed

lemma suminf_sum_ereal:
  fixes f :: "==> _ ==> ereal"
  assumes nonneg: "i a. a  A ==> 0  f i a"
  shows "(i. aA. f i a) = (aA. i. f i a)"
  using nonneg
by (induction A rule: infinite_finite_induct; simp add: suminf_add_ereal sum_nonneg)

lemma suminf_ereal_eq_0:
  fixes f :: "nat ==> ereal"
  assumes nneg: "i. 0  f i"
  shows "(i. f i) = 0  (i. f i = 0)"
proof
  assume "(i. f i) = 0"
  {
    fix i
    assume "f i  0"
    with nneg have "0 < f i"
      by (auto simp: less_le)
    also have "f i = (j. if j = i then f i else 0)"
      by (subst suminf_finite[where N="{i}"]) auto
    also have "  (i. f i)"
      using nneg
      by (auto intro!: suminf_le_pos)
    finally have False
      using (i. f i) = 0 by auto
  }
  then show "i. f i = 0"
    by auto
qed simp

lemma suminf_ereal_offset_le:
  fixes f :: "nat ==> ereal"
  assumes f: "i. 0  f i"
  shows "(i. f (i + k))  suminf f"
proof -
  have "(λn. i<n. f (i + k)) <---- (i. f (i + k))"
    using summable_sums[OF summable_ereal_pos]
    by (simp add: sums_def atLeast0LessThan f)
  moreover have "(λn. i<n. f i) <---- (i. f i)"
    using summable_sums[OF summable_ereal_pos]
    by (simp add: sums_def atLeast0LessThan f)
  then have "(λn. i<n + k. f i) <---- (i. f i)"
    by (rule LIMSEQ_ignore_initial_segment)
  ultimately show ?thesis
  proof (rule LIMSEQ_le, safe intro!: exI[of _ k])
    fix n assume " n"
    have "(i<n. f (i + k)) = (i<n. (f  plus k) i)"
      by (simp add: ac_simps)
    also have " = (i(plus k) ` {..<n}. f i)"
      by (rule sum.reindex [symmetric]) simp
    also have "  sum f {..<n + k}"
      by (intro sum_mono2) (auto simp: f)
    finally show "(i<n. f (i + k))  sum f {..<n + k}" .
  qed
qed

lemma sums_suminf_ereal: "f sums x ==> (i. ereal (f i)) = ereal x"
  by (metis sums_ereal sums_unique)

lemma suminf_ereal': "summable f ==> (i. ereal (f i)) = ereal (i. f i)"
  by (metis sums_ereal sums_unique summable_def)

lemma suminf_ereal_finite: "summable f ==> (i. ereal (f i))  "
  by (auto simp: summable_def simp flip: sums_ereal sums_unique)

lemma suminf_ereal_finite_neg:
  assumes "summable f"
  shows "(x. ereal (f x))  -"
  by (simp add: assms suminf_ereal')

lemma SUP_ereal_add_directed:
  fixes f g :: "'a ==> ereal"
  assumes nonneg: "i. i  I ==> 0  f i" "i. i  I ==> 0  g i"
  assumes directed: "i j. i  I ==> j  I ==> kI. f i + g j  f k + g k"
  shows "(SUP iI. f i + g i) = (SUP iI. f i) + (SUP iI. g i)"
proof cases
  assume "I = {}" then show ?thesis
    by (simp add: bot_ereal_def)
next
  assume " {}"
  show ?thesis
  proof (rule antisym)
    show "(SUP iI. f i + g i)  (SUP iI. f i) + (SUP iI. g i)"
      by (rule SUP_least; intro add_mono SUP_upper)
  next
    have "bot < (SUP iI. g i)"
      using I {} nonneg(2) by (auto simp: bot_ereal_def less_SUP_iff)
    then have "(SUP iI. f i) + (SUP iI. g i) = (SUP iI. f i + (SUP iI. g i))"
      by (intro SUP_ereal_add_left[symmetric] I {}) auto
    also have " = (SUP iI. (SUP jI. f i + g j))"
      using nonneg(1) I {} by (simp add: SUP_ereal_add_right)
    also have "  (SUP iI. f i + g i)"
      using directed by (intro SUP_least) (blast intro: SUP_upper2)
    finally show "(SUP iI. f i) + (SUP iI. g i)  (SUP iI. f i + g i)" .
  qed
qed

lemma SUP_ereal_sum_directed:
  fixes f g :: "'a ==> 'b ==> ereal"
  assumes " {}"
  assumes directed: "N i j. N  A ==> i  I ==> j  I ==> kI. nN. f n i  f n k  f n j  f n k"
  assumes nonneg: "n i. i  I ==> n  A ==> 0  f n i"
  shows "(SUP iI. nA. f n i) = (nA. SUP iI. f n i)"
proof -
  have " A ==> (SUP iI. nN. f n i) = (nN. SUP iI. f n i)" for N
  proof (induction N rule: infinite_finite_induct)
    case (insert n N)
    have "(SUP iI. f n i + (lN. f l i)) = (SUP iI. f n i) + (SUP iI. lN. f l i)"
    proof (rule SUP_ereal_add_directed)
      fix i assume " I" then show " f n i" " (lN. f l i)"
        using insert by (auto intro!: sum_nonneg nonneg)
    next
      fix i j assume " I" " I"
      from directed[OF insert(4) this]
      show "kI. f n i + (lN. f l j)  f n k + (lN. f l k)"
        by (auto intro!: add_mono sum_mono)
    qed
    with insert show ?case
      by simp
  qed (simp_all add: SUP_constant I {})
  from this[of A] show ?thesis by simp
qed

lemma suminf_SUP_eq_directed:
  fixes f :: "==> nat ==> ereal"
  assumes " {}"
  assumes directed: "N i j. i  I ==> j  I ==> finite N ==> kI. nN. f i n  f k n  f j n  f k n"
  assumes nonneg: "n i. 0  f n i"
  shows "(i. SUP nI. f n i) = (SUP nI. i. f n i)"
proof (subst (1 2) suminf_ereal_eq_SUP)
  show "n i. 0  f n i" "i. 0  (SUP nI. f n i)"
    using I {} nonneg by (auto intro: SUP_upper2)
  show "(SUP n. i<n. SUP nI. f n i) = (SUP nI. SUP j. i<j. f n i)"
    by (auto simp: finite_subset SUP_commute SUP_ereal_sum_directed assms)
qed

lemma ereal_dense3:
  fixes x y :: ereal
  shows "x < y ==> r::rat. x < real_of_rat r  real_of_rat r < y"
proof (cases x y rule: ereal2_cases, simp_all)
  fix r q :: real
  assume "r < q"
  from Rats_dense_in_real[OF this] show "x. r < real_of_rat x  real_of_rat x < q"
    by (fastforce simp: Rats_def)
next
  fix r :: real
  show "x. r < real_of_rat x" "x. real_of_rat x < r"
    using gt_ex[of r] lt_ex[of r] Rats_dense_in_real
    by (auto simp: Rats_def)
qed

lemma continuous_within_ereal[intro, simp]: " A ==> continuous (at x within A) ereal"
  using continuous_on_eq_continuous_within[of A ereal]
  by (auto intro: continuous_on_ereal continuous_on_id)

lemma ereal_open_uminus:
  fixes S :: "ereal set"
  assumes "open S"
  shows "open (uminus ` S)"
  using open S[unfolded open_generated_order]
proof induct
  have "range uminus = (UNIV :: ereal set)"
    by (auto simp: image_iff ereal_uminus_eq_reorder)
  then show "open (range uminus :: ereal set)"
    by simp
qed (auto simp: image_Union image_Int)

lemma ereal_uminus_complement:
  fixes S :: "ereal set"
  shows "uminus ` (- S) = - uminus ` S"
  by (auto intro!: bij_image_Compl_eq surjI[of _ uminus] simp: bij_betw_def)

lemma ereal_closed_uminus:
  fixes S :: "ereal set"
  assumes "closed S"
  shows "closed (uminus ` S)"
  using assms
  unfolding closed_def ereal_uminus_complement[symmetric]
  by (rule ereal_open_uminus)

lemma ereal_open_affinity_pos:
  fixes S :: "ereal set"
  assumes "open S"
    and m: " " "0 < m"
    and t: "t  "
  shows "open ((λx. m * x + t) ` S)"
proof -
  have "continuous_on UNIV (λx. inverse m * (x + - t))"
    using m t
    by (intro continuous_at_imp_continuous_on ballI continuous_at[THEN iffD2]; force)
  then have "open ((λx. inverse m * (x + -t)) -` S)"
    using open S open_vimage by blast
  also have "(λx. inverse m * (x + -t)) -` S = (λx. (x - t) / m) -` S"
    using m t by (auto simp: divide_ereal_def mult.commute minus_ereal_def
                       simp flip: uminus_ereal.simps)
  also have "(λx. (x - t) / m) -` S = (λx. m * x + t) ` S"
    using m t
    by (simp add: set_eq_iff image_iff)
       (metis abs_ereal_less0 abs_ereal_uminus ereal_divide_eq ereal_eq_minus ereal_minus(7,8)
              ereal_minus_less_minus ereal_mult_eq_PInfty ereal_uminus_uminus ereal_zero_mult)
  finally show ?thesis .
qed

lemma ereal_open_affinity:
  fixes S :: "ereal set"
  assumes "open S"
    and m: "m  " " 0"
    and t: "t  "
  shows "open ((λx. m * x + t) ` S)"
proof cases
  assume "0 < m"
  then show ?thesis
    using ereal_open_affinity_pos[OF open S _ _ t, of m] m
    by auto
next
  assume "¬ 0 < m" then
  have "0 < -m"
    using m 0
    by (cases m) auto
  then have m: "-m  " "0 < -m"
    using m
    by (auto simp: ereal_uminus_eq_reorder)
  from ereal_open_affinity_pos[OF ereal_open_uminus[OF open S] m t] show ?thesis
    unfolding image_image by simp
qed

lemma open_uminus_iff:
  fixes S :: "ereal set"
  shows "open (uminus ` S)  open S"
  using ereal_open_uminus[of S] ereal_open_uminus[of "uminus ` S"]
  by auto

lemma ereal_Liminf_uminus:
  fixes f :: "'a ==> ereal"
  shows "Liminf net (λx. - (f x)) = - Limsup net f"
  using ereal_Limsup_uminus[of _ "(λx. - (f x))"] by auto

lemma Liminf_PInfty:
  fixes f :: "'a ==> ereal"
  assumes "¬ trivial_limit net"
  shows "(f ---> ) net  Liminf net f = "
  unfolding tendsto_iff_Liminf_eq_Limsup[OF assms]
  using Liminf_le_Limsup[OF assms, of f]
  by auto

lemma Limsup_MInfty:
  fixes f :: "'a ==> ereal"
  assumes "¬ trivial_limit net"
  shows "(f ---> -) net  Limsup net f = -"
  unfolding tendsto_iff_Liminf_eq_Limsup[OF assms]
  using Liminf_le_Limsup[OF assms, of f]
  by auto

lemma convergent_ereal: 🍋 RENAME
  fixes X :: "nat ==> 'a :: {complete_linorder,linorder_topology}"
  shows "convergent X  limsup X = liminf X"
  using tendsto_iff_Liminf_eq_Limsup[of sequentially]
  by (auto simp: convergent_def)

lemma limsup_le_liminf_real:
  fixes X :: "nat ==> real" and L :: real
  assumes 1: "limsup X  L" and 2: " liminf X"
  shows "<---- L"
proof -
  from 1 2 have "limsup X  liminf X" by auto
  hence 3: "limsup X = liminf X"
    by (simp add: Liminf_le_Limsup order_class.order.antisym)
  hence 4: "convergent (λn. ereal (X n))"
    by (subst convergent_ereal)
  hence "limsup X = lim (λn. ereal(X n))"
    by (rule convergent_limsup_cl)
  also from 1 2 3 have "limsup X = L" by auto
  finally have "lim (λn. ereal(X n)) = L" ..
  hence "(λn. ereal (X n)) <---- L"
    using "4" convergent_LIMSEQ_iff by force
  thus ?thesis by simp
qed

lemma liminf_PInfty:
  fixes X :: "nat ==> ereal"
  shows "<----   liminf X = "
  by (metis Liminf_PInfty trivial_limit_sequentially)

lemma limsup_MInfty:
  fixes X :: "nat ==> ereal"
  shows "<---- -  limsup X = -"
  by (metis Limsup_MInfty trivial_limit_sequentially)

lemma SUP_eq_LIMSEQ:
  assumes "mono f"
  shows "(SUP n. ereal (f n)) = ereal x  f <---- x"
proof
  have inc: "incseq (λi. ereal (f i))"
    using mono f unfolding mono_def incseq_def by auto
  {
    assume "<---- x"
    then have "(λi. ereal (f i)) <---- ereal x"
      by auto
    from SUP_Lim[OF inc this] show "(SUP n. ereal (f n)) = ereal x" .
  next
    assume "(SUP n. ereal (f n)) = ereal x"
    with LIMSEQ_SUP[OF inc] show "<---- x" by auto
  }
qed

lemma liminf_ereal_cminus:
  fixes f :: "nat ==> ereal"
  assumes " -"
  shows "liminf (λx. c - f x) = c - limsup f"
proof (cases c)
  case PInf
  then show ?thesis
    by (simp add: Liminf_const)
next
  case (real r)
  then show ?thesis
    by (simp add: liminf_SUP_INF limsup_INF_SUP INF_ereal_minus_right SUP_ereal_minus_right)
qed (use c - in simp)


subsubsection Continuity

lemma continuous_at_of_ereal:
  "x0 :: ereal   ==> continuous (at x0) real_of_ereal"
  unfolding continuous_at
  by (rule lim_real_of_ereal) (simp add: ereal_real)

lemma nhds_ereal: "nhds (ereal r) = filtermap ereal (nhds r)"
  by (simp add: filtermap_nhds_open_map open_ereal continuous_at_of_ereal)

lemma at_ereal: "at (ereal r) = filtermap ereal (at r)"
  by (simp add: filter_eq_iff eventually_at_filter nhds_ereal eventually_filtermap)

lemma at_left_ereal: "at_left (ereal r) = filtermap ereal (at_left r)"
  by (simp add: filter_eq_iff eventually_at_filter nhds_ereal eventually_filtermap)

lemma at_right_ereal: "at_right (ereal r) = filtermap ereal (at_right r)"
  by (simp add: filter_eq_iff eventually_at_filter nhds_ereal eventually_filtermap)

lemma
  shows at_left_PInf: "at_left  = filtermap ereal at_top"
    and at_right_MInf: "at_right (-) = filtermap ereal at_bot"
  unfolding filter_eq_iff eventually_filtermap eventually_at_top_dense eventually_at_bot_dense
    eventually_at_left[OF ereal_less(5)] eventually_at_right[OF ereal_less(6)]
  by (auto simp: ereal_all_split ereal_ex_split)

lemma ereal_tendsto_simps1:
  "((f  real_of_ereal) ---> y) (at_left (ereal x))  (f ---> y) (at_left x)"
  "((f  real_of_ereal) ---> y) (at_right (ereal x))  (f ---> y) (at_right x)"
  "((f  real_of_ereal) ---> y) (at_left (::ereal))  (f ---> y) at_top"
  "((f  real_of_ereal) ---> y) (at_right (-::ereal))  (f ---> y) at_bot"
  unfolding tendsto_compose_filtermap at_left_ereal at_right_ereal at_left_PInf at_right_MInf
  by (auto simp: filtermap_filtermap filtermap_ident)

lemma ereal_tendsto_simps2:
  "((ereal  f) ---> ereal a) F  (f ---> a) F"
  "((ereal  f) ---> ) F  (LIM x F. f x :> at_top)"
  "((ereal  f) ---> -) F  (LIM x F. f x :> at_bot)"
  unfolding tendsto_PInfty filterlim_at_top_dense tendsto_MInfty filterlim_at_bot_dense
  using lim_ereal by (simp_all add: comp_def)

lemma inverse_infty_ereal_tendsto_0: "inverse ←- (0::ereal)"
proof -
  have **: "((λx. ereal (inverse x)) ---> ereal 0) at_infinity"
    by (intro tendsto_intros tendsto_inverse_0)
  then have "((λx. if x = 0 then  else ereal (inverse x)) ---> 0) at_top"
  proof (rule filterlim_mono_eventually)
    show "nhds (ereal 0)  nhds 0"
      by (simp add: zero_ereal_def)
    show "(at_top::real filter)  at_infinity"
      by (simp add: at_top_le_at_infinity)
  qed auto
  then show ?thesis
    unfolding at_infty_ereal_eq_at_top tendsto_compose_filtermap[symmetric] comp_def by auto
qed

lemma inverse_ereal_tendsto_pos:
  fixes x :: ereal assumes "0 < x"
  shows "inverse ←-x inverse x"
proof (cases x)
  case (real r)
  with 0 < x have **: "(λx. ereal (inverse x)) ←-r ereal (inverse r)"
    by (auto intro!: tendsto_inverse)
  from real 0 < x show ?thesis
    by (auto simp: at_ereal tendsto_compose_filtermap[symmetric] eventually_at_filter
             intro!: Lim_transform_eventually[OF **] t1_space_nhds)
qed (insert 0 < x, auto intro!: inverse_infty_ereal_tendsto_0)

lemma inverse_ereal_tendsto_at_right_0: "(inverse ---> ) (at_right (0::ereal))"
  unfolding tendsto_compose_filtermap[symmetric] at_right_ereal zero_ereal_def
  by (subst filterlim_cong[OF refl refl, where g="λx. ereal (inverse x)"])
     (auto simp: eventually_at_filter tendsto_PInfty_eq_at_top filterlim_inverse_at_top_right)

lemmas ereal_tendsto_simps = ereal_tendsto_simps1 ereal_tendsto_simps2

lemma continuous_at_iff_ereal:
  fixes f :: "'a::t2_space ==> real"
  shows "continuous (at x0 within s) f  continuous (at x0 within s) (ereal  f)"
  unfolding continuous_within comp_def lim_ereal ..

lemma continuous_on_iff_ereal:
  fixes f :: "'a::t2_space => real"
  assumes "open A"
  shows "continuous_on A f  continuous_on A (ereal  f)"
  unfolding continuous_on_def comp_def lim_ereal ..

lemma continuous_on_real: "continuous_on (UNIV - {, -::ereal}) real_of_ereal"
  using continuous_at_of_ereal continuous_on_eq_continuous_at open_image_ereal
  by auto

lemma continuous_on_iff_real:
  fixes f :: "'a::t2_space ==> ereal"
  assumes "x. x  A ==> f x  "
  shows "continuous_on A f  continuous_on A (real_of_ereal  f)"
proof
  assume L: "continuous_on A f"
  have "f ` A  UNIV - {, -}"
    using assms by force
  then show "continuous_on A (real_of_ereal  f)"
    by (meson L continuous_on_compose continuous_on_real continuous_on_subset)
next
  assume R: "continuous_on A (real_of_ereal  f)"
  then have "continuous_on A (ereal  (real_of_ereal  f))"
    by (meson continuous_at_iff_ereal continuous_on_eq_continuous_within)
  then show "continuous_on A f"
    using assms ereal_real' by auto
qed

lemma continuous_uminus_ereal [continuous_intros]: "continuous_on (A :: ereal set) uminus"
  unfolding continuous_on_def
  by (intro ballI tendsto_uminus_ereal[of "λx. x::ereal"]) simp

lemma ereal_uminus_atMost [simp]: "uminus ` {..(a::ereal)} = {-a..}"
proof (intro equalityI subsetI)
  fix x :: ereal assume " {-a..}"
  hence "-(-x)  uminus ` {..a}" by (intro imageI) (simp add: ereal_uminus_le_reorder)
  thus " uminus ` {..a}" by simp
qed auto

lemma continuous_on_inverse_ereal [continuous_intros]:
  "continuous_on {0::ereal ..} inverse"
  unfolding continuous_on_def
proof clarsimp
  fix x :: ereal assume " x"
  moreover have "at 0 within {0 ..} = at_right (0::ereal)"
    by (auto simp: filter_eq_iff eventually_at_filter le_less)
  moreover have "at x within {0 ..} = at x" if "0 < x"
    using that by (intro at_within_nhd[of _ "{0<..}"]) auto
  ultimately show "(inverse ---> inverse x) (at x within {0..})"
    by (auto simp: le_less inverse_ereal_tendsto_at_right_0 inverse_ereal_tendsto_pos)
qed

lemma continuous_inverse_ereal_nonpos: "continuous_on ({..<0} :: ereal set) inverse"
proof (subst continuous_on_cong[OF refl])
  have "continuous_on {(0::ereal)<..} inverse"
    by (rule continuous_on_subset[OF continuous_on_inverse_ereal]) auto
  thus "continuous_on {..<(0::ereal)} (uminus  inverse  uminus)"
    by (intro continuous_intros) simp_all
qed simp

lemma tendsto_inverse_ereal:
  assumes "(f ---> (c :: ereal)) F"
  assumes "eventually (λx. f x  0) F"
  shows "((λx. inverse (f x)) ---> inverse c) F"
  by (cases "F = bot")
     (auto intro!: tendsto_lowerbound assms
                   continuous_on_tendsto_compose[OF continuous_on_inverse_ereal])


subsubsection liminf and limsup

lemma Limsup_ereal_mult_right:
  assumes " bot" "(c::real)  0"
  shows "Limsup F (λn. f n * ereal c) = Limsup F f * ereal c"
proof (rule Limsup_compose_continuous_mono)
  from assms show "continuous_on UNIV (λa. a * ereal c)"
    using tendsto_cmult_ereal[of "ereal c" "λx. x" ]
    by (force simp: continuous_on_def mult_ac)
qed (use assms in auto simp: mono_def ereal_mult_right_mono)

lemma Liminf_ereal_mult_right:
  assumes " bot" "(c::real)  0"
  shows "Liminf F (λn. f n * ereal c) = Liminf F f * ereal c"
proof (rule Liminf_compose_continuous_mono)
  from assms show "continuous_on UNIV (λa. a * ereal c)"
    using tendsto_cmult_ereal[of "ereal c" "λx. x" ]
    by (force simp: continuous_on_def mult_ac)
qed (use assms in auto simp: mono_def ereal_mult_right_mono)

lemma Liminf_ereal_mult_left:
  assumes " bot" "(c::real)  0"
    shows "Liminf F (λn. ereal c * f n) = ereal c * Liminf F f"
using Liminf_ereal_mult_right[OF assms] by (subst (1 2) mult.commute)

lemma Limsup_ereal_mult_left:
  assumes " bot" "(c::real)  0"
  shows "Limsup F (λn. ereal c * f n) = ereal c * Limsup F f"
  using Limsup_ereal_mult_right[OF assms] by (subst (1 2) mult.commute)

lemma limsup_ereal_mult_right:
  "(c::real)  0 ==> limsup (λn. f n * ereal c) = limsup f * ereal c"
  by (rule Limsup_ereal_mult_right) simp_all

lemma limsup_ereal_mult_left:
  "(c::real)  0 ==> limsup (λn. ereal c * f n) = ereal c * limsup f"
  by (simp add: Limsup_ereal_mult_left)

lemma Limsup_add_ereal_right:
  " bot ==> abs c   ==> Limsup F (λn. g n + (c :: ereal)) = Limsup F g + c"
  by (rule Limsup_compose_continuous_mono) (auto simp: mono_def add_mono continuous_on_def)

lemma Limsup_add_ereal_left:
  " bot ==> abs c   ==> Limsup F (λn. (c :: ereal) + g n) = c + Limsup F g"
  by (subst (1 2) add.commute) (rule Limsup_add_ereal_right)

lemma Liminf_add_ereal_right:
  " bot ==> abs c   ==> Liminf F (λn. g n + (c :: ereal)) = Liminf F g + c"
  by (rule Liminf_compose_continuous_mono) (auto simp: mono_def add_mono continuous_on_def)

lemma Liminf_add_ereal_left:
  " bot ==> abs c   ==> Liminf F (λn. (c :: ereal) + g n) = c + Liminf F g"
  by (subst (1 2) add.commute) (rule Liminf_add_ereal_right)

lemma
  assumes " bot"
  assumes nonneg: "eventually (λx. f x  (0::ereal)) F"
  shows Liminf_inverse_ereal: "Liminf F (λx. inverse (f x)) = inverse (Limsup F f)"
  and Limsup_inverse_ereal: "Limsup F (λx. inverse (f x)) = inverse (Liminf F f)"
proof -
  define inv where [abs_def]: "inv x = (if x  0 then  else inverse x)" for x :: ereal
  have "continuous_on ({..0}  {0..}) inv" unfolding inv_def
    by (intro continuous_on_If) (auto intro!: continuous_intros)
  also have "{..0}  {0..} = (UNIV :: ereal set)" by auto
  finally have cont: "continuous_on UNIV inv" .
  have antimono: "antimono inv" unfolding inv_def antimono_def
    by (auto intro!: ereal_inverse_antimono)

  have "Liminf F (λx. inverse (f x)) = Liminf F (λx. inv (f x))" using nonneg
    by (auto intro!: Liminf_eq elim!: eventually_mono simp: inv_def)
  also have "... = inv (Limsup F f)"
    by (simp add: assms(1) Liminf_compose_continuous_antimono[OF cont antimono])
  also from assms have "Limsup F f  0" by (intro le_Limsup) simp_all
  hence "inv (Limsup F f) = inverse (Limsup F f)" by (simp add: inv_def)
  finally show "Liminf F (λx. inverse (f x)) = inverse (Limsup F f)" .

  have "Limsup F (λx. inverse (f x)) = Limsup F (λx. inv (f x))" using nonneg
    by (auto intro!: Limsup_eq elim!: eventually_mono simp: inv_def)
  also have "... = inv (Liminf F f)"
    by (simp add: assms(1) Limsup_compose_continuous_antimono[OF cont antimono])
  also from assms have "Liminf F f  0" by (intro Liminf_bounded) simp_all
  hence "inv (Liminf F f) = inverse (Liminf F f)" by (simp add: inv_def)
  finally show "Limsup F (λx. inverse (f x)) = inverse (Liminf F f)" .
qed

lemma ereal_diff_le_mono_left: "[ x  z; 0  y ] ==> x - y  (z :: ereal)"
by(cases x y z rule: ereal3_cases) simp_all

lemma neg_0_less_iff_less_erea [simp]: "0 < - a  (a :: ereal) < 0"
by(cases a) simp_all

lemma not_infty_ereal: "x    (x'. x = ereal x')"
  by auto

lemma neq_PInf_trans: fixes x y :: ereal shows "[ y  ; x  y ] ==> x  "
  by auto

lemma mult_2_ereal: "ereal 2 * x = x + x"
  by(cases x) simp_all

lemma ereal_diff_le_self: " y ==> x - y  (x :: ereal)"
  by(cases x y rule: ereal2_cases) simp_all

lemma ereal_le_add_self: " y ==> x  x + (y :: ereal)"
  by(cases x y rule: ereal2_cases) simp_all

lemma ereal_le_add_self2: " y ==> x  y + (x :: ereal)"
  by(cases x y rule: ereal2_cases) simp_all

lemma ereal_diff_nonpos:
  fixes a b :: ereal shows "[ a  b; a =  ==> b  ; a = - ==> b  - ] ==> a - b  0"
  by (cases rule: ereal2_cases[of a b]) auto

lemma minus_ereal_0 [simp]: "x - ereal 0 = x"
  by(simp flip: zero_ereal_def)

lemma ereal_diff_eq_0_iff: fixes a b :: ereal
  shows "(a =  ==> b  ==> a - b = 0  a = b"
  by(cases a b rule: ereal2_cases) simp_all

lemma SUP_ereal_eq_0_iff_nonneg:
  fixes f :: "==> ereal" and A
  assumes nonneg: "xA. f x  0"
    and A:" {}"
  shows "(SUP xA. f x) = 0  (xA. f x = 0)" (is "?lhs  _")
proof(intro iffI ballI)
  fix x
  assume "?lhs" " A"
  from x A have "f x  (SUP xA. f x)" by(rule SUP_upper)
  with ?lhs show "f x = 0" using nonneg x A by auto
qed (simp add: A)

lemma ereal_divide_le_posI:
  fixes x y z :: ereal
  shows "x > 0 ==> z  - ==> z  x * y ==> z / x  y"
  by (cases rule: ereal3_cases[of x y z])(auto simp: field_simps split: if_split_asm)

lemma add_diff_eq_ereal:
  fixes x y z :: ereal
  shows "x + (y - z) = x + y - z"
  by(cases x y z rule: ereal3_cases) simp_all

lemma ereal_diff_gr0:
  fixes a b :: ereal
  shows "a < b ==> 0 < b - a"
  by (cases rule: ereal2_cases[of a b]) auto

lemma ereal_minus_minus:
  fixes x y z :: ereal shows
  "(y =  ==> z  ==> x - (y - z) = x + z - y"
  by(cases x y z rule: ereal3_cases) simp_all

lemma diff_diff_commute_ereal:
  fixes x y z :: ereal
  shows "x - y - z = x - z - y"
  by (metis add_diff_eq_ereal ereal_add_uminus_conv_diff)

lemma ereal_diff_eq_MInfty_iff:
  fixes x y :: ereal
  shows "x - y = -  x = -  y  -  y =   x  "
  by(cases x y rule: ereal2_cases) simp_all

lemma ereal_diff_add_inverse:
  fixes x y :: ereal
  shows "x   ==> x + y - x = y"
  by(cases x y rule: ereal2_cases) simp_all

lemma tendsto_diff_ereal:
  fixes x y :: ereal
  assumes x: "x  " and y: "y  "
  assumes f: "(f ---> x) F" and g: "(g ---> y) F"
  shows "((λx. f x - g x) ---> x - y) F"
proof -
  from x obtain r where x': "x = ereal r" by (cases x) auto
  with f have "((λi. real_of_ereal (f i)) ---> r) F" by simp
  moreover
  from y obtain p where y': "y = ereal p" by (cases y) auto
  with g have "((λi. real_of_ereal (g i)) ---> p) F" by simp
  ultimately have "((λi. real_of_ereal (f i) - real_of_ereal (g i)) ---> r - p) F"
    by (rule tendsto_diff)
  moreover
  from eventually_finite[OF x f] eventually_finite[OF y g]
  have "eventually (λx. f x - g x = ereal (real_of_ereal (f x) - real_of_ereal (g x))) F"
    by eventually_elim auto
  ultimately show ?thesis
    by (simp add: x' y' cong: filterlim_cong)
qed

lemma continuous_on_diff_ereal:
  "continuous_on A f ==> continuous_on A g ==> (x. x  A ==> f x  ==> (x. x  A ==> g x  ==> continuous_on A (λz. f z - g z::ereal)"
  by (auto simp: tendsto_diff_ereal continuous_on_def)


subsubsection Tests for code generator

text A small list of simple arithmetic expressions.

value "- :: ereal"
value "- :: ereal"
value "4 + 5 / 4 - ereal 2 :: ereal"
value "ereal 3 < "
value "real_of_ereal (::ereal) = 0"

end

Messung V0.5 in Prozent
C=98 H=86 G=91

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.154Bemerkung:  (vorverarbeitet am  2026-04-30) ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge