(** Logical predicates *)

Definition eq := @Logic.eq N.Definition eq_equiv := @eq_equivalence N.Definition lt x y := (x ?= y) = Lt.Definition gt x y := (x ?= y) = Gt.Definition le x y := (x ?= y) <> Gt.Definition ge x y := (x ?= y) <> Lt.Infix "<=" := N.le : N_scope.Infix "<" := N.lt : N_scope.Infix ">=" := N.ge : N_scope.Infix ">" := N.gt : N_scope.Notation "x <= y <= z" := (x <= y /\ y <= z) : N_scope.Notation "x <= y < z" := (x <= y /\ y < z) : N_scope.Notation "x < y < z" := (x < y /\ y < z) : N_scope.Notation "x < y <= z" := (x < y /\ y <= z) : N_scope.Definition divide p q := exists r, q = r*p.Notation "( p | q )" := (N.divide p q) (at level 0) : N_scope.Definition Even n := exists m, n = 2*m.Definition Odd n := exists m, n = 2*m+1.Program Definition succ_wd : Proper (eq==>eq) succ := _.Program Definition pred_wd : Proper (eq==>eq) pred := _.Program Definition add_wd : Proper (eq==>eq==>eq) add := _.Program Definition sub_wd : Proper (eq==>eq==>eq) sub := _.Program Definition mul_wd : Proper (eq==>eq==>eq) mul := _.Program Definition lt_wd : Proper (eq==>eq==>iff) lt := _.Program Definition div_wd : Proper (eq==>eq==>eq) div := _.Program Definition mod_wd : Proper (eq==>eq==>eq) modulo := _.Program Definition pow_wd : Proper (eq==>eq==>eq) pow := _.Program Definition testbit_wd : Proper (eq==>eq==>Logic.eq) testbit := _.(** Decidability of equality. *)

Definition eq_dec : forall n m : N, { n = m } + { n <> m }.(** Discrimination principle *)

Definition discr n : { p:positive | n = pos p } + { n = 0 }.(** Convenient induction principles *)

Definition binary_rect (P:N -> Type) (f0 : P 0)
  (f2 : forall n, P n -> P (double n))
  (fS2 : forall n, P n -> P (succ_double n)) (n : N) : P n :=
 let P' p := P (pos p) in
 let f2' p := f2 (pos p) in
 let fS2' p := fS2 (pos p) in
 match n with
 | 0 => f0
 | pos p => positive_rect P' fS2' f2' (fS2 0 f0) p
 end.Definition binary_rec (P:N -> Set) := binary_rect P.Definition binary_ind (P:N -> Prop) := binary_rect P.(** Peano induction on binary natural numbers *)

Definition peano_rect
  (P : N -> Type) (f0 : P 0)
    (f : forall n : N, P n -> P (succ n)) (n : N) : P n :=
let P' p := P (pos p) in
let f' p := f (pos p) in
match n with
| 0 => f0
| pos p => Pos.peano_rect P' (f 0 f0) f' p
end.

(* Specifications: *)
Theorem peano_rect_base P a f : peano_rect P a f 0 = a.
Theorem peano_rect_succ P a f n : peano_rect P a f (succ n) = f n (peano_rect P a f n).