(*Recursive Definition addZ : Z -> Z -> Z :=
      OZ   y => y
    | (pos O)   y => (succZ y)
    | (pos (S n1))   y => (succZ (addZ (pos n1) y))
    | (neg O)   y => (predZ y)
    | (neg (S n1))   y => (predZ (addZ (neg n1) y)).
*)

Fixpoint add1 (x2 : Z) (n : nat) {struct n} : Z :=
  match n with
  | O => succZ x2
  | S n0 => succZ (add1 x2 n0)
  end
 
 with add2 (x2 : Z) (n : nat) {struct n} : Z :=
  match n with
  | O => predZ x2
  | S n0 => predZ (add2 x2 n0)
  end.Definition addZ (x1 x2 : Z) : Z :=
  match x1 with
  | OZ => x2
  | pos n => add1 x2 n
  | neg n => add2 x2 n
  end.

(* Specifications: *)
Lemma addZ_eq1 : forall y : Z, addZ OZ y = y.
Lemma addZ_eq2 : forall y : Z, addZ (pos 0) y = succZ y.
Lemma addZ_eq3 : forall (n1 : nat) (y : Z), addZ (pos (S n1)) y = succZ (addZ (pos n1) y).
Lemma addZ_eq4 : forall y : Z, addZ (neg 0) y = predZ y.
Lemma addZ_eq5 : forall (n1 : nat) (y : Z), addZ (neg (S n1)) y = predZ (addZ (neg n1) y).
Lemma succ_addZ_l : forall x y : Z, addZ (succZ x) y = succZ (addZ x y).
Lemma pred_addZ_l : forall x y : Z, addZ (predZ x) y = predZ (addZ x y).
Lemma tech_add_pos_succZ : forall (x : nat) (y : Z), addZ (pos (S x)) y = succZ (addZ (pos x) y).
Lemma tech_add_neg_predZ : forall (x : nat) (y : Z), addZ (neg (S x)) y = predZ (addZ (neg x) y).
Lemma succ_addZ_r : forall x y : Z, addZ x (succZ y) = succZ (addZ x y).
Lemma pred_addZ_r : forall x y : Z, addZ x (predZ y) = predZ (addZ x y).
Lemma add_OZ : forall x : Z, addZ x OZ = x.
Lemma add_IZ_succZ : forall x : Z, addZ x IZ = succZ x.
Lemma add_mIZ_predZ : forall x : Z, addZ x (neg 0) = predZ x.