/- Copyright (c) 2022 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ module public import Mathlib.Analysis.Calculus.ContDiff.Comp public import Mathlib.Analysis.Calculus.ParametricIntegral public import Mathlib.Analysis.Convolution /-! # Differentiability of a convolution of functions Criteria for a convolution of functions to be differentiable. ## Main Results * `HasCompactSupport.hasFDerivAt_convolution_right` and `HasCompactSupport.hasFDerivAt_convolution_left`: we can compute the total derivative of the convolution as a convolution with the total derivative of the right (left) function. * `HasCompactSupport.contDiff_convolution_right` and `HasCompactSupport.contDiff_convolution_left`: the convolution is `π’žβΏ` if one of the functions is `π’žβΏ` with compact support and the other function in locally integrable. -/ public section open Set Function Filter MeasureTheory MeasureTheory.Measure TopologicalSpace open Bornology ContinuousLinearMap Metric Topology open scoped Pointwise NNReal Filter universe uπ•œ uG uE uE' uE'' uF uF' uF'' uP variable {π•œ : Type uπ•œ} {G : Type uG} {E : Type uE} {E' : Type uE'} {E'' : Type uE''} {F : Type uF} {F' : Type uF'} {F'' : Type uF''} {P : Type uP} variable [NormedAddCommGroup E] [NormedAddCommGroup E'] [NormedAddCommGroup E''] [NormedAddCommGroup F] {f f' : G β†’ E} {g g' : G β†’ E'} {x x' : G} {y y' : E} namespace MeasureTheory open scoped Convolution section RCLike variable [RCLike π•œ] variable [NormedSpace π•œ E] variable [NormedSpace π•œ E'] variable [NormedSpace π•œ E''] variable [NormedSpace ℝ F] [NormedSpace π•œ F] variable {n : β„•βˆž} variable [MeasurableSpace G] {ΞΌ Ξ½ : Measure G} variable (L : E β†’L[π•œ] E' β†’L[π•œ] F) variable [NormedAddCommGroup G] [BorelSpace G] variable [NormedSpace π•œ G] [SFinite ΞΌ] [IsAddLeftInvariant ΞΌ] /-- Compute the total derivative of `f ⋆ g` if `g` is `C^1` with compact support and `f` is locally integrable. To write down the total derivative as a convolution, we use `ContinuousLinearMap.precompR`. -/ theorem _root_.HasCompactSupport.hasFDerivAt_convolution_right (hcg : HasCompactSupport g) (hf : LocallyIntegrable f ΞΌ) (hg : ContDiff π•œ 1 g) (xβ‚€ : G) : HasFDerivAt (f ⋆[L, ΞΌ] g) ((f ⋆[L.precompR G, ΞΌ] fderiv π•œ g) xβ‚€) xβ‚€ := by rcases hcg.eq_zero_or_finiteDimensional π•œ hg.continuous with (rfl | fin_dim) Β· have : fderiv π•œ (0 : G β†’ E') = 0 := fderiv_const (0 : E') simp only [this, convolution_zero, Pi.zero_apply] exact hasFDerivAt_const (0 : F) xβ‚€ have : ProperSpace G := FiniteDimensional.proper_rclike π•œ G set L' := L.precompR G have h1 : βˆ€αΆ  x in 𝓝 xβ‚€, AEStronglyMeasurable (fun t => L (f t) (g (x - t))) ΞΌ := Eventually.of_forall (hf.aestronglyMeasurable.convolution_integrand_snd L hg.continuous.aestronglyMeasurable) have h2 : βˆ€ x, AEStronglyMeasurable (fun t => L' (f t) (fderiv π•œ g (x - t))) ΞΌ := hf.aestronglyMeasurable.convolution_integrand_snd L' (hg.continuous_fderiv one_ne_zero).aestronglyMeasurable have h3 : βˆ€ x t, HasFDerivAt (fun x => g (x - t)) (fderiv π•œ g (x - t)) x := fun x t ↦ by simpa using! (hg.differentiable one_ne_zero).differentiableAt.hasFDerivAt.comp x ((hasFDerivAt_id x).sub (hasFDerivAt_const t x)) let K' := -tsupport (fderiv π•œ g) + closedBall xβ‚€ 1 have hK' : IsCompact K' := (hcg.fderiv π•œ).isCompact.neg.add (isCompact_closedBall xβ‚€ 1) apply hasFDerivAt_integral_of_dominated_of_fderiv_le (ball_mem_nhds _ zero_lt_one) h1 _ (h2 xβ‚€) Β· filter_upwards with t x hx using (hcg.fderiv π•œ).convolution_integrand_bound_right L' (hg.continuous_fderiv one_ne_zero) (ball_subset_closedBall hx) Β· rw [integrable_indicator_iff hK'.measurableSet] exact ((hf.integrableOn_isCompact hK').norm.const_mul _).mul_const _ Β· exact Eventually.of_forall fun t x _ => (L _).hasFDerivAt.comp x (h3 x t) Β· exact hcg.convolutionExists_right L hf hg.continuous xβ‚€ theorem _root_.HasCompactSupport.hasFDerivAt_convolution_left [IsNegInvariant ΞΌ] (hcf : HasCompactSupport f) (hf : ContDiff π•œ 1 f) (hg : LocallyIntegrable g ΞΌ) (xβ‚€ : G) : HasFDerivAt (f ⋆[L, ΞΌ] g) ((fderiv π•œ f ⋆[L.precompL G, ΞΌ] g) xβ‚€) xβ‚€ := by simp +singlePass only [← convolution_flip] exact hcf.hasFDerivAt_convolution_right L.flip hg hf xβ‚€ end RCLike section Real /-! The one-variable case -/ variable [RCLike π•œ] variable [NormedSpace π•œ E] variable [NormedSpace π•œ E'] variable [NormedSpace ℝ F] [NormedSpace π•œ F] variable {fβ‚€ : π•œ β†’ E} {gβ‚€ : π•œ β†’ E'} variable {n : β„•βˆž} variable (L : E β†’L[π•œ] E' β†’L[π•œ] F) variable {ΞΌ : Measure π•œ} variable [IsAddLeftInvariant ΞΌ] [SFinite ΞΌ] theorem _root_.HasCompactSupport.hasDerivAt_convolution_right (hf : LocallyIntegrable fβ‚€ ΞΌ) (hcg : HasCompactSupport gβ‚€) (hg : ContDiff π•œ 1 gβ‚€) (xβ‚€ : π•œ) : HasDerivAt (fβ‚€ ⋆[L, ΞΌ] gβ‚€) ((fβ‚€ ⋆[L, ΞΌ] deriv gβ‚€) xβ‚€) xβ‚€ := by convert (hcg.hasFDerivAt_convolution_right L hf hg xβ‚€).hasDerivAt rw [convolution_precompR_apply L hf (hcg.fderiv π•œ) (hg.continuous_fderiv one_ne_zero)] rfl theorem _root_.HasCompactSupport.hasDerivAt_convolution_left [IsNegInvariant ΞΌ] (hcf : HasCompactSupport fβ‚€) (hf : ContDiff π•œ 1 fβ‚€) (hg : LocallyIntegrable gβ‚€ ΞΌ) (xβ‚€ : π•œ) : HasDerivAt (fβ‚€ ⋆[L, ΞΌ] gβ‚€) ((deriv fβ‚€ ⋆[L, ΞΌ] gβ‚€) xβ‚€) xβ‚€ := by simp +singlePass only [← convolution_flip] exact hcf.hasDerivAt_convolution_right L.flip hg hf xβ‚€ end Real section WithParam variable [RCLike π•œ] [NormedSpace π•œ E] [NormedSpace π•œ E'] [NormedSpace π•œ E''] [NormedSpace ℝ F] [NormedSpace π•œ F] [MeasurableSpace G] [NormedAddCommGroup G] [BorelSpace G] [NormedSpace π•œ G] [NormedAddCommGroup P] [NormedSpace π•œ P] {ΞΌ : Measure G} (L : E β†’L[π•œ] E' β†’L[π•œ] F) /-- The derivative of the convolution `f * g` is given by `f * Dg`, when `f` is locally integrable and `g` is `C^1` and compactly supported. Version where `g` depends on an additional parameter in an open subset `s` of a parameter space `P` (and the compact support `k` is independent of the parameter in `s`). -/ theorem hasFDerivAt_convolution_right_with_param {g : P β†’ G β†’ E'} {s : Set P} {k : Set G} (hs : IsOpen s) (hk : IsCompact k) (hgs : βˆ€ p, βˆ€ x, p ∈ s β†’ x βˆ‰ k β†’ g p x = 0) (hf : LocallyIntegrable f ΞΌ) (hg : ContDiffOn π•œ 1 β†Ώg (s Γ—Λ’ univ)) (qβ‚€ : P Γ— G) (hqβ‚€ : qβ‚€.1 ∈ s) : HasFDerivAt (fun q : P Γ— G => (f ⋆[L, ΞΌ] g q.1) q.2) ((f ⋆[L.precompR (P Γ— G), ΞΌ] fun x : G => fderiv π•œ β†Ώg (qβ‚€.1, x)) qβ‚€.2) qβ‚€ := by let g' := fderiv π•œ β†Ώg have A : βˆ€ p ∈ s, Continuous (g p) := fun p hp ↦ by refine hg.continuousOn.comp_continuous (.prodMk_right _) fun x => ?_ simpa only [prodMk_mem_set_prod_eq, mem_univ, and_true] using hp have A' : βˆ€ q : P Γ— G, q.1 ∈ s β†’ s Γ—Λ’ univ ∈ 𝓝 q := fun q hq ↦ by apply (hs.prod isOpen_univ).mem_nhds simpa only [mem_prod, mem_univ, and_true] using hq -- The derivative of `g` vanishes away from `k`. have g'_zero : βˆ€ p x, p ∈ s β†’ x βˆ‰ k β†’ g' (p, x) = 0 := by intro p x hp hx refine (hasFDerivAt_zero_of_eventually_const 0 ?_).fderiv have M2 : kᢜ ∈ 𝓝 x := hk.isClosed.isOpen_compl.mem_nhds hx have M1 : s ∈ 𝓝 p := hs.mem_nhds hp rw [nhds_prod_eq] filter_upwards [prod_mem_prod M1 M2] rintro ⟨p, y⟩ ⟨hp, hy⟩ exact hgs p y hp hy /- We find a small neighborhood of `{qβ‚€.1} Γ— k` on which the derivative is uniformly bounded. This follows from the continuity at all points of the compact set `k`. -/ obtain ⟨Ρ, C, Ξ΅pos, hβ‚€Ξ΅, hΡ⟩ : βˆƒ Ξ΅ C, 0 < Ξ΅ ∧ ball qβ‚€.1 Ξ΅ βŠ† s ∧ βˆ€ p x, β€–p - qβ‚€.1β€– < Ξ΅ β†’ β€–g' (p, x)β€– ≀ C := by have A : IsCompact ({qβ‚€.1} Γ—Λ’ k) := isCompact_singleton.prod hk obtain ⟨t, kt, t_open, ht⟩ : βˆƒ t, {qβ‚€.1} Γ—Λ’ k βŠ† t ∧ IsOpen t ∧ IsBounded (g' '' t) := by have B : ContinuousOn g' (s Γ—Λ’ univ) := hg.continuousOn_fderiv_of_isOpen (hs.prod isOpen_univ) le_rfl apply exists_isOpen_isBounded_image_of_isCompact_of_continuousOn A (hs.prod isOpen_univ) _ B simp only [prod_subset_prod_iff, hqβ‚€, singleton_subset_iff, subset_univ, and_self_iff, true_or] obtain ⟨Ρ, Ξ΅pos, hΞ΅, h'Ρ⟩ : βˆƒ Ξ΅ : ℝ, 0 < Ξ΅ ∧ thickening Ξ΅ ({qβ‚€.fst} Γ—Λ’ k) βŠ† t ∧ ball qβ‚€.1 Ξ΅ βŠ† s := by obtain ⟨Ρ, Ξ΅pos, hΡ⟩ : βˆƒ Ξ΅ : ℝ, 0 < Ξ΅ ∧ thickening Ξ΅ (({qβ‚€.fst} : Set P) Γ—Λ’ k) βŠ† t := A.exists_thickening_subset_open t_open kt obtain ⟨δ, Ξ΄pos, hδ⟩ : βˆƒ Ξ΄ : ℝ, 0 < Ξ΄ ∧ ball qβ‚€.1 Ξ΄ βŠ† s := Metric.isOpen_iff.1 hs _ hqβ‚€ refine ⟨min Ξ΅ Ξ΄, lt_min Ξ΅pos Ξ΄pos, ?_, ?_⟩ Β· exact Subset.trans (thickening_mono (min_le_left _ _) _) hΞ΅ Β· exact Subset.trans (ball_subset_ball (min_le_right _ _)) hΞ΄ obtain ⟨C, Cpos, hC⟩ : βˆƒ C, 0 < C ∧ g' '' t βŠ† closedBall 0 C := ht.subset_closedBall_lt 0 0 refine ⟨Ρ, C, Ξ΅pos, h'Ξ΅, fun p x hp => ?_⟩ have hps : p ∈ s := h'Ξ΅ (mem_ball_iff_norm.2 hp) by_cases hx : x ∈ k Β· have H : (p, x) ∈ t := by apply hΞ΅ refine mem_thickening_iff.2 ⟨(qβ‚€.1, x), ?_, ?_⟩ Β· simp only [hx, singleton_prod, mem_image, Prod.mk_inj, true_and, exists_eq_right] Β· rw [← dist_eq_norm] at hp simpa only [Prod.dist_eq, Ξ΅pos, dist_self, max_lt_iff, and_true] using hp have : g' (p, x) ∈ closedBall (0 : P Γ— G β†’L[π•œ] E') C := hC (mem_image_of_mem _ H) rwa [mem_closedBall_zero_iff] at this Β· have : g' (p, x) = 0 := g'_zero _ _ hps hx rw [this] simpa only [norm_zero] using Cpos.le /- Now, we wish to apply a theorem on differentiation of integrals. For this, we need to check trivial measurability or integrability assumptions (in `I1`, `I2`, `I3`), as well as a uniform integrability assumption over the derivative (in `I4` and `I5`) and pointwise differentiability in `I6`. -/ have I1 : βˆ€αΆ  x : P Γ— G in 𝓝 qβ‚€, AEStronglyMeasurable (fun a : G => L (f a) (g x.1 (x.2 - a))) ΞΌ := by filter_upwards [A' qβ‚€ hqβ‚€] rintro ⟨p, x⟩ ⟨hp, -⟩ refine (HasCompactSupport.convolutionExists_right L ?_ hf (A _ hp) _).1 apply hk.of_isClosed_subset (isClosed_tsupport _) exact closure_minimal (support_subset_iff'.2 fun z hz => hgs _ _ hp hz) hk.isClosed have I2 : Integrable (fun a : G => L (f a) (g qβ‚€.1 (qβ‚€.2 - a))) ΞΌ := by have M : HasCompactSupport (g qβ‚€.1) := HasCompactSupport.intro hk fun x hx => hgs qβ‚€.1 x hqβ‚€ hx apply M.convolutionExists_right L hf (A qβ‚€.1 hqβ‚€) qβ‚€.2 have I3 : AEStronglyMeasurable (fun a : G => (L (f a)).comp (g' (qβ‚€.fst, qβ‚€.snd - a))) ΞΌ := by have T : HasCompactSupport fun y => g' (qβ‚€.1, y) := HasCompactSupport.intro hk fun x hx => g'_zero qβ‚€.1 x hqβ‚€ hx apply (HasCompactSupport.convolutionExists_right (L.precompR (P Γ— G) :) T hf _ qβ‚€.2).1 have : ContinuousOn g' (s Γ—Λ’ univ) := hg.continuousOn_fderiv_of_isOpen (hs.prod isOpen_univ) le_rfl apply this.comp_continuous (.prodMk_right _) intro x simpa only [prodMk_mem_set_prod_eq, mem_univ, and_true] using hqβ‚€ set K' := (-k + {qβ‚€.2} : Set G) with K'_def have hK' : IsCompact K' := hk.neg.add isCompact_singleton obtain ⟨U, U_open, K'U, hU⟩ : βˆƒ U, IsOpen U ∧ K' βŠ† U ∧ IntegrableOn f U ΞΌ := hf.integrableOn_nhds_isCompact hK' obtain ⟨δ, Ξ΄pos, δΡ, hδ⟩ : βˆƒ Ξ΄, (0 : ℝ) < Ξ΄ ∧ Ξ΄ ≀ Ξ΅ ∧ K' + ball 0 Ξ΄ βŠ† U := by obtain ⟨V, V_mem, hV⟩ : βˆƒ V ∈ 𝓝 (0 : G), K' + V βŠ† U := compact_open_separated_add_right hK' U_open K'U rcases Metric.mem_nhds_iff.1 V_mem with ⟨δ, Ξ΄pos, hδ⟩ refine ⟨min Ξ΄ Ξ΅, lt_min Ξ΄pos Ξ΅pos, min_le_right Ξ΄ Ξ΅, ?_⟩ exact (add_subset_add_left ((ball_subset_ball (min_le_left _ _)).trans hΞ΄)).trans hV letI := ContinuousLinearMap.hasOpNorm (π•œ := π•œ) (π•œβ‚‚ := π•œ) (E := E) (F := (P Γ— G β†’L[π•œ] E') β†’L[π•œ] P Γ— G β†’L[π•œ] F) (σ₁₂ := RingHom.id π•œ) let bound : G β†’ ℝ := indicator U fun t => β€–(L.precompR (P Γ— G))β€– * β€–f tβ€– * C have I4 : βˆ€α΅ a : G βˆ‚ΞΌ, βˆ€ x : P Γ— G, dist x qβ‚€ < Ξ΄ β†’ β€–L.precompR (P Γ— G) (f a) (g' (x.fst, x.snd - a))β€– ≀ bound a := by filter_upwards with a x hx rw [Prod.dist_eq, dist_eq_norm, dist_eq_norm] at hx have : (-tsupport fun a => g' (x.1, a)) + ball qβ‚€.2 Ξ΄ βŠ† U := by apply Subset.trans _ hΞ΄ rw [K'_def, add_assoc] apply add_subset_add Β· rw [neg_subset_neg] refine closure_minimal (support_subset_iff'.2 fun z hz => ?_) hk.isClosed apply g'_zero x.1 z (hβ‚€Ξ΅ _) hz rw [mem_ball_iff_norm] exact ((le_max_left _ _).trans_lt hx).trans_le δΡ Β· simp only [add_ball, thickening_singleton, zero_vadd, subset_rfl] apply convolution_integrand_bound_right_of_le_of_subset _ _ _ this Β· intro y exact hΞ΅ _ _ (((le_max_left _ _).trans_lt hx).trans_le δΡ) Β· rw [mem_ball_iff_norm] exact (le_max_right _ _).trans_lt hx have I5 : Integrable bound ΞΌ := by rw [integrable_indicator_iff U_open.measurableSet] exact (hU.norm.const_mul _).mul_const _ have I6 : βˆ€α΅ a : G βˆ‚ΞΌ, βˆ€ x : P Γ— G, dist x qβ‚€ < Ξ΄ β†’ HasFDerivAt (fun x : P Γ— G => L (f a) (g x.1 (x.2 - a))) ((L (f a)).comp (g' (x.fst, x.snd - a))) x := by filter_upwards with a x hx apply (L _).hasFDerivAt.comp x have N : s Γ—Λ’ univ ∈ 𝓝 (x.1, x.2 - a) := by apply A' apply hβ‚€Ξ΅ rw [Prod.dist_eq] at hx exact lt_of_lt_of_le (lt_of_le_of_lt (le_max_left _ _) hx) δΡ have Z := ((hg.differentiableOn one_ne_zero).differentiableAt N).hasFDerivAt have Z' : HasFDerivAt (fun x : P Γ— G => (x.1, x.2 - a)) (ContinuousLinearMap.id π•œ (P Γ— G)) x := by have : (fun x : P Γ— G => (x.1, x.2 - a)) = _root_.id - fun x => (0, a) := by ext x <;> simp only [Pi.sub_apply, _root_.id, Prod.fst_sub, sub_zero, Prod.snd_sub] rw [this] exact (hasFDerivAt_id x).sub_const (0, a) exact Z.comp x Z' exact hasFDerivAt_integral_of_dominated_of_fderiv_le (ball_mem_nhds _ Ξ΄pos) I1 I2 I3 I4 I5 I6 /-- The convolution `f * g` is `C^n` when `f` is locally integrable and `g` is `C^n` and compactly supported. Version where `g` depends on an additional parameter in an open subset `s` of a parameter space `P` (and the compact support `k` is independent of the parameter in `s`). In this version, all the types belong to the same universe (to get an induction working in the proof). Use instead `contDiffOn_convolution_right_with_param`, which removes this restriction. -/ theorem contDiffOn_convolution_right_with_param_aux {G : Type uP} {E' : Type uP} {F : Type uP} {P : Type uP} [NormedAddCommGroup E'] [NormedAddCommGroup F] [NormedSpace π•œ E'] [NormedSpace ℝ F] [NormedSpace π•œ F] [MeasurableSpace G] {ΞΌ : Measure G} [NormedAddCommGroup G] [BorelSpace G] [NormedSpace π•œ G] [NormedAddCommGroup P] [NormedSpace π•œ P] {f : G β†’ E} {n : β„•βˆž} (L : E β†’L[π•œ] E' β†’L[π•œ] F) {g : P β†’ G β†’ E'} {s : Set P} {k : Set G} (hs : IsOpen s) (hk : IsCompact k) (hgs : βˆ€ p, βˆ€ x, p ∈ s β†’ x βˆ‰ k β†’ g p x = 0) (hf : LocallyIntegrable f ΞΌ) (hg : ContDiffOn π•œ n β†Ώg (s Γ—Λ’ univ)) : ContDiffOn π•œ n (fun q : P Γ— G => (f ⋆[L, ΞΌ] g q.1) q.2) (s Γ—Λ’ univ) := by /- We have a formula for the derivation of `f * g`, which is of the same form, thanks to `hasFDerivAt_convolution_right_with_param`. Therefore, we can prove the result by induction on `n` (but for this we need the spaces at the different steps of the induction to live in the same universe, which is why we make the assumption in the lemma that all the relevant spaces come from the same universe). -/ induction n using ENat.nat_induction generalizing g E' F with | zero => rw [WithTop.coe_zero, contDiffOn_zero] at hg ⊒ exact continuousOn_convolution_right_with_param L hk hgs hf hg | succ n ih => simp only [Nat.succ_eq_add_one, Nat.cast_add, Nat.cast_one, WithTop.coe_add, WithTop.coe_natCast, WithTop.coe_one] at hg ⊒ let f' : P β†’ G β†’ P Γ— G β†’L[π•œ] F := fun p a => (f ⋆[L.precompR (P Γ— G), ΞΌ] fun x : G => fderiv π•œ (uncurry g) (p, x)) a have A : βˆ€ qβ‚€ : P Γ— G, qβ‚€.1 ∈ s β†’ HasFDerivAt (fun q : P Γ— G => (f ⋆[L, ΞΌ] g q.1) q.2) (f' qβ‚€.1 qβ‚€.2) qβ‚€ := hasFDerivAt_convolution_right_with_param L hs hk hgs hf hg.one_of_succ rw [contDiffOn_succ_iff_fderiv_of_isOpen (hs.prod (@isOpen_univ G _))] at hg ⊒ refine ⟨?_, by simp, ?_⟩ Β· rintro ⟨p, x⟩ ⟨hp, -⟩ exact (A (p, x) hp).differentiableAt.differentiableWithinAt Β· suffices H : ContDiffOn π•œ n β†Ώf' (s Γ—Λ’ univ) by apply H.congr rintro ⟨p, x⟩ ⟨hp, -⟩ exact (A (p, x) hp).fderiv have B : βˆ€ (p : P) (x : G), p ∈ s β†’ x βˆ‰ k β†’ fderiv π•œ (uncurry g) (p, x) = 0 := by intro p x hp hx apply (hasFDerivAt_zero_of_eventually_const (0 : E') _).fderiv have M2 : kᢜ ∈ 𝓝 x := IsOpen.mem_nhds hk.isClosed.isOpen_compl hx have M1 : s ∈ 𝓝 p := hs.mem_nhds hp rw [nhds_prod_eq] filter_upwards [prod_mem_prod M1 M2] rintro ⟨p, y⟩ ⟨hp, hy⟩ exact hgs p y hp hy apply ih (L.precompR (P Γ— G) :) B convert! hg.2.2 | top ih => rw [contDiffOn_infty] at hg ⊒ exact fun n ↦ ih n L hgs (hg n) /-- The convolution `f * g` is `C^n` when `f` is locally integrable and `g` is `C^n` and compactly supported. Version where `g` depends on an additional parameter in an open subset `s` of a parameter space `P` (and the compact support `k` is independent of the parameter in `s`). -/ theorem contDiffOn_convolution_right_with_param {f : G β†’ E} {n : β„•βˆž} (L : E β†’L[π•œ] E' β†’L[π•œ] F) {g : P β†’ G β†’ E'} {s : Set P} {k : Set G} (hs : IsOpen s) (hk : IsCompact k) (hgs : βˆ€ p, βˆ€ x, p ∈ s β†’ x βˆ‰ k β†’ g p x = 0) (hf : LocallyIntegrable f ΞΌ) (hg : ContDiffOn π•œ n β†Ώg (s Γ—Λ’ univ)) : ContDiffOn π•œ n (fun q : P Γ— G => (f ⋆[L, ΞΌ] g q.1) q.2) (s Γ—Λ’ univ) := by /- The result is known when all the universes are the same, from `contDiffOn_convolution_right_with_param_aux`. We reduce to this situation by pushing everything through `ULift` continuous linear equivalences. -/ let eG : Type max uG uE' uF uP := ULift.{max uE' uF uP} G borelize eG let eE' : Type max uE' uG uF uP := ULift.{max uG uF uP} E' let eF : Type max uF uG uE' uP := ULift.{max uG uE' uP} F let eP : Type max uP uG uE' uF := ULift.{max uG uE' uF} P let isoG : eG ≃L[π•œ] G := ContinuousLinearEquiv.ulift let isoE' : eE' ≃L[π•œ] E' := ContinuousLinearEquiv.ulift let isoF : eF ≃L[π•œ] F := ContinuousLinearEquiv.ulift let isoP : eP ≃L[π•œ] P := ContinuousLinearEquiv.ulift let ef := f ∘ isoG let eΞΌ : Measure eG := Measure.map isoG.symm ΞΌ let eg : eP β†’ eG β†’ eE' := fun ep ex => isoE'.symm (g (isoP ep) (isoG ex)) let eL := ContinuousLinearMap.comp ((ContinuousLinearEquiv.arrowCongr isoE' isoF).symm : (E' β†’L[π•œ] F) β†’L[π•œ] eE' β†’L[π•œ] eF) L let R := fun q : eP Γ— eG => (ef ⋆[eL, eΞΌ] eg q.1) q.2 have R_contdiff : ContDiffOn π•œ n R ((isoP ⁻¹' s) Γ—Λ’ univ) := by have hek : IsCompact (isoG ⁻¹' k) := isoG.toHomeomorph.isClosedEmbedding.isCompact_preimage hk have hes : IsOpen (isoP ⁻¹' s) := isoP.continuous.isOpen_preimage _ hs refine contDiffOn_convolution_right_with_param_aux eL hes hek ?_ ?_ ?_ Β· intro p x hp hx simp only [eg, ContinuousLinearEquiv.map_eq_zero_iff] exact hgs _ _ hp hx Β· exact (locallyIntegrable_map_homeomorph isoG.symm.toHomeomorph).2 hf Β· apply isoE'.symm.contDiff.comp_contDiffOn apply hg.comp (isoP.prodCongr isoG).contDiff.contDiffOn rintro ⟨p, x⟩ ⟨hp, -⟩ simpa only [mem_preimage, ContinuousLinearEquiv.prodCongr_apply, prodMk_mem_set_prod_eq, mem_univ, and_true] using hp have A : ContDiffOn π•œ n (isoF ∘ R ∘ (isoP.prodCongr isoG).symm) (s Γ—Λ’ univ) := by apply isoF.contDiff.comp_contDiffOn apply R_contdiff.comp (ContinuousLinearEquiv.contDiff _).contDiffOn rintro ⟨p, x⟩ ⟨hp, -⟩ simpa only [mem_preimage, mem_prod, mem_univ, and_true, ContinuousLinearEquiv.prodCongr_symm, ContinuousLinearEquiv.prodCongr_apply, ContinuousLinearEquiv.apply_symm_apply] using hp have : isoF ∘ R ∘ (isoP.prodCongr isoG).symm = fun q : P Γ— G => (f ⋆[L, ΞΌ] g q.1) q.2 := by apply funext rintro ⟨p, x⟩ simp only [(Β· ∘ Β·), ContinuousLinearEquiv.prodCongr_symm, ContinuousLinearEquiv.prodCongr_apply] simp only [R, convolution] rw [IsClosedEmbedding.integral_map, ← isoF.integral_comp_comm] Β· rfl Β· exact isoG.symm.toHomeomorph.isClosedEmbedding simp_rw [this] at A exact A /-- The convolution `f * g` is `C^n` when `f` is locally integrable and `g` is `C^n` and compactly supported. Version where `g` depends on an additional parameter in an open subset `s` of a parameter space `P` (and the compact support `k` is independent of the parameter in `s`), given in terms of composition with an additional `C^n` function. -/ theorem contDiffOn_convolution_right_with_param_comp {n : β„•βˆž} (L : E β†’L[π•œ] E' β†’L[π•œ] F) {s : Set P} {v : P β†’ G} (hv : ContDiffOn π•œ n v s) {f : G β†’ E} {g : P β†’ G β†’ E'} {k : Set G} (hs : IsOpen s) (hk : IsCompact k) (hgs : βˆ€ p, βˆ€ x, p ∈ s β†’ x βˆ‰ k β†’ g p x = 0) (hf : LocallyIntegrable f ΞΌ) (hg : ContDiffOn π•œ n β†Ώg (s Γ—Λ’ univ)) : ContDiffOn π•œ n (fun x => (f ⋆[L, ΞΌ] g x) (v x)) s := by apply (contDiffOn_convolution_right_with_param L hs hk hgs hf hg).comp (contDiffOn_id.prodMk hv) intro x hx simp only [hx, prodMk_mem_set_prod_eq, mem_univ, and_self_iff, _root_.id] /-- The convolution `g * f` is `C^n` when `f` is locally integrable and `g` is `C^n` and compactly supported. Version where `g` depends on an additional parameter in an open subset `s` of a parameter space `P` (and the compact support `k` is independent of the parameter in `s`). -/ theorem contDiffOn_convolution_left_with_param [ΞΌ.IsAddLeftInvariant] [ΞΌ.IsNegInvariant] (L : E' β†’L[π•œ] E β†’L[π•œ] F) {f : G β†’ E} {n : β„•βˆž} {g : P β†’ G β†’ E'} {s : Set P} {k : Set G} (hs : IsOpen s) (hk : IsCompact k) (hgs : βˆ€ p, βˆ€ x, p ∈ s β†’ x βˆ‰ k β†’ g p x = 0) (hf : LocallyIntegrable f ΞΌ) (hg : ContDiffOn π•œ n β†Ώg (s Γ—Λ’ univ)) : ContDiffOn π•œ n (fun q : P Γ— G => (g q.1 ⋆[L, ΞΌ] f) q.2) (s Γ—Λ’ univ) := by simpa only [convolution_flip] using contDiffOn_convolution_right_with_param L.flip hs hk hgs hf hg /-- The convolution `g * f` is `C^n` when `f` is locally integrable and `g` is `C^n` and compactly supported. Version where `g` depends on an additional parameter in an open subset `s` of a parameter space `P` (and the compact support `k` is independent of the parameter in `s`), given in terms of composition with additional `C^n` functions. -/ theorem contDiffOn_convolution_left_with_param_comp [ΞΌ.IsAddLeftInvariant] [ΞΌ.IsNegInvariant] (L : E' β†’L[π•œ] E β†’L[π•œ] F) {s : Set P} {n : β„•βˆž} {v : P β†’ G} (hv : ContDiffOn π•œ n v s) {f : G β†’ E} {g : P β†’ G β†’ E'} {k : Set G} (hs : IsOpen s) (hk : IsCompact k) (hgs : βˆ€ p, βˆ€ x, p ∈ s β†’ x βˆ‰ k β†’ g p x = 0) (hf : LocallyIntegrable f ΞΌ) (hg : ContDiffOn π•œ n β†Ώg (s Γ—Λ’ univ)) : ContDiffOn π•œ n (fun x => (g x ⋆[L, ΞΌ] f) (v x)) s := by apply (contDiffOn_convolution_left_with_param L hs hk hgs hf hg).comp (contDiffOn_id.prodMk hv) intro x hx simp only [hx, prodMk_mem_set_prod_eq, mem_univ, and_self_iff, _root_.id] theorem _root_.HasCompactSupport.contDiff_convolution_right {n : β„•βˆž} (hcg : HasCompactSupport g) (hf : LocallyIntegrable f ΞΌ) (hg : ContDiff π•œ n g) : ContDiff π•œ n (f ⋆[L, ΞΌ] g) := by rcases exists_compact_iff_hasCompactSupport.2 hcg with ⟨k, hk, h'k⟩ rw [← contDiffOn_univ] exact contDiffOn_convolution_right_with_param_comp L contDiffOn_id isOpen_univ hk (fun p x _ hx => h'k x hx) hf (hg.comp contDiff_snd).contDiffOn theorem _root_.HasCompactSupport.contDiff_convolution_left [ΞΌ.IsAddLeftInvariant] [ΞΌ.IsNegInvariant] {n : β„•βˆž} (hcf : HasCompactSupport f) (hf : ContDiff π•œ n f) (hg : LocallyIntegrable g ΞΌ) : ContDiff π•œ n (f ⋆[L, ΞΌ] g) := by rw [← convolution_flip] exact hcf.contDiff_convolution_right L.flip hg hf end WithParam end MeasureTheory