(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)
(* définition des adresses d'états produits *)
Fixpoint iad_conv_aux_0 (p : positive) : positive :=
match p with
| xH => 2%positive
| xO p' => xO (xO (iad_conv_aux_0 p'))
| xI p' => xO (xI (iad_conv_aux_0 p'))
end.
Fixpoint iad_conv_aux_1 (p : positive) : positive :=
match p with
| xH => 1%positive
| xO p' => xO (xO (iad_conv_aux_1 p'))
| xI p' => xI (xO (iad_conv_aux_1 p'))
end.
Fixpoint iad_conv_aux_2 (p0 p1 : positive) {struct p1} : positive :=
match p0, p1 with
| xH, xH => 3%positive
| xH, xO p1' => xI (xO (iad_conv_aux_0 p1'))
| xH, xI p1' => xI (xI (iad_conv_aux_0 p1'))
| xO p0', xH => xO (xI (iad_conv_aux_1 p0'))
| xO p0', xO p1' => xO (xO (iad_conv_aux_2 p0' p1'))
| xO p0', xI p1' => xO (xI (iad_conv_aux_2 p0' p1'))
| xI p0', xH => xI (xI (iad_conv_aux_1 p0'))
| xI p0', xO p1' => xI (xO (iad_conv_aux_2 p0' p1'))
| xI p0', xI p1' => xI (xI (iad_conv_aux_2 p0' p1'))
end.
Definition iad_conv (a0 a1 : ad) : ad :=
match a0, a1 with
| N0, N0 => N0
| N0, Npos p1 => Npos (iad_conv_aux_0 p1)
| Npos p0, N0 => Npos (iad_conv_aux_1 p0)
| Npos p0, Npos p1 => Npos (iad_conv_aux_2 p0 p1)
end.

(* Specifications: *)
Lemma iad_conv_aux_0_inj :
forall p0 p1 : positive, iad_conv_aux_0 p0 = iad_conv_aux_0 p1 -> p0 = p1.
Lemma iad_conv_aux_1_inj :
forall p0 p1 : positive, iad_conv_aux_1 p0 = iad_conv_aux_1 p1 -> p0 = p1.
Lemma iad_conv_aux_0_1_img_disj :
forall p0 p1 : positive, iad_conv_aux_0 p0 <> iad_conv_aux_1 p1.
Lemma iad_conv_aux_img_disj :
forall p0 p1 p2 : positive,
iad_conv_aux_0 p0 <> iad_conv_aux_2 p1 p2 /\
iad_conv_aux_1 p0 <> iad_conv_aux_2 p1 p2.
Lemma iad_conv_aux_0_2_img_disj :
forall p0 p1 p2 : positive, iad_conv_aux_0 p0 <> iad_conv_aux_2 p1 p2.
Lemma iad_conv_aux_1_2_img_disj :
forall p0 p1 p2 : positive, iad_conv_aux_1 p0 <> iad_conv_aux_2 p1 p2.
Lemma iad_conv_aux_2_inj :
forall p0 p1 p2 p3 : positive,
iad_conv_aux_2 p0 p1 = iad_conv_aux_2 p2 p3 -> p0 = p2 /\ p1 = p3.
Lemma iad_conv_inj :
forall a0 a1 a2 a3 : ad,
iad_conv a0 a1 = iad_conv a2 a3 -> a0 = a2 /\ a1 = a3.