/-
Copyright (c) 2021 Yury Kudryashov. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yury Kudryashov

! This file was ported from Lean 3 source module analysis.complex.cauchy_integral
! leanprover-community/mathlib commit f2ce6086713c78a7f880485f7917ea547a215982
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.MeasureTheory.Measure.ComplexLebesgue
import Mathbin.MeasureTheory.Integral.DivergenceTheorem
import Mathbin.MeasureTheory.Integral.CircleIntegral
import Mathbin.Analysis.Calculus.Dslope
import Mathbin.Analysis.Analytic.Basic
import Mathbin.Analysis.Complex.ReImTopology
import Mathbin.Analysis.Calculus.DiffContOnCl
import Mathbin.Data.Real.Cardinality

/-!
# Cauchy integral formula

In this file we prove the Cauchy-Goursat theorem and the Cauchy integral formula for integrals over
circles. Most results are formulated for a function `f : ℂ → E` that takes values in a complex
Banach space with second countable topology.

## Main statements

In the following theorems, if the name ends with `off_countable`, then the actual theorem assumes
differentiability at all but countably many points of the set mentioned below.

* `complex.integral_boundary_rect_of_has_fderiv_within_at_real_off_countable`: If a function
  `f : ℂ → E` is continuous on a closed rectangle and *real* differentiable on its interior, then
  its integral over the boundary of this rectangle is equal to the integral of
  `I • f' (x + y * I) 1 - f' (x + y * I) I` over the rectangle, where `f' z w : E` is the derivative
  of `f` at `z` in the direction `w` and `I = complex.I` is the imaginary unit.

* `complex.integral_boundary_rect_eq_zero_of_differentiable_on_off_countable`: If a function
  `f : ℂ → E` is continuous on a closed rectangle and is *complex* differentiable on its interior,
  then its integral over the boundary of this rectangle is equal to zero.

* `complex.circle_integral_sub_center_inv_smul_eq_of_differentiable_on_annulus_off_countable`: If a
  function `f : ℂ → E` is continuous on a closed annulus `{z | r ≤ |z - c| ≤ R}` and is complex
  differentiable on its interior `{z | r < |z - c| < R}`, then the integrals of `(z - c)⁻¹ • f z`
  over the outer boundary and over the inner boundary are equal.

* `complex.circle_integral_sub_center_inv_smul_of_differentiable_on_off_countable_of_tendsto`,
  `complex.circle_integral_sub_center_inv_smul_of_differentiable_on_off_countable`:
  If a function `f : ℂ → E` is continuous on a punctured closed disc `{z | |z - c| ≤ R ∧ z ≠ c}`, is
  complex differentiable on the corresponding punctured open disc, and tends to `y` as `z → c`,
  `z ≠ c`, then the integral of `(z - c)⁻¹ • f z` over the circle `|z - c| = R` is equal to
  `2πiy`. In particular, if `f` is continuous on the whole closed disc and is complex differentiable
  on the corresponding open disc, then this integral is equal to `2πif(c)`.

* `complex.circle_integral_sub_inv_smul_of_differentiable_on_off_countable`,
  `complex.two_pi_I_inv_smul_circle_integral_sub_inv_smul_of_differentiable_on_off_countable`
  **Cauchy integral formula**: if `f : ℂ → E` is continuous on a closed disc of radius `R` and is
  complex differentiable on the corresponding open disc, then for any `w` in the corresponding open
  disc the integral of `(z - w)⁻¹ • f z` over the boundary of the disc is equal to `2πif(w)`.
  Two versions of the lemma put the multiplier `2πi` at the different sides of the equality.

* `complex.has_fpower_series_on_ball_of_differentiable_off_countable`: If `f : ℂ → E` is continuous
  on a closed disc of positive radius and is complex differentiable on the corresponding open disc,
  then it is analytic on the corresponding open disc, and the coefficients of the power series are
  given by Cauchy integral formulas.

* `differentiable_on.has_fpower_series_on_ball`: If `f : ℂ → E` is complex differentiable on a
  closed disc of positive radius, then it is analytic on the corresponding open disc, and the
  coefficients of the power series are given by Cauchy integral formulas.

* `differentiable_on.analytic_at`, `differentiable.analytic_at`: If `f : ℂ → E` is differentiable
  on a neighborhood of a point, then it is analytic at this point. In particular, if `f : ℂ → E`
  is differentiable on the whole `ℂ`, then it is analytic at every point `z : ℂ`.

* `differentiable.has_power_series_on_ball`: If `f : ℂ → E` is differentiable everywhere then the
  `cauchy_power_series f z R` is a formal power series representing `f` at `z` with infinite
  radius of convergence (this holds for any choice of `0 < R`).

## Implementation details

The proof of the Cauchy integral formula in this file is based on a very general version of the
divergence theorem, see `measure_theory.integral_divergence_of_has_fderiv_within_at_off_countable`
(a version for functions defined on `fin (n + 1) → ℝ`),
`measure_theory.integral_divergence_prod_Icc_of_has_fderiv_within_at_off_countable_of_le`, and
`measure_theory.integral2_divergence_prod_of_has_fderiv_within_at_off_countable` (versions for
functions defined on `ℝ × ℝ`).

Usually, the divergence theorem is formulated for a $C^1$ smooth function. The theorems formulated
above deal with a function that is

* continuous on a closed box/rectangle;
* differentiable at all but countably many points of its interior;
* have divergence integrable over the closed box/rectangle.

First, we reformulate the theorem for a *real*-differentiable map `ℂ → E`, and relate the integral
of `f` over the boundary of a rectangle in `ℂ` to the integral of the derivative
$\frac{\partial f}{\partial \bar z}$ over the interior of this box. In particular, for a *complex*
differentiable function, the latter derivative is zero, hence the integral over the boundary of a
rectangle is zero. Thus we get the Cauchy-Goursat theorem for a rectangle in `ℂ`.

Next, we apply the this theorem to the function $F(z)=f(c+e^{z})$ on the rectangle
$[\ln r, \ln R]\times [0, 2\pi]$ to prove that
$$
  \oint_{|z-c|=r}\frac{f(z)\,dz}{z-c}=\oint_{|z-c|=R}\frac{f(z)\,dz}{z-c}
$$
provided that `f` is continuous on the closed annulus `r ≤ |z - c| ≤ R` and is complex
differentiable on its interior `r < |z - c| < R` (possibly, at all but countably many points).

Here and below, we write $\frac{f(z)}{z-c}$ in the documentation while the actual lemmas use
`(z - c)⁻¹ • f z` because `f z` belongs to some Banach space over `ℂ` and `f z / (z - c)` is
undefined.

Taking the limit of this equality as `r` tends to `𝓝[>] 0`, we prove
$$
  \oint_{|z-c|=R}\frac{f(z)\,dz}{z-c}=2\pi if(c)
$$
provided that `f` is continuous on the closed disc `|z - c| ≤ R` and is differentiable at all but
countably many points of its interior. This is the Cauchy integral formula for the center of a
circle. In particular, if we apply this function to `F z = (z - c) • f z`, then we get
$$
  \oint_{|z-c|=R} f(z)\,dz=0.
$$

In order to deduce the Cauchy integral formula for any point `w`, `|w - c| < R`, we consider the
slope function `g : ℂ → E` given by `g z = (z - w)⁻¹ • (f z - f w)` if `z ≠ w` and `g w = f' w`.
This function satisfies assumptions of the previous theorem, so we have
$$
  \oint_{|z-c|=R} \frac{f(z)\,dz}{z-w}=\oint_{|z-c|=R} \frac{f(w)\,dz}{z-w}=
  \left(\oint_{|z-c|=R} \frac{dz}{z-w}\right)f(w).
$$
The latter integral was computed in `circle_integral.integral_sub_inv_of_mem_ball` and is equal to
`2 * π * complex.I`.

There is one more step in the actual proof. Since we allow `f` to be non-differentiable on a
countable set `s`, we cannot immediately claim that `g` is continuous at `w` if `w ∈ s`. So, we use
the proof outlined in the previous paragraph for `w ∉ s` (see
`complex.circle_integral_sub_inv_smul_of_differentiable_on_off_countable_aux`), then use continuity
of both sides of the formula and density of `sᶜ` to prove the formula for all points of the open
ball, see `complex.circle_integral_sub_inv_smul_of_differentiable_on_off_countable`.

Finally, we use the properties of the Cauchy integrals established elsewhere (see
`has_fpower_series_on_cauchy_integral`) and Cauchy integral formula to prove that the original
function is analytic on the open ball.

## Tags

Cauchy-Goursat theorem, Cauchy integral formula
-/

open TopologicalSpace Set MeasureTheory intervalIntegral Metric Filter Function

open Interval Real NNReal ENNReal Topology BigOperators

noncomputable section

universe u

variable {E : Type u} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E]

namespace Complex

/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
/-- Suppose that a function `f : ℂ → E` is continuous on a closed rectangle with opposite corners at
`z w : ℂ`, is *real* differentiable at all but countably many points of the corresponding open
rectangle, and $\frac{\partial f}{\partial \bar z}$ is integrable on this rectangle. Then the
integral of `f` over the boundary of the rectangle is equal to the integral of
$2i\frac{\partial f}{\partial \bar z}=i\frac{\partial f}{\partial x}-\frac{\partial f}{\partial y}$
over the rectangle. -/
theorem integral_boundary_rect_of_hasFderivAt_real_off_countable (f : ℂ → E) (f' : ℂ → ℂ →L[ℝ] E)
    (z w : ℂ) (s : Set ℂ) (hs : s.Countable) (Hc : ContinuousOn f ([z.re, w.re] ×ℂ [z.im, w.im]))
    (Hd :
      ∀ x ∈ Ioo (min z.re w.re) (max z.re w.re) ×ℂ Ioo (min z.im w.im) (max z.im w.im) \ s,
        HasFderivAt f (f' x) x)
    (Hi : IntegrableOn (fun z => I • f' z 1 - f' z I) ([z.re, w.re] ×ℂ [z.im, w.im])) :
    ((((∫ x : ℝ in z.re..w.re, f (x + z.im * I)) - ∫ x : ℝ in z.re..w.re, f (x + w.im * I)) +
          I • ∫ y : ℝ in z.im..w.im, f (re w + y * I)) -
        I • ∫ y : ℝ in z.im..w.im, f (re z + y * I)) =
      ∫ x : ℝ in z.re..w.re, ∫ y : ℝ in z.im..w.im, I • f' (x + y * I) 1 - f' (x + y * I) I :=
  by
  set e : (ℝ × ℝ) ≃L[ℝ] ℂ := equiv_real_prod_clm.symm
  have he : ∀ x y : ℝ, ↑x + ↑y * I = e (x, y) := fun x y => (mk_eq_add_mul_I x y).symm
  have he₁ : e (1, 0) = 1 := rfl
  have he₂ : e (0, 1) = I := rfl
  simp only [he] at *
  set F : ℝ × ℝ → E := f ∘ e
  set F' : ℝ × ℝ → ℝ × ℝ →L[ℝ] E := fun p => (f' (e p)).comp (e : ℝ × ℝ →L[ℝ] ℂ)
  have hF' : ∀ p : ℝ × ℝ, (-(I • F' p)) (1, 0) + F' p (0, 1) = -(I • f' (e p) 1 - f' (e p) I) :=
    by
    rintro ⟨x, y⟩
    simp only [ContinuousLinearMap.neg_apply, ContinuousLinearMap.smul_apply, F',
      ContinuousLinearMap.comp_apply, ContinuousLinearEquiv.coe_coe, he₁, he₂, neg_add_eq_sub,
      neg_sub]
  set R : Set (ℝ × ℝ) := [z.re, w.re] ×ˢ [w.im, z.im]
  set t : Set (ℝ × ℝ) := e ⁻¹' s
  rw [uIcc_comm z.im] at Hc Hi
  rw [min_comm z.im, max_comm z.im] at Hd
  have hR : e ⁻¹' ([z.re, w.re] ×ℂ [w.im, z.im]) = R := rfl
  have htc : ContinuousOn F R := Hc.comp e.continuous_on hR.ge
  have htd :
    ∀ p ∈ Ioo (min z.re w.re) (max z.re w.re) ×ˢ Ioo (min w.im z.im) (max w.im z.im) \ t,
      HasFderivAt F (F' p) p :=
    fun p hp => (Hd (e p) hp).comp p e.has_fderiv_at
  simp_rw [← intervalIntegral.integral_smul, intervalIntegral.integral_symm w.im z.im, ←
    intervalIntegral.integral_neg, ← hF']
  refine'
    (integral2_divergence_prod_of_has_fderiv_within_at_off_countable (fun p => -(I • F p)) F
        (fun p => -(I • F' p)) F' z.re w.im w.re z.im t (hs.preimage e.injective)
        (htc.const_smul _).neg htc (fun p hp => ((htd p hp).const_smul I).neg) htd _).symm
  rw [←
    (volume_preserving_equiv_real_prod.symm _).integrableOn_comp_preimage
      (MeasurableEquiv.measurableEmbedding _)] at
    Hi
  simpa only [hF'] using Hi.neg
#align complex.integral_boundary_rect_of_has_fderiv_at_real_off_countable Complex.integral_boundary_rect_of_hasFderivAt_real_off_countable

/-- Suppose that a function `f : ℂ → E` is continuous on a closed rectangle with opposite corners at
`z w : ℂ`, is *real* differentiable on the corresponding open rectangle, and
$\frac{\partial f}{\partial \bar z}$ is integrable on this rectangle. Then the integral of `f` over
the boundary of the rectangle is equal to the integral of
$2i\frac{\partial f}{\partial \bar z}=i\frac{\partial f}{\partial x}-\frac{\partial f}{\partial y}$
over the rectangle. -/
theorem integral_boundary_rect_of_continuousOn_of_hasFderivAt_real (f : ℂ → E) (f' : ℂ → ℂ →L[ℝ] E)
    (z w : ℂ) (Hc : ContinuousOn f ([z.re, w.re] ×ℂ [z.im, w.im]))
    (Hd :
      ∀ x ∈ Ioo (min z.re w.re) (max z.re w.re) ×ℂ Ioo (min z.im w.im) (max z.im w.im),
        HasFderivAt f (f' x) x)
    (Hi : IntegrableOn (fun z => I • f' z 1 - f' z I) ([z.re, w.re] ×ℂ [z.im, w.im])) :
    ((((∫ x : ℝ in z.re..w.re, f (x + z.im * I)) - ∫ x : ℝ in z.re..w.re, f (x + w.im * I)) +
          I • ∫ y : ℝ in z.im..w.im, f (re w + y * I)) -
        I • ∫ y : ℝ in z.im..w.im, f (re z + y * I)) =
      ∫ x : ℝ in z.re..w.re, ∫ y : ℝ in z.im..w.im, I • f' (x + y * I) 1 - f' (x + y * I) I :=
  integral_boundary_rect_of_hasFderivAt_real_off_countable f f' z w ∅ countable_empty Hc
    (fun x hx => Hd x hx.1) Hi
#align complex.integral_boundary_rect_of_continuous_on_of_has_fderiv_at_real Complex.integral_boundary_rect_of_continuousOn_of_hasFderivAt_real

/-- Suppose that a function `f : ℂ → E` is *real* differentiable on a closed rectangle with opposite
corners at `z w : ℂ` and $\frac{\partial f}{\partial \bar z}$ is integrable on this rectangle. Then
the integral of `f` over the boundary of the rectangle is equal to the integral of
$2i\frac{\partial f}{\partial \bar z}=i\frac{\partial f}{\partial x}-\frac{\partial f}{\partial y}$
over the rectangle. -/
theorem integral_boundary_rect_of_differentiableOn_real (f : ℂ → E) (z w : ℂ)
    (Hd : DifferentiableOn ℝ f ([z.re, w.re] ×ℂ [z.im, w.im]))
    (Hi :
      IntegrableOn (fun z => I • fderiv ℝ f z 1 - fderiv ℝ f z I) ([z.re, w.re] ×ℂ [z.im, w.im])) :
    ((((∫ x : ℝ in z.re..w.re, f (x + z.im * I)) - ∫ x : ℝ in z.re..w.re, f (x + w.im * I)) +
          I • ∫ y : ℝ in z.im..w.im, f (re w + y * I)) -
        I • ∫ y : ℝ in z.im..w.im, f (re z + y * I)) =
      ∫ x : ℝ in z.re..w.re,
        ∫ y : ℝ in z.im..w.im, I • fderiv ℝ f (x + y * I) 1 - fderiv ℝ f (x + y * I) I :=
  integral_boundary_rect_of_hasFderivAt_real_off_countable f (fderiv ℝ f) z w ∅ countable_empty
    Hd.ContinuousOn
    (fun x hx =>
      Hd.HasFderivAt <| by
        simpa only [← mem_interior_iff_mem_nhds, interior_re_prod_im, uIcc, interior_Icc] using
          hx.1)
    Hi
#align complex.integral_boundary_rect_of_differentiable_on_real Complex.integral_boundary_rect_of_differentiableOn_real

/-- **Cauchy-Goursat theorem** for a rectangle: the integral of a complex differentiable function
over the boundary of a rectangle equals zero. More precisely, if `f` is continuous on a closed
rectangle and is complex differentiable at all but countably many points of the corresponding open
rectangle, then its integral over the boundary of the rectangle equals zero. -/
theorem integral_boundary_rect_eq_zero_of_differentiable_on_off_countable (f : ℂ → E) (z w : ℂ)
    (s : Set ℂ) (hs : s.Countable) (Hc : ContinuousOn f ([z.re, w.re] ×ℂ [z.im, w.im]))
    (Hd :
      ∀ x ∈ Ioo (min z.re w.re) (max z.re w.re) ×ℂ Ioo (min z.im w.im) (max z.im w.im) \ s,
        DifferentiableAt ℂ f x) :
    ((((∫ x : ℝ in z.re..w.re, f (x + z.im * I)) - ∫ x : ℝ in z.re..w.re, f (x + w.im * I)) +
          I • ∫ y : ℝ in z.im..w.im, f (re w + y * I)) -
        I • ∫ y : ℝ in z.im..w.im, f (re z + y * I)) =
      0 :=
  by
  refine'
      (integral_boundary_rect_of_has_fderiv_at_real_off_countable f
            (fun z => (fderiv ℂ f z).restrictScalars ℝ) z w s hs Hc
            (fun x hx => (Hd x hx).HasFderivAt.restrictScalars ℝ) _).trans
        _ <;>
    simp [← ContinuousLinearMap.map_smul]
#align complex.integral_boundary_rect_eq_zero_of_differentiable_on_off_countable Complex.integral_boundary_rect_eq_zero_of_differentiable_on_off_countable

/-- **Cauchy-Goursat theorem for a rectangle**: the integral of a complex differentiable function
over the boundary of a rectangle equals zero. More precisely, if `f` is continuous on a closed
rectangle and is complex differentiable on the corresponding open rectangle, then its integral over
the boundary of the rectangle equals zero. -/
theorem integral_boundary_rect_eq_zero_of_continuousOn_of_differentiableOn (f : ℂ → E) (z w : ℂ)
    (Hc : ContinuousOn f ([z.re, w.re] ×ℂ [z.im, w.im]))
    (Hd :
      DifferentiableOn ℂ f
        (Ioo (min z.re w.re) (max z.re w.re) ×ℂ Ioo (min z.im w.im) (max z.im w.im))) :
    ((((∫ x : ℝ in z.re..w.re, f (x + z.im * I)) - ∫ x : ℝ in z.re..w.re, f (x + w.im * I)) +
          I • ∫ y : ℝ in z.im..w.im, f (re w + y * I)) -
        I • ∫ y : ℝ in z.im..w.im, f (re z + y * I)) =
      0 :=
  integral_boundary_rect_eq_zero_of_differentiable_on_off_countable f z w ∅ countable_empty Hc
    fun x hx => Hd.DifferentiableAt <| (isOpen_Ioo.reProdIm isOpen_Ioo).mem_nhds hx.1
#align complex.integral_boundary_rect_eq_zero_of_continuous_on_of_differentiable_on Complex.integral_boundary_rect_eq_zero_of_continuousOn_of_differentiableOn

/-- **Cauchy-Goursat theorem** for a rectangle: the integral of a complex differentiable function
over the boundary of a rectangle equals zero. More precisely, if `f` is complex differentiable on a
closed rectangle, then its integral over the boundary of the rectangle equals zero. -/
theorem integral_boundary_rect_eq_zero_of_differentiableOn (f : ℂ → E) (z w : ℂ)
    (H : DifferentiableOn ℂ f ([z.re, w.re] ×ℂ [z.im, w.im])) :
    ((((∫ x : ℝ in z.re..w.re, f (x + z.im * I)) - ∫ x : ℝ in z.re..w.re, f (x + w.im * I)) +
          I • ∫ y : ℝ in z.im..w.im, f (re w + y * I)) -
        I • ∫ y : ℝ in z.im..w.im, f (re z + y * I)) =
      0 :=
  integral_boundary_rect_eq_zero_of_continuousOn_of_differentiableOn f z w H.ContinuousOn <|
    H.mono <|
      inter_subset_inter (preimage_mono Ioo_subset_Icc_self) (preimage_mono Ioo_subset_Icc_self)
#align complex.integral_boundary_rect_eq_zero_of_differentiable_on Complex.integral_boundary_rect_eq_zero_of_differentiableOn

/-- If `f : ℂ → E` is continuous the closed annulus `r ≤ ‖z - c‖ ≤ R`, `0 < r ≤ R`, and is complex
differentiable at all but countably many points of its interior, then the integrals of
`f z / (z - c)` (formally, `(z - c)⁻¹ • f z`) over the circles `‖z - c‖ = r` and `‖z - c‖ = R` are
equal to each other. -/
theorem circleIntegral_sub_center_inv_smul_eq_of_differentiable_on_annulus_off_countable {c : ℂ}
    {r R : ℝ} (h0 : 0 < r) (hle : r ≤ R) {f : ℂ → E} {s : Set ℂ} (hs : s.Countable)
    (hc : ContinuousOn f (closedBall c R \ ball c r))
    (hd : ∀ z ∈ (ball c R \ closedBall c r) \ s, DifferentiableAt ℂ f z) :
    (∮ z in C(c, R), (z - c)⁻¹ • f z) = ∮ z in C(c, r), (z - c)⁻¹ • f z :=
  by
  /- We apply the previous lemma to `λ z, f (c + exp z)` on the rectangle
    `[log r, log R] × [0, 2 * π]`. -/
  set A := closed_ball c R \ ball c r
  obtain ⟨a, rfl⟩ : ∃ a, Real.exp a = r
  exact ⟨Real.log r, Real.exp_log h0⟩
  obtain ⟨b, rfl⟩ : ∃ b, Real.exp b = R
  exact ⟨Real.log R, Real.exp_log (h0.trans_le hle)⟩
  rw [Real.exp_le_exp] at hle
  -- Unfold definition of `circle_integral` and cancel some terms.
  suffices
    (∫ θ in 0 ..2 * π, I • f (circleMap c (Real.exp b) θ)) =
      ∫ θ in 0 ..2 * π, I • f (circleMap c (Real.exp a) θ)
    by
    simpa only [circleIntegral, add_sub_cancel', of_real_exp, ← exp_add, smul_smul, ←
      div_eq_mul_inv, mul_div_cancel_left _ (circleMap_ne_center (Real.exp_pos _).ne'),
      circleMap_sub_center, deriv_circleMap]
  set R := [a, b] ×ℂ [0, 2 * π]
  set g : ℂ → ℂ := (· + ·) c ∘ exp
  have hdg : Differentiable ℂ g := differentiable_exp.const_add _
  replace hs : (g ⁻¹' s).Countable := (hs.preimage (add_right_injective c)).preimage_cexp
  have h_maps : maps_to g R A := by
    rintro z ⟨h, -⟩
    simpa [dist_eq, g, abs_exp, hle] using h.symm
  replace hc : ContinuousOn (f ∘ g) R
  exact hc.comp hdg.continuous.continuous_on h_maps
  replace hd :
    ∀ z ∈ Ioo (min a b) (max a b) ×ℂ Ioo (min 0 (2 * π)) (max 0 (2 * π)) \ g ⁻¹' s,
      DifferentiableAt ℂ (f ∘ g) z
  · refine' fun z hz => (hd (g z) ⟨_, hz.2⟩).comp z (hdg _)
    simpa [g, dist_eq, abs_exp, hle, and_comm] using hz.1.1
  simpa [g, circleMap, exp_periodic _, sub_eq_zero, ← exp_add] using
    integral_boundary_rect_eq_zero_of_differentiable_on_off_countable _ ⟨a, 0⟩ ⟨b, 2 * π⟩ _ hs hc hd
#align complex.circle_integral_sub_center_inv_smul_eq_of_differentiable_on_annulus_off_countable Complex.circleIntegral_sub_center_inv_smul_eq_of_differentiable_on_annulus_off_countable

/-- **Cauchy-Goursat theorem** for an annulus. If `f : ℂ → E` is continuous on the closed annulus
`r ≤ ‖z - c‖ ≤ R`, `0 < r ≤ R`, and is complex differentiable at all but countably many points of
its interior, then the integrals of `f` over the circles `‖z - c‖ = r` and `‖z - c‖ = R` are equal
to each other. -/
theorem circleIntegral_eq_of_differentiable_on_annulus_off_countable {c : ℂ} {r R : ℝ} (h0 : 0 < r)
    (hle : r ≤ R) {f : ℂ → E} {s : Set ℂ} (hs : s.Countable)
    (hc : ContinuousOn f (closedBall c R \ ball c r))
    (hd : ∀ z ∈ (ball c R \ closedBall c r) \ s, DifferentiableAt ℂ f z) :
    (∮ z in C(c, R), f z) = ∮ z in C(c, r), f z :=
  calc
    (∮ z in C(c, R), f z) = ∮ z in C(c, R), (z - c)⁻¹ • (z - c) • f z :=
      (circleIntegral.integral_sub_inv_smul_sub_smul _ _ _ _).symm
    _ = ∮ z in C(c, r), (z - c)⁻¹ • (z - c) • f z :=
      (circleIntegral_sub_center_inv_smul_eq_of_differentiable_on_annulus_off_countable h0 hle hs
        ((continuousOn_id.sub continuousOn_const).smul hc) fun z hz =>
        (differentiableAt_id.sub_const _).smul (hd z hz))
    _ = ∮ z in C(c, r), f z := circleIntegral.integral_sub_inv_smul_sub_smul _ _ _ _

#align complex.circle_integral_eq_of_differentiable_on_annulus_off_countable Complex.circleIntegral_eq_of_differentiable_on_annulus_off_countable

/-- **Cauchy integral formula** for the value at the center of a disc. If `f` is continuous on a
punctured closed disc of radius `R`, is differentiable at all but countably many points of the
interior of this disc, and has a limit `y` at the center of the disc, then the integral
$\oint_{‖z-c‖=R} \frac{f(z)}{z-c}\,dz$ is equal to $2πiy`. -/
theorem circleIntegral_sub_center_inv_smul_of_differentiable_on_off_countable_of_tendsto {c : ℂ}
    {R : ℝ} (h0 : 0 < R) {f : ℂ → E} {y : E} {s : Set ℂ} (hs : s.Countable)
    (hc : ContinuousOn f (closedBall c R \ {c}))
    (hd : ∀ z ∈ (ball c R \ {c}) \ s, DifferentiableAt ℂ f z) (hy : Tendsto f (𝓝[{c}ᶜ] c) (𝓝 y)) :
    (∮ z in C(c, R), (z - c)⁻¹ • f z) = (2 * π * I : ℂ) • y :=
  by
  rw [← sub_eq_zero, ← norm_le_zero_iff]
  refine' le_of_forall_le_of_dense fun ε ε0 => _
  obtain ⟨δ, δ0, hδ⟩ : ∃ δ > (0 : ℝ), ∀ z ∈ closed_ball c δ \ {c}, dist (f z) y < ε / (2 * π)
  exact
    ((nhdsWithin_hasBasis nhds_basis_closed_ball _).tendsto_iffₓ nhds_basis_ball).1 hy _
      (div_pos ε0 Real.two_pi_pos)
  obtain ⟨r, hr0, hrδ, hrR⟩ : ∃ r, 0 < r ∧ r ≤ δ ∧ r ≤ R :=
    ⟨min δ R, lt_min δ0 h0, min_le_left _ _, min_le_right _ _⟩
  have hsub : closed_ball c R \ ball c r ⊆ closed_ball c R \ {c} :=
    diff_subset_diff_right (singleton_subset_iff.2 <| mem_ball_self hr0)
  have hsub' : ball c R \ closed_ball c r ⊆ ball c R \ {c} :=
    diff_subset_diff_right (singleton_subset_iff.2 <| mem_closed_ball_self hr0.le)
  have hzne : ∀ z ∈ sphere c r, z ≠ c := fun z hz =>
    ne_of_mem_of_not_mem hz fun h => hr0.ne' <| dist_self c ▸ Eq.symm h
  /- The integral `∮ z in C(c, r), f z / (z - c)` does not depend on `0 < r ≤ R` and tends to
    `2πIy` as `r → 0`. -/
  calc
    ‖(∮ z in C(c, R), (z - c)⁻¹ • f z) - (2 * ↑π * I) • y‖ =
        ‖(∮ z in C(c, r), (z - c)⁻¹ • f z) - ∮ z in C(c, r), (z - c)⁻¹ • y‖ :=
      by
      congr 2
      ·
        exact
          circle_integral_sub_center_inv_smul_eq_of_differentiable_on_annulus_off_countable hr0 hrR
            hs (hc.mono hsub) fun z hz => hd z ⟨hsub' hz.1, hz.2⟩
      · simp [hr0.ne']
    _ = ‖∮ z in C(c, r), (z - c)⁻¹ • (f z - y)‖ :=
      by
      simp only [smul_sub]
      have hc' : ContinuousOn (fun z => (z - c)⁻¹) (sphere c r) :=
        (continuous_on_id.sub continuousOn_const).inv₀ fun z hz => sub_ne_zero.2 <| hzne _ hz
      rw [circleIntegral.integral_sub] <;> refine' (hc'.smul _).CircleIntegrable hr0.le
      ·
        exact
          hc.mono
            (subset_inter (sphere_subset_closed_ball.trans <| closed_ball_subset_closed_ball hrR)
              hzne)
      · exact continuousOn_const
    _ ≤ 2 * π * r * (r⁻¹ * (ε / (2 * π))) :=
      by
      refine' circleIntegral.norm_integral_le_of_norm_le_const hr0.le fun z hz => _
      specialize hzne z hz
      rw [mem_sphere, dist_eq_norm] at hz
      rw [norm_smul, norm_inv, hz, ← dist_eq_norm]
      refine' mul_le_mul_of_nonneg_left (hδ _ ⟨_, hzne⟩).le (inv_nonneg.2 hr0.le)
      rwa [mem_closedBall_iff_norm, hz]
    _ = ε := by
      field_simp [hr0.ne', real.two_pi_pos.ne']
      ac_rfl

#align complex.circle_integral_sub_center_inv_smul_of_differentiable_on_off_countable_of_tendsto Complex.circleIntegral_sub_center_inv_smul_of_differentiable_on_off_countable_of_tendsto

/-- **Cauchy integral formula** for the value at the center of a disc. If `f : ℂ → E` is continuous
on a closed disc of radius `R` and is complex differentiable at all but countably many points of its
interior, then the integral $\oint_{|z-c|=R} \frac{f(z)}{z-c}\,dz$ is equal to $2πiy`. -/
theorem circleIntegral_sub_center_inv_smul_of_differentiable_on_off_countable {R : ℝ} (h0 : 0 < R)
    {f : ℂ → E} {c : ℂ} {s : Set ℂ} (hs : s.Countable) (hc : ContinuousOn f (closedBall c R))
    (hd : ∀ z ∈ ball c R \ s, DifferentiableAt ℂ f z) :
    (∮ z in C(c, R), (z - c)⁻¹ • f z) = (2 * π * I : ℂ) • f c :=
  circleIntegral_sub_center_inv_smul_of_differentiable_on_off_countable_of_tendsto h0 hs
    (hc.mono <| diff_subset _ _) (fun z hz => hd z ⟨hz.1.1, hz.2⟩)
    (hc.ContinuousAt <| closedBall_mem_nhds _ h0).ContinuousWithinAt
#align complex.circle_integral_sub_center_inv_smul_of_differentiable_on_off_countable Complex.circleIntegral_sub_center_inv_smul_of_differentiable_on_off_countable

/-- **Cauchy-Goursat theorem** for a disk: if `f : ℂ → E` is continuous on a closed disk
`{z | ‖z - c‖ ≤ R}` and is complex differentiable at all but countably many points of its interior,
then the integral $\oint_{|z-c|=R}f(z)\,dz$ equals zero. -/
theorem circleIntegral_eq_zero_of_differentiable_on_off_countable {R : ℝ} (h0 : 0 ≤ R) {f : ℂ → E}
    {c : ℂ} {s : Set ℂ} (hs : s.Countable) (hc : ContinuousOn f (closedBall c R))
    (hd : ∀ z ∈ ball c R \ s, DifferentiableAt ℂ f z) : (∮ z in C(c, R), f z) = 0 :=
  by
  rcases h0.eq_or_lt with (rfl | h0); · apply circleIntegral.integral_radius_zero
  calc
    (∮ z in C(c, R), f z) = ∮ z in C(c, R), (z - c)⁻¹ • (z - c) • f z :=
      (circleIntegral.integral_sub_inv_smul_sub_smul _ _ _ _).symm
    _ = (2 * ↑π * I : ℂ) • (c - c) • f c :=
      (circle_integral_sub_center_inv_smul_of_differentiable_on_off_countable h0 hs
        ((continuous_on_id.sub continuousOn_const).smul hc) fun z hz =>
        (differentiable_at_id.sub_const _).smul (hd z hz))
    _ = 0 := by rw [sub_self, zero_smul, smul_zero]

#align complex.circle_integral_eq_zero_of_differentiable_on_off_countable Complex.circleIntegral_eq_zero_of_differentiable_on_off_countable

/-- An auxiliary lemma for
`complex.circle_integral_sub_inv_smul_of_differentiable_on_off_countable`. This lemma assumes
`w ∉ s` while the main lemma drops this assumption. -/
theorem circleIntegral_sub_inv_smul_of_differentiable_on_off_countable_aux {R : ℝ} {c w : ℂ}
    {f : ℂ → E} {s : Set ℂ} (hs : s.Countable) (hw : w ∈ ball c R \ s)
    (hc : ContinuousOn f (closedBall c R)) (hd : ∀ x ∈ ball c R \ s, DifferentiableAt ℂ f x) :
    (∮ z in C(c, R), (z - w)⁻¹ • f z) = (2 * π * I : ℂ) • f w :=
  by
  have hR : 0 < R := dist_nonneg.trans_lt hw.1
  set F : ℂ → E := dslope f w
  have hws : (insert w s).Countable := hs.insert w
  have hnhds : closed_ball c R ∈ 𝓝 w := closed_ball_mem_nhds_of_mem hw.1
  have hcF : ContinuousOn F (closed_ball c R) :=
    (continuousOn_dslope <| closed_ball_mem_nhds_of_mem hw.1).2 ⟨hc, hd _ hw⟩
  have hdF : ∀ z ∈ ball (c : ℂ) R \ insert w s, DifferentiableAt ℂ F z := fun z hz =>
    (differentiableAt_dslope_of_ne (ne_of_mem_of_not_mem (mem_insert _ _) hz.2).symm).2
      (hd _ (diff_subset_diff_right (subset_insert _ _) hz))
  have HI := circle_integral_eq_zero_of_differentiable_on_off_countable hR.le hws hcF hdF
  have hne : ∀ z ∈ sphere c R, z ≠ w := fun z hz => ne_of_mem_of_not_mem hz (ne_of_lt hw.1)
  have hFeq : eq_on F (fun z => (z - w)⁻¹ • f z - (z - w)⁻¹ • f w) (sphere c R) :=
    by
    intro z hz
    calc
      F z = (z - w)⁻¹ • (f z - f w) := update_noteq (hne z hz) _ _
      _ = (z - w)⁻¹ • f z - (z - w)⁻¹ • f w := smul_sub _ _ _

  have hc' : ContinuousOn (fun z => (z - w)⁻¹) (sphere c R) :=
    (continuous_on_id.sub continuousOn_const).inv₀ fun z hz => sub_ne_zero.2 <| hne z hz
  rw [← circleIntegral.integral_sub_inv_of_mem_ball hw.1, ← circleIntegral.integral_smul_const, ←
    sub_eq_zero, ← circleIntegral.integral_sub, ← circleIntegral.integral_congr hR.le hFeq, HI]
  exacts[(hc'.smul (hc.mono sphere_subset_closed_ball)).CircleIntegrable hR.le,
    (hc'.smul continuousOn_const).CircleIntegrable hR.le]
#align complex.circle_integral_sub_inv_smul_of_differentiable_on_off_countable_aux Complex.circleIntegral_sub_inv_smul_of_differentiable_on_off_countable_aux

/-- **Cauchy integral formula**: if `f : ℂ → E` is continuous on a closed disc of radius `R` and is
complex differentiable at all but countably many points of its interior, then for any `w` in this
interior we have $\frac{1}{2πi}\oint_{|z-c|=R}(z-w)^{-1}f(z)\,dz=f(w)$.
-/
theorem two_pi_i_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_countable {R : ℝ}
    {c w : ℂ} {f : ℂ → E} {s : Set ℂ} (hs : s.Countable) (hw : w ∈ ball c R)
    (hc : ContinuousOn f (closedBall c R)) (hd : ∀ x ∈ ball c R \ s, DifferentiableAt ℂ f x) :
    ((2 * π * I : ℂ)⁻¹ • ∮ z in C(c, R), (z - w)⁻¹ • f z) = f w :=
  by
  have hR : 0 < R := dist_nonneg.trans_lt hw
  suffices w ∈ closure (ball c R \ s) by
    lift R to ℝ≥0 using hR.le
    have A : ContinuousAt (fun w => (2 * π * I : ℂ)⁻¹ • ∮ z in C(c, R), (z - w)⁻¹ • f z) w :=
      by
      have :=
        hasFpowerSeriesOnCauchyIntegral
          ((hc.mono sphere_subset_closed_ball).CircleIntegrable R.coe_nonneg) hR
      refine' this.continuous_on.continuous_at (emetric.is_open_ball.mem_nhds _)
      rwa [Metric.emetric_ball_nnreal]
    have B : ContinuousAt f w := hc.continuous_at (closed_ball_mem_nhds_of_mem hw)
    refine' tendsto_nhds_unique_of_frequently_eq A B ((mem_closure_iff_frequently.1 this).mono _)
    intro z hz
    rw [circle_integral_sub_inv_smul_of_differentiable_on_off_countable_aux hs hz hc hd,
      inv_smul_smul₀]
    simp [Real.pi_ne_zero, I_ne_zero]
  refine' mem_closure_iff_nhds.2 fun t ht => _
  -- TODO: generalize to any vector space over `ℝ`
  set g : ℝ → ℂ := fun x => w + x
  have : tendsto g (𝓝 0) (𝓝 w) :=
    (continuous_const.add continuous_of_real).tendsto' 0 w (add_zero _)
  rcases mem_nhds_iff_exists_Ioo_subset.1 (this <| inter_mem ht <| is_open_ball.mem_nhds hw) with
    ⟨l, u, hlu₀, hlu_sub⟩
  obtain ⟨x, hx⟩ : (Ioo l u \ g ⁻¹' s).Nonempty :=
    by
    refine' nonempty_diff.2 fun hsub => _
    have : (Ioo l u).Countable :=
      (hs.preimage ((add_right_injective w).comp of_real_injective)).mono hsub
    rw [← Cardinal.le_aleph0_iff_set_countable, Cardinal.mk_Ioo_real (hlu₀.1.trans hlu₀.2)] at this
    exact this.not_lt Cardinal.aleph0_lt_continuum
  exact ⟨g x, (hlu_sub hx.1).1, (hlu_sub hx.1).2, hx.2⟩
#align complex.two_pi_I_inv_smul_circle_integral_sub_inv_smul_of_differentiable_on_off_countable Complex.two_pi_i_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_countable

/-- **Cauchy integral formula**: if `f : ℂ → E` is continuous on a closed disc of radius `R` and is
complex differentiable at all but countably many points of its interior, then for any `w` in this
interior we have $\oint_{|z-c|=R}(z-w)^{-1}f(z)\,dz=2πif(w)$.
-/
theorem circleIntegral_sub_inv_smul_of_differentiable_on_off_countable {R : ℝ} {c w : ℂ} {f : ℂ → E}
    {s : Set ℂ} (hs : s.Countable) (hw : w ∈ ball c R) (hc : ContinuousOn f (closedBall c R))
    (hd : ∀ x ∈ ball c R \ s, DifferentiableAt ℂ f x) :
    (∮ z in C(c, R), (z - w)⁻¹ • f z) = (2 * π * I : ℂ) • f w :=
  by
  rw [←
    two_pi_I_inv_smul_circle_integral_sub_inv_smul_of_differentiable_on_off_countable hs hw hc hd,
    smul_inv_smul₀]
  simp [Real.pi_ne_zero, I_ne_zero]
#align complex.circle_integral_sub_inv_smul_of_differentiable_on_off_countable Complex.circleIntegral_sub_inv_smul_of_differentiable_on_off_countable

/-- **Cauchy integral formula**: if `f : ℂ → E` is complex differentiable on an open disc and is
continuous on its closure, then for any `w` in this open ball we have
$\oint_{|z-c|=R}(z-w)^{-1}f(z)\,dz=2πif(w)$. -/
theorem DiffContOnCl.circleIntegral_sub_inv_smul {R : ℝ} {c w : ℂ} {f : ℂ → E}
    (h : DiffContOnCl ℂ f (ball c R)) (hw : w ∈ ball c R) :
    (∮ z in C(c, R), (z - w)⁻¹ • f z) = (2 * π * I : ℂ) • f w :=
  circleIntegral_sub_inv_smul_of_differentiable_on_off_countable countable_empty hw
    h.continuousOn_ball fun x hx => h.DifferentiableAt isOpen_ball hx.1
#align diff_cont_on_cl.circle_integral_sub_inv_smul DiffContOnCl.circleIntegral_sub_inv_smul

/-- **Cauchy integral formula**: if `f : ℂ → E` is complex differentiable on an open disc and is
continuous on its closure, then for any `w` in this open ball we have
$\frac{1}{2πi}\oint_{|z-c|=R}(z-w)^{-1}f(z)\,dz=f(w)$. -/
theorem DiffContOnCl.two_pi_i_inv_smul_circleIntegral_sub_inv_smul {R : ℝ} {c w : ℂ} {f : ℂ → E}
    (hf : DiffContOnCl ℂ f (ball c R)) (hw : w ∈ ball c R) :
    ((2 * π * I : ℂ)⁻¹ • ∮ z in C(c, R), (z - w)⁻¹ • f z) = f w :=
  by
  have hR : 0 < R := not_le.mp (ball_eq_empty.not.mp (nonempty_of_mem hw).ne_empty)
  refine'
    two_pi_I_inv_smul_circle_integral_sub_inv_smul_of_differentiable_on_off_countable
      countable_empty hw _ _
  · simpa only [closure_ball c hR.ne.symm] using hf.continuous_on
  · simpa only [diff_empty] using fun z hz => hf.differentiable_at is_open_ball hz
#align diff_cont_on_cl.two_pi_I_inv_smul_circle_integral_sub_inv_smul DiffContOnCl.two_pi_i_inv_smul_circleIntegral_sub_inv_smul

/-- **Cauchy integral formula**: if `f : ℂ → E` is complex differentiable on a closed disc of radius
`R`, then for any `w` in its interior we have $\oint_{|z-c|=R}(z-w)^{-1}f(z)\,dz=2πif(w)$. -/
theorem DifferentiableOn.circleIntegral_sub_inv_smul {R : ℝ} {c w : ℂ} {f : ℂ → E}
    (hd : DifferentiableOn ℂ f (closedBall c R)) (hw : w ∈ ball c R) :
    (∮ z in C(c, R), (z - w)⁻¹ • f z) = (2 * π * I : ℂ) • f w :=
  (hd.mono closure_ball_subset_closedBall).DiffContOnCl.circleIntegral_sub_inv_smul hw
#align differentiable_on.circle_integral_sub_inv_smul DifferentiableOn.circleIntegral_sub_inv_smul

/-- **Cauchy integral formula**: if `f : ℂ → ℂ` is continuous on a closed disc of radius `R` and is
complex differentiable at all but countably many points of its interior, then for any `w` in this
interior we have $\oint_{|z-c|=R}\frac{f(z)}{z-w}dz=2\pi i\,f(w)$.
-/
theorem circleIntegral_div_sub_of_differentiable_on_off_countable {R : ℝ} {c w : ℂ} {s : Set ℂ}
    (hs : s.Countable) (hw : w ∈ ball c R) {f : ℂ → ℂ} (hc : ContinuousOn f (closedBall c R))
    (hd : ∀ z ∈ ball c R \ s, DifferentiableAt ℂ f z) :
    (∮ z in C(c, R), f z / (z - w)) = 2 * π * I * f w := by
  simpa only [smul_eq_mul, div_eq_inv_mul] using
    circle_integral_sub_inv_smul_of_differentiable_on_off_countable hs hw hc hd
#align complex.circle_integral_div_sub_of_differentiable_on_off_countable Complex.circleIntegral_div_sub_of_differentiable_on_off_countable

/-- If `f : ℂ → E` is continuous on a closed ball of positive radius and is differentiable at all
but countably many points of the corresponding open ball, then it is analytic on the open ball with
coefficients of the power series given by Cauchy integral formulas. -/
theorem hasFpowerSeriesOnBallOfDifferentiableOffCountable {R : ℝ≥0} {c : ℂ} {f : ℂ → E} {s : Set ℂ}
    (hs : s.Countable) (hc : ContinuousOn f (closedBall c R))
    (hd : ∀ z ∈ ball c R \ s, DifferentiableAt ℂ f z) (hR : 0 < R) :
    HasFpowerSeriesOnBall f (cauchyPowerSeries f c R) c R :=
  { r_le := le_radius_cauchyPowerSeries _ _ _
    r_pos := ENNReal.coe_pos.2 hR
    HasSum := fun w hw =>
      by
      have hw' : c + w ∈ ball c R := by
        simpa only [add_mem_ball_iff_norm, ← coe_nnnorm, mem_emetric_ball_zero_iff,
          NNReal.coe_lt_coe, ENNReal.coe_lt_coe] using hw
      rw [←
        two_pi_I_inv_smul_circle_integral_sub_inv_smul_of_differentiable_on_off_countable hs hw' hc
          hd]
      exact
        (hasFpowerSeriesOnCauchyIntegral ((hc.mono sphere_subset_closed_ball).CircleIntegrable R.2)
              hR).HasSum
          hw }
#align complex.has_fpower_series_on_ball_of_differentiable_off_countable Complex.hasFpowerSeriesOnBallOfDifferentiableOffCountable

/-- If `f : ℂ → E` is complex differentiable on an open disc of positive radius and is continuous
on its closure, then it is analytic on the open disc with coefficients of the power series given by
Cauchy integral formulas. -/
theorem DiffContOnCl.hasFpowerSeriesOnBall {R : ℝ≥0} {c : ℂ} {f : ℂ → E}
    (hf : DiffContOnCl ℂ f (ball c R)) (hR : 0 < R) :
    HasFpowerSeriesOnBall f (cauchyPowerSeries f c R) c R :=
  hasFpowerSeriesOnBallOfDifferentiableOffCountable countable_empty hf.continuousOn_ball
    (fun z hz => hf.DifferentiableAt isOpen_ball hz.1) hR
#align diff_cont_on_cl.has_fpower_series_on_ball DiffContOnCl.hasFpowerSeriesOnBall

/-- If `f : ℂ → E` is complex differentiable on a closed disc of positive radius, then it is
analytic on the corresponding open disc, and the coefficients of the power series are given by
Cauchy integral formulas. See also
`complex.has_fpower_series_on_ball_of_differentiable_off_countable` for a version of this lemma with
weaker assumptions. -/
protected theorem DifferentiableOn.hasFpowerSeriesOnBall {R : ℝ≥0} {c : ℂ} {f : ℂ → E}
    (hd : DifferentiableOn ℂ f (closedBall c R)) (hR : 0 < R) :
    HasFpowerSeriesOnBall f (cauchyPowerSeries f c R) c R :=
  (hd.mono closure_ball_subset_closedBall).DiffContOnCl.HasFpowerSeriesOnBall hR
#align differentiable_on.has_fpower_series_on_ball DifferentiableOn.hasFpowerSeriesOnBall

/-- If `f : ℂ → E` is complex differentiable on some set `s`, then it is analytic at any point `z`
such that `s ∈ 𝓝 z` (equivalently, `z ∈ interior s`). -/
protected theorem DifferentiableOn.analyticAt {s : Set ℂ} {f : ℂ → E} {z : ℂ}
    (hd : DifferentiableOn ℂ f s) (hz : s ∈ 𝓝 z) : AnalyticAt ℂ f z :=
  by
  rcases nhds_basis_closed_ball.mem_iff.1 hz with ⟨R, hR0, hRs⟩
  lift R to ℝ≥0 using hR0.le
  exact ((hd.mono hRs).HasFpowerSeriesOnBall hR0).AnalyticAt
#align differentiable_on.analytic_at DifferentiableOn.analyticAt

theorem DifferentiableOn.analyticOn {s : Set ℂ} {f : ℂ → E} (hd : DifferentiableOn ℂ f s)
    (hs : IsOpen s) : AnalyticOn ℂ f s := fun z hz => hd.AnalyticAt (hs.mem_nhds hz)
#align differentiable_on.analytic_on DifferentiableOn.analyticOn

/-- A complex differentiable function `f : ℂ → E` is analytic at every point. -/
protected theorem Differentiable.analyticAt {f : ℂ → E} (hf : Differentiable ℂ f) (z : ℂ) :
    AnalyticAt ℂ f z :=
  hf.DifferentiableOn.AnalyticAt univ_mem
#align differentiable.analytic_at Differentiable.analyticAt

/-- When `f : ℂ → E` is differentiable, the `cauchy_power_series f z R` represents `f` as a power
series centered at `z` in the entirety of `ℂ`, regardless of `R : ℝ≥0`, with  `0 < R`. -/
protected theorem Differentiable.hasFpowerSeriesOnBall {f : ℂ → E} (h : Differentiable ℂ f) (z : ℂ)
    {R : ℝ≥0} (hR : 0 < R) : HasFpowerSeriesOnBall f (cauchyPowerSeries f z R) z ∞ :=
  (h.DifferentiableOn.HasFpowerSeriesOnBall hR).rEqTopOfExists fun r hr =>
    ⟨_, h.DifferentiableOn.HasFpowerSeriesOnBall hr⟩
#align differentiable.has_fpower_series_on_ball Differentiable.hasFpowerSeriesOnBall

end Complex


/-
Copyright (c) 2018 Chris Hughes. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes
-/

import data.polynomial.splits
import ring_theory.adjoin.basic
import ring_theory.adjoin_root

/-!
# Adjoining elements to a field

Some lemmas on the ring generating by adjoining an element to a field.

## Main statements

* `lift_of_splits`: If `K` and `L` are field extensions of `F` and we have `s : finset K` such that
the minimal polynomial of each `x ∈ s` splits in `L` then `algebra.adjoin F s` embeds in `L`.

-/

noncomputable theory
open_locale big_operators polynomial

section embeddings

variables (F : Type*) [field F]

/-- If `p` is the minimal polynomial of `a` over `F` then `F[a] ≃ₐ[F] F[x]/(p)` -/
def alg_equiv.adjoin_singleton_equiv_adjoin_root_minpoly
  {R : Type*} [comm_ring R] [algebra F R] (x : R) :
  algebra.adjoin F ({x} : set R) ≃ₐ[F] adjoin_root (minpoly F x) :=
alg_equiv.symm $ alg_equiv.of_bijective
  (alg_hom.cod_restrict
    (adjoin_root.lift_hom _ x $ minpoly.aeval F x) _
    (λ p, adjoin_root.induction_on _ p $ λ p,
      (algebra.adjoin_singleton_eq_range_aeval F x).symm ▸
        (polynomial.aeval _).mem_range.mpr ⟨p, rfl⟩))
  ⟨(alg_hom.injective_cod_restrict _ _ _).2 $ (injective_iff_map_eq_zero _).2 $ λ p,
    adjoin_root.induction_on _ p $ λ p hp, ideal.quotient.eq_zero_iff_mem.2 $
    ideal.mem_span_singleton.2 $ minpoly.dvd F x hp,
  λ y,
    let ⟨p, hp⟩ := (set_like.ext_iff.1
      (algebra.adjoin_singleton_eq_range_aeval F x) (y : R)).1 y.2 in
    ⟨adjoin_root.mk _ p, subtype.eq hp⟩⟩

open finset

/-- If `K` and `L` are field extensions of `F` and we have `s : finset K` such that
the minimal polynomial of each `x ∈ s` splits in `L` then `algebra.adjoin F s` embeds in `L`. -/
theorem lift_of_splits {F K L : Type*} [field F] [field K] [field L]
  [algebra F K] [algebra F L] (s : finset K) :
  (∀ x ∈ s, is_integral F x ∧ polynomial.splits (algebra_map F L) (minpoly F x)) →
  nonempty (algebra.adjoin F (↑s : set K) →ₐ[F] L) :=
begin
  classical,
  refine finset.induction_on s (λ H, _) (λ a s has ih H, _),
  { rw [coe_empty, algebra.adjoin_empty],
    exact ⟨(algebra.of_id F L).comp (algebra.bot_equiv F K)⟩ },
  rw forall_mem_insert at H, rcases H with ⟨⟨H1, H2⟩, H3⟩, cases ih H3 with f,
  choose H3 H4 using H3,
  rw [coe_insert, set.insert_eq, set.union_comm, algebra.adjoin_union_eq_adjoin_adjoin],
  letI := (f : algebra.adjoin F (↑s : set K) →+* L).to_algebra,
  haveI : finite_dimensional F (algebra.adjoin F (↑s : set K)) := (
    (submodule.fg_iff_finite_dimensional _).1
      (fg_adjoin_of_finite s.finite_to_set H3)).of_subalgebra_to_submodule,
  letI := field_of_finite_dimensional F (algebra.adjoin F (↑s : set K)),
  have H5 : is_integral (algebra.adjoin F (↑s : set K)) a := is_integral_of_is_scalar_tower H1,
  have H6 : (minpoly (algebra.adjoin F (↑s : set K)) a).splits
    (algebra_map (algebra.adjoin F (↑s : set K)) L),
  { refine polynomial.splits_of_splits_of_dvd _
      (polynomial.map_ne_zero $ minpoly.ne_zero H1 :
        polynomial.map (algebra_map _ _) _ ≠ 0)
      ((polynomial.splits_map_iff _ _).2 _)
      (minpoly.dvd _ _ _),
    { rw ← is_scalar_tower.algebra_map_eq, exact H2 },
    { rw [polynomial.aeval_map_algebra_map, minpoly.aeval] } },
  obtain ⟨y, hy⟩ := polynomial.exists_root_of_splits _ H6 (ne_of_lt (minpoly.degree_pos H5)).symm,
  refine ⟨subalgebra.of_restrict_scalars _ _ _⟩,
  refine (adjoin_root.lift_hom (minpoly (algebra.adjoin F (↑s : set K)) a) y hy).comp _,
  exact alg_equiv.adjoin_singleton_equiv_adjoin_root_minpoly (algebra.adjoin F (↑s : set K)) a
end

end embeddings


/-
Copyright (c) 2022 Yakov Pechersky. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yakov Pechersky
-/

import data.finsupp.defs
import data.finset.pairwise

/-!

# Sums of collections of finsupp, and their support

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.
This file provides results about the `finsupp.support` of sums of collections of `finsupp`,
including sums of `list`, `multiset`, and `finset`.

The support of the sum is a subset of the union of the supports:
* `list.support_sum_subset`
* `multiset.support_sum_subset`
* `finset.support_sum_subset`

The support of the sum of pairwise disjoint finsupps is equal to the union of the supports
* `list.support_sum_eq`
* `multiset.support_sum_eq`
* `finset.support_sum_eq`

Member in the support of the indexed union over a collection iff
it is a member of the support of a member of the collection:
* `list.mem_foldr_sup_support_iff`
* `multiset.mem_sup_map_support_iff`
* `finset.mem_sup_support_iff`

-/

variables {ι M : Type*} [decidable_eq ι]

lemma list.support_sum_subset [add_monoid M] (l : list (ι →₀ M)) :
  l.sum.support ⊆ l.foldr ((⊔) ∘ finsupp.support) ∅ :=
begin
  induction l with hd tl IH,
  { simp },
  { simp only [list.sum_cons, finset.union_comm],
    refine finsupp.support_add.trans (finset.union_subset_union _ IH),
    refl }
end

lemma multiset.support_sum_subset [add_comm_monoid M] (s : multiset (ι →₀ M)) :
  s.sum.support ⊆ (s.map (finsupp.support)).sup :=
begin
  induction s using quot.induction_on,
  simpa using list.support_sum_subset _
end

lemma finset.support_sum_subset [add_comm_monoid M] (s : finset (ι →₀ M)) :
  (s.sum id).support ⊆ finset.sup s finsupp.support :=
by { classical, convert multiset.support_sum_subset s.1; simp }

lemma list.mem_foldr_sup_support_iff [has_zero M] {l : list (ι →₀ M)} {x : ι} :
  x ∈ l.foldr ((⊔) ∘ finsupp.support) ∅ ↔ ∃ (f : ι →₀ M) (hf : f ∈ l), x ∈ f.support :=
begin
  simp only [finset.sup_eq_union, list.foldr_map, finsupp.mem_support_iff, exists_prop],
  induction l with hd tl IH,
  { simp },
  { simp only [IH, list.foldr_cons, finset.mem_union, finsupp.mem_support_iff, list.mem_cons_iff],
    split,
    { rintro (h|h),
      { exact ⟨hd, or.inl rfl, h⟩ },
      { exact h.imp (λ f hf, hf.imp_left or.inr) } },
    { rintro ⟨f, rfl|hf, h⟩,
      { exact or.inl h },
      { exact or.inr ⟨f, hf, h⟩ } } }
end

lemma multiset.mem_sup_map_support_iff [has_zero M] {s : multiset (ι →₀ M)} {x : ι} :
  x ∈ (s.map (finsupp.support)).sup ↔ ∃ (f : ι →₀ M) (hf : f ∈ s), x ∈ f.support :=
quot.induction_on s $ λ _, by simpa using list.mem_foldr_sup_support_iff

lemma finset.mem_sup_support_iff [has_zero M] {s : finset (ι →₀ M)} {x : ι} :
  x ∈ s.sup finsupp.support ↔ ∃ (f : ι →₀ M) (hf : f ∈ s), x ∈ f.support :=
multiset.mem_sup_map_support_iff

lemma list.support_sum_eq [add_monoid M] (l : list (ι →₀ M))
  (hl : l.pairwise (disjoint on finsupp.support)) :
  l.sum.support = l.foldr ((⊔) ∘ finsupp.support) ∅ :=
begin
  induction l with hd tl IH,
  { simp },
  { simp only [list.pairwise_cons] at hl,
    simp only [list.sum_cons, list.foldr_cons, function.comp_app],
    rw [finsupp.support_add_eq, IH hl.right, finset.sup_eq_union],
    suffices : disjoint hd.support (tl.foldr ((⊔) ∘ finsupp.support) ∅),
    { exact finset.disjoint_of_subset_right (list.support_sum_subset _) this },
    { rw [←list.foldr_map, ←finset.bot_eq_empty, list.foldr_sup_eq_sup_to_finset],
      rw finset.disjoint_sup_right,
      intros f hf,
      simp only [list.mem_to_finset, list.mem_map] at hf,
      obtain ⟨f, hf, rfl⟩ := hf,
      exact hl.left _ hf } }
end

lemma multiset.support_sum_eq [add_comm_monoid M] (s : multiset (ι →₀ M))
  (hs : s.pairwise (disjoint on finsupp.support)) :
  s.sum.support = (s.map finsupp.support).sup :=
begin
  induction s using quot.induction_on,
  obtain ⟨l, hl, hd⟩ := hs,
  convert list.support_sum_eq _ _,
  { simp },
  { simp },
  { simp only [multiset.quot_mk_to_coe'', multiset.coe_map, multiset.coe_eq_coe] at hl,
    exact hl.symm.pairwise hd (λ _ _ h, disjoint.symm h) }
end

lemma finset.support_sum_eq [add_comm_monoid M] (s : finset (ι →₀ M))
  (hs : (s : set (ι →₀ M)).pairwise_disjoint finsupp.support) :
  (s.sum id).support = finset.sup s finsupp.support :=
begin
  classical,
  convert multiset.support_sum_eq s.1 _,
  { exact (finset.sum_val _).symm },
  { obtain ⟨l, hl, hn⟩ : ∃ (l : list (ι →₀ M)), l.to_finset = s ∧ l.nodup,
    { refine ⟨s.to_list, _, finset.nodup_to_list _⟩,
      simp },
    subst hl,
    rwa [list.to_finset_val, list.dedup_eq_self.mpr hn,
        multiset.pairwise_coe_iff_pairwise,
        ←list.pairwise_disjoint_iff_coe_to_finset_pairwise_disjoint hn],
    intros x y hxy,
    exact symmetric_disjoint hxy }
end


/-

EXAM 2 ANSWER KEY AND GRADING RUBRIC

This is the answer key and grading
rubric for CS2102 Fall 2018 Exam 2.
There are acceptable ways to have
answered some of the questions on
the exam, so correct answers need
not literally match those provided
here.

#1. 5 points each, no partial credit

#2. 10 points for the proposition and
10 points for the proof, with partial
credit of 5 points for a proof that is
correct but for minor issues, e.g., a
misplaced comma.

#3. 20 points, no partial credit

#4. 10 points for a right proposition,
10 points for the proof, with 5 points
for a proof that's substantially right
and suffering only from minor issues,
e.g., a misplaced colon or something.

#5. 10 free points plus 10 points for
the proof, with 3 points for using exists
elim correctly, 3 for using exists intro
correctly, 3 for using forall elimination
correctly (applying the proof of the ∀
to w), and 1 more for getting it all
right.
-/

/- ******************************* -/

/-
This exam focuses on assessing your
ability to write and prove propositions
in predicate logic, with an emphasis on
predicates, disjunctions, and existentially
quantified propositions. There are three
parts:

A: Predicates [20 points in 4 parts]
B: Disjuctions [40 points in 2 parts]
C. Existentials [40 point in 2 parts]
-/

/- ******************************** -/
/- *** A. PREDICATES [20 points] ***-/
/- ******************************** -/

/-
1a. Define a function called isOdd that
takes an argument, n : ℕ, and returns a
proposition that asserts that n is odd.
The function will thus be a predicate on
values of type ℕ. Hint: a number is odd
if it's one more than an even number.
-/

def isOdd(n:ℕ) :=
    ∃ m, 2 * m + 1 = n

-- We will accept an answer that uses mod

/-
1b. To test your predicate, use "example"
to write and prove isOdd(15).
-/

example : isOdd 15 :=
    ⟨ 7, rfl ⟩

-- an answer using mod will be just rfl

/-
1c. Define isSmall : ℕ → Prop, to be a
predicate that is true exactly when the
argument, n, is such that n = 0 ∨ n = 1
∨ n = 2 ∨ n = 3 ∨ n = 4 ∨ n = 5. (Don't
try to rewrite this proposition as an
inequality; just use it as is.)
-/

def isSmall (n: ℕ) : Prop :=
    n = 0 ∨ n = 1 ∨ n = 2 ∨ n = 3 ∨ n = 4 ∨ n = 5

/-
1d. Define a predicate, isBoth(n:ℕ) that
is true exacly when n satisfies both the
isOdd and isSmall predicates. Use isOdd
and isSmall in your answer.
-/

def isBoth (n: ℕ ): Prop :=
    isOdd n ∧ isSmall n

/- ******************* -/
/- *** DISJUNCTIONS ***-/
/- ******************* -/

/-
2. [20 Points]

Jane walks to school or she carries
her lunch. In either case, she uses
a bag. If she walks, she uses a bag for
her books. If she carries her lunch, she
uses a bag to carry her food. So if she
walks, she uses a bag, and if she carries
her lunch, she uses a bag. From the fact
that she walks or carries her lunch, and
from the added facts that in either case
she uses a bag, we can conclude that she
uses a bag.

Using Walks, Carries, and Bag as names
of propositions, write a Lean example
that asserts the following proposition;
then prove it.

If Walks, Carries, and Bag are
propositions, then if (Walks ∨ Carries)
is true, and then if (Walks implies Bag)
is true, and then if (Carries implies Bag)
is true, then Bag is true.

Here's a start.

example : ∀ (Walks Carries Bag : Prop), ...
-/

example: ∀ Walks Carries Bag : Prop,
    Walks ∨ Carries →
    (Walks → Bag) →
    (Carries → Bag) →
    Bag :=
begin
intros Walks Carries Bag,
intros wc wb cb,
apply or.elim wc wb cb
end

-- It's ok with shorter names (W, C, B)

/-
3. [20 Points]

Prove the following proposition.
-/

example :
    ∀ (P Q R : Prop),
    (P ∧ Q) → (Q ∨ R) → (P ∨ R) :=
begin
intros P Q R pq qr,
apply or.inl pq.left
end

/- *********************** -/
/- *** C. EXISTENTIALS  ***-/
/- *********************** -/

/-
4. [20 points]

Referring to the isBoth predicate you
defined in question #1, state and prove
the proposition that there *exists* a
number, n, that satisfies isBoth. Remember that you can use the unfold
tactic to expand the name of a predicate
in a goal. Use "example" to state the
proposition.
-/

example : ∃ n : ℕ, isBoth n :=
begin
apply exists.intro 3,
unfold isBoth,
apply and.intro,
apply exists.intro 1, apply rfl,
unfold isSmall,
right, right, right, left, apply rfl,
end

/-
5. [20 points]

Suppose that Heavy and Round are
predicates on values of any type, T.
Prove the proposition that if every
t : T is Heavy (satisfies the Heavy
predicate) and if there exists some
t : T that is Round (satisfies the
Round predicate) then there exists
some t : T is both Heavy and Round
(satisfies the conjunction of the
two properties).
-/

example :
∀ T : Type, ∀ (Heavy Round : T → Prop),
(∀ t, Heavy t) → (∃ t, Round t) →
(∃ t, Heavy t ∧ Round t) :=
begin
intros T H R,
assume all_h exists_r,
apply exists.elim exists_r,
intros w rw,
apply exists.intro w,
apply and.intro (all_h w) rw,
end


class One (M : Type u) where one : M
instance {M} [One M] : OfNat M (nat_lit 1) := ⟨One.one⟩

class Zero (A : Type u) where zero : A
instance {A} [Zero A] : OfNat A (nat_lit 0) := ⟨Zero.zero⟩

class Monoid (M : Type u) extends Mul M, One M where
  mul_one (m : M) : m * 1 = m

class AddCommMonoid (A : Type u) extends Add A, Zero A

class MonoidWithZero (M₀ : Type u) extends Monoid M₀, Zero M₀

class Semiring (R : Type u) extends AddCommMonoid R, MonoidWithZero R, One R

#print Semiring -- only toMonoid field, no duplicate toOne

def oneViaMonoid {M} [Monoid M] : M := 1
example {R} [Semiring R] : (1 : R) = oneViaMonoid := rfl

example : Semiring Nat where
  mul_one := by simp
  zero := 0
  one := 1