Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/HOL/Analysis/   (Beweissystem Isabelle Version 2025-1©)  Datei vom 16.11.2025 mit Größe 371 kB image not shown  

Quellcode-Bibliothek Henstock_Kurzweil_Integration.thy

  Sprache: Isabelle
 

(*  Author:     John Harrison
  Author: Robert Himmelmann, TU Muenchen (Translation from HOL light)
  Huge cleanup by LCP
*)

section Henstock-Kurzweil Gauge Integration in Many Dimensions

theory Henstock_Kurzweil_Integration
imports
  Lebesgue_Measure Tagged_Division "HOL-Real_Asymp.Real_Asymp"

begin

lemma norm_diff2: "[y = y1 + y2; x = x1 + x2; e = e1 + e2; norm(y1 - x1) e1; norm(y2 - x2) e2]
  ==> norm(y-x) e"
  by (simp add: add_diff_add norm_add_rule_thm)

lemma setcomp_dot1: "{z. P (z (i,0))} = {(x,y). P(x i)}"
  by auto

lemma setcomp_dot2: "{z. P (z (0,i))} = {(x,y). P(y i)}"
  by auto

lemma Sigma_Int_Paircomp1: "(Sigma A B) {(x, y). P x} = Sigma (A {x. P x}) B"
  by blast

lemma Sigma_Int_Paircomp2: "(Sigma A B) {(x, y). P y} = Sigma A (λz. B z {y. P y})"
  by blast
(* END MOVE *)

subsection Content (length, area, volume, etc.) of an interval

abbreviation content :: "'a::euclidean_space set ==> real"
  where "content s measure lborel s"

lemma content_cbox_cases:
  "content (cbox a b) = (if iBasis. ai bi then prod (λi. bi - ai) Basis else 0)"
  by (simp add: measure_lborel_cbox_eq inner_diff)

lemma content_cbox: "iBasis. ai bi ==> content (cbox a b) = (iBasis. bi - ai)"
  unfolding content_cbox_cases by simp

lemma content_cbox': "cbox a b {} ==> content (cbox a b) = (iBasis. bi - ai)"
  by (simp add: box_ne_empty inner_diff)

lemma content_cbox_if: "content (cbox a b) = (if cbox a b = {} then 0 else iBasis. bi - ai)"
  by (simp add: content_cbox')

lemma content_cbox_cart:
   "cbox a b {} ==> content(cbox a b) = prod (λi. b$i - a$i) UNIV"
  by (simp add: content_cbox_if Basis_vec_def cart_eq_inner_axis axis_eq_axis prod.UNION_disjoint)

lemma content_cbox_if_cart:
   "content(cbox a b) = (if cbox a b = {} then 0 else prod (λi. b$i - a$i) UNIV)"
  by (simp add: content_cbox_cart)

lemma content_division_of:
  assumes "K D" "D division_of S"
  shows "content K = (i Basis. interval_upperbound K i - interval_lowerbound K i)"
proof -
  obtain a b where "K = cbox a b"
    using cbox_division_memE assms by metis
  then show ?thesis
    using assms by (force simp: division_of_def content_cbox')
qed

lemma content_real: "a b ==> content {a..b} = b - a"
  by simp

lemma abs_eq_content: "y - x = (if xy then content {x..y} else content {y..x})"
  by (auto simp: content_real)

lemma content_singleton: "content {a} = 0"
  by simp

lemma content_unit[iff]: "content (cbox 0 (One::'a::euclidean_space)) = 1"
  by simp

lemma content_pos_le [iff]: "0 content X"
  by simp

corollary🍋tag unimportant content_nonneg [simp]: "¬ content (cbox a b) < 0"
  using not_le by blast

lemma content_pos_lt: "iBasis. ai < bi ==> 0 < content (cbox a b)"
  by (auto simp: less_imp_le inner_diff box_eq_empty intro!: prod_pos)

lemma content_eq_0: "content (cbox a b) = 0 (iBasis. bi ai)"
  by (auto simp: content_cbox_cases not_le intro: less_imp_le antisym eq_refl)

lemma content_eq_0_interior: "content (cbox a b) = 0 interior(cbox a b) = {}"
  unfolding content_eq_0 interior_cbox box_eq_empty by auto

lemma content_pos_lt_eq: "0 < content (cbox a (b::'a::euclidean_space)) (iBasis. ai < bi)"
  by (auto simp: content_cbox_cases less_le prod_nonneg)

lemma content_empty [simp]: "content {} = 0"
  by simp

lemma content_real_if [simp]: "content {a..b} = (if a b then b - a else 0)"
  by (simp add: content_real)

lemma content_subset: "cbox a b cbox c d ==> content (cbox a b) content (cbox c d)"
  unfolding measure_def
  by (intro enn2real_mono emeasure_mono) (auto simp: emeasure_lborel_cbox_eq)

lemma content_lt_nz: "0 < content (cbox a b) content (cbox a b) 0"
  by (fact zero_less_measure_iff)

lemma content_Pair: "content (cbox (a,c) (b,d)) = content (cbox a b) * content (cbox c d)"
  unfolding measure_lborel_cbox_eq Basis_prod_def
  using Basis_zero 
  apply (simp add: prod.union_disjoint disjoint_iff image_iff ball_Un prod.reindex_nontrivial)
  apply (subst (1 2) prod.reindex_nontrivial)
  apply auto
  done

lemma content_cbox_pair_eq0_D:
   "content (cbox (a,c) (b,d)) = 0 ==> content (cbox a b) = 0 content (cbox c d) = 0"
  by (simp add: content_Pair)

lemma content_cbox_plus:
  fixes x :: "'a::euclidean_space"
  shows "content(cbox x (x + h *🪙R One)) = (if h 0 then h ^ DIM('a) else 0)"
  by (simp add: algebra_simps content_cbox_if box_eq_empty)

lemma content_0_subset: "content(cbox a b) = 0 ==> s cbox a b ==> content s = 0"
  using emeasure_mono[of s "cbox a b" lborel]
  by (auto simp: measure_def enn2real_eq_0_iff emeasure_lborel_cbox_eq)

lemma content_ball_pos:
  assumes "r > 0"
  shows   "content (ball c r) > 0"
proof -
  from rational_boxes[OF assms, of c] obtain a b where ab: "c box a b" "box a b ball c r"
    by auto
  then have "0 < content (box a b)"
    by (subst measure_lborel_box_eq) (auto intro!: prod_pos simp: algebra_simps box_def)
  have "emeasure lborel (box a b) emeasure lborel (ball c r)"
    using ab by (intro emeasure_mono) auto
  then show ?thesis
    using content (box a b) > 0
    by (metis Sigma_Algebra.measure_def emeasure_lborel_ball_finite enn2real_positive_iff
        infinity_ennreal_def le_zero_eq not_gr_zero)
qed

lemma content_cball_pos:
  assumes "r > 0"
  shows   "content (cball c r) > 0"
proof -
  from rational_boxes[OF assms, of c] obtain a b where ab: "c box a b" "box a b ball c r"
    by auto
  then have "0 < content (box a b)"
    by (subst measure_lborel_box_eq) (auto intro!: prod_pos simp: algebra_simps box_def)
  have "emeasure lborel (box a b) emeasure lborel (cball c r)"
    using ab by (intro emeasure_mono) auto
  also have "emeasure lborel (box a b) = ennreal (content (box a b))"
    using emeasure_lborel_box_finite[of a b] by (intro emeasure_eq_ennreal_measure) auto
  also have "emeasure lborel (cball c r) = ennreal (content (cball c r))"
    using emeasure_lborel_cball_finite[of c r] by (intro emeasure_eq_ennreal_measure) auto
  finally show ?thesis
    using content (box a b) > 0 by simp
qed

lemma content_split:
  fixes a :: "'a::euclidean_space"
  assumes "k Basis"
  shows "content (cbox a b) = content(cbox a b {x. xk c}) + content(cbox a b {x. xk c})"
  🍋 Prove using measure theory
proof (cases "iBasis. a i b i")
  case True
  have 1: "X Y Z. (iBasis. Z i (if i = k then X else Y i)) = Z k X * (iBasis-{k}. Z i (Y i))"
    by (simp add: if_distrib prod.delta_remove assms)
  note simps = interval_split[OF assms] content_cbox_cases
  have 2: "(iBasis. bi - ai) = (iBasis-{k}. bi - ai) * (bk - ak)"
    by (metis (no_types, lifting) assms finite_Basis mult.commute prod.remove)
  have "x. min (b k) c = max (a k) c ==>
    x * (bk - ak) = x * (max (a k) c - a k) + x * (b k - max (a k) c)"
    by  (auto simp: field_simps)
  moreover
  have 3: "(iBasis. ((iBasis. (if i = k then min (b k) c else b i) *🪙R i) i - a i)) =
      (iBasis. (if i = k then min (b k) c else b i) - a i)"
    "(iBasis. b i - ((iBasis. (if i = k then max (a k) c else a i) *🪙R i) i)) =
      (iBasis. b i - (if i = k then max (a k) c else a i))"
    by (simp_all cong: prod.cong)
  have "¬ a k c ==> ¬ c b k ==> False"
    unfolding not_le using True assms by auto
  ultimately show ?thesis
    using assms unfolding simps 1[of "λi x. bi - x"] 1[of "λi x. x - ai"] 2 3
    by auto
next
  case False
  then show ?thesis
    using box_ne_empty(1) by force
qed

lemma division_of_content_0:
  assumes "content (cbox a b) = 0" "d division_of (cbox a b)" "K d"
  shows "content K = 0"
  unfolding forall_in_division[OF assms(2)]
  by (meson assms content_0_subset division_of_def)

lemma sum_content_null:
  assumes "content (cbox a b) = 0"
    and "p tagged_division_of (cbox a b)"
  shows "((x,K)p. content K *🪙R f x) = (0::'a::real_normed_vector)"
proof (intro sum.neutral strip)
  fix y
  assume y: "y p"
  obtain x K where xk: "y = (x, K)"
    using surj_pair[of y] by blast
  then obtain c d where k: "K = cbox c d" "K cbox a b"
    by (metis assms(2) tagged_division_ofD(3) tagged_division_ofD(4) y)
  have "(λ(x',K'). content K' *🪙R f x') y = content K *🪙R f x"
    unfolding xk by auto
  also have " = 0"
    using assms(1) content_0_subset k(2) by auto
  finally show "(λ(x, k). content k *🪙R f x) y = 0" .
qed

global_interpretation sum_content: operative plus 0 content
  rewrites "comm_monoid_set.F plus 0 = sum"
proof -
  interpret operative plus 0 content
    by standard (auto simp: content_split [symmetric] content_eq_0_interior)
  show "operative plus 0 content"
    by standard
  show "comm_monoid_set.F plus 0 = sum"
    by (simp add: sum_def)
qed

lemma additive_content_division: "d division_of (cbox a b) ==> sum content d = content (cbox a b)"
  by (fact sum_content.division)

lemma additive_content_tagged_division:
  "d tagged_division_of (cbox a b) ==> sum (λ(x,l). content l) d = content (cbox a b)"
  by (fact sum_content.tagged_division)

lemma subadditive_content_division:
  assumes "D division_of S" "S cbox a b"
  shows "sum content D content(cbox a b)"
proof -
  have "D division_of D" "D cbox a b"
    using assms by auto
  then obtain Dwhere "D D'" "D' division_of cbox a b"
    using partial_division_extend_interval by metis
  then have "sum content D sum content D'"
    using sum_mono2 by blast
  also have " content(cbox a b)"
    by (simp add: D' division_of cbox a b additive_content_division less_eq_real_def)
  finally show ?thesis .
qed

lemma content_real_eq_0: "content {a..b::real} = 0 a b"
  by simp

lemma property_empty_interval: "a b. content (cbox a b) = 0 P (cbox a b) ==> P {}"
  using content_empty unfolding empty_as_interval by auto

lemma interval_bounds_nz_content [simp]:
  assumes "content (cbox a b) 0"
  shows "interval_upperbound (cbox a b) = b"
    and "interval_lowerbound (cbox a b) = a"
  by (metis assms content_empty interval_bounds')+

subsection Gauge integral

text Case distinction to define it first on compact intervals first, then use a limit. This is only
 much later unified. In Fremlin: Measure Theory, Volume 4I this is generalized using residual sets.

definition has_integral :: "('n::euclidean_space ==> 'b::real_normed_vector) ==> 'b ==> 'n set ==> bool"
  (infixr has'_integral 46)
  where "(f has_integral I) s
    (if a b. s = cbox a b
      then ((λp. (x,k)p. content k *🪙R f x) ---> I) (division_filter s)
      else (e>0. B>0. a b. ball 0 B cbox a b
        (z. ((λp. (x,k)p. content k *🪙R (if x s then f x else 0)) ---> z) (division_filter (cbox a b))
          norm (z - I) < e)))"

lemma has_integral_cbox:
  "(f has_integral I) (cbox a b) ((λp. (x,k)p. content k *🪙R f x) ---> I) (division_filter (cbox a b))"
  by (auto simp: has_integral_def)

lemma has_integral:
  "(f has_integral y) (cbox a b)
    (e>0. γ. gauge γ
      (D. D tagged_division_of (cbox a b) γ fine D
        norm (((x, k)D. content k *🪙R f x) - y) < e))"
  by (auto simp: dist_norm eventually_division_filter has_integral_def tendsto_iff)

lemma has_integral_real:
  "(f has_integral y) {a..b::real}
    (e>0. γ. gauge γ
      (D. D tagged_division_of {a..b} γ fine D
        norm (sum (λ(x,k). content(k) *🪙R f x) D - y) < e))"
  unfolding box_real[symmetric] by (rule has_integral)

lemma has_integralD[dest]:
  assumes "(f has_integral y) (cbox a b)"
    and "e > 0"
  obtains γ
    where "gauge γ"
      and "D. D tagged_division_of (cbox a b) ==> γ fine D ==>
        norm (((x,k)D. content k *🪙R f x) - y) < e"
  using assms unfolding has_integral by auto

lemma has_integral_alt:
  "(f has_integral y) i
    (if a b. i = cbox a b
     then (f has_integral y) i
     else (e>0. B>0. a b. ball 0 B cbox a b
      (z. ((λx. if x i then f x else 0) has_integral z) (cbox a b) norm (z - y) < e)))"
  by (subst has_integral_def) (auto simp: has_integral_cbox)

lemma has_integral_altD:
  assumes "(f has_integral y) i"
    and "¬ (a b. i = cbox a b)"
    and "e>0"
  obtains B where "B > 0"
    and "a b. ball 0 B cbox a b
      (z. ((λx. if x i then f(x) else 0) has_integral z) (cbox a b) norm(z - y) < e)"
  using assms has_integral_alt[of f y i] by auto

definition integrable_on (infixr integrable'_on 46)
  where "f integrable_on i (y. (f has_integral y) i)"

definition "integral i f = (SOME y. (f has_integral y) i ¬ f integrable_on i y=0)"

lemma integrable_integral[intro]: "f integrable_on i ==> (f has_integral (integral i f)) i"
  unfolding integrable_on_def integral_def by (metis (mono_tags, lifting))

lemma not_integrable_integral: "¬ f integrable_on i ==> integral i f = 0"
  unfolding integrable_on_def integral_def by blast

lemma has_integral_integrable[dest]: "(f has_integral i) s ==> f integrable_on s"
  unfolding integrable_on_def by auto

lemma has_integral_integral: "f integrable_on s (f has_integral (integral s f)) s"
  by auto

subsection Basic theorems about integrals

lemma has_integral_eq_rhs: "(f has_integral j) S ==> i = j ==> (f has_integral i) S"
  by (rule forw_subst)

lemma has_integral_unique_cbox:
  fixes f :: "'n::euclidean_space ==> 'a::real_normed_vector"
  shows "(f has_integral k1) (cbox a b) ==> (f has_integral k2) (cbox a b) ==> k1 = k2"
  by (meson division_filter_not_empty has_integral_cbox tendsto_unique)

lemma has_integral_unique:
  fixes f :: "'n::euclidean_space ==> 'a::real_normed_vector"
  assumes "(f has_integral k1) i" "(f has_integral k2) i"
  shows "k1 = k2"
proof (rule ccontr)
  let ?e = "norm (k1 - k2)/2"
  let ?F = "(λx. if x i then f x else 0)"
  assume "k1 k2"
  then have e: "?e > 0"
    by auto
  have nonbox: "¬ (a b. i = cbox a b)"
    using k1 k2 assms has_integral_unique_cbox by blast
  obtain B1 where B1:
      "0 < B1"
      "a b. ball 0 B1 cbox a b ==>
        z. (?F has_integral z) (cbox a b) norm (z - k1) < norm (k1 - k2)/2"
    by (rule has_integral_altD[OF assms(1) nonbox,OF e]) blast
  obtain B2 where B2:
      "0 < B2"
      "a b. ball 0 B2 cbox a b ==>
        z. (?F has_integral z) (cbox a b) norm (z - k2) < norm (k1 - k2)/2"
    by (rule has_integral_altD[OF assms(2) nonbox,OF e]) blast
  obtain a b :: 'n where ab: "ball 0 B1 cbox a b" "ball 0 B2 cbox a b"
    by (metis Un_subset_iff bounded_Un bounded_ball bounded_subset_cbox_symmetric)
  obtain w where w: "(?F has_integral w) (cbox a b)" "norm (w - k1) < norm (k1 - k2)/2"
    using B1(2)[OF ab(1)] by blast
  obtain z where z: "(?F has_integral z) (cbox a b)" "norm (z - k2) < norm (k1 - k2)/2"
    using B2(2)[OF ab(2)] by blast
  have "z = w"
    using has_integral_unique_cbox[OF w(1) z(1)] by auto
  then have "norm (k1 - k2) norm (z - k2) + norm (w - k1)"
    using norm_triangle_ineq4 [of "k1 - w" "k2 - z"]
    by (auto simp: norm_minus_commute)
  also have " < norm (k1 - k2)/2 + norm (k1 - k2)/2"
    by (metis add_strict_mono z(2) w(2))
  finally show False by auto
qed

lemma integral_unique [intro]: "(f has_integral y) k ==> integral k f = y"
  unfolding integral_def
  by (rule some_equality) (auto intro: has_integral_unique)

lemma has_integral_iff: "(f has_integral i) S (f integrable_on S integral S f = i)"
  by blast

lemma eq_integralD: "integral k f = y ==> (f has_integral y) k ¬ f integrable_on k y=0"
  unfolding integral_def integrable_on_def
  by (metis (mono_tags, lifting))

lemma has_integral_const [intro]:
  fixes a b :: "'a::euclidean_space"
  shows "((λx. c) has_integral (content (cbox a b) *🪙R c)) (cbox a b)"
  using eventually_division_filter_tagged_division[of "cbox a b"]
     additive_content_tagged_division[of _ a b]
  by (auto simp: has_integral_cbox split_beta' scaleR_sum_left[symmetric]
           elim!: eventually_mono intro!: tendsto_cong[THEN iffD1, OF _ tendsto_const])

lemma has_integral_const_real [intro]:
  fixes a b :: real
  shows "((λx. c) has_integral (content {a..b} *🪙R c)) {a..b}"
  by (metis box_real(2) has_integral_const)

lemma has_integral_integrable_integral: "(f has_integral i) s f integrable_on s integral s f = i"
  by blast

lemma integral_const [simp]:
  fixes a b :: "'a::euclidean_space"
  shows "integral (cbox a b) (λx. c) = content (cbox a b) *🪙R c"
  by blast

lemma integral_const_real [simp]:
  fixes a b :: real
  shows "integral {a..b} (λx. c) = content {a..b} *🪙R c"
  by blast

lemma has_integral_is_0_cbox:
  fixes f :: "'n::euclidean_space ==> 'a::real_normed_vector"
  assumes "x. x cbox a b ==> f x = 0"
  shows "(f has_integral 0) (cbox a b)"
    unfolding has_integral_cbox
    using eventually_division_filter_tagged_division[of "cbox a b"] assms
    by (subst tendsto_cong[where g="λ_. 0"])
       (auto elim!: eventually_mono intro!: sum.neutral simp: tag_in_interval)

lemma has_integral_is_0:
  fixes f :: "'n::euclidean_space ==> 'a::real_normed_vector"
  assumes "x. x S ==> f x = 0"
  shows "(f has_integral 0) S"
proof (cases "(a b. S = cbox a b)")
  case True with assms has_integral_is_0_cbox show ?thesis
    by blast
next
  case False
  have *: "(λx. if x S then f x else 0) = (λx. 0)"
    by (auto simp: assms)
  show ?thesis
    using has_integral_is_0_cbox False
    by (subst has_integral_alt) (force simp: *)
qed

lemma has_integral_0[simp]: "((λx::'n::euclidean_space. 0) has_integral 0) S"
  by (rule has_integral_is_0) auto

lemma has_integral_0_eq[simp]: "((λx. 0) has_integral i) S i = 0"
  using has_integral_unique[OF has_integral_0] by auto

lemma has_integral_linear_cbox:
  fixes f :: "'n::euclidean_space ==> 'a::real_normed_vector"
  assumes f: "(f has_integral y) (cbox a b)"
    and h: "bounded_linear h"
  shows "((h f) has_integral (h y)) (cbox a b)"
proof -
  interpret bounded_linear h using h .
  show ?thesis
    unfolding has_integral_cbox using tendsto [OF f [unfolded has_integral_cbox]]
    by (simp add: sum scaleR split_beta')
qed

lemma has_integral_linear:
  fixes f :: "'n::euclidean_space ==> 'a::real_normed_vector"
  assumes f: "(f has_integral y) S"
    and h: "bounded_linear h"
  shows "((h f) has_integral (h y)) S"
proof (cases "(a b. S = cbox a b)")
  case True with f h has_integral_linear_cbox show ?thesis 
    by blast
next
  case False
  interpret bounded_linear h using h .
  from pos_bounded obtain B where B: "0 < B" "x. norm (h x) norm x * B"
    by blast
  let ?S = "λf x. if x S then f x else 0"
  show ?thesis
  proof (subst has_integral_alt, clarsimp simp: False)
    fix e :: real
    assume e: "e > 0"
    have *: "0 < e/B" using e B(1) by simp
    obtain M where M:
      "M > 0"
      "a b. ball 0 M cbox a b ==>
        z. (?S f has_integral z) (cbox a b) norm (z - y) < e/B"
      using has_integral_altD[OF f False *] by blast
    show "B>0. a b. ball 0 B cbox a b
      (z. (?S(h f) has_integral z) (cbox a b) norm (z - h y) < e)"
    proof (rule exI, intro allI conjI impI)
      show "M > 0" using M by metis
    next
      fix a b::'n
      assume sb: "ball 0 M cbox a b"
      obtain z where z: "(?S f has_integral z) (cbox a b)" "norm (z - y) < e/B"
        using M(2)[OF sb] by blast
      have *: "?S(h f) = h ?S f"
        using zero by auto
      show "z. (?S(h f) has_integral z) (cbox a b) norm (z - h y) < e"
      proof (intro exI conjI)
        show "(?S(h f) has_integral h z) (cbox a b)"
          by (simp add: * has_integral_linear_cbox[OF z(1) h])
        show "norm (h z - h y) < e"
          by (metis B diff le_less_trans pos_less_divide_eq z(2))
      qed
    qed
  qed
qed

lemma has_integral_of_real:
  "(f has_integral I) A ==>
     ((λx::'a::euclidean_space. of_real (f x) :: 'b :: {real_normed_vector,real_normed_algebra_1})
        has_integral of_real I) A"
  using has_integral_linear[of f I A "of_real :: _ ==> 'b"]
  by (simp add: o_def bounded_linear_of_real)

lemma has_integral_scaleR_left:
  "(f has_integral y) S ==> ((λx. f x *🪙R c) has_integral (y *🪙R c)) S"
  using has_integral_linear[OF _ bounded_linear_scaleR_left] by (simp add: comp_def)

lemma integrable_on_scaleR_left:
  assumes "f integrable_on A"
  shows "(λx. f x *🪙R y) integrable_on A"
  using assms has_integral_scaleR_left unfolding integrable_on_def by blast

lemma has_integral_mult_left:
  fixes c :: "_ :: real_normed_algebra"
  shows "(f has_integral y) S ==> ((λx. f x * c) has_integral (y * c)) S"
  using has_integral_linear[OF _ bounded_linear_mult_left] by (simp add: comp_def)

lemma integrable_on_mult_left:
  fixes c :: "'a :: real_normed_algebra"
  assumes "f integrable_on A"
  shows   "(λx. f x * c) integrable_on A"
  using assms has_integral_mult_left by blast

lemma has_integral_divide:
  fixes c :: "_ :: real_normed_div_algebra"
  shows "(f has_integral y) S ==> ((λx. f x / c) has_integral (y / c)) S"
  unfolding divide_inverse by (simp add: has_integral_mult_left)

lemma integrable_on_divide:
  fixes c :: "'a :: real_normed_div_algebra"
  assumes "f integrable_on A"
  shows   "(λx. f x / c) integrable_on A"
  using assms has_integral_divide by blast

textThe case analysis eliminates the condition 🍋f integrable_on S at the cost
     of the type class constraint division_ring\<close>
corollary integral_mult_left [simp]:
  fixes c:: "'a::{real_normed_algebra,division_ring}"
  shows "integral S (λx. f x * c) = integral S f * c"
proof (cases "f integrable_on S c = 0")
  case True then show ?thesis
    by (force intro: has_integral_mult_left)
next
  case False then have "¬ (λx. f x * c) integrable_on S"
    using has_integral_mult_left [of "(λx. f x * c)" _ S "inverse c"]
    by (auto simp: mult.assoc)
  with False show ?thesis by (simp add: not_integrable_integral)
qed

corollary integral_mult_right [simp]:
  fixes c:: "'a::{real_normed_field}"
  shows "integral S (λx. c * f x) = c * integral S f"
by (simp add: mult.commute [of c])

corollary integral_divide [simp]:
  fixes z :: "'a::real_normed_field"
  shows "integral S (λx. f x / z) = integral S (λx. f x) / z"
using integral_mult_left [of S f "inverse z"]
  by (simp add: divide_inverse_commute)

lemma has_integral_mult_right:
  fixes c :: "'a :: real_normed_algebra"
  shows "(f has_integral y) A ==> ((λx. c * f x) has_integral (c * y)) A"
  using has_integral_linear[OF _ bounded_linear_mult_right] by (simp add: comp_def)

lemma integrable_on_mult_right:
  fixes c :: "'a :: real_normed_algebra"
  assumes "f integrable_on A"
  shows   "(λx. c * f x) integrable_on A"
  using assms has_integral_mult_right by blast

lemma has_integral_mult_right_iff:
  fixes c :: "'a :: real_normed_field"
  assumes "c 0"
  shows "((λx. c * f x) has_integral y) A (f has_integral (y / c)) A"
  using has_integral_mult_right[of f "y / c" A c] 
        has_integral_mult_right[of "λx. c * f x" y A "1/c"] assms
  by auto

lemma integrable_on_mult_right_iff [simp]:
  fixes c :: "'a :: real_normed_field"
  assumes "c 0"
  shows   "(λx. c * f x) integrable_on A f integrable_on A"
    using integrable_on_mult_right[of f A c]
          integrable_on_mult_right[of "λx. c * f x" A "inverse c"] assms
    by (auto simp: field_simps)

lemma integrable_on_mult_left_iff [simp]:
  fixes c :: "'a :: real_normed_field"
  assumes "c 0"
  shows   "(λx. f x * c) integrable_on A f integrable_on A"
  using integrable_on_mult_right_iff[OF assms, of f A] by (simp add: mult.commute)

lemma integrable_on_div_iff [simp]:
  fixes c :: "'a :: real_normed_field"
  assumes "c 0"
  shows   "(λx. f x / c) integrable_on A f integrable_on A"
  using integrable_on_mult_right_iff[of "inverse c" f A] assms by (simp add: field_simps)

lemma has_integral_cmul: "(f has_integral k) S ==> ((λx. c *🪙R f x) has_integral (c *🪙R k)) S"
  unfolding o_def[symmetric]
  by (metis has_integral_linear bounded_linear_scaleR_right)

lemma has_integral_cmult_real:
  fixes c :: real
  assumes "c 0 ==> (f has_integral x) A"
  shows "((λx. c * f x) has_integral c * x) A"
  by (metis assms has_integral_is_0 has_integral_mult_right lambda_zero)

lemma has_integral_neg: "(f has_integral k) S ==> ((λx. -(f x)) has_integral -k) S"
  by (drule_tac c="-1" in has_integral_cmul) auto

lemma has_integral_neg_iff: "((λx. - f x) has_integral k) S (f has_integral - k) S"
  using has_integral_neg[of f "- k"] has_integral_neg[of "λx. - f x" k] by auto

lemma has_integral_add_cbox:
  fixes f :: "'n::euclidean_space ==> 'a::real_normed_vector"
  assumes "(f has_integral k) (cbox a b)" "(g has_integral l) (cbox a b)"
  shows "((λx. f x + g x) has_integral (k + l)) (cbox a b)"
  using assms
    unfolding has_integral_cbox
    by (simp add: split_beta' scaleR_add_right sum.distrib[abs_def] tendsto_add)

lemma has_integral_add:
  fixes f :: "'n::euclidean_space ==> 'a::real_normed_vector"
  assumes f: "(f has_integral k) S" and g: "(g has_integral l) S"
  shows "((λx. f x + g x) has_integral (k + l)) S"
proof (cases "a b. S = cbox a b")
  case True with has_integral_add_cbox assms show ?thesis
    by blast 
next
  let ?S = "λf x. if x S then f x else 0"
  case False
  then show ?thesis
  proof (subst has_integral_alt, clarsimp, goal_cases)
    case (1 e)
    then have e2: "e/2 > 0"
      by auto
    obtain Bf where "0 < Bf"
      and Bf: "a b. ball 0 Bf cbox a b ==>

                     z. (?S f has_integral z) (cbox a b) norm (z - k) < e/2"
      using has_integral_altD[OF f False e2] by blast
    obtain Bg where "0 < Bg"
      and Bg: "a b. ball 0 Bg (cbox a b) ==>
                     z. (?S g has_integral z) (cbox a b) norm (z - l) < e/2"
      using has_integral_altD[OF g False e2] by blast
    show ?case
    proof (rule_tac x="max Bf Bg" in exI, clarsimp simp add: max.strict_coboundedI1 0 🚫)
      fix a b
      assume "ball 0 (max Bf Bg) cbox a (b::'n)"
      then have fs: "ball 0 Bf cbox a (b::'n)" and gs: "ball 0 Bg cbox a (b::'n)"
        by auto
      obtain w where w: "(?S f has_integral w) (cbox a b)" "norm (w - k) < e/2"
        using Bf[OF fs] by blast
      obtain z where z: "(?S g has_integral z) (cbox a b)" "norm (z - l) < e/2"
        using Bg[OF gs] by blast
      have *: "x. (if x S then f x + g x else 0) = (?S f x) + (?S g x)"
        by auto
      show "z. (?S(λx. f x + g x) has_integral z) (cbox a b) norm (z - (k + l)) < e"
      proof (intro exI conjI)
        show "(?S(λx. f x + g x) has_integral (w + z)) (cbox a b)"
          by (simp add: has_integral_add_cbox[OF w(1) z(1), unfolded *[symmetric]])
        show "norm (w + z - (k + l)) < e"
          by (metis dist_norm dist_triangle_add_half w(2) z(2))
      qed
    qed
  qed
qed

lemma has_integral_diff:
  "(f has_integral k) S ==> (g has_integral l) S ==>
    ((λx. f x - g x) has_integral (k - l)) S"
  using has_integral_add[OF _ has_integral_neg, of f k S g l]
  by (auto simp: algebra_simps)

lemma integral_0 [simp]:
  "integral S (λx::'n::euclidean_space. 0::'m::real_normed_vector) = 0"
  by auto

lemma integral_add: "f integrable_on S ==> g integrable_on S ==>
    integral S (λx. f x + g x) = integral S f + integral S g"
  by (rule integral_unique) (metis integrable_integral has_integral_add)

lemma integral_cmul [simp]: "integral S (λx. c *🪙R f x) = c *🪙R integral S f"
proof (cases "f integrable_on S c = 0")
  case True with has_integral_cmul integrable_integral show ?thesis
    by fastforce
next
  case False then have "¬ (λx. c *🪙R f x) integrable_on S"
    using has_integral_cmul [of "(λx. c *🪙R f x)" _ S "inverse c"by auto
  with False show ?thesis by (simp add: not_integrable_integral)
qed

lemma integral_mult:
  fixes K::real
  shows "f integrable_on X ==> K * integral X f = integral X (λx. K * f x)"
  by simp

lemma integral_neg [simp]: "integral S (λx. - f x) = - integral S f"
  by (metis eq_integralD equation_minus_iff has_integral_iff has_integral_neg_iff neg_equal_0_iff_equal)

lemma integral_diff: "f integrable_on S ==> g integrable_on S ==>
    integral S (λx. f x - g x) = integral S f - integral S g"
  by (rule integral_unique) (metis integrable_integral has_integral_diff)

lemma integrable_0: "(λx. 0) integrable_on S"
  unfolding integrable_on_def using has_integral_0 by auto

lemma integrable_add: "f integrable_on S ==> g integrable_on S ==> (λx. f x + g x) integrable_on S"
  unfolding integrable_on_def by(auto intro: has_integral_add)

lemma integrable_cmul: "f integrable_on S ==> (λx. c *🪙R f(x)) integrable_on S"
  unfolding integrable_on_def by(auto intro: has_integral_cmul)

lemma integrable_on_scaleR_iff [simp]:
  fixes c :: real
  assumes "c 0"
  shows "(λx. c *🪙R f x) integrable_on S f integrable_on S"
  using integrable_cmul[of "λx. c *🪙R f x" S "1 / c"] integrable_cmul[of f S c] c 0
  by auto

lemma integrable_on_cmult_iff [simp]:
  fixes c :: real
  assumes "c 0"
  shows "(λx. c * f x) integrable_on S f integrable_on S"
  using integrable_on_scaleR_iff [of c f] assms by simp

lemma integrable_on_cmult_left:
  assumes "f integrable_on S"
  shows "(λx. of_real c * f x) integrable_on S"
    using integrable_cmul[of f S "of_real c"] assms
    by (simp add: scaleR_conv_of_real)

lemma integrable_neg: "f integrable_on S ==> (λx. -f(x)) integrable_on S"
  unfolding integrable_on_def by(auto intro: has_integral_neg)

lemma integrable_neg_iff: "(λx. -f(x)) integrable_on S f integrable_on S"
  using integrable_neg by fastforce

lemma integrable_diff:
  "f integrable_on S ==> g integrable_on S ==> (λx. f x - g x) integrable_on S"
  unfolding integrable_on_def by(auto intro: has_integral_diff)

lemma integrable_linear:
  "f integrable_on S ==> bounded_linear h ==> (h f) integrable_on S"
  unfolding integrable_on_def by(auto intro: has_integral_linear)

lemma integral_linear:
  "f integrable_on S ==> bounded_linear h ==> integral S (h f) = h (integral S f)"
  by (meson has_integral_iff has_integral_linear)

lemma integrable_on_cnj_iff:
  "(λx. cnj (f x)) integrable_on A f integrable_on A"
  using integrable_linear[OF _ bounded_linear_cnj, of f A]
        integrable_linear[OF _ bounded_linear_cnj, of "cnj f" A]
  by (auto simp: o_def)

lemma integral_cnj: "cnj (integral A f) = integral A (λx. cnj (f x))"
  by (cases "f integrable_on A")
     (simp_all add: integral_linear[OF _ bounded_linear_cnj, symmetric]
                    o_def integrable_on_cnj_iff not_integrable_integral)

lemma has_integral_cnj: "(cnj f has_integral (cnj I)) A = (f has_integral I) A"
  unfolding has_integral_iff comp_def
  by (metis integral_cnj complex_cnj_cancel_iff integrable_on_cnj_iff)

lemma integral_component_eq[simp]:
  fixes f :: "'n::euclidean_space ==> 'm::euclidean_space"
  assumes "f integrable_on S"
  shows "integral S (λx. f x k) = integral S f k"
  unfolding integral_linear[OF assms(1) bounded_linear_inner_left,unfolded o_def] ..

lemma integral_eq_iff_componentwise:
  fixes f :: "'a :: euclidean_space ==> 'b :: euclidean_space"
  assumes "f integrable_on A"
  shows "integral A f = I (bBasis. integral A (λx. f x b) = I b)"
proof -
  have "integral A f = I (bBasis. integral A f b = I b)"
    by (metis euclidean_eqI)
  also have " (bBasis. integral A (λx. f x b) = I b)"
    using assms by force
  finally show ?thesis .
qed

lemma has_integral_sum:
  assumes "finite T"
    and "a. a T ==> ((f a) has_integral (i a)) S"
  shows "((λx. sum (λa. f a x) T) has_integral (sum i T)) S"
  using finite T subset_refl[of T]
  by (induct rule: finite_subset_induct) (use assms in auto simp: has_integral_add)

lemma integral_sum:
  "[finite I; a. a I ==> f a integrable_on S] ==>
   integral S (λx. aI. f a x) = (aI. integral S (f a))"
  by (simp add: has_integral_sum integrable_integral integral_unique)

lemma integrable_sum:
  "[finite I; a. a I ==> f a integrable_on S] ==> (λx. aI. f a x) integrable_on S"
  unfolding integrable_on_def using has_integral_sum[of I] by metis

lemma has_integral_eq:
  assumes "x. x s ==> f x = g x"
    and f: "(f has_integral k) s"
  shows "(g has_integral k) s"
  using has_integral_diff[OF f, of "λx. f x - g x" 0]
  using has_integral_is_0[of s "λx. f x - g x"]
  using assms
  by auto

lemma integrable_eq: "[f integrable_on s; x. x s ==> f x = g x] ==> g integrable_on s"
  unfolding integrable_on_def
  using has_integral_eq[of s f g] has_integral_eq by blast

lemma has_integral_cong:
  assumes "x. x s ==> f x = g x"
  shows "(f has_integral i) s = (g has_integral i) s"
  by (metis assms has_integral_eq)

lemma integrable_cong:
  assumes "x. x A ==> f x = g x"
  shows   "f integrable_on A g integrable_on A"
  using has_integral_cong [OF assms] by fast

lemma integral_cong:
  assumes "x. x s ==> f x = g x"
  shows "integral s f = integral s g"
  unfolding integral_def
by (metis (full_types, opaque_lifting) assms has_integral_cong integrable_eq)

lemma integrable_on_cmult_left_iff [simp]:
  assumes "c 0"
  shows "(λx. of_real c * f x) integrable_on s f integrable_on s"
        (is "?lhs = ?rhs")
proof
  assume ?lhs
  then have "(λx. of_real (1 / c) * (of_real c * f x)) integrable_on s"
    using integrable_cmul[of "λx. of_real c * f x" s "1 / of_real c"]
    by (simp add: scaleR_conv_of_real)
  then have "(λx. (of_real (1 / c) * of_real c * f x)) integrable_on s"
    by (simp add: algebra_simps)
  with c 0 show ?rhs
    by (metis (no_types, lifting) integrable_eq mult.left_neutral nonzero_divide_eq_eq of_real_1 of_real_mult)
qed (blast intro: integrable_on_cmult_left)

lemma integrable_on_cmult_right:
  fixes f :: "_ ==> 'b :: {comm_ring,real_algebra_1,real_normed_vector}"
  assumes "f integrable_on s"
  shows "(λx. f x * of_real c) integrable_on s"
  using integrable_on_cmult_left [OF assms] by (simp add: mult.commute)

lemma integrable_on_cmult_right_iff [simp]:
  fixes f :: "_ ==> 'b :: {comm_ring,real_algebra_1,real_normed_vector}"
  assumes "c 0"
  shows "(λx. f x * of_real c) integrable_on s f integrable_on s"
  using integrable_on_cmult_left_iff [OF assms] by (simp add: mult.commute)

lemma integrable_on_cdivide_iff [simp]:
  fixes f :: "_ ==> 'b :: real_normed_field"
  assumes "c 0"
  shows "(λx. f x / of_real c) integrable_on s f integrable_on s"
  by (simp add: divide_inverse assms flip: of_real_inverse)

lemma has_integral_null [intro]: "content(cbox a b) = 0 ==> (f has_integral 0) (cbox a b)"
  unfolding has_integral_cbox
  using eventually_division_filter_tagged_division[of "cbox a b"]
  by (subst tendsto_cong[where g="λ_. 0"]) (auto elim: eventually_mono intro: sum_content_null)

lemma has_integral_null_real [intro]: "content {a..b::real} = 0 ==> (f has_integral 0) {a..b}"
  by (metis box_real(2) has_integral_null)

lemma has_integral_null_eq[simp]: "content (cbox a b) = 0 ==> (f has_integral i) (cbox a b) i = 0"
  by (auto simp: has_integral_null dest!: integral_unique)

lemma integral_null [simp]: "content (cbox a b) = 0 ==> integral (cbox a b) f = 0"
  by (metis has_integral_null integral_unique)

lemma integrable_on_null [intro]: "content (cbox a b) = 0 ==> f integrable_on (cbox a b)"
  by (simp add: has_integral_integrable)

lemma has_integral_empty[intro]: "(f has_integral 0) {}"
  by (meson ex_in_conv has_integral_is_0)

lemma has_integral_empty_eq[simp]: "(f has_integral i) {} i = 0"
  by (auto simp: has_integral_empty has_integral_unique)

lemma integrable_on_empty[intro]: "f integrable_on {}"
  unfolding integrable_on_def by auto

lemma integral_empty[simp]: "integral {} f = 0"
  by blast

lemma has_integral_refl[intro]:
  fixes a :: "'a::euclidean_space"
  shows "(f has_integral 0) (cbox a a)"
    and "(f has_integral 0) {a}"
proof -
  show "(f has_integral 0) (cbox a a)"
     by (rule has_integral_null) simp
  then show "(f has_integral 0) {a}"
    by simp
qed

lemma integrable_on_refl[intro]: "f integrable_on cbox a a"
  unfolding integrable_on_def by auto

lemma integral_refl [simp]: "integral (cbox a a) f = 0"
  by auto

lemma integral_singleton [simp]: "integral {a} f = 0"
  by auto

lemma integral_blinfun_apply:
  assumes "f integrable_on s"
  shows "integral s (λx. blinfun_apply h (f x)) = blinfun_apply h (integral s f)"
  using integral_linear[OF assms blinfun.bounded_linear_right]
  by (metis (no_types, lifting) ext comp_def)

lemma blinfun_apply_integral:
  assumes "f integrable_on s"
  shows "blinfun_apply (integral s f) x = integral s (λy. blinfun_apply (f y) x)"
  by (metis (no_types, lifting) ext assms blinfun.prod_left.rep_eq
      integral_blinfun_apply)

lemma has_integral_componentwise_iff:
  fixes f :: "'a :: euclidean_space ==> 'b :: euclidean_space"
  shows "(f has_integral y) A (bBasis. ((λx. f x b) has_integral (y b)) A)"
proof (intro iffI strip)
  fix b :: 'b assume "(f has_integral y) A"
  from has_integral_linear[OF this(1) bounded_linear_inner_left, of b]
    show "((λx. f x b) has_integral (y b)) A" by (simp add: o_def)
next
  assume "(bBasis. ((λx. f x b) has_integral (y b)) A)"
  hence "bBasis. (((λx. x *🪙R b) (λx. f x b)) has_integral ((y b) *🪙R b)) A"
    using bounded_linear_scaleR_left has_integral_linear by blast
  hence "((λx. bBasis. (f x b) *🪙R b) has_integral (bBasis. (y b) *🪙R b)) A"
    by (intro has_integral_sum) (simp_all add: o_def)
  thus "(f has_integral y) A" by (simp add: euclidean_representation)
qed

lemma has_integral_componentwise:
  fixes f :: "'a :: euclidean_space ==> 'b :: euclidean_space"
  shows "(b. b Basis ==> ((λx. f x b) has_integral (y b)) A) ==> (f has_integral y) A"
  by (subst has_integral_componentwise_iff) blast

lemma integrable_componentwise_iff:
  fixes f :: "'a :: euclidean_space ==> 'b :: euclidean_space"
  shows "f integrable_on A (bBasis. (λx. f x b) integrable_on A)"
proof
  assume "f integrable_on A"
  then obtain y where "bBasis. ((λx. f x b) has_integral (y b)) A"
    using has_integral_componentwise_iff by blast
  thus "(bBasis. (λx. f x b) integrable_on A)" by (auto simp: integrable_on_def)
next
  assume "(bBasis. (λx. f x b) integrable_on A)"
  then obtain y where "bBasis. ((λx. f x b) has_integral y b) A"
    unfolding integrable_on_def by (subst (asm) bchoice_iff) blast
  hence "bBasis. (((λx. x *🪙R b) (λx. f x b)) has_integral (y b *🪙R b)) A"
    by (intro ballI has_integral_linear) (simp_all add: bounded_linear_scaleR_left)
  hence "((λx. bBasis. (f x b) *🪙R b) has_integral (bBasis. y b *🪙R b)) A"
    by (intro has_integral_sum) (simp_all add: o_def)
  thus "f integrable_on A" by (auto simp: integrable_on_def o_def euclidean_representation)
qed

lemma integrable_componentwise:
  fixes f :: "'a :: euclidean_space ==> 'b :: euclidean_space"
  shows "(b. b Basis ==> (λx. f x b) integrable_on A) ==> f integrable_on A"
  by (subst integrable_componentwise_iff) blast

lemma integral_componentwise:
  fixes f :: "'a :: euclidean_space ==> 'b :: euclidean_space"
  assumes "f integrable_on A"
  shows "integral A f = (bBasis. integral A (λx. (f x b) *🪙R b))"
proof -
  from assms have integrable: "bBasis. (λx. x *🪙R b) (λx. (f x b)) integrable_on A"
    using bounded_linear_scaleR_left integrable_componentwise_iff integrable_linear
    by blast
  have "integral A f = integral A (λx. bBasis. (f x b) *🪙R b)"
    by (simp add: euclidean_representation)
  also from integrable have " = (aBasis. integral A (λx. (f x a) *🪙R a))"
    by (subst integral_sum) (simp_all add: o_def)
  finally show ?thesis .
qed

lemma integrable_component:
  "f integrable_on A ==> (λx. f x (y :: 'b :: euclidean_space)) integrable_on A"
  by (drule integrable_linear[OF _ bounded_linear_inner_left[of y]]) (simp add: o_def)

lemma
  assumes "(f has_integral I) A "
  shows has_integral_Re: "((λx. Re (f x)) has_integral (Re I)) A"
  and   has_integral_Im: "((λx. Im (f x)) has_integral (Im I)) A"
proof -
  have "((λx. Re (f x)) has_integral (Re I)) A ((λx. Im (f x)) has_integral (Im I)) A"
    using assms by (subst (asm) has_integral_componentwise_iff) (auto simp: Basis_complex_def)
  thus "((λx. Re (f x)) has_integral (Re I)) A" "((λx. Im (f x)) has_integral (Im I)) A"
    by blast+
qed


subsection Cauchy-type criterion for integrability

proposition integrable_Cauchy:
  fixes f :: "'n::euclidean_space ==> 'a::{real_normed_vector,complete_space}"
  shows "f integrable_on cbox a b
        (e>0. γ. gauge γ
          (D1 D2. D1 tagged_division_of (cbox a b) γ fine D1
            D2 tagged_division_of (cbox a b) γ fine D2
            norm (((x,K)D1. content K *🪙R f x) - ((x,K)D2. content K *🪙R f x)) < e))"
  (is "?l = (e>0. γ. ?P e γ)")
proof (intro iffI allI impI)
  assume ?l
  then obtain y
    where y: "e. e > 0 ==>
        γ. gauge γ
            (D. D tagged_division_of cbox a b γ fine D
                 norm (((x,K) D. content K *🪙R f x) - y) < e)"
    by (auto simp: integrable_on_def has_integral)
  show "γ. ?P e γ" if "e > 0" for e
  proof -
    have "e/2 > 0" using that by auto
    with y obtain γ where "gauge γ"
      and "D. D tagged_division_of cbox a b γ fine D ==>
                  norm (((x,K)D. content K *🪙R f x) - y) < e/2"
      by meson
    then show ?thesis
      by (metis norm_triangle_half_l)
    qed
next
  assume "e>0. γ. ?P e γ"
  then have "n::nat. γ. ?P (1 / (n + 1)) γ"
    by auto
  then obtain γ :: "nat ==> 'n ==> 'n set" where γ:
    "m. gauge (γ m)"
    "m D1 D2. [D1 tagged_division_of cbox a b;
              γ m fine D1; D2 tagged_division_of cbox a b; γ m fine D2]
              ==> norm (((x,K) D1. content K *🪙R f x) - ((x,K) D2. content K *🪙R f x))
                  < 1 / (m + 1)"
    by metis
  have "gauge (λx. {γ i x |i. i {0..n}})" for n
    using γ by (intro gauge_Inter) auto
  then have "n. p. p tagged_division_of (cbox a b) (λx. {γ i x |i. i {0..n}}) fine p"
    by (meson fine_division_exists)
  then obtain p where p: "z. p z tagged_division_of cbox a b"
                         "z. (λx. {γ i x |i. i {0..z}}) fine p z"
    by meson
  have dp: "i n. in ==> γ i fine p n"
    using p unfolding fine_Inter
    using atLeastAtMost_iff by blast
  have "Cauchy (λn. sum (λ(x,K). content K *🪙R (f x)) (p n))"
  proof (rule CauchyI)
    fix e::real
    assume "0 < e"
    then obtain N where "N 0" and N: "inverse (real N) < e"
      using real_arch_inverse[of e] by blast
    show "M. mM. nM. norm (((x,K) p m. content K *🪙R f x) - ((x,K) p n. content K *🪙R f x)) < e"
    proof (intro exI allI impI)
      fix m n
      assume mn: "N m" "N n"
      have "norm (((x,K) p m. content K *🪙R f x)
                - ((x,K) p n. content K *🪙R f x)) < 1 / (real N + 1)"
        by (simp add: p(1) dp mn γ)
      also have " < e"
        using  N N 0 0 🚫 by (auto simp: field_simps)
      finally show "norm (((x,K) p m. content K *🪙R f x) - ((x,K) p n. content K *🪙R f x)) < e" .
    qed
  qed
  then obtain y where y: "no. nno. norm (((x,K) p n. content K *🪙R f x) - y) < r" if "r > 0" for r
    by (auto simp: convergent_eq_Cauchy[symmetric] dest: LIMSEQ_D)
  show ?l
    unfolding integrable_on_def has_integral
  proof (rule_tac x=y in exI, clarify)
    fix e :: real
    assume "e>0"
    then have e2: "e/2 > 0" by auto
    then obtain N1::nat where N1: "N1 0" "inverse (real N1) < e/2"
      using real_arch_inverse by blast
    obtain N2::nat where N2: "n. n N2 ==> norm (((x,K) p n. content K *🪙R f x) - y) < e/2"
      using y[OF e2] by metis
    show "γ. gauge γ
              (D. D tagged_division_of (cbox a b) γ fine D
                norm (((x,K) D. content K *🪙R f x) - y) < e)"
    proof (intro exI conjI allI impI)
      show "gauge (γ (N1+N2))"
        using γ by auto
      show "norm (((x,K) q. content K *🪙R f x) - y) < e"
           if "q tagged_division_of cbox a b γ (N1+N2) fine q" for q
      proof (rule norm_triangle_half_r)
        have "norm (((x,K) p (N1+N2). content K *🪙R f x)
                  - ((x,K) q. content K *🪙R f x))
               < 1 / (real (N1+N2) + 1)"
          by (rule γ; simp add: dp p that)
        also have " < e/2"
          using N1 0 🚫 by (auto simp: field_simps intro: less_le_trans)
        finally show "norm (((x,K) p (N1+N2). content K *🪙R f x) - ((x,K) q. content K *🪙R f x)) < e/2" .
        show "norm (((x,K) p (N1+N2). content K *🪙R f x) - y) < e/2"
          using N2 le_add_same_cancel2 by blast
      qed
    qed
  qed
qed


subsection Additivity of integral on abutting intervals

lemma tagged_division_split_left_inj_content:
  assumes D"D tagged_division_of S"
    and "(x1, K1) D" "(x2, K2) D" "K1 K2" "K1 {x. xk c} = K2 {x. xk c}" "k Basis"
  shows "content (K1 {x. xk c}) = 0"
proof -
  from tagged_division_ofD(4)[OF D (x1, K1) Dobtain a b where K1: "K1 = cbox a b"
    by auto
  then have "interior (K1 {x. x k c}) = {}"
    by (metis tagged_division_split_left_inj assms)
  then show ?thesis
    unfolding K1 interval_split[OF k Basisby (auto simp: content_eq_0_interior)
qed

lemma tagged_division_split_right_inj_content:
  assumes D"D tagged_division_of S"
    and "(x1, K1) D" "(x2, K2) D" "K1 K2" "K1 {x. xk c} = K2 {x. xk c}" "k Basis"
  shows "content (K1 {x. xk c}) = 0"
proof -
  from tagged_division_ofD(4)[OF D (x1, K1) Dobtain a b where K1: "K1 = cbox a b"
    by auto
  then have "interior (K1 {x. c x k}) = {}"
    by (metis tagged_division_split_right_inj assms)
  then show ?thesis
    unfolding K1 interval_split[OF k Basis]
    by (auto simp: content_eq_0_interior)
qed


proposition has_integral_split:
  fixes f :: "'a::euclidean_space ==> 'b::real_normed_vector"
  assumes fi: "(f has_integral i) (cbox a b {x. xk c})"
      and fj: "(f has_integral j) (cbox a b {x. xk c})"
      and k: "k Basis"
shows "(f has_integral (i + j)) (cbox a b)"
  unfolding has_integral
proof clarify
  fix e::real
  assume "0 < e"
  then have e: "e/2 > 0"
    by auto
    obtain γ1 where γ1: "gauge γ1"
      and γ1norm:
        "D. [D tagged_division_of cbox a b {x. x k c}; γ1 fine D]
             ==> norm (((x,K) D. content K *🪙R f x) - i) < e/2"
      by (metis (no_types, lifting) ext e fi has_integral interval_split(1) k)
    obtain γ2 where γ2: "gauge γ2"
      and γ2norm:
        "D. [D tagged_division_of cbox a b {x. c x k}; γ2 fine D]
             ==> norm (((x, k) D. content k *🪙R f x) - j) < e/2"
       apply (rule has_integralD[OF fj[unfolded interval_split[OF k]] e])
       apply (simp add: interval_split[symmetric] k)
       done
  let ?γ = "λx. if xk = c then (γ1 x γ2 x) else ball x xk - c γ1 x γ2 x"
  have "gauge ?γ"
    using γ1 γ2 unfolding gauge_def by auto
  then show "γ. gauge γ
                 (D. D tagged_division_of cbox a b γ fine D
                      norm (((x, k)D. content k *🪙R f x) - (i + j)) < e)"
  proof (rule_tac x="?γ" in exI, safe)
    fix p
    assume p: "p tagged_division_of (cbox a b)" and "?γ fine p"
    have ab_eqp: "cbox a b = {K. x. (x, K) p}"
      using p by blast
    have xk_le_c: "xk c" if as: "(x,K) p" and K: "K {x. xk c} {}" for x K
    proof (rule ccontr)
      assume **: "¬ x k c"
      then have "K ball x x k - c"
        using ?γ fine p as by (fastforce simp: not_le algebra_simps)
      with K obtain y where y: "y ball x x k - c" "yk c"
        by blast
      then have "x k - y k < x k - c"
        using Basis_le_norm[OF k, of "x - y"]
        by (auto simp: dist_norm inner_diff_left intro: le_less_trans)
      with y show False
        using ** by (auto simp: field_simps)
    qed
    have xk_ge_c: "xk c" if as: "(x,K) p" and K: "K {x. xk c} {}" for x K
    proof (rule ccontr)
      assume **: "¬ x k c"
      then have "K ball x x k - c"
        using ?γ fine p as by (fastforce simp: not_le algebra_simps)
      with K obtain y where y: "y ball x x k - c" "yk c"
        by blast
      then have "x k - y k < x k - c"
        using Basis_le_norm[OF k, of "x - y"]
        by (auto simp: dist_norm inner_diff_left intro: le_less_trans)
      with y show False
        using ** by (auto simp: field_simps)
    qed
    have fin_finite: "finite {(x,f K) | x K. (x,K) s P x K}"
      if "finite s" for s and f :: "'a set ==> 'a set" and P :: "'a ==> 'a set ==> bool"
    proof -
      from that have "finite ((λ(x,K). (x, f K)) ` s)"
        by auto
      then show ?thesis
        by (rule rev_finite_subset) auto
    qed
    { fix G :: "'a set ==> 'a set"
      fix i :: "'a × 'a set"
      assume "i (λ(x, k). (x, G k)) ` p - {(x, G k) |x k. (x, k) p G k {}}"
      then obtain x K where xk: "i = (x, G K)"  "(x,K) p"
                                "(x, G K) {(x, G K) |x K. (x,K) p G K {}}"
        by auto
      have "content (G K) = 0"
        using xk using content_empty by auto
      then have "(λ(x,K). content K *🪙R f x) i = 0"
        unfolding xk split_conv by auto
    } note [simp] = this
    have "finite p"
      using p by blast
    let ?M1 = "{(x, K {x. xk c}) |x K. (x,K) p K {x. xk c} {}}"
    have γ1_fine: "γ1 fine ?M1"
      using ?γ fine p by (fastforce simp: fine_def split: if_split_asm)
    have "norm (((x, k)?M1. content k *🪙R f x) - i) < e/2"
    proof (rule γ1norm [OF tagged_division_ofI γ1_fine])
      show "finite ?M1"
        by (rule fin_finite) (use p in blast)
      show "{k. x. (x, k) ?M1} = cbox a b {x. xk c}"
        by (auto simp: ab_eqp)

      fix x L
      assume xL: "(x, L) ?M1"
      then obtain x' L' where xL': "x = x'" "L = L' {x. x k c}"
                                   "(x', L') p" "L' {x. x k c} {}"
        by blast
      then obtain a' b' where ab': "L' = cbox a' b'"
        using p by blast
      show "x L" "L cbox a b {x. x k c}"
        using p xk_le_c xL' by auto
      show "a b. L = cbox a b"
        using ab' interval_split(1) k xL'(2) by blast

      fix y R
      assume yR: "(y, R) ?M1"
      then obtain y' R' where yR': "y = y'" "R = R' {x. x k c}"
                                   "(y', R') p" "R' {x. x k c} {}"
        by blast
      assume as: "(x, L) (y, R)"
      show "interior L interior R = {}"
      proof (cases "L' = R' x' = y'")
        case False
        have "interior R' = {}"
          by (metis (no_types) False Pair_inject inf.idem tagged_division_ofD(5) [OF p] xL'(3) yR'(3))
        then show ?thesis
          using yR' by simp
      next
        case True
        then have "L' R'"
          using as unfolding xL' yR' by auto
        have "interior L' interior R' = {}"
          by (metis (no_types) Pair_inject L' R' p tagged_division_ofD(5) xL'(3) yR'(3))
        then show ?thesis
          using xL'(2) yR'(2) by auto
      qed
    qed
    moreover
    let ?M2 = "{(x,K {x. xk c}) |x K. (x,K) p K {x. xk c} {}}"
    have γ2_fine: "γ2 fine ?M2"
      using ?γ fine p by (fastforce simp: fine_def split: if_split_asm)
    have "norm (((x, k)?M2. content k *🪙R f x) - j) < e/2"
    proof (rule γ2norm [OF tagged_division_ofI γ2_fine])
      show "finite ?M2"
        by (rule fin_finite) (use p in blast)
      show "{k. x. (x, k) ?M2} = cbox a b {x. xk c}"
        by (auto simp: ab_eqp)

      fix x L
      assume xL: "(x, L) ?M2"
      then obtain x' L' where xL': "x = x'" "L = L' {x. x k c}"
                                   "(x', L') p" "L' {x. x k c} {}"
        by blast
      then obtain a' b' where ab': "L' = cbox a' b'"
        using p by blast
      show "x L" "L cbox a b {x. x k c}"
        using p xk_ge_c xL' by auto
      show "a b. L = cbox a b"
        using p xL' ab' by (auto simp: interval_split[OF k,where c=c])

      fix y R
      assume yR: "(y, R) ?M2"
      then obtain y' R' where yR': "y = y'" "R = R' {x. x k c}"
                                   "(y', R') p" "R' {x. x k c} {}"
        by blast
      assume as: "(x, L) (y, R)"
      show "interior L interior R = {}"
      proof (cases "L' = R' x' = y'")
        case False
        have "interior R' = {}"
          by (metis (no_types) False Pair_inject inf.idem tagged_division_ofD(5) [OF p] xL'(3) yR'(3))
        then show ?thesis
          using yR' by simp
      next
        case True
        then have "L' R'"
          using as unfolding xL' yR' by auto
        have "interior L' interior R' = {}"
          by (metis (no_types) Pair_inject L' R' p tagged_division_ofD(5) xL'(3) yR'(3))
        then show ?thesis
          using xL'(2) yR'(2) by auto
      qed
    qed
    ultimately
    have "norm ((((x,K) ?M1. content K *🪙R f x) - i) + (((x,K) ?M2. content K *🪙R f x) - j)) < e/2 + e/2"
      using norm_add_less by blast
    moreover have "(((x,K) ?M1. content K *🪙R f x) - i) +
                   (((x,K) ?M2. content K *🪙R f x) - j) =
                   ((x, ka)p. content ka *🪙R f x) - (i + j)"
    proof -
      have eq0: "x y. x = (0::real) ==> x *🪙R (y::'b) = 0"
         by auto
      have cont_eq: "g. (λ(x,l). content l *🪙R f x) (λ(x,l). (x,g l)) = (λ(x,l). content (g l) *🪙R f x)"
        by auto
      have *: "G :: 'a set ==> 'a set.
                  ((x,K){(x, G K) |x K. (x,K) p G K {}}. content K *🪙R f x) =
                  ((x,K)(λ(x,K). (x, G K)) ` p. content K *🪙R f x)"
        by (rule sum.mono_neutral_left) (auto simp: finite p)
      have "(((x, k)?M1. content k *🪙R f x) - i) + (((x, k)?M2. content k *🪙R f x) - j) =
        ((x, k)?M1. content k *🪙R f x) + ((x, k)?M2. content k *🪙R f x) - (i + j)"
        by auto
      moreover have " = ((x,K) p. content (K {x. x k c}) *🪙R f x) +
        ((x,K) p. content (K {x. c x k}) *🪙R f x) - (i + j)"
        unfolding *
        apply (subst (1 2) sum.reindex_nontrivial)
           apply (auto intro!: k p eq0 tagged_division_split_left_inj_content tagged_division_split_right_inj_content
                       simp: cont_eq finite p)
        done
      moreover have "x. x p ==> (λ(a,B). content (B {a. a k c}) *🪙R f a) x +
                                (λ(a,B). content (B {a. c a k}) *🪙R f a) x =
                                (λ(a,B). content B *🪙R f a) x"
      proof clarify
        fix a B
        assume "(a, B) p"
        with p obtain u v where uv: "B = cbox u v" by blast
        then show "content (B {x. x k c}) *🪙R f a + content (B {x. c x k}) *??R f a = content B *🪙R f a"
          by (auto simp: scaleR_left_distrib uv content_split[OF k,of u v c])
      qed
      ultimately show ?thesis
        by (auto simp: sum.distrib[symmetric])
      qed
    ultimately show "norm (((x, k)p. content k *🪙R f x) - (i + j)) < e"
      by auto
  qed
qed


subsection A sort of converse, integrability on subintervals

lemma has_integral_separate_sides:
  fixes f :: "'a::euclidean_space ==> 'b::real_normed_vector"
  assumes f: "(f has_integral i) (cbox a b)"
    and "e > 0"
    and k: "k Basis"
  obtains d where "gauge d"
    "p1 p2. p1 tagged_division_of (cbox a b {x. xk c}) d fine p1
        p2 tagged_division_of (cbox a b {x. xk c}) d fine p2
        norm ((sum (λ(x,k). content k *🪙R f x) p1 + sum (λ(x,k). content k *🪙R f x) p2) - i) < e"
proof -
  obtain γ where d: "gauge γ"
      "p. [p tagged_division_of cbox a b; γ fine p]
            ==> norm (((x, k)p. content k *🪙R f x) - i) < e"
    using has_integralD[OF f e > 0by metis
  { fix p1 p2
    assume tdiv1: "p1 tagged_division_of (cbox a b) {x. x k c}" and "γ fine p1"
    note p1=tagged_division_ofD[OF this(1)] 
    assume tdiv2: "p2 tagged_division_of (cbox a b) {x. c x k}" and "γ fine p2"
    note p2=tagged_division_ofD[OF this(1)] 
    note tagged_division_Un_interval[OF tdiv1 tdiv2] 
    note p12 = tagged_division_ofD[OF this] this
    { fix a b
      assume ab: "(a, b) p1 p2"
      have "(a, b) p1"
        using ab by auto
      obtain u v where uv: "b = cbox u v"
        using (a, b) p1 p1(4) by moura
      have "b {x. xk = c}"
        using ab p1(3)[of a b] p2(3)[of a b] by fastforce
      moreover
      have "interior {x::'a. x k = c} = {}"
      proof (rule ccontr)
        assume "¬ ?thesis"
        then obtain x where x: "x interior {x::'a. xk = c}"
          by auto
        then obtain ε where "0 < ε" and ε: "ball x ε {x. x k = c}"
          using mem_interior by metis
        have x: "xk = c"
          using x interior_subset by fastforce
        have "(iBasis. (x - (x + (ε/2 ) *🪙R k)) i) =
              (iBasis. (if i = k then ε/2 else 0))"
          using 0 🚫εby (intro sum.cong) (auto simp: inner_not_same_Basis)
        also have " < ε"
          by (subst sum.delta) (use 0 🚫ε in auto)
        finally have "x + (ε/2) *🪙R k ball x ε"
          unfolding mem_ball dist_norm by(rule le_less_trans[OF norm_le_l1])
        then have "x + (ε/2) *🪙R k {x. xk = c}"
          using ε by auto
        then show False
          using 0 🚫ε x k by (auto simp: inner_simps)
      qed
      ultimately have "content b = 0"
        unfolding uv content_eq_0_interior
        using interior_mono by blast
      then have "content b *🪙R f a = 0"
        by auto
    }
    then have "norm (((x, k)p1. content k *🪙R f x) + ((x, k)p2. content k *🪙R f x) - i) =
               norm (((x, k)p1 p2. content k *🪙R f x) - i)"
      by (subst sum.union_inter_neutral) (auto simp: p1 p2)
    also have " < e"
      using d(2) p12 by (simp add: fine_Un k γ fine p1 γ fine p2)
    finally have "norm (((x, k)p1. content k *🪙R f x) + ((x, k)p2. content k *🪙R f x) - i) < e" .
   }
  then show ?thesis
    using d(1) that by auto
qed

lemma integrable_split [intro]:
  fixes f :: "'a::euclidean_space ==> 'b::{real_normed_vector,complete_space}"
  assumes f: "f integrable_on cbox a b"
      and k: "k Basis"
    shows "f integrable_on (cbox a b {x. xk c})"   (is ?thesis1)
    and   "f integrable_on (cbox a b {x. xk c})"   (is ?thesis2)
proof -
  obtain y where y: "(f has_integral y) (cbox a b)"
    using f by blast
  define a' where "a' = (iBasis. (if i = k then max (ak) c else ai)*🪙R i)"
  define b' where "b' = (iBasis. (if i = k then min (bk) c else bi)*🪙R i)"
  have "d. gauge d
            (p1 p2. p1 tagged_division_of cbox a b {x. x k c} d fine p1
                     p2 tagged_division_of cbox a b {x. x k c} d fine p2
                     norm (((x,K) p1. content K *🪙R f x) - ((x,K) p2. content K *🪙R f x)) < e)"
    if "e > 0" for e
  proof -
    have "e/2 > 0" using that by auto
  with has_integral_separate_sides[OF y this k, of c]
  obtain d
    where "gauge d"
         and d: "p1 p2. [p1 tagged_division_of cbox a b {x. x k c}; d fine p1;
                          p2 tagged_division_of cbox a b {x. c x k}; d fine p2]
                  ==> norm (((x,K)p1. content K *🪙R f x) + ((x,K)p2. content K *🪙R f x) - y) < e/2"
    by metis
  show ?thesis
    proof (rule_tac x=d in exI, clarsimp simp add: gauge d)
      fix p1 p2
      assume as: "p1 tagged_division_of (cbox a b) {x. x k c}" "d fine p1"
                 "p2 tagged_division_of (cbox a b) {x. x k c}" "d fine p2"
      show "norm (((x, k)p1. content k *🪙R f x) - ((x, k)p2. content k *🪙R f x)) < e"
      proof (rule fine_division_exists[OF gauge d, of a' b])
        fix p
        assume "p tagged_division_of cbox a' b" "d fine p"
        then show ?thesis
          using as norm_triangle_half_l[OF d[of p1 p] d[of p2 p]]
          unfolding interval_split[OF k] b'_def[symmetric] a'_def[symmetric]
          by (auto simp: algebra_simps)
      qed
    qed
  qed
  with f show ?thesis1
    by (simp add: interval_split[OF k] integrable_Cauchy)
  have "d. gauge d
            (p1 p2. p1 tagged_division_of cbox a b {x. x k c} d fine p1
                     p2 tagged_division_of cbox a b {x. x k c} d fine p2
                     norm (((x,K) p1. content K *🪙R f x) - ((x,K) p2. content K *🪙R f x)) < e)"
    if "e > 0" for e
  proof -
    have "e/2 > 0" using that by auto
  with has_integral_separate_sides[OF y this k, of c]
  obtain d
    where "gauge d"
         and d: "p1 p2. [p1 tagged_division_of cbox a b {x. x k c}; d fine p1;
                          p2 tagged_division_of cbox a b {x. c x k}; d fine p2]
                  ==> norm (((x,K)p1. content K *🪙R f x) + ((x,K)p2. content K *🪙R f x) - y) < e/2"
    by metis
  show ?thesis
    proof (rule_tac x=d in exI, clarsimp simp add: gauge d)
      fix p1 p2
      assume as: "p1 tagged_division_of (cbox a b) {x. x k c}" "d fine p1"
                 "p2 tagged_division_of (cbox a b) {x. x k c}" "d fine p2"
      show "norm (((x, k)p1. content k *🪙R f x) - ((x, k)p2. content k *🪙R f x)) < e"
      proof (rule fine_division_exists[OF gauge d, of a b'])
        fix p
        assume "p tagged_division_of cbox a b'" "d fine p"
        then show ?thesis
          using as norm_triangle_half_l[OF d[of p p1] d[of p p2]]
          unfolding interval_split[OF k] b'_def[symmetric] a'_def[symmetric]
          by (auto simp: algebra_simps)
      qed
    qed
  qed
  with f show ?thesis2
    by (simp add: interval_split[OF k] integrable_Cauchy)
qed

lemma operative_integralI:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  shows "operative (lift_option (+)) (Some 0)
    (λi. if f integrable_on i then Some (integral i f) else None)"
proof -
  interpret comm_monoid "lift_option plus" "Some (0::'b)"
    by (simp add: add.comm_monoid_axioms comm_monoid_lift_option)
  show ?thesis
  proof
    fix a b c
    fix k :: 'a
    assume k: "k Basis"
    show "(if f integrable_on cbox a b then Some (integral (cbox a b) f) else None) =
          lift_option (+) (if f integrable_on cbox a b {x. x k c} then Some (integral (cbox a b {x. x k c}) f) else None)
          (if f integrable_on cbox a b {x. c x k} then Some (integral (cbox a b {x. c x k}) f) else None)"
    proof (cases "f integrable_on cbox a b")
      case True
      with k show ?thesis
        by (auto simp: integrable_split intro: integral_unique [OF has_integral_split[OF _ _ k]])
    next
    case False
      have "¬ (f integrable_on cbox a b {x. x k c}) ¬ ( f integrable_on cbox a b {x. c x k})"
      proof (rule ccontr)
        assume "¬ ?thesis"
        then have "f integrable_on cbox a b"
          unfolding integrable_on_def using has_integral_split k by blast
        then show False
          using False by auto
      qed
      then show ?thesis
        using False by auto
    qed
  qed (auto simp: content_eq_0_interior)
qed

subsection Bounds on the norm of Riemann sums and the integral itself

lemma dsum_bound:
  assumes p: "p division_of (cbox a b)"
    and "norm c e"
  shows "norm (lp. content l *🪙R c) e * content(cbox a b)"
  by (metis abs_of_nonneg assms measure_nonneg mult.commute mult_right_mono norm_scaleR
      scaleR_left.sum sum_content.division)

lemma rsum_bound:
  assumes p: "p tagged_division_of (cbox a b)"
      and "xcbox a b. norm (f x) e"
    shows "norm ((x, k)p. content k *🪙R f x) e * content (cbox a b)"
proof (cases "cbox a b = {}")
  case True show ?thesis
    using p unfolding True tagged_division_of_trivial by auto
next
  case False
  then have e: "e 0"
    by (meson ex_in_conv assms(2) norm_ge_zero order_trans)
  have sum_le: "sum (content snd) p content (cbox a b)"
    unfolding additive_content_tagged_division[OF p, symmetric] split_def
    by (auto intro: eq_refl)
  have con: "xk. xk p ==> 0 content (snd xk)"
    using tagged_division_ofD(4) [OF p] content_pos_le
    by force
  have "norm (sum (λ(x,k). content k *🪙R f x) p) (ip. norm (case i of (x, k) ==> content k *🪙R f x))"
    by (rule norm_sum)
  also have " e * content (cbox a b)"
  proof -
    have "xk. xk p ==> norm (f (fst xk)) e"
      using assms(2) p tag_in_interval by force
    moreover have "(ip. content (snd i) * e) e * content (cbox a b)"
      unfolding sum_distrib_right[symmetric]
      using con sum_le by (auto simp: mult.commute intro: mult_left_mono [OF _ e])
    ultimately show ?thesis
      unfolding split_def norm_scaleR
      by (metis (no_types, lifting) mult_left_mono[OF _ abs_ge_zero]   order_trans[OF sum_mono])
  qed
  finally show ?thesis .
qed

lemma rsum_diff_bound:
  assumes "p tagged_division_of (cbox a b)"
    and "xcbox a b. norm (f x - g x) e"
  shows "norm (sum (λ(x,k). content k *🪙R f x) p - sum (λ(x,k). content k *🪙R g x) p)
         e * content (cbox a b)"
  using order_trans[OF _ rsum_bound[OF assms]]
  by (simp add: split_def scaleR_diff_right sum_subtractf eq_refl)

lemma has_integral_bound:
  fixes f :: "'a::euclidean_space ==> 'b::real_normed_vector"
  assumes "0 B"
      and f: "(f has_integral i) (cbox a b)"
      and "x. xcbox a b ==> norm (f x) B"
    shows "norm i B * content (cbox a b)"
proof (rule ccontr)
  assume "¬ ?thesis"
  then have "norm i - B * content (cbox a b) > 0"
    by auto
  with f[unfolded has_integral]
  obtain γ where "gauge γ" and γ:
    "p. [p tagged_division_of cbox a b; γ fine p]
          ==> norm (((x, K)p. content K *🪙R f x) - i) < norm i - B * content (cbox a b)"
    by metis
  then obtain p where p: "p tagged_division_of cbox a b" and "γ fine p"
    using fine_division_exists by blast
  have "s B. norm s B ==> ¬ norm (s - i) < norm i - B"
    unfolding not_less
    by (metis diff_left_mono dist_commute dist_norm norm_triangle_ineq2 order_trans)
  then show False
    using γ [OF p γ fine p] rsum_bound[OF p] assms by metis
qed

corollary integrable_bound:
  fixes f :: "'a::euclidean_space ==> 'b::real_normed_vector"
  assumes "0 B"
    and "f integrable_on (cbox a b)"
    and "x. xcbox a b ==> norm (f x) B"
  shows "norm (integral (cbox a b) f) B * content (cbox a b)"
  by (metis integrable_integral has_integral_bound assms)


subsection Similar theorems about relationship among components

lemma rsum_component_le:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes p: "p tagged_division_of (cbox a b)"
      and "x. x cbox a b ==> (f x)i (g x)i"
    shows "((x, K)p. content K *🪙R f x) i ((x, K)p. content K *🪙R g x) i"
proof -
have "a b. (a, b) p ==> content b *🪙R f a i content b *🪙R g a i"
  by (metis assms(2) inner_commute inner_scaleR_right mult_left_mono
      measure_nonneg p tag_in_interval)
  then show ?thesis
    by (simp add: inner_sum_left split_def sum_mono)
qed

lemma has_integral_component_le:
  fixes f g :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes k: "k Basis"
  assumes "(f has_integral i) S" "(g has_integral j) S"
    and f_le_g: "x. x S ==> (f x)k (g x)k"
  shows "ik jk"
proof -
  have ik_le_jk: "ik jk"
    if f_i: "(f has_integral i) (cbox a b)" and g_j: "(g has_integral j) (cbox a b)"
    and le: "xcbox a b. (f x)k (g x)k" 
    for a b i and j :: 'b and f g :: "'a ==> 'b"
  proof (rule ccontr)
    assume "¬ ?thesis"
    then have *: "0 < (ik - jk) / 3"
      by auto
    obtain γ1 where "gauge γ1" 
      and γ1: "p. [p tagged_division_of cbox a b; γ1 fine p]
                ==> norm (((x, k)p. content k *🪙R f x) - i) < (i k - j k) / 3"
      by (metis "*" f_i has_integral)
    obtain γ2 where "gauge γ2" 
      and γ2: "p. [p tagged_division_of cbox a b; γ2 fine p]
                ==> norm (((x, k)p. content k *🪙R g x) - j) < (i k - j k) / 3"
      by (metis "*" g_j has_integral)
    obtain p where p: "p tagged_division_of cbox a b" and "γ1 fine p" "γ2 fine p"
      using fine_division_exists[OF gauge_Int[OF gauge γ1 gauge γ2]] 
      unfolding fine_Int
       by metis
    then have "(((x, k)p. content k *🪙R f x) - i) k < (i k - j k) / 3"
         "(((x, k)p. content k *🪙R g x) - j) k < (i k - j k) / 3"
      using le_less_trans[OF Basis_le_norm[OF k]] k γ1 γ2 by metis+ 
    then show False
      unfolding inner_simps
      using rsum_component_le[OF p] le
      by (fastforce simp: abs_real_def split: if_split_asm)
  qed
  show ?thesis
  proof (cases "a b. S = cbox a b")
    case True
    with ik_le_jk assms show ?thesis
      by auto
  next
    case False
    show ?thesis
    proof (rule ccontr)
      assume "¬ ik jk"
      then have ij: "(ik - jk) / 3 > 0"
        by auto
      obtain B1 where "0 < B1" 
           and B1: "a b. ball 0 B1 cbox a b ==>
                    z. ((λx. if x S then f x else 0) has_integral z) (cbox a b)
                        norm (z - i) < (i k - j k) / 3"
        using has_integral_altD[OF _ False ij] assms by blast
      obtain B2 where "0 < B2" 
           and B2: "a b. ball 0 B2 cbox a b ==>
                    z. ((λx. if x S then g x else 0) has_integral z) (cbox a b)
                        norm (z - j) < (i k - j k) / 3"
        using has_integral_altD[OF _ False ij] assms by blast
      have "bounded (ball 0 B1 ball (0::'a) B2)"
        unfolding bounded_Un by(rule conjI bounded_ball)+
      from bounded_subset_cbox_symmetric[OF this] 
      obtain a b::'a where ab: "ball 0 B1 cbox a b" "ball 0 B2 cbox a b"
        by (meson Un_subset_iff)
      then obtain w1 w2 where int_w1: "((λx. if x S then f x else 0) has_integral w1) (cbox a b)"
                        and norm_w1:  "norm (w1 - i) < (i k - j k) / 3"
                        and int_w2: "((λx. if x S then g x else 0) has_integral w2) (cbox a b)"
                        and norm_w2: "norm (w2 - j) < (i k - j k) / 3"
        using B1 B2 by blast
      have *: "w1 w2 j i::real .w1 - i < (i - j) / 3 ==> w2 - j < (i - j) / 3 ==> w1 w2 ==> False"
        by (simp add: abs_real_def split: if_split_asm)
      have "(w1 - i) k < (i k - j k) / 3"
           "(w2 - j) k < (i k - j k) / 3"
        using Basis_le_norm k le_less_trans norm_w1 norm_w2 by blast+
      moreover
      have "w1k w2k"
        using ik_le_jk int_w1 int_w2 f_le_g by auto
      ultimately show False
        unfolding inner_simps by(rule *)
    qed
  qed
qed

lemma integral_component_le:
  fixes g f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "k Basis"
    and "f integrable_on S" "g integrable_on S"
    and "x. x S ==> (f x)k (g x)k"
  shows "(integral S f)k (integral S g)k"
  using has_integral_component_le assms by blast

lemma has_integral_component_nonneg:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "k Basis"
    and "(f has_integral i) S"
    and "x. x S ==> 0 (f x)k"
  shows "0 ik"
  by (metis (no_types, lifting) assms euclidean_all_zero_iff has_integral_0 has_integral_component_le)

lemma integral_component_nonneg:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "k Basis"
    and  "x. x S ==> 0 (f x)k"
  shows "0 (integral S f)k"
  by (metis assms order.refl has_integral_component_nonneg has_integral_integral
      inner_zero_left not_integrable_integral)

lemma has_integral_component_neg:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "k Basis"
    and "(f has_integral i) S"
    and "x. x S ==> (f x)k 0"
  shows "ik 0"
  by (metis (no_types, lifting) assms has_integral_0 has_integral_component_le inner_zero_left)

lemma has_integral_component_lbound:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "(f has_integral i) (cbox a b)"
    and "xcbox a b. B f(x)k"
    and "k Basis"
  shows "B * content (cbox a b) ik"
  using has_integral_component_le[OF assms(3) has_integral_const assms(1),of "(iBasis. B *🪙R i)::'b"] assms(2-)
  by (auto simp: field_simps)

lemma has_integral_component_ubound:
  fixes f::"'a::euclidean_space => 'b::euclidean_space"
  assumes "(f has_integral i) (cbox a b)"
    and "xcbox a b. f xk B"
    and "k Basis"
  shows "ik B * content (cbox a b)"
  using has_integral_component_le[OF assms(3,1) has_integral_const, of "iBasis. B *🪙R i"] assms(2-)
  by (auto simp: field_simps)

lemma integral_component_lbound:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "f integrable_on cbox a b"
    and "xcbox a b. B f(x)k"
    and "k Basis"
  shows "B * content (cbox a b) (integral(cbox a b) f)k"
  using assms has_integral_component_lbound by blast

lemma integral_component_lbound_real:
  assumes "f integrable_on {a ::real..b}"
    and "x{a..b}. B f(x)k"
    and "k Basis"
  shows "B * content {a..b} (integral {a..b} f)k"
  using assms by (metis box_real(2) integral_component_lbound)

lemma integral_component_ubound:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "f integrable_on cbox a b"
    and "xcbox a b. f xk B"
    and "k Basis"
  shows "(integral (cbox a b) f)k B * content (cbox a b)"
  using assms has_integral_component_ubound by blast

lemma integral_component_ubound_real:
  fixes f :: "real ==> 'a::euclidean_space"
  assumes "f integrable_on {a..b}"
    and "x{a..b}. f xk B"
    and "k Basis"
  shows "(integral {a..b} f)k B * content {a..b}"
  using assms by (metis box_real(2) integral_component_ubound)

subsection Uniform limit of integrable functions is integrable

lemma real_arch_invD:
  "0 < (e::real) ==> (n::nat. n 0 0 < inverse (real n) inverse (real n) < e)"
  by (subst(asm) real_arch_inverse)


lemma integrable_uniform_limit:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes "e. e > 0 ==> g. (xcbox a b. norm (f x - g x) e) g integrable_on cbox a b"
  shows "f integrable_on cbox a b"
proof (cases "content (cbox a b) > 0")
  case False then show ?thesis
    using has_integral_null by (simp add: content_lt_nz integrable_on_def)
next
  case True
  have "1 / (real n + 1) > 0" for n
    by auto
  then have "g. (xcbox a b. norm (f x - g x) 1 / (real n + 1)) g integrable_on cbox a b" for n
    using assms by blast
  then obtain g where g_near_f: "n x. x cbox a b ==> norm (f x - g n x) 1 / (real n + 1)"
                  and int_g: "n. g n integrable_on cbox a b"
    by metis
  then obtain h where h: "n. (g n has_integral h n) (cbox a b)"
    unfolding integrable_on_def by metis
  have "Cauchy h"
    unfolding Cauchy_def
  proof clarify
    fix e :: real
    assume "e>0"
    then have "e/4 / content (cbox a b) > 0"
      using True by (auto simp: field_simps)
    then obtain M where "M 0" and M: "1 / (real M) < e/4 / content (cbox a b)"
      by (metis inverse_eq_divide real_arch_inverse)
    show "M. mM. nM. dist (h m) (h n) < e"
    proof (intro exI strip)
      fix m n
      assume m: "M m" and n: "M n"
      have "e/4>0" using e>0 by auto
      then obtain gm gn where "gauge gm" "gauge gn"
              and gm: "D. D tagged_division_of cbox a b gm fine D
                            ==> norm (((x,K) D. content K *🪙R g m x) - h m) < e/4"
              and gn: "D. D tagged_division_of cbox a b gn fine D ==>
                      norm (((x,K) D. content K *🪙R g n x) - h n) < e/4"
        using h[unfolded has_integral] by meson
      then obtain D where D"D tagged_division_of cbox a b" "(λx. gm x gn x) fine D"
        by (metis (full_types) fine_division_exists gauge_Int)
      have triangle3: "norm (i1 - i2) < e"
        if no: "norm(s2 - s1) e/2" "norm (s1 - i1) < e/4" "norm (s2 - i2) < e/4" for s1 s2 i1 and i2::'b
      proof -
        have "norm (i1 - i2) norm (i1 - s1) + norm (s1 - s2) + norm (s2 - i2)"
          using norm_triangle_ineq[of "i1 - s1" "s1 - i2"]
          using norm_triangle_ineq[of "s1 - s2" "s2 - i2"]
          by (auto simp: algebra_simps)
        also have " < e"
          using no by (auto simp: algebra_simps norm_minus_commute)
        finally show ?thesis .
      qed
      have finep: "gm fine D" "gn fine D"
        using fine_Int D  by auto
      have norm_le: "norm (g n x - g m x) 2 / real M" if x: "x cbox a b" for x
      proof -
        have "norm (f x - g n x) + norm (f x - g m x) 1 / (real n + 1) + 1 / (real m + 1)"          
          using g_near_f[OF x, of n] g_near_f[OF x, of m] by simp
        also have " 1 / (real M) + 1 / (real M)"
          using M 0 m n by (intro add_mono; force simp: field_split_simps)
        also have " = 2 / real M"
          by auto
        finally show "norm (g n x - g m x) 2 / real M"
          using norm_triangle_le[of "g n x - f x" "f x - g m x" "2 / real M"]
          by (auto simp: algebra_simps simp add: norm_minus_commute)
      qed
      have "norm (((x,K) D. content K *🪙R g n x) - ((x,K) D. content K *🪙R g m x)) 2 / real M * content (cbox a b)"
        by (blast intro: norm_le rsum_diff_bound[OF D(1), where e="2 / real M"])
      also have " e/2"
        using M True
        by (auto simp: field_simps)
      finally have le_e2: "norm (((x,K) D. content K *🪙R g n x) - ((x,K) D. content K *🪙R g m x)) e/2" .
      then show "dist (h m) (h n) < e"
        unfolding dist_norm using gm gn D finep by (auto intro!: triangle3)
    qed
  qed
  then obtain s where s: "h <---- s"
    using convergent_eq_Cauchy[symmetric] by blast
  show ?thesis
    unfolding integrable_on_def has_integral
  proof (rule_tac x=s in exI, clarify)
    fix e::real
    assume e: "0 < e"
    then have "e/3 > 0" by auto
    then obtain N1 where N1: "nN1. norm (h n - s) < e/3"
      using LIMSEQ_D [OF s] by metis
    from e True have "e/3 / content (cbox a b) > 0"
      by (auto simp: field_simps)
    then obtain N2 :: nat
         where "N2 0" and N2: "1 / (real N2) < e/3 / content (cbox a b)"
      by (metis inverse_eq_divide real_arch_inverse)
    obtain g' where "gauge g'"
            and g': "D. D tagged_division_of cbox a b g' fine D ==>
                    norm (((x,K) D. content K *🪙R g (N1 + N2) x) - h (N1 + N2)) < e/3"
      by (metis h has_integral e/3 > 0)
    have *: "norm (sf - s) < e" 
        if no: "norm (sf - sg) e/3" "norm(h - s) < e/3" "norm (sg - h) < e/3" for sf sg h
    proof -
      have "norm (sf - s) norm (sf - sg) + norm (sg - h) + norm (h - s)"
        using norm_triangle_ineq[of "sf - sg" "sg - s"]
        using norm_triangle_ineq[of "sg - h" " h - s"]
        by (auto simp: algebra_simps)
      also have " < e"
        using no by (auto simp: algebra_simps norm_minus_commute)
      finally show ?thesis .
    qed
    { fix D
      assume ptag: "D tagged_division_of (cbox a b)" and "g' fine D"
      then have norm_less: "norm (((x,K) D. content K *🪙R g (N1 + N2) x) - h (N1 + N2)) < e/3"
        using g' by blast
      have "content (cbox a b) < e/3 * (of_nat N2)"
        using N2 0 N2 using True by (auto simp: field_split_simps)
      moreover have "e/3 * of_nat N2 e/3 * (of_nat (N1 + N2) + 1)"
        using e>0 by auto
      ultimately have "content (cbox a b) < e/3 * (of_nat (N1 + N2) + 1)"
        by linarith
      then have le_e3: "1 / (real (N1 + N2) + 1) * content (cbox a b) e/3"
        unfolding inverse_eq_divide
        by (auto simp: field_simps)
      have ne3: "norm (h (N1 + N2) - s) < e/3"
        using N1 by auto
      have "norm (((x,K) D. content K *🪙R f x) - ((x,K) D. content K *🪙R g (N1 + N2) x))
             1 / (real (N1 + N2) + 1) * content (cbox a b)"
        by (blast intro: g_near_f rsum_diff_bound[OF ptag])
      then have "norm (((x,K) D. content K *🪙R f x) - s) < e"
        by (rule *[OF order_trans [OF _ le_e3] ne3 norm_less])
    }
    then show "d. gauge d
             (D. D tagged_division_of cbox a b d fine D norm (((x,K) D. content K *🪙R f x) - s) < e)"
      by (blast intro: g' gauge g')
  qed
qed

lemmas integrable_uniform_limit_real = integrable_uniform_limit [where 'a=real, simplified]


subsection Negligible sets

definition "negligible (s:: 'a::euclidean_space set)
  (a b. ((indicator s :: 'a==>real) has_integral 0) (cbox a b))"


subsubsection Negligibility of hyperplane

lemma content_doublesplit:
  fixes a :: "'a::euclidean_space"
  assumes "0 < e"
    and k: "k Basis"
  obtains d where "0 < d" and "content (cbox a b {x. xk - c d}) < e"
proof cases
  assume *: "a k c c b k (jBasis. a j b j)"
  define a' where "a' d = (jBasis. (if j = k then max (aj) (c - d) else aj) *🪙R j)" for d
  define b' where "b' d = (jBasis. (if j = k then min (bj) (c + d) else bj) *🪙R j)" for d

  have "((λd. jBasis. (b' d - a' d) j) ---> (jBasis. (b' 0 - a' 0) j)) (at_right 0)"
    by (auto simp: b'_def a'_def intro!: tendsto_min tendsto_max tendsto_eq_intros)
  also have "(jBasis. (b' 0 - a' 0) j) = 0"
    using k * unfolding b'_def a'_def
    by (auto simp: inner_diff intro!: prod_zero sum.cong)
  also have "((λd. jBasis. (b' d - a' d) j) ---> 0) (at_right 0) =
    ((λd. content (cbox a b {x. xk - c d})) ---> 0) (at_right 0)"
  proof (intro tendsto_cong eventually_at_rightI)
    fix d :: real assume d: "d {0<..<1}"
    have "cbox a b {x. xk - c d} = cbox (a' d) (b' d)" for d
      using * d k by (auto simp: cbox_def set_eq_iff Int_def ball_conj_distrib abs_diff_le_iff a'_def b'_def)
    moreover have "j Basis ==> a' d j b' d j" for j
      using * d k by (auto simp: a'_def b'_def)
    ultimately show "(jBasis. (b' d - a' d) j) = content (cbox a b {x. xk - c d})"
      by simp
  qed simp
  finally have "((λd. content (cbox a b {x. x k - c d})) ---> 0) (at_right 0)" .
  from order_tendstoD(2)[OF this 0🚫]
  obtain d' where "0 < d'" and d': "y. y > 0 ==> y < d' ==> content (cbox a b {x. x k - c y}) < e"
    by (subst (asm) eventually_at_right[of _ 1]) auto
  show ?thesis
    by (rule that[of "d'/2"], insert 0🚫 d'[of "d'/2"], auto)
next
  assume *: "¬ (a k c c b k (jBasis. a j b j))"
  then have "(jBasis. b j < a j) (c < a k b k < c)"
    by (auto simp: not_le)
  show thesis
  proof cases
    assume "jBasis. b j < a j"
    then have [simp]: "cbox a b = {}"
      using box_ne_empty(1)[of a b] by auto
    show ?thesis
      by (rule that[of 1]) (simp_all add: 0🚫)
  next
    assume "¬ (jBasis. b j < a j)"
    with * have "c < a k b k < c"
      by auto
    then show thesis
    proof
      assume c: "c < a k"
      moreover have "x cbox a b ==> c x k" for x
        using k c by (auto simp: cbox_def)
      ultimately have "cbox a b {x. x k - c (a k - c)/2} = {}"
        using k by (auto simp: cbox_def)
      with 0🚫 c that[of "(a k - c)/2"show ?thesis
        by auto
    next
      assume c: "b k < c"
      moreover have "x cbox a b ==> x k c" for x
        using k c by (auto simp: cbox_def)
      ultimately have "cbox a b {x. x k - c (c - b k)/2} = {}"
        using k by (auto simp: cbox_def)
      with 0🚫 c that[of "(c - b k)/2"show ?thesis
        by auto
    qed
  qed
qed


proposition negligible_standard_hyperplane[intro]:
  fixes k :: "'a::euclidean_space"
  assumes k: "k Basis"
  shows "negligible {x. xk = c}"
  unfolding negligible_def has_integral
proof clarsimp
  fix a b and e::real assume "e > 0"
  with k obtain d where "0 < d" and d: "content (cbox a b {x. x k - c d}) < e"
    by (metis content_doublesplit)
  let ?i = "indicator {x::'a. xk = c} :: 'a==>real"
  show "γ. gauge γ
           (D. D tagged_division_of cbox a b γ fine D
                 (x,K) D. content K * ?i x < e)"
  proof (intro exI, safe)
    show "gauge (λx. ball x d)"
      using 0 🚫 by blast
  next
    fix D
    assume p: "D tagged_division_of (cbox a b)" "(λx. ball x d) fine D"
    have "content L = content (L {x. x k - c d})" 
      if "(x, L) D" "?i x 0" for x L
    proof -
      have xk: "xk = c"
        using that by (simp add: indicator_def split: if_split_asm)
      have "L {x. x k - c d}"
      proof 
        fix y
        assume y: "y L"
        have "L ball x d"
          using p(2) that(1) by auto
        then have "norm (x - y) < d"
          by (simp add: dist_norm subset_iff y)
        then have "(x - y) k < d"
          using k norm_bound_Basis_lt by blast
        then show "y {x. x k - c d}"
          unfolding inner_simps xk by auto
      qed 
      then show "content L = content (L {x. x k - c d})"
        by (metis inf.orderE)
    qed
    then have *: "((x,K)D. content K * ?i x) = ((x,K)D. content (K {x. xk - c d}) *🪙R ?i x)"
      by (force simp: split_paired_all intro!: sum.cong [OF refl])
    note p'= tagged_division_ofD[OF p(1)] and p''=division_of_tagged_division[OF p(1)]
    have "((x,K)D. content (K {x. x k - c d}) * indicator {x. x k = c} x) < e"
    proof -
      have "((x,K)D. content (K {x. x k - c d}) * ?i x) ((x,K)D. content (K {x. x k - c d}))"
        by (force simp: indicator_def intro!: sum_mono)
      also have " < e"
      proof (subst sum.over_tagged_division_lemma[OF p(1)])
        fix u v::'a
        assume "box u v = {}"
        then have *: "content (cbox u v) = 0"
          unfolding content_eq_0_interior by simp
        have "cbox u v {x. x k - c d} cbox u v"
          by auto
        then have "content (cbox u v {x. x k - c d}) content (cbox u v)"
          unfolding interval_doublesplit[OF k] by (rule content_subset)
        then show "content (cbox u v {x. x k - c d}) = 0"
          unfolding * interval_doublesplit[OF k]
          by (blast intro: antisym)
      next
        have "(lsnd ` D. content (l {x. x k - c d})) =
          sum content ((λl. l {x. x k - c d})`{lsnd ` D. l {x. x k - c d} {}})"
        proof (subst (2) sum.reindex_nontrivial)
          fix x y assume "x {l snd ` D. l {x. x k - c d} {}}" "y {l snd ` D. l {x. x k - c d} {}}"
            "x y" and eq: "x {x. x k - c d} = y {x. x k - c d}"
          then obtain x' y' where "(x', x) D" "x {x. x k - c d} {}" "(y', y) D" "y {x. x k - c d} {}"
            by (auto)
          from p'(5)[OF (x', x) D (y', y) Dx y have "interior (x y) = {}"
            by auto
          moreover have "interior ((x {x. x k - c d}) (y {x. x k - c d})) interior (x y)"
            by (auto intro: interior_mono)
          ultimately have "interior (x {x. x k - c d}) = {}"
            by (auto simp: eq)
          then show "content (x {x. x k - c d}) = 0"
            using p'(4)[OF (x', x) Dby (auto simp: interval_doublesplit[OF k] content_eq_0_interior simp del: interior_Int)
        qed (insert p'(1), auto intro!: sum.mono_neutral_right)
        also have " norm (l(λl. l {x. x k - c d})`{lsnd ` D. l {x. x k - c d} {}}. content l *🪙R 1::real)"
          by simp
        also have " 1 * content (cbox a b {x. x k - c d})"
          using division_doublesplit[OF p'' k, unfolded interval_doublesplit[OF k]]
          unfolding interval_doublesplit[OF k] by (intro dsum_bound) auto
        also have " < e"
          using d by simp
        finally show "(Ksnd ` D. content (K {x. x k - c d})) < e" .
      qed
      finally show "((x, K)D. content (K {x. x k - c d}) * ?i x) < e" .
    qed
    then show "(x, K)D. content K * ?i x < e"
      unfolding *  by (simp add: sum_nonneg split: prod.split)
  qed
qed

corollary negligible_standard_hyperplane_cart:
  fixes k :: "'a::finite"
  shows "negligible {x. x$k = (0::real)}"
  by (simp add: cart_eq_inner_axis negligible_standard_hyperplane)


subsubsection Hence the main theorem about negligible sets


lemma has_integral_negligible_cbox:
  fixes f :: "'b::euclidean_space ==> 'a::real_normed_vector"
  assumes negs: "negligible S"
    and 0: "x. x S ==> f x = 0"
  shows "(f has_integral 0) (cbox a b)"
  unfolding has_integral
proof clarify
  fix e::real
  assume "e > 0"
  then have nn_gt0: "e/2 / ((real n+1) * (2 ^ n)) > 0" for n
    by simp
  then have "γ. gauge γ
                 (D. D tagged_division_of cbox a b γ fine D
                      (x,K) D. content K *🪙R indicator S x
                      < e/2 / ((real n + 1) * 2 ^ n))" for n
    using negs [unfolded negligible_def has_integral] by auto
  then obtain γ where 
    gd: "n. gauge (γ n)"
    and γ: "n D. [D tagged_division_of cbox a b; γ n fine D]
                  ==> (x,K) D. content K *🪙R indicator S x < e/2 / ((real n + 1) * 2 ^ n)"
    by metis
  show "γ. gauge γ
             (D. D tagged_division_of cbox a b γ fine D
                  norm (((x,K) D. content K *🪙R f x) - 0) < e)"
  proof (intro exI, safe)
    show "gauge (λx. γ (nat norm (f x)) x)"
      using gd by (auto simp: gauge_def)

    show "norm (((x,K) D. content K *🪙R f x) - 0) < e"
      if "D tagged_division_of (cbox a b)" "(λx. γ (nat norm (f x)) x) fine D" for D
    proof (cases "D = {}")
      case True with 0 🚫 show ?thesis by simp
    next
      case False
      obtain N where "Max ((λ(x, K). norm (f x)) ` D) real N"
        using real_arch_simple by blast
      then have N: "x. x (λ(x, K). norm (f x)) ` D ==> x real N"
        by (meson Max_ge that(1) dual_order.trans finite_imageI tagged_division_of_finite)
      have "i. q. q tagged_division_of (cbox a b) (γ i) fine q ((x,K) D. K i) x (x, K) q)"
        by (auto intro: tagged_division_finer[OF that(1) gd])
      from choice[OF this] 
      obtain q where q: "n. q n tagged_division_of cbox a b"
                        "n. γ n fine q n"
                        "n x K. [(x, K) D; K γ n x] ==> (x, K) q n"
        by fastforce
      have "finite D"
        using that(1) by blast
      then have sum_le_inc: "[finite T; x y. (x,y) T ==> (0::real) g(x,y);
                      y. yD ==> x. (x,y) T f(y) g(x,y)] ==> sum f D sum g T" for f g T
        by (rule sum_le_included[of D T g snd f]; force)
      have "norm ((x,K) D. content K *🪙R f x) ((x,K) D. norm (content K *🪙R f x))"
        unfolding split_def by (rule norm_sum)
      also have " ((i, j) Sigma {..N + 1} q.
                          (real i + 1) * (case j of (x, K) ==> content K *🪙R indicator S x))"
      proof (rule sum_le_inc, safe)
        show "finite (Sigma {..N+1} q)"
          by (meson finite_SigmaI finite_atMost tagged_division_of_finite q(1)) 
      next
        fix x K
        assume xk: "(x, K) D"
        define n where "n = nat norm (f x)"
        have *: "norm (f x) (λ(x, K). norm (f x)) ` D"
          using xk by auto
        have nfx: "real n norm (f x)" "norm (f x) real n + 1"
          unfolding n_def by auto
        then have "n {0..N + 1}"
          using N[OF *] by auto
        moreover have "(x, K) q n"
          using n_def q(3) that(2) xk by fastforce
        moreover
        have "norm (content K *🪙R f x) (real n + 1) * (content K * indicator S x)"
        proof (cases "x S")
          case False
          then show ?thesis by (simp add: 0)
        next
          case True
          have *: "content K 0"
            using tagged_division_ofD(4)[OF that(1) xk] by auto
          moreover have "content K * norm (f x) content K * (real n + 1)"
            by (simp add: mult_left_mono nfx(2))
          ultimately show ?thesis
            using nfx True by (auto simp: field_simps)
        qed
        ultimately show "y. (y, x, K) (Sigma {..N + 1} q) norm (content K *🪙R f x)
          (real y + 1) * (content K *🪙R indicator S x)"
          by force
      qed auto
      also have " = (iN + 1. jq i. (real i + 1) * (case j of (x, K) ==> content K *🪙R indicator S x))"
        using q(1) by (intro sum_Sigma_product [symmetric]) auto
      also have " (iN + 1. (real i + 1) * (x,K) q i. content K *🪙R indicator S x)"
        by (rule sum_mono) (simp flip: sum_distrib_left)
      also have " (iN + 1. e/2/2 ^ i)"
      proof (rule sum_mono)
        show "(real i + 1) * (x,K) q i. content K *🪙R indicator S x e/2/2 ^ i"
          if "i {..N + 1}" for i
          using γ[of "q i" i] q by (simp add: divide_simps mult.left_commute)
      qed
      also have " = e/2 * (iN + 1. (1/2) ^ i)"
        unfolding sum_distrib_left by (metis divide_inverse inverse_eq_divide power_one_over)
      also have " < e/2 * 2"
      proof (rule mult_strict_left_mono)
        have "sum (power (1/2)) {..N + 1} = sum (power (1/2::real)) {..
          using lessThan_Suc_atMost by auto
        also have " < 2"
          by (auto simp: geometric_sum)
        finally show "sum (power (1/2::real)) {..N + 1} < 2" .
      qed (use 0 🚫 in auto)
      finally show ?thesis by simp
    qed
  qed
qed


proposition has_integral_negligible:
  fixes f :: "'b::euclidean_space ==> 'a::real_normed_vector"
  assumes negs: "negligible S"
    and "x. x (T - S) ==> f x = 0"
  shows "(f has_integral 0) T"
proof (cases "a b. T = cbox a b")
  case True
  then have "((λx. if x T then f x else 0) has_integral 0) T"
    using assms by (auto intro!: has_integral_negligible_cbox)
  then show ?thesis
    by (rule has_integral_eq [rotated]) auto
next
  case False
  let ?f = "(λx. if x T then f x else 0)"
  have "((λx. if x T then f x else 0) has_integral 0) T"
    apply (auto simp: False has_integral_alt [of ?f])
    apply (rule_tac x=1 in exI, auto)
    apply (rule_tac x=0 in exI, simp add: has_integral_negligible_cbox [OF negs] assms)
    done
  then show ?thesis
    by (rule_tac f="?f" in has_integral_eq) auto
qed

lemma
  assumes "negligible S"
  shows integrable_negligible: "f integrable_on S" and integral_negligible: "integral S f = 0"
  using has_integral_negligible [OF assms]
  by (auto simp: has_integral_iff)

lemma has_integral_spike:
  fixes f :: "'b::euclidean_space ==> 'a::real_normed_vector"
  assumes "negligible S"
    and gf: "x. x T - S ==> g x = f x"
    and fint: "(f has_integral y) T"
  shows "(g has_integral y) T"
proof -
  have *: "(g has_integral y) (cbox a b)"
       if "(f has_integral y) (cbox a b)" "x cbox a b - S. g x = f x" for a b f and g:: "'b ==> 'a" and y
  proof -
    have "((λx. f x + (g x - f x)) has_integral (y + 0)) (cbox a b)"
      using that by (intro has_integral_add has_integral_negligible) (auto intro!: negligible S)
    then show ?thesis
      by auto
  qed
  have 🍋"a b z. [x. x T x S ==> g x = f x;

                     ((λx. if x T then f x else 0) has_integral z) (cbox a b)]
                    ==> ((λx. if x T then g x else 0) has_integral z) (cbox a b)"
      by (auto dest!: *[where f="λx. if xT then f x else 0" and g="λx. if x T then g x else 0"])
  show ?thesis
    using fint gf
    apply (subst has_integral_alt)
    apply (subst (asm) has_integral_alt)
    apply (auto split: if_split_asm)
     apply (blast dest: *)
    using 🍋 by meson
qed

lemma has_integral_spike_eq:
  assumes "negligible S" and "x. x T - S ==> g x = f x"
  shows "(f has_integral y) T (g has_integral y) T"
  by (metis assms has_integral_spike)

lemma integrable_spike:
  assumes "f integrable_on T" "negligible S" "x. x T - S ==> g x = f x"
    shows "g integrable_on T"
  using assms unfolding integrable_on_def by (blast intro: has_integral_spike)

lemma integral_spike:
  assumes "negligible S" and "x. x T - S ==> g x = f x"
  shows "integral T f = integral T g"
  using has_integral_spike_eq[OF assms]
    by (auto simp: integral_def integrable_on_def)


subsection Some other trivialities about negligible sets

lemma negligible_subset:
  assumes "negligible S" "T S"
  shows "negligible T"
  unfolding negligible_def
    by (metis (no_types) Diff_iff assms contra_subsetD has_integral_negligible indicator_simps(2))

lemma negligible_diff[intro?]:
  assumes "negligible S"
  shows "negligible (S - T)"
  using assms by (meson Diff_subset negligible_subset)

lemma negligible_Int:
  assumes "negligible S negligible T"
  shows "negligible (S T)"
  using assms negligible_subset by force

lemma negligible_Un:
  assumes "negligible S" and T: "negligible T"
  shows "negligible (S T)"
proof -
  have "(indicat_real (S T) has_integral 0) (cbox a b)"
    if S0: "(indicat_real S has_integral 0) (cbox a b)" 
      and  "(indicat_real T has_integral 0) (cbox a b)" for a b
  proof (subst has_integral_spike_eq[OF T])
    show "indicat_real S x = indicat_real (S T) x" if "x cbox a b - T" for x
      using that by (simp add: indicator_def)
    show "(indicat_real S has_integral 0) (cbox a b)"
      by (simp add: S0)
  qed
  with assms show ?thesis
    unfolding negligible_def by blast
qed

lemma negligible_Un_eq[simp]: "negligible (S T) negligible S negligible T"
  using negligible_Un negligible_subset by blast

lemma negligible_sing[intro]: "negligible {a::'a::euclidean_space}"
  using negligible_standard_hyperplane[OF SOME_Basis, of "a (SOME i. i Basis)"] negligible_subset by blast

lemma negligible_insert[simp]: "negligible (insert a S) negligible S"
  by (metis insert_is_Un negligible_Un_eq negligible_sing)

lemma negligible_empty[iff]: "negligible {}"
  using negligible_insert by blast

textUseful in this form for backchaining
lemma empty_imp_negligible: "S = {} ==> negligible S"
  by simp

lemma negligible_finite[intro]:
  assumes "finite S"
  shows "negligible S"
  using assms by (induct S) auto

lemma negligible_Union[intro]:
  assumes "finite T"
    and "T. T T ==> negligible T"
  shows "negligible(T)"
  using assms by induct auto

lemma negligible: "negligible S (T. (indicat_real S has_integral 0) T)"
  by (meson DiffD2 has_integral_negligible indicator_simps(2) negligible_def)

subsection Finite case of the spike theorem is quite commonly needed

lemma has_integral_spike_finite:
  assumes "finite S"
    and "x. x T - S ==> g x = f x"
    and "(f has_integral y) T"
  shows "(g has_integral y) T"
  using assms has_integral_spike negligible_finite by blast

lemma has_integral_spike_finite_eq:
  assumes "finite S"
    and "x. x T - S ==> g x = f x"
  shows "((f has_integral y) T (g has_integral y) T)"
  by (metis assms has_integral_spike_finite)

lemma integrable_spike_finite:
  assumes "finite S"
    and "x. x T - S ==> g x = f x"
    and "f integrable_on T"
  shows "g integrable_on T"
  using assms has_integral_spike_finite by blast

lemma integrable_spike_finite_eq:
  assumes "finite S"
    and "x. x T - S ==> f x = g x"
  shows "f integrable_on T g integrable_on T"
  by (metis assms integrable_spike_finite)

lemma has_integral_bound_spike_finite:
  fixes f :: "'a::euclidean_space ==> 'b::real_normed_vector"
  assumes "0 B" "finite S"
      and f: "(f has_integral i) (cbox a b)"
      and leB: "x. x cbox a b - S ==> norm (f x) B"
    shows "norm i B * content (cbox a b)"
proof -
  define g where "g (λx. if x S then 0 else f x)"
  then have "x. x cbox a b - S ==> norm (g x) B"
    using leB by simp
  moreover have "(g has_integral i) (cbox a b)"
    using has_integral_spike_finite [OF finite S _ f]
    by (simp add: g_def)
  ultimately show ?thesis
    by (simp add: 0 B g_def has_integral_bound)
qed

corollary has_integral_bound_real:
  fixes f :: "real ==> 'b::real_normed_vector"
  assumes "0 B" "finite S"
      and "(f has_integral i) {a..b}"
      and "x. x {a..b} - S ==> norm (f x) B"
    shows "norm i B * content {a..b}"
  by (metis assms box_real(2) has_integral_bound_spike_finite)


subsection In particular, the boundary of an interval is negligible

lemma negligible_frontier_interval: "negligible(cbox a b - box a b)"
proof -
  let ?A = "((λk. {x. xk = ak} {x::'a. xk = bk}) ` Basis)"
  have "negligible ?A"
    by (force simp: negligible_Union[OF finite_imageI])
  moreover have "cbox a b - box a b ?A"
    by (force simp: mem_box)
  ultimately show ?thesis
    by (rule negligible_subset)
qed

lemma has_integral_spike_interior:
  assumes f: "(f has_integral y) (cbox a b)" and gf: "x. x box a b ==> g x = f x"
  shows "(g has_integral y) (cbox a b)"
  by (meson Diff_iff gf has_integral_spike[OF negligible_frontier_interval _ f])
  
lemma has_integral_spike_interior_eq:
  assumes "x. x box a b ==> g x = f x"
  shows "(f has_integral y) (cbox a b) (g has_integral y) (cbox a b)"
  by (metis assms has_integral_spike_interior)

lemma integrable_spike_interior:
  assumes "x. x box a b ==> g x = f x"
    and "f integrable_on cbox a b"
  shows "g integrable_on cbox a b"
  using assms has_integral_spike_interior_eq by blast


subsection Integrability of continuous functions

lemma operative_approximableI:
  fixes f :: "'b::euclidean_space ==> 'a::banach"
  assumes "0 e"
  shows "operative conj True (λi. g. (xi. norm (f x - g (x::'b)) e) g integrable_on i)"
proof -
  interpret comm_monoid conj True
    by standard auto
  show ?thesis
  proof (standard, safe)
    fix a b :: 'b
    show "g. (xcbox a b. norm (f x - g x) e) g integrable_on cbox a b"
      if "box a b = {}" for a b
      using assms that
      by (metis content_eq_0_interior integrable_on_null interior_cbox norm_zero right_minus_eq)
    {
      fix c g and k :: 'b
      assume fg: "xcbox a b. norm (f x - g x) e" and g: "g integrable_on cbox a b"
      assume k: "k Basis"
      show "g. (xcbox a b {x. x k c}. norm (f x - g x) e) g integrable_on cbox a b {x. x k c}"
           "g. (xcbox a b {x. c x k}. norm (f x - g x) e) g integrable_on cbox a b {x. c x k}"
        using fg g k by auto
    }
    show "g. (xcbox a b. norm (f x - g x) e) g integrable_on cbox a b"
      if fg1: "xcbox a b {x. x k c}. norm (f x - g1 x) e" 
        and g1: "g1 integrable_on cbox a b {x. x k c}"
        and fg2: "xcbox a b {x. c x k}. norm (f x - g2 x) e" 
        and g2: "g2 integrable_on cbox a b {x. c x k}" 
        and k: "k Basis"
      for c k g1 g2
    proof -
      let ?g = "λx. if xk = c then f x else if xk c then g1 x else g2 x"
      show "g. (xcbox a b. norm (f x - g x) e) g integrable_on cbox a b"
      proof (intro exI conjI ballI)
        show "norm (f x - ?g x) e" if "x cbox a b" for x
          by (auto simp: that assms fg1 fg2)
        show "?g integrable_on cbox a b"
        proof -
          have "?g integrable_on cbox a b {x. x k c}" "?g integrable_on cbox a b {x. x k c}"
            by(rule integrable_spike[OF _ negligible_standard_hyperplane[of k c]], use k g1 g2 in auto)+
          with has_integral_split[OF _ _ k] show ?thesis
            unfolding integrable_on_def by blast
        qed
      qed
    qed
  qed
qed

lemma comm_monoid_set_F_and: "comm_monoid_set.F () True f s (finite s (xs. f x))"
proof -
  interpret bool: comm_monoid_set () True ..
  show ?thesis
    by (induction s rule: infinite_finite_induct) auto
qed

lemma approximable_on_division:
  fixes f :: "'b::euclidean_space ==> 'a::banach"
  assumes "0 e"
    and d: "d division_of (cbox a b)"
    and f: "id. g. (xi. norm (f x - g x) e) g integrable_on i"
  obtains g where "xcbox a b. norm (f x - g x) e" "g integrable_on cbox a b"
proof -
  interpret operative conj True "λi. g. (xi. norm (f x - g (x::'b)) e) g integrable_on i"
    using 0 e by (rule operative_approximableI)
  from f local.division [OF d] that show thesis
    by auto
qed

lemma integrable_continuous:
  fixes f :: "'b::euclidean_space ==> 'a::banach"
  assumes "continuous_on (cbox a b) f"
  shows "f integrable_on cbox a b"
proof (rule integrable_uniform_limit)
  fix e :: real
  assume e: "e > 0"
  then obtain d where "0 < d" and d: "x x'. [x cbox a b; x' cbox a b; dist x' x < d] ==> dist (f x') (f x) < e"
    using compact_uniformly_continuous[OF assms compact_cbox] unfolding uniformly_continuous_on_def by metis
  obtain p where ptag: "p tagged_division_of cbox a b" and finep: "(λx. ball x d) fine p"
    using fine_division_exists[OF gauge_ball[OF 0 🚫], of a b] .
  have *: "isnd ` p. g. (xi. norm (f x - g x) e) g integrable_on i"
  proof clarsimp 
    fix x l
    assume as: "(x, l) p"
    obtain a b where l: "l = cbox a b"
      using as ptag by blast
    then have x: "x cbox a b"
      using as ptag by auto
    show "g. (xl. norm (f x - g x) e) g integrable_on l"
    proof (intro exI conjI strip)
      show "(λy. f x) integrable_on l"
        unfolding integrable_on_def l by blast
    next
      fix y
      assume y: "y l"
      then have "y ball x d"
        using as finep by fastforce
      then show "norm (f y - f x) e"
        using d x y as l
        by (metis dist_commute dist_norm less_imp_le mem_ball ptag subsetCE tagged_division_ofD(3))
    qed
  qed
  from e have "e 0"
    by auto
  from approximable_on_division[OF this division_of_tagged_division[OF ptag] *]
  show "g. (xcbox a b. norm (f x - g x) e) g integrable_on cbox a b"
    by metis
qed

lemma integrable_continuous_interval:
  fixes f :: "'b::ordered_euclidean_space ==> 'a::banach"
  assumes "continuous_on {a..b} f"
  shows "f integrable_on {a..b}"
  by (metis assms integrable_continuous interval_cbox)

lemmas integrable_continuous_real = integrable_continuous_interval[where 'b=real]

lemma integrable_continuous_closed_segment:
  fixes f :: "real ==> 'a::banach"
  assumes "continuous_on (closed_segment a b) f"
  shows "f integrable_on (closed_segment a b)"
  by (metis assms closed_segment_eq_real_ivl integrable_continuous_interval)


subsection Specialization of additivity to one dimension


subsection A useful lemma allowing us to factor out the content size

lemma has_integral_factor_content:
  "(f has_integral i) (cbox a b)
    (e>0. d. gauge d (p. p tagged_division_of (cbox a b) d fine p
      norm (sum (λ(x,k). content k *🪙R f x) p - i) e * content (cbox a b)))"
proof (cases "content (cbox a b) = 0")
  case True
  have "e p. p tagged_division_of cbox a b ==> norm (((x, k)p. content k *🪙R f x)) e * content (cbox a b)"
    unfolding sum_content_null[OF True] True by force
  moreover have "i = 0" 
    if "e. e > 0 ==> d. gauge d
              (p. p tagged_division_of cbox a b
                   d fine p
                   norm (((x, k)p. content k *🪙R f x) - i) e * content (cbox a b))"
    using that [of 1]
    by (force simp: True sum_content_null[OF True] intro: fine_division_exists[of _ a b])
  ultimately show ?thesis
    unfolding has_integral_null_eq[OF True]
    by force
next
  case False
  then have F: "0 < content (cbox a b)"
    using zero_less_measure_iff by blast
  let ?P = "λe opp. d. gauge d
    (p. p tagged_division_of (cbox a b) d fine p opp (norm (((x, k)p. content k *🪙R f x) - i)) e)"
  show ?thesis
  proof (subst has_integral, safe)
    fix e :: real
    assume e: "e > 0"
    show "?P (e * content (cbox a b)) ()" if 🍋[rule_format]: "ε>0. ?P ε (<)"
      using 🍋 [of "e * content (cbox a b)"]
      by (meson F e less_imp_le mult_pos_pos)
    show "?P e (<)" if 🍋[rule_format]:  "ε>0. ?P (ε * content (cbox a b)) ()"
      using 🍋 [of "e/2 / content (cbox a b)"]
        using F e by (force simp: algebra_simps)
  qed
qed

lemma has_integral_factor_content_real:
  "(f has_integral i) {a..b::real}
    (e>0. d. gauge d (p. p tagged_division_of {a..b} d fine p
      norm (sum (λ(x,k). content k *🪙R f x) p - i) e * content {a..b} ))"
  unfolding box_real[symmetric]
  by (rule has_integral_factor_content)


subsection Fundamental theorem of calculus

lemma interval_bounds_real:
  fixes q b :: real
  assumes "a b"
  shows "Sup {a..b} = b"
    and "Inf {a..b} = a"
  using assms by auto

theorem fundamental_theorem_of_calculus:
  fixes f :: "real ==> 'a::banach"
  assumes "a b" 
      and vecd: "x. x {a..b} ==> (f has_vector_derivative f' x) (at x within {a..b})"
  shows "(f' has_integral (f b - f a)) {a..b}"
  unfolding has_integral_factor_content box_real[symmetric]
proof safe
  fix e :: real
  assume "e > 0"
  then have "x. d>0. x {a..b}
         (y{a..b}. norm (y-x) < d norm (f y - f x - (y-x) *🪙R f' x) e * norm (y-x))"
    using vecd[unfolded has_vector_derivative_def has_derivative_within_alt] by blast
  then obtain d where d: "x. 0 < d x"
                 "x y. [x {a..b}; y {a..b}; norm (y-x) < d x]
                        ==> norm (f y - f x - (y-x) *🪙R f' x) e * norm (y-x)"
    by metis  
  show "d. gauge d (p. p tagged_division_of (cbox a b) d fine p
    norm (((x, k)p. content k *🪙R f' x) - (f b - f a)) e * content (cbox a b))"
  proof (rule exI, safe)
    show "gauge (λx. ball x (d x))"
      using d(1) gauge_ball_dependent by blast
  next
    fix p
    assume ptag: "p tagged_division_of cbox a b" and finep: "(λx. ball x (d x)) fine p"
    have ba: "b - a = ((x,K)p. Sup K - Inf K)" "f b - f a = ((x,K)p. f(Sup K) - f(Inf K))"
      using additive_tagged_division_1[where f= "λx. x"] additive_tagged_division_1[where f= f]
            a b ptag by auto
    have "norm ((x, K) p. (content K *🪙R f' x) - (f (Sup K) - f (Inf K)))
           (np. e * (case n of (x, k) ==> Sup k - Inf k))"
    proof (rule sum_norm_le,safe)
      fix x K
      assume "(x, K) p"
      then have "x K" and kab: "K cbox a b"
        using ptag by blast+
      then obtain u v where k: "K = cbox u v" and "x K" and kab: "K cbox a b"
        using ptag (x, K) p by auto 
      have "u v"
        using x K unfolding k by auto
      have ball: "yK. y ball x (d x)"
        using finep (x, K) p by blast
      have "u K" "v K"
        by (simp_all add: u v k)
      have "norm ((v - u) *🪙R f' x - (f v - f u)) = norm (f u - f x - (u - x) *🪙R f' x - (f v - f x - (v - x) *🪙R f' x))"
        by (auto simp: algebra_simps)
      also have " norm (f u - f x - (u - x) *🪙R f' x) + norm (f v - f x - (v - x) *??R f' x)"
        by (rule norm_triangle_ineq4)
      finally have "norm ((v - u) *🪙R f' x - (f v - f u))
        norm (f u - f x - (u - x) *🪙R f' x) + norm (f v - f x - (v - x) *🪙R f' x)" .
      also have " e * norm (u - x) + e * norm (v - x)"
      proof (rule add_mono)
        show "norm (f u - f x - (u - x) *🪙R f' x) e * norm (u - x)"
        proof (rule d)
          show "norm (u - x) < d x"
            using u K ball by (auto simp: dist_real_def)
        qed (use x K u K kab in auto)
        show "norm (f v - f x - (v - x) *🪙R f' x) e * norm (v - x)"
        proof (rule d)
          show "norm (v - x) < d x"
            using v K ball by (auto simp: dist_real_def)
        qed (use x K v K kab in auto)
      qed
      also have " e * (Sup K - Inf K)"
        using x K by (auto simp: k interval_bounds_real[OF u v] field_simps)
      finally show "norm (content K *🪙R f' x - (f (Sup K) - f (Inf K))) e * (Sup K - Inf K)"
        using u v by (simp add: k)
    qed
    with a b show "norm (((x, K)p. content K *🪙R f' x) - (f b - f a)) e * content (cbox a b)"
      by (auto simp: ba split_def sum_subtractf [symmetric] sum_distrib_left)
  qed
qed

lemma has_complex_derivative_imp_has_vector_derivative:
  fixes f :: "complex ==> complex"
  assumes "(f has_field_derivative f') (at (of_real a) within (cbox (of_real x) (of_real y)))"
  shows "((f o of_real) has_vector_derivative f') (at a within {x..y})"
  using has_derivative_in_compose[of of_real of_real a "{x..y}" f "(*) f'"] assms
  by (simp add: scaleR_conv_of_real ac_simps has_vector_derivative_def has_field_derivative_def o_def cbox_complex_of_real)

lemma ident_has_integral:
  fixes a::real
  assumes " b"
  shows "((λx. x) has_integral (b🪙2 - a🪙2)/2) {a..b}"
proof -
  have "((λx. x) has_integral inverse 2 * b🪙2 - inverse 2 * a🪙2) {a..b}"
    unfolding power2_eq_square
    by (rule fundamental_theorem_of_calculus [OF assms] derivative_eq_intros | simp)+
  then show ?thesis
    by (simp add: field_simps)
qed

lemma integral_ident [simp]:
  fixes a::real
  assumes " b"
  shows "integral {a..b} (λx. x) = (if a  b then (b🪙2 - a🪙2)/2 else 0)"
  by (metis assms ident_has_integral integral_unique)

lemma ident_integrable_on:
  fixes a::real
  shows "(λx. x) integrable_on {a..b}"
  using continuous_on_id integrable_continuous_real by blast

lemma integral_sin [simp]:
  fixes a::real
  assumes " b" shows "integral {a..b} sin = cos a - cos b"
proof -
  have "(sin has_integral (- cos b - - cos a)) {a..b}"
  proof (rule fundamental_theorem_of_calculus)
    show "((λa. - cos a) has_vector_derivative sin x) (at x within {a..b})" for x
      unfolding has_real_derivative_iff_has_vector_derivative [symmetric]
      by (rule derivative_eq_intros | force)+
  qed (use assms in auto)
  then show ?thesis
    by (simp add: integral_unique)
qed

lemma integral_cos [simp]:
  fixes a::real
  assumes " b" shows "integral {a..b} cos = sin b - sin a"
proof -
  have "(cos has_integral (sin b - sin a)) {a..b}"
  proof (rule fundamental_theorem_of_calculus)
    show "(sin has_vector_derivative cos x) (at x within {a..b})" for x
      unfolding has_real_derivative_iff_has_vector_derivative [symmetric]
      by (rule derivative_eq_intros | force)+
  qed (use assms in auto)
  then show ?thesis
    by (simp add: integral_unique)
qed

lemma integral_exp [simp]:
  fixes a::real
  assumes " b" shows "integral {a..b} exp = exp b - exp a"
  by (meson DERIV_exp assms fundamental_theorem_of_calculus has_real_derivative_iff_has_vector_derivative
       has_vector_derivative_at_within integral_unique)

lemma has_integral_sin_nx: "((λx. sin(real_of_int n * x)) has_integral 0) {-pi..pi}"
proof (cases "n = 0")
  case False
  have "((λx. sin (n * x)) has_integral (- cos (n * pi)/n - - cos (n * - pi)/n)) {-pi..pi}"
  proof (rule fundamental_theorem_of_calculus)
    show "((λx. - cos (n * x) / n) has_vector_derivative sin (n * a)) (at a within {-pi..pi})"
      if " {-pi..pi}" for a :: real
      using that False
      unfolding has_vector_derivative_def
      by (intro derivative_eq_intros | force)+
  qed auto
  then show ?thesis
    by simp
qed auto

lemma integral_sin_nx:
   "integral {-pi..pi} (λx. sin(x * real_of_int n)) = 0"
  using has_integral_sin_nx [of n] by (force simp: mult.commute)

lemma has_integral_cos_nx:
  "((λx. cos(real_of_int n * x)) has_integral (if n = 0 then 2 * pi else 0)) {-pi..pi}"
proof (cases "n = 0")
  case True
  then show ?thesis
    using has_integral_const_real [of "1::real" "-pi" pi] by auto
next
  case False
  have "((λx. cos (n * x)) has_integral (sin (n * pi)/n - sin (n * - pi)/n)) {-pi..pi}"
  proof (rule fundamental_theorem_of_calculus)
    show "((λx. sin (n * x) / n) has_vector_derivative cos (n * x)) (at x within {-pi..pi})"
      if " {-pi..pi}"
      for x :: real
      using that False
      unfolding has_vector_derivative_def
      by (intro derivative_eq_intros | force)+
  qed auto
  with False show ?thesis
    by (simp add: mult.commute)
qed

lemma integral_cos_nx:
   "integral {-pi..pi} (λx. cos(x * real_of_int n)) = (if n = 0 then 2 * pi else 0)"
  using has_integral_cos_nx [of n] by (force simp: mult.commute)


subsection Taylor series expansion

lemma mvt_integral:
  fixes f::"'a::real_normed_vector==>'b::banach"
  assumes f'[derivative_intros]:
    "x. x  S ==> (f has_derivative f' x) (at x within S)"
  assumes line_in: "t. t  {0..1} ==> x + t *🪙R y  S"
  shows "f (x + y) - f x = integral {0..1} (λt. f' (x + t *🪙R y) y)"
proof -
  from assms have subset: "(λxa. x + xa *🪙R y) ` {0..1}  S" by auto
  note [derivative_intros] =
    has_derivative_subset[OF _ subset]
    has_derivative_in_compose[where f="(λu. x + u *🪙R y)" and g = f]
  have "t. t  {0..1} ==>
    ((λt. f (x + t *🪙R y)) has_vector_derivative f' (x + t *🪙R y) y)
    (at t within {0..1})"
    using assms
    by (auto simp: has_vector_derivative_def
        linear_cmul[OF has_derivative_linear[OF f'], symmetric]
      intro!: derivative_eq_intros)
  from fundamental_theorem_of_calculus[OF _ this]
  show ?thesis
    by (simp add: integral_unique)
qed

lemma (in bounded_bilinear) sum_prod_derivatives_has_vector_derivative:
  assumes "p>0"
  and f0: "Df 0 = f"
  and Df: "m t. m < p ==> a  t ==> t  b ==>
    (Df m has_vector_derivative Df (Suc m) t) (at t within {a..b})"
  and g0: "Dg 0 = g"
  and Dg: "m t. m < p ==> a  t ==> t  b ==>
    (Dg m has_vector_derivative Dg (Suc m) t) (at t within {a..b})"
  and ivl: " t" " b"
  shows "((λt. i<p. (-1)^i *🪙R prod (Df i t) (Dg (p - Suc i) t))
    has_vector_derivative
      prod (f t) (Dg p t) - (-1)^p *🪙R prod (Df p t) (g t))
    (at t within {a..b})"
  using assms
proof cases
  assume p: " 1"
  define p' where "p' = p - 2"
  from assms p have p': "{..<p} = {..Suc p'}" "p = Suc (Suc p')"
    by (auto simp: p'_def)
  have *: "i. i  p' ==> Suc (Suc p' - i) = (Suc (Suc p') - i)"
    by auto
  let ?f = "λi. (-1) ^ i *🪙R (prod (Df i t) (Dg ((p - i)) t))"
  have "(i<p. (-1) ^ i *🪙R (prod (Df i t) (Dg (Suc (p - Suc i)) t) +
    prod (Df (Suc i) t) (Dg (p - Suc i) t))) =
    (i(Suc p'). ?f i - ?f (Suc i))"
    by (auto simp: algebra_simps p'(2) numeral_2_eq_2 * lessThan_Suc_atMost)
  also note sum_telescope
  finally
  have "(i<p. (-1) ^ i *🪙R (prod (Df i t) (Dg (Suc (p - Suc i)) t) +
    prod (Df (Suc i) t) (Dg (p - Suc i) t)))
    = prod (f t) (Dg p t) - (- 1) ^ p *🪙R prod (Df p t) (g t)"
    unfolding p'[symmetric]
    by (simp add: assms)
  thus ?thesis
    using assms
    by (auto intro!: derivative_eq_intros has_vector_derivative)
qed (auto intro!: derivative_eq_intros has_vector_derivative)

lemma
  fixes f::"real==>'a::banach"
  assumes "p>0"
  and f0: "Df 0 = f"
  and Df: "m t. m < p ==> a  t ==> t  b ==>
    (Df m has_vector_derivative Df (Suc m) t) (at t within {a..b})"
  and ivl: " b"
  defines " λx. ((b - x) ^ (p - 1) / fact (p - 1)) *🪙R Df p x"
  shows Taylor_has_integral:
    "(i has_integral f b - (i<p. ((b-a) ^ i / fact i) *🪙R Df i a)) {a..b}"
  and Taylor_integral:
    "f b = (i<p. ((b-a) ^ i / fact i) *🪙R Df i a) + integral {a..b} i"
  and Taylor_integrable:
    "i integrable_on {a..b}"
proof goal_cases
  case 1
  interpret bounded_bilinear "scaleR::real==>'a==>'a"
    by (rule bounded_bilinear_scaleR)
  define g where "g s = (b - s)^(p - 1)/fact (p - 1)" for s
  define Dg where [abs_def]:
    "Dg n s = (if n < p then (-1)^n * (b - s)^(p - 1 - n) / fact (p - 1 - n) else 0)" for n s
  have g0: "Dg 0 = g"
    using p > 0
    by (auto simp: Dg_def field_split_simps g_def split: if_split_asm)
  have fact_eq: "real (p - Suc m) * fact (p - Suc (Suc m)) = fact (p - Suc m)"
    if "p > Suc m" for m
    by (metis Suc_diff_Suc fact_Suc that)
  have Dg: "m t. m < p ==> a  t ==> t  b ==>
    (Dg m has_vector_derivative Dg (Suc m) t) (at t within {a..b})"
    unfolding Dg_def has_vector_derivative_def
    by (auto intro!: derivative_eq_intros simp: fact_eq divide_simps simp del: of_nat_diff)
  let ?sum = "λt. i<p. (- 1) ^ i *🪙R Dg i t *🪙R Df (p - Suc i) t"
  from sum_prod_derivatives_has_vector_derivative[of _ Dg _ _ _ Df,
      OF p > 0 g0 Dg f0 Df]
  have deriv: "t. a  t ==> t  b ==>
    (?sum has_vector_derivative
      g t *🪙R Df p t - (- 1) ^ p *🪙R Dg p t *🪙R f t) (at t within {a..b})"
    by auto
  from fundamental_theorem_of_calculus[OF a b deriv]
  have "(i has_integral ?sum b - ?sum a) {a..b}"
    using Dg_def g_def i_def by fastforce
  also
  have one: "(- 1) ^ p' * (- 1) ^ p' = (1::real)" "{..<p}  {i. p = Suc i} = {p - 1}" for p'
    using p > 0 by (auto simp: power_mult_distrib)
  then have "?sum b = f b"
    using Suc_pred'[OF p > 0]
    by (simp add: diff_eq_eq Dg_def power_0_left le_Suc_eq if_distrib
        if_distribR sum.If_cases f0)
  also
  have "?sum a = (i<p. ((b-a) ^ i / fact i) *🪙R Df i a)"
  proof (rule sum.reindex_cong)
    have "i. i < p ==> j<p. i = p - Suc j"
      by (metis Suc_diff_Suc p>0 diff_Suc_less diff_diff_cancel less_or_eq_imp_le)
    then show "{..<p} = (λx. p - x - 1) ` {..<p}"
      by force
  qed (auto simp: inj_on_def Dg_def one)
  finally show c: ?case .
  case 2 show ?case
    by (metis (lifting) add_diff_cancel_left' add_diff_eq c integral_unique)
  case 3 show ?case
    using c by force
qed


subsection Only need trivial subintervals if the interval itself is trivial

proposition division_of_nontrivial:
  fixes D :: "'a::euclidean_space set set"
  assumes sdiv: "D division_of (cbox a b)"
     and cont0: "content (cbox a b)  0"
  shows "{k. k  D  content k  0} division_of (cbox a b)"
  using sdiv
proof (induction "card D" arbitrary: D rule: less_induct)
  case less
  note D = division_ofD[OF less.prems]
  show ?case
  proof (cases "{k  D. content k  0} = D")
    case False
    then obtain K c d where " D" and contk: "content K = 0" and keq: "K = cbox c d"
      using D(4) by blast
    then have "card D > 0"
      unfolding card_gt_0_iff using less by auto
    then have card: "card (D - {K}) < card D"
      using less K D by (simp add: D(1))
    have closed: "closed ((D - {K}))"
      using less.prems by auto
    have "x islimpt (D - {K})" if " K" for x
      unfolding islimpt_approachable
    proof (intro allI impI)
      fix e::real
      assume "e > 0"
      obtain i where i: "ci = di" "iBasis"
        using contk D(3) [OF K D] unfolding box_ne_empty keq
        by (meson content_eq_0 dual_order.antisym)
      then have xi: "xi = di"
        using x K unfolding keq mem_box by (metis antisym)
      define y where "y = (jBasis. (if j = i then if c (ai + bi)/2 then ci +
      min e (bi - ci)/2 else ci - min e (ci - ai)/2 else xj) *🪙R j)"
      show "x'(D - {K}). x'  x  dist x' x < e"
      proof (intro bexI conjI)
        have " cbox c d"
          using D(3)[OF K D] by (simp add: box_ne_empty(1) keq mem_box(2))
        then have " cbox a b"
          using D(2)[OF K D] by (auto simp: keq)
        then have di: " i  d  i  d  i  b  i"
          using i Basis mem_box(2) by blast
        then have xyi: "y xi"
          unfolding y_def i xi using e > 0 cont0 i Basis
          by (auto simp: content_eq_0 elim!: ballE[of _ _ i])
        then show " x"
          unfolding euclidean_eq_iff[where 'a='a] using i by auto
        have "norm (y-x)  (bBasis. (y - x)  b)"
          by (rule norm_le_l1)
        also have " = (y - x)  i + ( Basis - {i}. (y - x)  b)"
          by (meson finite_Basis i(2) sum.remove)
        also have " <  e + sum (λi. 0) Basis"
        proof (rule add_less_le_mono)
          show "(y-x)  i < e"
            using di e > 0 y_def i xi by (auto simp: inner_simps)
          show "(iBasis - {i}. (y-x)  i (iBasis. 0)"
            unfolding y_def by (auto simp: inner_simps)
        qed
        finally have "norm (y-x) < e + sum (λi. 0) Basis" .
        then show "dist y x < e"
          unfolding dist_norm by auto
        have " K"
          unfolding keq mem_box using i(1) i(2) xi xyi by fastforce
        moreover have " D"
          using subsetD[OF D(2)[OF K D] x K] e > 0 di i
          by (auto simp: D mem_box y_def field_simps elim!: ballE[of _ _ i])
        ultimately show " (D - {K})" by auto
      qed
    qed
    then have " (D - {K})"
      using closed closed_limpt by blast
    then have "(D - {K}) = cbox a b"
      unfolding D(6)[symmetric] by auto
    then have "D - {K} division_of cbox a b"
      by (metis Diff_subset less.prems division_of_subset D(6))
    then have "{ka  D - {K}. content ka  0} division_of (cbox a b)"
      using card less.hyps by blast
    moreover have "{ka  D - {K}. content ka  0} = {K  D. content K  0}"
      using contk by auto
    ultimately show ?thesis by auto
  qed (use less.prems in auto)
qed

subsection Integrability on subintervals

lemma operative_integrableI:
  fixes f :: "'b::euclidean_space ==> 'a::banach"
  assumes " e"
  shows "operative conj True (λi. f integrable_on i)"
proof -
  interpret comm_monoid conj True
  proof qed
  show ?thesis
  proof
    show "a b. box a b = {} ==> (f integrable_on cbox a b) = True"
      by (simp add: content_eq_0_interior integrable_on_null)
    show "a b c k.
             k  Basis ==>
             (f integrable_on cbox a b) 
             (f integrable_on cbox a b  {x. x  k  c}  f integrable_on cbox a b  {x. c  x  k})"
      unfolding integrable_on_def by (auto intro!: has_integral_split)
  qed
qed

lemma integrable_subinterval:
  fixes f :: "'b::euclidean_space ==> 'a::banach"
  assumes f: "f integrable_on cbox a b"
    and cd: "cbox c d  cbox a b"
  shows "f integrable_on cbox c d"
proof -
  interpret operative conj True "λi. f integrable_on i"
    using order_refl by (rule operative_integrableI)
  show ?thesis
    by (metis cd division division_of_finite empty f partial_division_extend_1 remove)
qed

lemma integrable_subinterval_real:
  fixes f :: "real ==> 'a::banach"
  assumes "f integrable_on {a..b}"
    and "{c..d}  {a..b}"
  shows "f integrable_on {c..d}"
  by (metis assms box_real(2) integrable_subinterval)

subsection Combining adjacent intervals in 1 dimension

lemma has_integral_combine:
  fixes a b c :: real and j :: "'a::banach"
  assumes " c"
      and " b"
      and ac: "(f has_integral i) {a..c}"
      and cb: "(f has_integral j) {c..b}"
  shows "(f has_integral (i + j)) {a..b}"
proof -
  interpret operative_real "lift_option plus" "Some 0"
    "λi. if f integrable_on i then Some (integral i f) else None"
    using operative_integralI by (rule operative_realI)
  from a c c b ac cb coalesce_less_eq
  have *: "lift_option (+)
             (if f integrable_on {a..c} then Some (integral {a..c} f) else None)
             (if f integrable_on {c..b} then Some (integral {c..b} f) else None) =
            (if f integrable_on {a..b} then Some (integral {a..b} f) else None)"
    by (auto simp: split: if_split_asm)
  then have "f integrable_on cbox a b"
    using ac cb by (auto split: if_split_asm)
  with * show ?thesis
    using ac cb by (auto simp: integrable_on_def integral_unique split: if_split_asm)
qed

lemma integral_combine:
  fixes f :: "real ==> 'a::banach"
  assumes " c"
    and " b"
    and ab: "f integrable_on {a..b}"
  shows "integral {a..c} f + integral {c..b} f = integral {a..b} f"
proof -
  have "(f has_integral integral {a..c} f) {a..c}" "(f has_integral integral {c..b} f) {c..b}"
    using ab c b a c integrable_subinterval_real by fastforce+
  then show ?thesis
    by (smt (verit, best) assms has_integral_combine integral_unique)
qed

lemma integrable_combine:
  fixes f :: "real ==> 'a::banach"
  assumes " c"
    and " b"
    and "f integrable_on {a..c}"
    and "f integrable_on {c..b}"
  shows "f integrable_on {a..b}"
  using assms has_integral_combine by blast

lemma integral_minus_sets:
  fixes f::"real ==> 'a::banach"
  shows " a ==> c  b ==> f integrable_on {c .. max a b} ==>
    integral {c .. a} f - integral {c .. b} f =
    (if a  b then - integral {a .. b} f else integral {b .. a} f)"
  using integral_combine[of c a b f] integral_combine[of c b a f]
  by (auto simp: algebra_simps max_def)

lemma integral_minus_sets':
  fixes f::"real ==> 'a::banach"
  shows " a ==> c  b ==> f integrable_on {min a b .. c} ==>
    integral {a .. c} f - integral {b .. c} f =
    (if a  b then integral {a .. b} f else - integral {b .. a} f)"
  using integral_combine[of b a c f] integral_combine[of a b c f]
  by (auto simp: algebra_simps min_def)

subsection Reduce integrability to "local" integrability

lemma integrable_on_little_subintervals:
  fixes f :: "'b::euclidean_space ==> 'a::banach"
  assumes "xcbox a b. d>0. u v. x  cbox u v  cbox u v  ball x d  cbox u v  cbox a b 
    f integrable_on cbox u v"
  shows "f integrable_on cbox a b"
proof -
  interpret operative conj True "λi. f integrable_on i"
    using order_refl by (rule operative_integrableI)
  have "x. d>0. xcbox a b  (u v. x  cbox u v  cbox u v  ball x d  cbox u v  cbox a b 
    f integrable_on cbox u v)"
    using assms by (metis zero_less_one)
  then obtain d where d: "x. 0 < d x"
     "x u v. [ cbox a b; x  cbox u v; cbox u v  ball x (d x); cbox u v  cbox a b] 
               ==> f integrable_on cbox u v"
    by metis
  obtain p where p: "p tagged_division_of cbox a b" "(λx. ball x (d x)) fine p"
    using fine_division_exists[OF gauge_ball_dependent,of d a b] d(1) by blast
  then have sndp: "snd ` p division_of cbox a b"
    by (metis division_of_tagged_division)
  have "f integrable_on k" if "(x, k)  p" for x k
    using tagged_division_ofD(2-4)[OF p(1) that] fineD[OF p(2) that] d by blast
  then show ?thesis
    unfolding division [symmetric, OF sndp] comm_monoid_set_F_and
    by auto
qed


subsection Second FTC or existence of antiderivative

lemma integrable_const[intro]: "(λx. c) integrable_on cbox a b"
  unfolding integrable_on_def by blast

lemma integral_has_vector_derivative_continuous_at:
  fixes f :: "real ==> 'a::banach"
  assumes f: "f integrable_on {a..b}"
     and x: " {a..b} - S"
     and "finite S"
     and fx: "continuous (at x within ({a..b} - S)) f"
 shows "((λu. integral {a..u} f) has_vector_derivative f x) (at x within ({a..b} - S))"
proof -
  let ?I = "λa b. integral {a..b} f"
  { fix e::real
    assume "e > 0"
    obtain d where "d>0" and d: "x'. [x'  {a..b} - S; x' - x < d] ==> norm(f x' - f x)  e"
      using e>0 fx by (auto simp: continuous_within_eps_delta dist_norm less_imp_le)
    have "norm (integral {a..y} f - integral {a..x} f - (y-x) *🪙R f x)  e * y - x" (is "?lhs  ?rhs")
           if y: " {a..b} - S" and yx: "y - x < d" for y
    proof (cases "y < x")
      case False
      have "f integrable_on {a..y}"
        using f y by (simp add: integrable_subinterval_real)
      then have Idiff: "?I a y - ?I a x = ?I x y"
        using False x by (simp add: algebra_simps integral_combine)
      have fux_int: "((λu. f u - f x) has_integral integral {x..y} f - (y-x) *🪙R f x) {x..y}"
      proof (rule has_integral_diff)
        show "(f has_integral integral {x..y} f) {x..y}"
          using x y by (auto intro: integrable_integral [OF integrable_subinterval_real [OF f]])
        show "((λu. f x) has_integral (y - x) *🪙R f x) {x..y}"
          using has_integral_const_real [of "f x" x y] False by simp
      qed
      have "?lhs  e * content {x..y}"
        using yx False d x y e>0 assms
        by (intro has_integral_bound_real[where f="(λu. f u - f x)"]) (auto simp: Idiff fux_int)
      also have "  ?rhs"
        using False by auto
      finally show ?thesis .
    next
      case True
      have "f integrable_on {a..x}"
        using f x by (simp add: integrable_subinterval_real)
      then have Idiff: "?I a x - ?I a y = ?I y x"
        using True x y by (simp add: algebra_simps integral_combine)
      have fux_int: "((λu. f u - f x) has_integral integral {y..x} f - (x - y) *🪙R f x) {y..x}"
      proof (rule has_integral_diff)
        show "(f has_integral integral {y..x} f) {y..x}"
          using x y by (auto intro: integrable_integral [OF integrable_subinterval_real [OF f]])
        show "((λu. f x) has_integral (x - y) *🪙R f x) {y..x}"
          using has_integral_const_real [of "f x" y x] True by simp
      qed
      have "norm (integral {a..x} f - integral {a..y} f - (x - y) *🪙R f x)  e * content {y..x}"
        using yx True d x y e>0 assms
        by (intro has_integral_bound_real[where f="(λu. f u - f x)"]) (auto simp: Idiff fux_int)
      also have "  e * y - x"
        using True by auto
      finally have "norm (integral {a..x} f - integral {a..y} f - (x - y) *🪙R f x)  e * y - x" .
      then show ?thesis
        by (simp add: algebra_simps norm_minus_commute)
    qed
    then have "d>0. y{a..b} - S. y - x < d  norm (integral {a..y} f - integral {a..x} f - (y-x) *🪙f x)  e * y - x"
      using d>0 by blast
  }
  then show ?thesis
    by (simp add: has_vector_derivative_def has_derivative_within_alt bounded_linear_scaleR_left)
qed


lemma integral_has_vector_derivative:
  fixes f :: "real ==> 'a::banach"
  assumes "continuous_on {a..b} f"
    and " {a..b}"
  shows "((λu. integral {a..u} f) has_vector_derivative f(x)) (at x within {a..b})"
  using assms integral_has_vector_derivative_continuous_at [OF integrable_continuous_real]
  by (fastforce simp: continuous_on_eq_continuous_within)

lemma integral_has_real_derivative:
  assumes "continuous_on {a..b} g"
  assumes " {a..b}"
  shows "((λx. integral {a..x} g) has_real_derivative g t) (at t within {a..b})"
  using integral_has_vector_derivative[of a b g t] assms
  by (auto simp: has_real_derivative_iff_has_vector_derivative)

lemma antiderivative_continuous:
  fixes q b :: real
  assumes "continuous_on {a..b} f"
  obtains g where "x. x  {a..b} ==> (g has_vector_derivative (f x::_::banach)) (at x within {a..b})"
  using integral_has_vector_derivative[OF assms] by auto

subsection Combined fundamental theorem of calculus

lemma antiderivative_integral_continuous:
  fixes f :: "real ==> 'a::banach"
  assumes "continuous_on {a..b} f"
  obtains g where "u{a..b}.  {a..b}. u  v  (f has_integral (g v - g u)) {u..v}"
proof -
  obtain g
    where g: "x. x  {a..b} ==> (g has_vector_derivative f x) (at x within {a..b})"
    using antiderivative_continuous[OF assms] by metis
  have "(f has_integral g v - g u) {u..v}" if " {a..b}" " {a..b}" " v" for u v
  proof -
    have "x. x  cbox u v ==> (g has_vector_derivative f x) (at x within cbox u v)"
      by (metis atLeastAtMost_iff atLeastatMost_subset_iff box_real(2) g
          has_vector_derivative_within_subset subsetCE that)
    then show ?thesis
      by (metis box_real(2) u v fundamental_theorem_of_calculus)
  qed
  then show ?thesis
    using that by blast
qed


subsection General "twiddling" for interval-to-interval function image

lemma has_integral_twiddle:
  assumes "0 < r"
    and hg: "x. h(g x) = x"
    and gh: "x. g(h x) = x"
    and contg: "x. continuous (at x) g"
    and g: "u v. w z. g ` cbox u v = cbox w z"
    and h: "u v. w z. h ` cbox u v = cbox w z"
    and r: "u v. content(g ` cbox u v) = r * content (cbox u v)"
    and intfi: "(f has_integral i) (cbox a b)"
  shows "((λx. f(g x)) has_integral (1 / r) *🪙R i) (h ` cbox a b)"
proof (cases "cbox a b = {}")
  case False
  obtain w z where wz: "h ` cbox a b = cbox w z"
    using h by blast
  have inj: "inj g" "inj h"
    using hg gh injI by metis+
  from h obtain ha hb where h_eq: "h ` cbox a b = cbox ha hb" by blast
  have "d. gauge d  (p. p tagged_division_of h ` cbox a b  d fine p 
               norm (((x, k)p. content k *🪙R f (g x)) - (1 / r) *🪙R i) < e)"
    if "e > 0" for e
  proof -
    have "e * r > 0" using that 0 < r by simp
    with intfi[unfolded has_integral]
    obtain d where "gauge d"
               and d: "p. p tagged_division_of cbox a b  d fine p 
                        ==> norm (((x, k)p. content k *🪙R f x) - i) < e * r"
      by metis
    define d' where "d' x = g -` d (g x)" for x
    show ?thesis
    proof (rule_tac x=d' in exI, safe)
      show "gauge d'"
        using gauge d continuous_open_vimage[OF _ contg] by (auto simp: gauge_def d'_def)
    next
      fix p
      assume ptag: "p tagged_division_of h ` cbox a b" and finep: "d' fine p"
      note p = tagged_division_ofD[OF ptag]
      have gab: "g y  cbox a b" if " K" "(x, K)  p" for x y K
        by (metis hg inj(2) inj_image_mem_iff p(3) subsetCE that that)
      have gimp: "(λ(x,K). (g x, g ` K)) ` p tagged_division_of (cbox a b)  
                  d fine (λ(x, k). (g x, g ` k)) ` p"
        unfolding tagged_division_of
      proof safe
        show "finite ((λ(x, k). (g x, g ` k)) ` p)"
          using ptag by auto
        show "d fine (λ(x, k). (g x, g ` k)) ` p"
          using finep unfolding fine_def d'_def by auto
      next
        fix x K
        assume xk: "(x, K)  p"
        show "g x  g ` K"
          using p(2)[OF xk] by auto
        show "u v. g ` K = cbox u v"
          using p(4)[OF xk] using assms(5-6) by auto
        fix x' K' u
        assume xk': "(x', K')  p" and u: " interior (g ` K)" " interior (g ` K')"
        have "interior K  interior K'  {}"
        proof
          assume "interior K  interior K' = {}"
          moreover have " g ` (interior K  interior K')"
            using interior_image_subset[OF inj g contg] u
            unfolding image_Int[OF inj(1)] by blast
          ultimately show False by blast
        qed
        then have same: "(x, K) = (x', K')"
          using ptag xk' xk by blast
        then show "g x = g x'"
          by auto
        show "g u  g ` K'"if " K" for u
          using that same by auto
        show "g u  g ` K"if " K'" for u
          using that same by auto
      next
        fix x
        assume " cbox a b"
        then have "h x   {k. x. (x, k)  p}"
          using p(6) by auto
        then obtain X y where "h x  X" "(y, X)  p" by blast
        then show " {k. x. (x, k)  (λ(x, k). (g x, g ` k)) ` p}"
          by clarsimp (metis (no_types, lifting) gh image_eqI pair_imageI)
      qed (use gab in auto)
      have *: "inj_on (λ(x, k). (g x, g ` k)) p"
        using inj(1) unfolding inj_on_def by fastforce
      have "((x,K)(λ(y,L). (g y, g ` L)) ` p. content K *🪙R f x) 
          = (up. case case u of (x,K) ==> (g x, g ` K) of (y,L) ==> content L *🪙R f y)"
        by (metis (mono_tags, lifting) "*" sum.reindex_cong)
      also have " = ((x,K)p. r *🪙R content K *🪙R f (g x))"
        using r by (auto intro!: * sum.cong simp: bij_betw_def dest!: p(4))
      finally
      have "((x, K)(λ(x,K). (g x, g ` K)) ` p. content K *🪙R f x) - i = r *🪙R ((x,K)p. content K *🪙R f (g x)) - i"
        by (simp add: scaleR_right.sum split_def)
      also have " = r *🪙R (((x,K)p. content K *🪙R f (g x)) - (1 / r) *🪙R i)"
        using 0 < r by (auto simp: scaleR_diff_right)
      finally show "norm (((x,K)p. content K *🪙R f (g x)) - (1 / r) *🪙R i) < e"
        using d[OF gimp] 0 < r by auto
    qed
  qed
  then show ?thesis
    by (auto simp: h_eq has_integral)
qed (use intfi in auto)


subsection Special case of a basic affine transformation

lemma AE_lborel_inner_neq:
  assumes k: " Basis"
  shows "AE x in lborel. x  k  c"
proof -
  interpret finite_product_sigma_finite "λ_. lborel" Basis
    proof qed simp
    have "emeasure lborel {xspace lborel. x  k = c} 
        = emeasure (Π🪙M j::'aBasis. lborel) (Π🪙E jBasis. if j = k then {c} else UNIV)"
    using k
    by (auto simp: lborel_eq[where 'a='a] emeasure_distr intro!: arg_cong2[where f=emeasure])
       (auto simp: space_PiM PiE_iff extensional_def split: if_split_asm)
  also have " = (jBasis. emeasure lborel (if j = k then {c} else UNIV))"
    by (intro measure_times) auto
  also have " = 0"
    by (intro prod_zero bexI[OF _ k]) auto
  finally show ?thesis
    by (subst AE_iff_measurable[OF _ refl]) auto
qed

lemma content_image_stretch_interval:
  fixes m :: "'a::euclidean_space ==> real"
  defines "s f x  (k::'aBasis. (f k * (xk)) *🪙R k)"
  shows "content (s m ` cbox a b) = kBasis. m k * content (cbox a b)"
proof cases
  have s[measurable]: "s f  borel 🪙M borel" for f
    by (auto simp: s_def[abs_def])
  assume m: "kBasis. m k  0"
  then have s_comp_s: "s (λk. 1 / m k)  s m = id" "s m  s (λk. 1 / m k) = id"
    by (auto simp: s_def[abs_def] fun_eq_iff euclidean_representation)
  then have "inv (s (λk. 1 / m k)) = s m" "bij (s (λk. 1 / m k))"
    by (auto intro: inv_unique_comp o_bij)
  then have eq: "s m ` cbox a b = s (λk. 1 / m k) -` cbox a b"
    using bij_vimage_eq_inv_image[OF bij (s (λk. 1 / m k)), of "cbox a b"] by auto
  show ?thesis
    using m unfolding eq measure_def
    by (subst lborel_affine_euclidean[where c=m and t=0])
       (simp_all add: emeasure_density measurable_sets_borel[OF s] abs_prod nn_integral_cmult
                      s_def[symmetric] emeasure_distr vimage_comp s_comp_s enn2real_mult prod_nonneg)
next
  assume "¬ (kBasis. m k  0)"
  then obtain k where k: " Basis" "m k = 0" by auto
  then have [simp]: "(kBasis. m k) = 0"
    by (intro prod_zero) auto
  have "emeasure lborel {xspace lborel. x  s m ` cbox a b} = 0"
  proof (rule emeasure_eq_0_AE)
    show "AE x in lborel. x  s m ` cbox a b"
      using AE_lborel_inner_neq[OF kBasis]
    proof eventually_elim
      show " k  0 ==> x  s m ` cbox a b " for x
        using k by (auto simp: s_def[abs_def] cbox_def)
    qed
  qed
  then show ?thesis
    by (simp add: measure_def)
qed

lemma interval_image_affinity_interval:
  "u v. (λx. m *🪙R (x::'a::euclidean_space) + c) ` cbox a b = cbox u v"
  unfolding image_affinity_cbox
  by auto

lemma content_image_affinity_cbox:
  "content((λx::'a::euclidean_space. m *🪙R x + c) ` cbox a b) =
    m ^ DIM('a) * content (cbox a b)" (is "?l = ?r")
proof (cases "cbox a b = {}")
  case True then show ?thesis by simp
next
  case False
  show ?thesis
  proof (cases " 0")
    case True
    with cbox a b {} have "cbox (m *🪙R a + c) (m *🪙R b + c)  {}"
      by (simp add: box_ne_empty inner_left_distrib mult_left_mono)
    moreover from True have *: "i. (m *🪙R b + c)  i - (m *🪙R a + c)  i = m *🪙R (b-a)  i"
      by (simp add: inner_simps field_simps)
    ultimately show ?thesis
      by (simp add: image_affinity_cbox True content_cbox' prod.distrib inner_diff_left)
  next
    case False
    with cbox a b {} have "cbox (m *🪙R b + c) (m *🪙R a + c)  {}"
      by (simp add: box_ne_empty inner_left_distrib mult_left_mono)
    moreover from False have *: "i. (m *🪙R a + c)  i - (m *🪙R b + c)  i = (-m) *🪙R (b-a)  i"
      by (simp add: inner_simps field_simps)
    ultimately show ?thesis using False
      by (simp add: image_affinity_cbox content_cbox' inner_diff_left flip: prod_constant prod.distrib)
  qed
qed

lemma has_integral_affinity:
  fixes a :: "'a::euclidean_space"
  assumes "(f has_integral i) (cbox a b)"
      and " 0"
  shows "((λx. f(m *🪙R x + c)) has_integral (1 / (m ^ DIM('a))) *🪙R i) ((λx. (1 / m) *🪙R x + -((1 / m) *🪙R c)) ` cbox a b)"
proof (rule has_integral_twiddle)
  show "w z. (λx. (1 / m) *🪙R x + - ((1 / m) *🪙R c)) ` cbox u v = cbox w z"
       "w z. (λx. m *🪙R x + c) ` cbox u v = cbox w z" for u v
    using interval_image_affinity_interval by blast+
  show "content ((λx. m *🪙R x + c) ` cbox u v) = m ^ DIM('a) * content (cbox u v)" for u v
    using content_image_affinity_cbox by blast
qed (use assms zero_less_power in auto simp: field_simps)

lemma integrable_affinity:
  assumes "f integrable_on cbox a b"
    and " 0"
  shows "(λx. f(m *🪙R x + c)) integrable_on ((λx. (1 / m) *🪙R x + -((1/m) *🪙R c)) ` cbox a b)"
  using has_integral_affinity assms
  unfolding integrable_on_def by blast

lemmas has_integral_affinity01 = has_integral_affinity [of _ _ 0 "1::real", simplified]

lemma integrable_on_affinity:
  assumes " 0" "f integrable_on (cbox a b)"
  shows "(λx. f (m *🪙R x + c)) integrable_on ((λx. (1 / m) *🪙R x - ((1 / m) *🪙R c)) ` cbox a b)"
proof -
  from assms obtain I where "(f has_integral I) (cbox a b)"
    by (auto simp: integrable_on_def)
  from has_integral_affinity[OF this assms(1), of c] show ?thesis
    by (auto simp: integrable_on_def)
qed

lemma has_integral_cmul_iff:
  assumes " 0"
  shows "((λx. c *🪙R f x) has_integral (c *🪙R I)) A  (f has_integral I) A"
  using assms has_integral_cmul[of f I A c]
        has_integral_cmul[of "λx. c *🪙R f x" "c *🪙R I" A "inverse c"]
  by (auto simp: field_simps)

lemma has_integral_cmul_iff':
  assumes " 0"
  shows "((λx. c *🪙R f x) has_integral I) A  (f has_integral I /🪙R c) A"
  using assms by (metis divideR_right has_integral_cmul_iff)

lemma has_integral_affinity':
  fixes a :: "'a::euclidean_space"
  assumes "(f has_integral i) (cbox a b)" and "m > 0"
  shows "((λx. f(m *🪙R x + c)) has_integral (i /🪙R m ^ DIM('a)))
           (cbox ((a - c) /🪙R m) ((b - c) /🪙R m))"
proof (cases "cbox a b = {}")
  case True
  hence "(cbox ((a - c) /🪙R m) ((b - c) /🪙R m)) = {}"
    using m > 0 unfolding box_eq_empty by (auto simp: algebra_simps)
  with True and assms show ?thesis by simp
next
  case False
  have "((λx. f (m *🪙R x + c)) has_integral (1 / m ^ DIM('a)) *🪙R i)
          ((λx. (1 / m) *🪙R x + - ((1 / m) *🪙R c)) ` cbox a b)"
    using assms by (intro has_integral_affinity) auto
  also have "((λx. (1 / m) *🪙R x + - ((1 / m) *🪙R c)) ` cbox a b) =
               ((λx.  - ((1 / m) *🪙R c) + x) ` (λx. (1 / m) *🪙R x) ` cbox a b)"
    by (simp add: image_image algebra_simps)
  also have "(λx. (1 / m) *🪙R x) ` cbox a b = cbox ((1 / m) *🪙R a) ((1 / m) *🪙R b)" using m > 0 False
    by (subst image_smult_cbox) simp_all
  also have "(λx. - ((1 / m) *🪙R c) + x) `  = cbox ((a - c) /🪙R m) ((b - c) /🪙R m)"
    by (subst cbox_translation [symmetric]) (simp add: field_simps vector_add_divide_simps)
  finally show ?thesis using m > 0
    by (simp add: field_simps)
qed

lemma has_integral_affinity_iff:
  fixes f :: "'a :: euclidean_space ==> 'b :: real_normed_vector"
  assumes "m > 0"
  shows "((λx. f (m *🪙R x + c)) has_integral (I /🪙R m ^ DIM('a)))
               (cbox ((a - c) /🪙R m) ((b - c) /🪙R m)) 
           (f has_integral I) (cbox a b)" (is "?lhs = ?rhs")
proof
  assume ?lhs
  from has_integral_affinity'[OF this, of "1 / m" "-c /🪙R m"] and m > 0
  show ?rhs by (simp add: vector_add_divide_simps) (simp add: field_simps)
next
  assume ?rhs
  from has_integral_affinity'[OF this, of m c] and m > 0
  show ?lhs by simp
qed

lemma integrable_on_shift_cbox:
  "(f  ((+) c)) integrable_on cbox a b  f integrable_on (cbox (a + c) (b + c))"
proof
  assume *: "(f  ((+) c)) integrable_on cbox a b"
  show "f integrable_on (cbox (a+c) (b+c))"
    using integrable_on_affinity[OF _ *, of 1 "-c"] cbox_translation[of c a b]
    by (simp add: add_ac)
next
  assume *: "f integrable_on (cbox (a+c) (b+c))"
  show "(f  ((+) c)) integrable_on cbox a b"
    using integrable_on_affinity[OF _ *, of 1 "c"] cbox_translation[of "-c" "a+c" "b+c"]
    by (simp add: o_def add_ac)
qed

lemma integrable_on_shift_Icc_real:
  "(f  ((+) c)) integrable_on {a..b::real}  f integrable_on {a+c..b+c}"
  using integrable_on_shift_cbox[of f c a b] by simp

lemma has_integral_shift_cbox_iff:
  "((f  ((+) c)) has_integral I) (cbox a b) 
   (f has_integral I) (cbox (a + c) (b + c))"
proof
  assume *: "((f  ((+) c)) has_integral I) (cbox a b)"
  show "(f has_integral I) (cbox (a + c) (b + c))"
    using has_integral_affinity[OF *, of 1 "-c"] cbox_translation[of c a b]
    by (simp add: add_ac)
next
  assume *: "(f has_integral I) (cbox (a + c) (b + c))"
  show "((f  ((+) c)) has_integral I) (cbox a b)"
    using has_integral_affinity[OF *, of 1 "c"] cbox_translation[of "-c" "a+c" "b+c"]
    by (simp add: o_def add_ac)
qed

lemma has_integral_shift_Icc_real:
  "((f  ((+) c)) has_integral I) {a..b::real}  (f has_integral I) {a+c..b+c}"
  using has_integral_shift_cbox_iff[of f c I a b] by simp

lemma integral_shift_cbox_plus:
  "integral (cbox a b) (f  ((+) c)) = integral (cbox (a+c) (b+c)) f"
  using has_integral_shift_cbox_iff[of f c _ a b] integrable_on_shift_cbox[of f c a b]
  by (metis integrable_integral integral_unique not_integrable_integral)

lemma integral_shift_Icc_real:
  "integral {a..b::real} (f  ((+) c)) = integral {a+c..b+c} f"
  using integral_shift_cbox_plus[of a b f c] by simp

subsection Special case of stretching coordinate axes separately

lemma has_integral_stretch:
  fixes f :: "'a::euclidean_space ==> 'b::real_normed_vector"
  assumes "(f has_integral i) (cbox a b)" and "kBasis. m k  0"
  shows "((λx. f (kBasis. (m k * (xk))*🪙R k)) has_integral
         ((1/ prod m Basis) *🪙R i)) ((λx. (kBasis. (1 / m k * (xk))*🪙R k)) ` cbox a b)"
  apply (rule has_integral_twiddle[where f=f])
  unfolding zero_less_abs_iff content_image_stretch_interval
  unfolding image_stretch_interval empty_as_interval euclidean_eq_iff[where 'a='a]
  using assms
  by auto

lemma integrable_stretch:
  fixes f :: "'a::euclidean_space ==> 'b::real_normed_vector"
  assumes "f integrable_on cbox a b" and "kBasis. m k  0"
  shows "(λx::'a. f (kBasis. (m k * (xk))*🪙R k)) integrable_on
    ((λx. kBasis. (1 / m k * (xk))*🪙R k) ` cbox a b)"
  using assms unfolding integrable_on_def
  by (force dest: has_integral_stretch)

lemma has_integral_stretch_real:
  fixes f :: "real ==> 'b::real_normed_vector"
  assumes "(f has_integral i) {a..b}" and " 0"
  shows "((λx. f (m * x)) has_integral (1 / m) *🪙R i) ((λx. x / m) ` {a..b})"
  using has_integral_stretch [of f i a b "λb. m"] assms by simp

lemma integrable_stretch_real:
  fixes f :: "real ==> 'b::real_normed_vector"
  assumes "f integrable_on {a..b}" and " 0"
  shows "(λx. f (m * x)) integrable_on ((λx. x / m) ` {a..b})"
proof -
  from assms obtain I where "(f has_integral I) {a..b}"
    by (auto simp: integrable_on_def)
  from has_integral_stretch_real[OF this assms(2)] show ?thesis
    by (auto simp: integrable_on_def)
qed

lemma integrable_stretch_real_iff:
  fixes f :: "real ==> 'b::real_normed_vector"
  assumes " 0"
  shows "(λx. f (m * x)) integrable_on ((λx. x / m) ` {a..b})  f integrable_on {a..b}"
proof
  assume "f integrable_on {a..b}"
  thus "(λx. f (m * x)) integrable_on ((λx. x / m) ` {a..b})"
    using assms by (intro integrable_stretch_real) auto
next
  assume *: "(λx. f (m * x)) integrable_on ((λx. x / m) ` {a..b})"
  define a' where "a' = (if m > 0 then a / m else b / m)"
  define b' where "b' = (if m > 0 then b / m else a / m)"
  have "bij_betw (λx. x / m) {a..b} {a'..b'}"
    by (rule bij_betwI[of _ _ _ "λx. x * m"]) (use assms in auto simp: field_simps a'_def b'_def)
  hence eq: "(λx. x / m) ` {a..b} = {a'..b'}"
    by (simp add: bij_betw_def)
  from * have "(λx. f (m * x)) integrable_on {a'..b'}"
    unfolding eq .
  hence "(λx. f (m * (1 / m * x))) integrable_on (λx. x / (1 / m)) ` {a'..b'}"
    using assms by (intro integrable_stretch_real) auto
  also have "(λx. f (m * (1 / m * x))) = f"
    using assms by simp
  also have "bij_betw (λx. x / (1 / m)) {a'..b'} {a..b}"
    by (rule bij_betwI[of _ _ _ "λx. x / m"]) (use assms in auto simp: field_simps a'_def b'_def)
  hence "(λx. x / (1 / m)) ` {a'..b'} = {a..b}"
    by (simp add: bij_betw_def)
  finally show "f integrable_on {a..b}" .
qed

lemma integral_stretch_real:
  fixes f :: "real ==> 'b::real_normed_vector"
  assumes " 0"
  shows "integral ((λx. x / m) ` {a..b}) (λx. f (m * x)) = (1 / m) *🪙R integral {a..b} f"
proof (cases "f integrable_on {a..b}")
  case True
  hence "(f has_integral integral {a..b} f) {a..b}"
    by blast
  from has_integral_stretch_real[OF this assms] show ?thesis
    by (simp add: has_integral_iff)
next
  case False
  hence "¬(λx. f (m * x)) integrable_on ((λx. x / m) ` {a..b})"
    using assms by (subst integrable_stretch_real_iff)
  with False show ?thesis
    by (simp add: not_integrable_integral)
qed

lemma has_integral_stretch_real_iff:
  fixes f :: "real ==> 'b::real_normed_vector"
  assumes " 0"
  shows "((λx. f (m * x)) has_integral I) ((λx. x / m) ` {a..b})  
             (f has_integral (m *🪙R I)) {a..b}"
  using integral_stretch_real[of m a b f] integrable_stretch_real_iff[of m f a b] assms
  by (auto simp: has_integral_iff)

lemma has_integral_shift_cbox:
  fixes f :: "'a :: euclidean_space ==> 'b :: real_normed_vector"
  assumes "(f has_integral I) (cbox a b)"
  shows "((λx. f (x + c)) has_integral I) (cbox (a - c) (b - c))"
proof -
  have "((λx. f (x + c)) has_integral (1 / 1) *🪙R I) ((λx. x - c) ` cbox a b)"
    by (rule has_integral_twiddle)
       (use assms in auto simp: cbox_shift'' cbox_shift' content_cbox_if
  algebra_simps box_eq_empty)
  thus ?thesis
    by (simp add: cbox_shift'')
qed

lemma integrable_shift_cbox:
  fixes f :: "'a :: euclidean_space ==> 'b :: real_normed_vector"
  assumes "f integrable_on cbox a b"
  shows "(λx. f (x + c)) integrable_on (cbox (a - c) (b - c))"
  using has_integral_shift_cbox[of f _ a b c] assms
  by (auto simp: integrable_on_def)

lemma integrable_shift_cbox_iff:
  fixes f :: "'a :: euclidean_space ==> 'b :: real_normed_vector"
  shows "(λx. f (x + c)) integrable_on (cbox (a - c) (b - c))  f integrable_on cbox a b"
  using integrable_shift_cbox[of f a b c]
        integrable_shift_cbox[of "λx. f (x + c)" "a - c" "b - c" "-c"] by auto

lemma integral_shift_cbox:
  fixes f :: "'a :: euclidean_space ==> 'b :: real_normed_vector"
  shows "integral (cbox (a - c) (b - c)) (λx. f (x + c)) = integral (cbox a b) f"
  by (metis eq_integralD has_integral_integral has_integral_shift_cbox
      integrable_shift_cbox_iff integral_unique)

lemma has_integral_shift_real_ivl:
  fixes f :: "real ==> 'b :: real_normed_vector"
  assumes "(f has_integral I) {a..b}"
  shows "((λx. f (x + c)) has_integral I) {a-c..b-c}"
  using has_integral_shift_cbox[of f I a b c] assms by simp

lemma has_integral_shift_real_ivl_iff:
  fixes f :: "real ==> 'b :: real_normed_vector"
  shows "(f has_integral I) {a..b}  ((λx. f (x + c)) has_integral I) {a-c..b-c}"
  using has_integral_shift_real_ivl[of f I a b c]
        has_integral_shift_real_ivl[of "λx. f (x + c)" I "a-c" "b-c" "-c"] by auto

lemma integrable_shift_real_ivl:
  fixes f :: "real ==> 'b :: real_normed_vector"
  assumes "f integrable_on {a..b}"
  shows "(λx. f (x + c)) integrable_on {a-c..b-c}"
  using integrable_shift_cbox[of f a b c] assms by simp

lemma integrable_shift_real_ivl_iff:
  fixes f :: "real ==> 'b :: real_normed_vector"
  shows "(λx. f (x + c)) integrable_on {a-c..b-c}  f integrable_on {a..b}"
  using integrable_shift_cbox_iff[of f c a b] by simp

lemma integral_shift_real_ivl:
  fixes f :: "real ==> 'b :: real_normed_vector"
  shows "integral {a-c..b-c} (λx. f (x + c)) = integral {a..b} f"
  using integral_shift_cbox[of a c b f] by simp

lemma vec_lambda_eq_sum:
     "(χ k. f k (x $ k)) = (kBasis. (f (axis_index k) (x  k)) *🪙R k)" (is "?lhs = ?rhs")
proof -
  have "?lhs = (χ k. f k (x  axis k 1))"
    by (simp add: cart_eq_inner_axis)
  also have " = (uUNIV. f u (x  axis u 1) *🪙R axis u 1)"
    by (simp add: vec_eq_iff axis_def if_distrib cong: if_cong)
  also have " = ?rhs"
    by (simp add: Basis_vec_def UNION_singleton_eq_range sum.reindex axis_eq_axis inj_on_def)
  finally show ?thesis .
qed

lemma has_integral_stretch_cart:
  fixes m :: "'n::finite ==> real"
  assumes f: "(f has_integral i) (cbox a b)" and m: "k. m k  0"
  shows "((λx. f(χ k. m k * x$k)) has_integral i /🪙prod m UNIV)
            ((λx. χ k. x$k / m k) ` (cbox a b))"
proof -
  have *: "k:: real^'n  Basis. m (axis_index k)  0"
    using axis_index by (simp add: m)
  have eqp: "(k:: real^'n  Basis. m (axis_index k)) = prod m UNIV"
    by (simp add: Basis_vec_def UNION_singleton_eq_range prod.reindex axis_eq_axis inj_on_def)
  show ?thesis
    using has_integral_stretch [OF f *] vec_lambda_eq_sum [where f="λi x. m i * x"] vec_lambda_eq_sum [where f="λi x. x / m i"]
    by (simp add: field_simps eqp)
qed

lemma image_stretch_interval_cart:
  fixes m :: "'n::finite ==> real"
  shows "(λx. χ k. m k * x$k) ` cbox a b =
            (if cbox a b = {} then {}
            else cbox (χ k. min (m k * a$k) (m k * b$k)) (χ k. max (m k * a$k) (m k * b$k)))"
proof -
  have *: "(kBasis. min (m (axis_index k) * (a  k)) (m (axis_index k) * (b  k)) *🪙R k)
           = (χ k. min (m k * a $ k) (m k * b $ k))"
          "(kBasis. max (m (axis_index k) * (a  k)) (m (axis_index k) * (b  k)) *🪙R k)
           = (χ k. max (m k * a $ k) (m k * b $ k))"
    apply (simp_all add: Basis_vec_def cart_eq_inner_axis UNION_singleton_eq_range sum.reindex axis_eq_axis inj_on_def)
    apply (simp_all add: vec_eq_iff axis_def if_distrib cong: if_cong)
    done
  show ?thesis
    by (simp add: vec_lambda_eq_sum [where f="λi x. m i * x"] image_stretch_interval eq_cbox *)
qed


subsection even more special cases

lemma uminus_interval_vector[simp]:
  fixes a b :: "'a::euclidean_space"
  shows "uminus ` cbox a b = cbox (-b) (-a)"
proof -
  have " uminus ` cbox a b" if " cbox (- b) (- a)" for x
    by (smt (verit) add.inverse_inverse image_iff inner_minus_left mem_box(2) that)
  then show ?thesis
    by (auto simp: mem_box)
qed

lemma has_integral_reflect_lemma[intro]:
  assumes "(f has_integral i) (cbox a b)"
  shows "((λx. f(-x)) has_integral i) (cbox (-b) (-a))"
  using has_integral_affinity[OF assms, of "-1" 0]
  by auto

lemma has_integral_reflect_lemma_real[intro]:
  assumes "(f has_integral i) {a..b::real}"
  shows "((λx. f(-x)) has_integral i) {-b .. -a}"
  by (metis has_integral_reflect_lemma interval_cbox assms)

lemma has_integral_reflect[simp]:
  "((λx. f (-x)) has_integral i) (cbox (-b) (-a))  (f has_integral i) (cbox a b)"
  by (auto dest: has_integral_reflect_lemma)

lemma has_integral_reflect_real[simp]:
  fixes a b::real
  shows "((λx. f (-x)) has_integral i) {-b..-a}  (f has_integral i) {a..b}"
  by (metis has_integral_reflect interval_cbox)

lemma integrable_reflect[simp]: "(λx. f(-x)) integrable_on cbox (-b) (-a)  f integrable_on cbox a b"
  unfolding integrable_on_def by auto

lemma integrable_reflect_real[simp]: "(λx. f(-x)) integrable_on {-b .. -a}  f integrable_on {a..b::real}"
  unfolding box_real[symmetric]
  by (rule integrable_reflect)

lemma integral_reflect[simp]: "integral (cbox (-b) (-a)) (λx. f (-x)) = integral (cbox a b) f"
  unfolding integral_def by auto

lemma integral_reflect_real[simp]: "integral {-b .. -a} (λx. f (-x)) = integral {a..b::real} f"
  unfolding box_real[symmetric]
  by (rule integral_reflect)

subsection Stronger form of FCT; quite a tedious proof

lemma split_minus[simp]: "(λ(x, k). f x k) x - (λ(x, k). g x k) x = (λ(x, k). f x k - g x k) x"
  by (simp add: split_def)

theorem fundamental_theorem_of_calculus_interior:
  fixes f :: "real ==> 'a::real_normed_vector"
  assumes " b"
    and contf: "continuous_on {a..b} f"
    and derf: "x. x  {a <..< b} ==> (f has_vector_derivative f' x) (at x)"
  shows "(f' has_integral (f b - f a)) {a..b}"
proof (cases "a = b")
  case True
  then have *: "cbox a b = {b}" "f b - f a = 0"
    by (auto simp: order_antisym)
  with True show ?thesis by auto
next
  case False
  with a b have ab: "a < b" by arith
  show ?thesis
    unfolding has_integral_factor_content_real
  proof (intro allI impI)
    fix e :: real
    assume e: "e > 0"
    then have eba8: "(e * (b-a)) / 8 > 0"
      using ab by (auto simp: field_simps)
    note derf_exp = derf[unfolded has_vector_derivative_def has_derivative_at_alt, THEN conjunct2, rule_format]
    have bounded: "x. x  {a<..<b} ==> bounded_linear (λu. u *🪙R f' x)"
      by (simp add: bounded_linear_scaleR_left)
    have " box a b. d>0. y. norm (y-x) < d  norm (f y - f x - (y-x) *🪙R f' x)  e/2 * norm (y-x)"
      (is " box a b. ?Q x") 🍋The explicit quantifier is required by the following step
        using e derf_exp [of _ "e/2"] by auto
    then obtain d where d: "x. 0 < d x"
      "x y. [ box a b; norm (y-x) < d x] ==> norm (f y - f x - (y-x) *🪙R f' x)  e/2 * norm (y-x)"
      unfolding bgauge_existence_lemma by metis
    have "bounded (f ` cbox a b)"
      using compact_cbox assms by (auto simp: compact_imp_bounded compact_continuous_image)
    then obtain B
      where "0 < B" and B: "x. x  f ` cbox a b ==> norm x  B"
      unfolding bounded_pos by metis
    obtain da where "0 < da"
      and da: "c. [ c; {a..c}  {a..b}; {a..c}  ball a da]
                          ==> norm (content {a..c} *🪙R f' a - (f c - f a))  (e * (b-a)) / 4"
    proof -
      have "continuous (at a within {a..b}) f"
        using contf continuous_on_eq_continuous_within by force
      with eba8 obtain k where "0 < k"
        and k: "x. [ {a..b}; 0 < norm (x-a); norm (x-a) < k] ==> norm (f x - f a) < e * (b-a) / 8"
        unfolding continuous_within Lim_within dist_norm by metis
      obtain l where l: "0 < l" "norm (l *🪙R f' a)  e * (b-a) / 8"
      proof (cases "f' a = 0")
        case True with ab e that show ?thesis by auto
      next
        case False
        show ?thesis
        proof
          show "norm ((e * (b - a) / 8 / norm (f' a)) *🪙R f' a)  e * (b - a) / 8"
               "0 < e * (b - a) / 8 / norm (f' a)"
            using False ab e by (auto simp: field_simps)
        qed
      qed
      have "norm (content {a..c} *🪙R f' a - (f c - f a))  e * (b-a) / 4"
        if " c" "{a..c}  {a..b}" and bmin: "{a..c}  ball a (min k l)" for c
      proof -
        have minkl: "a - x < min k l" if " {a..c}" for x
          using bmin dist_real_def that by auto
        then have lel: "c - a  l"
          using that by force
        have "norm ((c - a) *🪙R f' a - (f c - f a))  norm ((c - a) *🪙R f' a) + norm (f c - f a)"
          by (rule norm_triangle_ineq4)
        also have "  e * (b-a) / 8 + e * (b-a) / 8"
        proof (rule add_mono)
          have "norm ((c - a) *🪙R f' a)  norm (l *🪙R f' a)"
            by (auto intro: mult_right_mono [OF lel])
          with l show "norm ((c - a) *🪙R f' a)  e * (b-a) / 8"
            by linarith
        next
          have "norm (f c - f a) < e * (b-a) / 8"
          proof (cases "a = c")
            case True then show ?thesis
              using eba8 by auto
          next
            case False show ?thesis
              by (rule k) (use minkl a c that False in auto)
          qed
          then show "norm (f c - f a)  e * (b-a) / 8" by simp
        qed
        finally show "norm (content {a..c} *🪙R f' a - (f c - f a))  e * (b-a) / 4"
          unfolding content_real[OF a c] by auto
      qed
      then show ?thesis
        by (rule_tac da="min k l" in that) (auto simp: l 0 < k)
    qed
    obtain db where "0 < db"
      and db: "c. [ b; {c..b}  {a..b}; {c..b}  ball b db]
                   ==> norm (content {c..b} *🪙R f' b - (f b - f c))  (e * (b-a)) / 4"
    proof -
      have "continuous (at b within {a..b}) f"
        using contf continuous_on_eq_continuous_within by force
      with eba8 obtain k
        where "0 < k"
          and k: "x. [ {a..b}; 0 < norm(x-b); norm(x-b) < k]
                     ==> norm (f b - f x) < e * (b-a) / 8"
        unfolding continuous_within Lim_within dist_norm norm_minus_commute by metis
      obtain l where l: "0 < l" "norm (l *🪙R f' b)  (e * (b-a)) / 8"
      proof (cases "f' b = 0")
        case True thus ?thesis
          using ab e that by auto
      next
        case False show ?thesis
        proof
          show "norm ((e * (b - a) / 8 / norm (f' b)) *🪙R f' b)  e * (b - a) / 8"
               "0 < e * (b - a) / 8 / norm (f' b)"
            using False ab e by (auto simp: field_simps)
        qed
      qed
      have "norm (content {c..b} *🪙R f' b - (f b - f c))  e * (b-a) / 4"
        if " b" "{c..b}  {a..b}" and bmin: "{c..b}  ball b (min k l)" for c
      proof -
        have minkl: "b - x < min k l" if " {c..b}" for x
          using bmin dist_real_def that by auto
        then have lel: "b - c  l"
          using that by force
        have "norm ((b - c) *🪙R f' b - (f b - f c))  norm ((b - c) *🪙R f' b) + norm (f b - f c)"
          by (rule norm_triangle_ineq4)
        also have "  e * (b-a) / 8 + e * (b-a) / 8"
        proof (rule add_mono)
          have "norm ((b - c) *🪙R f' b)  norm (l *🪙R f' b)"
            by (auto intro: mult_right_mono [OF lel])
          also have "  e * (b-a) / 8"
            by (rule l)
          finally show "norm ((b - c) *🪙R f' b)  e * (b-a) / 8" .
        next
          have "norm (f b - f c) < e * (b-a) / 8"
          proof (cases "b = c")
            case True with eba8 show ?thesis
              by auto
          next
            case False show ?thesis
              by (rule k) (use minkl c b that False in auto)
          qed
          then show "norm (f b - f c)  e * (b-a) / 8" by simp
        qed
        finally show "norm (content {c..b} *🪙R f' b - (f b - f c))  e * (b-a) / 4"
          unfolding content_real[OF c b] by auto
      qed
      then show ?thesis
        by (rule_tac db="min k l" in that) (auto simp: l 0 < k)
    qed
    let ?d = "(λx. ball x (if x=a then da else if x=b then db else d x))"
    show "d. gauge d  (p. p tagged_division_of {a..b}  d fine p 
              norm (((x,K)p. content K *🪙R f' x) - (f b - f a))  e * content {a..b})"
    proof (rule exI, safe)
      show "gauge ?d"
        using ab db > 0 da > 0 d(1) by (auto intro: gauge_ball_dependent)
    next
      fix p
      assume ptag: "p tagged_division_of {a..b}" and fine: "?d fine p"
      let ?A = "{t. fst t  {a, b}}"
      note p = tagged_division_ofD[OF ptag]
      have pA: "p = (p  ?A)  (p - ?A)" "finite (p  ?A)" "finite (p - ?A)" "(p  ?A)  (p - ?A) = {}"
        using ptag fine by auto
      have le_xz: "w x y z::real. y  z/2 ==> w - x  z/2 ==> w + y  x + z"
        by arith
      have non: False if xk: "(x,K)  p" and " a" " b"
        and less: "e * (Sup K - Inf K)/2 < norm (content K *🪙R f' x - (f (Sup K) - f (Inf K)))"
      for x K
      proof -
        obtain u v where k: "K = cbox u v"
          using p(4) xk by blast
        then have " v" and uv: "{u, v}  cbox u v"
          using p(2)[OF xk] by auto
        then have result: "e * (v - u)/2 < norm ((v - u) *🪙R f' x - (f v - f u))"
          using less[unfolded k box_real interval_bounds_real content_real] by auto
        then have " box a b"
          using p(2) p(3) x a x b xk by fastforce
        with d have *: "y. norm (y-x) < d x 
                ==> norm (f y - f x - (y-x) *🪙R f' x)  e/2 * norm (y-x)"
          by metis
        have xd: "norm (u - x) < d x" "norm (v - x) < d x"
          using fineD[OF fine xk] x a x b uv
          by (auto simp: k subset_eq dist_commute dist_real_def)
        have "norm ((v - u) *🪙R f' x - (f v - f u)) =
              norm ((f u - f x - (u - x) *🪙R f' x) - (f v - f x - (v - x) *🪙R f' x))"
          by (rule arg_cong[where f=norm]) (auto simp: scaleR_left.diff)
        also have "  e/2 * norm (u - x) + e/2 * norm (v - x)"
          by (metis norm_triangle_le_diff add_mono * xd)
        also have "  e/2 * norm (v - u)"
          using p(2)[OF xk] by (auto simp: field_simps k)
        also have " < norm ((v - u) *🪙R f' x - (f v - f u))"
          using result by (simp add: u v)
        finally have "e * (v - u)/2 < e * (v - u)/2"
          using uv by auto
        then show False by auto
      qed
      have "norm ((x, K)p - ?A. content K *🪙R f' x - (f (Sup K) - f (Inf K)))
           ((x, K)p - ?A. norm (content K *🪙R f' x - (f (Sup K) - f (Inf K))))"
        by (auto intro: sum_norm_le)
      also have "  (np - ?A. e * (case n of (x, k) ==> Sup k - Inf k)/2)"
        using non by (fastforce intro: sum_mono)
      finally have I: "norm ((x, k)p - ?A. content k *🪙R f' x - (f (Sup k) - f (Inf k)))
                      (np - ?A. e * (case n of (x, k) ==> Sup k - Inf k))/2"
        by (simp add: sum_divide_distrib)
      have II: "norm ((x, k) ?A. content k *🪙R f' x - (f (Sup k) - f (Inf k))) -
             (n ?A. e * (case n of (x, k) ==> Sup k - Inf k))
              (np - ?A. e * (case n of (x, k) ==> Sup k - Inf k))/2"
      proof -
        have ge0: " e * (Sup k - Inf k)" if xkp: "(x, k)  p  ?A" for x k
        proof -
          obtain u v where uv: "k = cbox u v"
            by (meson Int_iff xkp p(4))
          with p that have "cbox u v  {}"
            by blast
          then show " e * ((Sup k) - (Inf k))"
            unfolding uv using e by (auto simp: field_simps)
        qed
        let ?B = "λx. {t  p. fst t = x  content (snd t)  0}"
        let ?C = "{t  p. fst t  {a, b}  content (snd t)  0}"
        have "norm ((x, k) {t. fst t  {a, b}}. content k *🪙R f' x - (f (Sup k) - f (Inf k)))  e * (b-a)/2"
        proof -
          have *: "S f e. sum f S = sum f (p  ?C) ==> norm (sum f (p  ?C))  e ==> norm (sum f S)  e"
            by auto
          have 1: "content K *🪙R (f' x) - (f ((Sup K)) - f ((Inf K))) = 0"
            if "(x,K)  p  {t. fst t  {a, b}} - p  ?C" for x K
          proof -
            have xk: "(x,K)  p" and k0: "content K = 0"
              using that by auto
            then obtain u v where uv: "K = cbox u v" "u = v"
              using xk k0 p by fastforce
            then show "content K *🪙R (f' x) - (f ((Sup K)) - f ((Inf K))) = 0"
              using xk unfolding uv by auto
          qed
          have 2: "norm((x,K) ?C. content K *🪙R f' x - (f (Sup K) - f (Inf K)))   e * (b-a)/2"
          proof -
            have norm_le: "norm (sum f S)  e"
              if 🍋: "x y. [ S; y  S] ==> x = y" "x. x  S ==> norm (f x)  e" "e > 0"
              for S f and e :: real
            proof (cases "S = {}")
              case True
              with that show ?thesis by auto
            next
              case False then obtain x where "S = {x}"
                using 🍋 by blast
              then show ?thesis
                by (simp add: that(2))
            qed
            have *: " ?C = ?B a  ?B b"
              by blast
            then have "norm ((x,K) ?C. content K *🪙R f' x - (f (Sup K) - f (Inf K))) =
                       norm ((x,K)  ?B a  ?B b. content K *🪙R f' x - (f (Sup K) - f (Inf K)))"
              by simp
            also have " = norm (((x,K)  ?B a. content K *🪙R f' x - (f (Sup K) - f (Inf K))) + 
                                   ((x,K)  ?B b. content K *🪙R f' x - (f (Sup K) - f (Inf K))))"
              using p(1) ab e by (subst sum.union_disjoint) auto
            also have "  e * (b - a) / 4 + e * (b - a) / 4"
            proof (rule norm_triangle_le [OF add_mono])
              have pa: "v. k = cbox a v  a  v" if "(a, k)  p" for k
                using p that by fastforce
              show "norm ((x,K)  ?B a. content K *🪙R f' x - (f (Sup K) - f (Inf K)))  e * (b - a) / 4"
              proof (intro norm_le; clarsimp)
                fix K K'
                assume K: "(a, K)  p" "(a, K')  p" and ne0: "content K  0" "content K'  0"
                with pa obtain v v' where v: "K = cbox a v" " v" and v': "K' = cbox a v'" " v'"
                  by blast
                let ?v = "min v v'"
                have "box a ?v  K  K'"
                  unfolding v v' by (auto simp: mem_box)
                then have "interior (box a (min v v'))  interior K  interior K'"
                  using interior_Int interior_mono by blast
                moreover have "(a + ?v)/2  box a ?v"
                  using ne0 unfolding v v' content_eq_0 not_le
                  by (auto simp: mem_box)
                ultimately have "(a + ?v)/2  interior K  interior K'"
                  unfolding interior_open[OF open_box] by auto
                then show "K = K'"
                  using p(5)[OF K] by auto
              next
                fix K
                assume K: "(a, K)  p" and ne0: "content K  0"
                show "norm (content c *🪙R f' a - (f (Sup c) - f (Inf c))) * 4  e * (b-a)"
                  if "(a, c)  p" and ne0: "content c  0" for c
                proof -
                  obtain v where v: "c = cbox a v" and " v"
                    using pa[OF (a, c) p] by metis
                  then have " {a..v}" " b"
                    using p(3)[OF (a, c) p] by auto
                  moreover have "{a..v}  ball a da"
                    using fineD[OF ?d fine p (a, c) p] by (simp add: v split: if_split_asm)
                  ultimately show ?thesis
                    unfolding v interval_bounds_real[OF a v] box_real
                    using da a v by auto
                qed
              qed (use ab e in auto)
            next
              have pb: "v. k = cbox v b  b  v" if "(b, k)  p" for k
                using p that by fastforce
              show "norm ((x,K)  ?B b. content K *🪙R f' x - (f (Sup K) - f (Inf K)))  e * (b - a) / 4"
              proof (intro norm_le; clarsimp)
                fix K K'
                assume K: "(b, K)  p" "(b, K')  p" and ne0: "content K  0" "content K'  0"
                with pb obtain v v' where v: "K = cbox v b" " b" and v': "K' = cbox v' b" "v'  b"
                  by blast
                let ?v = "max v v'"
                have "box ?v b  K  K'"
                  unfolding v v' by (auto simp: mem_box)
                then have "interior (box (max v v') b)  interior K  interior K'"
                  using interior_Int interior_mono by blast
                moreover have "((b + ?v)/2)  box ?v b"
                  using ne0 unfolding v v' content_eq_0 not_le by (auto simp: mem_box)
                ultimately have "((b + ?v)/2)  interior K  interior K'"
                  unfolding interior_open[OF open_box] by auto
                then show "K = K'"
                  using p(5)[OF K] by auto
              next
                fix K
                assume K: "(b, K)  p" and ne0: "content K  0"
                show "norm (content c *🪙R f' b - (f (Sup c) - f (Inf c))) * 4  e * (b-a)"
                  if "(b, c)  p" and ne0: "content c  0" for c
                proof -
                obtain v where v: "c = cbox v b" and " b"
                  using (b, c) p pb by blast
                then have " a"" {v.. b}"
                  using p(3)[OF (b, c) p] by auto
                moreover have "{v..b}  ball b db"
                  using fineD[OF ?d fine p (b, c) p] box_real(2) v False by force
                ultimately show ?thesis
                  using db v by auto
                qed
              qed (use ab e in auto)
            qed
            also have " = e * (b-a)/2"
              by simp
            finally show "norm ((x,k) ?C.
                        content k *🪙R f' x - (f (Sup k) - f (Inf k)))  e * (b-a)/2" .
          qed
          show "norm ((x, k) ?A. content k *🪙R f' x - (f ((Sup k)) - f ((Inf k))))  e * (b-a)/2"
            apply (rule * [OF sum.mono_neutral_right[OF pA(2)]])
            using 1 2 by (auto simp: split_paired_all)
        qed
        also have " = (np. e * (case n of (x, k) ==> Sup k - Inf k))/2"
          unfolding sum_distrib_left[symmetric]
          by (subst additive_tagged_division_1[OF a b ptag]) auto
        finally have norm_le: "norm ((x,K) {t. fst t  {a, b}}. content K *🪙R f' x - (f (Sup K) - f (Inf K)))
                 (np. e * (case n of (x, K) ==> Sup K - Inf K))/2" .
        have le2: "x s1 s2::real. 0  s1 ==> x  (s1 + s2)/2 ==> x - s1  s2/2"
          by auto
        show ?thesis
          apply (rule le2 [OF sum_nonneg])
          using ge0 apply force
          by (metis (no_types, lifting) Diff_Diff_Int Diff_subset norm_le p(1) sum.subset_diff)
      qed
      note * = additive_tagged_division_1[OF assms(1) ptag, symmetric]
      have "norm ((x,K) ?A  (p - ?A). content K *🪙R f' x - (f (Sup K) - f (Inf K)))
                e * ((x,K) ?A  (p - ?A). Sup K - Inf K)"
        unfolding sum_distrib_left
        unfolding sum.union_disjoint[OF pA(2-)]
        using le_xz norm_triangle_le I II by blast
      then
      show "norm (((x,K)p. content K *🪙R f' x) - (f b - f a))  e * content {a..b}"
        by (simp only: content_real[OF a b] *[of "λx. x"] *[of f] sum_subtractf[symmetric] split_minus pA(1) [symmetric])
    qed
  qed
qed


subsection Stronger form with finite number of exceptional points

lemma fundamental_theorem_of_calculus_interior_strong:
 fixes f :: "real ==> 'a::banach"
 assumes "finite S"
   and " b" "x. x  {a <..< b} - S ==> (f has_vector_derivative f'(x)) (at x)"
   and "continuous_on {a .. b} f"
 shows "(f' has_integral (f b - f a)) {a .. b}"
  using assms
proof (induction arbitrary: a b)
case empty
  then show ?case
    using fundamental_theorem_of_calculus_interior by force
next
case (insert x S)
  show ?case
  proof (cases " {a<..<b}")
    case False then show ?thesis
      using insert by blast
  next
    case True then have "a < x" "x < b"
      by auto
    have "(f' has_integral f x - f a) {a..x}" "(f' has_integral f b - f x) {x..b}"
      using continuous_on {a..b} f a < x x < b continuous_on_subset by (force simp: intro!: insert)+
    then have "(f' has_integral f x - f a + (f b - f x)) {a..b}"
      using a < x x < b has_integral_combine less_imp_le by blast
    then show ?thesis
      by simp
  qed
qed

corollary fundamental_theorem_of_calculus_strong:
  fixes f :: "real ==> 'a::banach"
  assumes "finite S"
    and " b"
    and vec: "x. x  {a..b} - S ==> (f has_vector_derivative f'(x)) (at x)"
    and "continuous_on {a..b} f"
  shows "(f' has_integral (f b - f a)) {a..b}"
  by (rule fundamental_theorem_of_calculus_interior_strong [OF finite S]) (force simp: assms)+

proposition indefinite_integral_continuous_left:
  fixes f:: "real ==> 'a::banach"
  assumes intf: "f integrable_on {a..b}" and "a < c" " b" "e > 0"
  obtains d where "d > 0"
    and "t. c - d < t  t  c  norm (integral {a..c} f - integral {a..t} f) < e"
proof -
  obtain w where "w > 0" and w: "t. [c - w < t; t < c] ==> norm (f c) * norm(c - t) < e/3"
  proof (cases "f c = 0")
    case False
    hence e3: "0 < e/3 / norm (f c)" using e>0 by simp
    moreover have "norm (f c) * norm (c - t) < e/3"
      if "t < c" and "c - e/3 / norm (f c) < t" for t
      unfolding real_norm_def
      by (smt (verit) False divide_right_mono nonzero_mult_div_cancel_left norm_eq_zero norm_ge_zero that)
    ultimately show ?thesis
      using that by auto
  qed (use e > 0 in auto)

  let ?SUM = "λp. ((x,K)  p. content K *🪙R f x)"
  have e3: "e/3 > 0"
    using e > 0 by auto
  have "f integrable_on {a..c}"
    using a < c c b by (auto intro: integrable_subinterval_real[OF intf])
  then obtain d1 where "gauge d1" and d1:
    "p. [p tagged_division_of {a..c}; d1 fine p] ==> norm (?SUM p - integral {a..c} f) < e/3"
    using integrable_integral has_integral_real e3 by metis
  define d where [abs_def]: "d x = ball x w  d1 x" for x
  have "gauge d"
    unfolding d_def using w > 0 gauge d1 by auto
  then obtain k where "0 < k" and k: "ball c k  d c"
    by (meson gauge_def open_contains_ball)

  let ?d = "min k (c - a)/2"
  show thesis
  proof (intro that[of ?d] allI impI, safe)
    show "?d > 0"
      using 0 < k a < c by auto
  next
    fix t
    assume t: "c - ?d < t" " c"
    show "norm (integral ({a..c}) f - integral ({a..t}) f) < e"
    proof (cases "t < c")
      case False with t c show ?thesis
        by (simp add: e > 0)
    next
      case True
      have "f integrable_on {a..t}"
        using t < c c b by (auto intro: integrable_subinterval_real[OF intf])
      then obtain d2 where d2: "gauge d2"
        "p. p tagged_division_of {a..t}  d2 fine p ==> norm (?SUM p - integral {a..t} f) < e/3"
        using integrable_integral has_integral_real e3 by metis
      define d3 where "d3 x = (if x  t then d1 x  d2 x else d1 x)" for x
      have "gauge d3"
        using gauge d1 gauge d2 unfolding d3_def gauge_def by auto
      then obtain p where ptag: "p tagged_division_of {a..t}" and pfine: "d3 fine p"
        by (metis box_real(2) fine_division_exists)
      note p' = tagged_division_ofD[OF ptag]
      have pt: "(x,K)==> x  t" for x K
        by (meson atLeastAtMost_iff p'(2) p'(3) subsetCE)
      with pfine have "d2 fine p"
        unfolding fine_def d3_def by fastforce
      then have d2_fin: "norm (?SUM p - integral {a..t} f) < e/3"
        using d2(2) ptag by auto
      have eqs: "{a..c}  {x. x  t} = {a..t}" "{a..c}  {x. x  t} = {t..c}"
        using t by (auto simp: field_simps)
      have " {(c, {t..c})} tagged_division_of {a..c}"
        using t c
        by (intro tagged_division_Un_interval_real [of _ _ _ 1 t])
           (auto simp: eqs tagged_division_of_self_real eqs ptag)
      moreover
      have "d1 fine p  {(c, {t..c})}"
        unfolding fine_def
      proof safe
        fix x K y
        assume "(x,K)  p" and " K" then show " d1 x"
          by (metis Int_iff d3_def subsetD fineD pfine)
      next
        fix x assume " {t..c}"
        then have "dist c x < k"
          using t(1) by (auto simp: field_simps dist_real_def)
        with k show " d1 c"
          unfolding d_def by auto
      qed
      ultimately have d1_fin: "norm (?SUM(p  {(c, {t..c})}) - integral {a..c} f) < e/3"
        using d1 by metis
      have SUMEQ: "?SUM(p  {(c, {t..c})}) = (c - t) *🪙R f c + ?SUM p"
      proof -
        have "?SUM(p  {(c, {t..c})}) = (content{t..c} *🪙R f c) + ?SUM p"
        proof (subst sum.union_disjoint)
          show " {(c, {t..c})} = {}"
            using t < c pt by force
        qed (use p'(1) in auto)
        also have " = (c - t) *🪙R f c + ?SUM p"
          using t c by auto
        finally show ?thesis .
      qed
      have "c - k < t"
        using k>0 t(1) by (auto simp: field_simps)
      moreover have " w"
      proof (rule ccontr)
        assume "¬ k  w"
        then have "c + (k + w) / 2  d c"
          by (auto simp: field_simps not_le not_less dist_real_def d_def)
        then have "c + (k + w) / 2  ball c k"
          using k by blast
        then show False
          using 0 < w ¬ k w dist_real_def by auto
      qed
      ultimately have cwt: "c - w < t"
        by (auto simp: field_simps)
      have eq: "integral {a..c} f - integral {a..t} f = -(((c - t) *🪙R f c + ?SUM p) -
                integral {a..c} f) + (?SUM p - integral {a..t} f) + (c - t) *🪙R f c"
        by auto
      have "norm (integral {a..c} f - integral {a..t} f) < e/3 + e/3 + e/3"
        unfolding eq
      proof (intro norm_triangle_lt add_strict_mono)
        show "norm (- ((c - t) *🪙R f c + ?SUM p - integral {a..c} f)) < e/3"
          by (metis SUMEQ d1_fin norm_minus_cancel)
        show "norm (?SUM p - integral {a..t} f) < e/3"
          using d2_fin by blast
        show "norm ((c - t) *🪙R f c) < e/3"
          using w cwt t < c by simp (simp add: field_simps)
      qed
      then show ?thesis by simp
    qed
  qed
qed

lemma indefinite_integral_continuous_right:
  fixes f :: "real ==> 'a::banach"
  assumes "f integrable_on {a..b}"
    and " c"
    and "c < b"
    and "e > 0"
  obtains d where "0 < d"
    and "t. c  t  t < c + d  norm (integral {a..c} f - integral {a..t} f) < e"
proof -
  have intm: "(λx. f (- x)) integrable_on {-b .. -a}" "- b < - c" "- c  - a"
    using assms by auto
  from indefinite_integral_continuous_left[OF intm e>0]
  obtain d where "0 < d"
    and d: "t. [- c - d < t; t  -c] 
             ==> norm (integral {- b..- c} (λx. f (-x)) - integral {- b..t} (λx. f (-x))) < e"
    by metis
  let ?d = "min d (b - c)"
  show ?thesis
  proof (intro that[of "?d"] allI impI)
    show "0 < ?d"
      using 0 < d c < b by auto
    fix t :: real
    assume t: " t  t < c + ?d"
    have *: "integral {a..c} f = integral {a..b} f - integral {c..b} f"
            "integral {a..t} f = integral {a..b} f - integral {t..b} f"
      using assms t by (auto simp: algebra_simps integral_combine)
    have "(- c) - d < (- t)" "- t  - c"
      using t by auto
    from d[OF this] show "norm (integral {a..c} f - integral {a..t} f) < e"
      by (auto simp: algebra_simps norm_minus_commute *)
  qed
qed

lemma indefinite_integral_continuous_1:
  fixes f :: "real ==> 'a::banach"
  assumes "f integrable_on {a..b}"
  shows "continuous_on {a..b} (λx. integral {a..x} f)"
proof -
  have "d>0. x'{a..b}. dist x' x < d  dist (integral {a..x'} f) (integral {a..x} f) < e"
       if x: " {a..b}" and "e > 0" for x e :: real
  proof (cases "a = b")
    case True
    with that show ?thesis by force
  next
    case False
    with x have "a < b" by force
    with x consider "x = a" | "x = b" | "a < x" "x < b"
      by force
    then show ?thesis
    proof cases
      case 1 then show ?thesis
        by (force simp: dist_norm algebra_simps intro: indefinite_integral_continuous_right [OF assms _ a < b e > 0])
    next
      case 2 then show ?thesis
        by (force simp: dist_norm norm_minus_commute algebra_simps intro: indefinite_integral_continuous_left [OF assms a < b _ e > 0])
    next
      case 3
      obtain d1 where "0 < d1"
        and d1: "t. [x - d1 < t; t  x] ==> norm (integral {a..x} f - integral {a..t} f) < e"
        using 3 by (auto intro: indefinite_integral_continuous_left [OF assms a < x _ e > 0])
      obtain d2 where "0 < d2"
        and d2: "t. [ t; t < x + d2] ==> norm (integral {a..x} f - integral {a..t} f) < e"
        using 3 by (auto intro: indefinite_integral_continuous_right [OF assms _ x < b e > 0])
      show ?thesis
      proof (intro exI ballI conjI impI)
        show "0 < min d1 d2"
          using 0 < d1 0 < d2 by simp
        show "dist (integral {a..y} f) (integral {a..x} f) < e"
          if "dist y x < min d1 d2" for y
          by (smt (verit) d1 d2 dist_commute dist_norm dist_real_def that)
      qed
    qed
  qed
  then show ?thesis
    by (auto simp: continuous_on_iff)
qed

lemma indefinite_integral_continuous_1':
  fixes f::"real ==> 'a::banach"
  assumes "f integrable_on {a..b}"
  shows "continuous_on {a..b} (λx. integral {x..b} f)"
proof -
  have "integral {a..b} f - integral {a..x} f = integral {x..b} f" if " {a..b}" for x
    using integral_combine[OF _ _ assms, of x] that
    by (auto simp: algebra_simps)
  with _ show ?thesis
    by (rule continuous_on_eq) (auto intro!: continuous_intros indefinite_integral_continuous_1 assms)
qed

theorem integral_has_vector_derivative':
  fixes f :: "real ==> 'b::banach"
  assumes "continuous_on {a..b} f"
    and " {a..b}"
  shows "((λu. integral {u..b} f) has_vector_derivative - f x) (at x within {a..b})"
proof -
  have *: "integral {x..b} f = integral {a .. b} f - integral {a .. x} f" if " x" " b" for x
    using integral_combine[of a x b for x, OF that integrable_continuous_real[OF assms(1)]]
    by (simp add: algebra_simps)
  show ?thesis
    using x _ *
    by (rule has_vector_derivative_transform)
      (auto intro!: derivative_eq_intros assms integral_has_vector_derivative)
qed

lemma integral_has_real_derivative':
  assumes "continuous_on {a..b} g"
  assumes " {a..b}"
  shows "((λx. integral {x..b} g) has_real_derivative -g t) (at t within {a..b})"
  using integral_has_vector_derivative'[OF assms]
  by (auto simp: has_real_derivative_iff_has_vector_derivative)


subsection This doesn't directly involve integration, but that gives an easy proof

lemma has_derivative_zero_unique_strong_interval:
  fixes f :: "real ==> 'a::banach"
  assumes "finite k"
    and contf: "continuous_on {a..b} f"
    and "f a = y"
    and fder: "x. x  {a..b} - k ==> (f has_derivative (λh. 0)) (at x within {a..b})"
    and x: " {a..b}"
  shows "f x = y"
proof -
  have " b" " x"
    using assms by auto
  have "((λx. 0::'a) has_integral f x - f a) {a..x}"
  proof (rule fundamental_theorem_of_calculus_interior_strong[OF finite k a x]; clarify?)
    have "{a..x}  {a..b}"
      using x by auto
    then show "continuous_on {a..x} f"
      by (rule continuous_on_subset[OF contf])
    show "(f has_vector_derivative 0) (at z)" if z: " {a<..<x}" and notin: " k" for z
      unfolding has_vector_derivative_def
    proof (simp add: at_within_open[OF z, symmetric])
      show "(f has_derivative (λx. 0)) (at z within {a<..<x})"
        by (rule has_derivative_subset [OF fder]) (use x z notin in auto)
    qed
  qed
  from has_integral_unique[OF has_integral_0 this]
  show ?thesis
    unfolding assms by auto
qed


subsection Generalize a bit to any convex set

lemma has_derivative_zero_unique_strong_convex:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes "convex S" "finite K"
    and contf: "continuous_on S f"
    and " S" "f c = y"
    and derf: "x. x  S - K ==> (f has_derivative (λh. 0)) (at x within S)"
    and " S"
  shows "f x = y"
proof (cases "x = c")
  case True with f c = y show ?thesis
    by blast
next
  case False
  let ?φ = "λu. (1 - u) *🪙R c + u *🪙R x"
  have contf': "continuous_on {0 ..1} (f  ?φ)"
  proof (rule continuous_intros continuous_on_subset[OF contf])+
    show "(λu. (1 - u) *🪙R c + u *🪙R x) ` {0..1}  S"
      using convex S x S c S by (auto simp: convex_alt algebra_simps)
  qed
  have "t = u" if "?φ t = ?φ u" for t u
  proof -
    from that have "(t - u) *🪙R x = (t - u) *🪙R c"
      by (auto simp: algebra_simps)
    then show ?thesis
      using x c by auto
  qed
  then have eq: "(SOME t. ?φ t = ?φ u) = u" for u
    by blast
  then have "(?φ -` K)  (λz. SOME t. ?φ t = z) ` K"
    by (clarsimp simp: image_iff) (metis (no_types) eq)
  then have fin: "finite (?φ -` K)"
    by (rule finite_surj[OF finite K])

  have derf': "((λu. f (?φ u)) has_derivative (λh. 0)) (at t within {0..1})"
               if " {0..1} - {t. ?φ t  K}" for t
  proof -
    have df: "(f has_derivative (λh. 0)) (at (?φ t) within ?φ ` {0..1})"
      using convex S x S c S that
      by (auto simp: convex_alt algebra_simps intro: has_derivative_subset [OF derf])
    have "(f  ?φ has_derivative (λx. 0)  (λz. (0 - z *🪙R c) + z *🪙R x)) (at t within {0..1})"
      by (rule derivative_eq_intros df | simp)+
    then show ?thesis
      unfolding o_def .
  qed
  have "(f  ?φ) 1 = y"
    apply (rule has_derivative_zero_unique_strong_interval[OF fin contf'])
    unfolding o_def using f c = y derf' by auto
  then show ?thesis
    by auto
qed


text Also to any open connected set with finite set of exceptions. Could
  generalize to locally convex set with limpt-free set of exceptions.

lemma has_derivative_zero_unique_strong_connected:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes "connected S"
    and "open S"
    and "finite K"
    and contf: "continuous_on S f"
    and " S"
    and "f c = y"
    and derf: "x. x  S - K ==> (f has_derivative (λh. 0)) (at x within S)"
    and " S"
  shows "f x = y"
proof -
  have "e>0. ball x e  (S  f -` {f x})" if " S" for x
  proof -
    obtain e where "0 < e" and e: "ball x e  S"
      using x S open S open_contains_ball by blast
    have "ball x e  {u  S. f u  {f x}}"
    proof safe
      fix y
      assume y: " ball x e"
      then show " S"
        using e by auto
      show "f y = f x"
      proof (rule has_derivative_zero_unique_strong_convex[OF convex_ball finite K])
        show "continuous_on (ball x e) f"
          using contf continuous_on_subset e by blast
        show "(f has_derivative (λh. 0)) (at u within ball x e)"
             if " ball x e - K" for u
          by (metis Diff_iff contra_subsetD derf e has_derivative_subset that)
      qed (use y e 0 < e in auto)
    qed
    then show "e>0. ball x e  (S  f -` {f x})"
      using 0 < e by blast
  qed
  then have "openin (top_of_set S) (S  f -` {y})"
    by (auto intro!: open_openin_trans[OF open S] simp: open_contains_ball)
  moreover have "closedin (top_of_set S) (S  f -` {y})"
    by (force intro!: continuous_closedin_preimage [OF contf])
  ultimately have "(S  f -` {y}) = {}  (S  f -` {y}) = S"
    using connected S by (simp add: connected_clopen)
  then show ?thesis
    using x S f c = y c S by auto
qed

lemma has_derivative_zero_connected_constant_on:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes "connected S" "open S" "finite K" "continuous_on S f"
      and "xS-K. (f has_derivative (λh. 0)) (at x within S)"
  shows "f constant_on S"
  by (smt (verit, best) assms constant_on_def has_derivative_zero_unique_strong_connected)

lemma DERIV_zero_connected_constant_on:
  fixes f :: "'a::{real_normed_field,euclidean_space} ==> 'a"
  assumes *: "connected S" "open S" "finite K" "continuous_on S f"
      and 0: "xS-K. DERIV f x :> 0"
  shows "f constant_on S"
  using has_derivative_zero_connected_constant_on [OF *] 0
  by (metis has_derivative_at_withinI has_field_derivative_def lambda_zero)

lemma DERIV_zero_connected_constant:
  fixes f :: "'a::{real_normed_field,euclidean_space} ==> 'a"
  assumes "connected S" and "open S" and "finite K" and "continuous_on S f"
      and "xS-K. DERIV f x :> 0"
    obtains c where "x. x  S ==> f(x) = c"
  by (metis DERIV_zero_connected_constant_on [OF assms] constant_on_def)

lemma has_field_derivative_0_imp_constant_on:
  fixes f :: "'a::{real_normed_field,euclidean_space} ==> 'a"
  assumes "z. z  S ==> (f has_field_derivative 0) (at z)" and S: "connected S" "open S"
  shows "f constant_on S"
  using DERIV_zero_connected_constant_on [where K="Basis"]
  by (metis DERIV_isCont Diff_iff assms continuous_at_imp_continuous_on eucl.finite_Basis)


subsection Integrating characteristic function of an interval

lemma has_integral_restrict_open_subinterval:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes intf: "(f has_integral i) (cbox c d)"
    and cb: "cbox c d  cbox a b"
  shows "((λx. if x  box c d then f x else 0) has_integral i) (cbox a b)"
proof (cases "cbox c d = {}")
  case True
  then have "box c d = {}"
    by (metis bot.extremum_uniqueI box_subset_cbox)
  then show ?thesis
    using True intf by auto
next
  case False
  then obtain p where pdiv: "p division_of cbox a b" and inp: "cbox c d  p"
    using cb partial_division_extend_1 by blast
  define g where [abs_def]: "g x = (if x box c d then f x else 0)" for x
  interpret operative "lift_option plus" "Some (0 :: 'b)"
    "λi. if g integrable_on i then Some (integral i g) else None"
    by (fact operative_integralI)
  note operat = division [OF pdiv, symmetric]
  show ?thesis
  proof (cases "(g has_integral i) (cbox a b)")
    case True then show ?thesis
      by (simp add: g_def)
  next
    case False
    have iterate: "F (λi. if g integrable_on i then Some (integral i g) else None) (p - {cbox c d}) = Some 0"
    proof (intro neutral ballI)
      fix x
      assume x: " p - {cbox c d}"
      then have " p"
        by auto
      then obtain u v where uv: "x = cbox u v"
        using pdiv by blast
      have "interior x  interior (cbox c d) = {}"
        using pdiv inp x by blast
      then have "(g has_integral 0) x"
        unfolding uv using has_integral_spike_interior[where f="λx. 0"]
        by (metis (no_types, lifting) disjoint_iff_not_equal g_def has_integral_0_eq interior_cbox)
      then show "(if g integrable_on x then Some (integral x g) else None) = Some 0"
        by auto
    qed
    interpret comm_monoid_set "lift_option plus" "Some (0 :: 'b)"
      by (intro comm_monoid_set.intro comm_monoid_lift_option add.comm_monoid_axioms)
    have intg: "g integrable_on cbox c d"
      using integrable_spike_interior[where f=f]
      by (meson g_def has_integral_integrable intf)
    moreover have "integral (cbox c d) g = i"
      by (meson g_def has_integral_iff has_integral_spike_interior intf)
    ultimately have "F (λA. if g integrable_on A then Some (integral A g) else None) p = Some i"
      by (metis (full_types, lifting) division_of_finite inp iterate pdiv remove right_neutral)
    with False show ?thesis
      by (metis integrable_integral not_None_eq operat option.inject)
  qed
qed


lemma has_integral_restrict_closed_subinterval:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes "(f has_integral i) (cbox c d)"
    and "cbox c d  cbox a b"
  shows "((λx. if x  cbox c d then f x else 0) has_integral i) (cbox a b)"
proof -
  note has_integral_restrict_open_subinterval[OF assms]
  note * = has_integral_spike[OF negligible_frontier_interval _ this]
  show ?thesis
    by (rule *[of c d]) (use box_subset_cbox[of c d] in auto)
qed

lemma has_integral_restrict_closed_subintervals_eq:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes "cbox c d  cbox a b"
  shows "((λx. if x  cbox c d then f x else 0) has_integral i) (cbox a b)  (f has_integral i) (cbox c d)"
  (is "?l = ?r")
proof (cases "cbox c d = {}")
  case False
  let ?g = "λx. if x  cbox c d then f x else 0"
  show ?thesis
  proof
    assume ?l
    then have "?g integrable_on cbox c d"
      using assms has_integral_integrable integrable_subinterval by blast
    then have f: "f integrable_on cbox c d"
      by (rule integrable_eq) auto
    moreover have "i = integral (cbox c d) f"
      using f (?g has_integral i) (cbox a b)
      by (simp add: assms has_integral_restrict_closed_subinterval has_integral_unique
          integrable_integral)
    ultimately show ?r by auto
  next
    assume ?r then show ?l
      by (rule has_integral_restrict_closed_subinterval[OF _ assms])
  qed
qed auto


text Hence we can apply the limit process uniformly to all integrals.

lemma has_integral':
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  shows "(f has_integral i) S 
    (e>0. B>0. a b. ball 0 B  cbox a b 
      (z. ((λx. if x  S then f(x) else 0) has_integral z) (cbox a b)  norm(z - i) < e))"
  (is "?l  (e>0. ?r e)")
proof (cases "a b. S = cbox a b")
  case False then show ?thesis
    by (simp add: has_integral_alt)
next
  case True
  then obtain a b where S: "S = cbox a b"
    by blast
  obtain B where " 0 < B" and B: "x. x  cbox a b ==> norm x  B"
    using bounded_cbox[unfolded bounded_pos] by blast
  show ?thesis
  proof safe
    fix e :: real
    assume ?l and "e > 0"
    have "((λx. if x  S then f x else 0) has_integral i) (cbox c d)"
      if "ball 0 (B+1)  cbox c d" for c d
        unfolding S using B that
        by (force intro: ?l[unfolded S] has_integral_restrict_closed_subinterval)
    then show "?r e"
      by (meson 0 < B 0 < e add_pos_pos le_less_trans zero_less_one norm_pths(2))
  next
    assume as: "e>0. ?r e"
    then obtain C
      where C: "a b. ball 0 C  cbox a b ==>
                z. ((λx. if x  S then f x else 0) has_integral z) (cbox a b)"
      by (meson zero_less_one)
    define c :: 'n where "c = (iBasis. (- max B C) *🪙R i)"
    define d :: 'n where "d = (iBasis. max B C *🪙R i)"
    have " i  x  i  x  i  d  i" if "norm x  B" " Basis" for x i
      using that and Basis_le_norm[OF iBasis, of x]
      by (auto simp: field_simps sum_negf c_def d_def)
    then have c_d: "cbox a b  cbox c d"
      by (meson B mem_box(2) subsetI)
    have " i  x  i  x  i  d  i"
      if x: "norm (0 - x) < C" and i: " Basis" for x i
        using Basis_le_norm[OF i, of x] x i by (auto simp: sum_negf c_def d_def)
      then have "ball 0 C  cbox c d"
        by (auto simp: mem_box dist_norm)
    with C obtain y where y: "(f has_integral y) (cbox a b)"
      using c_d has_integral_restrict_closed_subintervals_eq S by blast
    have "y = i"
    proof (rule ccontr)
      assume " i"
      then have "0 < norm (y - i)"
        by auto
      from as[rule_format,OF this]
      obtain C where C: "a b. ball 0 C  cbox a b ==> 
           z. ((λx. if x  S then f x else 0) has_integral z) (cbox a b)  norm (z-i) < norm (y-i)"
        by auto
      define c :: 'n where "c = (iBasis. (- max B C) *🪙R i)"
      define d :: 'n where "d = (iBasis. max B C *🪙R i)"
      have " i  x  i  x  i  d  i"
        if "norm x  B" and " Basis" for x i
          using that Basis_le_norm[of i x] by (auto simp: field_simps sum_negf c_def d_def)
        then have c_d: "cbox a b  cbox c d"
        by (simp add: B mem_box(2) subset_eq)
      have " i  x  i  x  i  d  i" if "norm (0 - x) < C" and " Basis" for x i
        using Basis_le_norm[of i x] that by (auto simp: sum_negf c_def d_def)
      then have "ball 0 C  cbox c d"
        by (auto simp: mem_box dist_norm)
      with C obtain z where z: "(f has_integral z) (cbox a b)" "norm (z-i) < norm (y-i)"
        using has_integral_restrict_closed_subintervals_eq[OF c_d] S by blast
      moreover have "z = y"
        using z by (blast intro: has_integral_unique[OF _ y])
      ultimately show False
        by auto
    qed
    then show ?l
      using y by (auto simp: S)
  qed
qed

lemma has_integral_le:
  fixes f :: "'n::euclidean_space ==> real"
  assumes fg: "(f has_integral i) S" "(g has_integral j) S"
    and le: "x. x  S ==> f x  g x"
  shows " j"
  using has_integral_component_le[OF _ fg, of 1] le by auto

lemma integral_le:
  fixes f :: "'n::euclidean_space ==> real"
  assumes "f integrable_on S"
    and "g integrable_on S"
    and "x. x  S ==> f x  g x"
  shows "integral S f  integral S g"
  by (meson assms has_integral_le integrable_integral)

lemma has_integral_nonneg:
  fixes f :: "'n::euclidean_space ==> real"
  assumes "(f has_integral i) S" and "x. x  S ==> 0  f x"
  shows " i"
  using assms has_integral_0 has_integral_le by blast

lemma integral_nonneg:
  fixes f :: "'n::euclidean_space ==> real"
  assumes "f integrable_on S" and "x. x  S ==> 0  f x"
  shows " integral S f"
  using assms has_integral_nonneg by blast


text Hence a general restriction property.

lemma has_integral_restrict [simp]:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  assumes " T"
  shows "((λx. if x  S then f x else 0) has_integral i) T  (f has_integral i) S"
proof -
  have *: "x. (if x  T then if x  S then f x else 0 else 0) =  (if xthen f x else 0)"
    using assms by auto
  show ?thesis
    apply (subst(2) has_integral')
    apply (subst has_integral')
      apply (simp add: *)
    done
qed

corollary has_integral_restrict_UNIV:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  shows "((λx. if x  s then f x else 0) has_integral i) UNIV  (f has_integral i) s"
  by auto

lemma has_integral_restrict_Int:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  shows "((λx. if x  S then f x else 0) has_integral i) T  (f has_integral i) (S  T)"
proof -
  have "((λx. if x  T then if x  S then f x else 0 else 0) has_integral i) UNIV =
        ((λx. if x  S  T then f x else 0) has_integral i) UNIV"
    by (rule has_integral_cong) auto
  then show ?thesis
    using has_integral_restrict_UNIV by fastforce
qed

lemma integral_restrict_Int:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  shows "integral T (λx. if x  S then f x else 0) = integral (S  T) f"
  by (metis (no_types, lifting) has_integral_cong has_integral_restrict_Int integrable_integral integral_unique not_integrable_integral)

lemma integrable_restrict_Int:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  shows "(λx. if x  S then f x else 0) integrable_on T  f integrable_on (S  T)"
  using has_integral_restrict_Int by fastforce

lemma has_integral_on_superset:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "(f has_integral i) S"
      and "x. x  S ==> f x = 0"
      and " T"
    shows "(f has_integral i) T"
  by (smt (verit, ccfv_SIG) assms has_integral_cong has_integral_restrict)

lemma integrable_on_superset:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "f integrable_on S" and "x. x  S ==> f x = 0" and " t"
  shows "f integrable_on t"
  by (meson assms has_integral_on_superset integrable_integral integrable_on_def)

lemma integral_subset_negligible:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  assumes " T" "negligible (T - S)"
  shows "integral S f = integral T f"
proof -
  have "integral T f = integral T (λx. if x  S then f x else 0)"
    by (rule integral_spike[of "T - S"]) (use assms in auto)
  also have " = integral (S  T) f"
    by (subst integral_restrict_Int) auto
  also have " T = S" using assms by auto
  finally show ?thesis ..
qed

lemma integral_restrict_UNIV:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  shows "integral UNIV (λx. if x  S then f x else 0) = integral S f"
  by (simp add: integral_restrict_Int)

lemma integrable_restrict_UNIV:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  shows "(λx. if x  s then f x else 0) integrable_on UNIV  f integrable_on s"
  unfolding integrable_on_def
  by auto

lemma has_integral_subset_component_le:
  fixes f :: "'n::euclidean_space ==> 'm::euclidean_space"
  assumes k: " Basis"
    and " T" "(f has_integral i) S" "(f has_integral j) T" "x. x==> 0  f(x)k"
  shows "i jk"
proof -
  have 🍋: "((λx. if x  S then f x else 0) has_integral i) UNIV"
          "((λx. if x  T then f x else 0) has_integral j) UNIV"
    by (simp_all add: assms)
  show ?thesis
    using assms by (force intro!: has_integral_component_le[OF k 🍋])
qed

subsectionIntegrals on set differences

lemma has_integral_setdiff:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes S: "(f has_integral i) S" and T: "(f has_integral j) T"
    and neg: "negligible (T - S)"
  shows "(f has_integral (i - j)) (S - T)"
proof -
  show ?thesis
    unfolding has_integral_restrict_UNIV [symmetric, of f]
  proof (rule has_integral_spike [OF neg])
    have eq: "(λx. (if x  S then f x else 0) - (if x  T then f x else 0)) =
            (λx. if x  T - S then - f x else if x  S - T then f x else 0)"
      by force
    have "((λx. if x  S then f x else 0) has_integral i) UNIV"
      "((λx. if x  T then f x else 0) has_integral j) UNIV"
      using S T has_integral_restrict_UNIV by auto
    from has_integral_diff [OF this]
    show "((λx. if x  T - S then - f x else if x  S - T then f x else 0)
                   has_integral i-j) UNIV"
      by (simp add: eq)
  qed force
qed

lemma integral_setdiff:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes "f integrable_on S" "f integrable_on T" "negligible(T - S)"
 shows "integral (S - T) f = integral S f - integral T f"
  by (rule integral_unique) (simp add: assms has_integral_setdiff integrable_integral)

lemma integrable_setdiff:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  assumes "(f has_integral i) S" "(f has_integral j) T" "negligible (T - S)"
  shows "f integrable_on (S - T)"
  using has_integral_setdiff [OF assms]
  by (simp add: has_integral_iff)

lemma negligible_setdiff [simp]: " S ==> negligible (T - S)"
  by (metis Diff_eq_empty_iff negligible_empty)

lemma negligible_on_intervals: "negligible s  (a b. negligible(s  cbox a b))" (is "?l  ?r")
proof
  assume R: ?r
  show ?l
    unfolding negligible_def
    by (metis Diff_iff Int_iff R has_integral_negligible indicator_simps(2))
qed (simp add: negligible_Int)

lemma negligible_translation:
  assumes "negligible S"
    shows "negligible ((+) c ` S)"
proof -
  have inj: "inj ((+) c)"
    by simp
  show ?thesis
  using assms
  proof (clarsimp simp: negligible_def)
    fix a b
    assume "x y. (indicator S has_integral 0) (cbox x y)"
    then have *: "(indicator S has_integral 0) (cbox (a-c) (b-c))"
      by (meson Diff_iff assms has_integral_negligible indicator_simps(2))
    have eq: "indicator ((+) c ` S) = (λx. indicator S (x - c))"
      by (force simp: indicator_def)
    show "(indicator ((+) c ` S) has_integral 0) (cbox a b)"
      using has_integral_affinity [OF *, of 1 "-c"]
            cbox_translation [of "c" "-c+a" "-c+b"]
      by (simp add: eq) (simp add: ac_simps)
  qed
qed

lemma negligible_translation_rev:
  assumes "negligible ((+) c ` S)"
  shows "negligible S"
  by (metis negligible_translation [OF assms, of "-c"] translation_galois)

lemma negligible_atLeastAtMostI: " a ==> negligible {a..(b::real)}"
  using negligible_insert by fastforce

lemma has_integral_spike_set_eq:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "negligible {x  S - T. f x  0}" "negligible {x  T - S. f x  0}"
  shows "(f has_integral y) S  (f has_integral y) T"
proof -
  have "((λx. if x  S then f x else 0) has_integral y) UNIV =
        ((λx. if x  T then f x else 0) has_integral y) UNIV"
  proof (rule has_integral_spike_eq)
    show "negligible ({x  S - T. f x  0}  {x  T - S. f x  0})"
      by (rule negligible_Un [OF assms])
  qed auto
  then show ?thesis
    by (simp add: has_integral_restrict_UNIV)
qed

corollary integral_spike_set:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "negligible {x  S - T. f x  0}" "negligible {x  T - S. f x  0}"
  shows "integral S f = integral T f"
  using has_integral_spike_set_eq [OF assms]
  by (metis eq_integralD integral_unique)

lemma integrable_spike_set:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes f: "f integrable_on S" and neg: "negligible {x  S - T. f x  0}" "negligible {x  T - S. f x  0}"
  shows "f integrable_on T"
  using has_integral_spike_set_eq [OF neg] f by blast

lemma integrable_spike_set_eq:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "negligible ((S - T)  (T - S))"
  shows "f integrable_on S  f integrable_on T"
  by (blast intro: integrable_spike_set assms negligible_subset)

lemma integrable_on_insert_iff: "f integrable_on (insert x X)  f integrable_on X"
  for f::"==> 'a::banach"
  by (rule integrable_spike_set_eq) (auto simp: insert_Diff_if)

lemma has_integral_interior:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  shows "negligible(frontier S) ==> (f has_integral y) (interior S)  (f has_integral y) S"
proof (rule has_integral_spike_set_eq [OF empty_imp_negligible negligible_subset])
qed (use interior_subset in auto simp: frontier_def closure_def)

lemma has_integral_closure:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  shows "negligible(frontier S) ==> (f has_integral y) (closure S)  (f has_integral y) S"
proof (rule has_integral_spike_set_eq [OF negligible_subset empty_imp_negligible])
qed (auto simp: closure_Un_frontier )

lemma has_integral_open_interval:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  shows "(f has_integral y) (box a b)  (f has_integral y) (cbox a b)"
  unfolding interior_cbox [symmetric]
  by (metis frontier_cbox has_integral_interior negligible_frontier_interval)

lemma integrable_on_open_interval:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  shows "f integrable_on box a b  f integrable_on cbox a b"
  by (simp add: has_integral_open_interval integrable_on_def)

lemma integral_open_interval:
  fixes f :: "'a :: euclidean_space ==> 'b :: banach"
  shows "integral(box a b) f = integral(cbox a b) f"
  by (metis has_integral_integrable_integral has_integral_open_interval not_integrable_integral)

lemma integrable_on_open_interval_real:
  fixes f :: "real ==> 'b :: banach"
  shows "f integrable_on {a<..<b}  f integrable_on {a..b}"
  using integrable_on_open_interval[of f a b] by simp

lemma integral_open_interval_real:
  "integral {a..b} (f :: real ==> 'a :: banach) = integral {a<..<(b::real)} f"
  using integral_open_interval[of a b f] by simp

lemma has_integral_Icc_iff_Ioo:
  fixes f :: "real ==> 'a :: banach"
  shows "(f has_integral I) {a..b}  (f has_integral I) {a<..<b}"
  by (metis box_real(1) cbox_interval has_integral_open_interval)

lemma integrable_on_Icc_iff_Ioo:
  fixes f :: "real ==> 'a :: banach"
  shows "f integrable_on {a..b}  f integrable_on {a<..<b}"
  using has_integral_Icc_iff_Ioo by blast


subsection More lemmas that are useful later

lemma has_integral_subset_le:
  fixes f :: "'n::euclidean_space ==> real"
  assumes " t"
    and "(f has_integral i) s"
    and "(f has_integral j) t"
    and "xt. 0  f x"
  shows " j"
  using assms has_integral_subset_component_le[OF _ assms(1), of 1 f i j]
  by auto

lemma integral_subset_component_le:
  fixes f :: "'n::euclidean_space ==> 'm::euclidean_space"
  assumes " Basis"
    and " t"
    and "f integrable_on s"
    and "f integrable_on t"
    and " t. 0  f x  k"
  shows "(integral s f) (integral t f)k"
  by (meson assms has_integral_subset_component_le integrable_integral)

lemma integral_subset_le:
  fixes f :: "'n::euclidean_space ==> real"
  assumes " t"
    and "f integrable_on s"
    and "f integrable_on t"
    and " t. 0  f x"
  shows "integral s f  integral t f"
  using assms has_integral_subset_le by blast

lemma has_integral_alt':
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  shows "(f has_integral i) s  
          (a b. (λx. if x  s then f x else 0) integrable_on cbox a b) 
          (e>0. B>0. a b. ball 0 B  cbox a b 
            norm (integral (cbox a b) (λx. if x  s then f x else 0) - i) < e)"
  (is "?l = ?r")
proof
  assume rhs: ?r
  show ?l
  proof (subst has_integral', intro allI impI)
    fix e::real
    assume "e > 0"
    from rhs[THEN conjunct2,rule_format,OF this]
    show "B>0. a b. ball 0 B  cbox a b 
                   (z. ((λx. if x  s then f x else 0) has_integral z)
                         (cbox a b)  norm (z - i) < e)"
      by (simp add: has_integral_iff rhs)
  qed
next
  let ?Φ = "λe a b. z. ((λx. if x  s then f x else 0) has_integral z) (cbox a b)  norm (z - i) < e"
  assume ?l
  then have lhs: "B>0. a b. ball 0 B  cbox a b  ?Φ e a b" if "e > 0" for e
    using that has_integral'[of f] by auto
  let ?f = "λx. if x  s then f x else 0"
  show ?r
  proof (intro conjI allI impI)
    fix a b :: 'n
    from lhs[OF zero_less_one]
    obtain B where "0 < B" and B: "a b. ball 0 B  cbox a b ==> ?Φ 1 a b"
      by blast
    let ?a = "iBasis. min (ai) (-B) *🪙R i::'n"
    let ?b = "iBasis. max (bi) B *🪙R i::'n"
    show "?f integrable_on cbox a b"
    proof (rule integrable_subinterval[of _ ?a ?b])
      have "?a  i  x  i  x  i  ?b  i" if "norm (0 - x) < B" " Basis" for x i
        using Basis_le_norm[of i x] that by (auto simp:field_simps)
      then have "ball 0 B  cbox ?a ?b"
        by (auto simp: mem_box dist_norm)
      then show "?f integrable_on cbox ?a ?b"
        unfolding integrable_on_def using B by blast
      show "cbox a b  cbox ?a ?b"
        by (force simp: mem_box)
    qed
    fix e :: real
    assume "e > 0"
    with lhs show "B>0. a b. ball 0 B  cbox a b 
      norm (integral (cbox a b) (λx. if x  s then f x else 0) - i) < e"
      by (metis (no_types, lifting) has_integral_integrable_integral)
  qed
qed


subsection Continuity of the integral (for a 1-dimensional interval)

lemma integrable_alt:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  shows "f integrable_on s 
    (a b. (λx. if x  s then f x else 0) integrable_on cbox a b) 
    (e>0. B>0. a b c d. ball 0 B  cbox a b  ball 0 B  cbox c d 
    norm (integral (cbox a b) (λx. if x  s then f x else 0) -
      integral (cbox c d)  (λx. if x  s then f x else 0)) < e)"
  (is "?l = ?r")
proof
  let ?F = "λx. if x  s then f x else 0"
  assume ?l
  then obtain y where intF: "a b. ?F integrable_on cbox a b"
          and y: "e. 0 < e ==>
              B>0. a b. ball 0 B  cbox a b  norm (integral (cbox a b) ?F - y) < e"
    unfolding integrable_on_def has_integral_alt'[of f] by auto
  show ?r
  proof (intro conjI allI impI intF)
    fix e::real
    assume "e > 0"
    then have "e/2 > 0"
      by auto
    obtain B where "0 < B"
       and B: "a b. ball 0 B  cbox a b ==> norm (integral (cbox a b) ?F - y) < e/2"
      using 0 < e/2 y by blast
    show "B>0. a b c d. ball 0 B  cbox a b  ball 0 B  cbox c d 
                  norm (integral (cbox a b) ?F - integral (cbox c d) ?F) < e"
    proof (intro conjI exI impI allI, rule 0 < B)
      fix a b c d::'n
      assume sub: "ball 0 B  cbox a b  ball 0 B  cbox c d"
      show "norm (integral (cbox a b) ?F - integral (cbox c d) ?F) < e"
        using sub by (auto intro: norm_triangle_half_l dest: B)
    qed
  qed
next
  let ?F = "λx. if x  s then f x else 0"
  assume rhs: ?r
  let ?cube = "λn. cbox (iBasis. - real n *🪙R i::'n) (iBasis. real n *🪙R i)"
  have "Cauchy (λn. integral (?cube n) ?F)"
    unfolding Cauchy_def
  proof (intro allI impI)
    fix e::real
    assume "e > 0"
    with rhs obtain B where "0 < B"
      and B: "a b c d. ball 0 B  cbox a b  ball 0 B  cbox c d 
                        ==> norm (integral (cbox a b) ?F - integral (cbox c d) ?F) < e"
      by blast
    obtain N where N: " real N"
      using real_arch_simple by blast
    have "ball 0 B  ?cube n" if n: " N" for n
    proof -
      have "sum ((*\<^sub>R) (- real n)) Basis \<bullet> i \<le> x \<bullet> i \<and>
  x i sum ((*🪙R) (real n)) Basis i"
  if "norm x 🚫" "i Basis" for x i::'n
  using Basis_le_norm[of i x] n N that by (auto simp: field_simps sum_negf)
  then show ?thesis
  by (auto simp: mem_box dist_norm)
  qed
  then show "M. mM. nM. dist (integral (?cube m) ?F) (integral (?cube n) ?F) 🚫"
  by (fastforce simp: dist_norm intro!: B)
  qed
  then obtain i where i: "(λn. integral (?cube n) ?F) <---- i"
  using convergent_eq_Cauchy by blast
  have "B>0. a b. ball 0 B cbox a b norm (integral (cbox a b) ?F - i) 🚫"
  if "e > 0" for e
  proof -
  have *: "e/2 > 0" using that by auto
  then obtain N where N: "n. N n ==> norm (i - integral (?cube n) ?F) 🚫/2"
  using i[THEN LIMSEQ_D, simplified norm_minus_commute] by meson
  obtain B where "0 🚫"
  and B: "a b c d. [ball 0 B cbox a b; ball 0 B cbox c d] ==>
  norm (integral (cbox a b) ?F - integral (cbox c d) ?F) 🚫/2"
  using rhs * by meson
  let ?B = "max (real N) B"
  show ?thesis
  proof (intro exI conjI allI impI)
  show "0 🚫B"
  using B > 0 by auto
  fix a b :: 'n
  assume "ball 0 ?B cbox a b"
  moreover obtain n where n: "max (real N) B real n"
  using real_arch_simple by blast
  moreover have "ball 0 B ?cube n"
  proof
  fix x :: 'n
  assume x: "x ball 0 B"
  have "[norm (0 - x) 🚫; i Basis]
  ==> sum ((*🪙R) (-n)) Basis i x i x i sum ((*🪙R) n) Basis i" for i
  using Basis_le_norm[of i x] n by (auto simp: field_simps sum_negf)
  then show "x ?cube n"
  using x by (auto simp: mem_box dist_norm)
  qed
  ultimately show "norm (integral (cbox a b) ?F - i) 🚫"
  using norm_triangle_half_l [OF B N] by force
  qed
  qed
  then show ?l unfolding integrable_on_def has_integral_alt'[of f]
  using rhs by blast
 qed
 
 lemma integrable_altD:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "f integrable_on s"
  shows "a b. (λx. if x s then f x else 0) integrable_on cbox a b"
  and "e. e > 0 ==> B>0. a b c d. ball 0 B cbox a b ball 0 B cbox c d
  norm (integral (cbox a b) (λx. if x s then f x else 0) - integral (cbox c d) (λx. if x s then f x else 0)) 🚫"
  using assms[unfolded integrable_alt[of f]] by auto
 
 lemma integrable_alt_subset:
  fixes f :: "'a::euclidean_space ==> 'b::banach"
  shows
  "f integrable_on S
  (a b. (λx. if x S then f x else 0) integrable_on cbox a b)
  (e>0. B>0. a b c d.
  ball 0 B cbox a b cbox a b cbox c d
  norm(integral (cbox a b) (λx. if x S then f x else 0) -
  integral (cbox c d) (λx. if x S then f x else 0)) 🚫)"
  (is "_ = ?rhs")
 proof -
  let ?g = "λx. if x S then f x else 0"
  have "f integrable_on S
  (a b. ?g integrable_on cbox a b)
  (e>0. B>0. a b c d. ball 0 B cbox a b ball 0 B cbox c d
  norm (integral (cbox a b) ?g - integral (cbox c d) ?g) 🚫)"
  by (rule integrable_alt)
  also have " = ?rhs"
  proof -
  { fix e :: "real"
  assume e: "e. e>0 ==> B>0. a b c d. ball 0 B cbox a b cbox a b cbox c d
  norm (integral (cbox a b) ?g - integral (cbox c d) ?g) 🚫"
  and "e > 0"
  obtain B where "B > 0"
  and B: "a b c d. [ball 0 B cbox a b; cbox a b cbox c d] ==>
  norm (integral (cbox a b) ?g - integral (cbox c d) ?g) 🚫/2"
  using e > 0 e [of "e/2"] by force
  have "B>0. a b c d.
  ball 0 B cbox a b ball 0 B cbox c d
  norm (integral (cbox a b) ?g - integral (cbox c d) ?g) 🚫"
  proof (intro exI allI conjI impI)
  fix a b c d :: "'a"
  let ?α = "iBasis. max (a i) (c i) *🪙R i"
  let ?β = "iBasis. min (b i) (d i) *🪙R i"
  show "norm (integral (cbox a b) ?g - integral (cbox c d) ?g) 🚫"
  if ball: "ball 0 B cbox a b ball 0 B cbox c d"
  proof -
  have B': "norm (integral (cbox a b cbox c d) ?g - integral (cbox x y) ?g) 🚫/2"
  if "cbox a b cbox c d cbox x y" for x y
  using B [of ?α ?β x y] ball that by (simp add: Int_interval [symmetric])
  show ?thesis
  using B' [of a b] B' [of c d] norm_triangle_half_r by blast
  qed
  qed (use B > 0 in auto)}
  then show ?thesis
  by force
  qed
  finally show ?thesis .
 qed
 
 lemma integrable_on_subcbox:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes intf: "f integrable_on S"
  and sub: "cbox a b S"
  shows "f integrable_on cbox a b"
 proof -
  have "(λx. if x S then f x else 0) integrable_on cbox a b"
  by (simp add: intf integrable_altD(1))
 then show ?thesis
  by (simp add: inf.absorb2 integrable_restrict_Int sub)
 qed
 
 
 subsection A straddling criterion for integrability
 
 lemma integrable_straddle_interval:
  fixes f :: "'n::euclidean_space ==> real"
  assumes "e. e>0 ==> g h i j. (g has_integral i) (cbox a b) (h has_integral j) (cbox a b)
  i - j 🚫 (xcbox a b. (g x) f x f x h x)"
  shows "f integrable_on cbox a b"
 proof -
  have "d. gauge d
  (p1 p2. p1 tagged_division_of cbox a b d fine p1
  p2 tagged_division_of cbox a b d fine p2
  ((x,K)p1. content K *🪙R f x) - ((x,K)p2. content K *??R f x) 🚫)"
  if "e > 0" for e
  proof -
  have e: "e/3 > 0"
  using that by auto
  then obtain g h i j where ij: "i - j 🚫/3"
  and "(g has_integral i) (cbox a b)"
  and "(h has_integral j) (cbox a b)"
  and fgh: "x. x cbox a b ==> g x f x f x h x"
  using assms real_norm_def by metis
  then obtain d1 d2 where "gauge d1" "gauge d2"
  and d1: "p. [p tagged_division_of cbox a b; d1 fine p] ==>
  ((x,K)p. content K *🪙R g x) - i 🚫/3"
  and d2: "p. [p tagged_division_of cbox a b; d2 fine p] ==>
  ((x,K) p. content K *🪙R h x) - j 🚫/3"
  by (metis e has_integral real_norm_def)
  have "((x,K) p1. content K *🪙R f x) - ((x,K) p2. content K *🪙R f x) 🚫"
  if p1: "p1 tagged_division_of cbox a b" and 11: "d1 fine p1" and 21: "d2 fine p1"
  and p2: "p2 tagged_division_of cbox a b" and 12: "d1 fine p2" and 22: "d2 fine p2" for p1 p2
  proof -
  have *: "g1 g2 h1 h2 f1 f2.
  [g2 - i 🚫/3; g1 - i 🚫/3; h2 - j 🚫/3; h1 - j 🚫/3;
  g1 - h2 f1 - f2; f1 - f2 h1 - g2]
  ==> f1 - f2 🚫"
  using e > 0 ij by arith
  have 0: "((x, k)p1. content k *🪙R f x) - ((x, k)p1. content k *🪙R g x) 0"
  "0 ((x, k)p2. content k *🪙R h x) - ((x, k)p2. content k *🪙R f x)"
  "((x, k)p2. content k *🪙R f x) - ((x, k)p2. content k *🪙R g x) 0"
  "0 ((x, k)p1. content k *🪙R h x) - ((x, k)p1. content k *🪙R f x)"
  unfolding sum_subtractf[symmetric]
  apply (auto intro!: sum_nonneg)
  apply (meson fgh measure_nonneg mult_left_mono tag_in_interval that sum_nonneg)+
  done
  show ?thesis
      proof (rule *)
        show "((x,K) p2. content K *🪙R g x) - i < e/3"
          by (rule d1[OF p2 12])
        show "((x,K) p1. content K *🪙R g x) - i < e/3"
          by (rule d1[OF p1 11])
        show "((x,K) p2. content K *🪙R h x) - j < e/3"
          by (rule d2[OF p2 22])
        show "((x,K) p1. content K *🪙R h x) - j < e/3"
          by (rule d2[OF p1 21])
      qed (use 0 in auto)
    qed
    then show ?thesis
      by (rule_tac x="λx. d1 x d2 x" in exI)
        (auto simp: fine_Int intro: gauge d1 gauge d2 d1 d2)
  qed
  then show ?thesis
    by (simp add: integrable_Cauchy)
qed

lemma integrable_straddle:
  fixes f :: "'n::euclidean_space ==> real"
  assumes "e. e>0 ==> g h i j. (g has_integral i) s (h has_integral j) s
                     i - j < e (xs. g x f x f x h x)"
  shows "f integrable_on s"
proof -
  let ?fs = "(λx. if x s then f x else 0)"
  have "?fs integrable_on cbox a b" for a b
  proof (rule integrable_straddle_interval)
    fix e::real
    assume "e > 0"
    then have *: "e/4 > 0"
      by auto
    with assms obtain g h i j where g: "(g has_integral i) s" and h: "(h has_integral j) s"
                 and ij: "i - j < e/4"
                 and fgh: "x. x s ==> g x f x f x h x"
      by metis
    let ?gs = "(λx. if x s then g x else 0)"
    let ?hs = "(λx. if x s then h x else 0)"
    obtain Bg where Bg: "a b. ball 0 Bg cbox a b ==> integral (cbox a b) ?gs - i < e/4"
              and int_g: "a b. ?gs integrable_on cbox a b"
      using g * unfolding has_integral_alt' real_norm_def by meson
    obtain Bh where
          Bh: "a b. ball 0 Bh cbox a b ==> integral (cbox a b) ?hs - j < e/4"
         and int_h: "a b. ?hs integrable_on cbox a b"
      using h * unfolding has_integral_alt' real_norm_def by meson
    define c where "c = (iBasis. min (ai) (- (max Bg Bh)) *🪙R i)"
    define d where "d = (iBasis. max (bi) (max Bg Bh) *🪙R i)"
    have "[norm (0 - x) < Bg; i Basis] ==> c i x i x i d i" for x i
      using Basis_le_norm[of i x] unfolding c_def d_def by auto
    then have ballBg: "ball 0 Bg cbox c d"
      by (auto simp: mem_box dist_norm)
    have "[norm (0 - x) < Bh; i Basis] ==> c i x i x i d i" for x i
      using Basis_le_norm[of i x] unfolding c_def d_def by auto
    then have ballBh: "ball 0 Bh cbox c d"
      by (auto simp: mem_box dist_norm)
    have ab_cd: "cbox a b cbox c d"
      by (auto simp: c_def d_def subset_box_imp)
    have **: "ch cg ag ah::real. [ah - ag ch - cg; cg - i < e/4; ch - j < e/4]
       ==> ag - ah < e"
      using ij by arith
    show "g h i j. (g has_integral i) (cbox a b) (h has_integral j) (cbox a b) i - j < e
          (xcbox a b. g x (if x s then f x else 0)
                        (if x s then f x else 0) h x)"
    proof (intro exI ballI conjI)
      have eq: "x f g. (if x s then f x else 0) - (if x s then g x else 0) =
                       (if x s then f x - g x else (0::real))"
        by auto
      have int_hg: "(λx. if x s then h x - g x else 0) integrable_on cbox a b"
                   "(λx. if x s then h x - g x else 0) integrable_on cbox c d"
        by (metis (no_types) integrable_diff g h has_integral_integrable integrable_altD(1))+
      show "(?gs has_integral integral (cbox a b) ?gs) (cbox a b)"
           "(?hs has_integral integral (cbox a b) ?hs) (cbox a b)"
        by (intro integrable_integral int_g int_h)+
      then have "integral (cbox a b) ?gs integral (cbox a b) ?hs"
        using fgh by (force intro: has_integral_le)
      then have "0 integral (cbox a b) ?hs - integral (cbox a b) ?gs"
        by simp
      then have "integral (cbox a b) ?hs - integral (cbox a b) ?gs
               integral (cbox c d) ?hs - integral (cbox c d) ?gs"
        apply (simp add: integral_diff [symmetric] int_g int_h)
        apply (subst abs_of_nonneg[OF integral_nonneg[OF integrable_diff, OF int_h int_g]])
        using fgh apply (force simp: eq intro!: integral_subset_le [OF ab_cd int_hg])+
        done
      then show "integral (cbox a b) ?gs - integral (cbox a b) ?hs < e"
        using ** Bg ballBg Bh ballBh by blast
      show "x. x cbox a b ==> ?gs x ?fs x" "x. x cbox a b ==> ?fs x ?hs x"
        using fgh by auto
    qed
  qed
  then have int_f: "?fs integrable_on cbox a b" for a b
    by simp
  have "B>0. a b c d.
                  ball 0 B cbox a b ball 0 B cbox c d
                  abs (integral (cbox a b) ?fs - integral (cbox c d) ?fs) < e"
      if "0 < e" for e
  proof -
    have *: "e/3 > 0"
      using that by auto
    with assms obtain g h i j where g: "(g has_integral i) s" and h: "(h has_integral j) s"
                 and ij: "i - j < e/3"
                 and fgh: "x. x s ==> g x f x f x h x"
      by metis
    let ?gs = "(λx. if x s then g x else 0)"
    let ?hs = "(λx. if x s then h x else 0)"
    obtain Bg where "Bg > 0"
              and Bg: "a b. ball 0 Bg cbox a b ==> integral (cbox a b) ?gs - i < e/3"
              and int_g: "a b. ?gs integrable_on cbox a b"
      using g * unfolding has_integral_alt' real_norm_def by meson
    obtain Bh where "Bh > 0"
              and Bh: "a b. ball 0 Bh cbox a b ==> integral (cbox a b) ?hs - j < e/3"
              and int_h: "a b. ?hs integrable_on cbox a b"
      using h * unfolding has_integral_alt' real_norm_def by meson
    { fix a b c d :: 'n
      assume as: "ball 0 (max Bg Bh) cbox a b" "ball 0 (max Bg Bh) cbox c d"
      have **: "ball 0 Bg ball (0::'n) (max Bg Bh)" "ball 0 Bh ball (0::'n) (max Bg Bh)"
        by auto
      have *: "ga gc ha hc fa fc. [ga - i < e/3; gc - i < e/3; ha - j < e/3;
                     hc - j < e/3; ga fa; fa ha; gc fc; fc hc] ==>
        fa - fc < e"
        using ij by arith
      have "abs (integral (cbox a b) (λx. if x s then f x else 0) - integral (cbox c d)
        (λx. if x s then f x else 0)) < e"
      proof (rule *)
        show "integral (cbox a b) ?gs - i < e/3"
          using "**" Bg as by blast
        show "integral (cbox c d) ?gs - i < e/3"
          using "**" Bg as by blast
        show "integral (cbox a b) ?hs - j < e/3"
          using "**" Bh as by blast
        show "integral (cbox c d) ?hs - j < e/3"
          using "**" Bh as by blast
      qed (use int_f int_g int_h fgh in simp_all add: integral_le)
    }
    then show ?thesis
      by (meson 0 🚫 linorder_not_less max.bounded_iff)
  qed
  then show ?thesis
    unfolding integrable_alt[of f] real_norm_def by (blast intro: int_f)
qed


subsection Adding integrals over several sets

lemma has_integral_Un:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes f: "(f has_integral i) S" "(f has_integral j) T"
    and neg: "negligible (S T)"
  shows "(f has_integral (i + j)) (S T)"
  unfolding has_integral_restrict_UNIV[symmetric, of f]
proof (rule has_integral_spike[OF neg])
  let ?f = "λx. (if x S then f x else 0) + (if x T then f x else 0)"
  show "(?f has_integral i + j) UNIV"
    by (simp add: f has_integral_add)
qed auto

lemma integral_Un [simp]:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "f integrable_on S" "f integrable_on T" "negligible (S T)"
  shows "integral (S T) f = integral S f + integral T f"
  by (simp add: has_integral_Un assms integrable_integral integral_unique)

lemma integrable_Un:
  fixes f :: "'a::euclidean_space ==> 'b :: banach"
  assumes "negligible (A B)" "f integrable_on A" "f integrable_on B"
  shows   "f integrable_on (A B)"
proof -
  from assms obtain y z where "(f has_integral y) A" "(f has_integral z) B"
     by (auto simp: integrable_on_def)
  from has_integral_Un[OF this assms(1)] show ?thesis by (auto simp: integrable_on_def)
qed

lemma integrable_Un':
  fixes f :: "'a::euclidean_space ==> 'b :: banach"
  assumes "f integrable_on A" "f integrable_on B" "negligible (A B)" "C = A B"
  shows   "f integrable_on C"
  by (simp add: assms integrable_Un set_zero)

lemma has_integral_UN:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "finite I"
    and int: "i. i I ==> (f has_integral (g i)) (T i)"
    and neg: "pairwise (λi i'. negligible (T i T i')) I"
  shows "(f has_integral (sum g I)) (iI. T i)"
proof -
  let ?U = "((λ(a,b). T a T b) ` {(a,b). a I b I-{a}})"
  have "((λx. if x (iI. T i) then f x else 0) has_integral sum g I) UNIV"
  proof (rule has_integral_spike)
    show "negligible (?U)"
    proof (rule negligible_Union)
      have "finite (I × I)"
        by (simp add: finite I)
      moreover have "{(a,b). a I b I-{a}} I × I"
        by auto
      ultimately show "finite ?U"
        by (simp add: finite_subset)
      show "t. t ?U ==> negligible t"
        using neg unfolding pairwise_def by auto
    qed
  next
    show "(if x (iI. T i) then f x else 0) = (iI. if x T i then f x else 0)"
      if "x UNIV - (?U)" for x
    proof clarsimp
      fix i assume i: "i I" "x T i"
      then have "jI. x T j j = i"
        using that by blast
      with i show "f x = (iI. if x T i then f x else 0)"
        by (simp add: sum.delta[OF finite I])
    qed
  next
    show "((λx. (iI. if x T i then f x else 0)) has_integral sum g I) UNIV"
      using int by (simp add: has_integral_restrict_UNIV has_integral_sum [OF finite I])
  qed
  then show ?thesis
    using has_integral_restrict_UNIV by blast
qed

lemma has_integral_Union:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "finite T"
    and "S. S T ==> (f has_integral (i S)) S"
    and "pairwise (λS S'. negligible (S S')) T"
  shows "(f has_integral (sum i T)) (T)"
proof -
  have "(f has_integral (sum i T)) (ST. S)"
    by (intro has_integral_UN assms)
  then show ?thesis
    by force
qed

text In particular adding integrals over a division, maybe not of an interval.

lemma has_integral_combine_division:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "D division_of S"
    and "k. k D ==> (f has_integral (i k)) k"
  shows "(f has_integral (sum i D)) S"
proof -
  note D = division_ofD[OF assms(1)]
  have neg: "negligible (S s')" if "S D" "s' D" "S s'" for S s'
  proof -
    obtain a c b D where obt: "S = cbox a b" "s' = cbox c D"
      by (meson S D s' D D(4))
    from D(5)[OF that] show ?thesis
      unfolding obt interior_cbox
      by (metis (lifting) Diff_empty Int_interval box_Int_box negligible_frontier_interval)
  qed
  show ?thesis
    unfolding D(6)[symmetric]
    by (auto intro: D neg assms has_integral_Union pairwiseI)
qed

lemma integral_combine_division_bottomup:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "D division_of S" "k. k D ==> f integrable_on k"
  shows "integral S f = sum (λi. integral i f) D"
  by (meson assms integral_unique has_integral_combine_division has_integral_integrable_integral)

lemma has_integral_combine_division_topdown:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes f: "f integrable_on S"
    and D"D division_of K"
    and "K S"
  shows "(f has_integral (sum (λi. integral i f) D)) K"
proof -
  have "f integrable_on L" if "L D" for L
    by (smt (verit, best) assms cbox_division_memE f integrable_on_subcbox subset_trans that)
  then show ?thesis
    by (meson D has_integral_combine_division has_integral_integrable_integral)
qed

lemma integral_combine_division_topdown:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "f integrable_on S"
    and "D division_of S"
  shows "integral S f = sum (λi. integral i f) D"
  using assms has_integral_combine_division_topdown by blast

lemma integrable_combine_division:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes D"D division_of S"
    and f: "i. i D ==> f integrable_on i"
  shows "f integrable_on S"
  using f unfolding integrable_on_def by (metis has_integral_combine_division[OF D])

lemma integrable_on_subdivision:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes D"D division_of i"
    and f: "f integrable_on S"
    and "i S"
  shows "f integrable_on i"
proof -
  have "f integrable_on j" if "j D" for j
    using assms integrable_on_def that
    by (metis cbox_division_memE elementary_interval has_integral_combine_division_topdown)
  then show ?thesis
    using D integrable_combine_division by blast
qed


subsection Also tagged divisions

lemma has_integral_combine_tagged_division:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "p tagged_division_of S"
    and "x k. (x,k) p ==> (f has_integral (i k)) k"
  shows "(f has_integral ((x,k)p. i k)) S"
proof -
  have *: "(f has_integral (ksnd`p. integral k f)) S"
    by (smt (verit, del_insts) assms division_of_tagged_division has_integral_combine_division has_integral_iff imageE prod.collapse)
  also have "(ksnd`p. integral k f) = ((x, k)p. integral k f)"
    by (metis assms(1) eq_integralD has_integral_empty_eq has_integral_open_interval
        sum.over_tagged_division_lemma)
  finally show ?thesis
    using assms by (auto simp: has_integral_iff intro!: sum.cong)
qed

lemma integral_combine_tagged_division_bottomup:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes p: "p tagged_division_of (cbox a b)"
    and f: "x k. (x,k)p ==> f integrable_on k"
  shows "integral (cbox a b) f = sum (λ(x,k). integral k f) p"
  by (simp add: has_integral_combine_tagged_division[OF p] integral_unique f integrable_integral)

lemma has_integral_combine_tagged_division_topdown:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes f: "f integrable_on cbox a b"
    and p: "p tagged_division_of (cbox a b)"
  shows "(f has_integral (sum (λ(x,K). integral K f) p)) (cbox a b)"
proof -
  have "(f has_integral integral K f) K" if "(x,K) p" for x K
    by (metis assms integrable_integral integrable_on_subcbox tagged_division_ofD(3,4) that)
  then show ?thesis
    by (simp add: has_integral_combine_tagged_division p)
qed

lemma integral_combine_tagged_division_topdown:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes "f integrable_on cbox a b"
    and "p tagged_division_of (cbox a b)"
  shows "integral (cbox a b) f = ((x, k)p. integral k f)"
  using assms by (auto intro: integral_unique [OF has_integral_combine_tagged_division_topdown])


subsection Henstock's lemma

lemma Henstock_lemma_part1:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes intf: "f integrable_on cbox a b"
    and "e > 0"
    and "gauge d"
    and less_e: "p. [p tagged_division_of (cbox a b); d fine p] ==>
                     norm (sum (λ(x,K). content K *🪙R f x) p - integral(cbox a b) f) < e"
    and p: "p tagged_partial_division_of (cbox a b)" "d fine p"
  shows "norm (sum (λ(x,K). content K *🪙R f x - integral K f) p) e" (is "?lhs e")
proof (rule field_le_epsilon)
  fix k :: real
  assume "k > 0"
  let ?SUM = "λp. ((x,K) p. content K *🪙R f x)"
  note p' = tagged_partial_division_ofD[OF p(1)]
  have "(snd ` p) cbox a b"
    using p'(3) by fastforce
  then obtain q where q: "snd ` p q" and qdiv: "q division_of cbox a b"
    by (meson p(1) partial_division_extend_interval partial_division_of_tagged_division)
  note q' = division_ofD[OF qdiv]
  define r where "r = q - snd ` p"
  have "snd ` p r = {}"
    unfolding r_def by auto
  have "finite r"
    using q' unfolding r_def by auto
  have "p. p tagged_division_of i d fine p
        norm (?SUM p - integral i f) < k / (real (card r) + 1)"
    if "ir" for i
  proof -
    have gt0: "k / (real (card r) + 1) > 0" using k > 0 by simp
    have i: "i q"
      using that unfolding r_def by auto
    then obtain u v where uv: "i = cbox u v"
      using q'(4) by blast
    then have "cbox u v cbox a b"
      using i q'(2) by auto  
    then have "f integrable_on cbox u v"
      by (rule integrable_subinterval[OF intf])
    with integrable_integral[OF this, unfolded has_integral[of f]]
    obtain dd where "gauge dd" and dd:
      "D. [D tagged_division_of cbox u v; dd fine D] ==>
    norm (?SUM D - integral (cbox u v) f) < k / (real (card r) + 1)"
      using gt0 by auto
    with gauge_Int[OF gauge d gauge dd]
    obtain qq where qq: "qq tagged_division_of cbox u v" "(λx. d x dd x) fine qq"
      using fine_division_exists by blast
    with dd[of qq]  show ?thesis
      by (auto simp: fine_Int uv)
  qed
  then obtain qq where qq: "i. i r ==> qq i tagged_division_of i
      d fine qq i norm (?SUM (qq i) - integral i f) < k / (real (card r) + 1)"
    by metis

  let ?p = "p (qq ` r)"
  have "norm (?SUM ?p - integral (cbox a b) f) < e"
  proof (rule less_e)
    show "d fine ?p"
      by (metis (mono_tags, opaque_lifting) qq fine_Un fine_Union imageE p(2))
    note ptag = tagged_partial_division_of_Union_self[OF p(1)]
    have "p (qq ` r) tagged_division_of (snd ` p) r"
    proof (rule tagged_division_Un[OF ptag tagged_division_Union [OF finite r]])
      show "i. i r ==> qq i tagged_division_of i"
        using qq by auto
      show "i1 i2. [i1 r; i2 r; i1 i2] ==> interior i1 interior i2 = {}"
        by (simp add: q'(5) r_def)
      show "interior ((snd ` p)) interior (r) = {}"
      proof (rule Int_interior_Union_intervals [OF finite r])
        show "open (interior ((snd ` p)))"
          by blast
        show "T. T r ==> a b. T = cbox a b"
          by (simp add: q'(4) r_def)
        have "interior T interior ((snd ` p)) = {}" if "T r" for T
        proof (rule Int_interior_Union_intervals)
          show "U. U snd ` p ==> a b. U = cbox a b"
            using q q'(4) by blast
          show "U. U snd ` p ==> interior T interior U = {}"
            by (metis DiffE q q'(5) r_def subsetD that)
        qed (use p' in auto)
        then show "T. T r ==> interior ((snd ` p)) interior T = {}"
          by (metis Int_commute)
      qed
    qed
    moreover have "(snd ` p) r = cbox a b" and "{qq i |i. i r} = qq ` r"
      using qdiv q unfolding Union_Un_distrib[symmetric] r_def by auto
    ultimately show "?p tagged_division_of (cbox a b)"
      by fastforce
  qed
  then have "norm (?SUM p + (?SUM ((qq ` r))) - integral (cbox a b) f) < e"
  proof (subst sum.union_inter_neutral[symmetric, OF finite p], safe)
    show "content L *🪙R f x = 0" if "(x, L) p" "(x, L) qq K" "K r" for x K L 
    proof -
      obtain u v where uv: "L = cbox u v"
        using (x,L) p p'(4) by blast
      have "L K"
        using  qq[OF that(3)] tagged_division_ofD(3) (x,L) qq K by metis
      have "L snd ` p" 
        using (x,L) p image_iff by fastforce 
      then have "L q" "K q" "L K"
        using that q(1) unfolding r_def by auto
      with q'(5) show "content L *🪙R f x = 0"
        by (metis L K content_eq_0_interior inf.orderE interior_Int scaleR_eq_0_iff uv)
    qed
    show "finite ((qq ` r))"
      by (meson finite_UN qq finite r tagged_division_of_finite)
  qed
  moreover have "content M *🪙R f x = 0" 
      if x: "(x,M) qq K" "(x,M) qq L" and KL: "qq K qq L" and r: "K r" "L r"
    for x M K L
  proof -
    note kl = tagged_division_ofD(3,4)[OF qq[THEN conjunct1]]
    obtain u v where uv: "M = cbox u v"
      using (x, M) qq L L r kl(2) by blast
    have empty: "interior (K L) = {}"
      by (metis DiffD1 interior_Int q'(5) r_def KL r)
    with that kl show "content M *🪙R f x = 0"
      by (metis content_eq_0_interior dual_order.refl inf.orderE inf_mono interior_mono 
                scaleR_eq_0_iff subset_empty uv x)
  qed 
  ultimately have "norm (?SUM p + sum ?SUM (qq ` r) - integral (cbox a b) f) < e"
    apply (subst (asm) sum.Union_comp)
    using qq by (force simp: split_paired_all)+
  moreover have "content M *🪙R f x = 0" 
       if "K r" "L r" "K L" "qq K = qq L" "(x, M) qq K" for K L x M
    using tagged_division_ofD(6) qq that by (metis (no_types, lifting)) 
  ultimately have less_e: "norm (?SUM p + sum (?SUM qq) r - integral (cbox a b) f) < e"
  proof (subst (asm) sum.reindex_nontrivial [OF finite r])
    qed (auto simp: split_paired_all sum.neutral)
  have norm_le: "norm (cp - ip) e + k"
                  if "norm ((cp + cr) - i) < e" "norm (cr - ir) < k" "ip + ir = i"
                  for ir ip i cr cp::'a
    using norm_triangle_le[of "cp + cr - i" "- (cr - ir)"] that
    unfolding that(3)[symmetric] norm_minus_cancel
    by (auto simp: algebra_simps)

  have "?lhs = norm (?SUM p - ((x, k)p. integral k f))"
    unfolding split_def sum_subtractf ..
  also have " e + k"
  proof (rule norm_le[OF less_e])
    have lessk: "k * real (card r) / (1 + real (card r)) < k"
      using k>0 by (auto simp: field_simps)
    have "norm (sum (?SUM qq) r - (kr. integral k f)) (xr. k / (real (card r) + 1))"
      unfolding sum_subtractf[symmetric] by (force dest: qq intro!: sum_norm_le)
    also have " < k"
      by (simp add: lessk add.commute mult.commute)
    finally show "norm (sum (?SUM qq) r - (kr. integral k f)) < k" .
  next
    from q(1) have [simp]: "snd ` p q = q" by auto
    have "integral l f = 0"
      if inp: "(x, l) p" "(y, m) p" and ne: "(x, l) (y, m)" and "l = m" for x l y m
    proof -
      obtain u v where uv: "l = cbox u v"
        using inp p'(4) by blast
      then show ?thesis
        using uv that p
        by (metis content_eq_0_interior inf.orderE integral_null p'(5) subset_refl)
    qed
    then have "((x, K)p. integral K f) = (Ksnd ` p. integral K f)"
      apply (subst sum.reindex_nontrivial [OF finite p])
      unfolding split_paired_all split_def by auto
    then show "((x, k)p. integral k f) + (kr. integral k f) = integral (cbox a b) f"
      unfolding integral_combine_division_topdown[OF intf qdiv] r_def
      by (metis add.commute q q'(1) sum.subset_diff)
  qed
  finally show "?lhs e + k" .
qed

lemma Henstock_lemma_part2:
  fixes f :: "'m::euclidean_space ==> 'n::euclidean_space"
  assumes fed: "f integrable_on cbox a b" "e > 0" "gauge d"
    and less_e: "D. [D tagged_division_of (cbox a b); d fine D] ==>
                     norm (sum (λ(x,k). content k *🪙R f x) D - integral (cbox a b) f) < e"
    and tag: "p tagged_partial_division_of (cbox a b)"
    and "d fine p"
  shows "sum (λ(x,k). norm (content k *🪙R f x - integral k f)) p 2 * real (DIM('n)) * e"
proof -
  have "finite p"
    using tag tagged_partial_division_ofD by blast
  then show ?thesis
    unfolding split_def
  proof (rule sum_norm_allsubsets_bound)
    fix Q
    assume Q: "Q p"
    then have fine: "d fine Q"
      by (simp add: d fine p fine_subset)
    show "norm (xQ. content (snd x) *🪙R f (fst x) - integral (snd x) f) e"
      apply (rule Henstock_lemma_part1[OF fed less_e, unfolded split_def])
      using Q tag tagged_partial_division_subset by (force simp: fine)+
  qed
qed

lemma Henstock_lemma:
  fixes f :: "'m::euclidean_space ==> 'n::euclidean_space"
  assumes intf: "f integrable_on cbox a b"
    and "e > 0"
  obtains γ where "gauge γ"
    and "p. [p tagged_partial_division_of (cbox a b); γ fine p] ==>
             sum (λ(x,k). norm(content k *🪙R f x - integral k f)) p < e"
proof -
  have *: "e/(2 * (real DIM('n) + 1)) > 0" using e > 0 by simp
  with integrable_integral[OF intf, unfolded has_integral]
  obtain γ where "gauge γ"
    and γ: "D. [D tagged_division_of cbox a b; γ fine D] ==>
         norm (((x,K)D. content K *🪙R f x) - integral (cbox a b) f)
         < e/(2 * (real DIM('n) + 1))"
    by metis
  show thesis
  proof (rule that [OF gauge γ])
    fix p
    assume p: "p tagged_partial_division_of cbox a b" "γ fine p"
    have "((x,K)p. norm (content K *🪙R f x - integral K f))
           2 * real DIM('n) * (e/(2 * (real DIM('n) + 1)))"
      using Henstock_lemma_part2[OF intf * gauge γ γ p] by metis
    also have " < e"
      using e > 0 by (auto simp: field_simps)
    finally
    show "((x,K)p. norm (content K *🪙R f x - integral K f)) < e" .
  qed
qed


subsection Monotone convergence (bounded interval first)

lemma bounded_increasing_convergent:
  fixes f :: "nat ==> real"
  shows "[bounded (range f); n. f n f (Suc n)] ==> l. f <---- l"
  using Bseq_mono_convergent[of f] incseq_Suc_iff[of f]
  by (auto simp: image_def Bseq_eq_bounded convergent_def incseq_def)

lemma monotone_convergence_interval:
  fixes f :: "nat ==> 'n::euclidean_space ==> real"
  assumes intf: "k. (f k) integrable_on cbox a b"
    and le: "k x. x cbox a b ==> (f k x) f (Suc k) x"
    and fg: "x. x cbox a b ==> ((λk. f k x) ---> g x) sequentially"
    and bou: "bounded (range (λk. integral (cbox a b) (f k)))"
  shows "g integrable_on cbox a b ((λk. integral (cbox a b) (f k)) ---> integral (cbox a b) g) sequentially"
proof (cases "content (cbox a b) = 0")
  case True then show ?thesis
    by auto
next
  case False
  have fg1: "(f k x) (g x)" if x: "x cbox a b" for x k
  proof -
    have "🪙F j in sequentially. f k x f j x"
      by (metis eventually_sequentiallyI le lift_Suc_mono_le x)
    then show "f k x g x"
      using tendsto_lowerbound [OF fg] x trivial_limit_sequentially by blast
  qed
  have int_inc: "n. integral (cbox a b) (f n) integral (cbox a b) (f (Suc n))"
    by (metis integral_le intf le)
  then obtain i where i: "(λk. integral (cbox a b) (f k)) <---- i"
    using bounded_increasing_convergent bou by blast
  have "k. 🪙F x in sequentially. integral (cbox a b) (f k) integral (cbox a b) (f x)"
    unfolding eventually_sequentially
    by (force intro: transitive_stepwise_le int_inc)
  then have i': "k. (integral(cbox a b) (f k)) i"
    using tendsto_le [OF trivial_limit_sequentially i] by blast
  have "(g has_integral i) (cbox a b)"
    unfolding has_integral real_norm_def
  proof clarify
    fix e::real
    assume e: "e > 0"
    have "k. (γ. gauge γ (D. D tagged_division_of (cbox a b) γ fine D
      abs (((x,K)D. content K *🪙R f k x) - integral (cbox a b) (f k)) < e/2 ^ (k + 2)))"
      using intf e by (auto simp: has_integral_integral has_integral)
    then obtain c where c: "x. gauge (c x)"
          "x D. [D tagged_division_of cbox a b; c x fine D] ==>
              abs (((u,K)D. content K *🪙R f x u) - integral (cbox a b) (f x))
              < e/2 ^ (x + 2)"
      by metis

    have "r. kr. 0 i - (integral (cbox a b) (f k)) i - (integral (cbox a b) (f k)) < e/4"
    proof -
      have "e/4 > 0"
        using e by auto
      show ?thesis
        using LIMSEQ_D [OF i e/4 > 0] i' by auto
    qed
    then obtain r where r: "k. r k ==> 0 i - integral (cbox a b) (f k)"
                       "k. r k ==> i - integral (cbox a b) (f k) < e/4" 
      by metis
    have "nr. kn. 0 (g x) - (f k x) (g x) - (f k x) < e/(4 * content(cbox a b))"
      if "x cbox a b" for x
    proof -
      have "e/(4 * content (cbox a b)) > 0"
        by (simp add: False content_lt_nz e)
      with fg that LIMSEQ_D
      obtain N where "nN. norm (f n x - g x) < e/(4 * content (cbox a b))"
        by metis
      with fg1[OF that] show "nr. kn. 0 g x - f k x g x - f k x < e/(4 * content (cbox a b))"
        by (rule_tac x="N + r" in exI) (auto simp: field_simps)
    qed
    then obtain m where r_le_m: "x. x cbox a b ==> r m x"
       and m: "x k. [x cbox a b; m x k]
                     ==> 0 g x - f k x g x - f k x < e/(4 * content (cbox a b))"
      by metis
    define d where "d x = c (m x) x" for x
    show "γ. gauge γ
             (D. D tagged_division_of cbox a b
                  γ fine D abs (((x,K)D. content K *🪙R g x) - i) < e)"
    proof (rule exI, safe)
      show "gauge d"
        using c(1) unfolding gauge_def d_def by auto
    next
      fix D
      assume ptag: "D tagged_division_of (cbox a b)" and "d fine D"
      note p'=tagged_division_ofD[OF ptag]
      obtain s where s: "x. x D ==> m (fst x) s"
        by (metis finite_imageI finite_nat_set_iff_bounded_le p'(1) rev_image_eqI)
      have *: "a - d < e" if "a - b e/4" "b - c < e/2" "c - d < e/4" for a b c d
        using that norm_triangle_lt[of "a - b" "b - c" "3* e/4"]
          norm_triangle_lt[of "a - b + (b - c)" "c - d" e]
        by (auto simp: algebra_simps)
      show "((x, k)D. content k *🪙R g x) - i < e"
      proof (rule *)
        have "((x,K)D. content K *🪙R g x) - ((x,K)D. content K *🪙R f (m x) x)
               (iD. (case i of (x, K) ==> content K *🪙R g x) - (case i of (x, K) ==> content K *🪙R f (m x) x))"
          by (metis (mono_tags) sum_subtractf sum_abs) 
        also have " ((x, k)D. content k * (e/(4 * content (cbox a b))))"
        proof (rule sum_mono, simp add: split_paired_all)
          fix x K
          assume xk: "(x,K) D"
          with ptag have x: "x cbox a b"
            by blast
          then have "abs (content K * (g x - f (m x) x)) content K * (e/(4 * content (cbox a b)))"
            by (metis m[OF x] mult_nonneg_nonneg abs_of_nonneg less_eq_real_def measure_nonneg mult_left_mono order_refl)
          then show "content K * g x - content K * f (m x) x content K * e/(4 * content (cbox a b))"
            by (simp add: algebra_simps)
        qed
        also have " = (e/(4 * content (cbox a b))) * ((x, k)D. content k)"
          by (simp add: sum_distrib_left sum_divide_distrib split_def mult.commute)
        also have " e/4"
          by (metis False additive_content_tagged_division [OF ptag] nonzero_mult_divide_mult_cancel_right order_refl times_divide_eq_left)
        finally show "((x,K)D. content K *🪙R g x) - ((x,K)D. content K *🪙R f (m x) x) e/4" .

      next
        have "norm (((x,K)D. content K *🪙R f (m x) x) - ((x,K)D. integral K (f (m x))))
               norm (j = 0..s. (x,K){xk D. m (fst xk) = j}. content K *🪙R f (m x) x - integral K (f (m x)))"
          using s by (subst sum.group) (auto simp: sum_subtractf split_def p')
        also have " < e/2"
        proof -
          have "norm (j = 0..s. (x, k){xk D. m (fst xk) = j}. content k *🪙R f (m x) x - integral k (f (m x)))
                 (i = 0..s. e/2 ^ (i + 2))"
          proof (rule sum_norm_le)
            fix t
            assume "t {0..s}"
            have "norm ((x,k){xk D. m (fst xk) = t}. content k *🪙R f (m x) x - integral k (f (m x))) =
                  norm ((x,k){xk D. m (fst xk) = t}. content k *🪙R f t x - integral k (f t))"
              by (force intro!: sum.cong arg_cong[where f=norm])
            also have " e/2 ^ (t + 2)"
            proof (rule Henstock_lemma_part1 [OF intf])
              show "{xk D. m (fst xk) = t} tagged_partial_division_of cbox a b"
              proof (rule tagged_partial_division_subset[of D])
                show "D tagged_partial_division_of cbox a b"
                  using ptag tagged_division_of_def by blast
              qed auto
              show "c t fine {xk D. m (fst xk) = t}"
                using d fine D by (auto simp: fine_def d_def)
            qed (use c e in auto)
            finally show "norm ((x,K){xk D. m (fst xk) = t}. content K *🪙R f (m x) x -
                                integral K (f (m x))) e/2 ^ (t + 2)" .
          qed
          also have " = (e/2/2) * (i = 0..s. (1/2) ^ i)"
            by (simp add: sum_distrib_left field_simps)
          also have " < e/2"
            by (simp add: sum_gp mult_strict_left_mono[OF _ e])
          finally show "norm (j = 0..s. (x, k){xk D.
            m (fst xk) = j}. content k *🪙R f (m x) x - integral k (f (m x))) < e/2" .
        qed 
        finally show "((x,K)D. content K *🪙R f (m x) x) - ((x,K)D. integral K (f (m x))) < e/2"
          by simp
      next
        have comb: "integral (cbox a b) (f y) = ((x, k)D. integral k (f y))" for y
          using integral_combine_tagged_division_topdown[OF intf ptag] by metis
        have f_le: "y m n. [y cbox a b; nm] ==> f m y f n y"
          using le by (auto intro: transitive_stepwise_le)        
        have "((x, k)D. integral k (f r)) ((x, K)D. integral K (f (m x)))"
        proof (rule sum_mono, simp add: split_paired_all)
          fix x K
          assume xK: "(x, K) D"
          show "integral K (f r) integral K (f (m x))"
          proof (rule integral_le)
            show "f r integrable_on K"
              by (metis integrable_on_subcbox intf p'(3) p'(4) xK)
            show "f (m x) integrable_on K"
              by (metis elementary_interval integrable_on_subdivision intf p'(3) p'(4) xK)
            show "f r y f (m x) y" if "y K" for y
              using that r_le_m[of x] p'(2-3)[OF xK] f_le by auto
          qed
        qed
        moreover have "((x, K)D. integral K (f (m x))) ((x, k)D. integral k (f s))"
        proof (rule sum_mono, simp add: split_paired_all)
          fix x K
          assume xK: "(x, K) D"
          show "integral K (f (m x)) integral K (f s)"
          proof (rule integral_le)
            show "f (m x) integrable_on K"
              by (metis elementary_interval integrable_on_subdivision intf p'(3) p'(4) xK)
            show "f s integrable_on K"
              by (metis integrable_on_subcbox intf p'(3) p'(4) xK)
            show "f (m x) y f s y" if "y K" for y
              using that s xK f_le p'(3) by fastforce
          qed
        qed
        moreover have "0 i - integral (cbox a b) (f r)" "i - integral (cbox a b) (f r) < e/4"
          using r by auto
        ultimately show "((x,K)D. integral K (f (m x))) - i < e/4"
          using comb i'[of s] by auto
      qed
    qed
  qed 
  with i integral_unique show ?thesis
    by blast
qed

lemma monotone_convergence_increasing:
  fixes f :: "nat ==> 'n::euclidean_space ==> real"
  assumes int_f: "k. (f k) integrable_on S"
    and "k x. x S ==> (f k x) (f (Suc k) x)"
    and fg: "x. x S ==> ((λk. f k x) ---> g x) sequentially"
    and bou: "bounded (range (λk. integral S (f k)))"
  shows "g integrable_on S ((λk. integral S (f k)) ---> integral S g) sequentially"
proof -
  have lem: "g integrable_on S ((λk. integral S (f k)) ---> integral S g) sequentially"
    if f0: "k x. x S ==> 0 f k x"
    and int_f: "k. (f k) integrable_on S"
    and le: "k x. x S ==> f k x f (Suc k) x"
    and lim: "x. x S ==> ((λk. f k x) ---> g x) sequentially"
    and bou: "bounded (range(λk. integral S (f k)))"
    for f :: "nat ==> 'n::euclidean_space ==> real" and g S
  proof -
    have fg: "(f k x) (g x)" if "x S" for x k
    proof -
      have "xa. k xa ==> f k x f xa x"
        using le  by (force intro: transitive_stepwise_le that)
      then show ?thesis
        using tendsto_lowerbound [OF lim [OF that]] eventually_sequentiallyI by force
    qed
    obtain i where i: "(λk. integral S (f k)) <---- i"
      using bounded_increasing_convergent [OF bou] le int_f integral_le by blast
    have i': "(integral S (f k)) i" for k
    proof -
      have "k. x. x S ==> nk. f k x f n x"
        using le  by (force intro: transitive_stepwise_le)
      then show ?thesis
        using tendsto_lowerbound [OF i eventually_sequentiallyI trivial_limit_sequentially]
        by (meson int_f integral_le)
    qed
    let ?f = "(λk x. if x S then f k x else 0)"
    let ?g = "(λx. if x S then g x else 0)"
    have int: "?f k integrable_on cbox a b" for a b k
      by (simp add: int_f integrable_altD(1))
    have int': "k a b. f k integrable_on cbox a b S"
      using int by (simp add: Int_commute integrable_restrict_Int) 
    have g: "?g integrable_on cbox a b
             (λk. integral (cbox a b) (?f k)) <---- integral (cbox a b) ?g" for a b
    proof (rule monotone_convergence_interval)
      have "norm (integral (cbox a b) (?f k)) norm (integral S (f k))" for k
      proof -
        have "0 integral (cbox a b) (?f k)"
          by (metis (no_types) integral_nonneg Int_iff f0 inf_commute integral_restrict_Int int')
        moreover have "0 integral S (f k)"
          by (simp add: integral_nonneg f0 int_f)
        moreover have "integral (S cbox a b) (f k) integral S (f k)"
          by (metis f0 inf_commute int' int_f integral_subset_le le_inf_iff order_refl)
        ultimately show ?thesis
          by (simp add: integral_restrict_Int)
      qed
      moreover obtain B where "x. x range (λk. integral S (f k)) ==> norm x B"
        using bou unfolding bounded_iff by blast
      ultimately show "bounded (range (λk. integral (cbox a b) (?f k)))"
        unfolding bounded_iff by (blast intro: order_trans)
    qed (use int le lim in auto)
    moreover have "B>0. a b. ball 0 B cbox a b norm (integral (cbox a b) ?g - i) < e"
      if "0 < e" for e
    proof -
      have "e/4>0"
        using that by auto
      with LIMSEQ_D [OF i] obtain N where N: "n. n N ==> norm (integral S (f n) - i) < e/4"
        by metis
      obtain B where "0 < B" and B: 
        "a b. ball 0 B cbox a b ==> norm (integral (cbox a b) (?f N) - integral S (f N)) < e/4"
        by (metis (lifting) ext 0 🚫/4 has_integral_alt' int_f integrable_integral)
      have "norm (integral (cbox a b) ?g - i) < e" if  ab: "ball 0 B cbox a b" for a b
      proof -
        obtain M where M: "n. n M ==> abs (integral (cbox a b) (?f n) - integral (cbox a b) ?g) < e/2"
          using e > 0by (fastforce simp: dest!: LIMSEQ_D [where r = "e/2"])
        have *: "α β g. [α - i < e/2; β - g < e/2; α β; β i] ==> g - i < e"
          unfolding real_inner_1_right by arith
        show "norm (integral (cbox a b) ?g - i) < e"
          unfolding real_norm_def
        proof (rule *)
          show "integral (cbox a b) (?f N) - i < e/2"
          proof (rule abs_triangle_half_l)
            show "integral (cbox a b) (?f N) - integral S (f N) < e/2/2"
              using B[OF ab] by simp
            show "abs (i - integral S (f N)) < e/2/2"
              using N by (simp add: abs_minus_commute)
          qed
          show "integral (cbox a b) (?f (M + N)) - integral (cbox a b) ?g < e/2"
            by (metis le_add1 M[of "M + N"])
          show "integral (cbox a b) (?f N) integral (cbox a b) (?f (M + N))"
          proof (intro ballI integral_le[OF int int])
            fix x assume "x cbox a b"
            have "(f m x) (f n x)" if "x S" "n m" for m n
            proof (rule transitive_stepwise_le [OF n m order_refl])
              show "u y z. [f u x f y x; f y x f z x] ==> f u x f z x"
                using dual_order.trans by blast
            qed (simp add: le x S)
            then show "(?f N)x (?f (M+N))x"
              by auto
          qed
          have "integral (cbox a b S) (f (M + N)) integral S (f (M + N))"
            by (metis Int_lower1 f0 inf_commute int' int_f integral_subset_le)
          then have "integral (cbox a b) (?f (M + N)) integral S (f (M + N))"
            by (metis (no_types) inf_commute integral_restrict_Int)
          also have " i"
            using i'[of "M + N"by auto
          finally show "integral (cbox a b) (?f (M + N)) i" .
        qed
      qed
      then show ?thesis
        using 0 🚫 by blast
    qed
    ultimately have "(g has_integral i) S"
      unfolding has_integral_alt' by auto
    then show ?thesis
      using has_integral_integrable_integral i integral_unique by metis
  qed

  have sub: "k. integral S (λx. f k x - f 0 x) = integral S (f k) - integral S (f 0)"
    by (simp add: integral_diff int_f)
  have *: "x m n. x S ==> nm ==> f m x f n x"
    using assms(2) by (force intro: transitive_stepwise_le)
  have gf: "(λx. g x - f 0 x) integrable_on S ((λk. integral S (λx. f (Suc k) x - f 0 x)) --->
    integral S (λx. g x - f 0 x)) sequentially"
  proof (rule lem)
    show "k. (λx. f (Suc k) x - f 0 x) integrable_on S"
      by (simp add: integrable_diff int_f)
    show "(λk. f (Suc k) x - f 0 x) <---- g x - f 0 x" if "x S" for x
      using LIMSEQ_ignore_initial_segment[OF fg[OF x S], of 1]
      by (simp add: tendsto_diff)
    show "bounded (range (λk. integral S (λx. f (Suc k) x - f 0 x)))"
    proof -
      obtain B where B: "k. norm (integral S (f k)) B"
        using  bou by (auto simp: bounded_iff)
      then have "norm (integral S (λx. f (Suc k) x - f 0 x))
               B + norm (integral S (f 0))" for k
        unfolding sub by (meson add_le_cancel_right norm_triangle_le_diff)
      then show ?thesis
        unfolding bounded_iff by blast
    qed
  qed (use * in auto)
  then have "(λx. integral S (λxa. f (Suc x) xa - f 0 xa) + integral S (f 0))
             <---- integral S (λx. g x - f 0 x) + integral S (f 0)"
    by (auto simp: tendsto_add)
  moreover have "(λx. g x - f 0 x + f 0 x) integrable_on S"
    using gf integrable_add int_f [of 0] by metis
  ultimately show ?thesis
    by (simp add: integral_diff int_f LIMSEQ_imp_Suc sub)
qed

lemma has_integral_monotone_convergence_increasing:
  fixes f :: "nat ==> 'a::euclidean_space ==> real"
  assumes f: "k. (f k has_integral x k) s"
  assumes "k x. x s ==> f k x f (Suc k) x"
  assumes "x. x s ==> (λk. f k x) <---- g x"
  assumes "x <---- x'"
  shows "(g has_integral x') s"
proof -
  have x_eq: "x = (λi. integral s (f i))"
    by (simp add: integral_unique[OF f])
  then have x: "range(λk. integral s (f k)) = range x"
    by auto
  have *: "g integrable_on s (λk. integral s (f k)) <---- integral s g"
  proof (intro monotone_convergence_increasing allI ballI assms)
    show "bounded (range(λk. integral s (f k)))"
      using x convergent_imp_bounded assms by metis
  qed (use f in auto)
  then have "integral s g = x'"
    by (intro LIMSEQ_unique[OF _ x <---- x']) (simp add: x_eq)
  with * show ?thesis
    by (simp add: has_integral_integral)
qed

lemma monotone_convergence_decreasing:
  fixes f :: "nat ==> 'n::euclidean_space ==> real"
  assumes intf: "k. (f k) integrable_on S"
    and le: "k x. x S ==> f (Suc k) x f k x"
    and fg: "x. x S ==> ((λk. f k x) ---> g x) sequentially"
    and bou: "bounded (range(λk. integral S (f k)))"
  shows "g integrable_on S (λk. integral S (f k)) <---- integral S g"
proof -
  have *: "range(λk. integral S (λx. - f k x)) = (*🪙R) (- 1) ` (range(λk. integral S (f k)))"
    by force
  have "(λx. - g x) integrable_on S (λk. integral S (λx. - f k x)) <---- integral S (λx. - g x)"
  proof (rule monotone_convergence_increasing)
    show "k. (λx. - f k x) integrable_on S"
      by (blast intro: integrable_neg intf)
    show "k x. x S ==> - f k x - f (Suc k) x"
      by (simp add: le)
    show "x. x S ==> (λk. - f k x) <---- - g x"
      by (simp add: fg tendsto_minus)
    show "bounded (range(λk. integral S (λx. - f k x)))"
      using "*" bou bounded_scaling by auto
  qed
  then show ?thesis
    by (force dest: integrable_neg tendsto_minus)
qed

lemma integral_norm_bound_integral:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  assumes int_f: "f integrable_on S"
    and int_g: "g integrable_on S"
    and le_g: "x. x S ==> norm (f x) g x"
  shows "norm (integral S f) integral S g"
proof -
  have norm: "norm 🪙 y + e"
    if "norm ζ x" and "x - y < e/2" and "norm (ζ - 🪙) < e/2"
    for e x y and ζ 🪙 :: 'a
  proof -
    have "norm (🪙 - ζ) < e/2"
      by (metis norm_minus_commute that(3))
    moreover have "x y + e/2"
      using that(2) by linarith
    ultimately show ?thesis
      using that(1) le_less_trans[OF norm_triangle_sub[of 🪙 ζ]] by (auto simp: less_imp_le)
  qed
  have lem: "norm (integral(cbox a b) f) integral (cbox a b) g"
    if f: "f integrable_on cbox a b"
    and g: "g integrable_on cbox a b"
    and nle: "x. x cbox a b ==> norm (f x) g x"
    for f :: "'n ==> 'a" and g a b
  proof (rule field_le_epsilon)
    fix e :: real
    assume "e > 0"
    then have e: "e/2 > 0"
      by auto
    with integrable_integral[OF f,unfolded has_integral[of f]]
    obtain γ where γ: "gauge γ"
              "D. D tagged_division_of cbox a b γ fine D
           ==> norm (((x, k)D. content k *🪙R f x) - integral (cbox a b) f) < e/2"
      by meson 
    moreover
    from integrable_integral[OF g,unfolded has_integral[of g]] e
    obtain δ where δ: "gauge δ"
              "D. D tagged_division_of cbox a b δ fine D
           ==> norm (((x, k)D. content k *🪙R g x) - integral (cbox a b) g) < e/2"
      by meson
    ultimately have "gauge (λx. γ x δ x)"
      using gauge_Int by blast
    with fine_division_exists obtain D 
      where p: "D tagged_division_of cbox a b" "(λx. γ x δ x) fine D" 
      by metis
    have "γ fine D" "δ fine D"
      using fine_Int p(2) by blast+
    show "norm (integral (cbox a b) f) integral (cbox a b) g + e"
    proof (rule norm)
      have "norm (content K *🪙R f x) content K *🪙R g x" if  "(x, K) D" for x K
      proof-
        have K: "x K" "K cbox a b"
          using (x, K) D p(1) by blast+
        obtain u v where  "K = cbox u v"
          using (x, K) D p(1) by blast
        moreover have "content K * norm (f x) content K * g x"
          by (meson K(1) K(2) content_pos_le mult_left_mono nle subsetD)
        then show ?thesis
          by simp
      qed
      then show "norm ((x, k)D. content k *🪙R f x) ((x, k)D. content k *🪙R g x)"
        by (simp add: sum_norm_le split_def)
      show "norm (((x, k)D. content k *🪙R f x) - integral (cbox a b) f) < e/2"
        using γ fine D γ p(1) by simp
      show "((x, k)D. content k *🪙R g x) - integral (cbox a b) g < e/2"
        using δ fine D δ p(1) by simp
    qed
  qed
  show ?thesis
  proof (rule field_le_epsilon)
    fix e :: real
    assume "e > 0"
    then have e: "e/2 > 0"
      by auto
    let ?f = "(λx. if x S then f x else 0)"
    let ?g = "(λx. if x S then g x else 0)"
    have f: "?f integrable_on cbox a b" and g: "?g integrable_on cbox a b" for a b
      using int_f int_g integrable_altD by auto
    obtain Bf where "0 < Bf"
      and Bf: "a b. ball 0 Bf cbox a b ==>
        z. (?f has_integral z) (cbox a b) norm (z - integral S f) < e/2"
      using integrable_integral [OF int_f,unfolded has_integral'[of f]] e that by blast
    obtain Bg where "0 < Bg"
      and Bg: "a b. ball 0 Bg cbox a b ==>
        z. (?g has_integral z) (cbox a b) norm (z - integral S g) < e/2"
      using integrable_integral [OF int_g,unfolded has_integral'[of g]] e that by blast
    obtain a b::'n where ab: "ball 0 Bf ball 0 Bg cbox a b"
      using ball_max_Un  by (metis bounded_ball bounded_subset_cbox_symmetric)
    have "ball 0 Bf cbox a b"
      using ab by auto
    with Bf obtain z where int_fz: "(?f has_integral z) (cbox a b)" and z: "norm (z - integral S f) < e/2"
      by meson
    have "ball 0 Bg cbox a b"
      using ab by auto
    with Bg obtain w where int_gw: "(?g has_integral w) (cbox a b)" and w: "norm (w - integral S g) < e/2"
      by meson
    show "norm (integral S f) integral S g + e"
    proof (rule norm)
      show "norm (integral (cbox a b) ?f) integral (cbox a b) ?g"
        by (simp add: le_g lem[OF f g, of a b])
      show "integral (cbox a b) ?g - integral S g < e/2"
        using int_gw integral_unique w by auto
      show "norm (integral (cbox a b) ?f - integral S f) < e/2"
        using int_fz integral_unique z by blast
    qed
  qed
qed

lemma continuous_on_imp_absolutely_integrable_on:
  fixes f::"real ==> 'a::banach"
  shows "continuous_on {a..b} f ==>
    norm (integral {a..b} f) integral {a..b} (λx. norm (f x))"
  by (intro integral_norm_bound_integral integrable_continuous_real continuous_on_norm) auto

lemma integral_bound:
  fixes f::"real ==> 'a::banach"
  assumes "a b"
  assumes "continuous_on {a .. b} f"
  assumes "t. t {a .. b} ==> norm (f t) B"
  shows "norm (integral {a .. b} f) B * (b - a)"
proof -
  note continuous_on_imp_absolutely_integrable_on[OF assms(2)]
  also have "integral {a..b} (λx. norm (f x)) integral {a..b} (λ_. B)"
    by (rule integral_le)
      (auto intro!: integrable_continuous_real continuous_intros assms)
  also have " = B * (b - a)" using assms by simp
  finally show ?thesis .
qed

lemma integral_norm_bound_integral_component:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  fixes g :: "'n ==> 'b::euclidean_space"
  assumes f: "f integrable_on S" and g: "g integrable_on S"
    and fg: "x. x S ==> norm(f x) (g x)k"
  shows "norm (integral S f) (integral S g)k"
proof -
  have "norm (integral S f) integral S ((λx. x k) g)"
    using integral_norm_bound_integral[OF f integrable_linear[OF g]]
    by (simp add: bounded_linear_inner_left fg)
  then show ?thesis
    unfolding o_def integral_component_eq[OF g] .
qed

lemma has_integral_norm_bound_integral_component:
  fixes f :: "'n::euclidean_space ==> 'a::banach"
  fixes g :: "'n ==> 'b::euclidean_space"
  assumes "(f has_integral i) S" and "(g has_integral j) S"
    and "x. x S ==> norm (f x) (g x)k"
  shows "norm i jk"
  by (metis assms has_integral_integrable integral_norm_bound_integral_component integral_unique)


lemma uniformly_convergent_improper_integral:
  fixes f :: "'b ==> real ==> 'a :: {banach}"
  assumes deriv: "x. x a ==> (G has_field_derivative g x) (at x within {a..})"
  assumes integrable: "a' b x. x A ==> a' a ==> b a' ==> f x integrable_on {a'..b}"
  assumes G: "convergent G"
  assumes le: "y x. y A ==> x a ==> norm (f y x) g x"
  shows   "uniformly_convergent_on A (λb x. integral {a..b} (f x))"
proof (intro Cauchy_uniformly_convergent uniformly_Cauchy_onI', goal_cases)
  case (1 ε)
  from G have "Cauchy G"
    by (auto intro!: convergent_Cauchy)
  with 1 obtain M where M: "dist (G (real m)) (G (real n)) < ε" if "m M" "n M" for m n
    by (force simp: Cauchy_def)
  define M' where "M' = max (nat a) M"

  show ?case
  proof (rule exI[of _ M'], safe, goal_cases)
    case (1 x m n)
    have M': "M' a" "M' M" unfolding M'_def by linarith+
    have int_g: "(g has_integral (G (real n) - G (real m))) {real m..real n}"
      using 1 M' by (intro fundamental_theorem_of_calculus) 
                    (auto simp: has_real_derivative_iff_has_vector_derivative [symmetric] 
                          intro!: DERIV_subset[OF deriv])
    have int_f: "f x integrable_on {a'..real n}" if "a' a" for a'
      using that 1 by (cases "a' real n") (auto intro: integrable)

    have "dist (integral {a..real m} (f x)) (integral {a..real n} (f x)) =
            norm (integral {a..real n} (f x) - integral {a..real m} (f x))"
      by (simp add: dist_norm norm_minus_commute)
    also have "integral {a..real m} (f x) + integral {real m..real n} (f x) =
                 integral {a..real n} (f x)"
      using M' and 1 by (intro integral_combine int_f) auto
    hence "integral {a..real n} (f x) - integral {a..real m} (f x) =
             integral {real m..real n} (f x)"
      by (simp add: algebra_simps)
    also have "norm integral {real m..real n} g"
      using le 1 M' int_f int_g by (intro integral_norm_bound_integral) auto 
    also from int_g have "integral {real m..real n} g = G (real n) - G (real m)"
      by (simp add: has_integral_iff)
    also have " dist (G m) (G n)" 
      by (simp add: dist_norm)
    also from 1 and M' have " < ε"
      by (intro M) auto
    finally show ?case .
  qed
qed

lemma uniformly_convergent_improper_integral':
  fixes f :: "'b ==> real ==> 'a :: {banach, real_normed_algebra}"
  assumes deriv: "x. x a ==> (G has_field_derivative g x) (at x within {a..})"
  assumes integrable: "a' b x. x A ==> a' a ==> b a' ==> f x integrable_on {a'..b}"
  assumes G: "convergent G"
  assumes le: "eventually (λx. yA. norm (f y x) g x) at_top"
  shows   "uniformly_convergent_on A (λb x. integral {a..b} (f x))"
proof -
  from le obtain a'' where le: "y x. y A ==> x a'' ==> norm (f y x) g x"
    by (auto simp: eventually_at_top_linorder)
  define a' where "a' = max a a''"

  have "uniformly_convergent_on A (λb x. integral {a'..real b} (f x))"
  proof (rule uniformly_convergent_improper_integral)
    fix t assume t: "t a'"
    hence "(G has_field_derivative g t) (at t within {a..})"
      by (intro deriv) (auto simp: a'_def)
    moreover have "{a'..} {a..}" unfolding a'_def by auto
    ultimately show "(G has_field_derivative g t) (at t within {a'..})"
      by (rule DERIV_subset)
  qed (insert le, auto simp: a'_def intro: integrable G)
  hence "uniformly_convergent_on A (λb x. integral {a..a'} (f x) + integral {a'..real b} (f x))" 
    (is ?P) by (intro uniformly_convergent_add) auto
  also have "eventually (λx. yA. integral {a..a'} (f y) + integral {a'..x} (f y) =
                   integral {a..x} (f y)) sequentially"
    by (intro eventually_mono [OF eventually_ge_at_top[of "nat a'"]] ballI integral_combine)
       (auto simp: a'_def intro: integrable)
  hence "?P ?thesis"
    by (intro uniformly_convergent_cong) simp_all
  finally show ?thesis .
qed

subsection differentiation under the integral sign

lemma integral_continuous_on_param:
  fixes f::"'a::topological_space ==> 'b::euclidean_space ==> 'c::banach"
  assumes cont_fx: "continuous_on (U × cbox a b) (λ(x, t). f x t)"
  shows "continuous_on U (λx. integral (cbox a b) (f x))"
proof cases
  assume "content (cbox a b) 0"
  then have ne: "cbox a b {}" by auto

  note [continuous_intros] =
    continuous_on_compose2[OF cont_fx, where f="λy. Pair x y" for x,
      unfolded split_beta fst_conv snd_conv]

  show ?thesis
    unfolding continuous_on_def
  proof (intro strip tendstoI)
    fix e'::real and x
    assume "e' > 0"
    define e where "e = e' / (content (cbox a b) + 1)"
    have "e > 0" using e' > 0 by (auto simp: e_def intro!: divide_pos_pos add_nonneg_pos)
    assume "x U"
    from continuous_on_prod_compactE[OF cont_fx compact_cbox x U 0 🚫]
    obtain X0 where X0: "x X0" "open X0"
      and fx_bound: "y t. y X0 U ==> t cbox a b ==> norm (f y t - f x t) e"
      unfolding split_beta fst_conv snd_conv dist_norm
      by metis
    have "🪙F y in at x within U. y X0 U"
      using X0(1) X0(2) eventually_at_topological by auto
    then show "🪙F y in at x within U. dist (integral (cbox a b) (f y)) (integral (cbox a b) (f x)) < e'"
    proof eventually_elim
      case (elim y)
      have "dist (integral (cbox a b) (f y)) (integral (cbox a b) (f x)) =
        norm (integral (cbox a b) (λt. f y t - f x t))"
        using elim x U
        unfolding dist_norm
        proof (subst integral_diff)
        qed (auto intro!: integrable_continuous continuous_intros)
      also have " e * content (cbox a b)"
        using elim x U
        by (intro integrable_bound)
           (auto intro!: fx_bound x U less_imp_le[OF 0 🚫]
              integrable_continuous continuous_intros)
      also have " < e'"
        using 0 🚫' e > 0
        by (auto simp: e_def field_split_simps)
      finally show "dist (integral (cbox a b) (f y)) (integral (cbox a b) (f x)) < e'" .
    qed
  qed
qed (auto intro!: continuous_on_const)

lemma leibniz_rule:
  fixes f::"'a::banach ==> 'b::euclidean_space ==> 'c::banach"
  assumes fx: "x t. x U ==> t cbox a b ==>
    ((λx. f x t) has_derivative blinfun_apply (fx x t)) (at x within U)"
  assumes integrable_f2: "x. x U ==> f x integrable_on cbox a b"
  assumes cont_fx: "continuous_on (U × (cbox a b)) (λ(x, t). fx x t)"
  assumes [intro]: "x0 U"
  assumes "convex U"
  shows
    "((λx. integral (cbox a b) (f x)) has_derivative integral (cbox a b) (fx x0)) (at x0 within U)"
    (is "(?F has_derivative ?dF) _")
proof cases
  assume "content (cbox a b) 0"
  then have ne: "cbox a b {}" by auto
  note [continuous_intros] =
    continuous_on_compose2[OF cont_fx, where f="λy. Pair x y" for x,
      unfolded split_beta fst_conv snd_conv]
  show ?thesis
  proof (intro has_derivativeI bounded_linear_scaleR_left tendstoI, fold norm_conv_dist)
    have cont_f1: "t. t cbox a b ==> continuous_on U (λx. f x t)"
      by (auto simp: continuous_on_eq_continuous_within intro!: has_derivative_continuous fx)
    note [continuous_intros] = continuous_on_compose2[OF cont_f1]
    fix e'::real
    assume "e' > 0"
    define e where "e = e' / (content (cbox a b) + 1)"
    have "e > 0" using e' > 0 by (auto simp: e_def intro!: divide_pos_pos add_nonneg_pos)
    from continuous_on_prod_compactE[OF cont_fx compact_cbox x0 U e > 0]
    obtain X0 where X0: "x0 X0" "open X0"
      and fx_bound: "x t. x X0 U ==> t cbox a b ==> norm (fx x t - fx x0 t) e"
      unfolding split_beta fst_conv snd_conv
      by (metis dist_norm)

    note eventually_closed_segment[OF open X0 x0 X0, of U]
    moreover
    have "🪙F x in at x0 within U. x X0"
      using open X0 x0 X0 eventually_at_topological by blast
    moreover have "🪙F x in at x0 within U. x x0" "🪙F x in at x0 within U. x U"
      by (auto simp: eventually_at_filter)
    ultimately
    show "🪙F x in at x0 within U. norm ((?F x - ?F x0 - ?dF (x - x0)) /🪙R norm (x - x0)) < e'"
    proof eventually_elim
      case (elim x)
      from elim have "0 < norm (x - x0)" by simp
      have "closed_segment x0 x U"
        by (simp add: assms closed_segment_subset elim(4))
      from elim have [intro]: "x U" by auto
      have "?F x - ?F x0 - ?dF (x - x0) =
        integral (cbox a b) (λy. f x y - f x0 y - fx x0 y (x - x0))"
        (is "_ = ?id")
        using x x0
        by (subst blinfun_apply_integral integral_diff,
            auto intro!: integrable_diff integrable_f2 continuous_intros
              intro: integrable_continuous)+
      also
      have "norm ?id integral (cbox a b) (λ_. e * norm (x - x0))"
      proof (intro integral_norm_bound_integral)
        fix t assume t: "t (cbox a b)"
        then have deriv:
          "((λx. f x t) has_derivative (fx y t)) (at y within X0 U)"
          if "y X0 U" for y
          using fx has_derivative_subset that by fastforce
        have seg: "t. t {0..1} ==> x0 + t *🪙R (x - x0) X0 U"
          using closed_segment x0 x U closed_segment x0 x X0
          by (force simp: closed_segment_def algebra_simps)
        have "x. x X0 U ==> onorm (blinfun_apply (fx x t) - (fx x0 t)) e"
          using fx_bound t
          by (auto simp: norm_blinfun_def fun_diff_def blinfun.bilinear_simps[symmetric])
        from differentiable_bound_linearization[OF seg deriv this] X0
        show "norm (f x t - f x0 t - fx x0 t (x - x0)) e * norm (x - x0)"
          by (auto simp: ac_simps)
      qed (force intro: continuous_intros integrable_diff integrable_f2 integrable_continuous)+
      also have " = content (cbox a b) * e * norm (x - x0)"
        by simp
      also have " < e' * norm (x - x0)"
      proof (intro mult_strict_right_mono[OF _ 0 🚫 (x - x0)])
        show "content (cbox a b) * e < e'"
          using e' > 0 by (simp add: divide_simps e_def not_less)
      qed
      finally have "norm (?F x - ?F x0 - ?dF (x - x0)) < e' * norm (x - x0)" .
      then show ?case
        by (auto simp: divide_simps)
    qed
  qed (rule blinfun.bounded_linear_right)
qed (auto intro!: derivative_eq_intros simp: blinfun.bilinear_simps)

lemma has_vector_derivative_eq_has_derivative_blinfun:
  "(f has_vector_derivative f') (at x within U)
    (f has_derivative blinfun_scaleR_left f') (at x within U)"
  by (simp add: has_vector_derivative_def)

lemma leibniz_rule_vector_derivative:
  fixes f::"real ==> 'b::euclidean_space ==> 'c::banach"
  assumes fx: "x t. x U ==> t cbox a b ==>
      ((λx. f x t) has_vector_derivative (fx x t)) (at x within U)"
  assumes integrable_f2: "x. x U ==> (f x) integrable_on cbox a b"
  assumes cont_fx: "continuous_on (U × cbox a b) (λ(x, t). fx x t)"
  assumes U: "x0 U" "convex U"
  shows "((λx. integral (cbox a b) (f x)) has_vector_derivative integral (cbox a b) (fx x0))
      (at x0 within U)"
proof -
  note [continuous_intros] =
    continuous_on_compose2[OF cont_fx, where f="λy. Pair x y" for x,
      unfolded split_beta fst_conv snd_conv]
  show ?thesis
    unfolding has_vector_derivative_eq_has_derivative_blinfun
  proof (rule has_derivative_eq_rhs [OF leibniz_rule[OF _ integrable_f2 _ U]])
    show "continuous_on (U × cbox a b) (λ(x, t). blinfun_scaleR_left (fx x t))"
      using cont_fx by (auto simp: split_beta intro!: continuous_intros)
    show "blinfun_apply (integral (cbox a b) (λt. blinfun_scaleR_left (fx x0 t))) =
          blinfun_apply (blinfun_scaleR_left (integral (cbox a b) (fx x0)))"
    by (subst integral_linear[symmetric])
       (auto simp: has_vector_derivative_def o_def
         intro!: integrable_continuous U continuous_intros bounded_linear_intros)
    qed (use fx in auto simp: has_vector_derivative_def)
qed

lemma has_field_derivative_eq_has_derivative_blinfun:
  "(f has_field_derivative f') (at x within U) (f has_derivative blinfun_mult_right f') (at x within U)"
  by (simp add: has_field_derivative_def)

lemma leibniz_rule_field_derivative:
  fixes f::"'a::{real_normed_field, banach} ==> 'b::euclidean_space ==> 'a"
  assumes fx: "x t. x U ==> t cbox a b ==> ((λx. f x t) has_field_derivative fx x t) (at x within U)"
  assumes integrable_f2: "x. x U ==> (f x) integrable_on cbox a b"
  assumes cont_fx: "continuous_on (U × (cbox a b)) (λ(x, t). fx x t)"
  assumes U: "x0 U" "convex U"
  shows "((λx. integral (cbox a b) (f x)) has_field_derivative integral (cbox a b) (fx x0)) (at x0 within U)"
proof -
  note [continuous_intros] =
    continuous_on_compose2[OF cont_fx, where f="λy. Pair x y" for x,
      unfolded split_beta fst_conv snd_conv]
  have *: "blinfun_mult_right (integral (cbox a b) (fx x0)) =
    integral (cbox a b) (λt. blinfun_mult_right (fx x0 t))"
    by (subst integral_linear[symmetric])
      (auto simp: has_vector_derivative_def o_def
        intro!: integrable_continuous U continuous_intros bounded_linear_intros)
  show ?thesis
    unfolding has_field_derivative_eq_has_derivative_blinfun
  proof (rule has_derivative_eq_rhs [OF leibniz_rule[OF _ integrable_f2 _ U, where fx="λx t. blinfun_mult_right (fx x t)"]])
    show "continuous_on (U × cbox a b) (λ(x, t). blinfun_mult_right (fx x t))"
      using cont_fx by (auto simp: split_beta intro!: continuous_intros)
    show "blinfun_apply (integral (cbox a b) (λt. blinfun_mult_right (fx x0 t))) =
          blinfun_apply (blinfun_mult_right (integral (cbox a b) (fx x0)))"
      by (subst integral_linear[symmetric])
        (auto simp: has_vector_derivative_def o_def
          intro!: integrable_continuous U continuous_intros bounded_linear_intros)
  qed (use fx in auto simp: has_field_derivative_def)
qed

lemma leibniz_rule_field_differentiable:
  fixes f::"'a::{real_normed_field, banach} ==> 'b::euclidean_space ==> 'a"
  assumes "x t. x U ==> t cbox a b ==> ((λx. f x t) has_field_derivative fx x t) (at x within U)"
  assumes "x. x U ==> (f x) integrable_on cbox a b"
  assumes "continuous_on (U × (cbox a b)) (λ(x, t). fx x t)"
  assumes "x0 U" "convex U"
  shows "(λx. integral (cbox a b) (f x)) field_differentiable at x0 within U"
  using leibniz_rule_field_derivative[OF assms] by (auto simp: field_differentiable_def)


subsection Exchange uniform limit and integral

lemma uniform_limit_integral_cbox:
  fixes f::"'a ==> 'b::euclidean_space ==> 'c::banach"
  assumes u: "uniform_limit (cbox a b) f g F"
  assumes c: "n. continuous_on (cbox a b) (f n)"
  assumes [simp]: "F bot"
  obtains I J where
    "n. (f n has_integral I n) (cbox a b)"
    "(g has_integral J) (cbox a b)"
    "(I ---> J) F"
proof -
  have fi[simp]: "f n integrable_on (cbox a b)" for n
    by (auto intro!: integrable_continuous assms)
  then obtain I where I: "n. (f n has_integral I n) (cbox a b)"
    unfolding integrable_on_def by metis

  moreover
  have gi[simp]: "g integrable_on (cbox a b)"
    by (auto intro!: integrable_continuous uniform_limit_theorem[OF _ u] eventuallyI c)
  then obtain J where J: "(g has_integral J) (cbox a b)"
    by blast

  moreover
  have "(I ---> J) F"
  proof cases
    assume "content (cbox a b) = 0"
    hence "I = (λ_. 0)" "J = 0"
      by (auto intro!: has_integral_unique I J)
    thus ?thesis by simp
  next
    assume content_nonzero: "content (cbox a b) 0"
    show ?thesis
    proof (rule tendstoI)
      fix e::real
      assume "e > 0"
      define e' where "e' = e/2"
      with e > 0 have "e' > 0" by simp
      then have "🪙F n in F. xcbox a b. norm (f n x - g x) < e' / content (cbox a b)"
        using u content_nonzero by (auto simp: uniform_limit_iff dist_norm zero_less_measure_iff)
      then show "🪙F n in F. dist (I n) J < e"
      proof eventually_elim
        case (elim n)
        have "I n = integral (cbox a b) (f n)" "J = integral (cbox a b) g"
          using I[of n] J by (simp_all add: integral_unique)
        then have "dist (I n) J = norm (integral (cbox a b) (λx. f n x - g x))"
          by (simp add: integral_diff dist_norm)
        also have " integral (cbox a b) (λx. (e' / content (cbox a b)))"
          using elim
          by (intro integral_norm_bound_integral) (auto intro!: integrable_diff)
        also have " < e"
          using 0 🚫 by (simp add: e'_def)
        finally show ?case .
      qed
    qed
  qed
  ultimately show ?thesis ..
qed

lemma uniform_limit_integral:
  fixes f::"'a ==> 'b::ordered_euclidean_space ==> 'c::banach"
  assumes u: "uniform_limit {a..b} f g F"
  assumes c: "n. continuous_on {a..b} (f n)"
  assumes [simp]: "F bot"
  obtains I J where
    "n. (f n has_integral I n) {a..b}"
    "(g has_integral J) {a..b}"
    "(I ---> J) F"
  by (metis interval_cbox assms uniform_limit_integral_cbox)


subsection Integration by parts

lemma integration_by_parts_interior_strong:
  fixes prod :: "_ ==> _ ==> 'b :: banach"
  assumes bilinear: "bounded_bilinear (prod)"
  assumes s: "finite s" and le: "a b"
  assumes cont [continuous_intros]: "continuous_on {a..b} f" "continuous_on {a..b} g"
  assumes deriv: "x. x{a<..==> (f has_vector_derivative f' x) (at x)"
                 "x. x{a<..==> (g has_vector_derivative g' x) (at x)"
  assumes int: "((λx. prod (f x) (g' x)) has_integral
                  (prod (f b) (g b) - prod (f a) (g a) - y)) {a..b}"
  shows   "((λx. prod (f' x) (g x)) has_integral y) {a..b}"
proof -
  interpret bounded_bilinear prod by fact
  have "((λx. prod (f x) (g' x) + prod (f' x) (g x)) has_integral
          (prod (f b) (g b) - prod (f a) (g a))) {a..b}"
    using deriv by (intro fundamental_theorem_of_calculus_interior_strong[OF s le])
                   (auto intro!: continuous_intros continuous_on has_vector_derivative)
  from has_integral_diff[OF this int] show ?thesis by (simp add: algebra_simps)
qed

lemma integration_by_parts_interior:
  fixes prod :: "_ ==> _ ==> 'b :: banach"
  assumes "bounded_bilinear (prod)" "a b"
          "continuous_on {a..b} f" "continuous_on {a..b} g"
  assumes "x. x{a<..==> (f has_vector_derivative f' x) (at x)"
          "x. x{a<..==> (g has_vector_derivative g' x) (at x)"
  assumes "((λx. prod (f x) (g' x)) has_integral (prod (f b) (g b) - prod (f a) (g a) - y)) {a..b}"
  shows   "((λx. prod (f' x) (g x)) has_integral y) {a..b}"
  by (rule integration_by_parts_interior_strong[of _ "{}" _ _ f g f' g']) (use assms in simp_all)

lemma integration_by_parts:
  fixes prod :: "_ ==> _ ==> 'b :: banach"
  assumes "bounded_bilinear (prod)" "a b"
          "continuous_on {a..b} f" "continuous_on {a..b} g"
  assumes "x. x{a..b} ==> (f has_vector_derivative f' x) (at x)"
          "x. x{a..b} ==> (g has_vector_derivative g' x) (at x)"
  assumes "((λx. prod (f x) (g' x)) has_integral (prod (f b) (g b) - prod (f a) (g a) - y)) {a..b}"
  shows   "((λx. prod (f' x) (g x)) has_integral y) {a..b}"
  by (rule integration_by_parts_interior[of _ _ _ f g f' g']) (use assms in simp_all)

lemma integrable_by_parts_interior_strong:
  fixes prod :: "_ ==> _ ==> 'b :: banach"
  assumes bilinear: "bounded_bilinear (prod)"
  assumes s: "finite s" and le: "a b"
  assumes cont [continuous_intros]: "continuous_on {a..b} f" "continuous_on {a..b} g"
  assumes deriv: "x. x{a<..==> (f has_vector_derivative f' x) (at x)"
                 "x. x{a<..==> (g has_vector_derivative g' x) (at x)"
  assumes int: "(λx. prod (f x) (g' x)) integrable_on {a..b}"
  shows   "(λx. prod (f' x) (g x)) integrable_on {a..b}"
proof -
  from int obtain I where "((λx. prod (f x) (g' x)) has_integral I) {a..b}"
    unfolding integrable_on_def by blast
  hence "((λx. prod (f x) (g' x)) has_integral (prod (f b) (g b) - prod (f a) (g a) -
           (prod (f b) (g b) - prod (f a) (g a) - I))) {a..b}" by simp
  from integration_by_parts_interior_strong[OF assms(1-7) this]
    show ?thesis unfolding integrable_on_def by blast
qed

lemma integrable_by_parts_interior:
  fixes prod :: "_ ==> _ ==> 'b :: banach"
  assumes "bounded_bilinear (prod)" "a b"
          "continuous_on {a..b} f" "continuous_on {a..b} g"
  assumes "x. x{a<..==> (f has_vector_derivative f' x) (at x)"
          "x. x{a<..==> (g has_vector_derivative g' x) (at x)"
  assumes "(λx. prod (f x) (g' x)) integrable_on {a..b}"
  shows   "(λx. prod (f' x) (g x)) integrable_on {a..b}"
  by (rule integrable_by_parts_interior_strong[of _ "{}" _ _ f g f' g']) (use assms in simp_all)

lemma integrable_by_parts:
  fixes prod :: "_ ==> _ ==> 'b :: banach"
  assumes "bounded_bilinear (prod)" "a b"
          "continuous_on {a..b} f" "continuous_on {a..b} g"
  assumes "x. x{a..b} ==> (f has_vector_derivative f' x) (at x)"
          "x. x{a..b} ==> (g has_vector_derivative g' x) (at x)"
  assumes "(λx. prod (f x) (g' x)) integrable_on {a..b}"
  shows   "(λx. prod (f' x) (g x)) integrable_on {a..b}"
  by (rule integrable_by_parts_interior_strong[of _ "{}" _ _ f g f' g']) (use assms in simp_all)


subsection Integration by substitution

lemma has_integral_substitution_general:
  fixes f :: "real ==> 'a::euclidean_space" and g :: "real ==> real"
  assumes s: "finite s" and le: "a b"
      and subset: "g ` {a..b} {c..d}"
      and f [continuous_intros]: "continuous_on {c..d} f"
      and g [continuous_intros]: "continuous_on {a..b} g"
      and deriv [derivative_intros]:
              "x. x {a..b} - s ==> (g has_field_derivative g' x) (at x within {a..b})"
    shows "((λx. g' x *🪙R f (g x)) has_integral (integral {g a..g b} f - integral {g b..g a} f)) {a..b}"
proof -
  let ?F = "λx. integral {c..g x} f"
  have cont_int: "continuous_on {a..b} ?F"
    by (rule continuous_on_compose2[OF _ g subset] indefinite_integral_continuous_1
          f integrable_continuous_real)+
  have deriv: "(((λx. integral {c..x} f) g) has_vector_derivative g' x *🪙R f (g x))
                 (at x within {a..b})" if "x {a..b} - s" for x
  proof (rule has_vector_derivative_eq_rhs [OF vector_diff_chain_within refl])
    show "(g has_vector_derivative g' x) (at x within {a..b})"
      using deriv has_real_derivative_iff_has_vector_derivative that by blast
    show "((λx. integral {c..x} f) has_vector_derivative f (g x))
          (at (g x) within g ` {a..b})"
      using that le subset
      by (blast intro: has_vector_derivative_within_subset integral_has_vector_derivative f)
  qed
  have deriv: "(?F has_vector_derivative g' x *🪙R f (g x))
                  (at x)" if "x {a..b} - (s {a,b})" for x
    using deriv[of x] that by (simp add: at_within_Icc_at o_def)
  have "((λx. g' x *🪙R f (g x)) has_integral (?F b - ?F a)) {a..b}"
    using le cont_int s deriv cont_int
    by (intro fundamental_theorem_of_calculus_interior_strong[of "s {a,b}"]) simp_all
  also
  from subset have "g x {c..d}" if "x {a..b}" for x using that by blast
  from this[of a] this[of b] le have cd"c g a" "g b d" "c g b" "g a d" by auto
  have "integral {c..g b} f - integral {c..g a} f = integral {g a..g b} f - integral {g b..g a} f"
  proof cases
    assume "g a g b"
    note le = le this
    from cd have "integral {c..g a} f + integral {g a..g b} f = integral {c..g b} f"
      by (intro integral_combine integrable_continuous_real continuous_on_subset[OF f] le) simp_all
    with le show ?thesis
      by (cases "g a = g b") (simp_all add: algebra_simps)
  next
    assume less: "¬g a g b"
    then have "g a g b" by simp
    note le = le this
    from cd have "integral {c..g b} f + integral {g b..g a} f = integral {c..g a} f"
      by (intro integral_combine integrable_continuous_real continuous_on_subset[OF f] le) simp_all
    with less show ?thesis
      by (simp_all add: algebra_simps)
  qed
  finally show ?thesis .
qed

lemma has_integral_substitution_strong:
  fixes f :: "real ==> 'a::euclidean_space" and g :: "real ==> real"
  assumes s: "finite s" and le: "a b" "g a g b"
    and subset: "g ` {a..b} {c..d}"
    and f [continuous_intros]: "continuous_on {c..d} f"
    and g [continuous_intros]: "continuous_on {a..b} g"
    and deriv [derivative_intros]:
    "x. x {a..b} - s ==> (g has_field_derivative g' x) (at x within {a..b})"
  shows "((λx. g' x *🪙R f (g x)) has_integral (integral {g a..g b} f)) {a..b}"
  using has_integral_substitution_general[OF s le(1) subset f g deriv] le(2)
  by (cases "g a = g b") auto

lemma has_integral_substitution:
  fixes f :: "real ==> 'a::euclidean_space" and g :: "real ==> real"
  assumes "a b" "g a g b" "g ` {a..b} {c..d}"
      and "continuous_on {c..d} f"
      and "x. x {a..b} ==> (g has_field_derivative g' x) (at x within {a..b})"
    shows "((λx. g' x *🪙R f (g x)) has_integral (integral {g a..g b} f)) {a..b}"
proof (intro has_integral_substitution_strong[of "{}" a b g c d] assms)
qed (auto intro: DERIV_continuous_on assms)

lemma integral_shift:
  fixes f :: "real ==> 'a::euclidean_space"
  assumes cont: "continuous_on {a + c..b + c} f"
  shows "integral {a..b} (f (λx. x + c)) = integral {a + c..b + c} f"
proof (cases "a b")
  case True
  have "((λx. 1 *🪙R f (x + c)) has_integral integral {a+c..b+c} f) {a..b}"
    using True cont
    by (intro has_integral_substitution[where c = "a + c" and d = "b + c"])
       (auto intro!: derivative_eq_intros)
  thus ?thesis by (simp add: has_integral_iff o_def)
qed auto


subsection Compute a double integral using iterated integrals and switching the order of integration

lemma continuous_on_imp_integrable_on_Pair1:
  fixes f :: "_ ==> 'b::banach"
  assumes con: "continuous_on (cbox (a,c) (b,d)) f" and x: "x cbox a b"
  shows "(λy. f (x, y)) integrable_on (cbox c d)"
proof -
  have "f (λy. (x, y)) integrable_on (cbox c d)"
  proof (intro integrable_continuous continuous_on_compose [OF _ continuous_on_subset [OF con]])
    show "continuous_on (cbox c d) (Pair x)"
      by (simp add: continuous_on_Pair)
    show "Pair x ` cbox c d cbox (a,c) (b,d)"
      using x by blast
  qed
  then show ?thesis
    by (simp add: o_def)
qed

lemma integral_integrable_2dim:
  fixes f :: "('a::euclidean_space * 'b::euclidean_space) ==> 'c::banach"
  assumes "continuous_on (cbox (a,c) (b,d)) f"
    shows "(λx. integral (cbox c d) (λy. f (x,y))) integrable_on cbox a b"
proof (cases "content(cbox c d) = 0")
case True
  then show ?thesis
    by (simp add: True integrable_const)
next
  case False
  have uc: "uniformly_continuous_on (cbox (a,c) (b,d)) f"
    by (simp add: assms compact_cbox compact_uniformly_continuous)
  { fix x::'a and e::real
    assume x: "x cbox a b" and e: "0 < e"
    then have e2_gt: "0 < e/2 / content (cbox c d)" and e2_less: "e/2 / content (cbox c d) * content (cbox c d) < e"
      by (auto simp: False content_lt_nz e)
    then obtain dd
    where dd: "x x'. [xcbox (a, c) (b, d); x'cbox (a, c) (b, d); norm (x' - x) < dd]
                       ==> norm (f x' - f x) e/(2 * content (cbox c d))"  "dd>0"
      using uc [unfolded uniformly_continuous_on_def, THEN spec, of "e/(2 * content (cbox c d))"]
      by (auto simp: dist_norm intro: less_imp_le)
    have "delta>0. x'cbox a b. norm (x' - x) < delta norm (integral (cbox c d) (λu. f (x', u) - f (x, u))) < e"
      using dd e2_gt assms x
      apply (rule_tac x=dd in exI)
      apply clarify
      apply (rule le_less_trans [OF integrable_bound e2_less])
      apply (auto intro: integrable_diff continuous_on_imp_integrable_on_Pair1)
      done
  } note * = this
  show ?thesis
  proof (rule integrable_continuous)
    show "continuous_on (cbox a b) (λx. integral (cbox c d) (λy. f (x, y)))"
      by (simp add: * continuous_on_iff dist_norm integral_diff [symmetric] continuous_on_imp_integrable_on_Pair1 [OF assms])
  qed
qed

lemma integral_split:
  fixes f :: "'a::euclidean_space ==> 'b::{real_normed_vector,complete_space}"
  assumes f: "f integrable_on (cbox a b)"
      and k: "k Basis"
  shows "integral (cbox a b) f =
           integral (cbox a b {x. xk c}) f +
           integral (cbox a b {x. xk c}) f"
  using k f
  by (auto simp: has_integral_integral intro: integral_unique [OF has_integral_split])

lemma integral_swap_operativeI:
  fixes f :: "('a::euclidean_space * 'b::euclidean_space) ==> 'c::banach"
  assumes f: "continuous_on s f" and e: "0 < e"
    shows "operative conj True
           (λk. a b c d.
                cbox (a,c) (b,d) k cbox (a,c) (b,d) s
                 norm(integral (cbox (a,c) (b,d)) f -
                         integral (cbox a b) (λx. integral (cbox c d) (λy. f((x,y)))))
                     e * content (cbox (a,c) (b,d)))"
proof (standard, auto)
  fix a::'a and c::'b and b::'a and d::'b and u::'a and v::'a and w::'b and z::'b
  assume *: "box (a, c) (b, d) = {}"
     and cb1: "cbox (u, w) (v, z) cbox (a, c) (b, d)"
     and cb2: "cbox (u, w) (v, z) s"
  then have c0: "content (cbox (a, c) (b, d)) = 0"
    using * unfolding content_eq_0_interior by simp
  have c0': "content (cbox (u, w) (v, z)) = 0"
    by (fact content_0_subset [OF c0 cb1])
  show "norm (integral (cbox (u,w) (v,z)) f - integral (cbox u v) (λx. integral (cbox w z) (λy. f (x, y))))
           e * content (cbox (u,w) (v,z))"
    using content_cbox_pair_eq0_D [OF c0']
    by (force simp: c0')
next
  fix a::'a and c::'b and b::'a and d::'b
  and M::real and i::'a and j::'b
  and u::'a and v::'a and w::'b and z::'b
  assume ij: "(i,j) Basis"
     and n1: "a' b' c' d'.
                cbox (a',c') (b',d') cbox (a,c) (b,d)
                cbox (a',c') (b',d') {x. x (i,j) M} cbox (a',c') (b',d') s
                norm (integral (cbox (a',c') (b',d')) f - integral (cbox a' b') (λx. integral (cbox c' d') (λy. f (x,y))))
                 e * content (cbox (a',c') (b',d'))"
     and n2: "a' b' c' d'.
                cbox (a',c') (b',d') cbox (a,c) (b,d)
                cbox (a',c') (b',d') {x. M x (i,j)} cbox (a',c') (b',d') s
                norm (integral (cbox (a',c') (b',d')) f - integral (cbox a' b') (λx. integral (cbox c' d') (λy. f (x,y))))
                 e * content (cbox (a',c') (b',d'))"
     and subs: "cbox (u,w) (v,z) cbox (a,c) (b,d)"  "cbox (u,w) (v,z) s"
  have fcont: "continuous_on (cbox (u, w) (v, z)) f"
    using assms(1) continuous_on_subset  subs(2) by blast
  then have fint: "f integrable_on cbox (u, w) (v, z)"
    by (metis integrable_continuous)
  consider "i Basis" "j=0" | "j Basis" "i=0"  using ij
    by (auto simp: Euclidean_Space.Basis_prod_def)
  then show "norm (integral (cbox (u,w) (v,z)) f - integral (cbox u v) (λx. integral (cbox w z) (λy. f (x,y))))
              e * content (cbox (u,w) (v,z))" (is ?normle)
  proof cases
    case 1
    then have e: "e * content (cbox (u, w) (v, z)) =
                  e * (content (cbox u v {x. x i M}) * content (cbox w z)) +
                  e * (content (cbox u v {x. M x i}) * content (cbox w z))"
      by (simp add: content_split [where c=M] content_Pair algebra_simps)
    have *: "integral (cbox u v) (λx. integral (cbox w z) (λy. f (x, y))) =
                integral (cbox u v {x. x i M}) (λx. integral (cbox w z) (λy. f (x, y))) +
                integral (cbox u v {x. M x i}) (λx. integral (cbox w z) (λy. f (x, y)))"
      using 1 f subs integral_integrable_2dim continuous_on_subset
      by (blast intro: integral_split)
    show ?normle
      apply (rule norm_diff2 [OF integral_split [where c=M, OF fint ij] * e])
      using 1 subs
      apply (simp_all add: cbox_Pair_eq setcomp_dot1 [of "λu. Mu"] setcomp_dot1 [of "λu. uM"] Sigma_Int_Paircomp1)
      apply (simp_all add: interval_split ij flip: cbox_Pair_eq content_Pair)
      apply (force simp flip: interval_split intro!: n1 [rule_format])
      apply (force simp flip: interval_split intro!: n2 [rule_format])
      done
  next
    case 2
    then have e: "e * content (cbox (u, w) (v, z)) =
                  e * (content (cbox u v) * content (cbox w z {x. x j M})) +
                  e * (content (cbox u v) * content (cbox w z {x. M x j}))"
      by (simp add: content_split [where c=M] content_Pair algebra_simps)
    have "(λx. integral (cbox w z {x. x j M}) (λy. f (x, y))) integrable_on cbox u v"
         "(λx. integral (cbox w z {x. M x j}) (λy. f (x, y))) integrable_on cbox u v"
      using 2 subs
      apply (simp_all add: interval_split)
      apply (rule integral_integrable_2dim [OF continuous_on_subset [OF f]]; auto simp: cbox_Pair_eq interval_split [symmetric])+
      done
    with 2 have *: "integral (cbox u v) (λx. integral (cbox w z) (λy. f (x, y))) =
                   integral (cbox u v) (λx. integral (cbox w z {x. x j M}) (λy. f (x, y))) +
                   integral (cbox u v) (λx. integral (cbox w z {x. M x j}) (λy. f (x, y)))"
      by (simp add: integral_add [symmetric] integral_split [symmetric]
                    continuous_on_imp_integrable_on_Pair1 [OF fcont] cong: integral_cong)
    show ?normle
      apply (rule norm_diff2 [OF integral_split [where c=M, OF fint ij] * e])
      using 2 subs
      apply (simp_all add: cbox_Pair_eq setcomp_dot2 [of "λu. Mu"] setcomp_dot2 [of "λu. uM"] Sigma_Int_Paircomp2)
      apply (simp_all add: interval_split ij flip: cbox_Pair_eq content_Pair)
      apply (force simp flip: interval_split intro!: n1 [rule_format])
      apply (force simp flip: interval_split intro!: n2 [rule_format])
      done
  qed
qed

lemma integral_Pair_const:
    "integral (cbox (a,c) (b,d)) (λx. k) =
     integral (cbox a b) (λx. integral (cbox c d) (λy. k))"
  by (simp add: content_Pair)

lemma integral_prod_continuous:
  fixes f :: "('a::euclidean_space * 'b::euclidean_space) ==> 'c::banach"
  assumes "continuous_on (cbox (a, c) (b, d)) f" (is "continuous_on ?CBOX f")
    shows "integral (cbox (a, c) (b, d)) f = integral (cbox a b) (λx. integral (cbox c d) (λy. f (x, y)))"
proof (cases "content ?CBOX = 0")
  case True
  then show ?thesis
    by (auto simp: content_Pair)
next
  case False
  then have cbp: "content ?CBOX > 0"
    using content_lt_nz by blast
  have "norm (integral ?CBOX f - integral (cbox a b) (λx. integral (cbox c d) (λy. f (x,y)))) = 0"
  proof (rule dense_eq0_I, simp)
    fix e :: real 
    assume "0 < e"
    with content ?CBOX > 0 have "0 < e/content ?CBOX"
      by simp
    have f_int_acbd: "f integrable_on ?CBOX"
      by (rule integrable_continuous [OF assms])
    { fix p
      assume p: "p division_of ?CBOX"
      then have "finite p"
        by blast
      define e' where "e' = e/content ?CBOX"
      with 0 🚫 0 🚫/content ?CBOX
      have "0 < e'"
        by simp
      interpret operative conj True
           "λk. a' b' c' d'.
                cbox (a', c') (b', d') k cbox (a', c') (b', d') ?CBOX
                 norm (integral (cbox (a', c') (b', d')) f -
                         integral (cbox a' b') (λx. integral (cbox c' d') (λy. f ((x, y)))))
                     e' * content (cbox (a', c') (b', d'))"
        using assms 0 🚫' by (rule integral_swap_operativeI)
      have "norm (integral ?CBOX f - integral (cbox a b) (λx. integral (cbox c d) (λy. f (x, y))))
           e' * content ?CBOX"
        if "t u v w z. t p ==> cbox (u, w) (v, z) t ==> cbox (u, w) (v, z) ?CBOX
          ==> norm (integral (cbox (u, w) (v, z)) f -
              integral (cbox u v) (λx. integral (cbox w z) (λy. f (x, y))))
               e' * content (cbox (u, w) (v, z))"
        using that division [of p "(a, c)" "(b, d)"] p finite p by (auto simp: comm_monoid_set_F_and)
      with False have "norm (integral ?CBOX f - integral (cbox a b) (λx. integral (cbox c d) (λy. f (x, y))))
           e"
        if "t u v w z. t p ==> cbox (u, w) (v, z) t ==> cbox (u, w) (v, z) ?CBOX
          ==> norm (integral (cbox (u, w) (v, z)) f -
              integral (cbox u v) (λx. integral (cbox w z) (λy. f (x, y))))
               e * content (cbox (u, w) (v, z)) / content ?CBOX"
        using that by (simp add: e'_def)
    } note op_acbd = this
    { fix k::real and D and u::'a and v w and z::'b and t1 t2 l
      let ?CBUZ = "cbox (u,w) (v,z)"
      assume k: "0 < k"
         and nf: "x y u v.
                  [x cbox a b; y cbox c d; u cbox a b; vcbox c d; norm (u-x, v-y) < k]
                  ==> norm (f(u,v) - f(x,y)) < e/(2 * (content ?CBOX))"
         and p_acbd: "D tagged_division_of cbox (a,c) (b,d)"
         and fine: "(λx. ball x k) fine D"  "((t1,t2), l) D"
         and uwvz_sub: "?CBUZ l" "?CBUZ cbox (a,c) (b,d)"
      have t: "t1 cbox a b" "t2 cbox c d"
        by (meson fine p_acbd cbox_Pair_iff tag_in_interval)+
      have ls: "l ball (t1,t2) k"
        using fine by (simp add: fine_def Ball_def)
      { fix x1 x2
        assume xuvwz: "x1 cbox u v" "x2 cbox w z"
        then have x: "x1 cbox a b" "x2 cbox c d"
          using uwvz_sub by auto
        have "norm (x1 - t1, x2 - t2) = norm (t1 - x1, t2 - x2)"
          by (simp add: norm_Pair norm_minus_commute)
        also have "norm (t1 - x1, t2 - x2) < k"
          using xuvwz ls uwvz_sub unfolding ball_def
          by (force simp: cbox_Pair_eq dist_norm )
        finally have "norm (f (x1,x2) - f (t1,t2)) e/content ?CBOX/2"
          using nf [OF t x]  by simp
      } note nf' = this
      have f_int_uwvz: "f integrable_on ?CBUZ"
        using f_int_acbd uwvz_sub integrable_on_subcbox by blast
      have f_int_uv: "x. x cbox u v ==> (λy. f (x,y)) integrable_on cbox w z"
        using assms continuous_on_subset uwvz_sub
        by (blast intro: continuous_on_imp_integrable_on_Pair1)
      have 1: "norm (integral ?CBUZ f - integral ?CBUZ (λx. f (t1,t2)))
              e * content ?CBUZ / content ?CBOX/2"
        using cbp 0 🚫/content ?CBOX nf'
        apply (simp only: integral_diff [symmetric] f_int_uwvz integrable_const)
        apply (auto simp: integrable_diff f_int_uwvz integrable_const intro: order_trans [OF integrable_bound [of "e/content ?CBOX/2"]])
        done
      have int_integrable: "(λx. integral (cbox w z) (λy. f (x, y))) integrable_on cbox u v"
        using assms integral_integrable_2dim continuous_on_subset uwvz_sub(2) by blast
      have normint_wz:
         "x. x cbox u v ==>
               norm (integral (cbox w z) (λy. f (x, y)) - integral (cbox w z) (λy. f (t1, t2)))
                e * content (cbox w z) / content (cbox (a, c) (b, d))/2"
        using cbp 0 🚫/content ?CBOX nf'
        apply (simp only: integral_diff [symmetric] f_int_uv integrable_const)
        apply (auto simp: integrable_diff f_int_uv integrable_const intro: order_trans [OF integrable_bound [of "e/content ?CBOX/2"]])
        done
      have "norm (integral (cbox u v)
               (λx. integral (cbox w z) (λy. f (x,y)) - integral (cbox w z) (λy. f (t1,t2))))
             e * content (cbox w z) / content ?CBOX/2 * content (cbox u v)"
        using cbp 0 🚫/content ?CBOX
        apply (intro integrable_bound [OF _ _ normint_wz])
        apply (auto simp: field_split_simps integrable_diff int_integrable integrable_const)
        done
      also have " e * content ?CBUZ / content ?CBOX/2"
        by (simp add: content_Pair field_split_simps)
      finally have 2: "norm (integral (cbox u v) (λx. integral (cbox w z) (λy. f (x,y))) -
                      integral (cbox u v) (λx. integral (cbox w z) (λy. f (t1,t2))))
                 e * content ?CBUZ / content ?CBOX/2"
        by (simp only: integral_diff [symmetric] int_integrable integrable_const)
      have norm_xx: "[x' = y'; norm(x - x') e/2; norm(y - y') e/2] ==> norm(x - y) e" for x::'c and y x' y' e
        using norm_triangle_mono [of "x-y'" "e/2" "y'-y" "e/2"] field_sum_of_halves
        by (simp add: norm_minus_commute)
      have "norm (integral ?CBUZ f - integral (cbox u v) (λx. integral (cbox w z) (λy. f (x,y))))
             e * content ?CBUZ / content ?CBOX"
        by (rule norm_xx [OF integral_Pair_const 1 2])
    } note * = this
    have "norm (integral ?CBOX f - integral (cbox a b) (λx. integral (cbox c d) (λy. f (x,y)))) e" 
      if "x?CBOX. x'?CBOX. norm (x' - x) < k norm (f x' - f x) < e /(2 * content (?CBOX))" "0 < k" for k
    proof -
      obtain p where ptag: "p tagged_division_of cbox (a, c) (b, d)" 
                 and fine: "(λx. ball x k) fine p"
        using fine_division_exists 0 🚫 by blast
      show ?thesis
        using that fine ptag 0 🚫
        by (auto simp: * intro: op_acbd [OF division_of_tagged_division [OF ptag]])
    qed
    then show "norm (integral ?CBOX f - integral (cbox a b) (λx. integral (cbox c d) (λy. f (x,y)))) e"
      using compact_uniformly_continuous [OF assms compact_cbox]
      apply (simp add: uniformly_continuous_on_def dist_norm)
      apply (drule_tac x="e/2 / content?CBOX" in spec)
      using cbp 0 🚫 by (auto simp: zero_less_mult_iff)
  qed
  then show ?thesis
    by simp
qed

lemma integral_swap_2dim:
  fixes f :: "['a::euclidean_space, 'b::euclidean_space] ==> 'c::banach"
  assumes "continuous_on (cbox (a,c) (b,d)) (λ(x,y). f x y)"
    shows "integral (cbox (a, c) (b, d)) (λ(x, y). f x y) = integral (cbox (c, a) (d, b)) (λ(x, y). f y x)"
proof -
  have "((λ(x, y). f x y) has_integral integral (cbox (c, a) (d, b)) (λ(x, y). f y x)) (prod.swap ` (cbox (c, a) (d, b)))"
  proof (rule has_integral_twiddle [of 1 prod.swap prod.swap "λ(x,y). f y x" "integral (cbox (c, a) (d, b)) (λ(x, y). f y x)", simplified])
    show "u v. content (prod.swap ` cbox u v) = content (cbox u v)"
      by (metis content_Pair mult.commute old.prod.exhaust swap_cbox_Pair)
    show "((λ(x, y). f y x) has_integral integral (cbox (c, a) (d, b)) (λ(x, y). f y x)) (cbox (c, a) (d, b))"
      by (simp add: assms integrable_continuous integrable_integral swap_continuous)
  qed (use isCont_swap in fastforce+)
 then show ?thesis
   by force
qed

theorem integral_swap_continuous:
  fixes f :: "['a::euclidean_space, 'b::euclidean_space] ==> 'c::banach"
  assumes "continuous_on (cbox (a,c) (b,d)) (λ(x,y). f x y)"
    shows "integral (cbox a b) (λx. integral (cbox c d) (f x)) =
           integral (cbox c d) (λy. integral (cbox a b) (λx. f x y))"
proof -
  have "integral (cbox a b) (λx. integral (cbox c d) (f x)) = integral (cbox (a, c) (b, d)) (λ(x, y). f x y)"
    using integral_prod_continuous [OF assms] by auto
  also have " = integral (cbox (c, a) (d, b)) (λ(x, y). f y x)"
    by (rule integral_swap_2dim [OF assms])
  also have " = integral (cbox c d) (λy. integral (cbox a b) (λx. f x y))"
    using integral_prod_continuous [OF swap_continuous] assms
    by auto
  finally show ?thesis .
qed


subsection Definite integrals for exponential and power function

text This lemma packages up a reference to @{thm[source]monotone_convergence_increasing}
lemma has_integral_to_inf:
  fixes h ::"real ==> real"
  assumes int: "y::real. h integrable_on {a..y}"
    and lim: "((λy. integral {a..y} h) ---> l) at_top"
    and nonneg: "y. y a ==> h y 0"
  shows "(h has_integral l) {a..}"
proof -
  have ge: "integral {a..y} h 0" for y
    by (meson Henstock_Kurzweil_Integration.integral_nonneg atLeastAtMost_iff int nonneg)
  then have "l 0"
    using tendsto_lowerbound [OF lim] by simp 
  have "mono (λy. integral {a..y} h)"
    by (simp add: int integral_subset_le monoI nonneg)
  then have int_le_l: "integral {a..y} h l" for y
    using order_tendstoD [OF lim, of "integral {a..y} h"]
    by (smt (verit) eventually_at_top_linorder monotoneD nle_le)
  define f where "f λn x. if x {a..of_nat n} then h x else 0"
  have has_integral_f: "n. (f n has_integral (integral {a..of_nat n} h)) {a..}"
    unfolding f_def
    by (metis (no_types, lifting) ext Icc_subset_Ici_iff order.refl
        has_integral_restrict int integrable_integral)

  have integral_f: "integral {a..} (f n) = (if n a then integral {a..of_nat n} h else 0)" for n
    by (meson atLeastAtMost_iff f_def has_integral_f has_integral_iff has_integral_is_0 order_trans)
  have *: "h integrable_on {a..} (λn. integral {a..} (f n)) <---- integral {a..} h"
  proof (intro monotone_convergence_increasing allI ballI)
    fix n
    show "f n integrable_on {a..}"
      using has_integral_f by blast
  next
    fix n x
    show "f n x f (Suc n) x" using nonneg by (auto simp: f_def)
  next
    fix x :: real assume x: "x {a..}"
    have "eventually (λn. real n x) at_top"
      by (meson eventually_sequentiallyI nat_ceiling_le_eq)
    with x have "eventually (λn. f n x = h x) at_top"
      by (simp add: eventually_mono f_def)
    thus "(λn. f n x) <---- h x" by (simp add: tendsto_eventually)
  next
    have "norm (integral {a..} (f n)) l" for n
      by (simp add: 0 l ge int_le_l integral_f)
    thus "bounded (range(λk. integral {a..} (f k)))"
      by (metis (no_types, lifting) boundedI rangeE)
  qed
  have "eventually (λn. integral {a..n} h = integral {a..} (f n)) at_top"
    by (metis (mono_tags, lifting) eventuallyI has_integral_f integral_unique)
  moreover have "((λy. integral {a..y} h) real) <---- l"
    unfolding tendsto_compose_filtermap
    using filterlim_def filterlim_real_sequentially lim tendsto_mono by blast
  ultimately have "(λn. integral {a..} (f n)) <---- l"
    by (force intro: Lim_transform_eventually)
  then show ?thesis
    using "*" LIMSEQ_unique by blast
qed

lemma has_integral_exp_minus_to_infinity:
  assumes "a > 0"
  shows   "((λx::real. exp (-a*x)) has_integral exp (-a*c)/a) {c..}"
proof (intro has_integral_to_inf integrable_continuous_interval continuous_intros)
  have "((λx. exp (-a*x)) has_integral (-exp (-a*y)/a - (-exp (-a*c)/a))) {c..y}"
    if "y c" for y
    using that a > 0
      by (intro fundamental_theorem_of_calculus)
         (auto intro!: derivative_eq_intros
               simp flip: has_real_derivative_iff_has_vector_derivative)    
  then have "🪙F y in at_top. integral {c..y} (λx. exp (-a*x)) = -exp (-a*y)/a + exp (-a*c)/a"
    using eventually_at_top_linorder[of
        "λy. integral {c..y} (λx. exp (-a*x)) = -exp (-a*y)/a + exp (-a*c)/a"]
    by auto
  moreover have "((λy::real. -exp (-a*y)/a + exp (-a*c)/a) ---> exp (-a*c)/a) at_top"
    using a > 0 by real_asymp
  ultimately show "((λy. integral {c..y} (λx. exp (-a*x))) ---> exp (-a*c)/a) at_top"
    by (simp add: filterlim_cong)
qed auto

lemma integrable_on_exp_minus_to_infinity: "a > 0 ==> (λx. exp (-a*x) :: real) integrable_on {c..}"
  using has_integral_exp_minus_to_infinity[of a c] unfolding integrable_on_def by blast

lemma has_integral_powr_from_0:
  assumes a: "a > (-1::real)" and c: "c 0"
  shows   "((λx. x powr a) has_integral (c powr (a+1) / (a+1))) {0..c}"
proof (cases "c = 0")
  case False
  define f where "f = (λk x. if x {inverse (of_nat (Suc k))..c} then x powr a else 0)"
  define F where "F = (λk. if inverse (of_nat (Suc k)) c then
                             c powr (a+1)/(a+1) - inverse (real (Suc k)) powr (a+1)/(a+1) else 0)"
  have has_integral_f: "(f k has_integral F k) {0..c}" for k::nat
  proof (cases "inverse (of_nat (Suc k)) c")
    case True
    have x: "x > 0" if "x inverse (1 + real k)" for x
      by (metis inverse_Suc of_nat_Suc order_less_le_trans that)
    hence "((λx. x powr a) has_integral c powr (a + 1) / (a + 1) -
               inverse (real (Suc k)) powr (a + 1) / (a + 1)) {inverse (real (Suc k))..c}"
      using True a 
    proof (intro fundamental_theorem_of_calculus)
    qed (auto intro!: derivative_eq_intros continuous_on_powr' continuous_on_const
          simp flip: has_real_derivative_iff_has_vector_derivative)
    with True show ?thesis unfolding f_def F_def by (subst has_integral_restrict) simp_all
  next
    case False
    thus ?thesis unfolding f_def F_def
      by force 
  qed
  then have integral_f: "integral {0..c} (f k) = F k" for k
    by blast

  have A: "(λx. x powr a) integrable_on {0..c}
           (λk. integral {0..c} (f k)) <---- integral {0..c} (λx. x powr a)"
  proof (intro monotone_convergence_increasing ballI allI)
    fix k from has_integral_f[of k] show "f k integrable_on {0..c}"
      by (auto simp: integrable_on_def)
  next
    fix k :: nat and x :: real
    {
      assume x: "inverse (real (Suc k)) x"
      then have "inverse (real (Suc (Suc k))) x"
        using dual_order.trans by fastforce 
    }
    thus "f k x f (Suc k) x" by (auto simp: f_def simp del: of_nat_Suc)
  next
    fix x assume x: "x {0..c}"
    show "(λk. f k x) <---- x powr a"
    proof (cases "x = 0")
      case False
      with x have "x > 0" by simp
      from order_tendstoD(2)[OF LIMSEQ_inverse_real_of_nat this]
        have "eventually (λk. x powr a = f k x) sequentially"
        by eventually_elim (insert x, simp add: f_def)
      moreover have "(λ_. x powr a) <---- x powr a" by simp
      ultimately show ?thesis by (blast intro: Lim_transform_eventually)
    qed (simp_all add: f_def)
  next
    {
      fix k
      from a have "F k c powr (a + 1) / (a + 1)"
        by (auto simp: F_def divide_simps)
      also from a have "F k 0"
        by (auto simp: F_def divide_simps simp del: of_nat_Suc intro!: powr_mono2)
      hence "F k = abs (F k)" by simp
      finally have "abs (F k) c powr (a + 1) / (a + 1)" .
    }
    thus "bounded (range(λk. integral {0..c} (f k)))"
      by (intro boundedI[of _ "c powr (a+1) / (a+1)"]) (auto simp: integral_f)
  qed

  from False c have "c > 0" by simp
  from order_tendstoD(2)[OF LIMSEQ_inverse_real_of_nat this]
    have "eventually (λk. c powr (a + 1) / (a + 1) - inverse (real (Suc k)) powr (a+1) / (a+1) =
            integral {0..c} (f k)) sequentially"
    by eventually_elim (simp add: integral_f F_def)
  moreover have "(λk. c powr (a + 1) / (a + 1) - inverse (real (Suc k)) powr (a + 1) / (a + 1))
                   <---- c powr (a + 1) / (a + 1) - 0 powr (a + 1) / (a + 1)"
    using a by (intro tendsto_intros LIMSEQ_inverse_real_of_nat) auto
  hence "(λk. c powr (a + 1) / (a + 1) - inverse (real (Suc k)) powr (a + 1) / (a + 1))
          <---- c powr (a + 1) / (a + 1)" by simp
  ultimately have "(λk. integral {0..c} (f k)) <---- c powr (a+1) / (a+1)"
    by (blast intro: Lim_transform_eventually)
  with A have "integral {0..c} (λx. x powr a) = c powr (a+1) / (a+1)"
    by (blast intro: LIMSEQ_unique)
  with A show ?thesis by (simp add: has_integral_integral)
qed (simp_all add: has_integral_refl)

lemma integrable_on_powr_from_0:
  assumes a: "a > (-1::real)" and c: "c 0"
  shows   "(λx. x powr a) integrable_on {0..c}"
  using has_integral_powr_from_0[OF assms] unfolding integrable_on_def by blast
lemma has_integral_powr_to_inf:
  fixes a e :: real
  assumes "e < -1" "a > 0"
  shows   "((λx. x powr e) has_integral -(a powr (e+1)) / (e+1)) {a..}"
proof (intro has_integral_to_inf integrable_continuous_interval continuous_intros)
  define F where "F λx. x powr (e+1) / (e+1)"
  have "((λx. x powr e) has_integral (F y - F a)) {a..y}" if "y a" for y
    unfolding F_def using assms
    by (intro fundamental_theorem_of_calculus that)
       (auto intro!: derivative_eq_intros
               simp flip: has_real_derivative_iff_has_vector_derivative)
  then have "🪙F y in at_top. integral {a..y} (λx. x powr e) = F y - F a"
    by (meson eventually_at_top_linorderI integral_unique)
  moreover have "((λy::real. F y - F a) ---> - F a) at_top"
    using assms unfolding F_def by real_asymp
  ultimately 
  show "((λy. integral {a..y} (λx. x powr e)) ---> - (a powr (e+1)) / (e+1)) at_top"
    by (simp add: F_def filterlim_cong)
qed (use assms in auto)

lemma has_integral_inverse_power_to_inf:
  fixes a :: real and n :: nat
  assumes "n > 1" "a > 0"
  shows   "((λx. 1 / x ^ n) has_integral 1 / (real (n - 1) * a ^ (n - 1))) {a..}"
proof -
  from assms have "real_of_int (-int n) < -1" by simp
  note has_integral_powr_to_inf[OF this a > 0]
  also have "- (a powr (real_of_int (- int n) + 1)) / (real_of_int (- int n) + 1) =
                 1 / (real (n - 1) * a powr (real (n - 1)))" using assms
    by (simp add: field_split_simps powr_add [symmetric] of_nat_diff)
  also from assms have "a powr (real (n - 1)) = a ^ (n - 1)"
    by (intro powr_realpow)
  finally show ?thesis
  proof (rule has_integral_eq [rotated])
  qed (insert assms, simp_all add: powr_minus powr_realpow field_split_simps)
qed

subsection Adaption to ordered Euclidean spaces and the Cartesian Euclidean space

lemma integral_component_eq_cart[simp]:
  fixes f :: "'n::euclidean_space ==> real^'m"
  assumes "f integrable_on s"
  shows "integral s (λx. f x $ k) = integral s f $ k"
  using integral_linear[OF assms(1) bounded_linear_vec_nth,unfolded o_def] .

lemma content_closed_interval:
  fixes a :: "'a::ordered_euclidean_space"
  assumes "a b"
  shows "content {a..b} = (iBasis. bi - ai)"
  using content_cbox[of a b] assms by (simp add: cbox_interval eucl_le[where 'a='a])

lemma integrable_const_ivl[intro]:
  fixes a::"'a::ordered_euclidean_space"
  shows "(λx. c) integrable_on {a..b}"
  unfolding cbox_interval[symmetric] by (rule integrable_const)

lemma integrable_on_subinterval:
  fixes f :: "'n::ordered_euclidean_space ==> 'a::banach"
  assumes "f integrable_on S" "{a..b} S"
  shows "f integrable_on {a..b}"
  using integrable_on_subcbox[of f S a b] assms by (simp add: cbox_interval)

end

Messung V0.5 in Prozent
C=93 H=73 G=83

¤ 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.1.37Bemerkung:  (vorverarbeitet am  2026-04-27) ¤

*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.