Module mathcomp.experimental_reals.realseq
From mathcomp Require Import all_ssreflect all_algebra.
From mathcomp Require Import bigenough.
From mathcomp.classical Require Import boolp classical_sets functions.
From mathcomp.classical Require Import mathcomp_extra.
From mathcomp Require Import xfinmap constructive_ereal reals discrete.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Unset SsrOldRewriteGoalsOrder.
Import Order.TTheory GRing.Theory Num.Theory BigEnough.
Local Open Scope ring_scope.
Notation "f '<=1' g" := (forall x, f x <= g x)
(at level 70, no associativity).
Notation "f '<=2' g" := (forall x y, f x y <= g x y)
(at level 70, no associativity).
Section FFTheory.
Context {R : realDomainType} (T : Type).
Implicit Types (f g h : T -> R).
Lemma leff f : f <=1 f.
Proof.
by []. Qed.
Lemma lef_trans g f h : f <=1 g -> g <=1 h -> f <=1 h.
Proof.
Section Nbh.
Context {R : realType}.
Inductive nbh : \bar R -> predArgType :=
| NFin (c e : R) of (0 < e) : nbh c%:E
| NPInf (M : R) : nbh +oo
| NNInf (M : R) : nbh -oo.
Coercion pred_of_nbh l (v : nbh l) :=
match v with
| @NFin l e _ => [pred x : R | `|x - l| < e]
| @NPInf M => [pred x : R | x > M]
| @NNInf M => [pred x : R | x < M]
end.
End Nbh.
Section NbhElim.
Context {R : realType}.
Lemma nbh_finW c (P : forall x, nbh x -> Prop) :
(forall e (h : 0 < e), P _ (@NFin R c e h))
-> forall (v : nbh c%:E), P _ v.
Proof.
Lemma nbh_pinfW (P : forall x, nbh x -> Prop) :
(forall M, P _ (@NPInf R M)) -> forall (v : nbh +oo), P _ v.
Proof.
Lemma nbh_ninfW (P : forall x, nbh x -> Prop) :
(forall M, P _ (@NNInf R M)) -> forall (v : nbh -oo), P _ v.
Proof.
Arguments nbh_finW : clear implicits.
Arguments nbh_pinfW : clear implicits.
Arguments nbh_ninfW : clear implicits.
Definition eclamp {R : realType} (e : R) :=
if e <= 0 then 1 else e.
Lemma gt0_clamp {R : realType} (e : R) : 0 < eclamp e.
Lemma eclamp_id {R : realType} (e : R) : 0 < e -> eclamp e = e.
Definition B1 {R : realType} (x : R) :=
@NFin R x 1 ltr01.
Definition B {R : realType} (x e : R) :=
@NFin R x (eclamp e) (gt0_clamp e).
Lemma separable_le {R : realType} (l1 l2 : \bar R) :
(l1 < l2)%E -> exists (v1 : nbh l1) (v2 : nbh l2),
forall x y, x \in v1 -> y \in v2 -> x < y.
Proof.
case: l1 l2 => [l1||] [l2||] //= lt_l12; last first.
+ exists (NNInf 0), (NPInf 1) => x y; rewrite !inE => lt1 lt2.
by apply/(lt_trans lt1)/(lt_trans ltr01).
+ exists (NNInf (l2-1)), (B1 l2) => x y; rewrite !inE.
rewrite ltr_norml [-1 < _]ltrBrDl.
by move => lt1 /andP[lt2 _]; apply/(lt_trans lt1).
+ exists (B1 l1), (NPInf (l1+1)) => x y; rewrite !inE.
rewrite ltr_norml ltrBlDr [1+_]addrC => /andP[_].
by move=> lt1 lt2; apply/(lt_trans lt1).
pose e := l2 - l1; exists (B l1 (e/2%:R)), (B l2 (e/2%:R)).
have gt0_e: 0 < e by rewrite subr_gt0.
move=> x y; rewrite !inE/= /eclamp pmulr_rle0 // invr_le0.
rewrite lern0 /= !ltr_distl => /andP[_ lt1] /andP[lt2 _].
apply/(lt_trans lt1)/(le_lt_trans _ lt2).
by rewrite lerBrDl addrCA -splitr /e addrCA subrr addr0.
Qed.
+ exists (NNInf 0), (NPInf 1) => x y; rewrite !inE => lt1 lt2.
by apply/(lt_trans lt1)/(lt_trans ltr01).
+ exists (NNInf (l2-1)), (B1 l2) => x y; rewrite !inE.
rewrite ltr_norml [-1 < _]ltrBrDl.
by move => lt1 /andP[lt2 _]; apply/(lt_trans lt1).
+ exists (B1 l1), (NPInf (l1+1)) => x y; rewrite !inE.
rewrite ltr_norml ltrBlDr [1+_]addrC => /andP[_].
by move=> lt1 lt2; apply/(lt_trans lt1).
pose e := l2 - l1; exists (B l1 (e/2%:R)), (B l2 (e/2%:R)).
have gt0_e: 0 < e by rewrite subr_gt0.
move=> x y; rewrite !inE/= /eclamp pmulr_rle0 // invr_le0.
rewrite lern0 /= !ltr_distl => /andP[_ lt1] /andP[lt2 _].
apply/(lt_trans lt1)/(le_lt_trans _ lt2).
by rewrite lerBrDl addrCA -splitr /e addrCA subrr addr0.
Qed.
Lemma separable {R : realType} (l1 l2 : \bar R) :
l1 != l2 -> exists (v1 : nbh l1) (v2 : nbh l2),
forall x, x \notin [predI v1 & v2].
Proof.
wlog: l1 l2 / (l1 < l2)%E => [wlog ne_l12|le_l12 _].
case/boolP: (l1 < l2)%E => [/wlog/(_ ne_l12)//|].
rewrite -leNgt le_eqVlt eq_sym (negbTE ne_l12) /=.
case/wlog=> [|x [y h]]; first by rewrite eq_sym.
by exists y, x=> z; rewrite inE andbC /= (h z).
case/separable_le: le_l12 => [v1] [v2] h; exists v1, v2.
move=> x; apply/negP; rewrite inE/= => /andP[] xv1 xv2.
by have := h _ _ xv1 xv2; rewrite ltxx.
Qed.
case/boolP: (l1 < l2)%E => [/wlog/(_ ne_l12)//|].
rewrite -leNgt le_eqVlt eq_sym (negbTE ne_l12) /=.
case/wlog=> [|x [y h]]; first by rewrite eq_sym.
by exists y, x=> z; rewrite inE andbC /= (h z).
case/separable_le: le_l12 => [v1] [v2] h; exists v1, v2.
move=> x; apply/negP; rewrite inE/= => /andP[] xv1 xv2.
by have := h _ _ xv1 xv2; rewrite ltxx.
Qed.
Section SequenceLim.
Variable (R : realType).
Implicit Types (u v : nat -> R).
Definition ncvg u l :=
forall v : nbh l, exists K, forall n, (K <= n)%N -> u n \in v.
Definition iscvg (u : nat -> R) := exists l, ncvg u l%:E.
Definition nbounded u :=
exists v : nbh 0%:E, forall n, u n \in v.
Lemma nboundedP u :
reflect (exists2 M, 0 < M & forall n, `|u n| < M) `[< nbounded u >].
Proof.
Notation "c %:S" := (fun _ : nat => c) (at level 2, format "c %:S").
Section SeqLimTh.
Variable (R : realType).
Implicit Types (u v : nat -> R) (c : R) (l : \bar R).
Lemma ncvg_uniq u l1 l2 : ncvg u l1 -> ncvg u l2 -> l1 = l2.
Proof.
Lemma ncvg_eq_from K v u l :
(forall n, (K <= n)%N -> u n = v n) -> ncvg v l -> ncvg u l.
Proof.
Lemma ncvg_eq v u l : u =1 v -> ncvg v l -> ncvg u l.
Proof.
Lemma ncvg_le_from K v u (lv lu : \bar R) :
(forall n, (K <= n)%N -> u n <= v n) -> ncvg v lv -> ncvg u lu -> (lu <= lv)%E.
Proof.
Lemma ncvg_le v u (lv lu : \bar R) :
u <=1 v -> ncvg v lv -> ncvg u lu -> (lu <= lv)%E.
Proof.
Lemma ncvg_nbounded u x : ncvg u x%:E -> nbounded u.
Proof.
(* FIXME: factor out `sup` of a finite set *)
case/(_ (B x 1)) => K cu; pose S := [seq `|u n| | n <- iota 0 K].
pose M : R := sup [set x : R | x \in S]; pose e := Num.max (`|x| + 1) (M + 1).
apply/asboolP/nboundedP; exists e => [|n]; first by rewrite lt_max ltr_wpDl.
case: (ltnP n K); last first.
move/cu; rewrite inE eclamp_id ?ltr01 // => ltunBx1.
rewrite lt_max; apply/orP; left; rewrite -[u n](addrK x) addrAC.
by apply/(le_lt_trans (ler_normD _ _)); rewrite [ltLHS]addrC ltrD2l.
move=> lt_nK; have: `|u n| \in S; first by apply/map_f; rewrite mem_iota.
move=> un_S; rewrite lt_max; apply/orP; right.
case E: {+}K lt_nK => [|k] // lt_nSk; apply/ltr_pwDr; first apply/ltr01.
suff : has_sup (fun x : R => x \in S) by move/sup_upper_bound/ubP => ->.
split; first by exists `|u 0%N|; rewrite /S E inE eqxx.
elim: {+}S => [|v s [ux /ubP hux]]; first by exists 0; apply/ubP.
exists (Num.max v ux); apply/ubP=> y; rewrite inE => /orP[/eqP->|].
by rewrite le_max lexx.
by move/hux=> le_yux; rewrite le_max le_yux orbT.
Qed.
case/(_ (B x 1)) => K cu; pose S := [seq `|u n| | n <- iota 0 K].
pose M : R := sup [set x : R | x \in S]; pose e := Num.max (`|x| + 1) (M + 1).
apply/asboolP/nboundedP; exists e => [|n]; first by rewrite lt_max ltr_wpDl.
case: (ltnP n K); last first.
move/cu; rewrite inE eclamp_id ?ltr01 // => ltunBx1.
rewrite lt_max; apply/orP; left; rewrite -[u n](addrK x) addrAC.
by apply/(le_lt_trans (ler_normD _ _)); rewrite [ltLHS]addrC ltrD2l.
move=> lt_nK; have: `|u n| \in S; first by apply/map_f; rewrite mem_iota.
move=> un_S; rewrite lt_max; apply/orP; right.
case E: {+}K lt_nK => [|k] // lt_nSk; apply/ltr_pwDr; first apply/ltr01.
suff : has_sup (fun x : R => x \in S) by move/sup_upper_bound/ubP => ->.
split; first by exists `|u 0%N|; rewrite /S E inE eqxx.
elim: {+}S => [|v s [ux /ubP hux]]; first by exists 0; apply/ubP.
exists (Num.max v ux); apply/ubP=> y; rewrite inE => /orP[/eqP->|].
by rewrite le_max lexx.
by move/hux=> le_yux; rewrite le_max le_yux orbT.
Qed.
Lemma nboundedC c : nbounded c%:S.
Proof.
Lemma ncvgC c : ncvg c%:S c%:E.
Lemma ncvgD u v lu lv : ncvg u lu%:E -> ncvg v lv%:E ->
ncvg (u \+ v) (lu + lv)%:E.
Proof.
move=> cu cv; elim/nbh_finW => e /= gt0_e; pose z := e / 2%:R.
case: (cu (B lu z)) (cv (B lv z)) => [ku {}cu] [kv {}cv].
exists (maxn ku kv) => n; rewrite geq_max => /andP[leu lev].
rewrite inE opprD addrACA (le_lt_trans (ler_normD _ _)) //.
move: (cu _ leu) (cv _ lev); rewrite !inE eclamp_id.
by rewrite mulr_gt0 // invr_gt0 ltr0Sn.
move=> cu' cv'; suff ->: e = z + z by rewrite ltrD.
exact: splitr.
Qed.
case: (cu (B lu z)) (cv (B lv z)) => [ku {}cu] [kv {}cv].
exists (maxn ku kv) => n; rewrite geq_max => /andP[leu lev].
rewrite inE opprD addrACA (le_lt_trans (ler_normD _ _)) //.
move: (cu _ leu) (cv _ lev); rewrite !inE eclamp_id.
by rewrite mulr_gt0 // invr_gt0 ltr0Sn.
move=> cu' cv'; suff ->: e = z + z by rewrite ltrD.
exact: splitr.
Qed.
Lemma ncvgN u lu : ncvg u lu -> ncvg (- u) (- lu).
Proof.
case: lu => [lu||] cu /=; first last.
+ elim/nbh_pinfW=> M; case: (cu (NNInf (-M))) => K {}cu.
by exists K => n /cu; rewrite !inE ltrNr.
+ elim/nbh_ninfW=> M; case: (cu (NPInf (-M))) => K {}cu.
by exists K => n /cu; rewrite !inE ltrNl.
elim/nbh_finW => e /= gt0_e; case: (cu (B lu e)).
by move=> K {}cu; exists K=> n /cu; rewrite !inE -opprD normrN eclamp_id.
Qed.
+ elim/nbh_pinfW=> M; case: (cu (NNInf (-M))) => K {}cu.
by exists K => n /cu; rewrite !inE ltrNr.
+ elim/nbh_ninfW=> M; case: (cu (NPInf (-M))) => K {}cu.
by exists K => n /cu; rewrite !inE ltrNl.
elim/nbh_finW => e /= gt0_e; case: (cu (B lu e)).
by move=> K {}cu; exists K=> n /cu; rewrite !inE -opprD normrN eclamp_id.
Qed.
Lemma ncvgN_fin u lu : ncvg u lu%:E -> ncvg (- u) (- lu)%:E.
Proof.
Lemma ncvgB u v lu lv : ncvg u lu%:E -> ncvg v lv%:E ->
ncvg (u \- v) (lu - lv)%:E.
Lemma ncvg_abs u lu : ncvg u lu%:E -> ncvg (fun n => `|u n|) `|lu|%:E.
Proof.
move=> cu; elim/nbh_finW => e /= gt0_e; case: (cu (B lu e)).
move=> K {}cu; exists K=> n /cu; rewrite !inE eclamp_id //.
by move/(le_lt_trans (ler_dist_dist _ _)).
Qed.
move=> K {}cu; exists K=> n /cu; rewrite !inE eclamp_id //.
by move/(le_lt_trans (ler_dist_dist _ _)).
Qed.
Lemma ncvg_abs0 u : ncvg (fun n => `|u n|) 0%:E -> ncvg u 0%:E.
Proof.
Lemma ncvgMl u v : ncvg u 0%:E -> nbounded v -> ncvg (u \* v) 0%:E.
move=> cu /asboolP/nboundedP [M gt0_M ltM]; elim/nbh_finW => e /= gt0_e.
case: (cu (B 0 (e / (M + 1)))) => K {}cu; exists K => n le_Kn.
rewrite inE subr0 normrM; apply/(@lt_trans _ _ (e / (M + 1) * M)).
apply/ltr_pM => //; have /cu := le_Kn; rewrite inE subr0 eclamp_id //.
by rewrite mulr_gt0 // invr_gt0 addr_gt0.
rewrite -mulrAC -mulrA gtr_pMr // ltr_pdivrMr ?addr_gt0 //.
by rewrite mul1r ltrDl.
Lemma ncvgMr u v : ncvg v 0%:E -> nbounded u -> ncvg (u \* v) 0%:E.
Proof.
Lemma ncvgM u v lu lv : ncvg u lu%:E -> ncvg v lv%:E ->
ncvg (u \* v) (lu * lv)%:E.
Proof.
move=> cu cv; pose a := u \- lu%:S; pose b := v \- lv%:S.
have eq: (u \* v) =1 (lu * lv)%:S \+ ((lu%:S \* b) \+ (a \* v)).
move=> n; rewrite {}/a {}/b /= [u n+_]addrC [(_+_)*(v n)]mulrDl.
rewrite !addrA -[LHS]add0r; congr (_ + _); rewrite mulrDr.
by rewrite !(mulrN, mulNr) (addrCA (lu * lv)) subrr addr0 subrr.
apply/(ncvg_eq eq); rewrite -[X in X%:E]addr0; apply/ncvgD.
by apply/ncvgC. rewrite -[X in X%:E]addr0; apply/ncvgD.
+ apply/ncvgMr; first rewrite -[X in X%:E](subrr lv).
by apply/ncvgB/ncvgC. by apply/nboundedC.
+ apply/ncvgMl; first rewrite -[X in X%:E](subrr lu).
by apply/ncvgB/ncvgC. by apply/(ncvg_nbounded cv).
Qed.
have eq: (u \* v) =1 (lu * lv)%:S \+ ((lu%:S \* b) \+ (a \* v)).
move=> n; rewrite {}/a {}/b /= [u n+_]addrC [(_+_)*(v n)]mulrDl.
rewrite !addrA -[LHS]add0r; congr (_ + _); rewrite mulrDr.
by rewrite !(mulrN, mulNr) (addrCA (lu * lv)) subrr addr0 subrr.
apply/(ncvg_eq eq); rewrite -[X in X%:E]addr0; apply/ncvgD.
by apply/ncvgC. rewrite -[X in X%:E]addr0; apply/ncvgD.
+ apply/ncvgMr; first rewrite -[X in X%:E](subrr lv).
by apply/ncvgB/ncvgC. by apply/nboundedC.
+ apply/ncvgMl; first rewrite -[X in X%:E](subrr lu).
by apply/ncvgB/ncvgC. by apply/(ncvg_nbounded cv).
Qed.
Lemma ncvgZ c u lu : ncvg u lu%:E -> ncvg (c \*o u) (c * lu)%:E.
Lemma ncvg_leC c u (lu : \bar R) :
(forall n, u n <= c) -> ncvg u lu -> (lu <= c%:E)%E.
Lemma ncvg_geC c u (lu : \bar R) :
(forall n, c <= u n) -> ncvg u lu -> (c%:E <= lu)%E.
Lemma iscvgC c : iscvg c%:S.
Proof.
Hint Resolve iscvgC : core.
Lemma iscvgD (u v : nat -> R) : iscvg u -> iscvg v -> iscvg (u \+ v).
Lemma iscvg_sum {I : eqType} (u : I -> nat -> R) r :
(forall i, i \in r -> iscvg (u i)) ->
iscvg (fun n => \sum_(i <- r) u i n).
Proof.
elim: r => [|i r ih] h.
by exists 0; apply/(@ncvg_eq 0%:S)/ncvgC => n; rewrite big_nil.
case: ih => [j jr|c cv]; first by apply/h; rewrite inE jr orbT.
have [l cl]: iscvg (u i) by apply/h; rewrite inE eqxx.
exists (c + l); have := ncvgD cv cl; apply/ncvg_eq.
by move=> n; rewrite big_cons addrC.
Qed.
by exists 0; apply/(@ncvg_eq 0%:S)/ncvgC => n; rewrite big_nil.
case: ih => [j jr|c cv]; first by apply/h; rewrite inE jr orbT.
have [l cl]: iscvg (u i) by apply/h; rewrite inE eqxx.
exists (c + l); have := ncvgD cv cl; apply/ncvg_eq.
by move=> n; rewrite big_cons addrC.
Qed.
Lemma iscvg_eq (u v : nat -> R) :
u =1 v -> iscvg v -> iscvg u.
Proof.
Lemma ncvg_sub h u lu :
{homo h : x y / (x < y)%N}
-> ncvg u lu -> ncvg (fun n => u (h n)) lu.
Proof.
move=> mono_h cvu v; case: (cvu v)=> K {}cvu; exists K.
move=> n le_Kn; apply/cvu; apply/(leq_trans le_Kn).
elim: {le_Kn} n => [|n ih] //; apply/(leq_ltn_trans ih).
by rewrite mono_h.
Qed.
move=> n le_Kn; apply/cvu; apply/(leq_trans le_Kn).
elim: {le_Kn} n => [|n ih] //; apply/(leq_ltn_trans ih).
by rewrite mono_h.
Qed.
Lemma iscvg_sub σ u :
{homo σ : x y / (x < y)%N} -> iscvg u -> iscvg (u \o σ).
Proof.
Lemma ncvg_shift k (u : nat -> R) l :
ncvg u l <-> ncvg (fun n => u (n + k)%N) l.
Proof.
Lemma iscvg_shift k (u : nat -> R) :
iscvg u <-> iscvg (fun n => u (n + k)%N).
Proof.
Lemma ncvg_gt (u : nat -> R) (l1 l2 : \bar R) :
(l1 < l2)%E -> ncvg u l2 ->
exists K, forall n, (K <= n)%N -> (l1 < (u n)%:E)%E.
Proof.
case: l1 l2 => [l1||] [l2||] //=; first last.
+ by move=> _ _; exists 0%N => ? ?; exact: ltNyr.
+ by move=> _ _; exists 0%N => ? ?; exact: ltNyr.
+ by move=> _ /(_ (NPInf l1)) [K cv]; exists K => n /cv.
move=> lt_12; pose e := l2 - l1 => /(_ (B l2 e)).
case=> K cv; exists K => n /cv; rewrite !inE eclamp_id ?subr_gt0 //.
rewrite ltr_distl => /andP[] /(le_lt_trans _) h _; apply: h.
by rewrite {cv}/e opprB addrCA subrr addr0.
Qed.
+ by move=> _ _; exists 0%N => ? ?; exact: ltNyr.
+ by move=> _ _; exists 0%N => ? ?; exact: ltNyr.
+ by move=> _ /(_ (NPInf l1)) [K cv]; exists K => n /cv.
move=> lt_12; pose e := l2 - l1 => /(_ (B l2 e)).
case=> K cv; exists K => n /cv; rewrite !inE eclamp_id ?subr_gt0 //.
rewrite ltr_distl => /andP[] /(le_lt_trans _) h _; apply: h.
by rewrite {cv}/e opprB addrCA subrr addr0.
Qed.
Lemma ncvg_lt (u : nat -> R) (l1 l2 : \bar R) :
(l1 < l2)%E -> ncvg u l1 ->
exists K, forall n, (K <= n)%N -> ((u n)%:E < l2)%E.
Proof.
Lemma ncvg_homo_lt (u : nat -> R) (l1 l2 : \bar R) :
(forall m n, (m <= n)%N -> u m <= u n)
-> (l1 < l2)%E -> ncvg u l1 -> forall n, ((u n)%:E < l2)%E.
Proof.
move=> homo_u lt_12 cvu n; have [K {cvu}cv] := ncvg_lt lt_12 cvu.
case: (leqP n K) => [/homo_u|/ltnW /cv //].
by move/lee_tofin/le_lt_trans; apply; apply/cv.
Qed.
case: (leqP n K) => [/homo_u|/ltnW /cv //].
by move/lee_tofin/le_lt_trans; apply; apply/cv.
Qed.
Lemma ncvg_homo_le (u : nat -> R) (l : \bar R) :
(forall m n, (m <= n)%N -> u m <= u n)
-> ncvg u l -> forall n, ((u n)%:E <= l)%E.
Proof.
move=> homo_u cvu n; rewrite leNgt.
by apply/negP => /ncvg_homo_lt /(_ cvu) -/(_ homo_u n); rewrite ltxx.
Qed.
by apply/negP => /ncvg_homo_lt /(_ cvu) -/(_ homo_u n); rewrite ltxx.
Qed.
Section LimOp.
Context {R : realType}.
Implicit Types (u v : nat -> R).
Definition nlim u : \bar R :=
if @idP `[< exists l, `[< ncvg u l >] >] is ReflectT Px then
xchoose (asboolP _ Px) else -oo.
Lemma nlim_ncvg u : (exists l, ncvg u l) -> ncvg u (nlim u).
Proof.
Lemma nlim_out u : ~ (exists l, ncvg u l) -> nlim u = -oo%E.
Proof.
CoInductive nlim_spec (u : nat -> R) : \bar R -> Type :=
| NLimCvg l : ncvg u l -> nlim_spec u l
| NLimOut : ~ (exists l, ncvg u l) -> nlim_spec u -oo.
Lemma nlimP u : nlim_spec u (nlim u).
Proof.
Lemma nlimE (u : nat -> R) (l : \bar R) : ncvg u l -> nlim u = l.
Proof.
Lemma nlimC c : nlim c%:S = c%:E :> \bar R.
Lemma nlimD (u v : nat -> R) : iscvg u -> iscvg v ->
nlim (u \+ v) = (nlim u + nlim v)%E.
Proof.
Lemma eq_from_nlim K (v u : nat -> R) :
(forall n, (K <= n)%N -> u n = v n) -> nlim u = nlim v.
Proof.
move=> eq; have h := ncvg_eq_from eq; case: (nlimP v).
by move=> l cv; have cu := h _ cv; rewrite (nlimE cu).
move=> Ncv; rewrite nlim_out //; case=> l cu.
apply: Ncv; exists l; apply/(@ncvg_eq_from _ K u) => //.
by move=> n /eq /esym.
Qed.
by move=> l cv; have cu := h _ cv; rewrite (nlimE cu).
move=> Ncv; rewrite nlim_out //; case=> l cu.
apply: Ncv; exists l; apply/(@ncvg_eq_from _ K u) => //.
by move=> n /eq /esym.
Qed.
Lemma eq_nlim (v u : nat -> R) : u =1 v -> nlim u = nlim v.
Proof.
Lemma nlim_bump (u : nat -> R) : nlim (fun n => u n.+1) = nlim u.
Proof.
case: (nlimP u) => [l cu|Ncu].
suff: ncvg (fun n => u n.+1) l by move/nlimE.
move=> v; case/(_ v): cu => K cu; exists K => n le_Kn.
by apply/cu; apply/(leq_trans le_Kn).
rewrite nlim_out //; case=> l cu; apply/Ncu; exists l.
move=> v; case/(_ v): cu => K cu; exists K.+1 => n le_Kn.
rewrite -[n]prednK; first by apply/(leq_trans _ le_Kn).
by apply/cu; rewrite -ltnS prednK ?(leq_trans _ le_Kn).
Qed.
suff: ncvg (fun n => u n.+1) l by move/nlimE.
move=> v; case/(_ v): cu => K cu; exists K => n le_Kn.
by apply/cu; apply/(leq_trans le_Kn).
rewrite nlim_out //; case=> l cu; apply/Ncu; exists l.
move=> v; case/(_ v): cu => K cu; exists K.+1 => n le_Kn.
rewrite -[n]prednK; first by apply/(leq_trans _ le_Kn).
by apply/cu; rewrite -ltnS prednK ?(leq_trans _ le_Kn).
Qed.
Lemma nlim_lift (u : nat -> R) p : nlim (fun n => u (n + p)%N) = nlim u.
Proof.
Lemma nlim_sum {I : eqType} (u : I -> nat -> R) (r : seq I) :
(forall i, i \in r -> iscvg (u i)) ->
nlim (fun n => \sum_(i <- r) (u i) n)
= (\sum_(i <- r) nlim (u i))%E.
Proof.
elim: r => /= [|i r ih] h; first rewrite big_nil.
by rewrite (@eq_nlim 0%:S) ?nlimC //= => n; rewrite big_nil.
rewrite big_cons -ih -?nlimD.
by move=> j jr; apply/h; rewrite inE jr orbT.
by apply/h; rewrite inE eqxx.
by apply/iscvg_sum=> j jr; apply/h; rewrite inE jr orbT.
by apply/eq_nlim=> n /=; rewrite big_cons.
Qed.
by rewrite (@eq_nlim 0%:S) ?nlimC //= => n; rewrite big_nil.
rewrite big_cons -ih -?nlimD.
by move=> j jr; apply/h; rewrite inE jr orbT.
by apply/h; rewrite inE eqxx.
by apply/iscvg_sum=> j jr; apply/h; rewrite inE jr orbT.
by apply/eq_nlim=> n /=; rewrite big_cons.
Qed.
Lemma nlim_sumR {I : eqType} (u : I -> nat -> R) (r : seq I) :
(forall i, i \in r -> iscvg (u i)) ->
nlim (fun n => \sum_(i <- r) (u i) n) = (\sum_(i <- r)
(fine (nlim (u i)) : R))%:E.
Proof.
Lemma nlim_sup (u : nat -> R) l :
(forall n m, (n <= m)%N -> u n <= u m)
-> ncvg u l%:E
-> sup [set r | exists n, r = u n] = l.
Proof.
move=> mn_u cv_ul; set S := (X in sup X); suff: ncvg u (sup S)%:E.
by move/nlimE; move/nlimE: cv_ul => -> [->].
elim/nbh_finW=> /= e gt0_e; have sS: has_sup S.
split; first exists (u 0%N).
by exists 0%N.
exists l; apply/ubP => _ [n ->].
by rewrite -lee_fin; apply/ncvg_homo_le.
have /sup_adherent := sS => /(_ _ gt0_e) [r] [N ->] lt_uN.
exists N => n le_Nn; rewrite !inE distrC ger0_norm ?subr_ge0.
by move/ubP : (sup_upper_bound sS) => -> //; exists n.
by rewrite ltrBlDr -ltrBlDl (lt_le_trans lt_uN) ?mn_u.
Qed.
by move/nlimE; move/nlimE: cv_ul => -> [->].
elim/nbh_finW=> /= e gt0_e; have sS: has_sup S.
split; first exists (u 0%N).
by exists 0%N.
exists l; apply/ubP => _ [n ->].
by rewrite -lee_fin; apply/ncvg_homo_le.
have /sup_adherent := sS => /(_ _ gt0_e) [r] [N ->] lt_uN.
exists N => n le_Nn; rewrite !inE distrC ger0_norm ?subr_ge0.
by move/ubP : (sup_upper_bound sS) => -> //; exists n.
by rewrite ltrBlDr -ltrBlDl (lt_le_trans lt_uN) ?mn_u.
Qed.
End LimOp.