#[global]
Instance Op_eq_pos : BinRel (@eq positive) :=
  { TR := @eq Z ; TRInj := eq_pos_inj }.(* zify_positive_op *)

#[global]
Instance Op_Z_of_N : UnOp Z.of_N :=
  { TUOp x := x ; TUOpInj x := eq_refl (Z.of_N x) }.#[global]
Instance Op_Z_to_N : UnOp Z.to_N :=
  { TUOp x := Z.max 0 x ; TUOpInj x := ltac:(now destruct x) }.#[global]
Instance Op_Z_neg : UnOp Z.neg :=
  { TUOp := Z.opp ; TUOpInj x := eq_refl (Zneg x) }.#[global]
Instance Op_Z_pos : UnOp Z.pos :=
  { TUOp x := x ; TUOpInj x := eq_refl (Z.pos x) }.#[global]
Instance Op_pos_succ : UnOp Pos.succ :=
  { TUOp x := x + 1 ; TUOpInj := Pos2Z.inj_succ }.#[global]
Instance Op_pos_pred_double : UnOp Pos.pred_double :=
{ TUOp x := 2 * x - 1 ; TUOpInj _ := eq_refl }.#[global]
Instance Op_pos_pred : UnOp Pos.pred :=
  { TUOp x := Z.max 1 (x - 1) ;
    TUOpInj x := ltac:(rewrite <- Pos.sub_1_r; apply Pos2Z.inj_sub_max) }.#[global]
Instance Op_pos_predN : UnOp Pos.pred_N :=
  { TUOp x := x - 1 ;
    TUOpInj x := ltac: (now destruct x; rewrite N.pos_pred_spec) }.#[global]
Instance Op_pos_of_succ_nat : UnOp Pos.of_succ_nat :=
  { TUOp x := x + 1 ; TUOpInj := Zpos_P_of_succ_nat }.#[global]
Instance Op_pos_of_nat : UnOp Pos.of_nat :=
  { TUOp x := Z.max 1 x ;
    TUOpInj x := ltac: (now destruct x;
                        [|rewrite <- Pos.of_nat_succ, <- (Nat2Z.inj_max 1)]) }.#[global]
Instance Op_pos_add : BinOp Pos.add :=
  { TBOp := Z.add ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_pos_add_carry : BinOp Pos.add_carry :=
  { TBOp x y := x + y + 1 ;
    TBOpInj := ltac:(now intros; rewrite Pos.add_carry_spec, Pos2Z.inj_succ) }.#[global]
Instance Op_pos_sub : BinOp Pos.sub :=
  { TBOp n m := Z.max 1 (n - m) ; TBOpInj := Pos2Z.inj_sub_max }.#[global]
Instance Op_pos_mul : BinOp Pos.mul :=
  { TBOp := Z.mul ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_pos_min : BinOp Pos.min :=
  { TBOp := Z.min ; TBOpInj := Pos2Z.inj_min }.#[global]
Instance Op_pos_max : BinOp Pos.max :=
  { TBOp := Z.max ; TBOpInj := Pos2Z.inj_max }.#[global]
Instance Op_pos_pow : BinOp Pos.pow :=
  { TBOp := Z.pow ; TBOpInj := Pos2Z.inj_pow }.#[global]
Instance Op_pos_square : UnOp Pos.square :=
  { TUOp := Z.square ; TUOpInj := Pos2Z.inj_square }.#[global]
Instance Op_Pos_Nsucc_double : UnOp Pos.Nsucc_double :=
  { TUOp x := 2 * x + 1 ; TUOpInj x := ltac:(now destruct x) }.#[global]
Instance Op_Pos_Ndouble : UnOp Pos.Ndouble :=
  { TUOp x := 2 * x ; TUOpInj x := ltac:(now destruct x) }.#[global]
Instance Op_xO : UnOp xO :=
  { TUOp x := 2 * x ; TUOpInj _ := eq_refl }.#[global]
Instance Op_xI : UnOp xI :=
  { TUOp x := 2 * x + 1 ; TUOpInj _ := eq_refl }.#[global]
Instance Op_xH : CstOp xH :=
  { TCst := 1%Z ; TCstInj := eq_refl }.#[global]
Instance Op_Z_of_nat : UnOp Z.of_nat:=
  { TUOp x := x ; TUOpInj x := eq_refl (Z.of_nat x) }.(* zify_N_rel *)
#[global]
Instance Op_N_ge : BinRel N.ge :=
  { TR := Z.ge ; TRInj := N2Z.inj_ge }.#[global]
Instance Op_N_lt : BinRel N.lt :=
  { TR := Z.lt ; TRInj := N2Z.inj_lt }.#[global]
Instance Op_N_gt : BinRel N.gt :=
  { TR := Z.gt ; TRInj := N2Z.inj_gt }.#[global]
Instance Op_N_le : BinRel N.le :=
  { TR := Z.le ; TRInj := N2Z.inj_le }.#[global]
Instance Op_eq_N : BinRel (@eq N) :=
  { TR := @eq Z ; TRInj x y := iff_sym (N2Z.inj_iff x y) }.(* zify_N_op *)
#[global]
Instance Op_N_N0 : CstOp  N0 :=
  { TCst := Z0 ; TCstInj := eq_refl }.#[global]
Instance Op_N_Npos : UnOp  Npos :=
  { TUOp x := x ; TUOpInj _ := eq_refl }.#[global]
Instance Op_N_of_nat : UnOp  N.of_nat :=
  { TUOp x := x ; TUOpInj := nat_N_Z }.#[global]
Instance Op_Z_abs_N : UnOp Z.abs_N :=
  { TUOp := Z.abs ; TUOpInj := N2Z.inj_abs_N }.#[global]
Instance Op_N_pos : UnOp N.pos :=
  { TUOp x := x ; TUOpInj _ := eq_refl }.#[global]
Instance Op_N_add : BinOp N.add :=
  { TBOp := Z.add ; TBOpInj := N2Z.inj_add }.#[global]
Instance Op_N_min : BinOp N.min :=
  { TBOp := Z.min ; TBOpInj := N2Z.inj_min }.#[global]
Instance Op_N_max : BinOp N.max :=
  { TBOp := Z.max ; TBOpInj := N2Z.inj_max }.#[global]
Instance Op_N_mul : BinOp N.mul :=
  { TBOp := Z.mul ; TBOpInj := N2Z.inj_mul }.#[global]
Instance Op_N_sub : BinOp N.sub :=
  { TBOp x y := Z.max 0 (x - y) ; TBOpInj := N2Z.inj_sub_max }.#[global]
Instance Op_N_div : BinOp N.div :=
  { TBOp := Z.div ; TBOpInj := N2Z.inj_div }.#[global]
Instance Op_N_mod : BinOp N.modulo :=
  { TBOp := Z.rem ; TBOpInj := N2Z.inj_rem }.#[global]
Instance Op_N_pred : UnOp N.pred :=
  { TUOp x := Z.max 0 (x - 1) ;
    TUOpInj x := ltac:(rewrite N.pred_sub; apply N2Z.inj_sub_max) }.#[global]
Instance Op_N_succ : UnOp N.succ :=
  { TUOp x := x + 1 ; TUOpInj := N2Z.inj_succ }.#[global]
Instance Op_N_succ_double : UnOp N.succ_double :=
  { TUOp x := 2 * x + 1 ; TUOpInj x := ltac:(now destruct x) }.#[global]
Instance Op_N_double : UnOp N.double :=
  { TUOp x := 2 * x ; TUOpInj x := ltac:(now destruct x) }.#[global]
Instance Op_N_succ_pos : UnOp N.succ_pos :=
  { TUOp x := x + 1 ;
    TUOpInj x := ltac:(now destruct x; simpl; [| rewrite Pplus_one_succ_r]) }.#[global]
Instance Op_N_div2 : UnOp N.div2 :=
  { TUOp x := x / 2 ;
    TUOpInj x := ltac:(now rewrite N2Z.inj_div2, Z.div2_div) }.#[global]
Instance Op_N_pow : BinOp N.pow :=
  { TBOp := Z.pow ; TBOpInj := N2Z.inj_pow }.#[global]
Instance Op_N_square : UnOp N.square :=
  { TUOp x := x * x ;
    TUOpInj x := ltac:(now rewrite N.square_spec, N2Z.inj_mul) }.(** Support for Z - injected to itself *)

(* zify_Z_rel *)
#[global]
Instance Op_Z_ge : BinRel Z.ge :=
  { TR := Z.ge ; TRInj x y := iff_refl (x>= y) }.#[global]
Instance Op_Z_lt : BinRel Z.lt :=
  { TR := Z.lt ; TRInj x y := iff_refl (x < y) }.#[global]
Instance Op_Z_gt : BinRel Z.gt :=
  { TR := Z.gt ;TRInj x y := iff_refl (x > y) }.#[global]
Instance Op_Z_le : BinRel Z.le :=
  { TR := Z.le ;TRInj x y := iff_refl (x <= y) }.#[global]
Instance Op_eqZ : BinRel (@eq Z) :=
  { TR := @eq Z ; TRInj x y := iff_refl (x = y) }.#[global]
Instance Op_Z_Z0 : CstOp Z0 :=
  { TCst := Z0  ; TCstInj := eq_refl }.#[global]
Instance Op_Z_add : BinOp Z.add :=
  { TBOp := Z.add  ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_min : BinOp Z.min :=
  { TBOp := Z.min ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_max : BinOp Z.max :=
  { TBOp := Z.max ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_mul : BinOp Z.mul :=
  { TBOp := Z.mul ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_sub : BinOp Z.sub :=
  { TBOp := Z.sub ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_div : BinOp Z.div :=
  { TBOp := Z.div ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_mod : BinOp Z.modulo :=
  { TBOp := Z.modulo ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_rem : BinOp Z.rem :=
  { TBOp := Z.rem ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_quot : BinOp Z.quot :=
  { TBOp := Z.quot ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_succ : UnOp Z.succ :=
  { TUOp x := x + 1 ; TUOpInj _ := eq_refl }.#[global]
Instance Op_Z_pred : UnOp Z.pred :=
  { TUOp x := x - 1 ; TUOpInj _ := eq_refl }.#[global]
Instance Op_Z_opp : UnOp Z.opp :=
  { TUOp := Z.opp ; TUOpInj _ := eq_refl }.#[global]
Instance Op_Z_abs : UnOp Z.abs :=
  { TUOp := Z.abs ; TUOpInj _ := eq_refl }.#[global]
Instance Op_Z_sgn : UnOp Z.sgn :=
  { TUOp := Z.sgn ; TUOpInj _ := eq_refl }.#[global]
Instance Op_Z_pow : BinOp Z.pow :=
  { TBOp := Z.pow ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_pow_pos : BinOp Z.pow_pos :=
  { TBOp := Z.pow ; TBOpInj _ _ := eq_refl }.#[global]
Instance Op_Z_double : UnOp Z.double :=
  { TUOp := Z.mul 2 ; TUOpInj := Z.double_spec }.#[global]
Instance Op_Z_pred_double : UnOp Z.pred_double :=
  { TUOp x := 2 * x - 1 ; TUOpInj := Z.pred_double_spec }.#[global]
Instance Op_Z_succ_double : UnOp Z.succ_double :=
  { TUOp x := 2 * x + 1 ; TUOpInj := Z.succ_double_spec }.#[global]
Instance Op_Z_square : UnOp Z.square :=
  { TUOp x := x * x ; TUOpInj := Z.square_spec }.#[global]
Instance Op_Z_div2 : UnOp Z.div2 :=
  { TUOp x := x / 2 ; TUOpInj := Z.div2_div }.#[global]
Instance Op_Z_quot2 : UnOp Z.quot2 :=
  { TUOp x := Z.quot x 2 ; TUOpInj := Zeven.Zquot2_quot }.

Lemma of_nat_to_nat_eq x : Z.of_nat (Z.to_nat x) = Z.max 0 x.