(*********************************************************************)
(*                 The Calculus of Inductive Constructions           *)
(*                                                                   *)
(*                                Projet Coq                         *)
(*                                                                   *)
(*                     INRIA        LRI-CNRS        ENS-CNRS         *)
(*              Rocquencourt         Orsay          Lyon             *)
(*                                                                   *)
(*                                 Coq V6.2                          *)
(*                               May 1st 1998                        *)
(*                                                                   *)
(*********************************************************************)
(*                               derivee.v                           *)
(*********************************************************************)

(*********************************************************)
(*           Definition of the derivative                *)
(*                                                       *)
(*********************************************************)

Require Export Rfunctions.
Require Classical_Prop.
Require Classical_Pred_Type.
Require Omega.

(*******************************)
(*      Differentiation        *)
(*******************************)
Definition R_star:=[x:R]~x==R0.

(*********)
Definition D_in:(R->R)->(R->Prop)->(R->R)->Prop:=
  [f:R->R; D:R->Prop; d:R->R](x:R)(limit1_in 
    [h:R] (Rmult (Rminus (f (Rplus x h)) (f x)) (Rinv h)) 
    R_star (d x) R0).

(*********)
Lemma Dconst:(D:R->Prop)(y:R)(D_in [x:R]y (adhDa D) [x:R]R0).
Unfold D_in;Intros;Unfold limit1_in;Unfold limit_in;Intros;Simpl;
 Split with R1;Split.
Unfold Rgt;Apply Rlt_R0_R1.
Intros;Rewrite (eq_Rminus y y (refl_eqT R y));
 Rewrite (Rmult_Ol (Rinv x0));Unfold R_dist;
 Rewrite (eq_Rminus R0 R0 (refl_eqT R R0));Unfold Rabsolu;
 Case (case_Rabsolu R0);Intro.
Absurd (Rlt R0 R0);Auto.
Red;Intro;Apply (Rlt_antirefl R0 H1).
Unfold Rgt in H0;Assumption.
Save.

(*********)
Lemma Dx:(D:R->Prop)(D_in [x:R]x (adhDa D) [x:R]R1).
Unfold D_in;Intros;Unfold limit1_in;Unfold limit_in;Intros;Simpl;
 Split with R1;Split.
Unfold Rgt;Apply Rlt_R0_R1.
Intros;Unfold Rminus;Rewrite (Rplus_sym x x0);
 Rewrite (Rplus_assoc x0 x (Ropp x));Rewrite (Rplus_Ropp_r x);
 Elim (Rplus_ne x0);Intros a b;Rewrite a;Clear a b;
 Unfold R_star in H0;Elim H0;Intros;Rewrite (Rinv_r x0 H1);
 Unfold R_dist;Rewrite (eq_Rminus R1 R1 (refl_eqT R R1));
 Unfold Rabsolu;Case (case_Rabsolu R0);Intro.
Absurd (Rlt R0 R0);Auto.
Red;Intro;Apply (Rlt_antirefl R0 H3).
Unfold Rgt in H;Assumption.
Save.

(*********)
Lemma Dadd:(D:R->Prop)(df,dg:R->R)(f,g:R->R)
  (D_in f (adhDa D) df)->(D_in g (adhDa D) dg)->
  (D_in [x:R](Rplus (f x) (g x)) (adhDa D) [x:R](Rplus (df x) (dg x))).
Unfold D_in;Intros;Generalize (H x);Generalize (H0 x);Clear H H0;Intros;
 Generalize (limit_plus 
   [h:R](Rmult (Rminus (f (Rplus x h)) (f x)) (Rinv h))
   [h:R](Rmult (Rminus (g (Rplus x h)) (g x)) (Rinv h)) R_star (df x)
   (dg x) R0 H0 H);Intro;Clear H H0;
 Unfold limit1_in in H1;Unfold limit_in in H1;Simpl in H1;
 Unfold limit1_in;Unfold limit_in;Simpl;Intros;
 Elim (H1 eps H);Clear H1;Intros;Elim H0;Clear H0;Intros;
 Split with x0;Split;Auto;Intros;Generalize (H1 x1 H2);Clear H1;Intro;
 Rewrite (Rmult_sym (Rminus (f (Rplus x x1)) (f x)) (Rinv x1)) in H1;
 Rewrite (Rmult_sym (Rminus (g (Rplus x x1)) (g x)) (Rinv x1)) in H1;
 Rewrite <-(Rmult_Rplus_distr (Rinv x1) 
                    (Rminus (f (Rplus x x1)) (f x))
                    (Rminus (g (Rplus x x1)) (g x))) in H1;
 Rewrite (Rmult_sym (Rinv x1) (Rplus (Rminus (f (Rplus x x1)) (f x))
                                 (Rminus (g (Rplus x x1)) (g x)))) in H1;
 Unfold Rminus;Rewrite (Rplus_sym (f x) (g x));
 Rewrite (Rplus_assoc (f (Rplus x x1)) (g (Rplus x x1))
  (Ropp (Rplus (g x) (f x))));
 Rewrite (Ropp_distr1 (g x) (f x));
 Rewrite <-(Rplus_assoc (g (Rplus x x1)) (Ropp (g x)) (Ropp (f x)));
 Fold (Rminus (g (Rplus x x1)) (g x));
 Rewrite (Rplus_sym (Rminus (g (Rplus x x1)) (g x)) (Ropp (f x)));
 Rewrite <-(Rplus_assoc (f (Rplus x x1)) (Ropp (f x)) 
  (Rminus (g (Rplus x x1)) (g x)));Fold (Rminus (f (Rplus x x1)) (f x));
 Assumption.
Save.

(*********)
Lemma tech_limit:(f:R->R)(D:R->Prop)(l:R)(x0:R)(D x0)->
   (limit1_in f D l x0)->l==(f x0).
Unfold limit1_in;Unfold limit_in;Simpl;Intros;Apply NNPP;Red;Intro;
 Generalize (R_dist_pos (f x0) l);Intro;Unfold Rge in H2;Elim H2;Intro;
 Clear H2.
Elim (H0 (R_dist (f x0) l) H3);Intros;Elim H2;Clear H2 H0;
 Intros;Generalize (H2 x0);Clear H2;Intro;Elim (R_dist_refl x0 x0);
 Intros a b;Clear a;Rewrite (b (refl_eqT R x0)) in H2;Clear b;
 Unfold Rgt in H0;Generalize (H2 (conj (D x0) (Rlt R0 x) H H0));Intro;
 Clear H2;Generalize (Rlt_antirefl (R_dist (f x0) l));Intro;Auto.
Elim (R_dist_refl (f x0) l);Intros a b;Clear b;Generalize (a H3);Intro;
Generalize (sym_eqT R (f x0) l H2);Intro;Auto.
Save. 

(*********)
Lemma tech_limit_contr:(f:R->R)(D:R->Prop)(l:R)(x0:R)(D x0)->~l==(f x0)
   ->~(limit1_in f D l x0).
Intros;Generalize (tech_limit f D l x0);Tauto.
Save.

(*********)
Lemma lim_x:(D:R->Prop)(x0:R)(limit1_in [x:R]x D x0 x0).
(Unfold limit1_in; Unfold limit_in; Simpl; Intros;Split with eps;
 Split; Auto;Intros;Elim H0; Intros; Auto).
Save.

(*********)
Lemma lim_fx_R0:(f:R->R)(D:R->Prop)(x:R)(df:R->R)(D_in f (adhDa D) df)->
  (limit1_in [h:R](f (Rplus x h)) R_star (f x) R0).
Unfold D_in;Intros;Generalize (H x);Clear H;Intros;
 Generalize (lim_x R_star R0);Intros;
 Generalize (limit_mul 
   [h:R](Rmult (Rminus (f (Rplus x h)) (f x)) (Rinv h))
   [x:R]x R_star (df x) R0 R0 H H0);Intro;
 Rewrite (Rmult_Or (df x)) in H1;
 Cut (limit1_in [h:R](f x) R_star (f x) R0).
Intro;Generalize (limit_plus 
   [x0:R](Rmult (Rmult (Rminus (f (Rplus x x0)) (f x)) (Rinv x0)) x0)
   [h:R](f x) R_star R0 (f x) R0 H1 H2);Intro;Clear H H0 H1 H2;
 Elim (Rplus_ne (f x));Intros a b;Rewrite b in H3;Clear a b;
 Unfold limit1_in in H3;Unfold limit_in in H3;Simpl in H3;
 Unfold limit1_in;Unfold limit_in;Simpl;Intros;Elim (H3 eps H);Clear H3;
 Intros;Elim H0;Clear H0;Intros;Split with x0;Split;Auto;Intros;
 Generalize (H1 x1 H2);Clear H1;Intro;Elim H2;Clear H2;Intros;
 Unfold R_star in H2;
 Rewrite (Rmult_assoc (Rminus (f (Rplus x x1)) (f x)) (Rinv x1) x1) 
  in H1;Rewrite (Rinv_l x1 H2) in H1;
  Elim (Rmult_ne (Rminus (f (Rplus x x1)) (f x)));Intros a b;
 Rewrite a in H1;Clear a b;Unfold Rminus in H1;
 Rewrite (Rplus_assoc (f (Rplus x x1)) (Ropp (f x)) (f x)) in H1;
 Rewrite (Rplus_Ropp_l (f x)) in H1;Clear H2 H3;
 Elim (Rplus_ne (f (Rplus x x1)));Intros a b;Rewrite a in H1;Clear a b;
 Assumption.
Unfold limit1_in;Unfold limit_in;Simpl;Intros;Split with eps;Split;Auto;
 Intros;Elim (R_dist_refl (f x) (f x));Intros a b;
 Rewrite (b (refl_eqT R (f x)));Unfold Rgt in H2;Assumption.
Save.

(*********)
Lemma Dmult:(D:R->Prop)(df,dg:R->R)(f,g:R->R)
  (D_in f (adhDa D) df)->(D_in g (adhDa D) dg)->
  (D_in [x:R](Rmult (f x) (g x)) (adhDa D) 
             [x:R](Rplus (Rmult (df x) (g x)) (Rmult (f x) (dg x)))).
Intros;Unfold D_in;Intros;Generalize (lim_fx_R0 f R_star x df H);Intro;
 Unfold D_in in H H0;Generalize (H x);Generalize (H0 x);Clear H H0;
 Intros;Generalize (limit_mul 
   [h:R](Rmult (Rminus (g (Rplus x h)) (g x)) (Rinv h))
   [h:R](f (Rplus x h)) R_star (dg x) (f x) R0 H H1);Intro;Clear H H1;
 Cut (limit1_in [h:R](g x) R_star (g x) R0). 
Intro;Generalize (limit_mul 
  [h:R](Rmult (Rminus (f (Rplus x h)) (f x)) (Rinv h))
  [_:R](g x) R_star (df x) (g x) R0 H0 H);Clear H0 H;Intro;
 Generalize (limit_plus 
  [x0:R](Rmult (Rmult (Rminus (f (Rplus x x0)) (f x)) (Rinv x0)) (g x))
  [x0:R](Rmult (Rmult (Rminus (g (Rplus x x0)) (g x)) (Rinv x0))
                (f (Rplus x x0))) R_star (Rmult (df x) (g x)) 
                                        (Rmult (dg x) (f x)) R0 H H2);
 Clear H H2;Intro;Unfold limit1_in in H;Unfold limit_in in H;
 Simpl in H;Unfold limit1_in;Unfold limit_in;Simpl;Intros;
 Elim (H eps H0);Clear H;Intros;Elim H;Clear H;Intros;
 Split with x0;Split;Auto;Intros;Generalize (H1 x1 H2);Clear H1;Intro;
 Rewrite (Rmult_sym (f x) (dg x));
 Rewrite (Rmult_sym (Rminus (f (Rplus x x1)) (f x)) (Rinv x1)) in H1;
 Rewrite (Rmult_sym (Rminus (g (Rplus x x1)) (g x)) (Rinv x1)) in H1;
 Rewrite (Rmult_assoc (Rinv x1) (Rminus (f (Rplus x x1)) (f x)) 
                        (g x)) in H1;
 Rewrite (Rmult_assoc (Rinv x1) (Rminus (g (Rplus x x1)) (g x))
                        (f (Rplus x x1))) in H1;
 Rewrite <-(Rmult_Rplus_distr (Rinv x1) 
    (Rmult (Rminus (f (Rplus x x1)) (f x)) (g x))
    (Rmult (Rminus (g (Rplus x x1)) (g x)) (f (Rplus x x1)))) in H1;
 Rewrite (Rmult_sym (Rinv x1) 
    (Rplus (Rmult (Rminus (f (Rplus x x1)) (f x)) (g x))
        (Rmult (Rminus (g (Rplus x x1)) (g x)) (f (Rplus x x1))))) in H1;
 Unfold Rminus in H1;
 Rewrite (Rmult_sym (Rplus (f (Rplus x x1)) (Ropp (f x))) (g x)) 
  in H1;
 Rewrite (Rmult_sym (Rplus (g (Rplus x x1)) (Ropp (g x)))
  (f (Rplus x x1))) in H1;
 Rewrite (Rmult_Rplus_distr (g x) (f (Rplus x x1)) (Ropp (f x))) in H1;
 Rewrite (Rmult_Rplus_distr (f (Rplus x x1)) (g (Rplus x x1)) (Ropp (g x))) 
  in H1;Rewrite (Rmult_sym (g x) (Ropp (f x))) in H1;
 Rewrite (Rmult_sym (f (Rplus x x1)) (Ropp (g x))) in H1;
 Rewrite (Ropp_mul1 (f x) (g x))in H1;
 Rewrite (Ropp_mul1 (g x) (f (Rplus x x1))) in H1;
 Rewrite (Rplus_assoc (Rmult (g x) (f (Rplus x x1))) 
                     (Ropp (Rmult (f x) (g x)))
  (Rplus (Rmult (f (Rplus x x1)) (g (Rplus x x1))) 
           (Ropp (Rmult (g x) (f (Rplus x x1)))))) in H1;
 Rewrite (Rplus_sym (Rmult (g x) (f (Rplus x x1))) 
   (Rplus (Ropp (Rmult (f x) (g x)))
                 (Rplus (Rmult (f (Rplus x x1)) (g (Rplus x x1)))
                   (Ropp (Rmult (g x) (f (Rplus x x1))))))) in H1;
 Rewrite <-(Rplus_assoc (Ropp (Rmult (f x) (g x))) 
   (Rmult (f (Rplus x x1)) (g (Rplus x x1))) 
   (Ropp (Rmult (g x) (f (Rplus x x1))))) in H1; 
 Rewrite (Rplus_assoc (Rplus (Ropp (Rmult (f x) (g x)))
                   (Rmult (f (Rplus x x1)) (g (Rplus x x1)))) 
                     (Ropp (Rmult (g x) (f (Rplus x x1))))
                     (Rmult (g x) (f (Rplus x x1)))) in H1;
 Rewrite (Rplus_Ropp_l (Rmult (g x) (f (Rplus x x1)))) in H1;
 Rewrite (Rplus_sym (Ropp (Rmult (f x) (g x))) 
     (Rmult (f (Rplus x x1)) (g (Rplus x x1)))) in H1;
 Fold (Rminus (Rmult (f (Rplus x x1)) (g (Rplus x x1))) 
     (Rmult (f x) (g x))) in H1;Elim (Rplus_ne 
  (Rminus (Rmult (f (Rplus x x1)) (g (Rplus x x1))) (Rmult (f x) (g x))));
 Intros a b;Rewrite a in H1;Clear a b;Assumption.
Clear H0 H2;Unfold limit1_in;Unfold limit_in;Simpl;Intros;
 Split with eps;Split;Auto;Intros;Elim (R_dist_refl (g x) (g x));
 Intros a b;Rewrite (b (refl_eqT R (g x)));Unfold Rgt in H;Assumption.
Save.

(*********)
Lemma Dmult_const:(D:R->Prop)(f,df:R->R)(a:R)(D_in f (adhDa D) df)->
  (D_in [x:R](Rmult a (f x)) (adhDa D) ([x:R](Rmult a (df x)))).
Intros;Generalize (Dmult D [_:R]R0 df [_:R]a f (Dconst D a) H);
 Unfold D_in;Intros;Generalize (H0 x);Clear H0;Intro;
 Rewrite (Rmult_Ol (f x)) in H0;
 Rewrite (let (H1,H2)=(Rplus_ne (Rmult a (df x))) in H2) in H0;
 Assumption.
Save.

(*********)
Lemma Dopp:(D:R->Prop)(f,df:R->R)(D_in f (adhDa D) df)->
  (D_in [x:R](Ropp (f x)) (adhDa D) ([x:R](Ropp (df x)))).
Intros;Generalize (Dmult_const D  f df (Ropp R1) H); Unfold D_in;
 Intros;Generalize (H0 x);Clear H0;Unfold limit1_in;Unfold limit_in;
 Intros;Generalize (H0 eps H1);Clear H0;Intro;Elim H0;Clear H0;Intros; 
 Elim H0;Clear H0;Simpl;Intros;Split with x0;Split;Auto.
Intros;Generalize (H2 x1 H3);Clear H2;Intro;Rewrite Ropp_mul1 in H2;
 Rewrite Ropp_mul1 in H2;Rewrite Ropp_mul1 in H2;
 Rewrite (let (H1,H2)=(Rmult_ne (f (Rplus x x1))) in H2) in H2; 
 Rewrite (let (H1,H2)=(Rmult_ne (f x)) in H2) in H2;
 Rewrite (let (H1,H2)=(Rmult_ne (df x)) in H2) in H2;Assumption.
Save.

(*********)
Lemma Dx_pow_n:(n:nat)(D:R->Prop)
  (D_in [x:R](pow x n) (adhDa D) 
        [x:R](Rmult (INR n) (pow x (minus n (1))))).
Induction n;Intros.
Simpl; Rewrite Rmult_Ol; Apply Dconst.
Intros;Cut n0=(minus (S n0) (1));
  [ Intro a; Rewrite <- a;Clear a | Simpl; Apply minus_n_O ].
Generalize (Dmult D [_:R]R1 
   [x:R](Rmult (INR n0) (pow x (minus n0 (1)))) [x:R]x [x:R](pow x n0) 
   (Dx D) (H D));Unfold D_in;Unfold limit1_in;Unfold limit_in;Intros;
 Elim (H0 x eps H1);Clear H0;Intros;Elim H0;Clear H0;Intros;
 Split with x0;Split;Auto.
Intros;Generalize (H2 x1 H3);Clear H2 H3;Intro;
 Rewrite (let (H1,H2)=(Rmult_ne (pow x n0)) in H2) in H2;
 Rewrite (tech_pow_Rmult (Rplus x x1) n0) in H2;
 Rewrite (tech_pow_Rmult x n0) in H2;
 Rewrite (Rmult_sym (INR n0) (pow x (minus n0 (1)))) in H2;
 Rewrite <-(Rmult_assoc x (pow x (minus n0 (1))) (INR n0)) in H2;
 Rewrite (tech_pow_Rmult x (minus n0 (1))) in H2;
 Elim (classic (n0=O));Intro cond.
Rewrite cond in H2;Rewrite cond;Simpl in H2;Simpl;
 Cut (Rplus R1 (Rmult (Rmult x R1) R0))==(Rmult R1 R1);
 [Intro A; Rewrite A in H2; Assumption|Ring].
Cut ~(n0=O)->(S (minus n0 (1)))=n0;[Intro|Omega];
 Rewrite (H3 cond) in H2; Rewrite (Rmult_sym (pow x n0) (INR n0)) in H2;
 Rewrite (tech_pow_Rplus x n0 n0) in H2; Assumption.
Save.

(* $Id: Rderiv.v,v 1.2 1999/07/19 13:31:36 mayero Exp $ *)