(*****************************************************)
(** * Derivative's definition using Landau's kernel  *)
(*****************************************************)

Definition derivable_pt_lim f (x l:R) : Prop :=
  forall eps:R,
    0 < eps ->
    exists delta : posreal,
      (forall h:R,
        h <> 0 -> Rabs h < delta -> Rabs ((f (x + h) - f x) / h - l) < eps).Definition derivable_pt_abs f (x l:R) : Prop := derivable_pt_lim f x l.Definition derivable_pt f (x:R) := { l:R | derivable_pt_abs f x l }.Definition derivable f := forall x:R, derivable_pt f x.Definition derive_pt f (x:R) (pr:derivable_pt f x) := proj1_sig pr.Definition derive f (pr:derivable f) (x:R) := derive_pt f x (pr x).Definition antiderivative f (g:R -> R) (a b:R) : Prop :=
  (forall x:R,
    a <= x <= b ->  exists pr : derivable_pt g x, f x = derive_pt g x pr) /\
  a <= b.(**************************************)
(** * Class of differential functions *)
(**************************************)
Record Differential : Type := mkDifferential
  {d1 :> R -> R; cond_diff : derivable d1}.(**************************************)
(** * Class of differential functions *)
(**************************************)
Record Differential : Type := mkDifferential
  {d1 :> R -> R; cond_diff : derivable d1}.(**************************************)
(** * Class of differential functions *)
(**************************************)
Record Differential : Type := mkDifferential
  {d1 :> R -> R; cond_diff : derivable d1}.(**************************************)
(** * Class of differential functions *)
(**************************************)
Record Differential : Type := mkDifferential
  {d1 :> R -> R; cond_diff : derivable d1}.Record Differential_D2 : Type := mkDifferential_D2
  {d2 :> R -> R;
    cond_D1 : derivable d2;
    cond_D2 : derivable (derive d2 cond_D1)}.Record Differential_D2 : Type := mkDifferential_D2
  {d2 :> R -> R;
    cond_D1 : derivable d2;
    cond_D2 : derivable (derive d2 cond_D1)}.Record Differential_D2 : Type := mkDifferential_D2
  {d2 :> R -> R;
    cond_D1 : derivable d2;
    cond_D2 : derivable (derive d2 cond_D1)}.Record Differential_D2 : Type := mkDifferential_D2
  {d2 :> R -> R;
    cond_D1 : derivable d2;
    cond_D2 : derivable (derive d2 cond_D1)}.Record Differential_D2 : Type := mkDifferential_D2
  {d2 :> R -> R;
    cond_D1 : derivable d2;
    cond_D2 : derivable (derive d2 cond_D1)}.

(* Specifications: *)
Lemma uniqueness_step1 : forall f (x l1 l2:R), limit1_in (fun h:R => (f (x + h) - f x) / h) (fun h:R => h <> 0) l1 0 -> limit1_in (fun h:R => (f (x + h) - f x) / h) (fun h:R => h <> 0) l2 0 -> l1 = l2.
Lemma uniqueness_step2 : forall f (x l:R), derivable_pt_lim f x l -> limit1_in (fun h:R => (f (x + h) - f x) / h) (fun h:R => h <> 0) l 0.
Lemma uniqueness_step3 : forall f (x l:R), limit1_in (fun h:R => (f (x + h) - f x) / h) (fun h:R => h <> 0) l 0 -> derivable_pt_lim f x l.
Lemma uniqueness_limite : forall f (x l1 l2:R), derivable_pt_lim f x l1 -> derivable_pt_lim f x l2 -> l1 = l2.
Lemma derive_pt_eq : forall f (x l:R) (pr:derivable_pt f x), derive_pt f x pr = l <-> derivable_pt_lim f x l.
Lemma derive_pt_eq_0 : forall f (x l:R) (pr:derivable_pt f x), derivable_pt_lim f x l -> derive_pt f x pr = l.
Lemma derive_pt_eq_1 : forall f (x l:R) (pr:derivable_pt f x), derive_pt f x pr = l -> derivable_pt_lim f x l.
Lemma derive_pt_D_in : forall f (df:R -> R) (x:R) (pr:derivable_pt f x), D_in f df no_cond x <-> derive_pt f x pr = df x.
Lemma derivable_pt_lim_D_in : forall f (df:R -> R) (x:R), D_in f df no_cond x <-> derivable_pt_lim f x (df x).
Lemma derivable_pt_lim_ext : forall f g x l, (forall z, f z = g z) -> derivable_pt_lim f x l -> derivable_pt_lim g x l.
Lemma derivable_pt_lim_locally_ext : forall f g x a b l, a < x < b -> (forall z, a < z < b -> f z = g z) -> derivable_pt_lim f x l -> derivable_pt_lim g x l.
Lemma derivable_derive : forall f (x:R) (pr:derivable_pt f x), exists l : R, derive_pt f x pr = l.
Theorem derivable_continuous_pt : forall f (x:R), derivable_pt f x -> continuity_pt f x.
Theorem derivable_continuous : forall f, derivable f -> continuity f.
Lemma derivable_pt_lim_id : forall x:R, derivable_pt_lim id x 1.
Lemma derivable_pt_lim_comp : forall f1 f2 (x l1 l2:R), derivable_pt_lim f1 x l1 -> derivable_pt_lim f2 (f1 x) l2 -> derivable_pt_lim (f2 o f1) x (l2 * l1).
Lemma derivable_pt_lim_opp : forall f (x l:R), derivable_pt_lim f x l -> derivable_pt_lim (- f) x (- l).
Lemma derivable_pt_lim_opp_fwd : forall f (x l:R), derivable_pt_lim f x (- l) -> derivable_pt_lim (- f) x l.
Lemma derivable_pt_lim_opp_rev : forall f (x l:R), derivable_pt_lim (- f) x (- l) -> derivable_pt_lim f x l.
Lemma derivable_pt_lim_mirr_fwd : forall f (x l:R), derivable_pt_lim f (- x) (- l) -> derivable_pt_lim (mirr_fct f) x l.
Lemma derivable_pt_lim_mirr_rev : forall f (x l:R), derivable_pt_lim (mirr_fct f) (- x) (- l) -> derivable_pt_lim f x l.
Lemma derivable_pt_lim_plus : forall f1 f2 (x l1 l2:R), derivable_pt_lim f1 x l1 -> derivable_pt_lim f2 x l2 -> derivable_pt_lim (f1 + f2) x (l1 + l2).
Lemma derivable_pt_lim_minus : forall f1 f2 (x l1 l2:R), derivable_pt_lim f1 x l1 -> derivable_pt_lim f2 x l2 -> derivable_pt_lim (f1 - f2) x (l1 - l2).
Lemma derivable_pt_lim_mult : forall f1 f2 (x l1 l2:R), derivable_pt_lim f1 x l1 -> derivable_pt_lim f2 x l2 -> derivable_pt_lim (f1 * f2) x (l1 * f2 x + f1 x * l2).
Lemma derivable_pt_lim_const : forall a x:R, derivable_pt_lim (fct_cte a) x 0.
Lemma derivable_pt_lim_scal : forall f (a x l:R), derivable_pt_lim f x l -> derivable_pt_lim (mult_real_fct a f) x (a * l).
Lemma derivable_pt_lim_div_scal : forall f x l a, derivable_pt_lim f x l -> derivable_pt_lim (fun y => f y / a) x (l / a).
Lemma derivable_pt_lim_scal_right : forall f x l a, derivable_pt_lim f x l -> derivable_pt_lim (fun y => f y * a) x (l * a).
Lemma derivable_pt_lim_Rsqr : forall x:R, derivable_pt_lim Rsqr x (2 * x).
Lemma derivable_pt_id : forall x:R, derivable_pt id x.
Lemma derivable_pt_comp : forall f1 f2 (x:R), derivable_pt f1 x -> derivable_pt f2 (f1 x) -> derivable_pt (f2 o f1) x.
Lemma derivable_pt_xeq: forall (f : R -> R) (x1 x2 : R), x1=x2 -> derivable_pt f x1 -> derivable_pt f x2.
Lemma derivable_pt_opp : forall (f : R -> R) (x:R), derivable_pt f x -> derivable_pt (- f) x.
Lemma derivable_pt_opp_rev: forall (f : R -> R) (x : R), derivable_pt (- f) x -> derivable_pt f x.
Lemma derivable_pt_mirr: forall (f : R -> R) (x : R), derivable_pt f (-x) -> derivable_pt (mirr_fct f) x.
Lemma derivable_pt_mirr_rev: forall (f : R -> R) (x : R), derivable_pt (mirr_fct f) (- x) -> derivable_pt f x.
Lemma derivable_pt_mirr_prem: forall (f : R -> R) (x : R), derivable_pt (mirr_fct f) x -> derivable_pt f (-x).
Lemma derivable_pt_plus : forall f1 f2 (x:R), derivable_pt f1 x -> derivable_pt f2 x -> derivable_pt (f1 + f2) x.
Lemma derivable_pt_minus : forall f1 f2 (x:R), derivable_pt f1 x -> derivable_pt f2 x -> derivable_pt (f1 - f2) x.
Lemma derivable_pt_mult : forall f1 f2 (x:R), derivable_pt f1 x -> derivable_pt f2 x -> derivable_pt (f1 * f2) x.
Lemma derivable_pt_const : forall a x:R, derivable_pt (fct_cte a) x.
Lemma derivable_pt_scal : forall f (a x:R), derivable_pt f x -> derivable_pt (mult_real_fct a f) x.
Lemma derivable_pt_Rsqr : forall x:R, derivable_pt Rsqr x.
Lemma derivable_id : derivable id.
Lemma derivable_comp : forall f1 f2, derivable f1 -> derivable f2 -> derivable (f2 o f1).
Lemma derivable_opp : forall f, derivable f -> derivable (- f).
Lemma derivable_mirr : forall f, derivable f -> derivable (mirr_fct f).
Lemma derivable_plus : forall f1 f2, derivable f1 -> derivable f2 -> derivable (f1 + f2).
Lemma derivable_minus : forall f1 f2, derivable f1 -> derivable f2 -> derivable (f1 - f2).
Lemma derivable_mult : forall f1 f2, derivable f1 -> derivable f2 -> derivable (f1 * f2).
Lemma derivable_const : forall a:R, derivable (fct_cte a).
Lemma derivable_scal : forall f (a:R), derivable f -> derivable (mult_real_fct a f).
Lemma derivable_Rsqr : derivable Rsqr.
Lemma derive_pt_id : forall x:R, derive_pt id x (derivable_pt_id _) = 1.
Lemma derive_pt_comp : forall f1 f2 (x:R) (pr1:derivable_pt f1 x) (pr2:derivable_pt f2 (f1 x)), derive_pt (f2 o f1) x (derivable_pt_comp _ _ _ pr1 pr2) = derive_pt f2 (f1 x) pr2 * derive_pt f1 x pr1.
Lemma derive_pt_opp : forall f (x:R) (pr1:derivable_pt f x), derive_pt (- f) x (derivable_pt_opp _ _ pr1) = - derive_pt f x pr1.
Lemma derive_pt_opp_rev : forall f (x:R) (pr1:derivable_pt (- f) x), derive_pt (- f) x pr1 = - derive_pt f x (derivable_pt_opp_rev _ _ pr1).
Lemma derive_pt_mirr : forall f (x:R) (pr1:derivable_pt f (-x)), derive_pt (mirr_fct f) x (derivable_pt_mirr _ _ pr1) = - derive_pt f (-x) pr1.
Lemma derive_pt_mirr_rev : forall f (x:R) (pr1:derivable_pt (mirr_fct f) x), derive_pt (mirr_fct f) x pr1 = - derive_pt f (-x) (derivable_pt_mirr_prem f x pr1).
Lemma derive_pt_plus : forall f1 f2 (x:R) (pr1:derivable_pt f1 x) (pr2:derivable_pt f2 x), derive_pt (f1 + f2) x (derivable_pt_plus _ _ _ pr1 pr2) = derive_pt f1 x pr1 + derive_pt f2 x pr2.
Lemma derive_pt_minus : forall f1 f2 (x:R) (pr1:derivable_pt f1 x) (pr2:derivable_pt f2 x), derive_pt (f1 - f2) x (derivable_pt_minus _ _ _ pr1 pr2) = derive_pt f1 x pr1 - derive_pt f2 x pr2.
Lemma derive_pt_mult : forall f1 f2 (x:R) (pr1:derivable_pt f1 x) (pr2:derivable_pt f2 x), derive_pt (f1 * f2) x (derivable_pt_mult _ _ _ pr1 pr2) = derive_pt f1 x pr1 * f2 x + f1 x * derive_pt f2 x pr2.
Lemma derive_pt_const : forall a x:R, derive_pt (fct_cte a) x (derivable_pt_const a x) = 0.
Lemma derive_pt_scal : forall f (a x:R) (pr:derivable_pt f x), derive_pt (mult_real_fct a f) x (derivable_pt_scal _ _ _ pr) = a * derive_pt f x pr.
Lemma derive_pt_Rsqr : forall x:R, derive_pt Rsqr x (derivable_pt_Rsqr _) = 2 * x.