Module NdefOpsProp (Import N : NAxiomsRecSig').
Include NStrongRecProp N.
(** Nullity Test *)
Definition if_zero (A : Type) (a b : A) (n : N.t) : A :=
recursion a (fun _ _ => b) n.
Arguments if_zero [A] a b n.
Instance if_zero_wd (A : Type) :
Proper (Logic.eq ==> Logic.eq ==> N.eq ==> Logic.eq) (@if_zero A).
(*****************************************************)
(**                   Addition                       *)
Definition def_add (x y : N.t) := recursion y (fun _ => S) x.
Local Infix "+++" := def_add (at level 50, left associativity).
Instance def_add_wd : Proper (N.eq ==> N.eq ==> N.eq) def_add.
(*****************************************************)
(**                  Multiplication                  *)
Definition def_mul (x y : N.t) := recursion 0 (fun _ p => p +++ x) y.
Local Infix "**" := def_mul (at level 40, left associativity).
Instance def_mul_wd : Proper (N.eq ==> N.eq ==> N.eq) def_mul.
(*****************************************************)
(**                     Order                        *)
Definition ltb (m : N.t) : N.t -> bool :=
recursion
(if_zero false true)
(fun _ f n => recursion false (fun n' _ => f n') n)
m.
Local Infix "<<" := ltb (at level 70, no associativity).
Instance ltb_wd : Proper (N.eq ==> N.eq ==> Logic.eq) ltb.
(* Above, we rewrite applications of function. Is it possible to rewrite functions themselves, i.e., rewrite (recursion lt_base lt_step (S n)) to lt_step n (recursion lt_base lt_step n)? *)
(*****************************************************)
(**                     Even                         *)
Definition even (x : N.t) := recursion true (fun _ p => negb p) x.
Instance even_wd : Proper (N.eq==>Logic.eq) even.
(*****************************************************)
(**                Division by 2                     *)
Definition half_aux (x : N.t) : N.t * N.t :=
recursion (0, 0) (fun _ p => let (x1, x2) := p in (S x2, x1)) x.
Definition half (x : N.t) := snd (half_aux x).
Instance half_aux_wd : Proper (N.eq ==> N.eq*N.eq) half_aux.
Instance half_wd : Proper (N.eq==>N.eq) half.
(*****************************************************)
(**            Power                                 *)
Definition pow (n m : N.t) := recursion 1 (fun _ r => n*r) m.
Local Infix "^^" := pow (at level 30, right associativity).
Instance pow_wd : Proper (N.eq==>N.eq==>N.eq) pow.
(*****************************************************)
(**            Logarithm for the base 2              *)
Definition log (x : N.t) : N.t :=
strong_rec 0
(fun g x =>
if x << 2 then 0
else S (g (half x)))
x.
Instance log_prewd :
Proper ((N.eq==>N.eq)==>N.eq==>N.eq)
(fun g x => if x<<2 then 0 else S (g (half x))).
Instance log_wd : Proper (N.eq==>N.eq) log.

Lemma log_good_step : forall n h1 h2,
(forall m, m < n -> h1 m == h2 m) ->
(if n << 2 then 0 else S (h1 (half n))) ==
(if n << 2 then 0 else S (h2 (half n))).