--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/ascii_base.ma".
+include "common/comp.ma".
+include "num/bool_lemmas.ma".
+
+(* ************************** *)
+(* DEFINIZIONE ASCII MINIMALE *)
+(* ************************** *)
+
+ndefinition ascii_destruct_aux ≝
+Πc1,c2.ΠP:Prop.c1 = c2 →
+ match eq_ascii c1 c2 with [ true ⇒ P → P | false ⇒ P ].
+
+nlemma ascii_destruct : ascii_destruct_aux.
+ #c1; #c2; #P; #H;
+ nrewrite < H;
+ nelim c1;
+ nnormalize;
+ napply (λx.x).
+nqed.
+
+nlemma eq_to_eqascii : ∀n1,n2.n1 = n2 → eq_ascii n1 n2 = true.
+ #n1; #n2; #H;
+ nrewrite > H;
+ nelim n2;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma neqascii_to_neq : ∀n1,n2.eq_ascii n1 n2 = false → n1 ≠ n2.
+ #n1; #n2; #H;
+ napply (not_to_not (n1 = n2) (eq_ascii n1 n2 = true) …);
+ ##[ ##1: napply (eq_to_eqascii n1 n2)
+ ##| ##2: napply (eqfalse_to_neqtrue … H)
+ ##]
+nqed.
+
+(* !!! per brevita... *)
+naxiom eqascii_to_eq : ∀c1,c2.eq_ascii c1 c2 = true → c1 = c2.
+
+nlemma neq_to_neqascii : ∀n1,n2.n1 ≠ n2 → eq_ascii n1 n2 = false.
+ #n1; #n2; #H;
+ napply (neqtrue_to_eqfalse (eq_ascii n1 n2));
+ napply (not_to_not (eq_ascii n1 n2 = true) (n1 = n2) ? H);
+ napply (eqascii_to_eq n1 n2).
+nqed.
+
+nlemma decidable_ascii : ∀x,y:ascii.decidable (x = y).
+ #x; #y; nnormalize;
+ napply (or2_elim (eq_ascii x y = true) (eq_ascii x y = false) ? (decidable_bexpr ?));
+ ##[ ##1: #H; napply (or2_intro1 (x = y) (x ≠ y) (eqascii_to_eq … H))
+ ##| ##2: #H; napply (or2_intro2 (x = y) (x ≠ y) (neqascii_to_neq … H))
+ ##]
+nqed.
+
+nlemma symmetric_eqascii : symmetricT ascii bool eq_ascii.
+ #n1; #n2;
+ napply (or2_elim (n1 = n2) (n1 ≠ n2) ? (decidable_ascii n1 n2));
+ ##[ ##1: #H; nrewrite > H; napply refl_eq
+ ##| ##2: #H; nrewrite > (neq_to_neqascii n1 n2 H);
+ napply (symmetric_eq ? (eq_ascii n2 n1) false);
+ napply (neq_to_neqascii n2 n1 (symmetric_neq ? n1 n2 H))
+ ##]
+nqed.
+
+nlemma ascii_is_comparable : comparable.
+ @ ascii
+ ##[ napply ch_0
+ ##| napply forall_ascii
+ ##| napply eq_ascii
+ ##| napply eqascii_to_eq
+ ##| napply eq_to_eqascii
+ ##| napply neqascii_to_neq
+ ##| napply neq_to_neqascii
+ ##| napply decidable_ascii
+ ##| napply symmetric_eqascii
+ ##]
+nqed.
+
+unification hint 0 ≔ ⊢ carr ascii_is_comparable ≡ ascii.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/bool.ma".
+
+(* ************************** *)
+(* DEFINIZIONE ASCII MINIMALE *)
+(* ************************** *)
+
+ninductive ascii : Type ≝
+(* numeri *)
+ ch_0: ascii
+| ch_1: ascii
+| ch_2: ascii
+| ch_3: ascii
+| ch_4: ascii
+| ch_5: ascii
+| ch_6: ascii
+| ch_7: ascii
+| ch_8: ascii
+| ch_9: ascii
+
+(* simboli *)
+| ch__: ascii
+
+(* maiuscole *)
+| ch_A: ascii
+| ch_B: ascii
+| ch_C: ascii
+| ch_D: ascii
+| ch_E: ascii
+| ch_F: ascii
+| ch_G: ascii
+| ch_H: ascii
+| ch_I: ascii
+| ch_J: ascii
+| ch_K: ascii
+| ch_L: ascii
+| ch_M: ascii
+| ch_N: ascii
+| ch_O: ascii
+| ch_P: ascii
+| ch_Q: ascii
+| ch_R: ascii
+| ch_S: ascii
+| ch_T: ascii
+| ch_U: ascii
+| ch_V: ascii
+| ch_W: ascii
+| ch_X: ascii
+| ch_Y: ascii
+| ch_Z: ascii
+
+(* minuscole *)
+| ch_a: ascii
+| ch_b: ascii
+| ch_c: ascii
+| ch_d: ascii
+| ch_e: ascii
+| ch_f: ascii
+| ch_g: ascii
+| ch_h: ascii
+| ch_i: ascii
+| ch_j: ascii
+| ch_k: ascii
+| ch_l: ascii
+| ch_m: ascii
+| ch_n: ascii
+| ch_o: ascii
+| ch_p: ascii
+| ch_q: ascii
+| ch_r: ascii
+| ch_s: ascii
+| ch_t: ascii
+| ch_u: ascii
+| ch_v: ascii
+| ch_w: ascii
+| ch_x: ascii
+| ch_y: ascii
+| ch_z: ascii.
+
+(* iteratore sugli ascii *)
+ndefinition forall_ascii ≝ λP.
+ P ch_0 ⊗ P ch_1 ⊗ P ch_2 ⊗ P ch_3 ⊗ P ch_4 ⊗ P ch_5 ⊗ P ch_6 ⊗ P ch_7 ⊗
+ P ch_8 ⊗ P ch_9 ⊗ P ch__ ⊗ P ch_A ⊗ P ch_B ⊗ P ch_C ⊗ P ch_D ⊗ P ch_E ⊗
+ P ch_F ⊗ P ch_G ⊗ P ch_H ⊗ P ch_I ⊗ P ch_J ⊗ P ch_K ⊗ P ch_L ⊗ P ch_M ⊗
+ P ch_N ⊗ P ch_O ⊗ P ch_P ⊗ P ch_Q ⊗ P ch_R ⊗ P ch_S ⊗ P ch_T ⊗ P ch_U ⊗
+ P ch_V ⊗ P ch_W ⊗ P ch_X ⊗ P ch_Y ⊗ P ch_Z ⊗ P ch_a ⊗ P ch_b ⊗ P ch_c ⊗
+ P ch_d ⊗ P ch_e ⊗ P ch_f ⊗ P ch_g ⊗ P ch_h ⊗ P ch_i ⊗ P ch_j ⊗ P ch_k ⊗
+ P ch_l ⊗ P ch_m ⊗ P ch_n ⊗ P ch_o ⊗ P ch_p ⊗ P ch_q ⊗ P ch_r ⊗ P ch_s ⊗
+ P ch_t ⊗ P ch_u ⊗ P ch_v ⊗ P ch_w ⊗ P ch_x ⊗ P ch_y ⊗ P ch_z.
+
+(* confronto fra ascii *)
+ndefinition eq_ascii ≝
+λc,c':ascii.match c with
+ [ ch_0 ⇒ match c' with [ ch_0 ⇒ true | _ ⇒ false ] | ch_1 ⇒ match c' with [ ch_1 ⇒ true | _ ⇒ false ]
+ | ch_2 ⇒ match c' with [ ch_2 ⇒ true | _ ⇒ false ] | ch_3 ⇒ match c' with [ ch_3 ⇒ true | _ ⇒ false ]
+ | ch_4 ⇒ match c' with [ ch_4 ⇒ true | _ ⇒ false ] | ch_5 ⇒ match c' with [ ch_5 ⇒ true | _ ⇒ false ]
+ | ch_6 ⇒ match c' with [ ch_6 ⇒ true | _ ⇒ false ] | ch_7 ⇒ match c' with [ ch_7 ⇒ true | _ ⇒ false ]
+ | ch_8 ⇒ match c' with [ ch_8 ⇒ true | _ ⇒ false ] | ch_9 ⇒ match c' with [ ch_9 ⇒ true | _ ⇒ false ]
+ | ch__ ⇒ match c' with [ ch__ ⇒ true | _ ⇒ false ] | ch_A ⇒ match c' with [ ch_A ⇒ true | _ ⇒ false ]
+ | ch_B ⇒ match c' with [ ch_B ⇒ true | _ ⇒ false ] | ch_C ⇒ match c' with [ ch_C ⇒ true | _ ⇒ false ]
+ | ch_D ⇒ match c' with [ ch_D ⇒ true | _ ⇒ false ] | ch_E ⇒ match c' with [ ch_E ⇒ true | _ ⇒ false ]
+ | ch_F ⇒ match c' with [ ch_F ⇒ true | _ ⇒ false ] | ch_G ⇒ match c' with [ ch_G ⇒ true | _ ⇒ false ]
+ | ch_H ⇒ match c' with [ ch_H ⇒ true | _ ⇒ false ] | ch_I ⇒ match c' with [ ch_I ⇒ true | _ ⇒ false ]
+ | ch_J ⇒ match c' with [ ch_J ⇒ true | _ ⇒ false ] | ch_K ⇒ match c' with [ ch_K ⇒ true | _ ⇒ false ]
+ | ch_L ⇒ match c' with [ ch_L ⇒ true | _ ⇒ false ] | ch_M ⇒ match c' with [ ch_M ⇒ true | _ ⇒ false ]
+ | ch_N ⇒ match c' with [ ch_N ⇒ true | _ ⇒ false ] | ch_O ⇒ match c' with [ ch_O ⇒ true | _ ⇒ false ]
+ | ch_P ⇒ match c' with [ ch_P ⇒ true | _ ⇒ false ] | ch_Q ⇒ match c' with [ ch_Q ⇒ true | _ ⇒ false ]
+ | ch_R ⇒ match c' with [ ch_R ⇒ true | _ ⇒ false ] | ch_S ⇒ match c' with [ ch_S ⇒ true | _ ⇒ false ]
+ | ch_T ⇒ match c' with [ ch_T ⇒ true | _ ⇒ false ] | ch_U ⇒ match c' with [ ch_U ⇒ true | _ ⇒ false ]
+ | ch_V ⇒ match c' with [ ch_V ⇒ true | _ ⇒ false ] | ch_W ⇒ match c' with [ ch_W ⇒ true | _ ⇒ false ]
+ | ch_X ⇒ match c' with [ ch_X ⇒ true | _ ⇒ false ] | ch_Y ⇒ match c' with [ ch_Y ⇒ true | _ ⇒ false ]
+ | ch_Z ⇒ match c' with [ ch_Z ⇒ true | _ ⇒ false ] | ch_a ⇒ match c' with [ ch_a ⇒ true | _ ⇒ false ]
+ | ch_b ⇒ match c' with [ ch_b ⇒ true | _ ⇒ false ] | ch_c ⇒ match c' with [ ch_c ⇒ true | _ ⇒ false ]
+ | ch_d ⇒ match c' with [ ch_d ⇒ true | _ ⇒ false ] | ch_e ⇒ match c' with [ ch_e ⇒ true | _ ⇒ false ]
+ | ch_f ⇒ match c' with [ ch_f ⇒ true | _ ⇒ false ] | ch_g ⇒ match c' with [ ch_g ⇒ true | _ ⇒ false ]
+ | ch_h ⇒ match c' with [ ch_h ⇒ true | _ ⇒ false ] | ch_i ⇒ match c' with [ ch_i ⇒ true | _ ⇒ false ]
+ | ch_j ⇒ match c' with [ ch_j ⇒ true | _ ⇒ false ] | ch_k ⇒ match c' with [ ch_k ⇒ true | _ ⇒ false ]
+ | ch_l ⇒ match c' with [ ch_l ⇒ true | _ ⇒ false ] | ch_m ⇒ match c' with [ ch_m ⇒ true | _ ⇒ false ]
+ | ch_n ⇒ match c' with [ ch_n ⇒ true | _ ⇒ false ] | ch_o ⇒ match c' with [ ch_o ⇒ true | _ ⇒ false ]
+ | ch_p ⇒ match c' with [ ch_p ⇒ true | _ ⇒ false ] | ch_q ⇒ match c' with [ ch_q ⇒ true | _ ⇒ false ]
+ | ch_r ⇒ match c' with [ ch_r ⇒ true | _ ⇒ false ] | ch_s ⇒ match c' with [ ch_s ⇒ true | _ ⇒ false ]
+ | ch_t ⇒ match c' with [ ch_t ⇒ true | _ ⇒ false ] | ch_u ⇒ match c' with [ ch_u ⇒ true | _ ⇒ false ]
+ | ch_v ⇒ match c' with [ ch_v ⇒ true | _ ⇒ false ] | ch_w ⇒ match c' with [ ch_w ⇒ true | _ ⇒ false ]
+ | ch_x ⇒ match c' with [ ch_x ⇒ true | _ ⇒ false ] | ch_y ⇒ match c' with [ ch_y ⇒ true | _ ⇒ false ]
+ | ch_z ⇒ match c' with [ ch_z ⇒ true | _ ⇒ false ]
+ ].
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/hints_declaration.ma".
+include "num/bool.ma".
+
+alias symbol "hint_decl" (instance 1) = "hint_decl_Type1".
+
+nrecord comparable : Type[1] ≝
+ {
+ carr :> Type[0];
+ zeroc : carr;
+ forallc : (carr → bool) → bool;
+ eqc : carr → carr → bool;
+ eqc_to_eq : ∀x,y.(eqc x y = true) → (x = y);
+ eq_to_eqc : ∀x,y.(x = y) → (eqc x y = true);
+ neqc_to_neq : ∀x,y.(eqc x y = false) → (x ≠ y);
+ neq_to_neqc : ∀x,y.(x ≠ y) → (eqc x y = false);
+ decidable_c : ∀x,y:carr.decidable (x = y);
+ symmetric_eqc : symmetricT carr bool eqc
+ }.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/pts.ma".
+
+(*
+
+Notation for hint declaration
+==============================
+
+The idea is to write a context, with abstraction first, then
+recursive calls (let-in) and finally the two equivalent terms.
+The context can be empty. Note the ; to begin the second part of
+the context (necessary even if the first part is empty).
+
+ unification hint PREC \coloneq
+ ID : TY, ..., ID : TY
+ ; ID \equest T, ..., ID \equest T
+ \vdash T1 \equiv T2
+
+With unidoce and some ASCII art it looks like the following:
+
+ unification hint PREC ≔ ID : TY, ..., ID : TY;
+ ID ≟ T, ..., ID ≟ T
+ (*---------------------*) ⊢
+ T1 ≡ T2
+
+*)
+
+(* it seems unbelivable, but it works! *)
+notation > "≔ (list0 ( (list1 (ident x) sep , ) opt (: T) ) sep ,) opt (; (list1 (ident U ≟ term 90 V ) sep ,)) ⊢ term 19 Px ≡ term 19 Py"
+ with precedence 90
+ for @{ ${ fold right
+ @{ ${ default
+ @{ ${ fold right
+ @{ 'hint_decl $Px $Py }
+ rec acc1 @{ let ( ${ident U} : ?) ≝ $V in $acc1} } }
+ @{ 'hint_decl $Px $Py }
+ }
+ }
+ rec acc @{
+ ${ fold right @{ $acc } rec acc2
+ @{ ∀${ident x}:${ default @{ $T } @{ ? } }.$acc2 } }
+ }
+ }}.
+
+ndefinition hint_declaration_Type0 ≝ λA:Type[0].λa,b:A.Prop.
+ndefinition hint_declaration_Type1 ≝ λA:Type[1].λa,b:A.Prop.
+ndefinition hint_declaration_Type2 ≝ λa,b:Type[2].Prop.
+ndefinition hint_declaration_CProp0 ≝ λA:CProp[0].λa,b:A.Prop.
+ndefinition hint_declaration_CProp1 ≝ λA:CProp[1].λa,b:A.Prop.
+ndefinition hint_declaration_CProp2 ≝ λa,b:CProp[2].Prop.
+
+interpretation "hint_decl_Type2" 'hint_decl a b = (hint_declaration_Type2 a b).
+interpretation "hint_decl_CProp2" 'hint_decl a b = (hint_declaration_CProp2 a b).
+interpretation "hint_decl_Type1" 'hint_decl a b = (hint_declaration_Type1 ? a b).
+interpretation "hint_decl_CProp1" 'hint_decl a b = (hint_declaration_CProp1 ? a b).
+interpretation "hint_decl_CProp0" 'hint_decl a b = (hint_declaration_CProp0 ? a b).
+interpretation "hint_decl_Type0" 'hint_decl a b = (hint_declaration_Type0 ? a b).
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| A.Asperti, C.Sacerdoti Coen, *)
+(* ||A|| E.Tassi, S.Zacchiroli *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU Lesser General Public License Version 2.1 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/comp.ma".
+include "common/option.ma".
+include "common/nat.ma".
+
+(* *************** *)
+(* LISTE GENERICHE *)
+(* *************** *)
+
+ninductive list (A:Type) : Type ≝
+ nil: list A
+| cons: A → list A → list A.
+
+nlet rec append A (l1: list A) l2 on l1 ≝
+ match l1 with
+ [ nil ⇒ l2
+ | (cons hd tl) ⇒ cons A hd (append A tl l2) ].
+
+notation "hvbox(hd break :: tl)"
+ right associative with precedence 47
+ for @{'cons $hd $tl}.
+
+notation "[ list0 x sep ; ]"
+ non associative with precedence 90
+ for ${fold right @'nil rec acc @{'cons $x $acc}}.
+
+notation "hvbox(l1 break @ l2)"
+ right associative with precedence 47
+ for @{'append $l1 $l2 }.
+
+interpretation "nil" 'nil = (nil ?).
+interpretation "cons" 'cons hd tl = (cons ? hd tl).
+interpretation "append" 'append l1 l2 = (append ? l1 l2).
+
+nlemma list_destruct_1 : ∀T.∀x1,x2:T.∀y1,y2:list T.cons T x1 y1 = cons T x2 y2 → x1 = x2.
+ #T; #x1; #x2; #y1; #y2; #H;
+ nchange with (match cons T x2 y2 with [ nil ⇒ False | cons a _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma list_destruct_2 : ∀T.∀x1,x2:T.∀y1,y2:list T.cons T x1 y1 = cons T x2 y2 → y1 = y2.
+ #T; #x1; #x2; #y1; #y2; #H;
+ nchange with (match cons T x2 y2 with [ nil ⇒ False | cons _ b ⇒ y1 = b ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma list_destruct_cons_nil : ∀T.∀x:T.∀y:list T.cons T x y = nil T → False.
+ #T; #x; #y; #H;
+ nchange with (match cons T x y with [ nil ⇒ True | cons a b ⇒ False ]);
+ nrewrite > H;
+ nnormalize;
+ napply I.
+nqed.
+
+nlemma list_destruct_nil_cons : ∀T.∀x:T.∀y:list T.nil T = cons T x y → False.
+ #T; #x; #y; #H;
+ nchange with (match cons T x y with [ nil ⇒ True | cons a b ⇒ False ]);
+ nrewrite < H;
+ nnormalize;
+ napply I.
+nqed.
+
+nlemma append_nil : ∀T:Type.∀l:list T.(l@[]) = l.
+ #T; #l;
+ nelim l;
+ nnormalize;
+ ##[ ##1: napply refl_eq
+ ##| ##2: #x; #y; #H;
+ nrewrite > H;
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma associative_list : ∀T.associative (list T) (append T).
+ #T; #x; #y; #z;
+ nelim x;
+ nnormalize;
+ ##[ ##1: napply refl_eq
+ ##| ##2: #a; #b; #H;
+ nrewrite > H;
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma cons_append_commute : ∀T:Type.∀l1,l2:list T.∀a:T.a :: (l1 @ l2) = (a :: l1) @ l2.
+ #T; #l1; #l2; #a;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma append_cons_commute : ∀T:Type.∀a:T.∀l,l1:list T.l @ (a::l1) = (l@[a]) @ l1.
+ #T; #a; #l; #l1;
+ nrewrite > (associative_list T l [a] l1);
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+(* listlen *)
+nlet rec len_list (T:Type) (l:list T) on l ≝
+ match l with [ nil ⇒ O | cons _ t ⇒ S (len_list T t) ].
+
+(* vuota? *)
+ndefinition is_empty_list ≝
+λT:Type.λl:list T.match l with [ nil ⇒ True | cons _ _ ⇒ False ].
+
+ndefinition isb_empty_list ≝
+λT:Type.λl:list T.match l with [ nil ⇒ true | cons _ _ ⇒ false ].
+
+ndefinition isnot_empty_list ≝
+λT:Type.λl:list T.match l with [ nil ⇒ False | cons _ _ ⇒ True ].
+
+ndefinition isnotb_empty_list ≝
+λT:Type.λl:list T.match l with [ nil ⇒ false | cons _ _ ⇒ true ].
+
+(* reverse *)
+nlet rec reverse_list (T:Type) (l:list T) on l ≝
+ match l with
+ [ nil ⇒ nil T
+ | cons h t ⇒ (reverse_list T t)@[h]
+ ].
+
+(* getFirst *)
+ndefinition get_first_list ≝
+λT:Type.λl:list T.match l with
+ [ nil ⇒ None ?
+ | cons h _ ⇒ Some ? h ].
+
+(* getLast *)
+ndefinition get_last_list ≝
+λT:Type.λl:list T.match reverse_list T l with
+ [ nil ⇒ None ?
+ | cons h _ ⇒ Some ? h ].
+
+(* cutFirst *)
+ndefinition cut_first_list ≝
+λT:Type.λl:list T.match l with
+ [ nil ⇒ nil T
+ | cons _ t ⇒ t ].
+
+(* cutLast *)
+ndefinition cut_last_list ≝
+λT:Type.λl:list T.match reverse_list T l with
+ [ nil ⇒ nil T
+ | cons _ t ⇒ reverse_list T t ].
+
+(* apply f *)
+nlet rec apply_f_list (T1,T2:Type) (l:list T1) (f:T1 → T2) on l ≝
+match l with
+ [ nil ⇒ nil T2
+ | cons h t ⇒ cons T2 (f h) (apply_f_list T1 T2 t f) ].
+
+(* fold right *)
+nlet rec fold_right_list (T1,T2:Type) (f:T1 → T2 → T2) (acc:T2) (l:list T1) on l ≝
+ match l with
+ [ nil ⇒ acc
+ | cons h t ⇒ f h (fold_right_list T1 T2 f acc t)
+ ].
+
+(* double fold right *)
+nlemma fold_right_list2_aux1 :
+∀T.∀h,t.len_list T [] = len_list T (h::t) → False.
+ #T; #h; #t;
+ nnormalize;
+ #H;
+ ndestruct (*napply (nat_destruct_0_S ? H)*).
+nqed.
+
+nlemma fold_right_list2_aux2 :
+∀T.∀h,t.len_list T (h::t) = len_list T [] → False.
+ #T; #h; #t;
+ nnormalize;
+ #H;
+ ndestruct (*napply (nat_destruct_S_0 ? H)*).
+nqed.
+
+nlemma fold_right_list2_aux3 :
+∀T.∀h,h',t,t'.len_list T (h::t) = len_list T (h'::t') → len_list T t = len_list T t'.
+ #T; #h; #h'; #t; #t';
+ nelim t;
+ nelim t';
+ ##[ ##1: nnormalize; #H; napply refl_eq
+ ##| ##2: #a; #l'; #H; #H1;
+ nchange in H1:(%) with ((S O) = (S (S (len_list T l'))));
+ ndestruct (*nelim (nat_destruct_0_S ? (nat_destruct_S_S … H1))*)
+ ##| ##3: #a; #l'; #H; #H1;
+ nchange in H1:(%) with ((S (S (len_list T l'))) = (S O));
+ ndestruct (*nelim (nat_destruct_S_0 ? (nat_destruct_S_S … H1))*)
+ ##| ##4: #a; #l; #H; #a1; #l1; #H1; #H2;
+ nchange in H2:(%) with ((S (S (len_list T l1))) = (S (S (len_list T l))));
+ nchange with ((S (len_list T l1)) = (S (len_list T l)));
+ nrewrite > (nat_destruct_S_S … H2);
+ napply refl_eq
+ ##]
+nqed.
+
+nlet rec fold_right_list2 (T1,T2:Type) (f:T1 → T1 → T2 → T2) (acc:T2) (l1:list T1) on l1 ≝
+ match l1
+ return λl1.Πl2.len_list T1 l1 = len_list T1 l2 → T2
+ with
+ [ nil ⇒ λl2.match l2 return λl2.len_list T1 [] = len_list T1 l2 → T2 with
+ [ nil ⇒ λp:len_list T1 [] = len_list T1 [].acc
+ | cons h t ⇒ λp:len_list T1 [] = len_list T1 (h::t).
+ False_rect_Type0 ? (fold_right_list2_aux1 T1 h t p)
+ ]
+ | cons h t ⇒ λl2.match l2 return λl2.len_list T1 (h::t) = len_list T1 l2 → T2 with
+ [ nil ⇒ λp:len_list T1 (h::t) = len_list T1 [].
+ False_rect_Type0 ? (fold_right_list2_aux2 T1 h t p)
+ | cons h' t' ⇒ λp:len_list T1 (h::t) = len_list T1 (h'::t').
+ f h h' (fold_right_list2 T1 T2 f acc t t' (fold_right_list2_aux3 T1 h h' t t' p))
+ ]
+ ].
+
+nlet rec bfold_right_list2 (T1:Type) (f:T1 → T1 → bool) (l1,l2:list T1) on l1 ≝
+ match l1 with
+ [ nil ⇒ match l2 with
+ [ nil ⇒ true | cons h t ⇒ false ]
+ | cons h t ⇒ match l2 with
+ [ nil ⇒ false | cons h' t' ⇒ (f h h') ⊗ (bfold_right_list2 T1 f t t')
+ ]
+ ].
+
+(* nth elem *)
+nlet rec nth_list (T:Type) (l:list T) (n:nat) on l ≝
+ match l with
+ [ nil ⇒ None ?
+ | cons h t ⇒ match n with
+ [ O ⇒ Some ? h | S n' ⇒ nth_list T t n' ]
+ ].
+
+(* abs elem *)
+ndefinition abs_list_aux1 : ∀T:Type.∀n.((len_list T []) > n) = true → False.
+ #T; nnormalize; #n; #H; ndestruct (*napply (bool_destruct … H)*). nqed.
+
+ndefinition abs_list_aux2 : ∀T:Type.∀h:T.∀t:list T.∀n.((len_list T (h::t)) > (S n) = true) → ((len_list T t) > n) = true.
+ #T; #h; #t; #n; nnormalize; #H; napply H. nqed.
+
+nlet rec abs_list (T:Type) (l:list T) on l ≝
+ match l
+ return λl.Πn.(((len_list T l) > n) = true) → T
+ with
+ [ nil ⇒ λn.λp:(((len_list T []) > n) = true).False_rect_Type0 ? (abs_list_aux1 T n p)
+ | cons h t ⇒ λn.
+ match n with
+ [ O ⇒ λp:(((len_list T (h::t)) > O) = true).h
+ | S n' ⇒ λp:(((len_list T (h::t)) > (S n')) = true).
+ abs_list T t n' (abs_list_aux2 T h t n' p)
+ ]
+ ].
+
+(* esempio: abs_list ? [ 1; 2; 3 ; 4 ] 0 (refl_eq …) = 1. *)
+
+nlemma symmetric_lenlist : ∀T.∀l1,l2:list T.len_list T l1 = len_list T l2 → len_list T l2 = len_list T l1.
+ #T; #l1;
+ nelim l1;
+ ##[ ##1: #l2; ncases l2; nnormalize;
+ ##[ ##1: #H; napply refl_eq
+ ##| ##2: #h; #t; #H; ndestruct (*nelim (nat_destruct_0_S ? H)*)
+ ##]
+ ##| ##2: #h; #l2; ncases l2; nnormalize;
+ ##[ ##1: #H; #l; #H1; nrewrite < H1; napply refl_eq
+ ##| ##2: #h; #l; #H; #l3; #H1; nrewrite < H1; napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma symmetric_foldrightlist2_aux :
+∀T1,T2:Type.∀f:T1 → T1 → T2 → T2.
+ (∀x,y,z.f x y z = f y x z) →
+ (∀acc:T2.∀l1,l2:list T1.
+ ∀H1:(len_list T1 l1 = len_list T1 l2).
+ ∀H2:(len_list T1 l2 = len_list T1 l1).
+ (fold_right_list2 T1 T2 f acc l1 l2 H1 = fold_right_list2 T1 T2 f acc l2 l1 H2)).
+ #T1; #T2; #f; #H; #acc; #l1;
+ nelim l1;
+ ##[ ##1: #l2; ncases l2;
+ ##[ ##1: nnormalize; #H1; #H2; napply refl_eq
+ ##| ##2: #h; #l; #H1; #H2;
+ nchange in H1:(%) with (O = (S (len_list ? l)));
+ ndestruct (*nelim (nat_destruct_0_S ? H1)*)
+ ##]
+ ##| ##2: #h3; #l3; #H1; #l2; ncases l2;
+ ##[ ##1: #H2; #H3; nchange in H2:(%) with ((S (len_list ? l3)) = O);
+ ndestruct (*nelim (nat_destruct_S_0 ? H1)*)
+ ##| ##2: #h4; #l4; #H2; #H3;
+ nchange in H2:(%) with ((S (len_list ? l3)) = (S (len_list ? l4)));
+ nchange in H3:(%) with ((S (len_list ? l4)) = (S (len_list ? l3)));
+ nchange with ((f h3 h4 (fold_right_list2 T1 T2 f acc l3 l4 (fold_right_list2_aux3 T1 h3 h4 l3 l4 ?))) =
+ (f h4 h3 (fold_right_list2 T1 T2 f acc l4 l3 (fold_right_list2_aux3 T1 h4 h3 l4 l3 ?))));
+ nrewrite < (H1 l4 (fold_right_list2_aux3 T1 h3 h4 l3 l4 H2) (fold_right_list2_aux3 T1 h4 h3 l4 l3 H3));
+ nrewrite > (H h3 h4 (fold_right_list2 T1 T2 f acc l3 l4 ?));
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma symmetric_foldrightlist2 :
+∀T1,T2:Type.∀f:T1 → T1 → T2 → T2.
+ (∀x,y,z.f x y z = f y x z) →
+ (∀acc:T2.∀l1,l2:list T1.∀H:len_list T1 l1 = len_list T1 l2.
+ fold_right_list2 T1 T2 f acc l1 l2 H = fold_right_list2 T1 T2 f acc l2 l1 (symmetric_lenlist T1 l1 l2 H)).
+ #T1; #T2; #f; #H; #acc; #l1; #l2; #H1;
+ nrewrite > (symmetric_foldrightlist2_aux T1 T2 f H acc l1 l2 H1 (symmetric_lenlist T1 l1 l2 H1));
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_bfoldrightlist2 :
+∀T1:Type.∀f:T1 → T1 → bool.
+ (∀x,y.f x y = f y x) →
+ (∀l1,l2:list T1.
+ bfold_right_list2 T1 f l1 l2 = bfold_right_list2 T1 f l2 l1).
+ #T; #f; #H; #l1;
+ nelim l1;
+ ##[ ##1: #l2; ncases l2;
+ ##[ ##1: nnormalize; napply refl_eq
+ ##| ##2: #hh2; #ll2; nnormalize; napply refl_eq
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: nnormalize; napply refl_eq
+ ##| ##2: #hh2; #ll2; nnormalize;
+ nrewrite > (H1 ll2);
+ nrewrite > (H hh1 hh2);
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma bfoldrightlist2_to_eq :
+∀T1:Type.∀f:T1 → T1 → bool.
+ (∀x,y.(f x y = true → x = y)) →
+ (∀l1,l2:list T1.
+ (bfold_right_list2 T1 f l1 l2 = true → l1 = l2)).
+ #T; #f; #H; #l1;
+ nelim l1;
+ ##[ ##1: #l2; ncases l2;
+ ##[ ##1: #H1; napply refl_eq
+ ##| ##2: #hh2; #ll2; nnormalize; #H1;
+ ndestruct (*napply (bool_destruct … H1)*)
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: nnormalize; #H2;
+ ndestruct (*napply (bool_destruct … H2)*)
+ ##| ##2: #hh2; #ll2; #H2;
+ nchange in H2:(%) with (((f hh1 hh2)⊗(bfold_right_list2 T f ll1 ll2)) = true);
+ nrewrite > (H hh1 hh2 (andb_true_true_l … H2));
+ nrewrite > (H1 ll2 (andb_true_true_r … H2));
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma eq_to_bfoldrightlist2 :
+∀T1:Type.∀f:T1 → T1 → bool.
+ (∀x,y.(x = y → f x y = true)) →
+ (∀l1,l2:list T1.
+ (l1 = l2 → bfold_right_list2 T1 f l1 l2 = true)).
+ #T; #f; #H; #l1;
+ nelim l1;
+ ##[ ##1: #l2; ncases l2;
+ ##[ ##1: #H1; nnormalize; napply refl_eq
+ ##| ##2: #hh2; #ll2; #H1;
+ (* !!! ndestruct: assert false *)
+ nelim (list_destruct_nil_cons ??? H1)
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: #H2;
+ (* !!! ndestruct: assert false *)
+ nelim (list_destruct_cons_nil ??? H2)
+ ##| ##2: #hh2; #ll2; #H2; nnormalize;
+ nrewrite > (list_destruct_1 … H2);
+ nrewrite > (H hh2 hh2 (refl_eq …));
+ nnormalize;
+ nrewrite > (H1 ll2 (list_destruct_2 … H2));
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma bfoldrightlist2_to_lenlist :
+∀T.∀f:T → T → bool.
+ (∀l1,l2:list T.bfold_right_list2 T f l1 l2 = true → len_list T l1 = len_list T l2).
+ #T; #f; #l1;
+ nelim l1;
+ ##[ ##1: #l2; ncases l2;
+ ##[ ##1: nnormalize; #H; napply refl_eq
+ ##| ##2: nnormalize; #hh; #tt; #H;
+ ndestruct (*napply (bool_destruct … H)*)
+ ##]
+ ##| ##2: #hh; #tt; #H; #l2; ncases l2;
+ ##[ ##1: nnormalize; #H1;
+ ndestruct (*napply (bool_destruct … H1)*)
+ ##| ##2: #hh1; #tt1; #H1; nnormalize;
+ nrewrite > (H tt1 ?);
+ ##[ ##1: napply refl_eq
+ ##| ##2: nchange in H1:(%) with ((? ⊗ (bfold_right_list2 T f tt tt1)) = true);
+ napply (andb_true_true_r … H1)
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma decidable_list :
+∀T.(∀x,y:T.decidable (x = y)) →
+ (∀x,y:list T.decidable (x = y)).
+ #T; #H; #x; nelim x;
+ ##[ ##1: #y; ncases y;
+ ##[ ##1: nnormalize; napply (or2_intro1 (? = ?) (? ≠ ?) (refl_eq …))
+ ##| ##2: #hh2; #tt2; nnormalize; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H1;
+ (* !!! ndestruct: assert false *)
+ napply (list_destruct_nil_cons T … H1)
+ ##]
+ ##| ##2: #hh1; #tt1; #H1; #y; ncases y;
+ ##[ ##1: nnormalize; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (list_destruct_cons_nil T … H2)
+ ##| ##2: #hh2; #tt2; nnormalize; napply (or2_elim (hh1 = hh2) (hh1 ≠ hh2) ? (H …));
+ ##[ ##2: #H2; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H3; napply (H2 (list_destruct_1 T … H3))
+ ##| ##1: #H2; napply (or2_elim (tt1 = tt2) (tt1 ≠ tt2) ? (H1 tt2));
+ ##[ ##2: #H3; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H4; napply (H3 (list_destruct_2 T … H4))
+ ##| ##1: #H3; napply (or2_intro1 (? = ?) (? ≠ ?) ?);
+ nrewrite > H2; nrewrite > H3; napply refl_eq
+ ##]
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma nbfoldrightlist2_to_neq :
+∀T1:Type.∀f:T1 → T1 → bool.
+ (∀x,y.(f x y = false → x ≠ y)) →
+ (∀l1,l2:list T1.
+ (bfold_right_list2 T1 f l1 l2 = false → l1 ≠ l2)).
+ #T; #f; #H; #l1;
+ nelim l1;
+ ##[ ##1: #l2; ncases l2;
+ ##[ ##1: nnormalize; #H1;
+ ndestruct (*napply (bool_destruct … H1)*)
+ ##| ##2: #hh2; #ll2; #H1; nnormalize; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (list_destruct_nil_cons T … H2)
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: #H2; nnormalize; #H3;
+ (* !!! ndestruct: assert false *)
+ napply (list_destruct_cons_nil T … H3)
+ ##| ##2: #hh2; #ll2; #H2; nnormalize; #H3;
+ nchange in H2:(%) with (((f hh1 hh2)⊗(bfold_right_list2 T f ll1 ll2)) = false);
+ napply (H1 ll2 ? (list_destruct_2 T … H3));
+ napply (or2_elim ??? (andb_false2 … H2) );
+ ##[ ##1: #H4; napply (absurd (hh1 = hh2) …);
+ ##[ ##1: nrewrite > (list_destruct_1 T … H3); napply refl_eq
+ ##| ##2: napply (H … H4)
+ ##]
+ ##| ##2: #H4; napply H4
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma list_destruct :
+∀T.(∀x,y:T.decidable (x = y)) →
+ (∀h1,h2:T.∀l1,l2:list T.
+ (h1::l1) ≠ (h2::l2) → h1 ≠ h2 ∨ l1 ≠ l2).
+ #T; #H; #h1; #h2; #l1; nelim l1;
+ ##[ ##1: #l2; ncases l2;
+ ##[ ##1: #H1; napply (or2_intro1 (h1 ≠ h2) ([] ≠ []) …);
+ nnormalize; #H2; nrewrite > H2 in H1:(%);
+ nnormalize; #H1; napply (H1 (refl_eq …))
+ ##| ##2: #hh2; #ll2; #H1; napply (or2_intro2 (h1 ≠ h2) ([] ≠ (hh2::ll2)) …);
+ nnormalize; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (list_destruct_nil_cons T … H2)
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: #H2; napply (or2_intro2 (h1 ≠ h2) ((hh1::ll1) ≠ []) …);
+ nnormalize; #H3;
+ (* !!! ndestruct: assert false *)
+ napply (list_destruct_cons_nil T … H3)
+ ##| ##2: #hh2; #ll2; #H2;
+ napply (or2_elim (h1 = h2) (h1 ≠ h2) ? (H h1 h2) …);
+ ##[ ##2: #H3; napply (or2_intro1 (h1 ≠ h2) ((hh1::ll1) ≠ (hh2::ll2)) H3)
+ ##| ##1: #H3; napply (or2_intro2 (h1 ≠ h2) ((hh1::ll1) ≠ (hh2::ll2) …));
+ nrewrite > H3 in H2:(%); #H2;
+ nnormalize; #H4; nrewrite > (list_destruct_1 T … H4) in H2:(%); #H2;
+ nrewrite > (list_destruct_2 T … H4) in H2:(%); #H2;
+ napply (H2 (refl_eq …))
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_nbfoldrightlist2 :
+∀T:Type.∀f:T → T → bool.
+ (∀x,y:T.decidable (x = y)) →
+ (∀x,y.(x ≠ y → f x y = false)) →
+ (∀l1,l2:list T.
+ (l1 ≠ l2 → bfold_right_list2 T f l1 l2 = false)).
+ #T; #f; #H; #H1; #l1;
+ nelim l1;
+ ##[ ##1: #l2; ncases l2;
+ ##[ ##1: nnormalize; #H2; nelim (H2 (refl_eq …))
+ ##| ##2: #hh2; #ll2; nnormalize; #H2; napply refl_eq
+ ##]
+ ##| ##2: #hh1; #ll1; #H2; #l2; ncases l2;
+ ##[ ##1: nnormalize; #H3; napply refl_eq
+ ##| ##2: #hh2; #ll2; #H3;
+ nchange with (((f hh1 hh2)⊗(bfold_right_list2 T f ll1 ll2)) = false);
+ napply (or2_elim (hh1 ≠ hh2) (ll1 ≠ ll2) ? (list_destruct T H … H3) …);
+ ##[ ##1: #H4; nrewrite > (H1 hh1 hh2 H4); nnormalize; napply refl_eq
+ ##| ##2: #H4; nrewrite > (H2 ll2 H4);
+ nrewrite > (symmetric_andbool (f hh1 hh2) false);
+ nnormalize; napply refl_eq
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma isbemptylist_to_isemptylist : ∀T,l.isb_empty_list T l = true → is_empty_list T l.
+ #T; #l;
+ ncases l;
+ nnormalize;
+ ##[ ##1: #H; napply I
+ ##| ##2: #x; #l; #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma isnotbemptylist_to_isnotemptylist : ∀T,l.isnotb_empty_list T l = true → isnot_empty_list T l.
+ #T; #l;
+ ncases l;
+ nnormalize;
+ ##[ ##1: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##| ##2: #x; #l; #H; napply I
+ ##]
+nqed.
+
+nlemma list_is_comparable : comparable → comparable.
+ #T; napply (mk_comparable (list T));
+ ##[ napply (nil ?)
+ ##| napply (λx.false)
+ ##| napply (bfold_right_list2 T (eqc T))
+ ##| napply (bfoldrightlist2_to_eq … (eqc T));
+ napply (eqc_to_eq T)
+ ##| napply (eq_to_bfoldrightlist2 … (eqc T));
+ napply (eq_to_eqc T)
+ ##| napply (nbfoldrightlist2_to_neq … (eqc T));
+ napply (neqc_to_neq T)
+ ##| napply (neq_to_nbfoldrightlist2 … (eqc T));
+ ##[ napply (decidable_c T)
+ ##| napply (neq_to_neqc T)
+ ##]
+ ##| napply decidable_list;
+ napply (decidable_c T)
+ ##| napply symmetric_bfoldrightlist2;
+ napply (symmetric_eqc T)
+ ##]
+nqed.
+
+unification hint 0 ≔ S: comparable;
+ T ≟ (carr S),
+ X ≟ (list_is_comparable S)
+ (*********************************************) ⊢
+ carr X ≡ list T.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/comp.ma".
+include "num/bool_lemmas.ma".
+
+(* ******** *)
+(* NATURALI *)
+(* ******** *)
+
+ninductive nat : Type ≝
+ O : nat
+| S : nat → nat.
+
+(*
+interpretation "Natural numbers" 'N = nat.
+
+default "natural numbers" cic:/matita/common/nat/nat.ind.
+
+alias num (instance 0) = "natural number".
+*)
+
+nlet rec nat_it (T:Type) (f:T → T) (arg:T) (n:nat) on n ≝
+ match n with
+ [ O ⇒ arg
+ | S n' ⇒ nat_it T f (f arg) n'
+ ].
+
+ndefinition nat1 ≝ S O.
+ndefinition nat2 ≝ S nat1.
+ndefinition nat3 ≝ S nat2.
+ndefinition nat4 ≝ S nat3.
+ndefinition nat5 ≝ S nat4.
+ndefinition nat6 ≝ S nat5.
+ndefinition nat7 ≝ S nat6.
+ndefinition nat8 ≝ S nat7.
+ndefinition nat9 ≝ S nat8.
+ndefinition nat10 ≝ S nat9.
+ndefinition nat11 ≝ S nat10.
+ndefinition nat12 ≝ S nat11.
+ndefinition nat13 ≝ S nat12.
+ndefinition nat14 ≝ S nat13.
+ndefinition nat15 ≝ S nat14.
+ndefinition nat16 ≝ S nat15.
+ndefinition nat17 ≝ S nat16.
+ndefinition nat18 ≝ S nat17.
+ndefinition nat19 ≝ S nat18.
+ndefinition nat20 ≝ S nat19.
+ndefinition nat21 ≝ S nat20.
+ndefinition nat22 ≝ S nat21.
+ndefinition nat23 ≝ S nat22.
+ndefinition nat24 ≝ S nat23.
+ndefinition nat25 ≝ S nat24.
+ndefinition nat26 ≝ S nat25.
+ndefinition nat27 ≝ S nat26.
+ndefinition nat28 ≝ S nat27.
+ndefinition nat29 ≝ S nat28.
+ndefinition nat30 ≝ S nat29.
+ndefinition nat31 ≝ S nat30.
+ndefinition nat32 ≝ S nat31.
+ndefinition nat33 ≝ S nat32.
+ndefinition nat34 ≝ S nat33.
+ndefinition nat35 ≝ S nat34.
+ndefinition nat36 ≝ S nat35.
+ndefinition nat37 ≝ S nat36.
+ndefinition nat38 ≝ S nat37.
+ndefinition nat39 ≝ S nat38.
+ndefinition nat40 ≝ S nat39.
+ndefinition nat41 ≝ S nat40.
+ndefinition nat42 ≝ S nat41.
+ndefinition nat43 ≝ S nat42.
+ndefinition nat44 ≝ S nat43.
+ndefinition nat45 ≝ S nat44.
+ndefinition nat46 ≝ S nat45.
+ndefinition nat47 ≝ S nat46.
+ndefinition nat48 ≝ S nat47.
+ndefinition nat49 ≝ S nat48.
+ndefinition nat50 ≝ S nat49.
+ndefinition nat51 ≝ S nat50.
+ndefinition nat52 ≝ S nat51.
+ndefinition nat53 ≝ S nat52.
+ndefinition nat54 ≝ S nat53.
+ndefinition nat55 ≝ S nat54.
+ndefinition nat56 ≝ S nat55.
+ndefinition nat57 ≝ S nat56.
+ndefinition nat58 ≝ S nat57.
+ndefinition nat59 ≝ S nat58.
+ndefinition nat60 ≝ S nat59.
+ndefinition nat61 ≝ S nat60.
+ndefinition nat62 ≝ S nat61.
+ndefinition nat63 ≝ S nat62.
+ndefinition nat64 ≝ S nat63.
+ndefinition nat65 ≝ S nat64.
+ndefinition nat66 ≝ S nat65.
+ndefinition nat67 ≝ S nat66.
+ndefinition nat68 ≝ S nat67.
+ndefinition nat69 ≝ S nat68.
+ndefinition nat70 ≝ S nat69.
+ndefinition nat71 ≝ S nat70.
+ndefinition nat72 ≝ S nat71.
+ndefinition nat73 ≝ S nat72.
+ndefinition nat74 ≝ S nat73.
+ndefinition nat75 ≝ S nat74.
+ndefinition nat76 ≝ S nat75.
+ndefinition nat77 ≝ S nat76.
+ndefinition nat78 ≝ S nat77.
+ndefinition nat79 ≝ S nat78.
+ndefinition nat80 ≝ S nat79.
+ndefinition nat81 ≝ S nat80.
+ndefinition nat82 ≝ S nat81.
+ndefinition nat83 ≝ S nat82.
+ndefinition nat84 ≝ S nat83.
+ndefinition nat85 ≝ S nat84.
+ndefinition nat86 ≝ S nat85.
+ndefinition nat87 ≝ S nat86.
+ndefinition nat88 ≝ S nat87.
+ndefinition nat89 ≝ S nat88.
+ndefinition nat90 ≝ S nat89.
+ndefinition nat91 ≝ S nat90.
+ndefinition nat92 ≝ S nat91.
+ndefinition nat93 ≝ S nat92.
+ndefinition nat94 ≝ S nat93.
+ndefinition nat95 ≝ S nat94.
+ndefinition nat96 ≝ S nat95.
+ndefinition nat97 ≝ S nat96.
+ndefinition nat98 ≝ S nat97.
+ndefinition nat99 ≝ S nat98.
+ndefinition nat100 ≝ S nat99.
+
+nlet rec eq_nat (n1,n2:nat) on n1 ≝
+ match n1 with
+ [ O ⇒ match n2 with [ O ⇒ true | S _ ⇒ false ]
+ | S n1' ⇒ match n2 with [ O ⇒ false | S n2' ⇒ eq_nat n1' n2' ]
+ ].
+
+nlet rec le_nat n m ≝
+ match n with
+ [ O ⇒ true
+ | (S p) ⇒ match m with
+ [ O ⇒ false | (S q) ⇒ le_nat p q ]
+ ].
+
+interpretation "natural 'less or equal to'" 'leq x y = (le_nat x y).
+
+ndefinition lt_nat ≝ λn1,n2:nat.(le_nat n1 n2) ⊗ (⊖ (eq_nat n1 n2)).
+
+interpretation "natural 'less than'" 'lt x y = (lt_nat x y).
+
+ndefinition ge_nat ≝ λn1,n2:nat.(⊖ (le_nat n1 n2)) ⊕ (eq_nat n1 n2).
+
+interpretation "natural 'greater or equal to'" 'geq x y = (ge_nat x y).
+
+ndefinition gt_nat ≝ λn1,n2:nat.⊖ (le_nat n1 n2).
+
+interpretation "natural 'greater than'" 'gt x y = (gt_nat x y).
+
+nlet rec plus (n1,n2:nat) on n1 ≝
+ match n1 with
+ [ O ⇒ n2
+ | (S n1') ⇒ S (plus n1' n2) ].
+
+interpretation "natural plus" 'plus x y = (plus x y).
+
+nlet rec times (n1,n2:nat) on n1 ≝
+ match n1 with
+ [ O ⇒ O
+ | (S n1') ⇒ n2 + (times n1' n2) ].
+
+interpretation "natural times" 'times x y = (times x y).
+
+nlet rec minus n m ≝
+ match n with
+ [ O ⇒ O
+ | (S p) ⇒
+ match m with
+ [O ⇒ (S p)
+ | (S q) ⇒ minus p q ]].
+
+interpretation "natural minus" 'minus x y = (minus x y).
+
+nlet rec div_aux p m n : nat ≝
+match (le_nat m n) with
+[ true ⇒ O
+| false ⇒
+ match p with
+ [ O ⇒ O
+ | (S q) ⇒ S (div_aux q (m-(S n)) n)]].
+
+ndefinition div : nat → nat → nat ≝
+λn,m.match m with
+ [ O ⇒ S n
+ | (S p) ⇒ div_aux n n p].
+
+interpretation "natural divide" 'divide x y = (div x y).
+
+ndefinition pred ≝ λn.match n with [ O ⇒ O | S n ⇒ n ].
+
+ndefinition nat128 ≝ nat64 + nat64.
+ndefinition nat256 ≝ nat128 + nat128.
+ndefinition nat512 ≝ nat256 + nat256.
+ndefinition nat1024 ≝ nat512 + nat512.
+ndefinition nat2048 ≝ nat1024 + nat1024.
+ndefinition nat4096 ≝ nat2048 + nat2048.
+ndefinition nat8192 ≝ nat4096 + nat4096.
+ndefinition nat16384 ≝ nat8192 + nat8192.
+ndefinition nat32768 ≝ nat16384 + nat16384.
+ndefinition nat65536 ≝ nat32768 + nat32768.
+
+nlemma nat_destruct_S_S : ∀n1,n2:nat.S n1 = S n2 → n1 = n2.
+ #n1; #n2; #H;
+ nchange with (match S n2 with [ O ⇒ False | S a ⇒ n1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma nat_destruct_0_S : ∀n:nat.O = S n → False.
+ #n; #H;
+ nchange with (match S n with [ O ⇒ True | S a ⇒ False ]);
+ nrewrite < H;
+ nnormalize;
+ napply I.
+nqed.
+
+nlemma nat_destruct_S_0 : ∀n:nat.S n = O → False.
+ #n; #H;
+ nchange with (match S n with [ O ⇒ True | S a ⇒ False ]);
+ nrewrite > H;
+ nnormalize;
+ napply I.
+nqed.
+
+nlemma eq_to_eqnat : ∀n1,n2:nat.n1 = n2 → eq_nat n1 n2 = true.
+ #n1;
+ nelim n1;
+ ##[ ##1: #n2;
+ nelim n2;
+ nnormalize;
+ ##[ ##1: #H; napply refl_eq
+ ##| ##2: #n3; #H; #H1; ndestruct (*nelim (nat_destruct_0_S ? H1)*)
+ ##]
+ ##| ##2: #n2; #H; #n3; #H1;
+ ncases n3 in H1:(%) ⊢ %;
+ nnormalize;
+ ##[ ##1: #H1; ndestruct (*nelim (nat_destruct_S_0 ? H1)*)
+ ##| ##2: #n4; #H1;
+ napply (H n4 (nat_destruct_S_S … H1))
+ ##]
+ ##]
+nqed.
+
+nlemma neqnat_to_neq : ∀n1,n2:nat.(eq_nat n1 n2 = false → n1 ≠ n2).
+ #n1; #n2; #H;
+ napply (not_to_not (n1 = n2) (eq_nat n1 n2 = true) …);
+ ##[ ##1: napply (eq_to_eqnat n1 n2)
+ ##| ##2: napply (eqfalse_to_neqtrue … H)
+ ##]
+nqed.
+
+nlemma eqnat_to_eq : ∀n1,n2:nat.(eq_nat n1 n2 = true → n1 = n2).
+ #n1;
+ nelim n1;
+ ##[ ##1: #n2;
+ nelim n2;
+ nnormalize;
+ ##[ ##1: #H; napply refl_eq
+ ##| ##2: #n3; #H; #H1; ndestruct (*napply (bool_destruct … (O = S n3) H1)*)
+ ##]
+ ##| ##2: #n2; #H; #n3; #H1;
+ ncases n3 in H1:(%) ⊢ %;
+ nnormalize;
+ ##[ ##1: #H1; ndestruct (*napply (bool_destruct … (S n2 = O) H1)*)
+ ##| ##2: #n4; #H1;
+ nrewrite > (H n4 H1);
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqnat : ∀n1,n2:nat.n1 ≠ n2 → eq_nat n1 n2 = false.
+ #n1; #n2; #H;
+ napply (neqtrue_to_eqfalse (eq_nat n1 n2));
+ napply (not_to_not (eq_nat n1 n2 = true) (n1 = n2) ? H);
+ napply (eqnat_to_eq n1 n2).
+nqed.
+
+nlemma decidable_nat : ∀x,y:nat.decidable (x = y).
+ #x; #y; nnormalize;
+ napply (or2_elim (eq_nat x y = true) (eq_nat x y = false) ? (decidable_bexpr ?));
+ ##[ ##1: #H; napply (or2_intro1 (x = y) (x ≠ y) (eqnat_to_eq … H))
+ ##| ##2: #H; napply (or2_intro2 (x = y) (x ≠ y) (neqnat_to_neq … H))
+ ##]
+nqed.
+
+nlemma symmetric_eqnat : symmetricT nat bool eq_nat.
+ #n1; #n2;
+ napply (or2_elim (n1 = n2) (n1 ≠ n2) ? (decidable_nat n1 n2));
+ ##[ ##1: #H; nrewrite > H; napply refl_eq
+ ##| ##2: #H; nrewrite > (neq_to_neqnat n1 n2 H);
+ napply (symmetric_eq ? (eq_nat n2 n1) false);
+ napply (neq_to_neqnat n2 n1 (symmetric_neq ? n1 n2 H))
+ ##]
+nqed.
+
+nlemma Sn_p_n_to_S_npn : ∀n1,n2.(S n1) + n2 = S (n1 + n2).
+ #n1;
+ nelim n1;
+ ##[ ##1: nnormalize; #n2; napply refl_eq
+ ##| ##2: #n; #H; #n2; nrewrite > (H n2);
+ ncases n in H:(%) ⊢ %;
+ ##[ ##1: nnormalize; #H; napply refl_eq
+ ##| ##2: #n3; nnormalize; #H; napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma n_p_Sn_to_S_npn : ∀n1,n2.n1 + (S n2) = S (n1 + n2).
+ #n1;
+ nelim n1;
+ ##[ ##1: nnormalize; #n2; napply refl_eq
+ ##| ##2: #n; #H; #n2;
+ nrewrite > (Sn_p_n_to_S_npn n (S n2));
+ nrewrite > (H n2);
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma Opn_to_n : ∀n.O + n = n.
+ #n; nnormalize; napply refl_eq.
+nqed.
+
+nlemma npO_to_n : ∀n.n + O = n.
+ #n;
+ nelim n;
+ ##[ ##1: nnormalize; napply refl_eq
+ ##| ##2: #n1; #H;
+ nrewrite > (Sn_p_n_to_S_npn n1 O);
+ nrewrite > H;
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma symmetric_plusnat : symmetricT nat nat plus.
+ #n1;
+ nelim n1;
+ ##[ ##1: #n2; nrewrite > (npO_to_n n2); nnormalize; napply refl_eq
+ ##| ##2: #n2; #H; #n3;
+ nrewrite > (Sn_p_n_to_S_npn n2 n3);
+ nrewrite > (n_p_Sn_to_S_npn n3 n2);
+ nrewrite > (H n3);
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma nat_is_comparable : comparable.
+ napply (mk_comparable nat);
+ ##[ napply O
+ ##| napply (λx.false)
+ ##| napply eq_nat
+ ##| napply eqnat_to_eq
+ ##| napply eq_to_eqnat
+ ##| napply neqnat_to_neq
+ ##| napply neq_to_neqnat
+ ##| napply decidable_nat
+ ##| napply symmetric_eqnat
+ ##]
+nqed.
+
+unification hint 0 ≔ ⊢ carr nat_is_comparable ≡ nat.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| A.Asperti, C.Sacerdoti Coen, *)
+(* ||A|| E.Tassi, S.Zacchiroli *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU Lesser General Public License Version 2.1 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/list.ma".
+
+(* ************** *)
+(* NON-EMPTY LIST *)
+(* ************** *)
+
+(* lista non vuota *)
+ninductive ne_list (A:Type) : Type ≝
+ | ne_nil: A → ne_list A
+ | ne_cons: A → ne_list A → ne_list A.
+
+(* append *)
+nlet rec ne_append (A:Type) (l1,l2:ne_list A) on l1 ≝
+ match l1 with
+ [ ne_nil hd ⇒ ne_cons A hd l2
+ | ne_cons hd tl ⇒ ne_cons A hd (ne_append A tl l2) ].
+
+notation "hvbox(hd break §§ tl)"
+ right associative with precedence 46
+ for @{'ne_cons $hd $tl}.
+
+(* \laquo \raquo *)
+notation "« list0 x sep ; break £ y break »"
+ non associative with precedence 90
+ for ${fold right @{'ne_nil $y } rec acc @{'ne_cons $x $acc}}.
+
+notation "hvbox(l1 break & l2)"
+ right associative with precedence 47
+ for @{'ne_append $l1 $l2 }.
+
+interpretation "ne_nil" 'ne_nil hd = (ne_nil ? hd).
+interpretation "ne_cons" 'ne_cons hd tl = (ne_cons ? hd tl).
+interpretation "ne_append" 'ne_append l1 l2 = (ne_append ? l1 l2).
+
+nlemma nelist_destruct_nil_nil : ∀T.∀x1,x2:T.ne_nil T x1 = ne_nil T x2 → x1 = x2.
+ #T; #x1; #x2; #H;
+ nchange with (match ne_nil T x2 with [ ne_cons _ _ ⇒ False | ne_nil a ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma nelist_destruct_cons_cons_1 : ∀T.∀x1,x2:T.∀y1,y2:ne_list T.ne_cons T x1 y1 = ne_cons T x2 y2 → x1 = x2.
+ #T; #x1; #x2; #y1; #y2; #H;
+ nchange with (match ne_cons T x2 y2 with [ ne_nil _ ⇒ False | ne_cons a _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma nelist_destruct_cons_cons_2 : ∀T.∀x1,x2:T.∀y1,y2:ne_list T.ne_cons T x1 y1 = ne_cons T x2 y2 → y1 = y2.
+ #T; #x1; #x2; #y1; #y2; #H;
+ nchange with (match ne_cons T x2 y2 with [ ne_nil _ ⇒ False | ne_cons _ b ⇒ y1 = b ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma nelist_destruct_cons_nil : ∀T.∀x1,x2:T.∀y1:ne_list T.ne_cons T x1 y1 = ne_nil T x2 → False.
+ #T; #x1; #x2; #y1; #H;
+ nchange with (match ne_cons T x1 y1 with [ ne_nil _ ⇒ True | ne_cons a b ⇒ False ]);
+ nrewrite > H;
+ nnormalize;
+ napply I.
+nqed.
+
+nlemma nelist_destruct_nil_cons : ∀T.∀x1,x2:T.∀y2:ne_list T.ne_nil T x1 = ne_cons T x2 y2 → False.
+ #T; #x1; #x2; #y2; #H;
+ nchange with (match ne_cons T x2 y2 with [ ne_nil _ ⇒ True | ne_cons a b ⇒ False ]);
+ nrewrite < H;
+ nnormalize;
+ napply I.
+nqed.
+
+nlemma associative_nelist : ∀T.associative (ne_list T) (ne_append T).
+ #T; #x; #y; #z;
+ nelim x;
+ nnormalize;
+ ##[ ##1: #hh; napply refl_eq
+ ##| ##2: #hh; #tt; #H;
+ nrewrite > H;
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma necons_append_commute : ∀T:Type.∀l1,l2:ne_list T.∀a:T.(a §§ (l1 & l2)) = ((a §§ l1) & l2).
+ #T; #l1; #l2; #a;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma append_necons_commute : ∀T:Type.∀a:T.∀l,l1:ne_list T.(l & (a §§ l1)) = (l & «£a») & l1.
+ #T; #a; #l; #l1;
+ nrewrite > (associative_nelist T l «£a» l1);
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+(* listlen *)
+nlet rec len_neList (T:Type) (nl:ne_list T) on nl ≝
+ match nl with [ ne_nil _ ⇒ (S O) | ne_cons _ t ⇒ S (len_neList T t) ].
+
+(* reverse *)
+nlet rec reverse_neList (T:Type) (nl:ne_list T) on nl ≝
+ match nl with
+ [ ne_nil h ⇒ ne_nil T h
+ | ne_cons h t ⇒ (reverse_neList T t)&(ne_nil T h)
+ ].
+
+(* getFirst *)
+ndefinition get_first_neList ≝
+λT:Type.λnl:ne_list T.match nl with
+ [ ne_nil h ⇒ h
+ | ne_cons h _ ⇒ h ].
+
+(* getLast *)
+ndefinition get_last_neList ≝
+λT:Type.λnl:ne_list T.match reverse_neList T nl with
+ [ ne_nil h ⇒ h
+ | ne_cons h _ ⇒ h ].
+
+(* cutFirst *)
+ndefinition cut_first_neList ≝
+λT:Type.λnl:ne_list T.match nl with
+ [ ne_nil h ⇒ ne_nil T h
+ | ne_cons _ t ⇒ t ].
+
+(* cutLast *)
+ndefinition cut_last_neList ≝
+λT:Type.λnl:ne_list T.match reverse_neList T nl with
+ [ ne_nil h ⇒ ne_nil T h
+ | ne_cons _ t ⇒ reverse_neList T t ].
+
+(* apply f *)
+nlet rec apply_f_neList (T1,T2:Type) (nl:ne_list T1) (f:T1 → T2) on nl ≝
+match nl with
+ [ ne_nil h ⇒ ne_nil T2 (f h)
+ | ne_cons h t ⇒ ne_cons T2 (f h) (apply_f_neList T1 T2 t f) ].
+
+(* fold right *)
+nlet rec fold_right_neList (T1,T2:Type) (f:T1 → T2 → T2) (acc:T2) (nl:ne_list T1) on nl ≝
+ match nl with
+ [ ne_nil h ⇒ f h acc
+ | ne_cons h t ⇒ f h (fold_right_neList T1 T2 f acc t)
+ ].
+
+(* double fold right *)
+nlemma fold_right_neList2_aux1 :
+∀T.∀h,h',t'.len_neList T «£h» = len_neList T (h'§§t') → False.
+ #T; #h; #h'; #t';
+ nnormalize;
+ ncases t';
+ nnormalize;
+ ##[ ##1: #x; #H; ndestruct (*nelim (nat_destruct_0_S ? (nat_destruct_S_S … H))*)
+ ##| ##2: #x; #l; #H; ndestruct (*nelim (nat_destruct_0_S ? (nat_destruct_S_S … H))*)
+ ##]
+nqed.
+
+nlemma fold_right_neList2_aux2 :
+∀T.∀h,h',t.len_neList T (h§§t) = len_neList T «£h'» → False.
+ #T; #h; #h'; #t;
+ nnormalize;
+ ncases t;
+ nnormalize;
+ ##[ ##1: #x; #H; ndestruct (*nelim (nat_destruct_S_0 ? (nat_destruct_S_S … H))*)
+ ##| ##2: #x; #l; #H; ndestruct (*nelim (nat_destruct_S_0 ? (nat_destruct_S_S … H))*)
+ ##]
+nqed.
+
+nlemma fold_right_neList2_aux3 :
+∀T.∀h,h',t,t'.len_neList T (h§§t) = len_neList T (h'§§t') → len_neList T t = len_neList T t'.
+ #T; #h; #h'; #t; #t';
+ nelim t;
+ nelim t';
+ ##[ ##1: nnormalize; #x; #y; #H; napply refl_eq
+ ##| ##2: #a; #l'; #H; #x; #H1;
+ nchange in H1:(%) with ((S (len_neList T «£x»)) = (S (len_neList T (a§§l'))));
+ nrewrite > (nat_destruct_S_S … H1);
+ napply refl_eq
+ ##| ##3: #x; #a; #l'; #H; #H1;
+ nchange in H1:(%) with ((S (len_neList T (a§§l')))= (S (len_neList T «£x»)));
+ nrewrite > (nat_destruct_S_S … H1);
+ napply refl_eq
+ ##| ##4: #a; #l; #H; #a1; #l1; #H1; #H2;
+ nchange in H2:(%) with ((S (len_neList T (a1§§l1))) = (S (len_neList T (a§§l))));
+ nrewrite > (nat_destruct_S_S … H2);
+ napply refl_eq
+ ##]
+nqed.
+
+nlet rec fold_right_neList2 (T1,T2:Type) (f:T1 → T1 → T2 → T2) (acc:T2) (l1:ne_list T1) on l1 ≝
+ match l1
+ return λl1.Πl2.len_neList T1 l1 = len_neList T1 l2 → T2
+ with
+ [ ne_nil h ⇒ λl2.match l2 return λl2.len_neList T1 «£h» = len_neList T1 l2 → T2 with
+ [ ne_nil h' ⇒ λp:len_neList T1 «£h» = len_neList T1 «£h'».
+ f h h' acc
+ | ne_cons h' t' ⇒ λp:len_neList T1 «£h» = len_neList T1 (h'§§t').
+ False_rect_Type0 ? (fold_right_neList2_aux1 T1 h h' t' p)
+ ]
+ | ne_cons h t ⇒ λl2.match l2 return λl2.len_neList T1 (h§§t) = len_neList T1 l2 → T2 with
+ [ ne_nil h' ⇒ λp:len_neList T1 (h§§t) = len_neList T1 «£h'».
+ False_rect_Type0 ? (fold_right_neList2_aux2 T1 h h' t p)
+ | ne_cons h' t' ⇒ λp:len_neList T1 (h§§t) = len_neList T1 (h'§§t').
+ f h h' (fold_right_neList2 T1 T2 f acc t t' (fold_right_neList2_aux3 T1 h h' t t' p))
+ ]
+ ].
+
+nlet rec bfold_right_neList2 (T1:Type) (f:T1 → T1 → bool) (l1,l2:ne_list T1) on l1 ≝
+ match l1 with
+ [ ne_nil h ⇒ match l2 with
+ [ ne_nil h' ⇒ f h h' | ne_cons h' t' ⇒ false ]
+ | ne_cons h t ⇒ match l2 with
+ [ ne_nil h' ⇒ false | ne_cons h' t' ⇒ (f h h') ⊗ (bfold_right_neList2 T1 f t t')
+ ]
+ ].
+
+(* nth elem *)
+nlet rec nth_neList (T:Type) (nl:ne_list T) (n:nat) on nl ≝
+ match nl with
+ [ ne_nil h ⇒ match n with
+ [ O ⇒ Some ? h | S _ ⇒ None ? ]
+ | ne_cons h t ⇒ match n with
+ [ O ⇒ Some ? h | S n' ⇒ nth_neList T t n' ]
+ ].
+
+(* abs elem *)
+ndefinition abs_neList_aux1 : ∀T:Type.∀h:T.∀n.((len_neList T («£h»)) > (S n)) = true → False.
+ #T; #h; #n; nnormalize; #H; ndestruct (*napply (bool_destruct … H)*). nqed.
+
+ndefinition abs_neList_aux2 : ∀T:Type.∀h:T.∀t:ne_list T.∀n.((len_neList T (h§§t)) > (S n) = true) → ((len_neList T t) > n) = true.
+ #T; #h; #t; #n; nnormalize; #H; napply H. nqed.
+
+nlet rec abs_neList (T:Type) (l:ne_list T) on l ≝
+ match l
+ return λl.Πn.(((len_neList T l) > n) = true) → T
+ with
+ [ ne_nil h ⇒ λn.
+ match n
+ return λn.(((len_neList T (ne_nil T h)) > n) = true) → T
+ with
+ [ O ⇒ λp:(((len_neList T (ne_nil T h)) > O) = true).h
+ | S n' ⇒ λp:(((len_neList T (ne_nil T h)) > (S n')) = true).
+ False_rect_Type0 ? (abs_neList_aux1 T h n' p)
+ ]
+ | ne_cons h t ⇒ λn.
+ match n with
+ [ O ⇒ λp:(((len_neList T (ne_cons T h t)) > O) = true).h
+ | S n' ⇒ λp:(((len_neList T (ne_cons T h t)) > (S n')) = true).
+ abs_neList T t n' (abs_neList_aux2 T h t n' p)
+ ]
+ ].
+
+(* esempio: abs_neList ? « 1; 2; 3 £ 4 » 0 (refl_eq …) = 1. *)
+
+(* conversione *)
+nlet rec neList_to_list (T:Type) (nl:ne_list T) on nl : list T ≝
+ match nl with [ ne_nil h ⇒ [h] | ne_cons h t ⇒ [h]@(neList_to_list T t) ].
+
+nlemma symmetric_lennelist : ∀T.∀l1,l2:ne_list T.len_neList T l1 = len_neList T l2 → len_neList T l2 = len_neList T l1.
+ #T; #l1;
+ nelim l1;
+ ##[ ##1: #h; #l2; ncases l2; nnormalize;
+ ##[ ##1: #H; #H1; napply refl_eq
+ ##| ##2: #h; #t; #H; nrewrite > H; napply refl_eq
+ ##]
+ ##| ##2: #h; #l2; ncases l2; nnormalize;
+ ##[ ##1: #h1; #H; #l; #H1; nrewrite < H1; napply refl_eq
+ ##| ##2: #h; #l; #H; #l3; #H1; nrewrite < H1; napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma symmetric_foldrightnelist2_aux :
+∀T1,T2:Type.∀f:T1 → T1 → T2 → T2.
+ (∀x,y,z.f x y z = f y x z) →
+ (∀acc:T2.∀l1,l2:ne_list T1.
+ ∀H1:len_neList T1 l1 = len_neList T1 l2.∀H2:len_neList T1 l2 = len_neList T1 l1.
+ fold_right_neList2 T1 T2 f acc l1 l2 H1 = fold_right_neList2 T1 T2 f acc l2 l1 H2).
+ #T1; #T2; #f; #H; #acc; #l1;
+ nelim l1;
+ ##[ ##1: #h; #l2; ncases l2;
+ ##[ ##1: #h1; nnormalize; #H1; #H2; nrewrite > (H h h1 acc); napply refl_eq
+ ##| ##2: #h1; #l; ncases l;
+ ##[ ##1: #h3; #H1; #H2;
+ nchange in H1:(%) with ((S O) = (S (S O)));
+ (* !!! ndestruct: si inceppa su un'ipotesi che non e' H1 *)
+ nelim (nat_destruct_0_S ? (nat_destruct_S_S … H1))
+ ##| ##2: #h3; #l3; #H1; #H2;
+ nchange in H1:(%) with ((S O) = (S (S (len_neList ? l3))));
+ (* !!! ndestruct: si inceppa su un'ipotesi che non e' H1 *)
+ nelim (nat_destruct_0_S ? (nat_destruct_S_S … H1))
+ ##]
+ ##]
+ ##| ##2: #h3; #l3; #H1; #l2; ncases l2;
+ ##[ ##1: #h4; ncases l3;
+ ##[ ##1: #h5; #H2; #H3;
+ nchange in H2:(%) with ((S (S O)) = (S O));
+ (* !!! ndestruct: si inceppa su un'ipotesi che non e' H1 *)
+ nelim (nat_destruct_S_0 ? (nat_destruct_S_S … H2))
+ ##| ##2: #h5; #l5; #H2; #H3;
+ nchange in H2:(%) with ((S (S (len_neList ? l5))) = (S O));
+ (* !!! ndestruct: si inceppa su un'ipotesi che non e' H1 *)
+ nelim (nat_destruct_S_0 ? (nat_destruct_S_S … H2))
+ ##]
+ ##| ##2: #h4; #l4; #H2; #H3;
+ nchange in H2:(%) with ((S (len_neList ? l3)) = (S (len_neList ? l4)));
+ nchange in H3:(%) with ((S (len_neList ? l4)) = (S (len_neList ? l3)));
+ nchange with ((f h3 h4 (fold_right_neList2 T1 T2 f acc l3 l4 (fold_right_neList2_aux3 T1 h3 h4 l3 l4 ?))) =
+ (f h4 h3 (fold_right_neList2 T1 T2 f acc l4 l3 (fold_right_neList2_aux3 T1 h4 h3 l4 l3 ?))));
+ nrewrite < (H1 l4 (fold_right_neList2_aux3 T1 h3 h4 l3 l4 H2) (fold_right_neList2_aux3 T1 h4 h3 l4 l3 H3));
+ nrewrite > (H h3 h4 (fold_right_neList2 T1 T2 f acc l3 l4 ?));
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma symmetric_foldrightnelist2 :
+∀T1,T2:Type.∀f:T1 → T1 → T2 → T2.
+ (∀x,y,z.f x y z = f y x z) →
+ (∀acc:T2.∀l1,l2:ne_list T1.∀H:len_neList T1 l1 = len_neList T1 l2.
+ fold_right_neList2 T1 T2 f acc l1 l2 H = fold_right_neList2 T1 T2 f acc l2 l1 (symmetric_lennelist T1 l1 l2 H)).
+ #T1; #T2; #f; #H; #acc; #l1; #l2; #H1;
+ nrewrite > (symmetric_foldrightnelist2_aux T1 T2 f H acc l1 l2 H1 (symmetric_lennelist T1 l1 l2 H1));
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_bfoldrightnelist2 :
+∀T1:Type.∀f:T1 → T1 → bool.
+ (∀x,y.f x y = f y x) →
+ (∀l1,l2:ne_list T1.
+ bfold_right_neList2 T1 f l1 l2 = bfold_right_neList2 T1 f l2 l1).
+ #T; #f; #H; #l1;
+ nelim l1;
+ ##[ ##1: #hh1; #l2; ncases l2;
+ ##[ ##1: #hh2; nnormalize; nrewrite > (H hh1 hh2); napply refl_eq
+ ##| ##2: #hh2; #ll2; nnormalize; napply refl_eq
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: #hh2; nnormalize; napply refl_eq
+ ##| ##2: #hh2; #ll2; nnormalize;
+ nrewrite > (H1 ll2);
+ nrewrite > (H hh1 hh2);
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma bfoldrightnelist2_to_eq :
+∀T1:Type.∀f:T1 → T1 → bool.
+ (∀x,y.(f x y = true → x = y)) →
+ (∀l1,l2:ne_list T1.
+ (bfold_right_neList2 T1 f l1 l2 = true → l1 = l2)).
+ #T; #f; #H; #l1;
+ nelim l1;
+ ##[ ##1: #hh1; #l2; ncases l2;
+ ##[ ##1: #hh2; #H1; nnormalize in H1:(%); nrewrite > (H hh1 hh2 H1); napply refl_eq
+ ##| ##2: #hh2; #ll2; nnormalize; #H1; ndestruct (*napply (bool_destruct … H1)*)
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: #hh2; nnormalize; #H2; ndestruct (*napply (bool_destruct … H2)*)
+ ##| ##2: #hh2; #ll2; #H2;
+ nchange in H2:(%) with (((f hh1 hh2)⊗(bfold_right_neList2 T f ll1 ll2)) = true);
+ nrewrite > (H hh1 hh2 (andb_true_true_l … H2));
+ nrewrite > (H1 ll2 (andb_true_true_r … H2));
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma eq_to_bfoldrightnelist2 :
+∀T1:Type.∀f:T1 → T1 → bool.
+ (∀x,y.(x = y → f x y = true)) →
+ (∀l1,l2:ne_list T1.
+ (l1 = l2 → bfold_right_neList2 T1 f l1 l2 = true)).
+ #T; #f; #H; #l1;
+ nelim l1;
+ ##[ ##1: #hh1; #l2; ncases l2;
+ ##[ ##1: #hh2; #H1; nnormalize;
+ nrewrite > (H hh1 hh2 (nelist_destruct_nil_nil … H1));
+ napply refl_eq
+ ##| ##2: #hh2; #ll2; #H1;
+ (* !!! ndestruct: assert false *)
+ nelim (nelist_destruct_nil_cons ???? H1)
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: #hh2; #H2;
+ (* !!! ndestruct: assert false *)
+ nelim (nelist_destruct_cons_nil ???? H2)
+ ##| ##2: #hh2; #ll2; #H2; nnormalize;
+ nrewrite > (nelist_destruct_cons_cons_1 … H2);
+ nrewrite > (H hh2 hh2 (refl_eq …));
+ nnormalize;
+ nrewrite > (H1 ll2 (nelist_destruct_cons_cons_2 … H2));
+ napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma bfoldrightnelist2_to_lennelist :
+∀T.∀f:T → T → bool.
+ (∀l1,l2:ne_list T.bfold_right_neList2 T f l1 l2 = true → len_neList T l1 = len_neList T l2).
+ #T; #f; #l1;
+ nelim l1;
+ ##[ ##1: #hh1; #l2; ncases l2;
+ ##[ ##1: nnormalize; #hh2; #H; napply refl_eq
+ ##| ##2: nnormalize; #hh2; #tt2; #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+ ##| ##2: #hh1; #tt1; #H; #l2; ncases l2;
+ ##[ ##1: nnormalize; #hh2; #H1; ndestruct (*napply (bool_destruct … H1)*)
+ ##| ##2: #hh2; #tt2; #H1; nnormalize;
+ nrewrite > (H tt2 ?);
+ ##[ ##1: napply refl_eq
+ ##| ##2: nchange in H1:(%) with ((? ⊗ (bfold_right_neList2 T f tt1 tt2)) = true);
+ napply (andb_true_true_r … H1)
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma decidable_nelist :
+∀T.(∀x,y:T.decidable (x = y)) →
+ (∀x,y:ne_list T.decidable (x = y)).
+ #T; #H; #x; nelim x;
+ ##[ ##1: #hh1; #y; ncases y;
+ ##[ ##1: #hh2; nnormalize; napply (or2_elim (hh1 = hh2) (hh1 ≠ hh2) ? (H hh1 hh2));
+ ##[ ##1: #H1; nrewrite > H1; napply (or2_intro1 (? = ?) (? ≠ ?) (refl_eq …))
+ ##| ##2: #H1; napply (or2_intro2 (? = ?) (? ≠ ?) ?); nnormalize;
+ #H2; napply (H1 (nelist_destruct_nil_nil T … H2))
+ ##]
+ ##| ##2: #hh2; #tt2; nnormalize; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H1;
+ (* !!! ndestruct: assert false *)
+ napply (nelist_destruct_nil_cons T … H1)
+ ##]
+ ##| ##2: #hh1; #tt1; #H1; #y; ncases y;
+ ##[ ##1: #hh1; nnormalize; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (nelist_destruct_cons_nil T … H2)
+ ##| ##2: #hh2; #tt2; nnormalize; napply (or2_elim (hh1 = hh2) (hh1 ≠ hh2) ? (H …));
+ ##[ ##2: #H2; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H3; napply (H2 (nelist_destruct_cons_cons_1 T … H3))
+ ##| ##1: #H2; napply (or2_elim (tt1 = tt2) (tt1 ≠ tt2) ? (H1 tt2));
+ ##[ ##2: #H3; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H4; napply (H3 (nelist_destruct_cons_cons_2 T … H4))
+ ##| ##1: #H3; napply (or2_intro1 (? = ?) (? ≠ ?) ?);
+ nrewrite > H2; nrewrite > H3; napply refl_eq
+ ##]
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma nbfoldrightnelist2_to_neq :
+∀T1:Type.∀f:T1 → T1 → bool.
+ (∀x,y.(f x y = false → x ≠ y)) →
+ (∀l1,l2:ne_list T1.
+ (bfold_right_neList2 T1 f l1 l2 = false → l1 ≠ l2)).
+ #T; #f; #H; #l1;
+ nelim l1;
+ ##[ ##1: #hh1; #l2; ncases l2;
+ ##[ ##1: #hh2; nnormalize; #H1; #H2; napply (H hh1 hh2 H1 (nelist_destruct_nil_nil T … H2))
+ ##| ##2: #hh2; #ll2; #H1; nnormalize; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (nelist_destruct_nil_cons T … H2)
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: #hh2; #H2; nnormalize; #H3;
+ (* !!! ndestruct: assert false *)
+ napply (nelist_destruct_cons_nil T … H3)
+ ##| ##2: #hh2; #ll2; #H2; nnormalize; #H3;
+ nchange in H2:(%) with (((f hh1 hh2)⊗(bfold_right_neList2 T f ll1 ll2)) = false);
+ napply (H1 ll2 ? (nelist_destruct_cons_cons_2 T … H3));
+ napply (or2_elim ??? (andb_false2 … H2) );
+ ##[ ##1: #H4; napply (absurd (hh1 = hh2) …);
+ ##[ ##1: nrewrite > (nelist_destruct_cons_cons_1 T … H3); napply refl_eq
+ ##| ##2: napply (H … H4)
+ ##]
+ ##| ##2: #H4; napply H4
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma nelist_destruct :
+∀T.(∀x,y:T.decidable (x = y)) →
+ (∀h1,h2:T.∀l1,l2:ne_list T.
+ (h1§§l1) ≠ (h2§§l2) → h1 ≠ h2 ∨ l1 ≠ l2).
+ #T; #H; #h1; #h2; #l1; nelim l1;
+ ##[ ##1: #hh1; #l2; ncases l2;
+ ##[ ##1: #hh2; #H1; napply (or2_elim (h1 = h2) (h1 ≠ h2) ? (H …) …);
+ ##[ ##2: #H2; napply (or2_intro1 (h1 ≠ h2) («£hh1» ≠ «£hh2») H2)
+ ##| ##1: #H2; nrewrite > H2 in H1:(%); #H1;
+ napply (or2_elim (hh1 = hh2) (hh1 ≠ hh2) ? (H …) …);
+ ##[ ##2: #H3; napply (or2_intro2 (h2 ≠ h2) («£hh1» ≠ «£hh2») ?);
+ nnormalize; #H4; napply (H3 (nelist_destruct_nil_nil T … H4))
+ ##| ##1: #H3; nrewrite > H3 in H1:(%); #H1; nelim (H1 (refl_eq …))
+ ##]
+ ##]
+ ##| ##2: #hh2; #ll2; #H1; napply (or2_intro2 (h1 ≠ h2) («£hh1» ≠ (hh2§§ll2)) …);
+ nnormalize; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (nelist_destruct_nil_cons T … H2)
+ ##]
+ ##| ##2: #hh1; #ll1; #H1; #l2; ncases l2;
+ ##[ ##1: #hh2; #H2; napply (or2_intro2 (h1 ≠ h2) ((hh1§§ll1) ≠ «£hh2») …);
+ nnormalize; #H3;
+ (* !!! ndestruct: assert false *)
+ napply (nelist_destruct_cons_nil T … H3)
+ ##| ##2: #hh2; #ll2; #H2;
+ napply (or2_elim (h1 = h2) (h1 ≠ h2) ? (H h1 h2) …);
+ ##[ ##2: #H3; napply (or2_intro1 (h1 ≠ h2) ((hh1§§ll1) ≠ (hh2§§ll2)) H3)
+ ##| ##1: #H3; napply (or2_intro2 (h1 ≠ h2) ((hh1§§ll1) ≠ (hh2§§ll2) …));
+ nrewrite > H3 in H2:(%); #H2;
+ nnormalize; #H4; nrewrite > (nelist_destruct_cons_cons_1 T … H4) in H2:(%); #H2;
+ nrewrite > (nelist_destruct_cons_cons_2 T … H4) in H2:(%); #H2;
+ napply (H2 (refl_eq …))
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_nbfoldrightnelist2 :
+∀T:Type.∀f:T → T → bool.
+ (∀x,y:T.decidable (x = y)) →
+ (∀x,y.(x ≠ y → f x y = false)) →
+ (∀l1,l2:ne_list T.
+ (l1 ≠ l2 → bfold_right_neList2 T f l1 l2 = false)).
+ #T; #f; #H; #H1; #l1;
+ nelim l1;
+ ##[ ##1: #hh1; #l2; ncases l2;
+ ##[ ##1: #hh2; nnormalize; #H2; napply (H1 hh1 hh2 ?);
+ nnormalize; #H3; nrewrite > H3 in H2:(%); #H2; napply (H2 (refl_eq …))
+ ##| ##2: #hh2; #ll2; nnormalize; #H2; napply refl_eq
+ ##]
+ ##| ##2: #hh1; #ll1; #H2; #l2; ncases l2;
+ ##[ ##1: #hh2; nnormalize; #H3; napply refl_eq
+ ##| ##2: #hh2; #ll2; #H3;
+ nchange with (((f hh1 hh2)⊗(bfold_right_neList2 T f ll1 ll2)) = false);
+ napply (or2_elim (hh1 ≠ hh2) (ll1 ≠ ll2) ? (nelist_destruct T H … H3) …);
+ ##[ ##1: #H4; nrewrite > (H1 hh1 hh2 H4); nnormalize; napply refl_eq
+ ##| ##2: #H4; nrewrite > (H2 ll2 H4);
+ nrewrite > (symmetric_andbool (f hh1 hh2) false);
+ nnormalize; napply refl_eq
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma nelist_is_comparable : comparable → comparable.
+ #T; napply (mk_comparable (ne_list T));
+ ##[ napply (ne_nil ? (zeroc T))
+ ##| napply (λx.false)
+ ##| napply (bfold_right_neList2 T (eqc T))
+ ##| napply (bfoldrightnelist2_to_eq … (eqc T));
+ napply (eqc_to_eq T)
+ ##| napply (eq_to_bfoldrightnelist2 … (eqc T));
+ napply (eq_to_eqc T)
+ ##| napply (nbfoldrightnelist2_to_neq … (eqc T));
+ napply (neqc_to_neq T)
+ ##| napply (neq_to_nbfoldrightnelist2 … (eqc T));
+ ##[ napply (decidable_c T)
+ ##| napply (neq_to_neqc T)
+ ##]
+ ##| napply decidable_nelist;
+ napply (decidable_c T)
+ ##| napply symmetric_bfoldrightnelist2;
+ napply (symmetric_eqc T)
+ ##]
+nqed.
+
+unification hint 0 ≔ S: comparable;
+ T ≟ (carr S),
+ X ≟ (nelist_is_comparable S)
+ (*********************************************) ⊢
+ carr X ≡ ne_list T.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/comp.ma".
+include "common/option_base.ma".
+include "num/bool_lemmas.ma".
+
+(* ****** *)
+(* OPTION *)
+(* ****** *)
+
+nlemma option_destruct_some_some : ∀T.∀x1,x2:T.Some T x1 = Some T x2 → x1 = x2.
+ #T; #x1; #x2; #H;
+ nchange with (match Some T x2 with [ None ⇒ False | Some a ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma option_destruct_some_none : ∀T.∀x:T.Some T x = None T → False.
+ #T; #x; #H;
+ nchange with (match Some T x with [ None ⇒ True | Some a ⇒ False ]);
+ nrewrite > H;
+ nnormalize;
+ napply I.
+nqed.
+
+nlemma option_destruct_none_some : ∀T.∀x:T.None T = Some T x → False.
+ #T; #x; #H;
+ nchange with (match Some T x with [ None ⇒ True | Some a ⇒ False ]);
+ nrewrite < H;
+ nnormalize;
+ napply I.
+nqed.
+
+nlemma symmetric_eqoption :
+∀T:Type.∀f:T → T → bool.
+ (symmetricT T bool f) →
+ (∀op1,op2:option T.
+ (eq_option T f op1 op2 = eq_option T f op2 op1)).
+ #T; #f; #H;
+ #op1; #op2; nelim op1; nelim op2;
+ nnormalize;
+ ##[ ##1: napply refl_eq
+ ##| ##2,3: #H; napply refl_eq
+ ##| ##4: #a; #a0;
+ nrewrite > (H a0 a);
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma eq_to_eqoption :
+∀T.∀f:T → T → bool.
+ (∀x1,x2:T.x1 = x2 → f x1 x2 = true) →
+ (∀op1,op2:option T.
+ (op1 = op2 → eq_option T f op1 op2 = true)).
+ #T; #f; #H;
+ #op1; #op2; nelim op1; nelim op2;
+ nnormalize;
+ ##[ ##1: #H1; napply refl_eq
+ ##| ##2: #a; #H1;
+ (* !!! ndestruct: assert false *)
+ nelim (option_destruct_none_some ?? H1)
+ ##| ##3: #a; #H1;
+ (* !!! ndestruct: assert false *)
+ nelim (option_destruct_some_none ?? H1)
+ ##| ##4: #a; #a0; #H1;
+ nrewrite > (H … (option_destruct_some_some … H1));
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma eqoption_to_eq :
+∀T.∀f:T → T → bool.
+ (∀x1,x2:T.f x1 x2 = true → x1 = x2) →
+ (∀op1,op2:option T.
+ (eq_option T f op1 op2 = true → op1 = op2)).
+ #T; #f; #H;
+ #op1; #op2; nelim op1; nelim op2;
+ nnormalize;
+ ##[ ##1: #H1; napply refl_eq
+ ##| ##2,3: #a; #H1; ndestruct (*napply (bool_destruct … H1)*)
+ ##| ##4: #a; #a0; #H1;
+ nrewrite > (H … H1);
+ napply refl_eq
+ ##]
+nqed.
+
+nlemma decidable_option :
+∀T.(Πx,y:T.decidable (x = y)) →
+ (∀x,y:option T.decidable (x = y)).
+ #T; #H; #x; nelim x;
+ ##[ ##1: #y; ncases y;
+ ##[ ##1: nnormalize; napply (or2_intro1 (? = ?) (? ≠ ?) (refl_eq …))
+ ##| ##2: #yy; nnormalize; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H1;
+ (* !!! ndestruct: assert false *)
+ napply (option_destruct_none_some T … H1)
+ ##]
+ ##| ##2: #xx; #y; ncases y;
+ ##[ ##1: nnormalize; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (option_destruct_some_none T … H2)
+ ##| ##2: #yy; nnormalize; napply (or2_elim (xx = yy) (xx ≠ yy) ? (H …));
+ ##[ ##2: #H1; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H2;
+ napply (H1 (option_destruct_some_some T … H2))
+ ##| ##1: #H1; napply (or2_intro1 (? = ?) (? ≠ ?) ?);
+ nrewrite > H1; napply refl_eq
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqoption :
+∀T.∀f:T → T → bool.
+ (∀x1,x2:T.x1 ≠ x2 → f x1 x2 = false) →
+ (∀op1,op2:option T.
+ (op1 ≠ op2 → eq_option T f op1 op2 = false)).
+ #T; #f; #H; #op1; nelim op1;
+ ##[ ##1: #op2; ncases op2;
+ ##[ ##1: nnormalize; #H1; nelim (H1 (refl_eq …))
+ ##| ##2: #yy; nnormalize; #H1; napply refl_eq
+ ##]
+ ##| ##2: #xx; #op2; ncases op2;
+ ##[ ##1: nnormalize; #H1; napply refl_eq
+ ##| ##2: #yy; nnormalize; #H1; napply (H xx yy …);
+ nnormalize; #H2; nrewrite > H2 in H1:(%); #H1;
+ napply (H1 (refl_eq …))
+ ##]
+ ##]
+nqed.
+
+nlemma neqoption_to_neq :
+∀T.∀f:T → T → bool.
+ (∀x1,x2:T.f x1 x2 = false → x1 ≠ x2) →
+ (∀op1,op2:option T.
+ (eq_option T f op1 op2 = false → op1 ≠ op2)).
+ #T; #f; #H; #op1; nelim op1;
+ ##[ ##1: #op2; ncases op2;
+ ##[ ##1: nnormalize; #H1;
+ ndestruct (*napply (bool_destruct … H1)*)
+ ##| ##2: #yy; nnormalize; #H1; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (option_destruct_none_some T … H2)
+ ##]
+ ##| ##2: #xx; #op2; ncases op2;
+ ##[ ##1: nnormalize; #H1; #H2;
+ (* !!! ndestruct: assert false *)
+ napply (option_destruct_some_none T … H2)
+ ##| ##2: #yy; nnormalize; #H1; #H2; napply (H xx yy H1 ?);
+ napply (option_destruct_some_some T … H2)
+ ##]
+ ##]
+nqed.
+
+nlemma option_is_comparable :
+ comparable → comparable.
+ #T; napply (mk_comparable (option T));
+ ##[ napply (None ?)
+ ##| napply (λx.false)
+ ##| napply (eq_option … (eqc T))
+ ##| napply (eqoption_to_eq … (eqc T));
+ napply (eqc_to_eq T)
+ ##| napply (eq_to_eqoption … (eqc T));
+ napply (eq_to_eqc T)
+ ##| napply (neqoption_to_neq … (eqc T));
+ napply (neqc_to_neq T)
+ ##| napply (neq_to_neqoption … (eqc T));
+ napply (neq_to_neqc T)
+ ##| napply decidable_option;
+ napply (decidable_c T)
+ ##| napply symmetric_eqoption;
+ napply (symmetric_eqc T)
+ ##]
+nqed.
+
+unification hint 0 ≔ S: comparable;
+ T ≟ (carr S),
+ X ≟ (option_is_comparable S)
+ (*********************************************) ⊢
+ carr X ≡ option T.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/bool.ma".
+
+(* ****** *)
+(* OPTION *)
+(* ****** *)
+
+ninductive option (A:Type) : Type ≝
+ None : option A
+| Some : A → option A.
+
+ndefinition eq_option ≝
+λT.λf:T → T → bool.λop1,op2:option T.
+ match op1 with
+ [ None ⇒ match op2 with [ None ⇒ true | Some _ ⇒ false ]
+ | Some x1 ⇒ match op2 with [ None ⇒ false | Some x2 ⇒ f x1 x2 ]
+ ].
+
+(* option map = match ... with [ None ⇒ None ? | Some .. ⇒ .. ] *)
+ndefinition opt_map ≝
+λT1,T2:Type.λt:option T1.λf:T1 → option T2.
+ match t with [ None ⇒ None ? | Some x ⇒ (f x) ].
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/comp.ma".
+include "common/prod_base.ma".
+include "num/bool_lemmas.ma".
+
+(* ********* *)
+(* TUPLE x 2 *)
+(* ********* *)
+
+nlemma pair_destruct_1 :
+∀T1,T2.∀x1,x2:T1.∀y1,y2:T2.
+ pair T1 T2 x1 y1 = pair T1 T2 x2 y2 → x1 = x2.
+ #T1; #T2; #x1; #x2; #y1; #y2; #H;
+ nchange with (match pair T1 T2 x2 y2 with [ pair a _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma pair_destruct_2 :
+∀T1,T2.∀x1,x2:T1.∀y1,y2:T2.
+ pair T1 T2 x1 y1 = pair T1 T2 x2 y2 → y1 = y2.
+ #T1; #T2; #x1; #x2; #y1; #y2; #H;
+ nchange with (match pair T1 T2 x2 y2 with [ pair _ b ⇒ y1 = b ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_eqpair :
+∀T1,T2:Type.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.
+ (symmetricT T1 bool f1) →
+ (symmetricT T2 bool f2) →
+ (∀p1,p2:ProdT T1 T2.
+ (eq_pair T1 T2 f1 f2 p1 p2 = eq_pair T1 T2 f1 f2 p2 p1)).
+ #T1; #T2; #f1; #f2; #H; #H1;
+ #p1; nelim p1; #x1; #y1;
+ #p2; nelim p2; #x2; #y2;
+ nnormalize;
+ nrewrite > (H x1 x2);
+ ncases (f1 x2 x1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H1 y1 y2); napply refl_eq
+ ##| ##2: napply refl_eq
+ ##]
+nqed.
+
+nlemma eq_to_eqpair :
+∀T1,T2.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.
+ (∀x,y:T1.x = y → f1 x y = true) →
+ (∀x,y:T2.x = y → f2 x y = true) →
+ (∀p1,p2:ProdT T1 T2.
+ (p1 = p2 → eq_pair T1 T2 f1 f2 p1 p2 = true)).
+ #T1; #T2; #f1; #f2; #H1; #H2;
+ #p1; nelim p1; #x1; #y1;
+ #p2; nelim p2; #x2; #y2; #H;
+ nnormalize;
+ nrewrite > (H1 … (pair_destruct_1 … H));
+ nnormalize;
+ nrewrite > (H2 … (pair_destruct_2 … H));
+ napply refl_eq.
+nqed.
+
+nlemma eqpair_to_eq :
+∀T1,T2.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.
+ (∀x,y:T1.f1 x y = true → x = y) →
+ (∀x,y:T2.f2 x y = true → x = y) →
+ (∀p1,p2:ProdT T1 T2.
+ (eq_pair T1 T2 f1 f2 p1 p2 = true → p1 = p2)).
+ #T1; #T2; #f1; #f2; #H1; #H2;
+ #p1; nelim p1; #x1; #y1;
+ #p2; nelim p2; #x2; #y2; #H;
+ nnormalize in H:(%);
+ nletin K ≝ (H1 x1 x2);
+ ncases (f1 x1 x2) in H:(%) K:(%);
+ nnormalize;
+ #H3;
+ ##[ ##2: ndestruct (*napply (bool_destruct … H3)*) ##]
+ #H4;
+ nrewrite > (H4 (refl_eq …));
+ nrewrite > (H2 y1 y2 H3);
+ napply refl_eq.
+nqed.
+
+nlemma decidable_pair :
+∀T1,T2.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:ProdT T1 T2.decidable (x = y)).
+ #T1; #T2; #H; #H1;
+ #x; nelim x; #xx1; #xx2;
+ #y; nelim y; #yy1; #yy2;
+ nnormalize;
+ napply (or2_elim (xx1 = yy1) (xx1 ≠ yy1) ? (H xx1 yy1) ?);
+ ##[ ##2: #H2; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H3; napply (H2 (pair_destruct_1 T1 T2 … H3))
+ ##| ##1: #H2; napply (or2_elim (xx2 = yy2) (xx2 ≠ yy2) ? (H1 xx2 yy2) ?);
+ ##[ ##2: #H3; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H4; napply (H3 (pair_destruct_2 T1 T2 … H4))
+ ##| ##1: #H3; napply (or2_intro1 (? = ?) (? ≠ ?) ?);
+ nrewrite > H2; nrewrite > H3; napply refl_eq
+ ##]
+ ##]
+nqed.
+
+nlemma neqpair_to_neq :
+∀T1,T2.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.
+ (∀x,y:T1.f1 x y = false → x ≠ y) →
+ (∀x,y:T2.f2 x y = false → x ≠ y) →
+ (∀p1,p2:ProdT T1 T2.
+ (eq_pair T1 T2 f1 f2 p1 p2 = false → p1 ≠ p2)).
+ #T1; #T2; #f1; #f2; #H1; #H2;
+ #p1; nelim p1; #x1; #y1;
+ #p2; nelim p2; #x2; #y2;
+ nchange with ((((f1 x1 x2) ⊗ (f2 y1 y2)) = false) → ?); #H;
+ nnormalize; #H3;
+ napply (or2_elim ((f1 x1 x2) = false) ((f2 y1 y2) = false) ? (andb_false2 … H) ?);
+ ##[ ##1: #H4; napply (H1 x1 x2 H4); napply (pair_destruct_1 T1 T2 … H3)
+ ##| ##2: #H4; napply (H2 y1 y2 H4); napply (pair_destruct_2 T1 T2 … H3)
+ ##]
+nqed.
+
+nlemma pair_destruct :
+∀T1,T2.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x1,x2:T1.∀y1,y2:T2.
+ (pair T1 T2 x1 y1) ≠ (pair T1 T2 x2 y2) → x1 ≠ x2 ∨ y1 ≠ y2).
+ #T1; #T2; #H1; #H2; #x1; #x2; #y1; #y2;
+ nnormalize; #H;
+ napply (or2_elim (x1 = x2) (x1 ≠ x2) ? (H1 x1 x2) ?);
+ ##[ ##2: #H3; napply (or2_intro1 … H3)
+ ##| ##1: #H3; napply (or2_elim (y1 = y2) (y1 ≠ y2) ? (H2 y1 y2) ?);
+ ##[ ##2: #H4; napply (or2_intro2 … H4)
+ ##| ##1: #H4; nrewrite > H3 in H:(%);
+ nrewrite > H4; #H; nelim (H (refl_eq …))
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqpair :
+∀T1,T2.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T1.x ≠ y → f1 x y = false) →
+ (∀x,y:T2.x ≠ y → f2 x y = false) →
+ (∀p1,p2:ProdT T1 T2.
+ (p1 ≠ p2 → eq_pair T1 T2 f1 f2 p1 p2 = false)).
+ #T1; #T2; #f1; #f2; #H1; #H2; #H3; #H4;
+ #p1; nelim p1; #x1; #y1;
+ #p2; nelim p2; #x2; #y2; #H;
+ nchange with (((f1 x1 x2) ⊗ (f2 y1 y2)) = false);
+ napply (or2_elim (x1 ≠ x2) (y1 ≠ y2) ? (pair_destruct T1 T2 H1 H2 … H) ?);
+ ##[ ##2: #H5; nrewrite > (H4 … H5); nrewrite > (andb_false2_2 (f1 x1 x2)); napply refl_eq
+ ##| ##1: #H5; nrewrite > (H3 … H5); nnormalize; napply refl_eq
+ ##]
+nqed.
+
+nlemma pair_is_comparable :
+ comparable → comparable → comparable.
+ #T1; #T2; napply (mk_comparable (ProdT T1 T2));
+ ##[ napply (pair … (zeroc T1) (zeroc T2))
+ ##| napply (λx.false)
+ ##| napply (eq_pair … (eqc T1) (eqc T2))
+ ##| napply (eqpair_to_eq … (eqc T1) (eqc T2));
+ ##[ napply (eqc_to_eq T1)
+ ##| napply (eqc_to_eq T2)
+ ##]
+ ##| napply (eq_to_eqpair … (eqc T1) (eqc T2));
+ ##[ napply (eq_to_eqc T1)
+ ##| napply (eq_to_eqc T2)
+ ##]
+ ##| napply (neqpair_to_neq … (eqc T1) (eqc T2));
+ ##[ napply (neqc_to_neq T1)
+ ##| napply (neqc_to_neq T2)
+ ##]
+ ##| napply (neq_to_neqpair … (eqc T1) (eqc T2));
+ ##[ napply (decidable_c T1)
+ ##| napply (decidable_c T2)
+ ##| napply (neq_to_neqc T1)
+ ##| napply (neq_to_neqc T2)
+ ##]
+ ##| napply decidable_pair;
+ ##[ napply (decidable_c T1)
+ ##| napply (decidable_c T2)
+ ##]
+ ##| napply symmetric_eqpair;
+ ##[ napply (symmetric_eqc T1)
+ ##| napply (symmetric_eqc T2)
+ ##]
+ ##]
+nqed.
+
+unification hint 0 ≔ S1: comparable, S2: comparable;
+ T1 ≟ (carr S1), T2 ≟ (carr S2),
+ X ≟ (pair_is_comparable S1 S2)
+ (*********************************************) ⊢
+ carr X ≡ ProdT T1 T2.
+
+(* ********* *)
+(* TUPLE x 3 *)
+(* ********* *)
+
+nlemma triple_destruct_1 :
+∀T1,T2,T3.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.
+ triple T1 T2 T3 x1 y1 z1 = triple T1 T2 T3 x2 y2 z2 → x1 = x2.
+ #T1; #T2; #T3; #x1; #x2; #y1; #y2; #z1; #z2; #H;
+ nchange with (match triple T1 T2 T3 x2 y2 z2 with [ triple a _ _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma triple_destruct_2 :
+∀T1,T2,T3.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.
+ triple T1 T2 T3 x1 y1 z1 = triple T1 T2 T3 x2 y2 z2 → y1 = y2.
+ #T1; #T2; #T3; #x1; #x2; #y1; #y2; #z1; #z2; #H;
+ nchange with (match triple T1 T2 T3 x2 y2 z2 with [ triple _ b _ ⇒ y1 = b ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma triple_destruct_3 :
+∀T1,T2,T3.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.
+ triple T1 T2 T3 x1 y1 z1 = triple T1 T2 T3 x2 y2 z2 → z1 = z2.
+ #T1; #T2; #T3; #x1; #x2; #y1; #y2; #z1; #z2; #H;
+ nchange with (match triple T1 T2 T3 x2 y2 z2 with [ triple _ _ c ⇒ z1 = c ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_eqtriple :
+∀T1,T2,T3:Type.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.
+ (symmetricT T1 bool f1) →
+ (symmetricT T2 bool f2) →
+ (symmetricT T3 bool f3) →
+ (∀p1,p2:Prod3T T1 T2 T3.
+ (eq_triple T1 T2 T3 f1 f2 f3 p1 p2 = eq_triple T1 T2 T3 f1 f2 f3 p2 p1)).
+ #T1; #T2; #T3; #f1; #f2; #f3; #H; #H1; #H2;
+ #p1; nelim p1; #x1; #y1; #z1;
+ #p2; nelim p2; #x2; #y2; #z2;
+ nnormalize;
+ nrewrite > (H x1 x2);
+ ncases (f1 x2 x1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H1 y1 y2);
+ ncases (f2 y2 y1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H2 z1 z2); napply refl_eq
+ ##| ##2: napply refl_eq
+ ##]
+ ##| ##2: napply refl_eq
+ ##]
+nqed.
+
+nlemma eq_to_eqtriple :
+∀T1,T2,T3.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.
+ (∀x1,x2:T1.x1 = x2 → f1 x1 x2 = true) →
+ (∀y1,y2:T2.y1 = y2 → f2 y1 y2 = true) →
+ (∀z1,z2:T3.z1 = z2 → f3 z1 z2 = true) →
+ (∀p1,p2:Prod3T T1 T2 T3.
+ (p1 = p2 → eq_triple T1 T2 T3 f1 f2 f3 p1 p2 = true)).
+ #T1; #T2; #T3; #f1; #f2; #f3; #H1; #H2; #H3;
+ #p1; nelim p1; #x1; #y1; #z1;
+ #p2; nelim p2; #x2; #y2; #z2; #H;
+ nnormalize;
+ nrewrite > (H1 … (triple_destruct_1 … H));
+ nnormalize;
+ nrewrite > (H2 … (triple_destruct_2 … H));
+ nnormalize;
+ nrewrite > (H3 … (triple_destruct_3 … H));
+ napply refl_eq.
+nqed.
+
+nlemma eqtriple_to_eq :
+∀T1,T2,T3.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.
+ (∀x1,x2:T1.f1 x1 x2 = true → x1 = x2) →
+ (∀y1,y2:T2.f2 y1 y2 = true → y1 = y2) →
+ (∀z1,z2:T3.f3 z1 z2 = true → z1 = z2) →
+ (∀p1,p2:Prod3T T1 T2 T3.
+ (eq_triple T1 T2 T3 f1 f2 f3 p1 p2 = true → p1 = p2)).
+ #T1; #T2; #T3; #f1; #f2; #f3; #H1; #H2; #H3;
+ #p1; nelim p1; #x1; #y1; #z1;
+ #p2; nelim p2; #x2; #y2; #z2; #H;
+ nnormalize in H:(%);
+ nletin K ≝ (H1 x1 x2);
+ ncases (f1 x1 x2) in H:(%) K:(%);
+ nnormalize;
+ ##[ ##2: #H4; ndestruct (*napply (bool_destruct … H4)*) ##]
+ nletin K1 ≝ (H2 y1 y2);
+ ncases (f2 y1 y2) in K1:(%) ⊢ %;
+ nnormalize;
+ ##[ ##2: #H4; #H5; ndestruct (*napply (bool_destruct … H5)*) ##]
+ #H4; #H5; #H6;
+ nrewrite > (H4 (refl_eq …));
+ nrewrite > (H6 (refl_eq …));
+ nrewrite > (H3 z1 z2 H5);
+ napply refl_eq.
+nqed.
+
+nlemma decidable_triple :
+∀T1,T2,T3.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x,y:Prod3T T1 T2 T3.decidable (x = y)).
+ #T1; #T2; #T3; #H; #H1; #H2;
+ #x; nelim x; #xx1; #xx2; #xx3;
+ #y; nelim y; #yy1; #yy2; #yy3;
+ nnormalize;
+ napply (or2_elim (xx1 = yy1) (xx1 ≠ yy1) ? (H xx1 yy1) ?);
+ ##[ ##2: #H3; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H4; napply (H3 (triple_destruct_1 T1 T2 T3 … H4))
+ ##| ##1: #H3; napply (or2_elim (xx2 = yy2) (xx2 ≠ yy2) ? (H1 xx2 yy2) ?);
+ ##[ ##2: #H4; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H5; napply (H4 (triple_destruct_2 T1 T2 T3 … H5))
+ ##| ##1: #H4; napply (or2_elim (xx3 = yy3) (xx3 ≠ yy3) ? (H2 xx3 yy3) ?);
+ ##[ ##2: #H5; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H6; napply (H5 (triple_destruct_3 T1 T2 T3 … H6))
+ ##| ##1: #H5; napply (or2_intro1 (? = ?) (? ≠ ?) ?);
+ nrewrite > H3;
+ nrewrite > H4;
+ nrewrite > H5;
+ napply refl_eq
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neqtriple_to_neq :
+∀T1,T2,T3.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.
+ (∀x,y:T1.f1 x y = false → x ≠ y) →
+ (∀x,y:T2.f2 x y = false → x ≠ y) →
+ (∀x,y:T3.f3 x y = false → x ≠ y) →
+ (∀p1,p2:Prod3T T1 T2 T3.
+ (eq_triple T1 T2 T3 f1 f2 f3 p1 p2 = false → p1 ≠ p2)).
+ #T1; #T2; #T3; #f1; #f2; #f3; #H1; #H2; #H3;
+ #p1; nelim p1; #x1; #y1; #z1;
+ #p2; nelim p2; #x2; #y2; #z2;
+ nchange with ((((f1 x1 x2) ⊗ (f2 y1 y2) ⊗ (f3 z1 z2)) = false) → ?); #H;
+ nnormalize; #H4;
+ napply (or3_elim ((f1 x1 x2) = false) ((f2 y1 y2) = false) ((f3 z1 z2) = false) ? (andb_false3 … H) ?);
+ ##[ ##1: #H5; napply (H1 x1 x2 H5); napply (triple_destruct_1 T1 T2 T3 … H4)
+ ##| ##2: #H5; napply (H2 y1 y2 H5); napply (triple_destruct_2 T1 T2 T3 … H4)
+ ##| ##3: #H5; napply (H3 z1 z2 H5); napply (triple_destruct_3 T1 T2 T3 … H4)
+ ##]
+nqed.
+
+nlemma triple_destruct :
+∀T1,T2,T3.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.
+ (triple T1 T2 T3 x1 y1 z1) ≠ (triple T1 T2 T3 x2 y2 z2) →
+ Or3 (x1 ≠ x2) (y1 ≠ y2) (z1 ≠ z2)).
+ #T1; #T2; #T3; #H1; #H2; #H3; #x1; #x2; #y1; #y2; #z1; #z2;
+ nnormalize; #H;
+ napply (or2_elim (x1 = x2) (x1 ≠ x2) ? (H1 x1 x2) ?);
+ ##[ ##2: #H4; napply (or3_intro1 … H4)
+ ##| ##1: #H4; napply (or2_elim (y1 = y2) (y1 ≠ y2) ? (H2 y1 y2) ?);
+ ##[ ##2: #H5; napply (or3_intro2 … H5)
+ ##| ##1: #H5; napply (or2_elim (z1 = z2) (z1 ≠ z2) ? (H3 z1 z2) ?);
+ ##[ ##2: #H6; napply (or3_intro3 … H6)
+ ##| ##1: #H6; nrewrite > H4 in H:(%);
+ nrewrite > H5;
+ nrewrite > H6; #H; nelim (H (refl_eq …))
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqtriple :
+∀T1,T2,T3.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x,y:T1.x ≠ y → f1 x y = false) →
+ (∀x,y:T2.x ≠ y → f2 x y = false) →
+ (∀x,y:T3.x ≠ y → f3 x y = false) →
+ (∀p1,p2:Prod3T T1 T2 T3.
+ (p1 ≠ p2 → eq_triple T1 T2 T3 f1 f2 f3 p1 p2 = false)).
+ #T1; #T2; #T3; #f1; #f2; #f3; #H1; #H2; #H3; #H4; #H5; #H6;
+ #p1; nelim p1; #x1; #y1; #z1;
+ #p2; nelim p2; #x2; #y2; #z2; #H;
+ nchange with (((f1 x1 x2) ⊗ (f2 y1 y2) ⊗ (f3 z1 z2)) = false);
+ napply (or3_elim (x1 ≠ x2) (y1 ≠ y2) (z1 ≠ z2) ? (triple_destruct T1 T2 T3 H1 H2 H3 … H) ?);
+ ##[ ##1: #H7; nrewrite > (H4 … H7); nrewrite > (andb_false3_1 (f2 y1 y2) (f3 z1 z2)); napply refl_eq
+ ##| ##2: #H7; nrewrite > (H5 … H7); nrewrite > (andb_false3_2 (f1 x1 x2) (f3 z1 z2)); napply refl_eq
+ ##| ##3: #H7; nrewrite > (H6 … H7); nrewrite > (andb_false3_3 (f1 x1 x2) (f2 y1 y2)); napply refl_eq
+ ##]
+nqed.
+
+nlemma triple_is_comparable :
+ comparable → comparable → comparable → comparable.
+ #T1; #T2; #T3; napply (mk_comparable (Prod3T T1 T2 T3));
+ ##[ napply (triple … (zeroc T1) (zeroc T2) (zeroc T3))
+ ##| napply (λx.false)
+ ##| napply (eq_triple … (eqc T1) (eqc T2) (eqc T3))
+ ##| napply (eqtriple_to_eq … (eqc T1) (eqc T2) (eqc T3));
+ ##[ napply (eqc_to_eq T1)
+ ##| napply (eqc_to_eq T2)
+ ##| napply (eqc_to_eq T3)
+ ##]
+ ##| napply (eq_to_eqtriple … (eqc T1) (eqc T2) (eqc T3));
+ ##[ napply (eq_to_eqc T1)
+ ##| napply (eq_to_eqc T2)
+ ##| napply (eq_to_eqc T3)
+ ##]
+ ##| napply (neqtriple_to_neq … (eqc T1) (eqc T2) (eqc T3));
+ ##[ napply (neqc_to_neq T1)
+ ##| napply (neqc_to_neq T2)
+ ##| napply (neqc_to_neq T3)
+ ##]
+ ##| napply (neq_to_neqtriple … (eqc T1) (eqc T2) (eqc T3));
+ ##[ napply (decidable_c T1)
+ ##| napply (decidable_c T2)
+ ##| napply (decidable_c T3)
+ ##| napply (neq_to_neqc T1)
+ ##| napply (neq_to_neqc T2)
+ ##| napply (neq_to_neqc T3)
+ ##]
+ ##| napply decidable_triple;
+ ##[ napply (decidable_c T1)
+ ##| napply (decidable_c T2)
+ ##| napply (decidable_c T3)
+ ##]
+ ##| napply symmetric_eqtriple;
+ ##[ napply (symmetric_eqc T1)
+ ##| napply (symmetric_eqc T2)
+ ##| napply (symmetric_eqc T3)
+ ##]
+ ##]
+nqed.
+
+unification hint 0 ≔ S1: comparable, S2: comparable, S3: comparable;
+ T1 ≟ (carr S1), T2 ≟ (carr S2), T3 ≟ (carr S3),
+ X ≟ (triple_is_comparable S1 S2 S3)
+ (*********************************************) ⊢
+ carr X ≡ Prod3T T1 T2 T3.
+
+(* ********* *)
+(* TUPLE x 4 *)
+(* ********* *)
+
+nlemma quadruple_destruct_1 :
+∀T1,T2,T3,T4.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.
+ quadruple T1 T2 T3 T4 x1 y1 z1 v1 = quadruple T1 T2 T3 T4 x2 y2 z2 v2 → x1 = x2.
+ #T1; #T2; #T3; #T4; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #H;
+ nchange with (match quadruple T1 T2 T3 T4 x2 y2 z2 v2 with [ quadruple a _ _ _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma quadruple_destruct_2 :
+∀T1,T2,T3,T4.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.
+ quadruple T1 T2 T3 T4 x1 y1 z1 v1 = quadruple T1 T2 T3 T4 x2 y2 z2 v2 → y1 = y2.
+ #T1; #T2; #T3; #T4; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #H;
+ nchange with (match quadruple T1 T2 T3 T4 x2 y2 z2 v2 with [ quadruple _ b _ _ ⇒ y1 = b ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma quadruple_destruct_3 :
+∀T1,T2,T3,T4.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.
+ quadruple T1 T2 T3 T4 x1 y1 z1 v1 = quadruple T1 T2 T3 T4 x2 y2 z2 v2 → z1 = z2.
+ #T1; #T2; #T3; #T4; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #H;
+ nchange with (match quadruple T1 T2 T3 T4 x2 y2 z2 v2 with [ quadruple _ _ c _ ⇒ z1 = c ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma quadruple_destruct_4 :
+∀T1,T2,T3,T4.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.
+ quadruple T1 T2 T3 T4 x1 y1 z1 v1 = quadruple T1 T2 T3 T4 x2 y2 z2 v2 → v1 = v2.
+ #T1; #T2; #T3; #T4; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #H;
+ nchange with (match quadruple T1 T2 T3 T4 x2 y2 z2 v2 with [ quadruple _ _ _ d ⇒ v1 = d ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_eqquadruple :
+∀T1,T2,T3,T4:Type.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.
+ (symmetricT T1 bool f1) →
+ (symmetricT T2 bool f2) →
+ (symmetricT T3 bool f3) →
+ (symmetricT T4 bool f4) →
+ (∀p1,p2:Prod4T T1 T2 T3 T4.
+ (eq_quadruple T1 T2 T3 T4 f1 f2 f3 f4 p1 p2 = eq_quadruple T1 T2 T3 T4 f1 f2 f3 f4 p2 p1)).
+ #T1; #T2; #T3; #T4; #f1; #f2; #f3; #f4; #H; #H1; #H2; #H3;
+ #p1; nelim p1; #x1; #y1; #z1; #v1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2;
+ nnormalize;
+ nrewrite > (H x1 x2);
+ ncases (f1 x2 x1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H1 y1 y2);
+ ncases (f2 y2 y1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H2 z1 z2);
+ ncases (f3 z2 z1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H3 v1 v2); napply refl_eq
+ ##| ##2: napply refl_eq
+ ##]
+ ##| ##2: napply refl_eq
+ ##]
+ ##| ##2: napply refl_eq
+ ##]
+nqed.
+
+nlemma eq_to_eqquadruple :
+∀T1,T2,T3,T4.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.
+ (∀x,y:T1.x = y → f1 x y = true) →
+ (∀x,y:T2.x = y → f2 x y = true) →
+ (∀x,y:T3.x = y → f3 x y = true) →
+ (∀x,y:T4.x = y → f4 x y = true) →
+ (∀p1,p2:Prod4T T1 T2 T3 T4.
+ (p1 = p2 → eq_quadruple T1 T2 T3 T4 f1 f2 f3 f4 p1 p2 = true)).
+ #T1; #T2; #T3; #T4; #f1; #f2; #f3; #f4; #H1; #H2; #H3; #H4;
+ #p1; nelim p1; #x1; #y1; #z1; #v1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2; #H;
+ nnormalize;
+ nrewrite > (H1 … (quadruple_destruct_1 … H));
+ nnormalize;
+ nrewrite > (H2 … (quadruple_destruct_2 … H));
+ nnormalize;
+ nrewrite > (H3 … (quadruple_destruct_3 … H));
+ nnormalize;
+ nrewrite > (H4 … (quadruple_destruct_4 … H));
+ napply refl_eq.
+nqed.
+
+nlemma eqquadruple_to_eq :
+∀T1,T2,T3,T4.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.
+ (∀x,y:T1.f1 x y = true → x = y) →
+ (∀x,y:T2.f2 x y = true → x = y) →
+ (∀x,y:T3.f3 x y = true → x = y) →
+ (∀x,y:T4.f4 x y = true → x = y) →
+ (∀p1,p2:Prod4T T1 T2 T3 T4.
+ (eq_quadruple T1 T2 T3 T4 f1 f2 f3 f4 p1 p2 = true → p1 = p2)).
+ #T1; #T2; #T3; #T4; #f1; #f2; #f3; #f4; #H1; #H2; #H3; #H4;
+ #p1; nelim p1; #x1; #y1; #z1; #v1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2; #H;
+ nnormalize in H:(%);
+ nletin K ≝ (H1 x1 x2);
+ ncases (f1 x1 x2) in H:(%) K:(%);
+ nnormalize;
+ ##[ ##2: #H5; ndestruct (*napply (bool_destruct … H5)*) ##]
+ nletin K1 ≝ (H2 y1 y2);
+ ncases (f2 y1 y2) in K1:(%) ⊢ %;
+ nnormalize;
+ ##[ ##2: #H5; #H6; ndestruct (*napply (bool_destruct … H6)*) ##]
+ nletin K2 ≝ (H3 z1 z2);
+ ncases (f3 z1 z2) in K2:(%) ⊢ %;
+ nnormalize;
+ ##[ ##2: #H5; #H6; #H7; ndestruct (*napply (bool_destruct … H7)*) ##]
+ #H5; #H6; #H7; #H8;
+ nrewrite > (H5 (refl_eq …));
+ nrewrite > (H6 (refl_eq …));
+ nrewrite > (H8 (refl_eq …));
+ nrewrite > (H4 v1 v2 H7);
+ napply refl_eq.
+nqed.
+
+nlemma decidable_quadruple :
+∀T1,T2,T3,T4.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x,y:T4.decidable (x = y)) →
+ (∀x,y:Prod4T T1 T2 T3 T4.decidable (x = y)).
+ #T1; #T2; #T3; #T4; #H; #H1; #H2; #H3;
+ #x; nelim x; #xx1; #xx2; #xx3; #xx4;
+ #y; nelim y; #yy1; #yy2; #yy3; #yy4;
+ nnormalize;
+ napply (or2_elim (xx1 = yy1) (xx1 ≠ yy1) ? (H xx1 yy1) ?);
+ ##[ ##2: #H4; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H5; napply (H4 (quadruple_destruct_1 T1 T2 T3 T4 … H5))
+ ##| ##1: #H4; napply (or2_elim (xx2 = yy2) (xx2 ≠ yy2) ? (H1 xx2 yy2) ?);
+ ##[ ##2: #H5; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H6; napply (H5 (quadruple_destruct_2 T1 T2 T3 T4 … H6))
+ ##| ##1: #H5; napply (or2_elim (xx3 = yy3) (xx3 ≠ yy3) ? (H2 xx3 yy3) ?);
+ ##[ ##2: #H6; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H7; napply (H6 (quadruple_destruct_3 T1 T2 T3 T4 … H7))
+ ##| ##1: #H6; napply (or2_elim (xx4 = yy4) (xx4 ≠ yy4) ? (H3 xx4 yy4) ?);
+ ##[ ##2: #H7; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H8; napply (H7 (quadruple_destruct_4 T1 T2 T3 T4 … H8))
+ ##| ##1: #H7; napply (or2_intro1 (? = ?) (? ≠ ?) ?);
+ nrewrite > H4;
+ nrewrite > H5;
+ nrewrite > H6;
+ nrewrite > H7;
+ napply refl_eq
+ ##]
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neqquadruple_to_neq :
+∀T1,T2,T3,T4.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.
+ (∀x,y:T1.f1 x y = false → x ≠ y) →
+ (∀x,y:T2.f2 x y = false → x ≠ y) →
+ (∀x,y:T3.f3 x y = false → x ≠ y) →
+ (∀x,y:T4.f4 x y = false → x ≠ y) →
+ (∀p1,p2:Prod4T T1 T2 T3 T4.
+ (eq_quadruple T1 T2 T3 T4 f1 f2 f3 f4 p1 p2 = false → p1 ≠ p2)).
+ #T1; #T2; #T3; #T4; #f1; #f2; #f3; #f4; #H1; #H2; #H3; #H4;
+ #p1; nelim p1; #x1; #y1; #z1; #v1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2;
+ nchange with ((((f1 x1 x2) ⊗ (f2 y1 y2) ⊗ (f3 z1 z2) ⊗ (f4 v1 v2)) = false) → ?); #H;
+ nnormalize; #H5;
+ napply (or4_elim ((f1 x1 x2) = false) ((f2 y1 y2) = false) ((f3 z1 z2) = false) ((f4 v1 v2) = false) ? (andb_false4 … H) ?);
+ ##[ ##1: #H6; napply (H1 x1 x2 H6); napply (quadruple_destruct_1 T1 T2 T3 T4 … H5)
+ ##| ##2: #H6; napply (H2 y1 y2 H6); napply (quadruple_destruct_2 T1 T2 T3 T4 … H5)
+ ##| ##3: #H6; napply (H3 z1 z2 H6); napply (quadruple_destruct_3 T1 T2 T3 T4 … H5)
+ ##| ##4: #H6; napply (H4 v1 v2 H6); napply (quadruple_destruct_4 T1 T2 T3 T4 … H5)
+ ##]
+nqed.
+
+nlemma quadruple_destruct :
+∀T1,T2,T3,T4.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x,y:T4.decidable (x = y)) →
+ (∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.
+ (quadruple T1 T2 T3 T4 x1 y1 z1 v1) ≠ (quadruple T1 T2 T3 T4 x2 y2 z2 v2) →
+ Or4 (x1 ≠ x2) (y1 ≠ y2) (z1 ≠ z2) (v1 ≠ v2)).
+ #T1; #T2; #T3; #T4; #H1; #H2; #H3; #H4;
+ #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2;
+ nnormalize; #H;
+ napply (or2_elim (x1 = x2) (x1 ≠ x2) ? (H1 x1 x2) ?);
+ ##[ ##2: #H5; napply (or4_intro1 … H5)
+ ##| ##1: #H5; napply (or2_elim (y1 = y2) (y1 ≠ y2) ? (H2 y1 y2) ?);
+ ##[ ##2: #H6; napply (or4_intro2 … H6)
+ ##| ##1: #H6; napply (or2_elim (z1 = z2) (z1 ≠ z2) ? (H3 z1 z2) ?);
+ ##[ ##2: #H7; napply (or4_intro3 … H7)
+ ##| ##1: #H7; napply (or2_elim (v1 = v2) (v1 ≠ v2) ? (H4 v1 v2) ?);
+ ##[ ##2: #H8; napply (or4_intro4 … H8)
+ ##| ##1: #H8; nrewrite > H5 in H:(%);
+ nrewrite > H6;
+ nrewrite > H7;
+ nrewrite > H8; #H; nelim (H (refl_eq …))
+ ##]
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqquadruple :
+∀T1,T2,T3,T4.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x,y:T4.decidable (x = y)) →
+ (∀x,y:T1.x ≠ y → f1 x y = false) →
+ (∀x,y:T2.x ≠ y → f2 x y = false) →
+ (∀x,y:T3.x ≠ y → f3 x y = false) →
+ (∀x,y:T4.x ≠ y → f4 x y = false) →
+ (∀p1,p2:Prod4T T1 T2 T3 T4.
+ (p1 ≠ p2 → eq_quadruple T1 T2 T3 T4 f1 f2 f3 f4 p1 p2 = false)).
+ #T1; #T2; #T3; #T4; #f1; #f2; #f3; #f4; #H1; #H2; #H3; #H4; #H5; #H6; #H7; #H8;
+ #p1; nelim p1; #x1; #y1; #z1; #v1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2; #H;
+ nchange with (((f1 x1 x2) ⊗ (f2 y1 y2) ⊗ (f3 z1 z2) ⊗ (f4 v1 v2)) = false);
+ napply (or4_elim (x1 ≠ x2) (y1 ≠ y2) (z1 ≠ z2) (v1 ≠ v2) ? (quadruple_destruct T1 T2 T3 T4 H1 H2 H3 H4 … H) ?);
+ ##[ ##1: #H9; nrewrite > (H5 … H9); nrewrite > (andb_false4_1 (f2 y1 y2) (f3 z1 z2) (f4 v1 v2)); napply refl_eq
+ ##| ##2: #H9; nrewrite > (H6 … H9); nrewrite > (andb_false4_2 (f1 x1 x2) (f3 z1 z2) (f4 v1 v2)); napply refl_eq
+ ##| ##3: #H9; nrewrite > (H7 … H9); nrewrite > (andb_false4_3 (f1 x1 x2) (f2 y1 y2) (f4 v1 v2)); napply refl_eq
+ ##| ##4: #H9; nrewrite > (H8 … H9); nrewrite > (andb_false4_4 (f1 x1 x2) (f2 y1 y2) (f3 z1 z2)); napply refl_eq
+ ##]
+nqed.
+
+nlemma quadruple_is_comparable :
+ comparable → comparable → comparable → comparable → comparable.
+ #T1; #T2; #T3; #T4; napply (mk_comparable (Prod4T T1 T2 T3 T4));
+ ##[ napply (quadruple … (zeroc T1) (zeroc T2) (zeroc T3) (zeroc T4))
+ ##| napply (λx.false)
+ ##| napply (eq_quadruple … (eqc T1) (eqc T2) (eqc T3) (eqc T4))
+ ##| napply (eqquadruple_to_eq … (eqc T1) (eqc T2) (eqc T3) (eqc T4));
+ ##[ napply (eqc_to_eq T1)
+ ##| napply (eqc_to_eq T2)
+ ##| napply (eqc_to_eq T3)
+ ##| napply (eqc_to_eq T4)
+ ##]
+ ##| napply (eq_to_eqquadruple … (eqc T1) (eqc T2) (eqc T3) (eqc T4));
+ ##[ napply (eq_to_eqc T1)
+ ##| napply (eq_to_eqc T2)
+ ##| napply (eq_to_eqc T3)
+ ##| napply (eq_to_eqc T4)
+ ##]
+ ##| napply (neqquadruple_to_neq … (eqc T1) (eqc T2) (eqc T3) (eqc T4));
+ ##[ napply (neqc_to_neq T1)
+ ##| napply (neqc_to_neq T2)
+ ##| napply (neqc_to_neq T3)
+ ##| napply (neqc_to_neq T4)
+ ##]
+ ##| napply (neq_to_neqquadruple … (eqc T1) (eqc T2) (eqc T3) (eqc T4));
+ ##[ napply (decidable_c T1)
+ ##| napply (decidable_c T2)
+ ##| napply (decidable_c T3)
+ ##| napply (decidable_c T4)
+ ##| napply (neq_to_neqc T1)
+ ##| napply (neq_to_neqc T2)
+ ##| napply (neq_to_neqc T3)
+ ##| napply (neq_to_neqc T4)
+ ##]
+ ##| napply decidable_quadruple;
+ ##[ napply (decidable_c T1)
+ ##| napply (decidable_c T2)
+ ##| napply (decidable_c T3)
+ ##| napply (decidable_c T4)
+ ##]
+ ##| napply symmetric_eqquadruple;
+ ##[ napply (symmetric_eqc T1)
+ ##| napply (symmetric_eqc T2)
+ ##| napply (symmetric_eqc T3)
+ ##| napply (symmetric_eqc T4)
+ ##]
+ ##]
+nqed.
+
+unification hint 0 ≔ S1: comparable, S2: comparable, S3: comparable, S4: comparable;
+ T1 ≟ (carr S1), T2 ≟ (carr S2), T3 ≟ (carr S3), T4 ≟ (carr S4),
+ X ≟ (quadruple_is_comparable S1 S2 S3 S4)
+ (*********************************************) ⊢
+ carr X ≡ Prod4T T1 T2 T3 T4.
+
+(* ********* *)
+(* TUPLE x 5 *)
+(* ********* *)
+
+nlemma quintuple_destruct_1 :
+∀T1,T2,T3,T4,T5.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.∀w1,w2:T5.
+ quintuple T1 T2 T3 T4 T5 x1 y1 z1 v1 w1 = quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 → x1 = x2.
+ #T1; #T2; #T3; #T4; #T5; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #w1; #w2; #H;
+ nchange with (match quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 with [ quintuple a _ _ _ _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma quintuple_destruct_2 :
+∀T1,T2,T3,T4,T5.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.∀w1,w2:T5.
+ quintuple T1 T2 T3 T4 T5 x1 y1 z1 v1 w1 = quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 → y1 = y2.
+ #T1; #T2; #T3; #T4; #T5; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #w1; #w2; #H;
+ nchange with (match quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 with [ quintuple _ b _ _ _ ⇒ y1 = b ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma quintuple_destruct_3 :
+∀T1,T2,T3,T4,T5.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.∀w1,w2:T5.
+ quintuple T1 T2 T3 T4 T5 x1 y1 z1 v1 w1 = quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 → z1 = z2.
+ #T1; #T2; #T3; #T4; #T5; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #w1; #w2; #H;
+ nchange with (match quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 with [ quintuple _ _ c _ _ ⇒ z1 = c ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma quintuple_destruct_4 :
+∀T1,T2,T3,T4,T5.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.∀w1,w2:T5.
+ quintuple T1 T2 T3 T4 T5 x1 y1 z1 v1 w1 = quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 → v1 = v2.
+ #T1; #T2; #T3; #T4; #T5; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #w1; #w2; #H;
+ nchange with (match quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 with [ quintuple _ _ _ d _ ⇒ v1 = d ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma quintuple_destruct_5 :
+∀T1,T2,T3,T4,T5.∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.∀w1,w2:T5.
+ quintuple T1 T2 T3 T4 T5 x1 y1 z1 v1 w1 = quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 → w1 = w2.
+ #T1; #T2; #T3; #T4; #T5; #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #w1; #w2; #H;
+ nchange with (match quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2 with [ quintuple _ _ _ _ e ⇒ w1 = e ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_eqquintuple :
+∀T1,T2,T3,T4,T5:Type.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.∀f5:T5 → T5 → bool.
+ (symmetricT T1 bool f1) →
+ (symmetricT T2 bool f2) →
+ (symmetricT T3 bool f3) →
+ (symmetricT T4 bool f4) →
+ (symmetricT T5 bool f5) →
+ (∀p1,p2:Prod5T T1 T2 T3 T4 T5.
+ (eq_quintuple T1 T2 T3 T4 T5 f1 f2 f3 f4 f5 p1 p2 = eq_quintuple T1 T2 T3 T4 T5 f1 f2 f3 f4 f5 p2 p1)).
+ #T1; #T2; #T3; #T4; #T5; #f1; #f2; #f3; #f4; #f5; #H; #H1; #H2; #H3; #H4;
+ #p1; nelim p1; #x1; #y1; #z1; #v1; #w1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2; #w2;
+ nnormalize;
+ nrewrite > (H x1 x2);
+ ncases (f1 x2 x1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H1 y1 y2);
+ ncases (f2 y2 y1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H2 z1 z2);
+ ncases (f3 z2 z1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H3 v1 v2);
+ ncases (f4 v2 v1);
+ nnormalize;
+ ##[ ##1: nrewrite > (H4 w1 w2); napply refl_eq
+ ##| ##2: napply refl_eq
+ ##]
+ ##| ##2: napply refl_eq
+ ##]
+ ##| ##2: napply refl_eq
+ ##]
+ ##| ##2: napply refl_eq
+ ##]
+nqed.
+
+nlemma eq_to_eqquintuple :
+∀T1,T2,T3,T4,T5.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.∀f5:T5 → T5 → bool.
+ (∀x,y:T1.x = y → f1 x y = true) →
+ (∀x,y:T2.x = y → f2 x y = true) →
+ (∀x,y:T3.x = y → f3 x y = true) →
+ (∀x,y:T4.x = y → f4 x y = true) →
+ (∀x,y:T5.x = y → f5 x y = true) →
+ (∀p1,p2:Prod5T T1 T2 T3 T4 T5.
+ (p1 = p2 → eq_quintuple T1 T2 T3 T4 T5 f1 f2 f3 f4 f5 p1 p2 = true)).
+ #T1; #T2; #T3; #T4; #T5; #f1; #f2; #f3; #f4; #f5; #H1; #H2; #H3; #H4; #H5;
+ #p1; nelim p1; #x1; #y1; #z1; #v1; #w1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2; #w2; #H;
+ nnormalize;
+ nrewrite > (H1 … (quintuple_destruct_1 … H));
+ nnormalize;
+ nrewrite > (H2 … (quintuple_destruct_2 … H));
+ nnormalize;
+ nrewrite > (H3 … (quintuple_destruct_3 … H));
+ nnormalize;
+ nrewrite > (H4 … (quintuple_destruct_4 … H));
+ nnormalize;
+ nrewrite > (H5 … (quintuple_destruct_5 … H));
+ napply refl_eq.
+nqed.
+
+nlemma eqquintuple_to_eq :
+∀T1,T2,T3,T4,T5.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.∀f5:T5 → T5 → bool.
+ (∀x,y:T1.f1 x y = true → x = y) →
+ (∀x,y:T2.f2 x y = true → x = y) →
+ (∀x,y:T3.f3 x y = true → x = y) →
+ (∀x,y:T4.f4 x y = true → x = y) →
+ (∀x,y:T5.f5 x y = true → x = y) →
+ (∀p1,p2:Prod5T T1 T2 T3 T4 T5.
+ (eq_quintuple T1 T2 T3 T4 T5 f1 f2 f3 f4 f5 p1 p2 = true → p1 = p2)).
+ #T1; #T2; #T3; #T4; #T5; #f1; #f2; #f3; #f4; #f5; #H1; #H2; #H3; #H4; #H5;
+ #p1; nelim p1; #x1; #y1; #z1; #v1; #w1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2; #w2; #H;
+ nnormalize in H:(%);
+ nletin K ≝ (H1 x1 x2);
+ ncases (f1 x1 x2) in H:(%) K:(%);
+ nnormalize;
+ ##[ ##2: #H6; ndestruct (*napply (bool_destruct … H6)*) ##]
+ nletin K1 ≝ (H2 y1 y2);
+ ncases (f2 y1 y2) in K1:(%) ⊢ %;
+ nnormalize;
+ ##[ ##2: #H6; #H7; ndestruct (*napply (bool_destruct … H7)*) ##]
+ nletin K2 ≝ (H3 z1 z2);
+ ncases (f3 z1 z2) in K2:(%) ⊢ %;
+ nnormalize;
+ ##[ ##2: #H6; #H7; #H8; ndestruct (*napply (bool_destruct … H8)*) ##]
+ nletin K3 ≝ (H4 v1 v2);
+ ncases (f4 v1 v2) in K3:(%) ⊢ %;
+ nnormalize;
+ ##[ ##2: #H6; #H7; #H8; #H9; ndestruct (*napply (bool_destruct … H9)*) ##]
+ #H6; #H7; #H8; #H9; #H10;
+ nrewrite > (H6 (refl_eq …));
+ nrewrite > (H7 (refl_eq …));
+ nrewrite > (H8 (refl_eq …));
+ nrewrite > (H10 (refl_eq …));
+ nrewrite > (H5 w1 w2 H9);
+ napply refl_eq.
+nqed.
+
+nlemma decidable_quintuple :
+∀T1,T2,T3,T4,T5.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x,y:T4.decidable (x = y)) →
+ (∀x,y:T5.decidable (x = y)) →
+ (∀x,y:Prod5T T1 T2 T3 T4 T5.decidable (x = y)).
+ #T1; #T2; #T3; #T4; #T5; #H; #H1; #H2; #H3; #H4;
+ #x; nelim x; #xx1; #xx2; #xx3; #xx4; #xx5;
+ #y; nelim y; #yy1; #yy2; #yy3; #yy4; #yy5;
+ nnormalize;
+ napply (or2_elim (xx1 = yy1) (xx1 ≠ yy1) ? (H xx1 yy1) ?);
+ ##[ ##2: #H5; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H6; napply (H5 (quintuple_destruct_1 T1 T2 T3 T4 T5 … H6))
+ ##| ##1: #H5; napply (or2_elim (xx2 = yy2) (xx2 ≠ yy2) ? (H1 xx2 yy2) ?);
+ ##[ ##2: #H6; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H7; napply (H6 (quintuple_destruct_2 T1 T2 T3 T4 T5 … H7))
+ ##| ##1: #H6; napply (or2_elim (xx3 = yy3) (xx3 ≠ yy3) ? (H2 xx3 yy3) ?);
+ ##[ ##2: #H7; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H8; napply (H7 (quintuple_destruct_3 T1 T2 T3 T4 T5 … H8))
+ ##| ##1: #H7; napply (or2_elim (xx4 = yy4) (xx4 ≠ yy4) ? (H3 xx4 yy4) ?);
+ ##[ ##2: #H8; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H9; napply (H8 (quintuple_destruct_4 T1 T2 T3 T4 T5 … H9))
+ ##| ##1: #H8; napply (or2_elim (xx5 = yy5) (xx5 ≠ yy5) ? (H4 xx5 yy5) ?);
+ ##[ ##2: #H9; napply (or2_intro2 (? = ?) (? ≠ ?) ?);
+ nnormalize; #H10; napply (H9 (quintuple_destruct_5 T1 T2 T3 T4 T5 … H10))
+ ##| ##1: #H9; napply (or2_intro1 (? = ?) (? ≠ ?) ?);
+ nrewrite > H5;
+ nrewrite > H6;
+ nrewrite > H7;
+ nrewrite > H8;
+ nrewrite > H9;
+ napply refl_eq
+ ##]
+ ##]
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neqquintuple_to_neq :
+∀T1,T2,T3,T4,T5.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.∀f5:T5 → T5 → bool.
+ (∀x,y:T1.f1 x y = false → x ≠ y) →
+ (∀x,y:T2.f2 x y = false → x ≠ y) →
+ (∀x,y:T3.f3 x y = false → x ≠ y) →
+ (∀x,y:T4.f4 x y = false → x ≠ y) →
+ (∀x,y:T5.f5 x y = false → x ≠ y) →
+ (∀p1,p2:Prod5T T1 T2 T3 T4 T5.
+ (eq_quintuple T1 T2 T3 T4 T5 f1 f2 f3 f4 f5 p1 p2 = false → p1 ≠ p2)).
+ #T1; #T2; #T3; #T4; #T5; #f1; #f2; #f3; #f4; #f5; #H1; #H2; #H3; #H4; #H5;
+ #p1; nelim p1; #x1; #y1; #z1; #v1; #w1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2; #w2;
+ nchange with ((((f1 x1 x2) ⊗ (f2 y1 y2) ⊗ (f3 z1 z2) ⊗ (f4 v1 v2) ⊗ (f5 w1 w2)) = false) → ?); #H;
+ nnormalize; #H6;
+ napply (or5_elim ((f1 x1 x2) = false) ((f2 y1 y2) = false) ((f3 z1 z2) = false) ((f4 v1 v2) = false) ((f5 w1 w2) = false) ? (andb_false5 … H) ?);
+ ##[ ##1: #H7; napply (H1 x1 x2 H7); napply (quintuple_destruct_1 T1 T2 T3 T4 T5 … H6)
+ ##| ##2: #H7; napply (H2 y1 y2 H7); napply (quintuple_destruct_2 T1 T2 T3 T4 T5 … H6)
+ ##| ##3: #H7; napply (H3 z1 z2 H7); napply (quintuple_destruct_3 T1 T2 T3 T4 T5 … H6)
+ ##| ##4: #H7; napply (H4 v1 v2 H7); napply (quintuple_destruct_4 T1 T2 T3 T4 T5 … H6)
+ ##| ##5: #H7; napply (H5 w1 w2 H7); napply (quintuple_destruct_5 T1 T2 T3 T4 T5 … H6)
+ ##]
+nqed.
+
+nlemma quintuple_destruct :
+∀T1,T2,T3,T4,T5.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x,y:T4.decidable (x = y)) →
+ (∀x,y:T5.decidable (x = y)) →
+ (∀x1,x2:T1.∀y1,y2:T2.∀z1,z2:T3.∀v1,v2:T4.∀w1,w2:T5.
+ (quintuple T1 T2 T3 T4 T5 x1 y1 z1 v1 w1) ≠ (quintuple T1 T2 T3 T4 T5 x2 y2 z2 v2 w2) →
+ Or5 (x1 ≠ x2) (y1 ≠ y2) (z1 ≠ z2) (v1 ≠ v2) (w1 ≠ w2)).
+ #T1; #T2; #T3; #T4; #T5; #H1; #H2; #H3; #H4; #H5;
+ #x1; #x2; #y1; #y2; #z1; #z2; #v1; #v2; #w1; #w2;
+ nnormalize; #H;
+ napply (or2_elim (x1 = x2) (x1 ≠ x2) ? (H1 x1 x2) ?);
+ ##[ ##2: #H6; napply (or5_intro1 … H6)
+ ##| ##1: #H6; napply (or2_elim (y1 = y2) (y1 ≠ y2) ? (H2 y1 y2) ?);
+ ##[ ##2: #H7; napply (or5_intro2 … H7)
+ ##| ##1: #H7; napply (or2_elim (z1 = z2) (z1 ≠ z2) ? (H3 z1 z2) ?);
+ ##[ ##2: #H8; napply (or5_intro3 … H8)
+ ##| ##1: #H8; napply (or2_elim (v1 = v2) (v1 ≠ v2) ? (H4 v1 v2) ?);
+ ##[ ##2: #H9; napply (or5_intro4 … H9)
+ ##| ##1: #H9; napply (or2_elim (w1 = w2) (w1 ≠ w2) ? (H5 w1 w2) ?);
+ ##[ ##2: #H10; napply (or5_intro5 … H10)
+ ##| ##1: #H10; nrewrite > H6 in H:(%);
+ nrewrite > H7;
+ nrewrite > H8;
+ nrewrite > H9;
+ nrewrite > H10; #H; nelim (H (refl_eq …))
+ ##]
+ ##]
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqquintuple :
+∀T1,T2,T3,T4,T5.
+∀f1:T1 → T1 → bool.∀f2:T2 → T2 → bool.∀f3:T3 → T3 → bool.∀f4:T4 → T4 → bool.∀f5:T5 → T5 → bool.
+ (∀x,y:T1.decidable (x = y)) →
+ (∀x,y:T2.decidable (x = y)) →
+ (∀x,y:T3.decidable (x = y)) →
+ (∀x,y:T4.decidable (x = y)) →
+ (∀x,y:T5.decidable (x = y)) →
+ (∀x,y:T1.x ≠ y → f1 x y = false) →
+ (∀x,y:T2.x ≠ y → f2 x y = false) →
+ (∀x,y:T3.x ≠ y → f3 x y = false) →
+ (∀x,y:T4.x ≠ y → f4 x y = false) →
+ (∀x,y:T5.x ≠ y → f5 x y = false) →
+ (∀p1,p2:Prod5T T1 T2 T3 T4 T5.
+ (p1 ≠ p2 → eq_quintuple T1 T2 T3 T4 T5 f1 f2 f3 f4 f5 p1 p2 = false)).
+ #T1; #T2; #T3; #T4; #T5; #f1; #f2; #f3; #f4; #f5;
+ #H1; #H2; #H3; #H4; #H5; #H6; #H7; #H8; #H9; #H10;
+ #p1; nelim p1; #x1; #y1; #z1; #v1; #w1;
+ #p2; nelim p2; #x2; #y2; #z2; #v2; #w2; #H;
+ nchange with (((f1 x1 x2) ⊗ (f2 y1 y2) ⊗ (f3 z1 z2) ⊗ (f4 v1 v2) ⊗ (f5 w1 w2)) = false);
+ napply (or5_elim (x1 ≠ x2) (y1 ≠ y2) (z1 ≠ z2) (v1 ≠ v2) (w1 ≠ w2) ? (quintuple_destruct T1 T2 T3 T4 T5 H1 H2 H3 H4 H5 … H) ?);
+ ##[ ##1: #H11; nrewrite > (H6 … H11); nrewrite > (andb_false5_1 (f2 y1 y2) (f3 z1 z2) (f4 v1 v2) (f5 w1 w2)); napply refl_eq
+ ##| ##2: #H11; nrewrite > (H7 … H11); nrewrite > (andb_false5_2 (f1 x1 x2) (f3 z1 z2) (f4 v1 v2) (f5 w1 w2)); napply refl_eq
+ ##| ##3: #H11; nrewrite > (H8 … H11); nrewrite > (andb_false5_3 (f1 x1 x2) (f2 y1 y2) (f4 v1 v2) (f5 w1 w2)); napply refl_eq
+ ##| ##4: #H11; nrewrite > (H9 … H11); nrewrite > (andb_false5_4 (f1 x1 x2) (f2 y1 y2) (f3 z1 z2) (f5 w1 w2)); napply refl_eq
+ ##| ##5: #H11; nrewrite > (H10 … H11); nrewrite > (andb_false5_5 (f1 x1 x2) (f2 y1 y2) (f3 z1 z2) (f4 v1 v2)); napply refl_eq
+ ##]
+nqed.
+
+nlemma quintuple_is_comparable :
+ comparable → comparable → comparable → comparable → comparable → comparable.
+ #T1; #T2; #T3; #T4; #T5; napply (mk_comparable (Prod5T T1 T2 T3 T4 T5));
+ ##[ napply (quintuple … (zeroc T1) (zeroc T2) (zeroc T3) (zeroc T4) (zeroc T5))
+ ##| napply (λx.false)
+ ##| napply (eq_quintuple … (eqc T1) (eqc T2) (eqc T3) (eqc T4) (eqc T5))
+ ##| napply (eqquintuple_to_eq … (eqc T1) (eqc T2) (eqc T3) (eqc T4) (eqc T5));
+ ##[ napply (eqc_to_eq T1)
+ ##| napply (eqc_to_eq T2)
+ ##| napply (eqc_to_eq T3)
+ ##| napply (eqc_to_eq T4)
+ ##| napply (eqc_to_eq T5)
+ ##]
+ ##| napply (eq_to_eqquintuple … (eqc T1) (eqc T2) (eqc T3) (eqc T4) (eqc T5));
+ ##[ napply (eq_to_eqc T1)
+ ##| napply (eq_to_eqc T2)
+ ##| napply (eq_to_eqc T3)
+ ##| napply (eq_to_eqc T4)
+ ##| napply (eq_to_eqc T5)
+ ##]
+ ##| napply (neqquintuple_to_neq … (eqc T1) (eqc T2) (eqc T3) (eqc T4) (eqc T5));
+ ##[ napply (neqc_to_neq T1)
+ ##| napply (neqc_to_neq T2)
+ ##| napply (neqc_to_neq T3)
+ ##| napply (neqc_to_neq T4)
+ ##| napply (neqc_to_neq T5)
+ ##]
+ ##| napply (neq_to_neqquintuple … (eqc T1) (eqc T2) (eqc T3) (eqc T4) (eqc T5));
+ ##[ napply (decidable_c T1)
+ ##| napply (decidable_c T2)
+ ##| napply (decidable_c T3)
+ ##| napply (decidable_c T4)
+ ##| napply (decidable_c T5)
+ ##| napply (neq_to_neqc T1)
+ ##| napply (neq_to_neqc T2)
+ ##| napply (neq_to_neqc T3)
+ ##| napply (neq_to_neqc T4)
+ ##| napply (neq_to_neqc T5)
+ ##]
+ ##| napply decidable_quintuple;
+ ##[ napply (decidable_c T1)
+ ##| napply (decidable_c T2)
+ ##| napply (decidable_c T3)
+ ##| napply (decidable_c T4)
+ ##| napply (decidable_c T5)
+ ##]
+ ##| napply symmetric_eqquintuple;
+ ##[ napply (symmetric_eqc T1)
+ ##| napply (symmetric_eqc T2)
+ ##| napply (symmetric_eqc T3)
+ ##| napply (symmetric_eqc T4)
+ ##| napply (symmetric_eqc T5)
+ ##]
+ ##]
+nqed.
+
+unification hint 0 ≔ S1: comparable, S2: comparable, S3: comparable, S4: comparable, S5: comparable;
+ T1 ≟ (carr S1), T2 ≟ (carr S2), T3 ≟ (carr S3), T4 ≟ (carr S4), T5 ≟ (carr S5),
+ X ≟ (quintuple_is_comparable S1 S2 S3 S4 S5)
+ (*********************************************) ⊢
+ carr X ≡ Prod5T T1 T2 T3 T4 T5.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/bool.ma".
+
+(* ***** *)
+(* TUPLE *)
+(* ***** *)
+
+ninductive ProdT (T1:Type) (T2:Type) : Type ≝
+ pair : T1 → T2 → ProdT T1 T2.
+
+ndefinition fst ≝
+λT1,T2:Type.λp:ProdT T1 T2.match p with [ pair x _ ⇒ x ].
+
+ndefinition snd ≝
+λT1,T2:Type.λp:ProdT T1 T2.match p with [ pair _ x ⇒ x ].
+
+ndefinition eq_pair ≝
+λT1,T2:Type.
+λf1:T1 → T1 → bool.λf2:T2 → T2 → bool.
+λp1,p2:ProdT T1 T2.
+ (f1 (fst … p1) (fst … p2)) ⊗
+ (f2 (snd … p1) (snd … p2)).
+
+ninductive Prod3T (T1:Type) (T2:Type) (T3:Type) : Type ≝
+triple : T1 → T2 → T3 → Prod3T T1 T2 T3.
+
+ndefinition fst3T ≝
+λT1.λT2.λT3.λp:Prod3T T1 T2 T3.match p with [ triple x _ _ ⇒ x ].
+
+ndefinition snd3T ≝
+λT1.λT2.λT3.λp:Prod3T T1 T2 T3.match p with [ triple _ x _ ⇒ x ].
+
+ndefinition thd3T ≝
+λT1.λT2.λT3.λp:Prod3T T1 T2 T3.match p with [ triple _ _ x ⇒ x ].
+
+ndefinition eq_triple ≝
+λT1,T2,T3:Type.
+λf1:T1 → T1 → bool.λf2:T2 → T2 → bool.λf3:T3 → T3 → bool.
+λp1,p2:Prod3T T1 T2 T3.
+ (f1 (fst3T … p1) (fst3T … p2)) ⊗
+ (f2 (snd3T … p1) (snd3T … p2)) ⊗
+ (f3 (thd3T … p1) (thd3T … p2)).
+
+ninductive Prod4T (T1:Type) (T2:Type) (T3:Type) (T4:Type) : Type ≝
+quadruple : T1 → T2 → T3 → T4 → Prod4T T1 T2 T3 T4.
+
+ndefinition fst4T ≝
+λT1.λT2.λT3.λT4.λp:Prod4T T1 T2 T3 T4.match p with [ quadruple x _ _ _ ⇒ x ].
+
+ndefinition snd4T ≝
+λT1.λT2.λT3.λT4.λp:Prod4T T1 T2 T3 T4.match p with [ quadruple _ x _ _ ⇒ x ].
+
+ndefinition thd4T ≝
+λT1.λT2.λT3.λT4.λp:Prod4T T1 T2 T3 T4.match p with [ quadruple _ _ x _ ⇒ x ].
+
+ndefinition fth4T ≝
+λT1.λT2.λT3.λT4.λp:Prod4T T1 T2 T3 T4.match p with [ quadruple _ _ _ x ⇒ x ].
+
+ndefinition eq_quadruple ≝
+λT1,T2,T3,T4:Type.
+λf1:T1 → T1 → bool.λf2:T2 → T2 → bool.λf3:T3 → T3 → bool.λf4:T4 → T4 → bool.
+λp1,p2:Prod4T T1 T2 T3 T4.
+ (f1 (fst4T … p1) (fst4T … p2)) ⊗
+ (f2 (snd4T … p1) (snd4T … p2)) ⊗
+ (f3 (thd4T … p1) (thd4T … p2)) ⊗
+ (f4 (fth4T … p1) (fth4T … p2)).
+
+ninductive Prod5T (T1:Type) (T2:Type) (T3:Type) (T4:Type) (T5:Type) : Type ≝
+quintuple : T1 → T2 → T3 → T4 → T5 → Prod5T T1 T2 T3 T4 T5.
+
+ndefinition fst5T ≝
+λT1.λT2.λT3.λT4.λT5.λp:Prod5T T1 T2 T3 T4 T5.match p with [ quintuple x _ _ _ _ ⇒ x ].
+
+ndefinition snd5T ≝
+λT1.λT2.λT3.λT4.λT5.λp:Prod5T T1 T2 T3 T4 T5.match p with [ quintuple _ x _ _ _ ⇒ x ].
+
+ndefinition thd5T ≝
+λT1.λT2.λT3.λT4.λT5.λp:Prod5T T1 T2 T3 T4 T5.match p with [ quintuple _ _ x _ _ ⇒ x ].
+
+ndefinition fth5T ≝
+λT1.λT2.λT3.λT4.λT5.λp:Prod5T T1 T2 T3 T4 T5.match p with [ quintuple _ _ _ x _ ⇒ x ].
+
+ndefinition fft5T ≝
+λT1.λT2.λT3.λT4.λT5.λp:Prod5T T1 T2 T3 T4 T5.match p with [ quintuple _ _ _ _ x ⇒ x ].
+
+ndefinition eq_quintuple ≝
+λT1,T2,T3,T4,T5:Type.
+λf1:T1 → T1 → bool.λf2:T2 → T2 → bool.λf3:T3 → T3 → bool.λf4:T4 → T4 → bool.λf5:T5 → T5 → bool.
+λp1,p2:Prod5T T1 T2 T3 T4 T5.
+ (f1 (fst5T … p1) (fst5T … p2)) ⊗
+ (f2 (snd5T … p1) (snd5T … p2)) ⊗
+ (f3 (thd5T … p1) (thd5T … p2)) ⊗
+ (f4 (fth5T … p1) (fth5T … p2)) ⊗
+ (f5 (fft5T … p1) (fft5T … p2)).
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| A.Asperti, C.Sacerdoti Coen, *)
+(* ||A|| E.Tassi, S.Zacchiroli *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU Lesser General Public License Version 2.1 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+universe constraint Type[0] < Type[1].
+universe constraint Type[1] < Type[2].
+universe constraint Type[2] < Type[3].
+universe constraint Type[3] < Type[4].
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/theory.ma".
+
+(* coppia dipendente *)
+
+ninductive sigma (A:Type) (P:A → Type) : Type ≝
+ sigma_intro: ∀x:A.P x → sigma A P.
+
+notation < "hvbox(\Sigma ident i opt (: tx) break . p)"
+ right associative with precedence 20
+for @{ 'Sigma ${default
+ @{\lambda ${ident i} : $tx. $p}
+ @{\lambda ${ident i} . $p}}}.
+
+notation > "\Sigma list1 ident x sep , opt (: T). term 19 Px"
+ with precedence 20
+ for ${ default
+ @{ ${ fold right @{$Px} rec acc @{'Sigma (λ${ident x}:$T.$acc)} } }
+ @{ ${ fold right @{$Px} rec acc @{'Sigma (λ${ident x}.$acc)} } }
+ }.
+
+notation "\ll term 19 a, break term 19 b \gg"
+with precedence 90 for @{'dependent_pair (λx:?.? x) $a $b}.
+interpretation "dependent pair" 'dependent_pair \eta.c a b = (sigma_intro ? c a b).
+
+interpretation "sigma" 'Sigma \eta.x = (sigma ? x).
+
+ndefinition sigmaFst ≝
+λT:Type.λf:T → Type.λs:sigma T f.match s with [ sigma_intro x _ ⇒ x ].
+ndefinition sigmaSnd ≝
+λT:Type.λf:T → Type.λs:sigma T f.match s return λs.f (sigmaFst ?? s) with [ sigma_intro _ x ⇒ x ].
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/ascii.ma".
+include "common/list.ma".
+
+(* ******* *)
+(* STRINGA *)
+(* ******* *)
+
+(* tipo pubblico *)
+ndefinition aux_str_type ≝ list ascii.
+
+unification hint 0 ≔ ⊢ carr (list_is_comparable ascii_is_comparable) ≡ list ascii.
+unification hint 0 ≔ ⊢ carr (list_is_comparable ascii_is_comparable) ≡ aux_str_type.
+
+(* ************ *)
+(* STRINGA + ID *)
+(* ************ *)
+
+(* tipo pubblico *)
+nrecord strId : Type ≝
+ {
+ str_elem: aux_str_type;
+ id_elem: nat
+ }.
+
+(* confronto *)
+ndefinition eq_strId ≝
+λsid,sid':strId.
+ (eqc ? (str_elem sid) (str_elem sid'))⊗
+ (eqc ? (id_elem sid) (id_elem sid')).
+
+nlemma strid_destruct_1 : ∀x1,x2,y1,y2.mk_strId x1 y1 = mk_strId x2 y2 → x1 = x2.
+ #x1; #x2; #y1; #y2; #H;
+ nchange with (match mk_strId x2 y2 with [ mk_strId a _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma strid_destruct_2 : ∀x1,x2,y1,y2.mk_strId x1 y1 = mk_strId x2 y2 → y1 = y2.
+ #x1; #x2; #y1; #y2; #H;
+ nchange with (match mk_strId x2 y2 with [ mk_strId _ b ⇒ y1 = b ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_eqstrid : symmetricT strId bool eq_strId.
+ #si1; #si2;
+ nchange with (
+ ((eqc ? (str_elem si1) (str_elem si2))⊗(eqc ? (id_elem si1) (id_elem si2))) =
+ ((eqc ? (str_elem si2) (str_elem si1))⊗(eqc ? (id_elem si2) (id_elem si1))));
+ nrewrite > (symmetric_eqc ? (str_elem si1) (str_elem si2));
+ nrewrite > (symmetric_eqc ? (id_elem si1) (id_elem si2));
+ napply refl_eq.
+nqed.
+
+nlemma eqstrid_to_eq : ∀s,s'.eq_strId s s' = true → s = s'.
+ #si1; #si2;
+ nelim si1;
+ #l1; #n1;
+ nelim si2;
+ #l2; #n2; #H;
+ nchange in H:(%) with (((eqc ? l1 l2)⊗(eqc ? n1 n2)) = true);
+ nrewrite > (eqc_to_eq ? l1 l2 (andb_true_true_l … H));
+ nrewrite > (eqc_to_eq ? n1 n2 (andb_true_true_r … H));
+ napply refl_eq.
+nqed.
+
+nlemma eq_to_eqstrid : ∀s,s'.s = s' → eq_strId s s' = true.
+ #si1; #si2;
+ nelim si1;
+ #l1; #n1;
+ nelim si2;
+ #l2; #n2; #H;
+ nchange with (((eqc ? l1 l2)⊗(eqc ? n1 n2)) = true);
+ nrewrite > (strid_destruct_1 … H);
+ nrewrite > (strid_destruct_2 … H);
+ nrewrite > (eq_to_eqc ? l2 l2 (refl_eq …));
+ nrewrite > (eq_to_eqc ? n2 n2 (refl_eq …));
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma decidable_strid_aux1 : ∀s1,n1,s2,n2.s1 ≠ s2 → (mk_strId s1 n1) ≠ (mk_strId s2 n2).
+ #s1; #n1; #s2; #n2;
+ nnormalize; #H; #H1;
+ napply (H (strid_destruct_1 … H1)).
+nqed.
+
+nlemma decidable_strid_aux2 : ∀s1,n1,s2,n2.n1 ≠ n2 → (mk_strId s1 n1) ≠ (mk_strId s2 n2).
+ #s1; #n1; #s2; #n2;
+ nnormalize; #H; #H1;
+ napply (H (strid_destruct_2 … H1)).
+nqed.
+
+nlemma decidable_strid : ∀x,y:strId.decidable (x = y).
+ #x; nelim x; #s1; #n1;
+ #y; nelim y; #s2; #n2;
+ nnormalize;
+ napply (or2_elim (s1 = s2) (s1 ≠ s2) ? (decidable_c ? s1 s2) …);
+ ##[ ##2: #H; napply (or2_intro2 … (decidable_strid_aux1 … H))
+ ##| ##1: #H; napply (or2_elim (n1 = n2) (n1 ≠ n2) ? (decidable_c ? n1 n2) …);
+ ##[ ##2: #H1; napply (or2_intro2 … (decidable_strid_aux2 … H1))
+ ##| ##1: #H1; nrewrite > H; nrewrite > H1;
+ napply (or2_intro1 … (refl_eq ? (mk_strId s2 n2)))
+ ##]
+ ##]
+nqed.
+
+nlemma neqstrid_to_neq : ∀sid1,sid2:strId.(eq_strId sid1 sid2 = false) → (sid1 ≠ sid2).
+ #sid1; nelim sid1; #s1; #n1;
+ #sid2; nelim sid2; #s2; #n2;
+ nchange with ((((eqc ? s1 s2) ⊗ (eqc ? n1 n2)) = false) → ?);
+ #H;
+ napply (or2_elim ((eqc ? s1 s2) = false) ((eqc ? n1 n2) = false) ? (andb_false2 … H) …);
+ ##[ ##1: #H1; napply (decidable_strid_aux1 … (neqc_to_neq … H1))
+ ##| ##2: #H1; napply (decidable_strid_aux2 … (neqc_to_neq … H1))
+ ##]
+nqed.
+
+nlemma strid_destruct : ∀s1,s2,n1,n2.(mk_strId s1 n1) ≠ (mk_strId s2 n2) → s1 ≠ s2 ∨ n1 ≠ n2.
+ #s1; #s2; #n1; #n2;
+ nnormalize; #H;
+ napply (or2_elim (s1 = s2) (s1 ≠ s2) ? (decidable_c ? s1 s2) …);
+ ##[ ##2: #H1; napply (or2_intro1 … H1)
+ ##| ##1: #H1; napply (or2_elim (n1 = n2) (n1 ≠ n2) ? (decidable_c ? n1 n2) …);
+ ##[ ##2: #H2; napply (or2_intro2 … H2)
+ ##| ##1: #H2; nrewrite > H1 in H:(%);
+ nrewrite > H2;
+ #H; nelim (H (refl_eq …))
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqstrid : ∀sid1,sid2.sid1 ≠ sid2 → eq_strId sid1 sid2 = false.
+ #sid1; nelim sid1; #s1; #n1;
+ #sid2; nelim sid2; #s2; #n2;
+ #H; nchange with (((eqc ? s1 s2) ⊗ (eqc ? n1 n2)) = false);
+ napply (or2_elim (s1 ≠ s2) (n1 ≠ n2) ? (strid_destruct … H) …);
+ ##[ ##1: #H1; nrewrite > (neq_to_neqc … H1); nnormalize; napply refl_eq
+ ##| ##2: #H1; nrewrite > (neq_to_neqc … H1);
+ nrewrite > (symmetric_andbool (eqc ? s1 s2) false);
+ nnormalize; napply refl_eq
+ ##]
+nqed.
+
+nlemma strid_is_comparable : comparable.
+ napply (mk_comparable strId);
+ ##[ napply (mk_strId (nil ?) O)
+ ##| napply (λx.false)
+ ##| napply eq_strId
+ ##| napply eqstrid_to_eq
+ ##| napply eq_to_eqstrid
+ ##| napply neqstrid_to_neq
+ ##| napply neq_to_neqstrid
+ ##| napply decidable_strid
+ ##| napply symmetric_eqstrid
+ ##]
+nqed.
+
+unification hint 0 ≔ ⊢ carr strid_is_comparable ≡ strId.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| A.Asperti, C.Sacerdoti Coen, *)
+(* ||A|| E.Tassi, S.Zacchiroli *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU Lesser General Public License Version 2.1 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/pts.ma".
+
+(* ********************************** *)
+(* SOTTOINSIEME MINIMALE DELLA TEORIA *)
+(* ********************************** *)
+
+(* logic/connectives.ma *)
+
+ninductive True: Prop ≝
+ I : True.
+
+ninductive False: Prop ≝.
+
+ndefinition Not: Prop → Prop ≝
+λA.(A → False).
+
+interpretation "logical not" 'not x = (Not x).
+
+nlemma absurd : ∀A,C:Prop.A → ¬A → C.
+ #A; #C; #H;
+ nnormalize;
+ #H1;
+ nelim (H1 H).
+nqed.
+
+nlemma not_to_not : ∀A,B:Prop. (A → B) → ((¬B) → (¬A)).
+ #A; #B; #H;
+ nnormalize;
+ #H1; #H2;
+ nelim (H1 (H H2)).
+nqed.
+
+nlemma prop_to_nnprop : ∀P.P → ¬¬P.
+ #P; nnormalize; #H; #H1;
+ napply (H1 H).
+nqed.
+
+ninductive And2 (A,B:Prop) : Prop ≝
+ conj2 : A → B → (And2 A B).
+
+interpretation "logical and" 'and x y = (And2 x y).
+
+nlemma proj2_1: ∀A,B:Prop.A ∧ B → A.
+ #A; #B; #H;
+ napply (And2_ind A B … H);
+ #H1; #H2;
+ napply H1.
+nqed.
+
+nlemma proj2_2: ∀A,B:Prop.A ∧ B → B.
+ #A; #B; #H;
+ napply (And2_ind A B … H);
+ #H1; #H2;
+ napply H2.
+nqed.
+
+ninductive And3 (A,B,C:Prop) : Prop ≝
+ conj3 : A → B → C → (And3 A B C).
+
+nlemma proj3_1: ∀A,B,C:Prop.And3 A B C → A.
+ #A; #B; #C; #H;
+ napply (And3_ind A B C … H);
+ #H1; #H2; #H3;
+ napply H1.
+nqed.
+
+nlemma proj3_2: ∀A,B,C:Prop.And3 A B C → B.
+ #A; #B; #C; #H;
+ napply (And3_ind A B C … H);
+ #H1; #H2; #H3;
+ napply H2.
+nqed.
+
+nlemma proj3_3: ∀A,B,C:Prop.And3 A B C → C.
+ #A; #B; #C; #H;
+ napply (And3_ind A B C … H);
+ #H1; #H2; #H3;
+ napply H3.
+nqed.
+
+ninductive And4 (A,B,C,D:Prop) : Prop ≝
+ conj4 : A → B → C → D → (And4 A B C D).
+
+nlemma proj4_1: ∀A,B,C,D:Prop.And4 A B C D → A.
+ #A; #B; #C; #D; #H;
+ napply (And4_ind A B C D … H);
+ #H1; #H2; #H3; #H4;
+ napply H1.
+nqed.
+
+nlemma proj4_2: ∀A,B,C,D:Prop.And4 A B C D → B.
+ #A; #B; #C; #D; #H;
+ napply (And4_ind A B C D … H);
+ #H1; #H2; #H3; #H4;
+ napply H2.
+nqed.
+
+nlemma proj4_3: ∀A,B,C,D:Prop.And4 A B C D → C.
+ #A; #B; #C; #D; #H;
+ napply (And4_ind A B C D … H);
+ #H1; #H2; #H3; #H4;
+ napply H3.
+nqed.
+
+nlemma proj4_4: ∀A,B,C,D:Prop.And4 A B C D → D.
+ #A; #B; #C; #D; #H;
+ napply (And4_ind A B C D … H);
+ #H1; #H2; #H3; #H4;
+ napply H4.
+nqed.
+
+ninductive And5 (A,B,C,D,E:Prop) : Prop ≝
+ conj5 : A → B → C → D → E → (And5 A B C D E).
+
+nlemma proj5_1: ∀A,B,C,D,E:Prop.And5 A B C D E → A.
+ #A; #B; #C; #D; #E; #H;
+ napply (And5_ind A B C D E … H);
+ #H1; #H2; #H3; #H4; #H5;
+ napply H1.
+nqed.
+
+nlemma proj5_2: ∀A,B,C,D,E:Prop.And5 A B C D E → B.
+ #A; #B; #C; #D; #E; #H;
+ napply (And5_ind A B C D E … H);
+ #H1; #H2; #H3; #H4; #H5;
+ napply H2.
+nqed.
+
+nlemma proj5_3: ∀A,B,C,D,E:Prop.And5 A B C D E → C.
+ #A; #B; #C; #D; #E; #H;
+ napply (And5_ind A B C D E … H);
+ #H1; #H2; #H3; #H4; #H5;
+ napply H3.
+nqed.
+
+nlemma proj5_4: ∀A,B,C,D,E:Prop.And5 A B C D E → D.
+ #A; #B; #C; #D; #E; #H;
+ napply (And5_ind A B C D E … H);
+ #H1; #H2; #H3; #H4; #H5;
+ napply H4.
+nqed.
+
+nlemma proj5_5: ∀A,B,C,D,E:Prop.And5 A B C D E → E.
+ #A; #B; #C; #D; #E; #H;
+ napply (And5_ind A B C D E … H);
+ #H1; #H2; #H3; #H4; #H5;
+ napply H5.
+nqed.
+
+ninductive Or2 (A,B:Prop) : Prop ≝
+ or2_intro1 : A → (Or2 A B)
+| or2_intro2 : B → (Or2 A B).
+
+interpretation "logical or" 'or x y = (Or2 x y).
+
+ndefinition decidable ≝ λA:Prop.A ∨ (¬A).
+
+nlemma or2_elim
+ : ∀P1,P2,Q:Prop.Or2 P1 P2 → ∀f1:P1 → Q.∀f2:P2 → Q.Q.
+ #P1; #P2; #Q; #H; #f1; #f2;
+ napply (Or2_ind P1 P2 ? f1 f2 ?);
+ napply H.
+nqed.
+
+nlemma symmetric_or2 : ∀P1,P2.Or2 P1 P2 → Or2 P2 P1.
+ #P1; #P2; #H;
+ napply (or2_elim P1 P2 ? H);
+ ##[ ##1: #H1; napply (or2_intro2 P2 P1 H1)
+ ##| ##2: #H1; napply (or2_intro1 P2 P1 H1)
+ ##]
+nqed.
+
+ninductive Or3 (A,B,C:Prop) : Prop ≝
+ or3_intro1 : A → (Or3 A B C)
+| or3_intro2 : B → (Or3 A B C)
+| or3_intro3 : C → (Or3 A B C).
+
+nlemma or3_elim
+ : ∀P1,P2,P3,Q:Prop.Or3 P1 P2 P3 → ∀f1:P1 → Q.∀f2:P2 → Q.∀f3:P3 → Q.Q.
+ #P1; #P2; #P3; #Q; #H; #f1; #f2; #f3;
+ napply (Or3_ind P1 P2 P3 ? f1 f2 f3 ?);
+ napply H.
+nqed.
+
+nlemma symmetric_or3_12 : ∀P1,P2,P3:Prop.Or3 P1 P2 P3 → Or3 P2 P1 P3.
+ #P1; #P2; #P3; #H;
+ napply (or3_elim P1 P2 P3 ? H);
+ ##[ ##1: #H1; napply (or3_intro2 P2 P1 P3 H1)
+ ##| ##2: #H1; napply (or3_intro1 P2 P1 P3 H1)
+ ##| ##3: #H1; napply (or3_intro3 P2 P1 P3 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or3_13 : ∀P1,P2,P3:Prop.Or3 P1 P2 P3 → Or3 P3 P2 P1.
+ #P1; #P2; #P3; #H;
+ napply (or3_elim P1 P2 P3 ? H);
+ ##[ ##1: #H1; napply (or3_intro3 P3 P2 P1 H1)
+ ##| ##2: #H1; napply (or3_intro2 P3 P2 P1 H1)
+ ##| ##3: #H1; napply (or3_intro1 P3 P2 P1 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or3_23 : ∀P1,P2,P3:Prop.Or3 P1 P2 P3 → Or3 P1 P3 P2.
+ #P1; #P2; #P3; #H;
+ napply (or3_elim P1 P2 P3 ? H);
+ ##[ ##1: #H1; napply (or3_intro1 P1 P3 P2 H1)
+ ##| ##2: #H1; napply (or3_intro3 P1 P3 P2 H1)
+ ##| ##3: #H1; napply (or3_intro2 P1 P3 P2 H1)
+ ##]
+nqed.
+
+ninductive Or4 (A,B,C,D:Prop) : Prop ≝
+ or4_intro1 : A → (Or4 A B C D)
+| or4_intro2 : B → (Or4 A B C D)
+| or4_intro3 : C → (Or4 A B C D)
+| or4_intro4 : D → (Or4 A B C D).
+
+nlemma or4_elim
+ : ∀P1,P2,P3,P4,Q:Prop.Or4 P1 P2 P3 P4 → ∀f1:P1 → Q.∀f2:P2 → Q.
+ ∀f3:P3 → Q.∀f4:P4 → Q.Q.
+ #P1; #P2; #P3; #P4; #Q; #H; #f1; #f2; #f3; #f4;
+ napply (Or4_ind P1 P2 P3 P4 ? f1 f2 f3 f4 ?);
+ napply H.
+nqed.
+
+nlemma symmetric_or4_12 : ∀P1,P2,P3,P4:Prop.Or4 P1 P2 P3 P4 → Or4 P2 P1 P3 P4.
+ #P1; #P2; #P3; #P4; #H;
+ napply (or4_elim P1 P2 P3 P4 ? H);
+ ##[ ##1: #H1; napply (or4_intro2 P2 P1 P3 P4 H1)
+ ##| ##2: #H1; napply (or4_intro1 P2 P1 P3 P4 H1)
+ ##| ##3: #H1; napply (or4_intro3 P2 P1 P3 P4 H1)
+ ##| ##4: #H1; napply (or4_intro4 P2 P1 P3 P4 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or4_13 : ∀P1,P2,P3,P4:Prop.Or4 P1 P2 P3 P4 → Or4 P3 P2 P1 P4.
+ #P1; #P2; #P3; #P4; #H;
+ napply (or4_elim P1 P2 P3 P4 ? H);
+ ##[ ##1: #H1; napply (or4_intro3 P3 P2 P1 P4 H1)
+ ##| ##2: #H1; napply (or4_intro2 P3 P2 P1 P4 H1)
+ ##| ##3: #H1; napply (or4_intro1 P3 P2 P1 P4 H1)
+ ##| ##4: #H1; napply (or4_intro4 P3 P2 P1 P4 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or4_14 : ∀P1,P2,P3,P4:Prop.Or4 P1 P2 P3 P4 → Or4 P4 P2 P3 P1.
+ #P1; #P2; #P3; #P4; #H;
+ napply (or4_elim P1 P2 P3 P4 ? H);
+ ##[ ##1: #H1; napply (or4_intro4 P4 P2 P3 P1 H1)
+ ##| ##2: #H1; napply (or4_intro2 P4 P2 P3 P1 H1)
+ ##| ##3: #H1; napply (or4_intro3 P4 P2 P3 P1 H1)
+ ##| ##4: #H1; napply (or4_intro1 P4 P2 P3 P1 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or4_23 : ∀P1,P2,P3,P4:Prop.Or4 P1 P2 P3 P4 → Or4 P1 P3 P2 P4.
+ #P1; #P2; #P3; #P4; #H;
+ napply (or4_elim P1 P2 P3 P4 ? H);
+ ##[ ##1: #H1; napply (or4_intro1 P1 P3 P2 P4 H1)
+ ##| ##2: #H1; napply (or4_intro3 P1 P3 P2 P4 H1)
+ ##| ##3: #H1; napply (or4_intro2 P1 P3 P2 P4 H1)
+ ##| ##4: #H1; napply (or4_intro4 P1 P3 P2 P4 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or4_24 : ∀P1,P2,P3,P4:Prop.Or4 P1 P2 P3 P4 → Or4 P1 P4 P3 P2.
+ #P1; #P2; #P3; #P4; #H;
+ napply (or4_elim P1 P2 P3 P4 ? H);
+ ##[ ##1: #H1; napply (or4_intro1 P1 P4 P3 P2 H1)
+ ##| ##2: #H1; napply (or4_intro4 P1 P4 P3 P2 H1)
+ ##| ##3: #H1; napply (or4_intro3 P1 P4 P3 P2 H1)
+ ##| ##4: #H1; napply (or4_intro2 P1 P4 P3 P2 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or4_34 : ∀P1,P2,P3,P4:Prop.Or4 P1 P2 P3 P4 → Or4 P1 P2 P4 P3.
+ #P1; #P2; #P3; #P4; #H;
+ napply (or4_elim P1 P2 P3 P4 ? H);
+ ##[ ##1: #H1; napply (or4_intro1 P1 P2 P4 P3 H1)
+ ##| ##2: #H1; napply (or4_intro2 P1 P2 P4 P3 H1)
+ ##| ##3: #H1; napply (or4_intro4 P1 P2 P4 P3 H1)
+ ##| ##4: #H1; napply (or4_intro3 P1 P2 P4 P3 H1)
+ ##]
+nqed.
+
+ninductive Or5 (A,B,C,D,E:Prop) : Prop ≝
+ or5_intro1 : A → (Or5 A B C D E)
+| or5_intro2 : B → (Or5 A B C D E)
+| or5_intro3 : C → (Or5 A B C D E)
+| or5_intro4 : D → (Or5 A B C D E)
+| or5_intro5 : E → (Or5 A B C D E).
+
+nlemma or5_elim
+ : ∀P1,P2,P3,P4,P5,Q:Prop.Or5 P1 P2 P3 P4 P5 → ∀f1:P1 → Q.∀f2:P2 → Q.
+ ∀f3:P3 → Q.∀f4:P4 → Q.∀f5:P5 → Q.Q.
+ #P1; #P2; #P3; #P4; #P5; #Q; #H; #f1; #f2; #f3; #f4; #f5;
+ napply (Or5_ind P1 P2 P3 P4 P5 ? f1 f2 f3 f4 f5 ?);
+ napply H.
+nqed.
+
+nlemma symmetric_or5_12 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P2 P1 P3 P4 P5.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro2 P2 P1 P3 P4 P5 H1)
+ ##| ##2: #H1; napply (or5_intro1 P2 P1 P3 P4 P5 H1)
+ ##| ##3: #H1; napply (or5_intro3 P2 P1 P3 P4 P5 H1)
+ ##| ##4: #H1; napply (or5_intro4 P2 P1 P3 P4 P5 H1)
+ ##| ##5: #H1; napply (or5_intro5 P2 P1 P3 P4 P5 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_13 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P3 P2 P1 P4 P5.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro3 P3 P2 P1 P4 P5 H1)
+ ##| ##2: #H1; napply (or5_intro2 P3 P2 P1 P4 P5 H1)
+ ##| ##3: #H1; napply (or5_intro1 P3 P2 P1 P4 P5 H1)
+ ##| ##4: #H1; napply (or5_intro4 P3 P2 P1 P4 P5 H1)
+ ##| ##5: #H1; napply (or5_intro5 P3 P2 P1 P4 P5 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_14 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P4 P2 P3 P1 P5.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro4 P4 P2 P3 P1 P5 H1)
+ ##| ##2: #H1; napply (or5_intro2 P4 P2 P3 P1 P5 H1)
+ ##| ##3: #H1; napply (or5_intro3 P4 P2 P3 P1 P5 H1)
+ ##| ##4: #H1; napply (or5_intro1 P4 P2 P3 P1 P5 H1)
+ ##| ##5: #H1; napply (or5_intro5 P4 P2 P3 P1 P5 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_15 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P5 P2 P3 P4 P1.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro5 P5 P2 P3 P4 P1 H1)
+ ##| ##2: #H1; napply (or5_intro2 P5 P2 P3 P4 P1 H1)
+ ##| ##3: #H1; napply (or5_intro3 P5 P2 P3 P4 P1 H1)
+ ##| ##4: #H1; napply (or5_intro4 P5 P2 P3 P4 P1 H1)
+ ##| ##5: #H1; napply (or5_intro1 P5 P2 P3 P4 P1 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_23 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P1 P3 P2 P4 P5.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro1 P1 P3 P2 P4 P5 H1)
+ ##| ##2: #H1; napply (or5_intro3 P1 P3 P2 P4 P5 H1)
+ ##| ##3: #H1; napply (or5_intro2 P1 P3 P2 P4 P5 H1)
+ ##| ##4: #H1; napply (or5_intro4 P1 P3 P2 P4 P5 H1)
+ ##| ##5: #H1; napply (or5_intro5 P1 P3 P2 P4 P5 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_24 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P1 P4 P3 P2 P5.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro1 P1 P4 P3 P2 P5 H1)
+ ##| ##2: #H1; napply (or5_intro4 P1 P4 P3 P2 P5 H1)
+ ##| ##3: #H1; napply (or5_intro3 P1 P4 P3 P2 P5 H1)
+ ##| ##4: #H1; napply (or5_intro2 P1 P4 P3 P2 P5 H1)
+ ##| ##5: #H1; napply (or5_intro5 P1 P4 P3 P2 P5 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_25 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P1 P5 P3 P4 P2.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro1 P1 P5 P3 P4 P2 H1)
+ ##| ##2: #H1; napply (or5_intro5 P1 P5 P3 P4 P2 H1)
+ ##| ##3: #H1; napply (or5_intro3 P1 P5 P3 P4 P2 H1)
+ ##| ##4: #H1; napply (or5_intro4 P1 P5 P3 P4 P2 H1)
+ ##| ##5: #H1; napply (or5_intro2 P1 P5 P3 P4 P2 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_34 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P1 P2 P4 P3 P5.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro1 P1 P2 P4 P3 P5 H1)
+ ##| ##2: #H1; napply (or5_intro2 P1 P2 P4 P3 P5 H1)
+ ##| ##3: #H1; napply (or5_intro4 P1 P2 P4 P3 P5 H1)
+ ##| ##4: #H1; napply (or5_intro3 P1 P2 P4 P3 P5 H1)
+ ##| ##5: #H1; napply (or5_intro5 P1 P2 P4 P3 P5 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_35 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P1 P2 P5 P4 P3.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro1 P1 P2 P5 P4 P3 H1)
+ ##| ##2: #H1; napply (or5_intro2 P1 P2 P5 P4 P3 H1)
+ ##| ##3: #H1; napply (or5_intro5 P1 P2 P5 P4 P3 H1)
+ ##| ##4: #H1; napply (or5_intro4 P1 P2 P5 P4 P3 H1)
+ ##| ##5: #H1; napply (or5_intro3 P1 P2 P5 P4 P3 H1)
+ ##]
+nqed.
+
+nlemma symmetric_or5_45 : ∀P1,P2,P3,P4,P5:Prop.Or5 P1 P2 P3 P4 P5 → Or5 P1 P2 P3 P5 P4.
+ #P1; #P2; #P3; #P4; #P5; #H;
+ napply (or5_elim P1 P2 P3 P4 P5 ? H);
+ ##[ ##1: #H1; napply (or5_intro1 P1 P2 P3 P5 P4 H1)
+ ##| ##2: #H1; napply (or5_intro2 P1 P2 P3 P5 P4 H1)
+ ##| ##3: #H1; napply (or5_intro3 P1 P2 P3 P5 P4 H1)
+ ##| ##4: #H1; napply (or5_intro5 P1 P2 P3 P5 P4 H1)
+ ##| ##5: #H1; napply (or5_intro4 P1 P2 P3 P5 P4 H1)
+ ##]
+nqed.
+
+ninductive ex (A:Type) (Q:A → Prop) : Prop ≝
+ ex_intro: ∀x:A.Q x → ex A Q.
+
+interpretation "exists" 'exists x = (ex ? x).
+
+ninductive ex2 (A:Type) (Q,R:A → Prop) : Prop ≝
+ ex_intro2: ∀x:A.Q x → R x → ex2 A Q R.
+
+(* higher_order_defs/relations *)
+
+ndefinition relation : Type → Type ≝
+λA.A → A → Prop.
+
+ndefinition reflexive : ∀A:Type.∀R:relation A.Prop ≝
+λA.λR.∀x:A.R x x.
+
+ndefinition symmetric : ∀A:Type.∀R:relation A.Prop ≝
+λA.λR.∀x,y:A.R x y → R y x.
+
+ndefinition transitive : ∀A:Type.∀R:relation A.Prop ≝
+λA.λR.∀x,y,z:A.R x y → R y z → R x z.
+
+ndefinition irreflexive : ∀A:Type.∀R:relation A.Prop ≝
+λA.λR.∀x:A.¬ (R x x).
+
+ndefinition cotransitive : ∀A:Type.∀R:relation A.Prop ≝
+λA.λR.∀x,y:A.R x y → ∀z:A. R x z ∨ R z y.
+
+ndefinition tight_apart : ∀A:Type.∀eq,ap:relation A.Prop ≝
+λA.λeq,ap.∀x,y:A. (¬ (ap x y) → eq x y) ∧ (eq x y → ¬ (ap x y)).
+
+ndefinition antisymmetric : ∀A:Type.∀R:relation A.Prop ≝
+λA.λR.∀x,y:A.R x y → ¬ (R y x).
+
+(* logic/equality.ma *)
+
+ninductive eq (A:Type) (x:A) : A → Prop ≝
+ refl_eq : eq A x x.
+
+ndefinition refl ≝ refl_eq.
+
+interpretation "leibnitz's equality" 'eq t x y = (eq t x y).
+
+interpretation "leibnitz's non-equality" 'neq t x y = (Not (eq t x y)).
+
+nlemma eq_f : ∀T1,T2:Type.∀x,y:T1.∀f:T1 → T2.x = y → (f x) = (f y).
+ #T1; #T2; #x; #y; #f; #H;
+ nrewrite < H;
+ napply refl_eq.
+nqed.
+
+nlemma eq_f2 : ∀T1,T2,T3:Type.∀x1,y1:T1.∀x2,y2:T2.∀f:T1 → T2 → T3.x1 = y1 → x2 = y2 → f x1 x2 = f y1 y2.
+ #T1; #T2; #T3; #x1; #y1; #x2; #y2; #f; #H1; #H2;
+ nrewrite < H1;
+ nrewrite < H2;
+ napply refl_eq.
+nqed.
+
+nlemma neqf_to_neq : ∀T1,T2:Type.∀x,y:T1.∀f:T1 → T2.((f x) ≠ (f y)) → x ≠ y.
+ #T1; #T2; #x; #y; #f;
+ nnormalize; #H; #H1;
+ napply (H (eq_f … H1)).
+nqed.
+
+nlemma symmetric_eq: ∀A:Type. symmetric A (eq A).
+ #A;
+ nnormalize;
+ #x; #y; #H;
+ nrewrite < H;
+ napply refl_eq.
+nqed.
+
+nlemma eq_ind_r: ∀A:Type[0].∀x:A.∀P:A → Prop.P x → ∀y:A.y=x → P y.
+ #A; #x; #P; #H; #y; #H1;
+ nrewrite < (symmetric_eq … H1);
+ napply H.
+nqed.
+
+ndefinition R0 ≝ λT:Type[0].λt:T.t.
+
+ndefinition R1 ≝ eq_rect_Type0.
+
+ndefinition R2 :
+ ∀T0:Type[0].
+ ∀a0:T0.
+ ∀T1:∀x0:T0. a0=x0 → Type[0].
+ ∀a1:T1 a0 (refl_eq ? a0).
+ ∀T2:∀x0:T0. ∀p0:a0=x0. ∀x1:T1 x0 p0. R1 ?? T1 a1 ? p0 = x1 → Type[0].
+ ∀a2:T2 a0 (refl_eq ? a0) a1 (refl_eq ? a1).
+ ∀b0:T0.
+ ∀e0:a0 = b0.
+ ∀b1: T1 b0 e0.
+ ∀e1:R1 ?? T1 a1 ? e0 = b1.
+ T2 b0 e0 b1 e1.
+ #T0;#a0;#T1;#a1;#T2;#a2;#b0;#e0;#b1;#e1;
+ napply (eq_rect_Type0 ????? e1);
+ napply (R1 ?? ? ?? e0);
+ napply a2;
+nqed.
+
+ndefinition R3 :
+ ∀T0:Type[0].
+ ∀a0:T0.
+ ∀T1:∀x0:T0. a0=x0 → Type[0].
+ ∀a1:T1 a0 (refl_eq ? a0).
+ ∀T2:∀x0:T0. ∀p0:a0=x0. ∀x1:T1 x0 p0. R1 ?? T1 a1 ? p0 = x1 → Type[0].
+ ∀a2:T2 a0 (refl_eq ? a0) a1 (refl_eq ? a1).
+ ∀T3:∀x0:T0. ∀p0:a0=x0. ∀x1:T1 x0 p0.∀p1:R1 ?? T1 a1 ? p0 = x1.
+ ∀x2:T2 x0 p0 x1 p1.R2 ???? T2 a2 x0 p0 ? p1 = x2 → Type[0].
+ ∀a3:T3 a0 (refl_eq ? a0) a1 (refl_eq ? a1) a2 (refl_eq ? a2).
+ ∀b0:T0.
+ ∀e0:a0 = b0.
+ ∀b1: T1 b0 e0.
+ ∀e1:R1 ?? T1 a1 ? e0 = b1.
+ ∀b2: T2 b0 e0 b1 e1.
+ ∀e2:R2 ???? T2 a2 b0 e0 ? e1 = b2.
+ T3 b0 e0 b1 e1 b2 e2.
+ #T0;#a0;#T1;#a1;#T2;#a2;#T3;#a3;#b0;#e0;#b1;#e1;#b2;#e2;
+ napply (eq_rect_Type0 ????? e2);
+ napply (R2 ?? ? ???? e0 ? e1);
+ napply a3;
+nqed.
+
+ndefinition R4 :
+ ∀T0:Type[0].
+ ∀a0:T0.
+ ∀T1:∀x0:T0. eq T0 a0 x0 → Type[0].
+ ∀a1:T1 a0 (refl_eq T0 a0).
+ ∀T2:∀x0:T0. ∀p0:eq (T0 …) a0 x0. ∀x1:T1 x0 p0.eq (T1 …) (R1 T0 a0 T1 a1 x0 p0) x1 → Type[0].
+ ∀a2:T2 a0 (refl_eq T0 a0) a1 (refl_eq (T1 a0 (refl_eq T0 a0)) a1).
+ ∀T3:∀x0:T0. ∀p0:eq (T0 …) a0 x0. ∀x1:T1 x0 p0.∀p1:eq (T1 …) (R1 T0 a0 T1 a1 x0 p0) x1.
+ ∀x2:T2 x0 p0 x1 p1.eq (T2 …) (R2 T0 a0 T1 a1 T2 a2 x0 p0 x1 p1) x2 → Type[0].
+ ∀a3:T3 a0 (refl_eq T0 a0) a1 (refl_eq (T1 a0 (refl_eq T0 a0)) a1)
+ a2 (refl_eq (T2 a0 (refl_eq T0 a0) a1 (refl_eq (T1 a0 (refl_eq T0 a0)) a1)) a2).
+ ∀T4:∀x0:T0. ∀p0:eq (T0 …) a0 x0. ∀x1:T1 x0 p0.∀p1:eq (T1 …) (R1 T0 a0 T1 a1 x0 p0) x1.
+ ∀x2:T2 x0 p0 x1 p1.∀p2:eq (T2 …) (R2 T0 a0 T1 a1 T2 a2 x0 p0 x1 p1) x2.
+ ∀x3:T3 x0 p0 x1 p1 x2 p2.∀p3:eq (T3 …) (R3 T0 a0 T1 a1 T2 a2 T3 a3 x0 p0 x1 p1 x2 p2) x3.
+ Type[0].
+ ∀a4:T4 a0 (refl_eq T0 a0) a1 (refl_eq (T1 a0 (refl_eq T0 a0)) a1)
+ a2 (refl_eq (T2 a0 (refl_eq T0 a0) a1 (refl_eq (T1 a0 (refl_eq T0 a0)) a1)) a2)
+ a3 (refl_eq (T3 a0 (refl_eq T0 a0) a1 (refl_eq (T1 a0 (refl_eq T0 a0)) a1)
+ a2 (refl_eq (T2 a0 (refl_eq T0 a0) a1 (refl_eq (T1 a0 (refl_eq T0 a0)) a1)) a2))
+ a3).
+ ∀b0:T0.
+ ∀e0:eq (T0 …) a0 b0.
+ ∀b1: T1 b0 e0.
+ ∀e1:eq (T1 …) (R1 T0 a0 T1 a1 b0 e0) b1.
+ ∀b2: T2 b0 e0 b1 e1.
+ ∀e2:eq (T2 …) (R2 T0 a0 T1 a1 T2 a2 b0 e0 b1 e1) b2.
+ ∀b3: T3 b0 e0 b1 e1 b2 e2.
+ ∀e3:eq (T3 …) (R3 T0 a0 T1 a1 T2 a2 T3 a3 b0 e0 b1 e1 b2 e2) b3.
+ T4 b0 e0 b1 e1 b2 e2 b3 e3.
+ #T0;#a0;#T1;#a1;#T2;#a2;#T3;#a3;#T4;#a4;#b0;#e0;#b1;#e1;#b2;#e2;#b3;#e3;
+ napply (eq_rect_Type0 ????? e3);
+ napply (R3 ????????? e0 ? e1 ? e2);
+ napply a4;
+nqed.
+
+naxiom streicherK : ∀T:Type[0].∀t:T.∀P:t = t → Type[2].P (refl ? t) → ∀p.P p.
+
+nlemma symmetric_neq : ∀T:Type.∀x,y:T.x ≠ y → y ≠ x.
+ #T; #x; #y;
+ nnormalize;
+ #H; #H1;
+ nrewrite > H1 in H:(%); #H;
+ napply (H (refl_eq …)).
+nqed.
+
+ndefinition relationT : Type → Type → Type ≝
+λA,T:Type.A → A → T.
+
+ndefinition symmetricT: ∀A,T:Type.∀R:relationT A T.Prop ≝
+λA,T.λR.∀x,y:A.R x y = R y x.
+
+ndefinition associative : ∀A:Type.∀R:relationT A A.Prop ≝
+λA.λR.∀x,y,z:A.R (R x y) z = R x (R y z).
--- /dev/null
+common/nat.ma common/comp.ma num/bool_lemmas.ma
+num/word32.ma num/word16.ma
+common/ascii_base.ma num/bool.ma
+num/bitrigesim.ma common/comp.ma num/bool_lemmas.ma
+common/pts.ma
+common/prod.ma common/comp.ma common/prod_base.ma num/bool_lemmas.ma
+common/prod_base.ma num/bool.ma
+universe/universe.ma common/nelist.ma common/prod.ma
+num/bool_lemmas.ma num/bool.ma
+common/comp.ma common/hints_declaration.ma num/bool.ma
+num/exadecim.ma num/bool_lemmas.ma num/comp_ext.ma num/oct.ma
+num/word24.ma num/byte8.ma
+common/theory.ma common/pts.ma
+common/sigma.ma common/theory.ma
+num/oct.ma common/comp.ma num/bool_lemmas.ma
+common/hints_declaration.ma common/pts.ma
+num/byte8.ma num/bitrigesim.ma num/comp_num.ma num/exadecim.ma
+common/option.ma common/comp.ma common/option_base.ma num/bool_lemmas.ma
+num/bool.ma common/theory.ma
+common/option_base.ma num/bool.ma
+num/word16.ma common/nat.ma num/byte8.ma
+common/string.ma common/ascii.ma common/list.ma
+common/ascii.ma common/ascii_base.ma common/comp.ma num/bool_lemmas.ma
+common/list.ma common/comp.ma common/nat.ma common/option.ma
+num/comp_num.ma num/bool_lemmas.ma num/comp_ext.ma
+num/comp_ext.ma common/comp.ma common/prod.ma
+common/nelist.ma common/list.ma
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/comp.ma".
+include "num/bool_lemmas.ma".
+
+(* ************* *)
+(* BITRIGESIMALI *)
+(* ************* *)
+
+ninductive bitrigesim : Type ≝
+ t00: bitrigesim
+| t01: bitrigesim
+| t02: bitrigesim
+| t03: bitrigesim
+| t04: bitrigesim
+| t05: bitrigesim
+| t06: bitrigesim
+| t07: bitrigesim
+| t08: bitrigesim
+| t09: bitrigesim
+| t0A: bitrigesim
+| t0B: bitrigesim
+| t0C: bitrigesim
+| t0D: bitrigesim
+| t0E: bitrigesim
+| t0F: bitrigesim
+| t10: bitrigesim
+| t11: bitrigesim
+| t12: bitrigesim
+| t13: bitrigesim
+| t14: bitrigesim
+| t15: bitrigesim
+| t16: bitrigesim
+| t17: bitrigesim
+| t18: bitrigesim
+| t19: bitrigesim
+| t1A: bitrigesim
+| t1B: bitrigesim
+| t1C: bitrigesim
+| t1D: bitrigesim
+| t1E: bitrigesim
+| t1F: bitrigesim.
+
+(* operatore = *)
+ndefinition eq_bit ≝
+λt1,t2:bitrigesim.
+ match t1 with
+ [ t00 ⇒ match t2 with [ t00 ⇒ true | _ ⇒ false ] | t01 ⇒ match t2 with [ t01 ⇒ true | _ ⇒ false ]
+ | t02 ⇒ match t2 with [ t02 ⇒ true | _ ⇒ false ] | t03 ⇒ match t2 with [ t03 ⇒ true | _ ⇒ false ]
+ | t04 ⇒ match t2 with [ t04 ⇒ true | _ ⇒ false ] | t05 ⇒ match t2 with [ t05 ⇒ true | _ ⇒ false ]
+ | t06 ⇒ match t2 with [ t06 ⇒ true | _ ⇒ false ] | t07 ⇒ match t2 with [ t07 ⇒ true | _ ⇒ false ]
+ | t08 ⇒ match t2 with [ t08 ⇒ true | _ ⇒ false ] | t09 ⇒ match t2 with [ t09 ⇒ true | _ ⇒ false ]
+ | t0A ⇒ match t2 with [ t0A ⇒ true | _ ⇒ false ] | t0B ⇒ match t2 with [ t0B ⇒ true | _ ⇒ false ]
+ | t0C ⇒ match t2 with [ t0C ⇒ true | _ ⇒ false ] | t0D ⇒ match t2 with [ t0D ⇒ true | _ ⇒ false ]
+ | t0E ⇒ match t2 with [ t0E ⇒ true | _ ⇒ false ] | t0F ⇒ match t2 with [ t0F ⇒ true | _ ⇒ false ]
+ | t10 ⇒ match t2 with [ t10 ⇒ true | _ ⇒ false ] | t11 ⇒ match t2 with [ t11 ⇒ true | _ ⇒ false ]
+ | t12 ⇒ match t2 with [ t12 ⇒ true | _ ⇒ false ] | t13 ⇒ match t2 with [ t13 ⇒ true | _ ⇒ false ]
+ | t14 ⇒ match t2 with [ t14 ⇒ true | _ ⇒ false ] | t15 ⇒ match t2 with [ t15 ⇒ true | _ ⇒ false ]
+ | t16 ⇒ match t2 with [ t16 ⇒ true | _ ⇒ false ] | t17 ⇒ match t2 with [ t17 ⇒ true | _ ⇒ false ]
+ | t18 ⇒ match t2 with [ t18 ⇒ true | _ ⇒ false ] | t19 ⇒ match t2 with [ t19 ⇒ true | _ ⇒ false ]
+ | t1A ⇒ match t2 with [ t1A ⇒ true | _ ⇒ false ] | t1B ⇒ match t2 with [ t1B ⇒ true | _ ⇒ false ]
+ | t1C ⇒ match t2 with [ t1C ⇒ true | _ ⇒ false ] | t1D ⇒ match t2 with [ t1D ⇒ true | _ ⇒ false ]
+ | t1E ⇒ match t2 with [ t1E ⇒ true | _ ⇒ false ] | t1F ⇒ match t2 with [ t1F ⇒ true | _ ⇒ false ]
+ ].
+
+(* iteratore sui bitrigesimali *)
+ndefinition forall_bit ≝ λP.
+ P t00 ⊗ P t01 ⊗ P t02 ⊗ P t03 ⊗ P t04 ⊗ P t05 ⊗ P t06 ⊗ P t07 ⊗
+ P t08 ⊗ P t09 ⊗ P t0A ⊗ P t0B ⊗ P t0C ⊗ P t0D ⊗ P t0E ⊗ P t0F ⊗
+ P t10 ⊗ P t11 ⊗ P t12 ⊗ P t13 ⊗ P t14 ⊗ P t15 ⊗ P t16 ⊗ P t17 ⊗
+ P t18 ⊗ P t19 ⊗ P t1A ⊗ P t1B ⊗ P t1C ⊗ P t1D ⊗ P t1E ⊗ P t1F.
+
+(* operatore successore *)
+ndefinition succ_bit ≝
+λn.match n with
+ [ t00 ⇒ t01 | t01 ⇒ t02 | t02 ⇒ t03 | t03 ⇒ t04 | t04 ⇒ t05 | t05 ⇒ t06 | t06 ⇒ t07 | t07 ⇒ t08
+ | t08 ⇒ t09 | t09 ⇒ t0A | t0A ⇒ t0B | t0B ⇒ t0C | t0C ⇒ t0D | t0D ⇒ t0E | t0E ⇒ t0F | t0F ⇒ t10
+ | t10 ⇒ t11 | t11 ⇒ t12 | t12 ⇒ t13 | t13 ⇒ t14 | t14 ⇒ t15 | t15 ⇒ t16 | t16 ⇒ t17 | t17 ⇒ t18
+ | t18 ⇒ t19 | t19 ⇒ t1A | t1A ⇒ t1B | t1B ⇒ t1C | t1C ⇒ t1D | t1D ⇒ t1E | t1E ⇒ t1F | t1F ⇒ t00
+ ].
+
+(* bitrigesimali ricorsivi *)
+ninductive rec_bitrigesim : bitrigesim → Type ≝
+ bi_O : rec_bitrigesim t00
+| bi_S : ∀n.rec_bitrigesim n → rec_bitrigesim (succ_bit n).
+
+(* bitrigesimali → bitrigesimali ricorsivi *)
+ndefinition bit_to_recbit ≝
+λn.match n return λx.rec_bitrigesim x with
+ [ t00 ⇒ bi_O
+ | t01 ⇒ bi_S ? bi_O
+ | t02 ⇒ bi_S ? (bi_S ? bi_O)
+ | t03 ⇒ bi_S ? (bi_S ? (bi_S ? bi_O))
+ | t04 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O)))
+ | t05 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O))))
+ | t06 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O)))))
+ | t07 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O))))))
+ | t08 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ bi_O)))))))
+ | t09 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? bi_O))))))))
+ | t0A ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? bi_O)))))))))
+ | t0B ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))
+ | t0C ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O)))))))))))
+ | t0D ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))))
+ | t0E ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O)))))))))))))
+ | t0F ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))))))
+ | t10 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ bi_O)))))))))))))))
+ | t11 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? bi_O))))))))))))))))
+ | t12 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? bi_O)))))))))))))))))
+ | t13 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))))))))))
+ | t14 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O)))))))))))))))))))
+ | t15 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))))))))))))
+ | t16 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O)))))))))))))))))))))
+ | t17 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))))))))))))))
+ | t18 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ bi_O)))))))))))))))))))))))
+ | t19 ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? bi_O))))))))))))))))))))))))
+ | t1A ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? bi_O)))))))))))))))))))))))))
+ | t1B ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))))))))))))))))))
+ | t1C ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O)))))))))))))))))))))))))))
+ | t1D ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))))))))))))))))))))
+ | t1E ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O)))))))))))))))))))))))))))))
+ | t1F ⇒ bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ?
+ (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? (bi_S ? bi_O))))))))))))))))))))))))))))))
+ ].
+
+ndefinition bitrigesim_destruct_aux ≝
+Πt1,t2:bitrigesim.ΠP:Prop.t1 = t2 →
+ match eq_bit t1 t2 with [ true ⇒ P → P | false ⇒ P ].
+
+ndefinition bitrigesim_destruct : bitrigesim_destruct_aux.
+ #t1; #t2; #P; #H;
+ nrewrite < H;
+ nelim t1;
+ nnormalize;
+ napply (λx.x).
+nqed.
+
+nlemma eq_to_eqbit : ∀n1,n2.n1 = n2 → eq_bit n1 n2 = true.
+ #n1; #n2; #H;
+ nrewrite > H;
+ nelim n2;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma neqbit_to_neq : ∀n1,n2.eq_bit n1 n2 = false → n1 ≠ n2.
+ #n1; #n2; #H;
+ napply (not_to_not (n1 = n2) (eq_bit n1 n2 = true) …);
+ ##[ ##1: napply (eq_to_eqbit n1 n2)
+ ##| ##2: napply (eqfalse_to_neqtrue … H)
+ ##]
+nqed.
+
+(* !!! per brevita... *)
+naxiom eqbit_to_eq : ∀t1,t2.eq_bit t1 t2 = true → t1 = t2.
+
+nlemma neq_to_neqbit : ∀n1,n2.n1 ≠ n2 → eq_bit n1 n2 = false.
+ #n1; #n2; #H;
+ napply (neqtrue_to_eqfalse (eq_bit n1 n2));
+ napply (not_to_not (eq_bit n1 n2 = true) (n1 = n2) ? H);
+ napply (eqbit_to_eq n1 n2).
+nqed.
+
+nlemma decidable_bit : ∀x,y:bitrigesim.decidable (x = y).
+ #x; #y; nnormalize;
+ napply (or2_elim (eq_bit x y = true) (eq_bit x y = false) ? (decidable_bexpr ?));
+ ##[ ##1: #H; napply (or2_intro1 (x = y) (x ≠ y) (eqbit_to_eq … H))
+ ##| ##2: #H; napply (or2_intro2 (x = y) (x ≠ y) (neqbit_to_neq … H))
+ ##]
+nqed.
+
+nlemma symmetric_eqbit : symmetricT bitrigesim bool eq_bit.
+ #n1; #n2;
+ napply (or2_elim (n1 = n2) (n1 ≠ n2) ? (decidable_bit n1 n2));
+ ##[ ##1: #H; nrewrite > H; napply refl_eq
+ ##| ##2: #H; nrewrite > (neq_to_neqbit n1 n2 H);
+ napply (symmetric_eq ? (eq_bit n2 n1) false);
+ napply (neq_to_neqbit n2 n1 (symmetric_neq ? n1 n2 H))
+ ##]
+nqed.
+
+nlemma bitrigesim_is_comparable : comparable.
+ @ bitrigesim
+ ##[ napply t00
+ ##| napply forall_bit
+ ##| napply eq_bit
+ ##| napply eqbit_to_eq
+ ##| napply eq_to_eqbit
+ ##| napply neqbit_to_neq
+ ##| napply neq_to_neqbit
+ ##| napply decidable_bit
+ ##| napply symmetric_eqbit
+ ##]
+nqed.
+
+unification hint 0 ≔ ⊢ carr bitrigesim_is_comparable ≡ bitrigesim.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/theory.ma".
+
+(* ******** *)
+(* BOOLEANI *)
+(* ******** *)
+
+ninductive bool : Type ≝
+ true : bool
+| false : bool.
+
+(* operatori booleani *)
+
+ndefinition eq_bool ≝
+λb1,b2:bool.match b1 with
+ [ true ⇒ match b2 with [ true ⇒ true | false ⇒ false ]
+ | false ⇒ match b2 with [ true ⇒ false | false ⇒ true ]
+ ].
+
+ndefinition not_bool ≝
+λb:bool.match b with [ true ⇒ false | false ⇒ true ].
+
+ndefinition and_bool ≝
+λb1,b2:bool.match b1 with
+ [ true ⇒ b2 | false ⇒ false ].
+
+ndefinition or_bool ≝
+λb1,b2:bool.match b1 with
+ [ true ⇒ true | false ⇒ b2 ].
+
+ndefinition xor_bool ≝
+λb1,b2:bool.match b1 with
+ [ true ⇒ not_bool b2
+ | false ⇒ b2 ].
+
+(* \ominus *)
+notation "hvbox(⊖ a)" non associative with precedence 36
+ for @{ 'not_bool $a }.
+interpretation "not_bool" 'not_bool x = (not_bool x).
+
+(* \otimes *)
+notation "hvbox(a break ⊗ b)" left associative with precedence 35
+ for @{ 'and_bool $a $b }.
+interpretation "and_bool" 'and_bool x y = (and_bool x y).
+
+(* \oplus *)
+notation "hvbox(a break ⊕ b)" left associative with precedence 34
+ for @{ 'or_bool $a $b }.
+interpretation "or_bool" 'or_bool x y = (or_bool x y).
+
+(* \odot *)
+notation "hvbox(a break ⊙ b)" left associative with precedence 33
+ for @{ 'xor_bool $a $b }.
+interpretation "xor_bool" 'xor_bool x y = (xor_bool x y).
+
+ndefinition boolRelation : Type → Type ≝
+λA:Type.A → A → bool.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/bool.ma".
+
+(* ******** *)
+(* BOOLEANI *)
+(* ******** *)
+
+ndefinition bool_destruct_aux ≝
+Πb1,b2:bool.ΠP:Prop.b1 = b2 →
+ match eq_bool b1 b2 with [ true ⇒ P → P | false ⇒ P ].
+
+ndefinition bool_destruct : bool_destruct_aux.
+ #b1; #b2; #P; #H;
+ nrewrite < H;
+ nelim b1;
+ nnormalize;
+ napply (λx.x).
+nqed.
+
+nlemma symmetric_eqbool : symmetricT bool bool eq_bool.
+ #b1; #b2;
+ nelim b1;
+ nelim b2;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_andbool : symmetricT bool bool and_bool.
+ #b1; #b2;
+ nelim b1;
+ nelim b2;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma associative_andbool : ∀b1,b2,b3.((b1 ⊗ b2) ⊗ b3) = (b1 ⊗ (b2 ⊗ b3)).
+ #b1; #b2; #b3;
+ nelim b1;
+ nelim b2;
+ nelim b3;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_orbool : symmetricT bool bool or_bool.
+ #b1; #b2;
+ nelim b1;
+ nelim b2;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma associative_orbool : ∀b1,b2,b3.((b1 ⊕ b2) ⊕ b3) = (b1 ⊕ (b2 ⊕ b3)).
+ #b1; #b2; #b3;
+ nelim b1;
+ nelim b2;
+ nelim b3;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_xorbool : symmetricT bool bool xor_bool.
+ #b1; #b2;
+ nelim b1;
+ nelim b2;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma associative_xorbool : ∀b1,b2,b3.((b1 ⊙ b2) ⊙ b3) = (b1 ⊙ (b2 ⊙ b3)).
+ #b1; #b2; #b3;
+ nelim b1;
+ nelim b2;
+ nelim b3;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma eqbool_to_eq : ∀b1,b2:bool.(eq_bool b1 b2 = true) → (b1 = b2).
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##1,4: #H; napply refl_eq
+ ##| ##*: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma eq_to_eqbool : ∀b1,b2.b1 = b2 → eq_bool b1 b2 = true.
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##1,4: #H; napply refl_eq
+ ##| ##*: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma decidable_bool : ∀x,y:bool.decidable (x = y).
+ #x; #y;
+ nnormalize;
+ nelim x;
+ nelim y;
+ ##[ ##1,4: napply (or2_intro1 (? = ?) (? ≠ ?) …); napply refl_eq
+ ##| ##*: napply (or2_intro2 (? = ?) (? ≠ ?) …);
+ nnormalize; #H;
+ napply False_ind;
+ ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma decidable_bexpr : ∀x.(x = true) ∨ (x = false).
+ #x; ncases x;
+ ##[ ##1: napply (or2_intro1 (true = true) (true = false) (refl_eq …))
+ ##| ##2: napply (or2_intro2 (false = true) (false = false) (refl_eq …))
+ ##]
+nqed.
+
+nlemma neqbool_to_neq : ∀b1,b2:bool.(eq_bool b1 b2 = false) → (b1 ≠ b2).
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##1,4: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##| ##*: #H; #H1; ndestruct (*napply (bool_destruct … H1)*)
+ ##]
+nqed.
+
+nlemma neq_to_neqbool : ∀b1,b2.b1 ≠ b2 → eq_bool b1 b2 = false.
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##1,4: #H; nelim (H (refl_eq …))
+ ##| ##*: #H; napply refl_eq
+ ##]
+nqed.
+
+nlemma eqfalse_to_neqtrue : ∀x.x = false → x ≠ true.
+ #x; nelim x;
+ ##[ ##1: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##| ##2: #H; nnormalize; #H1; ndestruct (*napply (bool_destruct … H1)*)
+ ##]
+nqed.
+
+nlemma eqtrue_to_neqfalse : ∀x.x = true → x ≠ false.
+ #x; nelim x;
+ ##[ ##1: #H; nnormalize; #H1; ndestruct (*napply (bool_destruct … H1)*)
+ ##| ##2: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma neqfalse_to_eqtrue : ∀x.x ≠ false → x = true.
+ #x; nelim x;
+ ##[ ##1: #H; napply refl_eq
+ ##| ##2: nnormalize; #H; nelim (H (refl_eq …))
+ ##]
+nqed.
+
+nlemma neqtrue_to_eqfalse : ∀x.x ≠ true → x = false.
+ #x; nelim x;
+ ##[ ##1: nnormalize; #H; nelim (H (refl_eq …))
+ ##| ##2: #H; napply refl_eq
+ ##]
+nqed.
+
+nlemma andb_true_true_l: ∀b1,b2.(b1 ⊗ b2) = true → b1 = true.
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##1,2: #H; napply refl_eq
+ ##| ##*: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma andb_true_true_r: ∀b1,b2.(b1 ⊗ b2) = true → b2 = true.
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##1,3: #H; napply refl_eq
+ ##| ##*: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma andb_false2
+ : ∀b1,b2.(b1 ⊗ b2) = false →
+ (b1 = false) ∨ (b2 = false).
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##1: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##| ##2,4: #H; napply (or2_intro2 … H)
+ ##| ##3: #H; napply (or2_intro1 … H)
+ ##]
+nqed.
+
+nlemma andb_false3
+ : ∀b1,b2,b3.(b1 ⊗ b2 ⊗ b3) = false →
+ Or3 (b1 = false) (b2 = false) (b3 = false).
+ #b1; #b2; #b3;
+ ncases b1;
+ ncases b2;
+ ncases b3;
+ nnormalize;
+ ##[ ##1: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##| ##5,6,7,8: #H; napply (or3_intro1 … H)
+ ##| ##2,4: #H; napply (or3_intro3 … H)
+ ##| ##3: #H; napply (or3_intro2 … H)
+ ##]
+nqed.
+
+nlemma andb_false4
+ : ∀b1,b2,b3,b4.(b1 ⊗ b2 ⊗ b3 ⊗ b4) = false →
+ Or4 (b1 = false) (b2 = false) (b3 = false) (b4 = false).
+ #b1; #b2; #b3; #b4;
+ ncases b1;
+ ncases b2;
+ ncases b3;
+ ncases b4;
+ nnormalize;
+ ##[ ##1: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##| ##9,10,11,12,13,14,15,16: #H; napply (or4_intro1 … H)
+ ##| ##5,6,7,8: #H; napply (or4_intro2 … H)
+ ##| ##3,4: #H; napply (or4_intro3 … H)
+ ##| ##2: #H; napply (or4_intro4 … H)
+ ##]
+nqed.
+
+nlemma andb_false5
+ : ∀b1,b2,b3,b4,b5.(b1 ⊗ b2 ⊗ b3 ⊗ b4 ⊗ b5) = false →
+ Or5 (b1 = false) (b2 = false) (b3 = false) (b4 = false) (b5 = false).
+ #b1; #b2; #b3; #b4; #b5;
+ ncases b1;
+ ncases b2;
+ ncases b3;
+ ncases b4;
+ ncases b5;
+ nnormalize;
+ ##[ ##1: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##| ##17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32: #H; napply (or5_intro1 … H)
+ ##| ##9,10,11,12,13,14,15,16: #H; napply (or5_intro2 … H)
+ ##| ##5,6,7,8: #H; napply (or5_intro3 … H)
+ ##| ##3,4: #H; napply (or5_intro4 … H)
+ ##| ##2: #H; napply (or5_intro5 … H)
+ ##]
+nqed.
+
+nlemma andb_false2_1 : ∀b.(false ⊗ b) = false.
+ #b; nnormalize; napply refl_eq. nqed.
+nlemma andb_false2_2 : ∀b.(b ⊗ false) = false.
+ #b; nelim b; nnormalize; napply refl_eq. nqed.
+
+nlemma andb_false3_1 : ∀b1,b2.(false ⊗ b1 ⊗ b2) = false.
+ #b1; #b2; nnormalize; napply refl_eq. nqed.
+nlemma andb_false3_2 : ∀b1,b2.(b1 ⊗ false ⊗ b2) = false.
+ #b1; #b2; nelim b1; nnormalize; napply refl_eq. nqed.
+nlemma andb_false3_3 : ∀b1,b2.(b1 ⊗ b2 ⊗ false) = false.
+ #b1; #b2; nelim b1; nelim b2; nnormalize; napply refl_eq. nqed.
+
+nlemma andb_false4_1 : ∀b1,b2,b3.(false ⊗ b1 ⊗ b2 ⊗ b3) = false.
+ #b1; #b2; #b3; nnormalize; napply refl_eq. nqed.
+nlemma andb_false4_2 : ∀b1,b2,b3.(b1 ⊗ false ⊗ b2 ⊗ b3) = false.
+ #b1; #b2; #b3; nelim b1; nnormalize; napply refl_eq. nqed.
+nlemma andb_false4_3 : ∀b1,b2,b3.(b1 ⊗ b2 ⊗ false ⊗ b3) = false.
+ #b1; #b2; #b3; nelim b1; nelim b2; nnormalize; napply refl_eq. nqed.
+nlemma andb_false4_4 : ∀b1,b2,b3.(b1 ⊗ b2 ⊗ b3 ⊗ false) = false.
+ #b1; #b2; #b3; nelim b1; nelim b2; nelim b3; nnormalize; napply refl_eq. nqed.
+
+nlemma andb_false5_1 : ∀b1,b2,b3,b4.(false ⊗ b1 ⊗ b2 ⊗ b3 ⊗ b4) = false.
+ #b1; #b2; #b3; #b4; nnormalize; napply refl_eq. nqed.
+nlemma andb_false5_2 : ∀b1,b2,b3,b4.(b1 ⊗ false ⊗ b2 ⊗ b3 ⊗ b4) = false.
+ #b1; #b2; #b3; #b4; nelim b1; nnormalize; napply refl_eq. nqed.
+nlemma andb_false5_3 : ∀b1,b2,b3,b4.(b1 ⊗ b2 ⊗ false ⊗ b3 ⊗ b4) = false.
+ #b1; #b2; #b3; #b4; nelim b1; nelim b2; nnormalize; napply refl_eq. nqed.
+nlemma andb_false5_4 : ∀b1,b2,b3,b4.(b1 ⊗ b2 ⊗ b3 ⊗ false ⊗ b4) = false.
+ #b1; #b2; #b3; #b4; nelim b1; nelim b2; nelim b3; nnormalize; napply refl_eq. nqed.
+nlemma andb_false5_5 : ∀b1,b2,b3,b4.(b1 ⊗ b2 ⊗ b3 ⊗ b4 ⊗ false) = false.
+ #b1; #b2; #b3; #b4; nelim b1; nelim b2; nelim b3; nelim b4; nnormalize; napply refl_eq. nqed.
+
+nlemma orb_false_false_l : ∀b1,b2:bool.(b1 ⊕ b2) = false → b1 = false.
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##4: #H; napply refl_eq
+ ##| ##*: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma orb_false_false_r : ∀b1,b2:bool.(b1 ⊕ b2) = false → b2 = false.
+ #b1; #b2;
+ ncases b1;
+ ncases b2;
+ nnormalize;
+ ##[ ##4: #H; napply refl_eq
+ ##| ##*: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/comp_num.ma".
+include "num/exadecim.ma".
+include "num/bitrigesim.ma".
+
+(* **** *)
+(* BYTE *)
+(* **** *)
+
+ndefinition byte8 ≝ comp_num exadecim.
+ndefinition mk_byte8 ≝ λe1,e2.mk_comp_num exadecim e1 e2.
+
+(* \langle \rangle *)
+notation "〈x,y〉" non associative with precedence 80
+ for @{ mk_comp_num exadecim $x $y }.
+
+ndefinition byte8_is_comparable_ext ≝ cn_is_comparable_ext exadecim_is_comparable_ext.
+unification hint 0 ≔ ⊢ carr (comp_base byte8_is_comparable_ext) ≡ comp_num exadecim.
+unification hint 0 ≔ ⊢ carr (comp_base byte8_is_comparable_ext) ≡ byte8.
+
+(* operatore estensione unsigned *)
+ndefinition extu_b8 ≝ λe2.〈zeroc ?,e2〉.
+
+(* operatore estensione signed *)
+ndefinition exts_b8 ≝
+λe2.〈(match getMSBc ? e2 with
+ [ true ⇒ predc ? (zeroc ?) | false ⇒ zeroc ? ]),e2〉.
+
+(* operatore moltiplicazione senza segno: e*e=[0x00,0xE1] *)
+ndefinition mulu_ex ≝
+λe1,e2:exadecim.match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x0〉 | x2 ⇒ 〈x0,x0〉 | x3 ⇒ 〈x0,x0〉
+ | x4 ⇒ 〈x0,x0〉 | x5 ⇒ 〈x0,x0〉 | x6 ⇒ 〈x0,x0〉 | x7 ⇒ 〈x0,x0〉
+ | x8 ⇒ 〈x0,x0〉 | x9 ⇒ 〈x0,x0〉 | xA ⇒ 〈x0,x0〉 | xB ⇒ 〈x0,x0〉
+ | xC ⇒ 〈x0,x0〉 | xD ⇒ 〈x0,x0〉 | xE ⇒ 〈x0,x0〉 | xF ⇒ 〈x0,x0〉 ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x1〉 | x2 ⇒ 〈x0,x2〉 | x3 ⇒ 〈x0,x3〉
+ | x4 ⇒ 〈x0,x4〉 | x5 ⇒ 〈x0,x5〉 | x6 ⇒ 〈x0,x6〉 | x7 ⇒ 〈x0,x7〉
+ | x8 ⇒ 〈x0,x8〉 | x9 ⇒ 〈x0,x9〉 | xA ⇒ 〈x0,xA〉 | xB ⇒ 〈x0,xB〉
+ | xC ⇒ 〈x0,xC〉 | xD ⇒ 〈x0,xD〉 | xE ⇒ 〈x0,xE〉 | xF ⇒ 〈x0,xF〉 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x2〉 | x2 ⇒ 〈x0,x4〉 | x3 ⇒ 〈x0,x6〉
+ | x4 ⇒ 〈x0,x8〉 | x5 ⇒ 〈x0,xA〉 | x6 ⇒ 〈x0,xC〉 | x7 ⇒ 〈x0,xE〉
+ | x8 ⇒ 〈x1,x0〉 | x9 ⇒ 〈x1,x2〉 | xA ⇒ 〈x1,x4〉 | xB ⇒ 〈x1,x6〉
+ | xC ⇒ 〈x1,x8〉 | xD ⇒ 〈x1,xA〉 | xE ⇒ 〈x1,xC〉 | xF ⇒ 〈x1,xE〉 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x3〉 | x2 ⇒ 〈x0,x6〉 | x3 ⇒ 〈x0,x9〉
+ | x4 ⇒ 〈x0,xC〉 | x5 ⇒ 〈x0,xF〉 | x6 ⇒ 〈x1,x2〉 | x7 ⇒ 〈x1,x5〉
+ | x8 ⇒ 〈x1,x8〉 | x9 ⇒ 〈x1,xB〉 | xA ⇒ 〈x1,xE〉 | xB ⇒ 〈x2,x1〉
+ | xC ⇒ 〈x2,x4〉 | xD ⇒ 〈x2,x7〉 | xE ⇒ 〈x2,xA〉 | xF ⇒ 〈x2,xD〉 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x4〉 | x2 ⇒ 〈x0,x8〉 | x3 ⇒ 〈x0,xC〉
+ | x4 ⇒ 〈x1,x0〉 | x5 ⇒ 〈x1,x4〉 | x6 ⇒ 〈x1,x8〉 | x7 ⇒ 〈x1,xC〉
+ | x8 ⇒ 〈x2,x0〉 | x9 ⇒ 〈x2,x4〉 | xA ⇒ 〈x2,x8〉 | xB ⇒ 〈x2,xC〉
+ | xC ⇒ 〈x3,x0〉 | xD ⇒ 〈x3,x4〉 | xE ⇒ 〈x3,x8〉 | xF ⇒ 〈x3,xC〉 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x5〉 | x2 ⇒ 〈x0,xA〉 | x3 ⇒ 〈x0,xF〉
+ | x4 ⇒ 〈x1,x4〉 | x5 ⇒ 〈x1,x9〉 | x6 ⇒ 〈x1,xE〉 | x7 ⇒ 〈x2,x3〉
+ | x8 ⇒ 〈x2,x8〉 | x9 ⇒ 〈x2,xD〉 | xA ⇒ 〈x3,x2〉 | xB ⇒ 〈x3,x7〉
+ | xC ⇒ 〈x3,xC〉 | xD ⇒ 〈x4,x1〉 | xE ⇒ 〈x4,x6〉 | xF ⇒ 〈x4,xB〉 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x6〉 | x2 ⇒ 〈x0,xC〉 | x3 ⇒ 〈x1,x2〉
+ | x4 ⇒ 〈x1,x8〉 | x5 ⇒ 〈x1,xE〉 | x6 ⇒ 〈x2,x4〉 | x7 ⇒ 〈x2,xA〉
+ | x8 ⇒ 〈x3,x0〉 | x9 ⇒ 〈x3,x6〉 | xA ⇒ 〈x3,xC〉 | xB ⇒ 〈x4,x2〉
+ | xC ⇒ 〈x4,x8〉 | xD ⇒ 〈x4,xE〉 | xE ⇒ 〈x5,x4〉 | xF ⇒ 〈x5,xA〉 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x7〉 | x2 ⇒ 〈x0,xE〉 | x3 ⇒ 〈x1,x5〉
+ | x4 ⇒ 〈x1,xC〉 | x5 ⇒ 〈x2,x3〉 | x6 ⇒ 〈x2,xA〉 | x7 ⇒ 〈x3,x1〉
+ | x8 ⇒ 〈x3,x8〉 | x9 ⇒ 〈x3,xF〉 | xA ⇒ 〈x4,x6〉 | xB ⇒ 〈x4,xD〉
+ | xC ⇒ 〈x5,x4〉 | xD ⇒ 〈x5,xB〉 | xE ⇒ 〈x6,x2〉 | xF ⇒ 〈x6,x9〉 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x8〉 | x2 ⇒ 〈x1,x0〉 | x3 ⇒ 〈x1,x8〉
+ | x4 ⇒ 〈x2,x0〉 | x5 ⇒ 〈x2,x8〉 | x6 ⇒ 〈x3,x0〉 | x7 ⇒ 〈x3,x8〉
+ | x8 ⇒ 〈x4,x0〉 | x9 ⇒ 〈x4,x8〉 | xA ⇒ 〈x5,x0〉 | xB ⇒ 〈x5,x8〉
+ | xC ⇒ 〈x6,x0〉 | xD ⇒ 〈x6,x8〉 | xE ⇒ 〈x7,x0〉 | xF ⇒ 〈x7,x8〉 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x9〉 | x2 ⇒ 〈x1,x2〉 | x3 ⇒ 〈x1,xB〉
+ | x4 ⇒ 〈x2,x4〉 | x5 ⇒ 〈x2,xD〉 | x6 ⇒ 〈x3,x6〉 | x7 ⇒ 〈x3,xF〉
+ | x8 ⇒ 〈x4,x8〉 | x9 ⇒ 〈x5,x1〉 | xA ⇒ 〈x5,xA〉 | xB ⇒ 〈x6,x3〉
+ | xC ⇒ 〈x6,xC〉 | xD ⇒ 〈x7,x5〉 | xE ⇒ 〈x7,xE〉 | xF ⇒ 〈x8,x7〉 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,xA〉 | x2 ⇒ 〈x1,x4〉 | x3 ⇒ 〈x1,xE〉
+ | x4 ⇒ 〈x2,x8〉 | x5 ⇒ 〈x3,x2〉 | x6 ⇒ 〈x3,xC〉 | x7 ⇒ 〈x4,x6〉
+ | x8 ⇒ 〈x5,x0〉 | x9 ⇒ 〈x5,xA〉 | xA ⇒ 〈x6,x4〉 | xB ⇒ 〈x6,xE〉
+ | xC ⇒ 〈x7,x8〉 | xD ⇒ 〈x8,x2〉 | xE ⇒ 〈x8,xC〉 | xF ⇒ 〈x9,x6〉 ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,xB〉 | x2 ⇒ 〈x1,x6〉 | x3 ⇒ 〈x2,x1〉
+ | x4 ⇒ 〈x2,xC〉 | x5 ⇒ 〈x3,x7〉 | x6 ⇒ 〈x4,x2〉 | x7 ⇒ 〈x4,xD〉
+ | x8 ⇒ 〈x5,x8〉 | x9 ⇒ 〈x6,x3〉 | xA ⇒ 〈x6,xE〉 | xB ⇒ 〈x7,x9〉
+ | xC ⇒ 〈x8,x4〉 | xD ⇒ 〈x8,xF〉 | xE ⇒ 〈x9,xA〉 | xF ⇒ 〈xA,x5〉 ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,xC〉 | x2 ⇒ 〈x1,x8〉 | x3 ⇒ 〈x2,x4〉
+ | x4 ⇒ 〈x3,x0〉 | x5 ⇒ 〈x3,xC〉 | x6 ⇒ 〈x4,x8〉 | x7 ⇒ 〈x5,x4〉
+ | x8 ⇒ 〈x6,x0〉 | x9 ⇒ 〈x6,xC〉 | xA ⇒ 〈x7,x8〉 | xB ⇒ 〈x8,x4〉
+ | xC ⇒ 〈x9,x0〉 | xD ⇒ 〈x9,xC〉 | xE ⇒ 〈xA,x8〉 | xF ⇒ 〈xB,x4〉 ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,xD〉 | x2 ⇒ 〈x1,xA〉 | x3 ⇒ 〈x2,x7〉
+ | x4 ⇒ 〈x3,x4〉 | x5 ⇒ 〈x4,x1〉 | x6 ⇒ 〈x4,xE〉 | x7 ⇒ 〈x5,xB〉
+ | x8 ⇒ 〈x6,x8〉 | x9 ⇒ 〈x7,x5〉 | xA ⇒ 〈x8,x2〉 | xB ⇒ 〈x8,xF〉
+ | xC ⇒ 〈x9,xC〉 | xD ⇒ 〈xA,x9〉 | xE ⇒ 〈xB,x6〉 | xF ⇒ 〈xC,x3〉 ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,xE〉 | x2 ⇒ 〈x1,xC〉 | x3 ⇒ 〈x2,xA〉
+ | x4 ⇒ 〈x3,x8〉 | x5 ⇒ 〈x4,x6〉 | x6 ⇒ 〈x5,x4〉 | x7 ⇒ 〈x6,x2〉
+ | x8 ⇒ 〈x7,x0〉 | x9 ⇒ 〈x7,xE〉 | xA ⇒ 〈x8,xC〉 | xB ⇒ 〈x9,xA〉
+ | xC ⇒ 〈xA,x8〉 | xD ⇒ 〈xB,x6〉 | xE ⇒ 〈xC,x4〉 | xF ⇒ 〈xD,x2〉 ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,xF〉 | x2 ⇒ 〈x1,xE〉 | x3 ⇒ 〈x2,xD〉
+ | x4 ⇒ 〈x3,xC〉 | x5 ⇒ 〈x4,xB〉 | x6 ⇒ 〈x5,xA〉 | x7 ⇒ 〈x6,x9〉
+ | x8 ⇒ 〈x7,x8〉 | x9 ⇒ 〈x8,x7〉 | xA ⇒ 〈x9,x6〉 | xB ⇒ 〈xA,x5〉
+ | xC ⇒ 〈xB,x4〉 | xD ⇒ 〈xC,x3〉 | xE ⇒ 〈xD,x2〉 | xF ⇒ 〈xE,x1〉 ]
+ ].
+
+(* operatore moltiplicazione con segno *)
+ndefinition muls_ex ≝
+λe1,e2:exadecim.match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x0〉 | x2 ⇒ 〈x0,x0〉 | x3 ⇒ 〈x0,x0〉
+ | x4 ⇒ 〈x0,x0〉 | x5 ⇒ 〈x0,x0〉 | x6 ⇒ 〈x0,x0〉 | x7 ⇒ 〈x0,x0〉
+ | x8 ⇒ 〈x0,x0〉 | x9 ⇒ 〈x0,x0〉 | xA ⇒ 〈x0,x0〉 | xB ⇒ 〈x0,x0〉
+ | xC ⇒ 〈x0,x0〉 | xD ⇒ 〈x0,x0〉 | xE ⇒ 〈x0,x0〉 | xF ⇒ 〈x0,x0〉 ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x1〉 | x2 ⇒ 〈x0,x2〉 | x3 ⇒ 〈x0,x3〉
+ | x4 ⇒ 〈x0,x4〉 | x5 ⇒ 〈x0,x5〉 | x6 ⇒ 〈x0,x6〉 | x7 ⇒ 〈x0,x7〉
+ | x8 ⇒ 〈xF,x8〉 | x9 ⇒ 〈xF,x9〉 | xA ⇒ 〈xF,xA〉 | xB ⇒ 〈xF,xB〉
+ | xC ⇒ 〈xF,xC〉 | xD ⇒ 〈xF,xD〉 | xE ⇒ 〈xF,xE〉 | xF ⇒ 〈xF,xF〉 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x2〉 | x2 ⇒ 〈x0,x4〉 | x3 ⇒ 〈x0,x6〉
+ | x4 ⇒ 〈x0,x8〉 | x5 ⇒ 〈x0,xA〉 | x6 ⇒ 〈x0,xC〉 | x7 ⇒ 〈x0,xE〉
+ | x8 ⇒ 〈xF,x0〉 | x9 ⇒ 〈xF,x2〉 | xA ⇒ 〈xF,x4〉 | xB ⇒ 〈xF,x6〉
+ | xC ⇒ 〈xF,x8〉 | xD ⇒ 〈xF,xA〉 | xE ⇒ 〈xF,xC〉 | xF ⇒ 〈xF,xE〉 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x3〉 | x2 ⇒ 〈x0,x6〉 | x3 ⇒ 〈x0,x9〉
+ | x4 ⇒ 〈x0,xC〉 | x5 ⇒ 〈x0,xF〉 | x6 ⇒ 〈x1,x2〉 | x7 ⇒ 〈x1,x5〉
+ | x8 ⇒ 〈xE,x8〉 | x9 ⇒ 〈xE,xB〉 | xA ⇒ 〈xE,xE〉 | xB ⇒ 〈xF,x1〉
+ | xC ⇒ 〈xF,x4〉 | xD ⇒ 〈xF,x7〉 | xE ⇒ 〈xF,xA〉 | xF ⇒ 〈xF,xD〉 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x4〉 | x2 ⇒ 〈x0,x8〉 | x3 ⇒ 〈x0,xC〉
+ | x4 ⇒ 〈x1,x0〉 | x5 ⇒ 〈x1,x4〉 | x6 ⇒ 〈x1,x8〉 | x7 ⇒ 〈x1,xC〉
+ | x8 ⇒ 〈xE,x0〉 | x9 ⇒ 〈xE,x4〉 | xA ⇒ 〈xE,x8〉 | xB ⇒ 〈xE,xC〉
+ | xC ⇒ 〈xF,x0〉 | xD ⇒ 〈xF,x4〉 | xE ⇒ 〈xF,x8〉 | xF ⇒ 〈xF,xC〉 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x5〉 | x2 ⇒ 〈x0,xA〉 | x3 ⇒ 〈x0,xF〉
+ | x4 ⇒ 〈x1,x4〉 | x5 ⇒ 〈x1,x9〉 | x6 ⇒ 〈x1,xE〉 | x7 ⇒ 〈x2,x3〉
+ | x8 ⇒ 〈xD,x8〉 | x9 ⇒ 〈xD,xD〉 | xA ⇒ 〈xE,x2〉 | xB ⇒ 〈xE,x7〉
+ | xC ⇒ 〈xE,xC〉 | xD ⇒ 〈xF,x1〉 | xE ⇒ 〈xF,x6〉 | xF ⇒ 〈xF,xB〉 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x6〉 | x2 ⇒ 〈x0,xC〉 | x3 ⇒ 〈x1,x2〉
+ | x4 ⇒ 〈x1,x8〉 | x5 ⇒ 〈x1,xE〉 | x6 ⇒ 〈x2,x4〉 | x7 ⇒ 〈x2,xA〉
+ | x8 ⇒ 〈xD,x0〉 | x9 ⇒ 〈xD,x6〉 | xA ⇒ 〈xD,xC〉 | xB ⇒ 〈xE,x2〉
+ | xC ⇒ 〈xE,x8〉 | xD ⇒ 〈xE,xE〉 | xE ⇒ 〈xF,x4〉 | xF ⇒ 〈xF,xA〉 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈x0,x7〉 | x2 ⇒ 〈x0,xE〉 | x3 ⇒ 〈x1,x5〉
+ | x4 ⇒ 〈x1,xC〉 | x5 ⇒ 〈x2,x3〉 | x6 ⇒ 〈x2,xA〉 | x7 ⇒ 〈x3,x1〉
+ | x8 ⇒ 〈xC,x8〉 | x9 ⇒ 〈xC,xF〉 | xA ⇒ 〈xD,x6〉 | xB ⇒ 〈xD,xD〉
+ | xC ⇒ 〈xE,x4〉 | xD ⇒ 〈xE,xB〉 | xE ⇒ 〈xF,x2〉 | xF ⇒ 〈xF,x9〉 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈xF,x8〉 | x2 ⇒ 〈xF,x0〉 | x3 ⇒ 〈xE,x8〉
+ | x4 ⇒ 〈xE,x0〉 | x5 ⇒ 〈xD,x8〉 | x6 ⇒ 〈xD,x0〉 | x7 ⇒ 〈xC,x8〉
+ | x8 ⇒ 〈x4,x0〉 | x9 ⇒ 〈x3,x8〉 | xA ⇒ 〈x3,x0〉 | xB ⇒ 〈x2,x8〉
+ | xC ⇒ 〈x2,x0〉 | xD ⇒ 〈x1,x8〉 | xE ⇒ 〈x1,x0〉 | xF ⇒ 〈x0,x8〉 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈xF,x9〉 | x2 ⇒ 〈xF,x2〉 | x3 ⇒ 〈xE,xB〉
+ | x4 ⇒ 〈xE,x4〉 | x5 ⇒ 〈xD,xD〉 | x6 ⇒ 〈xD,x6〉 | x7 ⇒ 〈xC,xF〉
+ | x8 ⇒ 〈x3,x8〉 | x9 ⇒ 〈x3,x1〉 | xA ⇒ 〈x2,xA〉 | xB ⇒ 〈x2,x3〉
+ | xC ⇒ 〈x1,xC〉 | xD ⇒ 〈x1,x5〉 | xE ⇒ 〈x0,xE〉 | xF ⇒ 〈x0,x7〉 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈xF,xA〉 | x2 ⇒ 〈xF,x4〉 | x3 ⇒ 〈xE,xE〉
+ | x4 ⇒ 〈xE,x8〉 | x5 ⇒ 〈xE,x2〉 | x6 ⇒ 〈xD,xC〉 | x7 ⇒ 〈xD,x6〉
+ | x8 ⇒ 〈x3,x0〉 | x9 ⇒ 〈x2,xA〉 | xA ⇒ 〈x2,x4〉 | xB ⇒ 〈x1,xE〉
+ | xC ⇒ 〈x1,x8〉 | xD ⇒ 〈x1,x2〉 | xE ⇒ 〈x0,xC〉 | xF ⇒ 〈x0,x6〉 ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈xF,xB〉 | x2 ⇒ 〈xF,x6〉 | x3 ⇒ 〈xF,x1〉
+ | x4 ⇒ 〈xE,xC〉 | x5 ⇒ 〈xE,x7〉 | x6 ⇒ 〈xE,x2〉 | x7 ⇒ 〈xD,xD〉
+ | x8 ⇒ 〈x2,x8〉 | x9 ⇒ 〈x2,x3〉 | xA ⇒ 〈x1,xE〉 | xB ⇒ 〈x1,x9〉
+ | xC ⇒ 〈x1,x4〉 | xD ⇒ 〈x0,xF〉 | xE ⇒ 〈x0,xA〉 | xF ⇒ 〈x0,x5〉 ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈xF,xC〉 | x2 ⇒ 〈xF,x8〉 | x3 ⇒ 〈xF,x4〉
+ | x4 ⇒ 〈xF,x0〉 | x5 ⇒ 〈xE,xC〉 | x6 ⇒ 〈xE,x8〉 | x7 ⇒ 〈xE,x4〉
+ | x8 ⇒ 〈x2,x0〉 | x9 ⇒ 〈x1,xC〉 | xA ⇒ 〈x1,x8〉 | xB ⇒ 〈x1,x4〉
+ | xC ⇒ 〈x1,x0〉 | xD ⇒ 〈x0,xC〉 | xE ⇒ 〈x0,x8〉 | xF ⇒ 〈x0,x4〉 ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈xF,xD〉 | x2 ⇒ 〈xF,xA〉 | x3 ⇒ 〈xF,x7〉
+ | x4 ⇒ 〈xF,x4〉 | x5 ⇒ 〈xF,x1〉 | x6 ⇒ 〈xE,xE〉 | x7 ⇒ 〈xE,xB〉
+ | x8 ⇒ 〈x1,x8〉 | x9 ⇒ 〈x1,x5〉 | xA ⇒ 〈x1,x2〉 | xB ⇒ 〈x0,xF〉
+ | xC ⇒ 〈x0,xC〉 | xD ⇒ 〈x0,x9〉 | xE ⇒ 〈x0,x6〉 | xF ⇒ 〈x0,x3〉 ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈xF,xE〉 | x2 ⇒ 〈xF,xC〉 | x3 ⇒ 〈xF,xA〉
+ | x4 ⇒ 〈xF,x8〉 | x5 ⇒ 〈xF,x6〉 | x6 ⇒ 〈xF,x4〉 | x7 ⇒ 〈xF,x2〉
+ | x8 ⇒ 〈x1,x0〉 | x9 ⇒ 〈x0,xE〉 | xA ⇒ 〈x0,xC〉 | xB ⇒ 〈x0,xA〉
+ | xC ⇒ 〈x0,x8〉 | xD ⇒ 〈x0,x6〉 | xE ⇒ 〈x0,x4〉 | xF ⇒ 〈x0,x2〉 ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ 〈x0,x0〉 | x1 ⇒ 〈xF,xF〉 | x2 ⇒ 〈xF,xE〉 | x3 ⇒ 〈xF,xD〉
+ | x4 ⇒ 〈xF,xC〉 | x5 ⇒ 〈xF,xB〉 | x6 ⇒ 〈xF,xA〉 | x7 ⇒ 〈xF,x9〉
+ | x8 ⇒ 〈x0,x8〉 | x9 ⇒ 〈x0,x7〉 | xA ⇒ 〈x0,x6〉 | xB ⇒ 〈x0,x5〉
+ | xC ⇒ 〈x0,x4〉 | xD ⇒ 〈x0,x3〉 | xE ⇒ 〈x0,x2〉 | xF ⇒ 〈x0,x1〉 ]
+ ].
+
+(* correzione per somma su BCD *)
+(* input: halfcarry,carry,X(BCD+BCD) *)
+(* output: X',carry' *)
+ndefinition daa_b8 ≝
+λh,c:bool.λX:byte8.
+ match ltc ? X 〈x9,xA〉 with
+ (* [X:0x00-0x99] *)
+ (* c' = c *)
+ (* X' = [(b16l X):0x0-0x9] X + [h=1 ? 0x06 : 0x00] + [c=1 ? 0x60 : 0x00]
+ [(b16l X):0xA-0xF] X + 0x06 + [c=1 ? 0x60 : 0x00] *)
+ [ true ⇒
+ let X' ≝ match (ltc ? (cnL ? X) xA) ⊗ (⊖h) with
+ [ true ⇒ X
+ | false ⇒ plusc_d_d ? X 〈x0,x6〉 ] in
+ let X'' ≝ match c with
+ [ true ⇒ plusc_d_d ? X' 〈x6,x0〉
+ | false ⇒ X' ] in
+ pair … c X''
+ (* [X:0x9A-0xFF] *)
+ (* c' = 1 *)
+ (* X' = [X:0x9A-0xFF]
+ [(b16l X):0x0-0x9] X + [h=1 ? 0x06 : 0x00] + 0x60
+ [(b16l X):0xA-0xF] X + 0x6 + 0x60 *)
+ | false ⇒
+ let X' ≝ match (ltc ? (cnL ? X) xA) ⊗ (⊖h) with
+ [ true ⇒ X
+ | false ⇒ plusc_d_d ? X 〈x0,x6〉 ] in
+ let X'' ≝ plusc_d_d ? X' 〈x6,x0〉 in
+ pair … true X''
+ ].
+
+(* byte ricorsivi *)
+ninductive rec_byte8 : byte8 → Type ≝
+ b8_O : rec_byte8 (zeroc ?)
+| b8_S : ∀n.rec_byte8 n → rec_byte8 (succc ? n).
+
+(* byte → byte ricorsivi *)
+ndefinition b8_to_recb8_aux1 : Πn.rec_byte8 〈n,x0〉 → rec_byte8 〈succc ? n,x0〉 ≝
+λn.λrecb:rec_byte8 〈n,x0〉.
+ b8_S 〈n,xF〉 (b8_S 〈n,xE〉 (b8_S 〈n,xD〉 (b8_S 〈n,xC〉 (
+ b8_S 〈n,xB〉 (b8_S 〈n,xA〉 (b8_S 〈n,x9〉 (b8_S 〈n,x8〉 (
+ b8_S 〈n,x7〉 (b8_S 〈n,x6〉 (b8_S 〈n,x5〉 (b8_S 〈n,x4〉 (
+ b8_S 〈n,x3〉 (b8_S 〈n,x2〉 (b8_S 〈n,x1〉 (b8_S 〈n,x0〉 recb))))))))))))))).
+
+(* ... cifra esadecimale superiore *)
+nlet rec b8_to_recb8_aux2 (n:exadecim) (r:rec_exadecim n) on r ≝
+ match r return λx.λy:rec_exadecim x.rec_byte8 〈x,x0〉 with
+ [ ex_O ⇒ b8_O
+ | ex_S t n' ⇒ b8_to_recb8_aux1 ? (b8_to_recb8_aux2 t n')
+ ].
+
+(* ... cifra esadecimale inferiore *)
+ndefinition b8_to_recb8_aux3 : Πn1,n2.rec_byte8 〈n1,x0〉 → rec_byte8 〈n1,n2〉 ≝
+λn1,n2.λrecb:rec_byte8 〈n1,x0〉.
+ match n2 return λx.rec_byte8 〈n1,x〉 with
+ [ x0 ⇒ recb
+ | x1 ⇒ b8_S 〈n1,x0〉 recb
+ | x2 ⇒ b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb)
+ | x3 ⇒ b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb))
+ | x4 ⇒ b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb)))
+ | x5 ⇒ b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (
+ b8_S 〈n1,x0〉 recb))))
+ | x6 ⇒ b8_S 〈n1,x5〉 (b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (
+ b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb)))))
+ | x7 ⇒ b8_S 〈n1,x6〉 (b8_S 〈n1,x5〉 (b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (
+ b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb))))))
+ | x8 ⇒ b8_S 〈n1,x7〉 (b8_S 〈n1,x6〉 (b8_S 〈n1,x5〉 (b8_S 〈n1,x4〉 (
+ b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb)))))))
+ | x9 ⇒ b8_S 〈n1,x8〉 (b8_S 〈n1,x7〉 (b8_S 〈n1,x6〉 (b8_S 〈n1,x5〉 (
+ b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (
+ b8_S 〈n1,x0〉 recb))))))))
+ | xA ⇒ b8_S 〈n1,x9〉 (b8_S 〈n1,x8〉 (b8_S 〈n1,x7〉 (b8_S 〈n1,x6〉 (
+ b8_S 〈n1,x5〉 (b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (
+ b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb)))))))))
+ | xB ⇒ b8_S 〈n1,xA〉 (b8_S 〈n1,x9〉 (b8_S 〈n1,x8〉 (b8_S 〈n1,x7〉 (
+ b8_S 〈n1,x6〉 (b8_S 〈n1,x5〉 (b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (
+ b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb))))))))))
+ | xC ⇒ b8_S 〈n1,xB〉 (b8_S 〈n1,xA〉 (b8_S 〈n1,x9〉 (b8_S 〈n1,x8〉 (
+ b8_S 〈n1,x7〉 (b8_S 〈n1,x6〉 (b8_S 〈n1,x5〉 (b8_S 〈n1,x4〉 (
+ b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb)))))))))))
+ | xD ⇒ b8_S 〈n1,xC〉 (b8_S 〈n1,xB〉 (b8_S 〈n1,xA〉 (b8_S 〈n1,x9〉 (
+ b8_S 〈n1,x8〉 (b8_S 〈n1,x7〉 (b8_S 〈n1,x6〉 (b8_S 〈n1,x5〉 (
+ b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (
+ b8_S 〈n1,x0〉 recb))))))))))))
+ | xE ⇒ b8_S 〈n1,xD〉 (b8_S 〈n1,xC〉 (b8_S 〈n1,xB〉 (b8_S 〈n1,xA〉 (
+ b8_S 〈n1,x9〉 (b8_S 〈n1,x8〉 (b8_S 〈n1,x7〉 (b8_S 〈n1,x6〉 (
+ b8_S 〈n1,x5〉 (b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (b8_S 〈n1,x2〉 (
+ b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb)))))))))))))
+ | xF ⇒ b8_S 〈n1,xE〉 (b8_S 〈n1,xD〉 (b8_S 〈n1,xC〉 (b8_S 〈n1,xB〉 (
+ b8_S 〈n1,xA〉 (b8_S 〈n1,x9〉 (b8_S 〈n1,x8〉 (b8_S 〈n1,x7〉 (
+ b8_S 〈n1,x6〉 (b8_S 〈n1,x5〉 (b8_S 〈n1,x4〉 (b8_S 〈n1,x3〉 (
+ b8_S 〈n1,x2〉 (b8_S 〈n1,x1〉 (b8_S 〈n1,x0〉 recb))))))))))))))
+ ].
+
+(*
+nlemma b8_to_recb8 : Πb.rec_byte8 b.
+ #b; nletin K ≝ (b8_to_recb8_aux3
+ (b8h b) (b8l b) (b8_to_recb8_aux2 (b8h b) (ex_to_recex (b8h b))));
+ ncases b in K; #e1; #e2; #K; napply K;
+nqed.
+*)
+
+ndefinition b8_to_recb8 : Πb.rec_byte8 b ≝
+λb.match b with
+ [ mk_comp_num h l ⇒ b8_to_recb8_aux3 h l (b8_to_recb8_aux2 h (ex_to_recex h)) ].
+
+(* ottali → esadecimali *)
+ndefinition b8_of_bit ≝
+λn.match n with
+ [ t00 ⇒ 〈x0,x0〉 | t01 ⇒ 〈x0,x1〉 | t02 ⇒ 〈x0,x2〉 | t03 ⇒ 〈x0,x3〉
+ | t04 ⇒ 〈x0,x4〉 | t05 ⇒ 〈x0,x5〉 | t06 ⇒ 〈x0,x6〉 | t07 ⇒ 〈x0,x7〉
+ | t08 ⇒ 〈x0,x8〉 | t09 ⇒ 〈x0,x9〉 | t0A ⇒ 〈x0,xA〉 | t0B ⇒ 〈x0,xB〉
+ | t0C ⇒ 〈x0,xC〉 | t0D ⇒ 〈x0,xD〉 | t0E ⇒ 〈x0,xE〉 | t0F ⇒ 〈x0,xF〉
+ | t10 ⇒ 〈x1,x0〉 | t11 ⇒ 〈x1,x1〉 | t12 ⇒ 〈x1,x2〉 | t13 ⇒ 〈x1,x3〉
+ | t14 ⇒ 〈x1,x4〉 | t15 ⇒ 〈x1,x5〉 | t16 ⇒ 〈x1,x6〉 | t17 ⇒ 〈x1,x7〉
+ | t18 ⇒ 〈x1,x8〉 | t19 ⇒ 〈x1,x9〉 | t1A ⇒ 〈x1,xA〉 | t1B ⇒ 〈x1,xB〉
+ | t1C ⇒ 〈x1,xC〉 | t1D ⇒ 〈x1,xD〉 | t1E ⇒ 〈x1,xE〉 | t1F ⇒ 〈x1,xF〉
+ ].
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/comp.ma".
+include "common/prod.ma".
+
+alias symbol "hint_decl" (instance 1) = "hint_decl_Type1".
+
+nrecord comparable_ext : Type[1] ≝
+ {
+ comp_base : comparable;
+ ltc : (carr comp_base) → (carr comp_base) → bool;
+ lec : (carr comp_base) → (carr comp_base) → bool;
+ gtc : (carr comp_base) → (carr comp_base) → bool;
+ gec : (carr comp_base) → (carr comp_base) → bool;
+ andc : (carr comp_base) → (carr comp_base) → (carr comp_base);
+ orc : (carr comp_base) → (carr comp_base) → (carr comp_base);
+ xorc : (carr comp_base) → (carr comp_base) → (carr comp_base);
+ getMSBc : (carr comp_base) → bool;
+ setMSBc : (carr comp_base) → (carr comp_base);
+ clrMSBc : (carr comp_base) → (carr comp_base);
+ getLSBc : (carr comp_base) → bool;
+ setLSBc : (carr comp_base) → (carr comp_base);
+ clrLSBc : (carr comp_base) → (carr comp_base);
+ rcrc : bool → (carr comp_base) → ProdT bool (carr comp_base);
+ shrc : (carr comp_base) → ProdT bool (carr comp_base);
+ rorc : (carr comp_base) → (carr comp_base);
+ rclc : bool → (carr comp_base) → ProdT bool (carr comp_base);
+ shlc : (carr comp_base) → ProdT bool (carr comp_base);
+ rolc : (carr comp_base) → (carr comp_base);
+ notc : (carr comp_base) → (carr comp_base);
+ plusc_dc_dc : bool → (carr comp_base) → (carr comp_base) → ProdT bool (carr comp_base);
+ plusc_d_dc : (carr comp_base) → (carr comp_base) → ProdT bool (carr comp_base);
+ plusc_dc_d : bool → (carr comp_base) → (carr comp_base) → (carr comp_base);
+ plusc_d_d : (carr comp_base) → (carr comp_base) → (carr comp_base);
+ plusc_dc_c : bool → (carr comp_base) → (carr comp_base) → bool;
+ plusc_d_c : (carr comp_base) → (carr comp_base) → bool;
+ predc : (carr comp_base) → (carr comp_base);
+ succc : (carr comp_base) → (carr comp_base);
+ complc : (carr comp_base) → (carr comp_base);
+ absc : (carr comp_base) → (carr comp_base);
+ inrangec : (carr comp_base) → (carr comp_base) → (carr comp_base) → bool
+ }.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/comp_ext.ma".
+include "num/bool_lemmas.ma".
+
+(* ******** *)
+(* COMPOSTI *)
+(* ******** *)
+
+nrecord comp_num (T:Type) : Type ≝
+ {
+ cnH: T;
+ cnL: T
+ }.
+
+(* operatore = *)
+ndefinition eq_cn ≝
+λT.λfeq:T → T → bool.
+λcn1,cn2:comp_num T.
+ (feq (cnH ? cn1) (cnH ? cn2)) ⊗ (feq (cnL ? cn1) (cnL ? cn2)).
+
+nlemma cn_destruct_1 :
+∀T.∀x1,x2,y1,y2:T.
+ mk_comp_num T x1 y1 = mk_comp_num T x2 y2 → x1 = x2.
+ #T; #x1; #x2; #y1; #y2; #H;
+ nchange with (match mk_comp_num ? x2 y2 with [ mk_comp_num a _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma cn_destruct_2 :
+∀T.∀x1,x2,y1,y2:T.
+ mk_comp_num T x1 y1 = mk_comp_num T x2 y2 → y1 = y2.
+ #T; #x1; #x2; #y1; #y2; #H;
+ nchange with (match mk_comp_num ? x2 y2 with [ mk_comp_num _ b ⇒ y1 = b ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_eqcn :
+∀T.∀feq:T → T → bool.
+ (symmetricT T bool feq) →
+ (symmetricT (comp_num T) bool (eq_cn T feq)).
+ #T; #feq; #H;
+ #b1; nelim b1; #e1; #e2;
+ #b2; nelim b2; #e3; #e4;
+ nchange with (((feq e1 e3)⊗(feq e2 e4)) = ((feq e3 e1)⊗(feq e4 e2)));
+ nrewrite > (H e1 e3);
+ nrewrite > (H e2 e4);
+ napply refl_eq.
+nqed.
+
+nlemma eqcn_to_eq :
+∀T.∀feq:T → T → bool.
+ (∀x,y:T.(feq x y = true) → (x = y)) →
+ (∀b1,b2:comp_num T.
+ ((eq_cn T feq b1 b2 = true) → (b1 = b2))).
+ #T; #feq; #H; #b1; #b2;
+ nelim b1; #e1; #e2;
+ nelim b2; #e3; #e4;
+ nchange in ⊢ (% → ?) with (((feq e1 e3)⊗(feq e2 e4)) = true);
+ #H1;
+ nrewrite < (H … (andb_true_true_l … H1));
+ nrewrite < (H … (andb_true_true_r … H1));
+ napply refl_eq.
+nqed.
+
+nlemma eq_to_eqcn :
+∀T.∀feq:T → T → bool.
+ (∀x,y:T.(x = y) → (feq x y = true)) →
+ (∀b1,b2:comp_num T.
+ ((b1 = b2) → (eq_cn T feq b1 b2 = true))).
+ #T; #feq; #H; #b1; #b2;
+ nelim b1; #e1; #e2;
+ nelim b2; #e3; #e4;
+ #H1;
+ nrewrite < (cn_destruct_1 … H1);
+ nrewrite < (cn_destruct_2 … H1);
+ nchange with (((feq e1 e1)⊗(feq e2 e2)) = true);
+ nrewrite > (H e1 e1 (refl_eq …));
+ nrewrite > (H e2 e2 (refl_eq …));
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma decidable_cn_aux1 :
+∀T.∀e1,e2,e3,e4:T.e1 ≠ e3 → (mk_comp_num T e1 e2) ≠ (mk_comp_num T e3 e4).
+ #T; #e1; #e2; #e3; #e4;
+ nnormalize; #H; #H1;
+ napply (H (cn_destruct_1 … H1)).
+nqed.
+
+nlemma decidable_cn_aux2 :
+∀T.∀e1,e2,e3,e4:T.e2 ≠ e4 → (mk_comp_num T e1 e2) ≠ (mk_comp_num T e3 e4).
+ #T; #e1; #e2; #e3; #e4;
+ nnormalize; #H; #H1;
+ napply (H (cn_destruct_2 … H1)).
+nqed.
+
+nlemma decidable_cn :
+∀T.(∀x,y:T.decidable (x = y)) →
+ (∀b1,b2:comp_num T.
+ (decidable (b1 = b2))).
+ #T; #H;
+ #b1; nelim b1; #e1; #e2;
+ #b2; nelim b2; #e3; #e4;
+ nnormalize;
+ napply (or2_elim (e1 = e3) (e1 ≠ e3) ? (H e1 e3) …);
+ ##[ ##2: #H1; napply (or2_intro2 … (decidable_cn_aux1 T e1 e2 e3 e4 H1))
+ ##| ##1: #H1; napply (or2_elim (e2 = e4) (e2 ≠ e4) ? (H e2 e4) …);
+ ##[ ##2: #H2; napply (or2_intro2 … (decidable_cn_aux2 T e1 e2 e3 e4 H2))
+ ##| ##1: #H2; nrewrite > H1; nrewrite > H2;
+ napply (or2_intro1 … (refl_eq ? (mk_comp_num T e3 e4)))
+ ##]
+ ##]
+nqed.
+
+nlemma neqcn_to_neq :
+∀T.∀feq:T → T → bool.
+ (∀x,y:T.(feq x y = false) → (x ≠ y)) →
+ (∀b1,b2:comp_num T.
+ ((eq_cn T feq b1 b2 = false) → (b1 ≠ b2))).
+ #T; #feq; #H; #b1; #b2;
+ nelim b1; #e1; #e2;
+ nelim b2; #e3; #e4;
+ nchange with ((((feq e1 e3) ⊗ (feq e2 e4)) = false) → ?);
+ #H1;
+ napply (or2_elim ((feq e1 e3) = false) ((feq e2 e4) = false) ? (andb_false2 … H1) …);
+ ##[ ##1: #H2; napply (decidable_cn_aux1 … (H … H2))
+ ##| ##2: #H2; napply (decidable_cn_aux2 … (H … H2))
+ ##]
+nqed.
+
+nlemma cn_destruct :
+∀T.(∀x,y:T.decidable (x = y)) →
+ (∀e1,e2,e3,e4:T.
+ ((mk_comp_num T e1 e2) ≠ (mk_comp_num T e3 e4)) →
+ ((e1 ≠ e3) ∨ (e2 ≠ e4))).
+ #T; #H; #e1; #e2; #e3; #e4;
+ nnormalize; #H1;
+ napply (or2_elim (e1 = e3) (e1 ≠ e3) ? (H e1 e3) …);
+ ##[ ##2: #H2; napply (or2_intro1 … H2)
+ ##| ##1: #H2; napply (or2_elim (e2 = e4) (e2 ≠ e4) ? (H e2 e4) …);
+ ##[ ##2: #H3; napply (or2_intro2 … H3)
+ ##| ##1: #H3; nrewrite > H2 in H1:(%);
+ nrewrite > H3;
+ #H1; nelim (H1 (refl_eq …))
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqcn :
+∀T.∀feq:T → T → bool.
+ (∀x,y:T.(x ≠ y) → (feq x y = false)) →
+ (∀x,y:T.decidable (x = y)) →
+ (∀b1,b2:comp_num T.
+ ((b1 ≠ b2) → (eq_cn T feq b1 b2 = false))).
+ #T; #feq; #H; #H1; #b1; #b2;
+ nelim b1; #e1; #e2;
+ nelim b2; #e3; #e4;
+ #H2; nchange with (((feq e1 e3) ⊗ (feq e2 e4)) = false);
+ napply (or2_elim (e1 ≠ e3) (e2 ≠ e4) ? (cn_destruct T H1 e1 e2 e3 e4 … H2) …);
+ ##[ ##1: #H3; nrewrite > (H … H3); nnormalize; napply refl_eq
+ ##| ##2: #H3; nrewrite > (H … H3);
+ nrewrite > (symmetric_andbool (feq e1 e3) false);
+ nnormalize; napply refl_eq
+ ##]
+nqed.
+
+nlemma cn_is_comparable : comparable → comparable.
+ #T; @ (comp_num T)
+ (* zero *)
+ ##[ napply (mk_comp_num ? (zeroc ?) (zeroc ?))
+ (* forall *)
+ ##| napply (λP.forallc T
+ (λh.forallc T
+ (λl.P (mk_comp_num ? h l))))
+ (* eq *)
+ ##| napply (eq_cn ? (eqc T))
+ (* eqc_to_eq *)
+ ##| napply (eqcn_to_eq … (eqc_to_eq T))
+ (* eq_to_eqc *)
+ ##| napply (eq_to_eqcn … (eq_to_eqc T))
+ (* neqc_to_neq *)
+ ##| napply (neqcn_to_neq … (neqc_to_neq T))
+ (* neq_to_neqc *)
+ ##| napply (neq_to_neqcn … (neq_to_neqc T));
+ napply (decidable_c T)
+ (* decidable_c *)
+ ##| napply (decidable_cn … (decidable_c T))
+ (* symmetric_eqc *)
+ ##| napply (symmetric_eqcn … (symmetric_eqc T))
+ ##]
+nqed.
+
+nlemma cn_is_comparable_ext : comparable_ext → comparable_ext.
+ #T; nelim T; #c;
+ #ltc; #lec; #gtc; #gec; #andc; #orc; #xorc;
+ #getMSBc; #setMSBc; #clrMSBc; #getLSBc; #setLSBc; #clrLSBc;
+ #rcrc; #shrc; #rorc; #rclc; #shlc; #rolc; #notc;
+ #plusc_dc_dc; #plusc_d_dc; #plusc_dc_d; #plusc_d_d; #plusc_dc_c; #plusc_d_c;
+ #predc; #succc; #complc; #absc; #inrangec;
+ napply (mk_comparable_ext);
+ ##[ napply (cn_is_comparable c)
+ (* lt *)
+ ##| napply (λx,y.(ltc (cnH ? x) (cnH ? y)) ⊕
+ (((eqc c) (cnH ? x) (cnH ? y)) ⊗ (ltc (cnL ? x) (cnL ? y))))
+ (* le *)
+ ##| napply (λx,y.(ltc (cnH ? x) (cnH ? y)) ⊕
+ (((eqc c) (cnH ? x) (cnH ? y)) ⊗ (lec (cnL ? x) (cnL ? y))))
+ (* gt *)
+ ##| napply (λx,y.(gtc (cnH ? x) (cnH ? y)) ⊕
+ (((eqc c) (cnH ? x) (cnH ? y)) ⊗ (gtc (cnL ? x) (cnL ? y))))
+ (* ge *)
+ ##| napply (λx,y.(gtc (cnH ? x) (cnH ? y)) ⊕
+ (((eqc c) (cnH ? x) (cnH ? y)) ⊗ (gec (cnL ? x) (cnL ? y))))
+ (* and *)
+ ##| napply (λx,y.mk_comp_num ? (andc (cnH ? x) (cnH ? y))
+ (andc (cnL ? x) (cnL ? y)))
+ (* or *)
+ ##| napply (λx,y.mk_comp_num ? (orc (cnH ? x) (cnH ? y))
+ (orc (cnL ? x) (cnL ? y)))
+ (* xor *)
+ ##| napply (λx,y.mk_comp_num ? (xorc (cnH ? x) (cnH ? y))
+ (xorc (cnL ? x) (cnL ? y)))
+ (* getMSB *)
+ ##| napply (λx.getMSBc (cnH ? x))
+ (* setMSB *)
+ ##| napply (λx.mk_comp_num ? (setMSBc (cnH ? x)) (cnL ? x))
+ (* clrMSB *)
+ ##| napply (λx.mk_comp_num ? (clrMSBc (cnH ? x)) (cnL ? x))
+ (* getLSB *)
+ ##| napply (λx.getLSBc (cnL ? x))
+ (* setLSB *)
+ ##| napply (λx.mk_comp_num ? (cnH ? x) (setLSBc (cnL ? x)))
+ (* clrLSB *)
+ ##| napply (λx.mk_comp_num ? (cnH ? x) (clrLSBc (cnL ? x)))
+ (* rcr *)
+ ##| napply (λcy,x.match rcrc cy (cnH ? x) with
+ [ pair cy' cnh' ⇒ match rcrc cy' (cnL ? x) with
+ [ pair cy'' cnl' ⇒ pair … cy'' (mk_comp_num ? cnh' cnl')]])
+ (* shr *)
+ ##| napply (λx.match shrc (cnH ? x) with
+ [ pair cy' cnh' ⇒ match rcrc cy' (cnL ? x) with
+ [ pair cy'' cnl' ⇒ pair … cy'' (mk_comp_num ? cnh' cnl')]])
+ (* ror *)
+ ##| napply (λx.match shrc (cnH ? x) with
+ [ pair cy' cnh' ⇒ match rcrc cy' (cnL ? x) with
+ [ pair cy'' cnl' ⇒ mk_comp_num ?
+ (match cy'' with [ true ⇒ setMSBc
+ | false ⇒ λh.h ] cnh') cnl']])
+ (* rcl *)
+ ##| napply (λcy,x.match rclc cy (cnL ? x) with
+ [ pair cy' cnl' ⇒ match rclc cy' (cnH ? x) with
+ [ pair cy'' cnh' ⇒ pair … cy'' (mk_comp_num ? cnh' cnl')]])
+ (* shl *)
+ ##| napply (λx.match shlc (cnL ? x) with
+ [ pair cy' cnl' ⇒ match rclc cy' (cnH ? x) with
+ [ pair cy'' cnh' ⇒ pair … cy'' (mk_comp_num ? cnh' cnl')]])
+ (* rol *)
+ ##| napply (λx.match shlc (cnL ? x) with
+ [ pair cy' cnl' ⇒ match rclc cy' (cnH ? x) with
+ [ pair cy'' cnh' ⇒ mk_comp_num ?
+ cnh' (match cy'' with [ true ⇒ setLSBc
+ | false ⇒ λh.h ] cnl')]])
+ (* not *)
+ ##| napply (λx.mk_comp_num ? (notc (cnH ? x)) (notc (cnL ? x)))
+ (* plus_dc_dc *)
+ ##| napply (λcy,x,y.match plusc_dc_dc cy (cnL ? x) (cnL ? y) with
+ [ pair cy' cnl' ⇒ match plusc_dc_dc cy' (cnH ? x) (cnH ? y) with
+ [ pair cy'' cnh' ⇒ pair … cy'' (mk_comp_num ? cnh' cnl')]])
+ (* plus_d_dc *)
+ ##| napply (λx,y.match plusc_d_dc (cnL ? x) (cnL ? y) with
+ [ pair cy' cnl' ⇒ match plusc_dc_dc cy' (cnH ? x) (cnH ? y) with
+ [ pair cy'' cnh' ⇒ pair … cy'' (mk_comp_num ? cnh' cnl')]])
+ (* plus_dc_d *)
+ ##| napply (λcy,x,y.match plusc_dc_dc cy (cnL ? x) (cnL ? y) with
+ [ pair cy' cnl' ⇒ mk_comp_num ? (plusc_dc_d cy' (cnH ? x) (cnH ? y)) cnl'])
+ (* plus_d_d *)
+ ##| napply (λx,y.match plusc_d_dc (cnL ? x) (cnL ? y) with
+ [ pair cy' cnl' ⇒ mk_comp_num ? (plusc_dc_d cy' (cnH ? x) (cnH ? y)) cnl'])
+ (* plus_dc_c *)
+ ##| napply (λcy,x,y.plusc_dc_c (plusc_dc_c cy (cnL ? x) (cnL ? y))
+ (cnH ? x) (cnH ? y))
+ (* plus_d_c *)
+ ##| napply (λx,y.plusc_dc_c (plusc_d_c (cnL ? x) (cnL ? y))
+ (cnH ? x) (cnH ? y))
+ (* pred *)
+ ##| napply (λx.match (eqc c) (zeroc c) (cnL ? x) with
+ [ true ⇒ mk_comp_num ? (predc (cnH ? x)) (predc (cnL ? x))
+ | false ⇒ mk_comp_num ? (cnH ? x) (predc (cnL ? x)) ])
+ (* succ *)
+ ##| napply (λx.match (eqc c) (predc (zeroc c)) (cnL ? x) with
+ [ true ⇒ mk_comp_num ? (succc (cnH ? x)) (succc (cnL ? x))
+ | false ⇒ mk_comp_num ? (cnH ? x) (succc (cnL ? x)) ])
+ (* compl *)
+ ##| napply (λx.(match (eqc c) (zeroc c) (cnL ? x) with
+ [ true ⇒ mk_comp_num ? (complc (cnH ? x)) (complc (cnL ? x))
+ | false ⇒ mk_comp_num ? (notc (cnH ? x)) (complc (cnL ? x)) ]))
+ (* abs *)
+ ##| napply (λx.match getMSBc (cnH ? x) with
+ [ true ⇒ match (eqc c) (zeroc c) (cnL ? x) with
+ [ true ⇒ mk_comp_num ? (complc (cnH ? x)) (complc (cnL ? x))
+ | false ⇒ mk_comp_num ? (notc (cnH ? x)) (complc (cnL ? x)) ]
+ | false ⇒ x ])
+ (* inrange *)
+ ##| napply (λx,inf,sup.
+ match (ltc (cnH ? inf) (cnH ? sup)) ⊕
+ (((eqc c) (cnH ? inf) (cnH ? sup)) ⊗ (lec (cnL ? inf) (cnL ? sup))) with
+ [ true ⇒ and_bool | false ⇒ or_bool ]
+ ((ltc (cnH ? inf) (cnH ? x)) ⊕
+ (((eqc c) (cnH ? inf) (cnH ? x)) ⊗ (lec (cnL ? inf) (cnL ? x))))
+ ((ltc (cnH ? x) (cnH ? sup)) ⊕
+ (((eqc c) (cnH ? x) (cnH ? sup)) ⊗ (lec (cnL ? x) (cnL ? sup)))))
+ ##]
+nqed.
+
+unification hint 0 ≔ S: comparable;
+ T ≟ (carr S),
+ X ≟ (cn_is_comparable S)
+ (*********************************************) ⊢
+ carr X ≡ comp_num T.
+
+ndefinition zeroc ≝ λx:comparable_ext.zeroc (comp_base x).
+ndefinition forallc ≝ λx:comparable_ext.forallc (comp_base x).
+ndefinition eqc ≝ λx:comparable_ext.eqc (comp_base x).
+ndefinition eqc_to_eq ≝ λx:comparable_ext.eqc_to_eq (comp_base x).
+ndefinition eq_to_eqc ≝ λx:comparable_ext.eq_to_eqc (comp_base x).
+ndefinition neqc_to_neq ≝ λx:comparable_ext.neqc_to_neq (comp_base x).
+ndefinition neq_to_neqc ≝ λx:comparable_ext.neq_to_neqc (comp_base x).
+ndefinition decidable_c ≝ λx:comparable_ext.decidable_c (comp_base x).
+ndefinition symmetric_eqc ≝ λx:comparable_ext.symmetric_eqc (comp_base x).
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/comp_ext.ma".
+include "num/bool_lemmas.ma".
+include "num/oct.ma".
+
+(* *********** *)
+(* ESADECIMALI *)
+(* *********** *)
+
+ninductive exadecim : Type ≝
+ x0: exadecim
+| x1: exadecim
+| x2: exadecim
+| x3: exadecim
+| x4: exadecim
+| x5: exadecim
+| x6: exadecim
+| x7: exadecim
+| x8: exadecim
+| x9: exadecim
+| xA: exadecim
+| xB: exadecim
+| xC: exadecim
+| xD: exadecim
+| xE: exadecim
+| xF: exadecim.
+
+(* iteratore sugli esadecimali *)
+ndefinition forall_ex ≝ λP.
+ P x0 ⊗ P x1 ⊗ P x2 ⊗ P x3 ⊗ P x4 ⊗ P x5 ⊗ P x6 ⊗ P x7 ⊗
+ P x8 ⊗ P x9 ⊗ P xA ⊗ P xB ⊗ P xC ⊗ P xD ⊗ P xE ⊗ P xF.
+
+(* operatore = *)
+ndefinition eq_ex ≝
+λe1,e2:exadecim.
+ match e1 with
+ [ x0 ⇒ match e2 with [ x0 ⇒ true | _ ⇒ false ]
+ | x1 ⇒ match e2 with [ x1 ⇒ true | _ ⇒ false ]
+ | x2 ⇒ match e2 with [ x2 ⇒ true | _ ⇒ false ]
+ | x3 ⇒ match e2 with [ x3 ⇒ true | _ ⇒ false ]
+ | x4 ⇒ match e2 with [ x4 ⇒ true | _ ⇒ false ]
+ | x5 ⇒ match e2 with [ x5 ⇒ true | _ ⇒ false ]
+ | x6 ⇒ match e2 with [ x6 ⇒ true | _ ⇒ false ]
+ | x7 ⇒ match e2 with [ x7 ⇒ true | _ ⇒ false ]
+ | x8 ⇒ match e2 with [ x8 ⇒ true | _ ⇒ false ]
+ | x9 ⇒ match e2 with [ x9 ⇒ true | _ ⇒ false ]
+ | xA ⇒ match e2 with [ xA ⇒ true | _ ⇒ false ]
+ | xB ⇒ match e2 with [ xB ⇒ true | _ ⇒ false ]
+ | xC ⇒ match e2 with [ xC ⇒ true | _ ⇒ false ]
+ | xD ⇒ match e2 with [ xD ⇒ true | _ ⇒ false ]
+ | xE ⇒ match e2 with [ xE ⇒ true | _ ⇒ false ]
+ | xF ⇒ match e2 with [ xF ⇒ true | _ ⇒ false ]
+ ].
+
+(* operatore < *)
+ndefinition lt_ex ≝
+λe1,e2:exadecim.
+ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ true | xF ⇒ true ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ true ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ ].
+
+(* operatore ≤ *)
+ndefinition le_ex ≝
+λe1,e2:exadecim.
+ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ true | xF ⇒ true ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ true ]
+ ].
+
+(* operatore > *)
+ndefinition gt_ex ≝
+λe1,e2:exadecim.
+ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ false | xF ⇒ false ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ false ]
+ ].
+
+(* operatore ≥ *)
+ndefinition ge_ex ≝
+λe1,e2:exadecim.
+ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ false | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ false | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ false
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ false | xF ⇒ false ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ false ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true
+ | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ ].
+
+(* operatore and *)
+ndefinition and_ex ≝
+λe1,e2:exadecim.match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x0 | x3 ⇒ x0
+ | x4 ⇒ x0 | x5 ⇒ x0 | x6 ⇒ x0 | x7 ⇒ x0
+ | x8 ⇒ x0 | x9 ⇒ x0 | xA ⇒ x0 | xB ⇒ x0
+ | xC ⇒ x0 | xD ⇒ x0 | xE ⇒ x0 | xF ⇒ x0 ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x0 | x3 ⇒ x1
+ | x4 ⇒ x0 | x5 ⇒ x1 | x6 ⇒ x0 | x7 ⇒ x1
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x0 | xB ⇒ x1
+ | xC ⇒ x0 | xD ⇒ x1 | xE ⇒ x0 | xF ⇒ x1 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x2 | x3 ⇒ x2
+ | x4 ⇒ x0 | x5 ⇒ x0 | x6 ⇒ x2 | x7 ⇒ x2
+ | x8 ⇒ x0 | x9 ⇒ x0 | xA ⇒ x2 | xB ⇒ x2
+ | xC ⇒ x0 | xD ⇒ x0 | xE ⇒ x2 | xF ⇒ x2 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3
+ | x4 ⇒ x0 | x5 ⇒ x1 | x6 ⇒ x2 | x7 ⇒ x3
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x2 | xB ⇒ x3
+ | xC ⇒ x0 | xD ⇒ x1 | xE ⇒ x2 | xF ⇒ x3 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x0 | x3 ⇒ x0
+ | x4 ⇒ x4 | x5 ⇒ x4 | x6 ⇒ x4 | x7 ⇒ x4
+ | x8 ⇒ x0 | x9 ⇒ x0 | xA ⇒ x0 | xB ⇒ x0
+ | xC ⇒ x4 | xD ⇒ x4 | xE ⇒ x4 | xF ⇒ x4 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x0 | x3 ⇒ x1
+ | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x4 | x7 ⇒ x5
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x0 | xB ⇒ x1
+ | xC ⇒ x4 | xD ⇒ x5 | xE ⇒ x4 | xF ⇒ x5 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x2 | x3 ⇒ x2
+ | x4 ⇒ x4 | x5 ⇒ x4 | x6 ⇒ x6 | x7 ⇒ x6
+ | x8 ⇒ x0 | x9 ⇒ x0 | xA ⇒ x2 | xB ⇒ x2
+ | xC ⇒ x4 | xD ⇒ x4 | xE ⇒ x6 | xF ⇒ x6 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3
+ | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x2 | xB ⇒ x3
+ | xC ⇒ x4 | xD ⇒ x5 | xE ⇒ x6 | xF ⇒ x7 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x0 | x3 ⇒ x0
+ | x4 ⇒ x0 | x5 ⇒ x0 | x6 ⇒ x0 | x7 ⇒ x0
+ | x8 ⇒ x8 | x9 ⇒ x8 | xA ⇒ x8 | xB ⇒ x8
+ | xC ⇒ x8 | xD ⇒ x8 | xE ⇒ x8 | xF ⇒ x8 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x0 | x3 ⇒ x1
+ | x4 ⇒ x0 | x5 ⇒ x1 | x6 ⇒ x0 | x7 ⇒ x1
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ x8 | xB ⇒ x9
+ | xC ⇒ x8 | xD ⇒ x9 | xE ⇒ x8 | xF ⇒ x9 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x2 | x3 ⇒ x2
+ | x4 ⇒ x0 | x5 ⇒ x0 | x6 ⇒ x2 | x7 ⇒ x2
+ | x8 ⇒ x8 | x9 ⇒ x8 | xA ⇒ xA | xB ⇒ xA
+ | xC ⇒ x8 | xD ⇒ x8 | xE ⇒ xA | xF ⇒ xA ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3
+ | x4 ⇒ x0 | x5 ⇒ x1 | x6 ⇒ x2 | x7 ⇒ x3
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB
+ | xC ⇒ x8 | xD ⇒ x9 | xE ⇒ xA | xF ⇒ xB ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x0 | x3 ⇒ x0
+ | x4 ⇒ x4 | x5 ⇒ x4 | x6 ⇒ x4 | x7 ⇒ x4
+ | x8 ⇒ x8 | x9 ⇒ x8 | xA ⇒ x8 | xB ⇒ x8
+ | xC ⇒ xC | xD ⇒ xC | xE ⇒ xC | xF ⇒ xC ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x0 | x3 ⇒ x1
+ | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x4 | x7 ⇒ x5
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ x8 | xB ⇒ x9
+ | xC ⇒ xC | xD ⇒ xD | xE ⇒ xC | xF ⇒ xD ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x2 | x3 ⇒ x2
+ | x4 ⇒ x4 | x5 ⇒ x4 | x6 ⇒ x6 | x7 ⇒ x6
+ | x8 ⇒ x8 | x9 ⇒ x8 | xA ⇒ xA | xB ⇒ xA
+ | xC ⇒ xC | xD ⇒ xC | xE ⇒ xE | xF ⇒ xE ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3
+ | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB
+ | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ ].
+
+(* operatore or *)
+ndefinition or_ex ≝
+λe1,e2:exadecim.match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3
+ | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB
+ | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ x1 | x1 ⇒ x1 | x2 ⇒ x3 | x3 ⇒ x3
+ | x4 ⇒ x5 | x5 ⇒ x5 | x6 ⇒ x7 | x7 ⇒ x7
+ | x8 ⇒ x9 | x9 ⇒ x9 | xA ⇒ xB | xB ⇒ xB
+ | xC ⇒ xD | xD ⇒ xD | xE ⇒ xF | xF ⇒ xF ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ x2 | x1 ⇒ x3 | x2 ⇒ x2 | x3 ⇒ x3
+ | x4 ⇒ x6 | x5 ⇒ x7 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ xA | x9 ⇒ xB | xA ⇒ xA | xB ⇒ xB
+ | xC ⇒ xE | xD ⇒ xF | xE ⇒ xE | xF ⇒ xF ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ x3 | x1 ⇒ x3 | x2 ⇒ x3 | x3 ⇒ x3
+ | x4 ⇒ x7 | x5 ⇒ x7 | x6 ⇒ x7 | x7 ⇒ x7
+ | x8 ⇒ xB | x9 ⇒ xB | xA ⇒ xB | xB ⇒ xB
+ | xC ⇒ xF | xD ⇒ xF | xE ⇒ xF | xF ⇒ xF ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ x4 | x1 ⇒ x5 | x2 ⇒ x6 | x3 ⇒ x7
+ | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ xC | x9 ⇒ xD | xA ⇒ xE | xB ⇒ xF
+ | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ x5 | x1 ⇒ x5 | x2 ⇒ x7 | x3 ⇒ x7
+ | x4 ⇒ x5 | x5 ⇒ x5 | x6 ⇒ x7 | x7 ⇒ x7
+ | x8 ⇒ xD | x9 ⇒ xD | xA ⇒ xF | xB ⇒ xF
+ | xC ⇒ xD | xD ⇒ xD | xE ⇒ xF | xF ⇒ xF ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ x6 | x1 ⇒ x7 | x2 ⇒ x6 | x3 ⇒ x7
+ | x4 ⇒ x6 | x5 ⇒ x7 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ xE | x9 ⇒ xF | xA ⇒ xE | xB ⇒ xF
+ | xC ⇒ xE | xD ⇒ xF | xE ⇒ xE | xF ⇒ xF ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ x7 | x1 ⇒ x7 | x2 ⇒ x7 | x3 ⇒ x7
+ | x4 ⇒ x7 | x5 ⇒ x7 | x6 ⇒ x7 | x7 ⇒ x7
+ | x8 ⇒ xF | x9 ⇒ xF | xA ⇒ xF | xB ⇒ xF
+ | xC ⇒ xF | xD ⇒ xF | xE ⇒ xF | xF ⇒ xF ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ x8 | x1 ⇒ x9 | x2 ⇒ xA | x3 ⇒ xB
+ | x4 ⇒ xC | x5 ⇒ xD | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB
+ | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ x9 | x1 ⇒ x9 | x2 ⇒ xB | x3 ⇒ xB
+ | x4 ⇒ xD | x5 ⇒ xD | x6 ⇒ xF | x7 ⇒ xF
+ | x8 ⇒ x9 | x9 ⇒ x9 | xA ⇒ xB | xB ⇒ xB
+ | xC ⇒ xD | xD ⇒ xD | xE ⇒ xF | xF ⇒ xF ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ xA | x1 ⇒ xB | x2 ⇒ xA | x3 ⇒ xB
+ | x4 ⇒ xE | x5 ⇒ xF | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ xA | x9 ⇒ xB | xA ⇒ xA | xB ⇒ xB
+ | xC ⇒ xE | xD ⇒ xF | xE ⇒ xE | xF ⇒ xF ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ xB | x1 ⇒ xB | x2 ⇒ xB | x3 ⇒ xB
+ | x4 ⇒ xF | x5 ⇒ xF | x6 ⇒ xF | x7 ⇒ xF
+ | x8 ⇒ xB | x9 ⇒ xB | xA ⇒ xB | xB ⇒ xB
+ | xC ⇒ xF | xD ⇒ xF | xE ⇒ xF | xF ⇒ xF ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ xC | x1 ⇒ xD | x2 ⇒ xE | x3 ⇒ xF
+ | x4 ⇒ xC | x5 ⇒ xD | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ xC | x9 ⇒ xD | xA ⇒ xE | xB ⇒ xF
+ | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ xD | x1 ⇒ xD | x2 ⇒ xF | x3 ⇒ xF
+ | x4 ⇒ xD | x5 ⇒ xD | x6 ⇒ xF | x7 ⇒ xF
+ | x8 ⇒ xD | x9 ⇒ xD | xA ⇒ xF | xB ⇒ xF
+ | xC ⇒ xD | xD ⇒ xD | xE ⇒ xF | xF ⇒ xF ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ xE | x1 ⇒ xF | x2 ⇒ xE | x3 ⇒ xF
+ | x4 ⇒ xE | x5 ⇒ xF | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ xE | x9 ⇒ xF | xA ⇒ xE | xB ⇒ xF
+ | xC ⇒ xE | xD ⇒ xF | xE ⇒ xE | xF ⇒ xF ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ xF | x1 ⇒ xF | x2 ⇒ xF | x3 ⇒ xF
+ | x4 ⇒ xF | x5 ⇒ xF | x6 ⇒ xF | x7 ⇒ xF
+ | x8 ⇒ xF | x9 ⇒ xF | xA ⇒ xF | xB ⇒ xF
+ | xC ⇒ xF | xD ⇒ xF | xE ⇒ xF | xF ⇒ xF ]
+ ].
+
+(* operatore xor *)
+ndefinition xor_ex ≝
+λe1,e2:exadecim.match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3
+ | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB
+ | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ x1 | x1 ⇒ x0 | x2 ⇒ x3 | x3 ⇒ x2
+ | x4 ⇒ x5 | x5 ⇒ x4 | x6 ⇒ x7 | x7 ⇒ x6
+ | x8 ⇒ x9 | x9 ⇒ x8 | xA ⇒ xB | xB ⇒ xA
+ | xC ⇒ xD | xD ⇒ xC | xE ⇒ xF | xF ⇒ xE ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ x2 | x1 ⇒ x3 | x2 ⇒ x0 | x3 ⇒ x1
+ | x4 ⇒ x6 | x5 ⇒ x7 | x6 ⇒ x4 | x7 ⇒ x5
+ | x8 ⇒ xA | x9 ⇒ xB | xA ⇒ x8 | xB ⇒ x9
+ | xC ⇒ xE | xD ⇒ xF | xE ⇒ xC | xF ⇒ xD ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ x3 | x1 ⇒ x2 | x2 ⇒ x1 | x3 ⇒ x0
+ | x4 ⇒ x7 | x5 ⇒ x6 | x6 ⇒ x5 | x7 ⇒ x4
+ | x8 ⇒ xB | x9 ⇒ xA | xA ⇒ x9 | xB ⇒ x8
+ | xC ⇒ xF | xD ⇒ xE | xE ⇒ xD | xF ⇒ xC ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ x4 | x1 ⇒ x5 | x2 ⇒ x6 | x3 ⇒ x7
+ | x4 ⇒ x0 | x5 ⇒ x1 | x6 ⇒ x2 | x7 ⇒ x3
+ | x8 ⇒ xC | x9 ⇒ xD | xA ⇒ xE | xB ⇒ xF
+ | xC ⇒ x8 | xD ⇒ x9 | xE ⇒ xA | xF ⇒ xB ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ x5 | x1 ⇒ x4 | x2 ⇒ x7 | x3 ⇒ x6
+ | x4 ⇒ x1 | x5 ⇒ x0 | x6 ⇒ x3 | x7 ⇒ x2
+ | x8 ⇒ xD | x9 ⇒ xC | xA ⇒ xF | xB ⇒ xE
+ | xC ⇒ x9 | xD ⇒ x8 | xE ⇒ xB | xF ⇒ xA ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ x6 | x1 ⇒ x7 | x2 ⇒ x4 | x3 ⇒ x5
+ | x4 ⇒ x2 | x5 ⇒ x3 | x6 ⇒ x0 | x7 ⇒ x1
+ | x8 ⇒ xE | x9 ⇒ xF | xA ⇒ xC | xB ⇒ xD
+ | xC ⇒ xA | xD ⇒ xB | xE ⇒ x8 | xF ⇒ x9 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ x7 | x1 ⇒ x6 | x2 ⇒ x5 | x3 ⇒ x4
+ | x4 ⇒ x3 | x5 ⇒ x2 | x6 ⇒ x1 | x7 ⇒ x0
+ | x8 ⇒ xF | x9 ⇒ xE | xA ⇒ xD | xB ⇒ xC
+ | xC ⇒ xB | xD ⇒ xA | xE ⇒ x9 | xF ⇒ x8 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ x8 | x1 ⇒ x9 | x2 ⇒ xA | x3 ⇒ xB
+ | x4 ⇒ xC | x5 ⇒ xD | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x2 | xB ⇒ x3
+ | xC ⇒ x4 | xD ⇒ x5 | xE ⇒ x6 | xF ⇒ x7 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ x9 | x1 ⇒ x8 | x2 ⇒ xB | x3 ⇒ xA
+ | x4 ⇒ xD | x5 ⇒ xC | x6 ⇒ xF | x7 ⇒ xE
+ | x8 ⇒ x1 | x9 ⇒ x0 | xA ⇒ x3 | xB ⇒ x2
+ | xC ⇒ x5 | xD ⇒ x4 | xE ⇒ x7 | xF ⇒ x6 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ xA | x1 ⇒ xB | x2 ⇒ x8 | x3 ⇒ x9
+ | x4 ⇒ xE | x5 ⇒ xF | x6 ⇒ xC | x7 ⇒ xD
+ | x8 ⇒ x2 | x9 ⇒ x3 | xA ⇒ x0 | xB ⇒ x1
+ | xC ⇒ x6 | xD ⇒ x7 | xE ⇒ x4 | xF ⇒ x5 ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ xB | x1 ⇒ xA | x2 ⇒ x9 | x3 ⇒ x8
+ | x4 ⇒ xF | x5 ⇒ xE | x6 ⇒ xD | x7 ⇒ xC
+ | x8 ⇒ x3 | x9 ⇒ x2 | xA ⇒ x1 | xB ⇒ x0
+ | xC ⇒ x7 | xD ⇒ x6 | xE ⇒ x5 | xF ⇒ x4 ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ xC | x1 ⇒ xD | x2 ⇒ xE | x3 ⇒ xF
+ | x4 ⇒ x8 | x5 ⇒ x9 | x6 ⇒ xA | x7 ⇒ xB
+ | x8 ⇒ x4 | x9 ⇒ x5 | xA ⇒ x6 | xB ⇒ x7
+ | xC ⇒ x0 | xD ⇒ x1 | xE ⇒ x2 | xF ⇒ x3 ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ xD | x1 ⇒ xC | x2 ⇒ xF | x3 ⇒ xE
+ | x4 ⇒ x9 | x5 ⇒ x8 | x6 ⇒ xB | x7 ⇒ xA
+ | x8 ⇒ x5 | x9 ⇒ x4 | xA ⇒ x7 | xB ⇒ x6
+ | xC ⇒ x1 | xD ⇒ x0 | xE ⇒ x3 | xF ⇒ x2 ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ xE | x1 ⇒ xF | x2 ⇒ xC | x3 ⇒ xD
+ | x4 ⇒ xA | x5 ⇒ xB | x6 ⇒ x8 | x7 ⇒ x9
+ | x8 ⇒ x6 | x9 ⇒ x7 | xA ⇒ x4 | xB ⇒ x5
+ | xC ⇒ x2 | xD ⇒ x3 | xE ⇒ x0 | xF ⇒ x1 ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ xF | x1 ⇒ xE | x2 ⇒ xD | x3 ⇒ xC
+ | x4 ⇒ xB | x5 ⇒ xA | x6 ⇒ x9 | x7 ⇒ x8
+ | x8 ⇒ x7 | x9 ⇒ x6 | xA ⇒ x5 | xB ⇒ x4
+ | xC ⇒ x3 | xD ⇒ x2 | xE ⇒ x1 | xF ⇒ x0 ]
+ ].
+
+(* operatore Most Significant Bit *)
+ndefinition getMSB_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false
+ | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true
+ | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ].
+
+ndefinition setMSB_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ x8 | x1 ⇒ x9 | x2 ⇒ xA | x3 ⇒ xB
+ | x4 ⇒ xC | x5 ⇒ xD | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB
+ | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ].
+
+ndefinition clrMSB_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3
+ | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x2 | xB ⇒ x3
+ | xC ⇒ x4 | xD ⇒ x5 | xE ⇒ x6 | xF ⇒ x7 ].
+
+(* operatore Least Significant Bit *)
+ndefinition getLSB_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ false | x1 ⇒ true | x2 ⇒ false | x3 ⇒ true
+ | x4 ⇒ false | x5 ⇒ true | x6 ⇒ false | x7 ⇒ true
+ | x8 ⇒ false | x9 ⇒ true | xA ⇒ false | xB ⇒ true
+ | xC ⇒ false | xD ⇒ true | xE ⇒ false | xF ⇒ true ].
+
+ndefinition setLSB_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ x1 | x1 ⇒ x1 | x2 ⇒ x3 | x3 ⇒ x3
+ | x4 ⇒ x5 | x5 ⇒ x5 | x6 ⇒ x7 | x7 ⇒ x7
+ | x8 ⇒ x9 | x9 ⇒ x9 | xA ⇒ xB | xB ⇒ xB
+ | xC ⇒ xD | xD ⇒ xD | xE ⇒ xF | xF ⇒ xF ].
+
+ndefinition clrLSB_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ x0 | x1 ⇒ x0 | x2 ⇒ x2 | x3 ⇒ x2
+ | x4 ⇒ x4 | x5 ⇒ x4 | x6 ⇒ x6 | x7 ⇒ x6
+ | x8 ⇒ x8 | x9 ⇒ x8 | xA ⇒ xA | xB ⇒ xA
+ | xC ⇒ xC | xD ⇒ xC | xE ⇒ xE | xF ⇒ xE ].
+
+(* operatore rotazione destra con carry *)
+ndefinition rcr_ex ≝
+λc:bool.λe:exadecim.match c with
+ [ true ⇒ match e with
+ [ x0 ⇒ pair … false x8 | x1 ⇒ pair … true x8
+ | x2 ⇒ pair … false x9 | x3 ⇒ pair … true x9
+ | x4 ⇒ pair … false xA | x5 ⇒ pair … true xA
+ | x6 ⇒ pair … false xB | x7 ⇒ pair … true xB
+ | x8 ⇒ pair … false xC | x9 ⇒ pair … true xC
+ | xA ⇒ pair … false xD | xB ⇒ pair … true xD
+ | xC ⇒ pair … false xE | xD ⇒ pair … true xE
+ | xE ⇒ pair … false xF | xF ⇒ pair … true xF ]
+ | false ⇒ match e with
+ [ x0 ⇒ pair … false x0 | x1 ⇒ pair … true x0
+ | x2 ⇒ pair … false x1 | x3 ⇒ pair … true x1
+ | x4 ⇒ pair … false x2 | x5 ⇒ pair … true x2
+ | x6 ⇒ pair … false x3 | x7 ⇒ pair … true x3
+ | x8 ⇒ pair … false x4 | x9 ⇒ pair … true x4
+ | xA ⇒ pair … false x5 | xB ⇒ pair … true x5
+ | xC ⇒ pair … false x6 | xD ⇒ pair … true x6
+ | xE ⇒ pair … false x7 | xF ⇒ pair … true x7 ]
+ ].
+
+(* operatore shift destro *)
+ndefinition shr_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ pair … false x0 | x1 ⇒ pair … true x0
+ | x2 ⇒ pair … false x1 | x3 ⇒ pair … true x1
+ | x4 ⇒ pair … false x2 | x5 ⇒ pair … true x2
+ | x6 ⇒ pair … false x3 | x7 ⇒ pair … true x3
+ | x8 ⇒ pair … false x4 | x9 ⇒ pair … true x4
+ | xA ⇒ pair … false x5 | xB ⇒ pair … true x5
+ | xC ⇒ pair … false x6 | xD ⇒ pair … true x6
+ | xE ⇒ pair … false x7 | xF ⇒ pair … true x7 ].
+
+(* operatore rotazione destra *)
+ndefinition ror_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ x0 | x1 ⇒ x8 | x2 ⇒ x1 | x3 ⇒ x9
+ | x4 ⇒ x2 | x5 ⇒ xA | x6 ⇒ x3 | x7 ⇒ xB
+ | x8 ⇒ x4 | x9 ⇒ xC | xA ⇒ x5 | xB ⇒ xD
+ | xC ⇒ x6 | xD ⇒ xE | xE ⇒ x7 | xF ⇒ xF ].
+
+(* operatore rotazione sinistra con carry *)
+ndefinition rcl_ex ≝
+λc:bool.λe:exadecim.match c with
+ [ true ⇒ match e with
+ [ x0 ⇒ pair … false x1 | x1 ⇒ pair … false x3
+ | x2 ⇒ pair … false x5 | x3 ⇒ pair … false x7
+ | x4 ⇒ pair … false x9 | x5 ⇒ pair … false xB
+ | x6 ⇒ pair … false xD | x7 ⇒ pair … false xF
+ | x8 ⇒ pair … true x1 | x9 ⇒ pair … true x3
+ | xA ⇒ pair … true x5 | xB ⇒ pair … true x7
+ | xC ⇒ pair … true x9 | xD ⇒ pair … true xB
+ | xE ⇒ pair … true xD | xF ⇒ pair … true xF ]
+ | false ⇒ match e with
+ [ x0 ⇒ pair … false x0 | x1 ⇒ pair … false x2
+ | x2 ⇒ pair … false x4 | x3 ⇒ pair … false x6
+ | x4 ⇒ pair … false x8 | x5 ⇒ pair … false xA
+ | x6 ⇒ pair … false xC | x7 ⇒ pair … false xE
+ | x8 ⇒ pair … true x0 | x9 ⇒ pair … true x2
+ | xA ⇒ pair … true x4 | xB ⇒ pair … true x6
+ | xC ⇒ pair … true x8 | xD ⇒ pair … true xA
+ | xE ⇒ pair … true xC | xF ⇒ pair … true xE ]
+ ].
+
+(* operatore shift sinistro *)
+ndefinition shl_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ pair … false x0 | x1 ⇒ pair … false x2
+ | x2 ⇒ pair … false x4 | x3 ⇒ pair … false x6
+ | x4 ⇒ pair … false x8 | x5 ⇒ pair … false xA
+ | x6 ⇒ pair … false xC | x7 ⇒ pair … false xE
+ | x8 ⇒ pair … true x0 | x9 ⇒ pair … true x2
+ | xA ⇒ pair … true x4 | xB ⇒ pair … true x6
+ | xC ⇒ pair … true x8 | xD ⇒ pair … true xA
+ | xE ⇒ pair … true xC | xF ⇒ pair … true xE ].
+
+(* operatore rotazione sinistra *)
+ndefinition rol_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ x0 | x1 ⇒ x2 | x2 ⇒ x4 | x3 ⇒ x6
+ | x4 ⇒ x8 | x5 ⇒ xA | x6 ⇒ xC | x7 ⇒ xE
+ | x8 ⇒ x1 | x9 ⇒ x3 | xA ⇒ x5 | xB ⇒ x7
+ | xC ⇒ x9 | xD ⇒ xB | xE ⇒ xD | xF ⇒ xF ].
+
+(* operatore not/complemento a 1 *)
+ndefinition not_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ xF | x1 ⇒ xE | x2 ⇒ xD | x3 ⇒ xC
+ | x4 ⇒ xB | x5 ⇒ xA | x6 ⇒ x9 | x7 ⇒ x8
+ | x8 ⇒ x7 | x9 ⇒ x6 | xA ⇒ x5 | xB ⇒ x4
+ | xC ⇒ x3 | xD ⇒ x2 | xE ⇒ x1 | xF ⇒ x0 ].
+
+(* operatore somma con data+carry → data+carry *)
+ndefinition plus_ex_dc_dc ≝
+λc:bool.λe1,e2:exadecim.
+ match c with
+ [ true ⇒ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ pair … false x1 | x1 ⇒ pair … false x2 | x2 ⇒ pair … false x3 | x3 ⇒ pair … false x4
+ | x4 ⇒ pair … false x5 | x5 ⇒ pair … false x6 | x6 ⇒ pair … false x7 | x7 ⇒ pair … false x8
+ | x8 ⇒ pair … false x9 | x9 ⇒ pair … false xA | xA ⇒ pair … false xB | xB ⇒ pair … false xC
+ | xC ⇒ pair … false xD | xD ⇒ pair … false xE | xE ⇒ pair … false xF | xF ⇒ pair … true x0 ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ pair … false x2 | x1 ⇒ pair … false x3 | x2 ⇒ pair … false x4 | x3 ⇒ pair … false x5
+ | x4 ⇒ pair … false x6 | x5 ⇒ pair … false x7 | x6 ⇒ pair … false x8 | x7 ⇒ pair … false x9
+ | x8 ⇒ pair … false xA | x9 ⇒ pair … false xB | xA ⇒ pair … false xC | xB ⇒ pair … false xD
+ | xC ⇒ pair … false xE | xD ⇒ pair … false xF | xE ⇒ pair … true x0 | xF ⇒ pair … true x1 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ pair … false x3 | x1 ⇒ pair … false x4 | x2 ⇒ pair … false x5 | x3 ⇒ pair … false x6
+ | x4 ⇒ pair … false x7 | x5 ⇒ pair … false x8 | x6 ⇒ pair … false x9 | x7 ⇒ pair … false xA
+ | x8 ⇒ pair … false xB | x9 ⇒ pair … false xC | xA ⇒ pair … false xD | xB ⇒ pair … false xE
+ | xC ⇒ pair … false xF | xD ⇒ pair … true x0 | xE ⇒ pair … true x1 | xF ⇒ pair … true x2 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ pair … false x4 | x1 ⇒ pair … false x5 | x2 ⇒ pair … false x6 | x3 ⇒ pair … false x7
+ | x4 ⇒ pair … false x8 | x5 ⇒ pair … false x9 | x6 ⇒ pair … false xA | x7 ⇒ pair … false xB
+ | x8 ⇒ pair … false xC | x9 ⇒ pair … false xD | xA ⇒ pair … false xE | xB ⇒ pair … false xF
+ | xC ⇒ pair … true x0 | xD ⇒ pair … true x1 | xE ⇒ pair … true x2 | xF ⇒ pair … true x3 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ pair … false x5 | x1 ⇒ pair … false x6 | x2 ⇒ pair … false x7 | x3 ⇒ pair … false x8
+ | x4 ⇒ pair … false x9 | x5 ⇒ pair … false xA | x6 ⇒ pair … false xB | x7 ⇒ pair … false xC
+ | x8 ⇒ pair … false xD | x9 ⇒ pair … false xE | xA ⇒ pair … false xF | xB ⇒ pair … true x0
+ | xC ⇒ pair … true x1 | xD ⇒ pair … true x2 | xE ⇒ pair … true x3 | xF ⇒ pair … true x4 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ pair … false x6 | x1 ⇒ pair … false x7 | x2 ⇒ pair … false x8 | x3 ⇒ pair … false x9
+ | x4 ⇒ pair … false xA | x5 ⇒ pair … false xB | x6 ⇒ pair … false xC | x7 ⇒ pair … false xD
+ | x8 ⇒ pair … false xE | x9 ⇒ pair … false xF | xA ⇒ pair … true x0 | xB ⇒ pair … true x1
+ | xC ⇒ pair … true x2 | xD ⇒ pair … true x3 | xE ⇒ pair … true x4 | xF ⇒ pair … true x5 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ pair … false x7 | x1 ⇒ pair … false x8 | x2 ⇒ pair … false x9 | x3 ⇒ pair … false xA
+ | x4 ⇒ pair … false xB | x5 ⇒ pair … false xC | x6 ⇒ pair … false xD | x7 ⇒ pair … false xE
+ | x8 ⇒ pair … false xF | x9 ⇒ pair … true x0 | xA ⇒ pair … true x1 | xB ⇒ pair … true x2
+ | xC ⇒ pair … true x3 | xD ⇒ pair … true x4 | xE ⇒ pair … true x5 | xF ⇒ pair … true x6 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ pair … false x8 | x1 ⇒ pair … false x9 | x2 ⇒ pair … false xA | x3 ⇒ pair … false xB
+ | x4 ⇒ pair … false xC | x5 ⇒ pair … false xD | x6 ⇒ pair … false xE | x7 ⇒ pair … false xF
+ | x8 ⇒ pair … true x0 | x9 ⇒ pair … true x1 | xA ⇒ pair … true x2 | xB ⇒ pair … true x3
+ | xC ⇒ pair … true x4 | xD ⇒ pair … true x5 | xE ⇒ pair … true x6 | xF ⇒ pair … true x7 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ pair … false x9 | x1 ⇒ pair … false xA | x2 ⇒ pair … false xB | x3 ⇒ pair … false xC
+ | x4 ⇒ pair … false xD | x5 ⇒ pair … false xE | x6 ⇒ pair … false xF | x7 ⇒ pair … true x0
+ | x8 ⇒ pair … true x1 | x9 ⇒ pair … true x2 | xA ⇒ pair … true x3 | xB ⇒ pair … true x4
+ | xC ⇒ pair … true x5 | xD ⇒ pair … true x6 | xE ⇒ pair … true x7 | xF ⇒ pair … true x8 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ pair … false xA | x1 ⇒ pair … false xB | x2 ⇒ pair … false xC | x3 ⇒ pair … false xD
+ | x4 ⇒ pair … false xE | x5 ⇒ pair … false xF | x6 ⇒ pair … true x0 | x7 ⇒ pair … true x1
+ | x8 ⇒ pair … true x2 | x9 ⇒ pair … true x3 | xA ⇒ pair … true x4 | xB ⇒ pair … true x5
+ | xC ⇒ pair … true x6 | xD ⇒ pair … true x7 | xE ⇒ pair … true x8 | xF ⇒ pair … true x9 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ pair … false xB | x1 ⇒ pair … false xC | x2 ⇒ pair … false xD | x3 ⇒ pair … false xE
+ | x4 ⇒ pair … false xF | x5 ⇒ pair … true x0 | x6 ⇒ pair … true x1 | x7 ⇒ pair … true x2
+ | x8 ⇒ pair … true x3 | x9 ⇒ pair … true x4 | xA ⇒ pair … true x5 | xB ⇒ pair … true x6
+ | xC ⇒ pair … true x7 | xD ⇒ pair … true x8 | xE ⇒ pair … true x9 | xF ⇒ pair … true xA ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ pair … false xC | x1 ⇒ pair … false xD | x2 ⇒ pair … false xE | x3 ⇒ pair … false xF
+ | x4 ⇒ pair … true x0 | x5 ⇒ pair … true x1 | x6 ⇒ pair … true x2 | x7 ⇒ pair … true x3
+ | x8 ⇒ pair … true x4 | x9 ⇒ pair … true x5 | xA ⇒ pair … true x6 | xB ⇒ pair … true x7
+ | xC ⇒ pair … true x8 | xD ⇒ pair … true x9 | xE ⇒ pair … true xA | xF ⇒ pair … true xB ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ pair … false xD | x1 ⇒ pair … false xE | x2 ⇒ pair … false xF | x3 ⇒ pair … true x0
+ | x4 ⇒ pair … true x1 | x5 ⇒ pair … true x2 | x6 ⇒ pair … true x3 | x7 ⇒ pair … true x4
+ | x8 ⇒ pair … true x5 | x9 ⇒ pair … true x6 | xA ⇒ pair … true x7 | xB ⇒ pair … true x8
+ | xC ⇒ pair … true x9 | xD ⇒ pair … true xA | xE ⇒ pair … true xB | xF ⇒ pair … true xC ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ pair … false xE | x1 ⇒ pair … false xF | x2 ⇒ pair … true x0 | x3 ⇒ pair … true x1
+ | x4 ⇒ pair … true x2 | x5 ⇒ pair … true x3 | x6 ⇒ pair … true x4 | x7 ⇒ pair … true x5
+ | x8 ⇒ pair … true x6 | x9 ⇒ pair … true x7 | xA ⇒ pair … true x8 | xB ⇒ pair … true x9
+ | xC ⇒ pair … true xA | xD ⇒ pair … true xB | xE ⇒ pair … true xC | xF ⇒ pair … true xD ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ pair … false xF | x1 ⇒ pair … true x0 | x2 ⇒ pair … true x1 | x3 ⇒ pair … true x2
+ | x4 ⇒ pair … true x3 | x5 ⇒ pair … true x4 | x6 ⇒ pair … true x5 | x7 ⇒ pair … true x6
+ | x8 ⇒ pair … true x7 | x9 ⇒ pair … true x8 | xA ⇒ pair … true x9 | xB ⇒ pair … true xA
+ | xC ⇒ pair … true xB | xD ⇒ pair … true xC | xE ⇒ pair … true xD | xF ⇒ pair … true xE ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ pair … true x0 | x1 ⇒ pair … true x1 | x2 ⇒ pair … true x2 | x3 ⇒ pair … true x3
+ | x4 ⇒ pair … true x4 | x5 ⇒ pair … true x5 | x6 ⇒ pair … true x6 | x7 ⇒ pair … true x7
+ | x8 ⇒ pair … true x8 | x9 ⇒ pair … true x9 | xA ⇒ pair … true xA | xB ⇒ pair … true xB
+ | xC ⇒ pair … true xC | xD ⇒ pair … true xD | xE ⇒ pair … true xE | xF ⇒ pair … true xF ]
+ ]
+ | false ⇒ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ pair … false x0 | x1 ⇒ pair … false x1 | x2 ⇒ pair … false x2 | x3 ⇒ pair … false x3
+ | x4 ⇒ pair … false x4 | x5 ⇒ pair … false x5 | x6 ⇒ pair … false x6 | x7 ⇒ pair … false x7
+ | x8 ⇒ pair … false x8 | x9 ⇒ pair … false x9 | xA ⇒ pair … false xA | xB ⇒ pair … false xB
+ | xC ⇒ pair … false xC | xD ⇒ pair … false xD | xE ⇒ pair … false xE | xF ⇒ pair … false xF ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ pair … false x1 | x1 ⇒ pair … false x2 | x2 ⇒ pair … false x3 | x3 ⇒ pair … false x4
+ | x4 ⇒ pair … false x5 | x5 ⇒ pair … false x6 | x6 ⇒ pair … false x7 | x7 ⇒ pair … false x8
+ | x8 ⇒ pair … false x9 | x9 ⇒ pair … false xA | xA ⇒ pair … false xB | xB ⇒ pair … false xC
+ | xC ⇒ pair … false xD | xD ⇒ pair … false xE | xE ⇒ pair … false xF | xF ⇒ pair … true x0 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ pair … false x2 | x1 ⇒ pair … false x3 | x2 ⇒ pair … false x4 | x3 ⇒ pair … false x5
+ | x4 ⇒ pair … false x6 | x5 ⇒ pair … false x7 | x6 ⇒ pair … false x8 | x7 ⇒ pair … false x9
+ | x8 ⇒ pair … false xA | x9 ⇒ pair … false xB | xA ⇒ pair … false xC | xB ⇒ pair … false xD
+ | xC ⇒ pair … false xE | xD ⇒ pair … false xF | xE ⇒ pair … true x0 | xF ⇒ pair … true x1 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ pair … false x3 | x1 ⇒ pair … false x4 | x2 ⇒ pair … false x5 | x3 ⇒ pair … false x6
+ | x4 ⇒ pair … false x7 | x5 ⇒ pair … false x8 | x6 ⇒ pair … false x9 | x7 ⇒ pair … false xA
+ | x8 ⇒ pair … false xB | x9 ⇒ pair … false xC | xA ⇒ pair … false xD | xB ⇒ pair … false xE
+ | xC ⇒ pair … false xF | xD ⇒ pair … true x0 | xE ⇒ pair … true x1 | xF ⇒ pair … true x2 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ pair … false x4 | x1 ⇒ pair … false x5 | x2 ⇒ pair … false x6 | x3 ⇒ pair … false x7
+ | x4 ⇒ pair … false x8 | x5 ⇒ pair … false x9 | x6 ⇒ pair … false xA | x7 ⇒ pair … false xB
+ | x8 ⇒ pair … false xC | x9 ⇒ pair … false xD | xA ⇒ pair … false xE | xB ⇒ pair … false xF
+ | xC ⇒ pair … true x0 | xD ⇒ pair … true x1 | xE ⇒ pair … true x2 | xF ⇒ pair … true x3 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ pair … false x5 | x1 ⇒ pair … false x6 | x2 ⇒ pair … false x7 | x3 ⇒ pair … false x8
+ | x4 ⇒ pair … false x9 | x5 ⇒ pair … false xA | x6 ⇒ pair … false xB | x7 ⇒ pair … false xC
+ | x8 ⇒ pair … false xD | x9 ⇒ pair … false xE | xA ⇒ pair … false xF | xB ⇒ pair … true x0
+ | xC ⇒ pair … true x1 | xD ⇒ pair … true x2 | xE ⇒ pair … true x3 | xF ⇒ pair … true x4 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ pair … false x6 | x1 ⇒ pair … false x7 | x2 ⇒ pair … false x8 | x3 ⇒ pair … false x9
+ | x4 ⇒ pair … false xA | x5 ⇒ pair … false xB | x6 ⇒ pair … false xC | x7 ⇒ pair … false xD
+ | x8 ⇒ pair … false xE | x9 ⇒ pair … false xF | xA ⇒ pair … true x0 | xB ⇒ pair … true x1
+ | xC ⇒ pair … true x2 | xD ⇒ pair … true x3 | xE ⇒ pair … true x4 | xF ⇒ pair … true x5 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ pair … false x7 | x1 ⇒ pair … false x8 | x2 ⇒ pair … false x9 | x3 ⇒ pair … false xA
+ | x4 ⇒ pair … false xB | x5 ⇒ pair … false xC | x6 ⇒ pair … false xD | x7 ⇒ pair … false xE
+ | x8 ⇒ pair … false xF | x9 ⇒ pair … true x0 | xA ⇒ pair … true x1 | xB ⇒ pair … true x2
+ | xC ⇒ pair … true x3 | xD ⇒ pair … true x4 | xE ⇒ pair … true x5 | xF ⇒ pair … true x6 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ pair … false x8 | x1 ⇒ pair … false x9 | x2 ⇒ pair … false xA | x3 ⇒ pair … false xB
+ | x4 ⇒ pair … false xC | x5 ⇒ pair … false xD | x6 ⇒ pair … false xE | x7 ⇒ pair … false xF
+ | x8 ⇒ pair … true x0 | x9 ⇒ pair … true x1 | xA ⇒ pair … true x2 | xB ⇒ pair … true x3
+ | xC ⇒ pair … true x4 | xD ⇒ pair … true x5 | xE ⇒ pair … true x6 | xF ⇒ pair … true x7 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ pair … false x9 | x1 ⇒ pair … false xA | x2 ⇒ pair … false xB | x3 ⇒ pair … false xC
+ | x4 ⇒ pair … false xD | x5 ⇒ pair … false xE | x6 ⇒ pair … false xF | x7 ⇒ pair … true x0
+ | x8 ⇒ pair … true x1 | x9 ⇒ pair … true x2 | xA ⇒ pair … true x3 | xB ⇒ pair … true x4
+ | xC ⇒ pair … true x5 | xD ⇒ pair … true x6 | xE ⇒ pair … true x7 | xF ⇒ pair … true x8 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ pair … false xA | x1 ⇒ pair … false xB | x2 ⇒ pair … false xC | x3 ⇒ pair … false xD
+ | x4 ⇒ pair … false xE | x5 ⇒ pair … false xF | x6 ⇒ pair … true x0 | x7 ⇒ pair … true x1
+ | x8 ⇒ pair … true x2 | x9 ⇒ pair … true x3 | xA ⇒ pair … true x4 | xB ⇒ pair … true x5
+ | xC ⇒ pair … true x6 | xD ⇒ pair … true x7 | xE ⇒ pair … true x8 | xF ⇒ pair … true x9 ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ pair … false xB | x1 ⇒ pair … false xC | x2 ⇒ pair … false xD | x3 ⇒ pair … false xE
+ | x4 ⇒ pair … false xF | x5 ⇒ pair … true x0 | x6 ⇒ pair … true x1 | x7 ⇒ pair … true x2
+ | x8 ⇒ pair … true x3 | x9 ⇒ pair … true x4 | xA ⇒ pair … true x5 | xB ⇒ pair … true x6
+ | xC ⇒ pair … true x7 | xD ⇒ pair … true x8 | xE ⇒ pair … true x9 | xF ⇒ pair … true xA ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ pair … false xC | x1 ⇒ pair … false xD | x2 ⇒ pair … false xE | x3 ⇒ pair … false xF
+ | x4 ⇒ pair … true x0 | x5 ⇒ pair … true x1 | x6 ⇒ pair … true x2 | x7 ⇒ pair … true x3
+ | x8 ⇒ pair … true x4 | x9 ⇒ pair … true x5 | xA ⇒ pair … true x6 | xB ⇒ pair … true x7
+ | xC ⇒ pair … true x8 | xD ⇒ pair … true x9 | xE ⇒ pair … true xA | xF ⇒ pair … true xB ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ pair … false xD | x1 ⇒ pair … false xE | x2 ⇒ pair … false xF | x3 ⇒ pair … true x0
+ | x4 ⇒ pair … true x1 | x5 ⇒ pair … true x2 | x6 ⇒ pair … true x3 | x7 ⇒ pair … true x4
+ | x8 ⇒ pair … true x5 | x9 ⇒ pair … true x6 | xA ⇒ pair … true x7 | xB ⇒ pair … true x8
+ | xC ⇒ pair … true x9 | xD ⇒ pair … true xA | xE ⇒ pair … true xB | xF ⇒ pair … true xC ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ pair … false xE | x1 ⇒ pair … false xF | x2 ⇒ pair … true x0 | x3 ⇒ pair … true x1
+ | x4 ⇒ pair … true x2 | x5 ⇒ pair … true x3 | x6 ⇒ pair … true x4 | x7 ⇒ pair … true x5
+ | x8 ⇒ pair … true x6 | x9 ⇒ pair … true x7 | xA ⇒ pair … true x8 | xB ⇒ pair … true x9
+ | xC ⇒ pair … true xA | xD ⇒ pair … true xB | xE ⇒ pair … true xC | xF ⇒ pair … true xD ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ pair … false xF | x1 ⇒ pair … true x0 | x2 ⇒ pair … true x1 | x3 ⇒ pair … true x2
+ | x4 ⇒ pair … true x3 | x5 ⇒ pair … true x4 | x6 ⇒ pair … true x5 | x7 ⇒ pair … true x6
+ | x8 ⇒ pair … true x7 | x9 ⇒ pair … true x8 | xA ⇒ pair … true x9 | xB ⇒ pair … true xA
+ | xC ⇒ pair … true xB | xD ⇒ pair … true xC | xE ⇒ pair … true xD | xF ⇒ pair … true xE ]
+ ]].
+
+(* operatore somma con data → data+carry *)
+ndefinition plus_ex_d_dc ≝
+λe1,e2:exadecim.
+ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ pair … false x0 | x1 ⇒ pair … false x1 | x2 ⇒ pair … false x2 | x3 ⇒ pair … false x3
+ | x4 ⇒ pair … false x4 | x5 ⇒ pair … false x5 | x6 ⇒ pair … false x6 | x7 ⇒ pair … false x7
+ | x8 ⇒ pair … false x8 | x9 ⇒ pair … false x9 | xA ⇒ pair … false xA | xB ⇒ pair … false xB
+ | xC ⇒ pair … false xC | xD ⇒ pair … false xD | xE ⇒ pair … false xE | xF ⇒ pair … false xF ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ pair … false x1 | x1 ⇒ pair … false x2 | x2 ⇒ pair … false x3 | x3 ⇒ pair … false x4
+ | x4 ⇒ pair … false x5 | x5 ⇒ pair … false x6 | x6 ⇒ pair … false x7 | x7 ⇒ pair … false x8
+ | x8 ⇒ pair … false x9 | x9 ⇒ pair … false xA | xA ⇒ pair … false xB | xB ⇒ pair … false xC
+ | xC ⇒ pair … false xD | xD ⇒ pair … false xE | xE ⇒ pair … false xF | xF ⇒ pair … true x0 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ pair … false x2 | x1 ⇒ pair … false x3 | x2 ⇒ pair … false x4 | x3 ⇒ pair … false x5
+ | x4 ⇒ pair … false x6 | x5 ⇒ pair … false x7 | x6 ⇒ pair … false x8 | x7 ⇒ pair … false x9
+ | x8 ⇒ pair … false xA | x9 ⇒ pair … false xB | xA ⇒ pair … false xC | xB ⇒ pair … false xD
+ | xC ⇒ pair … false xE | xD ⇒ pair … false xF | xE ⇒ pair … true x0 | xF ⇒ pair … true x1 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ pair … false x3 | x1 ⇒ pair … false x4 | x2 ⇒ pair … false x5 | x3 ⇒ pair … false x6
+ | x4 ⇒ pair … false x7 | x5 ⇒ pair … false x8 | x6 ⇒ pair … false x9 | x7 ⇒ pair … false xA
+ | x8 ⇒ pair … false xB | x9 ⇒ pair … false xC | xA ⇒ pair … false xD | xB ⇒ pair … false xE
+ | xC ⇒ pair … false xF | xD ⇒ pair … true x0 | xE ⇒ pair … true x1 | xF ⇒ pair … true x2 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ pair … false x4 | x1 ⇒ pair … false x5 | x2 ⇒ pair … false x6 | x3 ⇒ pair … false x7
+ | x4 ⇒ pair … false x8 | x5 ⇒ pair … false x9 | x6 ⇒ pair … false xA | x7 ⇒ pair … false xB
+ | x8 ⇒ pair … false xC | x9 ⇒ pair … false xD | xA ⇒ pair … false xE | xB ⇒ pair … false xF
+ | xC ⇒ pair … true x0 | xD ⇒ pair … true x1 | xE ⇒ pair … true x2 | xF ⇒ pair … true x3 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ pair … false x5 | x1 ⇒ pair … false x6 | x2 ⇒ pair … false x7 | x3 ⇒ pair … false x8
+ | x4 ⇒ pair … false x9 | x5 ⇒ pair … false xA | x6 ⇒ pair … false xB | x7 ⇒ pair … false xC
+ | x8 ⇒ pair … false xD | x9 ⇒ pair … false xE | xA ⇒ pair … false xF | xB ⇒ pair … true x0
+ | xC ⇒ pair … true x1 | xD ⇒ pair … true x2 | xE ⇒ pair … true x3 | xF ⇒ pair … true x4 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ pair … false x6 | x1 ⇒ pair … false x7 | x2 ⇒ pair … false x8 | x3 ⇒ pair … false x9
+ | x4 ⇒ pair … false xA | x5 ⇒ pair … false xB | x6 ⇒ pair … false xC | x7 ⇒ pair … false xD
+ | x8 ⇒ pair … false xE | x9 ⇒ pair … false xF | xA ⇒ pair … true x0 | xB ⇒ pair … true x1
+ | xC ⇒ pair … true x2 | xD ⇒ pair … true x3 | xE ⇒ pair … true x4 | xF ⇒ pair … true x5 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ pair … false x7 | x1 ⇒ pair … false x8 | x2 ⇒ pair … false x9 | x3 ⇒ pair … false xA
+ | x4 ⇒ pair … false xB | x5 ⇒ pair … false xC | x6 ⇒ pair … false xD | x7 ⇒ pair … false xE
+ | x8 ⇒ pair … false xF | x9 ⇒ pair … true x0 | xA ⇒ pair … true x1 | xB ⇒ pair … true x2
+ | xC ⇒ pair … true x3 | xD ⇒ pair … true x4 | xE ⇒ pair … true x5 | xF ⇒ pair … true x6 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ pair … false x8 | x1 ⇒ pair … false x9 | x2 ⇒ pair … false xA | x3 ⇒ pair … false xB
+ | x4 ⇒ pair … false xC | x5 ⇒ pair … false xD | x6 ⇒ pair … false xE | x7 ⇒ pair … false xF
+ | x8 ⇒ pair … true x0 | x9 ⇒ pair … true x1 | xA ⇒ pair … true x2 | xB ⇒ pair … true x3
+ | xC ⇒ pair … true x4 | xD ⇒ pair … true x5 | xE ⇒ pair … true x6 | xF ⇒ pair … true x7 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ pair … false x9 | x1 ⇒ pair … false xA | x2 ⇒ pair … false xB | x3 ⇒ pair … false xC
+ | x4 ⇒ pair … false xD | x5 ⇒ pair … false xE | x6 ⇒ pair … false xF | x7 ⇒ pair … true x0
+ | x8 ⇒ pair … true x1 | x9 ⇒ pair … true x2 | xA ⇒ pair … true x3 | xB ⇒ pair … true x4
+ | xC ⇒ pair … true x5 | xD ⇒ pair … true x6 | xE ⇒ pair … true x7 | xF ⇒ pair … true x8 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ pair … false xA | x1 ⇒ pair … false xB | x2 ⇒ pair … false xC | x3 ⇒ pair … false xD
+ | x4 ⇒ pair … false xE | x5 ⇒ pair … false xF | x6 ⇒ pair … true x0 | x7 ⇒ pair … true x1
+ | x8 ⇒ pair … true x2 | x9 ⇒ pair … true x3 | xA ⇒ pair … true x4 | xB ⇒ pair … true x5
+ | xC ⇒ pair … true x6 | xD ⇒ pair … true x7 | xE ⇒ pair … true x8 | xF ⇒ pair … true x9 ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ pair … false xB | x1 ⇒ pair … false xC | x2 ⇒ pair … false xD | x3 ⇒ pair … false xE
+ | x4 ⇒ pair … false xF | x5 ⇒ pair … true x0 | x6 ⇒ pair … true x1 | x7 ⇒ pair … true x2
+ | x8 ⇒ pair … true x3 | x9 ⇒ pair … true x4 | xA ⇒ pair … true x5 | xB ⇒ pair … true x6
+ | xC ⇒ pair … true x7 | xD ⇒ pair … true x8 | xE ⇒ pair … true x9 | xF ⇒ pair … true xA ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ pair … false xC | x1 ⇒ pair … false xD | x2 ⇒ pair … false xE | x3 ⇒ pair … false xF
+ | x4 ⇒ pair … true x0 | x5 ⇒ pair … true x1 | x6 ⇒ pair … true x2 | x7 ⇒ pair … true x3
+ | x8 ⇒ pair … true x4 | x9 ⇒ pair … true x5 | xA ⇒ pair … true x6 | xB ⇒ pair … true x7
+ | xC ⇒ pair … true x8 | xD ⇒ pair … true x9 | xE ⇒ pair … true xA | xF ⇒ pair … true xB ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ pair … false xD | x1 ⇒ pair … false xE | x2 ⇒ pair … false xF | x3 ⇒ pair … true x0
+ | x4 ⇒ pair … true x1 | x5 ⇒ pair … true x2 | x6 ⇒ pair … true x3 | x7 ⇒ pair … true x4
+ | x8 ⇒ pair … true x5 | x9 ⇒ pair … true x6 | xA ⇒ pair … true x7 | xB ⇒ pair … true x8
+ | xC ⇒ pair … true x9 | xD ⇒ pair … true xA | xE ⇒ pair … true xB | xF ⇒ pair … true xC ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ pair … false xE | x1 ⇒ pair … false xF | x2 ⇒ pair … true x0 | x3 ⇒ pair … true x1
+ | x4 ⇒ pair … true x2 | x5 ⇒ pair … true x3 | x6 ⇒ pair … true x4 | x7 ⇒ pair … true x5
+ | x8 ⇒ pair … true x6 | x9 ⇒ pair … true x7 | xA ⇒ pair … true x8 | xB ⇒ pair … true x9
+ | xC ⇒ pair … true xA | xD ⇒ pair … true xB | xE ⇒ pair … true xC | xF ⇒ pair … true xD ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ pair … false xF | x1 ⇒ pair … true x0 | x2 ⇒ pair … true x1 | x3 ⇒ pair … true x2
+ | x4 ⇒ pair … true x3 | x5 ⇒ pair … true x4 | x6 ⇒ pair … true x5 | x7 ⇒ pair … true x6
+ | x8 ⇒ pair … true x7 | x9 ⇒ pair … true x8 | xA ⇒ pair … true x9 | xB ⇒ pair … true xA
+ | xC ⇒ pair … true xB | xD ⇒ pair … true xC | xE ⇒ pair … true xD | xF ⇒ pair … true xE ]
+ ].
+
+(* operatore somma con data+carry → data *)
+ndefinition plus_ex_dc_d ≝
+λc:bool.λe1,e2:exadecim.
+ match c with
+ [ true ⇒ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ x1 | x1 ⇒ x2 | x2 ⇒ x3 | x3 ⇒ x4 | x4 ⇒ x5 | x5 ⇒ x6 | x6 ⇒ x7 | x7 ⇒ x8
+ | x8 ⇒ x9 | x9 ⇒ xA | xA ⇒ xB | xB ⇒ xC | xC ⇒ xD | xD ⇒ xE | xE ⇒ xF | xF ⇒ x0 ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ x2 | x1 ⇒ x3 | x2 ⇒ x4 | x3 ⇒ x5 | x4 ⇒ x6 | x5 ⇒ x7 | x6 ⇒ x8 | x7 ⇒ x9
+ | x8 ⇒ xA | x9 ⇒ xB | xA ⇒ xC | xB ⇒ xD | xC ⇒ xE | xD ⇒ xF | xE ⇒ x0 | xF ⇒ x1 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ x3 | x1 ⇒ x4 | x2 ⇒ x5 | x3 ⇒ x6 | x4 ⇒ x7 | x5 ⇒ x8 | x6 ⇒ x9 | x7 ⇒ xA
+ | x8 ⇒ xB | x9 ⇒ xC | xA ⇒ xD | xB ⇒ xE | xC ⇒ xF | xD ⇒ x0 | xE ⇒ x1 | xF ⇒ x2 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ x4 | x1 ⇒ x5 | x2 ⇒ x6 | x3 ⇒ x7 | x4 ⇒ x8 | x5 ⇒ x9 | x6 ⇒ xA | x7 ⇒ xB
+ | x8 ⇒ xC | x9 ⇒ xD | xA ⇒ xE | xB ⇒ xF | xC ⇒ x0 | xD ⇒ x1 | xE ⇒ x2 | xF ⇒ x3 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ x5 | x1 ⇒ x6 | x2 ⇒ x7 | x3 ⇒ x8 | x4 ⇒ x9 | x5 ⇒ xA | x6 ⇒ xB | x7 ⇒ xC
+ | x8 ⇒ xD | x9 ⇒ xE | xA ⇒ xF | xB ⇒ x0 | xC ⇒ x1 | xD ⇒ x2 | xE ⇒ x3 | xF ⇒ x4 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ x6 | x1 ⇒ x7 | x2 ⇒ x8 | x3 ⇒ x9 | x4 ⇒ xA | x5 ⇒ xB | x6 ⇒ xC | x7 ⇒ xD
+ | x8 ⇒ xE | x9 ⇒ xF | xA ⇒ x0 | xB ⇒ x1 | xC ⇒ x2 | xD ⇒ x3 | xE ⇒ x4 | xF ⇒ x5 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ x7 | x1 ⇒ x8 | x2 ⇒ x9 | x3 ⇒ xA | x4 ⇒ xB | x5 ⇒ xC | x6 ⇒ xD | x7 ⇒ xE
+ | x8 ⇒ xF | x9 ⇒ x0 | xA ⇒ x1 | xB ⇒ x2 | xC ⇒ x3 | xD ⇒ x4 | xE ⇒ x5 | xF ⇒ x6 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ x8 | x1 ⇒ x9 | x2 ⇒ xA | x3 ⇒ xB | x4 ⇒ xC | x5 ⇒ xD | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x2 | xB ⇒ x3 | xC ⇒ x4 | xD ⇒ x5 | xE ⇒ x6 | xF ⇒ x7 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ x9 | x1 ⇒ xA | x2 ⇒ xB | x3 ⇒ xC | x4 ⇒ xD | x5 ⇒ xE | x6 ⇒ xF | x7 ⇒ x0
+ | x8 ⇒ x1 | x9 ⇒ x2 | xA ⇒ x3 | xB ⇒ x4 | xC ⇒ x5 | xD ⇒ x6 | xE ⇒ x7 | xF ⇒ x8 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ xA | x1 ⇒ xB | x2 ⇒ xC | x3 ⇒ xD | x4 ⇒ xE | x5 ⇒ xF | x6 ⇒ x0 | x7 ⇒ x1
+ | x8 ⇒ x2 | x9 ⇒ x3 | xA ⇒ x4 | xB ⇒ x5 | xC ⇒ x6 | xD ⇒ x7 | xE ⇒ x8 | xF ⇒ x9 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ xB | x1 ⇒ xC | x2 ⇒ xD | x3 ⇒ xE | x4 ⇒ xF | x5 ⇒ x0 | x6 ⇒ x1 | x7 ⇒ x2
+ | x8 ⇒ x3 | x9 ⇒ x4 | xA ⇒ x5 | xB ⇒ x6 | xC ⇒ x7 | xD ⇒ x8 | xE ⇒ x9 | xF ⇒ xA ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ xC | x1 ⇒ xD | x2 ⇒ xE | x3 ⇒ xF | x4 ⇒ x0 | x5 ⇒ x1 | x6 ⇒ x2 | x7 ⇒ x3
+ | x8 ⇒ x4 | x9 ⇒ x5 | xA ⇒ x6 | xB ⇒ x7 | xC ⇒ x8 | xD ⇒ x9 | xE ⇒ xA | xF ⇒ xB ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ xD | x1 ⇒ xE | x2 ⇒ xF | x3 ⇒ x0 | x4 ⇒ x1 | x5 ⇒ x2 | x6 ⇒ x3 | x7 ⇒ x4
+ | x8 ⇒ x5 | x9 ⇒ x6 | xA ⇒ x7 | xB ⇒ x8 | xC ⇒ x9 | xD ⇒ xA | xE ⇒ xB | xF ⇒ xC ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ xE | x1 ⇒ xF | x2 ⇒ x0 | x3 ⇒ x1 | x4 ⇒ x2 | x5 ⇒ x3 | x6 ⇒ x4 | x7 ⇒ x5
+ | x8 ⇒ x6 | x9 ⇒ x7 | xA ⇒ x8 | xB ⇒ x9 | xC ⇒ xA | xD ⇒ xB | xE ⇒ xC | xF ⇒ xD ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ xF | x1 ⇒ x0 | x2 ⇒ x1 | x3 ⇒ x2 | x4 ⇒ x3 | x5 ⇒ x4 | x6 ⇒ x5 | x7 ⇒ x6
+ | x8 ⇒ x7 | x9 ⇒ x8 | xA ⇒ x9 | xB ⇒ xA | xC ⇒ xB | xD ⇒ xC | xE ⇒ xD | xF ⇒ xE ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3 | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ ]
+ | false ⇒ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3 | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ x1 | x1 ⇒ x2 | x2 ⇒ x3 | x3 ⇒ x4 | x4 ⇒ x5 | x5 ⇒ x6 | x6 ⇒ x7 | x7 ⇒ x8
+ | x8 ⇒ x9 | x9 ⇒ xA | xA ⇒ xB | xB ⇒ xC | xC ⇒ xD | xD ⇒ xE | xE ⇒ xF | xF ⇒ x0 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ x2 | x1 ⇒ x3 | x2 ⇒ x4 | x3 ⇒ x5 | x4 ⇒ x6 | x5 ⇒ x7 | x6 ⇒ x8 | x7 ⇒ x9
+ | x8 ⇒ xA | x9 ⇒ xB | xA ⇒ xC | xB ⇒ xD | xC ⇒ xE | xD ⇒ xF | xE ⇒ x0 | xF ⇒ x1 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ x3 | x1 ⇒ x4 | x2 ⇒ x5 | x3 ⇒ x6 | x4 ⇒ x7 | x5 ⇒ x8 | x6 ⇒ x9 | x7 ⇒ xA
+ | x8 ⇒ xB | x9 ⇒ xC | xA ⇒ xD | xB ⇒ xE | xC ⇒ xF | xD ⇒ x0 | xE ⇒ x1 | xF ⇒ x2 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ x4 | x1 ⇒ x5 | x2 ⇒ x6 | x3 ⇒ x7 | x4 ⇒ x8 | x5 ⇒ x9 | x6 ⇒ xA | x7 ⇒ xB
+ | x8 ⇒ xC | x9 ⇒ xD | xA ⇒ xE | xB ⇒ xF | xC ⇒ x0 | xD ⇒ x1 | xE ⇒ x2 | xF ⇒ x3 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ x5 | x1 ⇒ x6 | x2 ⇒ x7 | x3 ⇒ x8 | x4 ⇒ x9 | x5 ⇒ xA | x6 ⇒ xB | x7 ⇒ xC
+ | x8 ⇒ xD | x9 ⇒ xE | xA ⇒ xF | xB ⇒ x0 | xC ⇒ x1 | xD ⇒ x2 | xE ⇒ x3 | xF ⇒ x4 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ x6 | x1 ⇒ x7 | x2 ⇒ x8 | x3 ⇒ x9 | x4 ⇒ xA | x5 ⇒ xB | x6 ⇒ xC | x7 ⇒ xD
+ | x8 ⇒ xE | x9 ⇒ xF | xA ⇒ x0 | xB ⇒ x1 | xC ⇒ x2 | xD ⇒ x3 | xE ⇒ x4 | xF ⇒ x5 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ x7 | x1 ⇒ x8 | x2 ⇒ x9 | x3 ⇒ xA | x4 ⇒ xB | x5 ⇒ xC | x6 ⇒ xD | x7 ⇒ xE
+ | x8 ⇒ xF | x9 ⇒ x0 | xA ⇒ x1 | xB ⇒ x2 | xC ⇒ x3 | xD ⇒ x4 | xE ⇒ x5 | xF ⇒ x6 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ x8 | x1 ⇒ x9 | x2 ⇒ xA | x3 ⇒ xB | x4 ⇒ xC | x5 ⇒ xD | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x2 | xB ⇒ x3 | xC ⇒ x4 | xD ⇒ x5 | xE ⇒ x6 | xF ⇒ x7 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ x9 | x1 ⇒ xA | x2 ⇒ xB | x3 ⇒ xC | x4 ⇒ xD | x5 ⇒ xE | x6 ⇒ xF | x7 ⇒ x0
+ | x8 ⇒ x1 | x9 ⇒ x2 | xA ⇒ x3 | xB ⇒ x4 | xC ⇒ x5 | xD ⇒ x6 | xE ⇒ x7 | xF ⇒ x8 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ xA | x1 ⇒ xB | x2 ⇒ xC | x3 ⇒ xD | x4 ⇒ xE | x5 ⇒ xF | x6 ⇒ x0 | x7 ⇒ x1
+ | x8 ⇒ x2 | x9 ⇒ x3 | xA ⇒ x4 | xB ⇒ x5 | xC ⇒ x6 | xD ⇒ x7 | xE ⇒ x8 | xF ⇒ x9 ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ xB | x1 ⇒ xC | x2 ⇒ xD | x3 ⇒ xE | x4 ⇒ xF | x5 ⇒ x0 | x6 ⇒ x1 | x7 ⇒ x2
+ | x8 ⇒ x3 | x9 ⇒ x4 | xA ⇒ x5 | xB ⇒ x6 | xC ⇒ x7 | xD ⇒ x8 | xE ⇒ x9 | xF ⇒ xA ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ xC | x1 ⇒ xD | x2 ⇒ xE | x3 ⇒ xF | x4 ⇒ x0 | x5 ⇒ x1 | x6 ⇒ x2 | x7 ⇒ x3
+ | x8 ⇒ x4 | x9 ⇒ x5 | xA ⇒ x6 | xB ⇒ x7 | xC ⇒ x8 | xD ⇒ x9 | xE ⇒ xA | xF ⇒ xB ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ xD | x1 ⇒ xE | x2 ⇒ xF | x3 ⇒ x0 | x4 ⇒ x1 | x5 ⇒ x2 | x6 ⇒ x3 | x7 ⇒ x4
+ | x8 ⇒ x5 | x9 ⇒ x6 | xA ⇒ x7 | xB ⇒ x8 | xC ⇒ x9 | xD ⇒ xA | xE ⇒ xB | xF ⇒ xC ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ xE | x1 ⇒ xF | x2 ⇒ x0 | x3 ⇒ x1 | x4 ⇒ x2 | x5 ⇒ x3 | x6 ⇒ x4 | x7 ⇒ x5
+ | x8 ⇒ x6 | x9 ⇒ x7 | xA ⇒ x8 | xB ⇒ x9 | xC ⇒ xA | xD ⇒ xB | xE ⇒ xC | xF ⇒ xD ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ xF | x1 ⇒ x0 | x2 ⇒ x1 | x3 ⇒ x2 | x4 ⇒ x3 | x5 ⇒ x4 | x6 ⇒ x5 | x7 ⇒ x6
+ | x8 ⇒ x7 | x9 ⇒ x8 | xA ⇒ x9 | xB ⇒ xA | xC ⇒ xB | xD ⇒ xC | xE ⇒ xD | xF ⇒ xE ]
+ ]].
+
+(* operatore somma con data → data *)
+ndefinition plus_ex_d_d ≝
+λe1,e2:exadecim.
+ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ x0 | x1 ⇒ x1 | x2 ⇒ x2 | x3 ⇒ x3 | x4 ⇒ x4 | x5 ⇒ x5 | x6 ⇒ x6 | x7 ⇒ x7
+ | x8 ⇒ x8 | x9 ⇒ x9 | xA ⇒ xA | xB ⇒ xB | xC ⇒ xC | xD ⇒ xD | xE ⇒ xE | xF ⇒ xF ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ x1 | x1 ⇒ x2 | x2 ⇒ x3 | x3 ⇒ x4 | x4 ⇒ x5 | x5 ⇒ x6 | x6 ⇒ x7 | x7 ⇒ x8
+ | x8 ⇒ x9 | x9 ⇒ xA | xA ⇒ xB | xB ⇒ xC | xC ⇒ xD | xD ⇒ xE | xE ⇒ xF | xF ⇒ x0 ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ x2 | x1 ⇒ x3 | x2 ⇒ x4 | x3 ⇒ x5 | x4 ⇒ x6 | x5 ⇒ x7 | x6 ⇒ x8 | x7 ⇒ x9
+ | x8 ⇒ xA | x9 ⇒ xB | xA ⇒ xC | xB ⇒ xD | xC ⇒ xE | xD ⇒ xF | xE ⇒ x0 | xF ⇒ x1 ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ x3 | x1 ⇒ x4 | x2 ⇒ x5 | x3 ⇒ x6 | x4 ⇒ x7 | x5 ⇒ x8 | x6 ⇒ x9 | x7 ⇒ xA
+ | x8 ⇒ xB | x9 ⇒ xC | xA ⇒ xD | xB ⇒ xE | xC ⇒ xF | xD ⇒ x0 | xE ⇒ x1 | xF ⇒ x2 ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ x4 | x1 ⇒ x5 | x2 ⇒ x6 | x3 ⇒ x7 | x4 ⇒ x8 | x5 ⇒ x9 | x6 ⇒ xA | x7 ⇒ xB
+ | x8 ⇒ xC | x9 ⇒ xD | xA ⇒ xE | xB ⇒ xF | xC ⇒ x0 | xD ⇒ x1 | xE ⇒ x2 | xF ⇒ x3 ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ x5 | x1 ⇒ x6 | x2 ⇒ x7 | x3 ⇒ x8 | x4 ⇒ x9 | x5 ⇒ xA | x6 ⇒ xB | x7 ⇒ xC
+ | x8 ⇒ xD | x9 ⇒ xE | xA ⇒ xF | xB ⇒ x0 | xC ⇒ x1 | xD ⇒ x2 | xE ⇒ x3 | xF ⇒ x4 ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ x6 | x1 ⇒ x7 | x2 ⇒ x8 | x3 ⇒ x9 | x4 ⇒ xA | x5 ⇒ xB | x6 ⇒ xC | x7 ⇒ xD
+ | x8 ⇒ xE | x9 ⇒ xF | xA ⇒ x0 | xB ⇒ x1 | xC ⇒ x2 | xD ⇒ x3 | xE ⇒ x4 | xF ⇒ x5 ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ x7 | x1 ⇒ x8 | x2 ⇒ x9 | x3 ⇒ xA | x4 ⇒ xB | x5 ⇒ xC | x6 ⇒ xD | x7 ⇒ xE
+ | x8 ⇒ xF | x9 ⇒ x0 | xA ⇒ x1 | xB ⇒ x2 | xC ⇒ x3 | xD ⇒ x4 | xE ⇒ x5 | xF ⇒ x6 ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ x8 | x1 ⇒ x9 | x2 ⇒ xA | x3 ⇒ xB | x4 ⇒ xC | x5 ⇒ xD | x6 ⇒ xE | x7 ⇒ xF
+ | x8 ⇒ x0 | x9 ⇒ x1 | xA ⇒ x2 | xB ⇒ x3 | xC ⇒ x4 | xD ⇒ x5 | xE ⇒ x6 | xF ⇒ x7 ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ x9 | x1 ⇒ xA | x2 ⇒ xB | x3 ⇒ xC | x4 ⇒ xD | x5 ⇒ xE | x6 ⇒ xF | x7 ⇒ x0
+ | x8 ⇒ x1 | x9 ⇒ x2 | xA ⇒ x3 | xB ⇒ x4 | xC ⇒ x5 | xD ⇒ x6 | xE ⇒ x7 | xF ⇒ x8 ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ xA | x1 ⇒ xB | x2 ⇒ xC | x3 ⇒ xD | x4 ⇒ xE | x5 ⇒ xF | x6 ⇒ x0 | x7 ⇒ x1
+ | x8 ⇒ x2 | x9 ⇒ x3 | xA ⇒ x4 | xB ⇒ x5 | xC ⇒ x6 | xD ⇒ x7 | xE ⇒ x8 | xF ⇒ x9 ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ xB | x1 ⇒ xC | x2 ⇒ xD | x3 ⇒ xE | x4 ⇒ xF | x5 ⇒ x0 | x6 ⇒ x1 | x7 ⇒ x2
+ | x8 ⇒ x3 | x9 ⇒ x4 | xA ⇒ x5 | xB ⇒ x6 | xC ⇒ x7 | xD ⇒ x8 | xE ⇒ x9 | xF ⇒ xA ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ xC | x1 ⇒ xD | x2 ⇒ xE | x3 ⇒ xF | x4 ⇒ x0 | x5 ⇒ x1 | x6 ⇒ x2 | x7 ⇒ x3
+ | x8 ⇒ x4 | x9 ⇒ x5 | xA ⇒ x6 | xB ⇒ x7 | xC ⇒ x8 | xD ⇒ x9 | xE ⇒ xA | xF ⇒ xB ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ xD | x1 ⇒ xE | x2 ⇒ xF | x3 ⇒ x0 | x4 ⇒ x1 | x5 ⇒ x2 | x6 ⇒ x3 | x7 ⇒ x4
+ | x8 ⇒ x5 | x9 ⇒ x6 | xA ⇒ x7 | xB ⇒ x8 | xC ⇒ x9 | xD ⇒ xA | xE ⇒ xB | xF ⇒ xC ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ xE | x1 ⇒ xF | x2 ⇒ x0 | x3 ⇒ x1 | x4 ⇒ x2 | x5 ⇒ x3 | x6 ⇒ x4 | x7 ⇒ x5
+ | x8 ⇒ x6 | x9 ⇒ x7 | xA ⇒ x8 | xB ⇒ x9 | xC ⇒ xA | xD ⇒ xB | xE ⇒ xC | xF ⇒ xD ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ xF | x1 ⇒ x0 | x2 ⇒ x1 | x3 ⇒ x2 | x4 ⇒ x3 | x5 ⇒ x4 | x6 ⇒ x5 | x7 ⇒ x6
+ | x8 ⇒ x7 | x9 ⇒ x8 | xA ⇒ x9 | xB ⇒ xA | xC ⇒ xB | xD ⇒ xC | xE ⇒ xD | xF ⇒ xE ]
+ ].
+
+(* operatore somma con data+carry → carry *)
+ndefinition plus_ex_dc_c ≝
+λc:bool.λe1,e2:exadecim.
+ match c with
+ [ true ⇒ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ true ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ false | xE ⇒ true | xF ⇒ true ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ true | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ true | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ ]
+ | false ⇒ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ true ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ false | xE ⇒ true | xF ⇒ true ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ true | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ ]].
+
+(* operatore somma con data → carry *)
+ndefinition plus_ex_d_c ≝
+λe1,e2:exadecim.
+ match e1 with
+ [ x0 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ false ]
+ | x1 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ false | xE ⇒ false | xF ⇒ true ]
+ | x2 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ false | xE ⇒ true | xF ⇒ true ]
+ | x3 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ false | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x4 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ false | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x5 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ false | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x6 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ false | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x7 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ false | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x8 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ false
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | x9 ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ false | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xA ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ false | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xB ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ false | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xC ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ false | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xD ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ false | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xE ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ false | x2 ⇒ true | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ | xF ⇒ match e2 with
+ [ x0 ⇒ false | x1 ⇒ true | x2 ⇒ true | x3 ⇒ true | x4 ⇒ true | x5 ⇒ true | x6 ⇒ true | x7 ⇒ true
+ | x8 ⇒ true | x9 ⇒ true | xA ⇒ true | xB ⇒ true | xC ⇒ true | xD ⇒ true | xE ⇒ true | xF ⇒ true ]
+ ].
+
+(* operatore predecessore *)
+ndefinition pred_ex ≝
+λe:exadecim.
+ match e with
+ [ x0 ⇒ xF | x1 ⇒ x0 | x2 ⇒ x1 | x3 ⇒ x2
+ | x4 ⇒ x3 | x5 ⇒ x4 | x6 ⇒ x5 | x7 ⇒ x6
+ | x8 ⇒ x7 | x9 ⇒ x8 | xA ⇒ x9 | xB ⇒ xA
+ | xC ⇒ xB | xD ⇒ xC | xE ⇒ xD | xF ⇒ xE ].
+
+(* operatore successore *)
+ndefinition succ_ex ≝
+λe:exadecim.
+ match e with
+ [ x0 ⇒ x1 | x1 ⇒ x2 | x2 ⇒ x3 | x3 ⇒ x4
+ | x4 ⇒ x5 | x5 ⇒ x6 | x6 ⇒ x7 | x7 ⇒ x8
+ | x8 ⇒ x9 | x9 ⇒ xA | xA ⇒ xB | xB ⇒ xC
+ | xC ⇒ xD | xD ⇒ xE | xE ⇒ xF | xF ⇒ x0 ].
+
+(* operatore neg/complemento a 2 *)
+ndefinition compl_ex ≝
+λe:exadecim.match e with
+ [ x0 ⇒ x0 | x1 ⇒ xF | x2 ⇒ xE | x3 ⇒ xD
+ | x4 ⇒ xC | x5 ⇒ xB | x6 ⇒ xA | x7 ⇒ x9
+ | x8 ⇒ x8 | x9 ⇒ x7 | xA ⇒ x6 | xB ⇒ x5
+ | xC ⇒ x4 | xD ⇒ x3 | xE ⇒ x2 | xF ⇒ x1 ].
+
+(* operatore abs *)
+ndefinition abs_ex ≝
+λe:exadecim.match getMSB_ex e with
+ [ true ⇒ compl_ex e | false ⇒ e ].
+
+(* operatore x in [inf,sup] o in sup],[inf *)
+ndefinition inrange_ex ≝
+λx,inf,sup:exadecim.
+ match le_ex inf sup with
+ [ true ⇒ and_bool | false ⇒ or_bool ]
+ (le_ex inf x) (le_ex x sup).
+
+(* esadecimali ricorsivi *)
+ninductive rec_exadecim : exadecim → Type ≝
+ ex_O : rec_exadecim x0
+| ex_S : ∀n.rec_exadecim n → rec_exadecim (succ_ex n).
+
+(* esadecimali → esadecimali ricorsivi *)
+ndefinition ex_to_recex ≝
+λn.match n return λx.rec_exadecim x with
+ [ x0 ⇒ ex_O
+ | x1 ⇒ ex_S ? ex_O
+ | x2 ⇒ ex_S ? (ex_S ? ex_O)
+ | x3 ⇒ ex_S ? (ex_S ? (ex_S ? ex_O))
+ | x4 ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O)))
+ | x5 ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O))))
+ | x6 ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O)))))
+ | x7 ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O))))))
+ | x8 ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O)))))))
+ | x9 ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O))))))))
+ | xA ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O)))))))))
+ | xB ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O))))))))))
+ | xC ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O)))))))))))
+ | xD ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O))))))))))))
+ | xE ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O)))))))))))))
+ | xF ⇒ ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? (ex_S ? ex_O))))))))))))))
+ ].
+
+(* ottali → esadecimali *)
+ndefinition ex_of_oct ≝
+λn.match n with
+ [ o0 ⇒ x0 | o1 ⇒ x1 | o2 ⇒ x2 | o3 ⇒ x3 | o4 ⇒ x4 | o5 ⇒ x5 | o6 ⇒ x6 | o7 ⇒ x7 ].
+
+(* esadecimali xNNNN → ottali *)
+ndefinition oct_of_exL ≝
+λn.match n with
+ [ x0 ⇒ o0 | x1 ⇒ o1 | x2 ⇒ o2 | x3 ⇒ o3 | x4 ⇒ o4 | x5 ⇒ o5 | x6 ⇒ o6 | x7 ⇒ o7
+ | x8 ⇒ o0 | x9 ⇒ o1 | xA ⇒ o2 | xB ⇒ o3 | xC ⇒ o4 | xD ⇒ o5 | xE ⇒ o6 | xF ⇒ o7 ].
+
+(* esadecimali NNNNx → ottali *)
+ndefinition oct_of_exH ≝
+λn.match n with
+ [ x0 ⇒ o0 | x1 ⇒ o0 | x2 ⇒ o1 | x3 ⇒ o1 | x4 ⇒ o2 | x5 ⇒ o2 | x6 ⇒ o3 | x7 ⇒ o3
+ | x8 ⇒ o4 | x9 ⇒ o4 | xA ⇒ o5 | xB ⇒ o5 | xC ⇒ o6 | xD ⇒ o6 | xE ⇒ o7 | xF ⇒ o7 ].
+
+ndefinition exadecim_destruct_aux ≝
+Πe1,e2.ΠP:Prop.ΠH:e1 = e2.
+ match eq_ex e1 e2 with [ true ⇒ P → P | false ⇒ P ].
+
+ndefinition exadecim_destruct : exadecim_destruct_aux.
+ #e1; #e2; #P; #H;
+ nrewrite < H;
+ nelim e1;
+ nnormalize;
+ napply (λx.x).
+nqed.
+
+nlemma eq_to_eqex : ∀n1,n2.n1 = n2 → eq_ex n1 n2 = true.
+ #n1; #n2; #H;
+ nrewrite > H;
+ nelim n2;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma neqex_to_neq : ∀n1,n2.eq_ex n1 n2 = false → n1 ≠ n2.
+ #n1; #n2; #H;
+ napply (not_to_not (n1 = n2) (eq_ex n1 n2 = true) …);
+ ##[ ##1: napply (eq_to_eqex n1 n2)
+ ##| ##2: napply (eqfalse_to_neqtrue … H)
+ ##]
+nqed.
+
+nlemma eqex_to_eq : ∀n1,n2.eq_ex n1 n2 = true → n1 = n2.
+ #n1; #n2;
+ ncases n1;
+ ncases n2;
+ nnormalize;
+ ##[ ##1,18,35,52,69,86,103,120,137,154,171,188,205,222,239,256: #H; napply refl_eq
+ ##| ##*: #H; (*ndestruct lentissima...*) napply (bool_destruct … H)
+ ##]
+nqed.
+
+nlemma neq_to_neqex : ∀n1,n2.n1 ≠ n2 → eq_ex n1 n2 = false.
+ #n1; #n2; #H;
+ napply (neqtrue_to_eqfalse (eq_ex n1 n2));
+ napply (not_to_not (eq_ex n1 n2 = true) (n1 = n2) ? H);
+ napply (eqex_to_eq n1 n2).
+nqed.
+
+nlemma decidable_ex : ∀x,y:exadecim.decidable (x = y).
+ #x; #y; nnormalize;
+ napply (or2_elim (eq_ex x y = true) (eq_ex x y = false) ? (decidable_bexpr ?));
+ ##[ ##1: #H; napply (or2_intro1 (x = y) (x ≠ y) (eqex_to_eq … H))
+ ##| ##2: #H; napply (or2_intro2 (x = y) (x ≠ y) (neqex_to_neq … H))
+ ##]
+nqed.
+
+nlemma symmetric_eqex : symmetricT exadecim bool eq_ex.
+ #n1; #n2;
+ napply (or2_elim (n1 = n2) (n1 ≠ n2) ? (decidable_ex n1 n2));
+ ##[ ##1: #H; nrewrite > H; napply refl_eq
+ ##| ##2: #H; nrewrite > (neq_to_neqex n1 n2 H);
+ napply (symmetric_eq ? (eq_ex n2 n1) false);
+ napply (neq_to_neqex n2 n1 (symmetric_neq ? n1 n2 H))
+ ##]
+nqed.
+
+nlemma exadecim_is_comparable : comparable.
+ @ exadecim
+ ##[ napply x0
+ ##| napply forall_ex
+ ##| napply eq_ex
+ ##| napply eqex_to_eq
+ ##| napply eq_to_eqex
+ ##| napply neqex_to_neq
+ ##| napply neq_to_neqex
+ ##| napply decidable_ex
+ ##| napply symmetric_eqex
+ ##]
+nqed.
+
+unification hint 0 ≔ ⊢ carr exadecim_is_comparable ≡ exadecim.
+
+nlemma exadecim_is_comparable_ext : comparable_ext.
+ napply mk_comparable_ext;
+ ##[ napply exadecim_is_comparable
+ ##| napply lt_ex
+ ##| napply le_ex
+ ##| napply gt_ex
+ ##| napply ge_ex
+ ##| napply and_ex
+ ##| napply or_ex
+ ##| napply xor_ex
+ ##| napply getMSB_ex
+ ##| napply setMSB_ex
+ ##| napply clrMSB_ex
+ ##| napply getLSB_ex
+ ##| napply setLSB_ex
+ ##| napply clrLSB_ex
+ ##| napply rcr_ex
+ ##| napply shr_ex
+ ##| napply ror_ex
+ ##| napply rcl_ex
+ ##| napply shl_ex
+ ##| napply rol_ex
+ ##| napply not_ex
+ ##| napply plus_ex_dc_dc
+ ##| napply plus_ex_d_dc
+ ##| napply plus_ex_dc_d
+ ##| napply plus_ex_d_d
+ ##| napply plus_ex_dc_c
+ ##| napply plus_ex_d_c
+ ##| napply pred_ex
+ ##| napply succ_ex
+ ##| napply compl_ex
+ ##| napply abs_ex
+ ##| napply inrange_ex
+ ##]
+nqed.
+
+unification hint 0 ≔ ⊢ carr (comp_base exadecim_is_comparable_ext) ≡ exadecim.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/comp.ma".
+include "num/bool_lemmas.ma".
+
+(* ****** *)
+(* OTTALI *)
+(* ****** *)
+
+ninductive oct : Type ≝
+ o0: oct
+| o1: oct
+| o2: oct
+| o3: oct
+| o4: oct
+| o5: oct
+| o6: oct
+| o7: oct.
+
+(* iteratore sugli ottali *)
+ndefinition forall_oct ≝ λP.
+ P o0 ⊗ P o1 ⊗ P o2 ⊗ P o3 ⊗ P o4 ⊗ P o5 ⊗ P o6 ⊗ P o7.
+
+(* operatore = *)
+ndefinition eq_oct ≝
+λn1,n2:oct.
+ match n1 with
+ [ o0 ⇒ match n2 with [ o0 ⇒ true | _ ⇒ false ]
+ | o1 ⇒ match n2 with [ o1 ⇒ true | _ ⇒ false ]
+ | o2 ⇒ match n2 with [ o2 ⇒ true | _ ⇒ false ]
+ | o3 ⇒ match n2 with [ o3 ⇒ true | _ ⇒ false ]
+ | o4 ⇒ match n2 with [ o4 ⇒ true | _ ⇒ false ]
+ | o5 ⇒ match n2 with [ o5 ⇒ true | _ ⇒ false ]
+ | o6 ⇒ match n2 with [ o6 ⇒ true | _ ⇒ false ]
+ | o7 ⇒ match n2 with [ o7 ⇒ true | _ ⇒ false ]
+ ].
+
+(* operatore and *)
+ndefinition and_oct ≝
+λe1,e2:oct.match e1 with
+ [ o0 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o0 | o2 ⇒ o0 | o3 ⇒ o0
+ | o4 ⇒ o0 | o5 ⇒ o0 | o6 ⇒ o0 | o7 ⇒ o0 ]
+ | o1 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o1 | o2 ⇒ o0 | o3 ⇒ o1
+ | o4 ⇒ o0 | o5 ⇒ o1 | o6 ⇒ o0 | o7 ⇒ o1 ]
+ | o2 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o0 | o2 ⇒ o2 | o3 ⇒ o2
+ | o4 ⇒ o0 | o5 ⇒ o0 | o6 ⇒ o2 | o7 ⇒ o2 ]
+ | o3 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o1 | o2 ⇒ o2 | o3 ⇒ o3
+ | o4 ⇒ o0 | o5 ⇒ o1 | o6 ⇒ o2 | o7 ⇒ o3 ]
+ | o4 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o0 | o2 ⇒ o0 | o3 ⇒ o0
+ | o4 ⇒ o4 | o5 ⇒ o4 | o6 ⇒ o4 | o7 ⇒ o4 ]
+ | o5 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o1 | o2 ⇒ o0 | o3 ⇒ o1
+ | o4 ⇒ o4 | o5 ⇒ o5 | o6 ⇒ o4 | o7 ⇒ o5 ]
+ | o6 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o0 | o2 ⇒ o2 | o3 ⇒ o2
+ | o4 ⇒ o4 | o5 ⇒ o4 | o6 ⇒ o6 | o7 ⇒ o6 ]
+ | o7 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o1 | o2 ⇒ o2 | o3 ⇒ o3
+ | o4 ⇒ o4 | o5 ⇒ o5 | o6 ⇒ o6 | o7 ⇒ o7 ]
+ ].
+
+(* operatore or *)
+ndefinition or_oct ≝
+λe1,e2:oct.match e1 with
+ [ o0 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o1 | o2 ⇒ o2 | o3 ⇒ o3
+ | o4 ⇒ o4 | o5 ⇒ o5 | o6 ⇒ o6 | o7 ⇒ o7 ]
+ | o1 ⇒ match e2 with
+ [ o0 ⇒ o1 | o1 ⇒ o1 | o2 ⇒ o3 | o3 ⇒ o3
+ | o4 ⇒ o5 | o5 ⇒ o5 | o6 ⇒ o7 | o7 ⇒ o7 ]
+ | o2 ⇒ match e2 with
+ [ o0 ⇒ o2 | o1 ⇒ o3 | o2 ⇒ o2 | o3 ⇒ o3
+ | o4 ⇒ o6 | o5 ⇒ o7 | o6 ⇒ o6 | o7 ⇒ o7 ]
+ | o3 ⇒ match e2 with
+ [ o0 ⇒ o3 | o1 ⇒ o3 | o2 ⇒ o3 | o3 ⇒ o3
+ | o4 ⇒ o7 | o5 ⇒ o7 | o6 ⇒ o7 | o7 ⇒ o7 ]
+ | o4 ⇒ match e2 with
+ [ o0 ⇒ o4 | o1 ⇒ o5 | o2 ⇒ o6 | o3 ⇒ o7
+ | o4 ⇒ o4 | o5 ⇒ o5 | o6 ⇒ o6 | o7 ⇒ o7 ]
+ | o5 ⇒ match e2 with
+ [ o0 ⇒ o5 | o1 ⇒ o5 | o2 ⇒ o7 | o3 ⇒ o7
+ | o4 ⇒ o5 | o5 ⇒ o5 | o6 ⇒ o7 | o7 ⇒ o7 ]
+ | o6 ⇒ match e2 with
+ [ o0 ⇒ o6 | o1 ⇒ o7 | o2 ⇒ o6 | o3 ⇒ o7
+ | o4 ⇒ o6 | o5 ⇒ o7 | o6 ⇒ o6 | o7 ⇒ o7 ]
+ | o7 ⇒ match e2 with
+ [ o0 ⇒ o7 | o1 ⇒ o7 | o2 ⇒ o7 | o3 ⇒ o7
+ | o4 ⇒ o7 | o5 ⇒ o7 | o6 ⇒ o7 | o7 ⇒ o7 ]
+ ].
+
+(* operatore xor *)
+ndefinition xor_oct ≝
+λe1,e2:oct.match e1 with
+ [ o0 ⇒ match e2 with
+ [ o0 ⇒ o0 | o1 ⇒ o1 | o2 ⇒ o2 | o3 ⇒ o3
+ | o4 ⇒ o4 | o5 ⇒ o5 | o6 ⇒ o6 | o7 ⇒ o7 ]
+ | o1 ⇒ match e2 with
+ [ o0 ⇒ o1 | o1 ⇒ o0 | o2 ⇒ o3 | o3 ⇒ o2
+ | o4 ⇒ o5 | o5 ⇒ o4 | o6 ⇒ o7 | o7 ⇒ o6 ]
+ | o2 ⇒ match e2 with
+ [ o0 ⇒ o2 | o1 ⇒ o3 | o2 ⇒ o0 | o3 ⇒ o1
+ | o4 ⇒ o6 | o5 ⇒ o7 | o6 ⇒ o4 | o7 ⇒ o5 ]
+ | o3 ⇒ match e2 with
+ [ o0 ⇒ o3 | o1 ⇒ o2 | o2 ⇒ o1 | o3 ⇒ o0
+ | o4 ⇒ o7 | o5 ⇒ o6 | o6 ⇒ o5 | o7 ⇒ o4 ]
+ | o4 ⇒ match e2 with
+ [ o0 ⇒ o4 | o1 ⇒ o5 | o2 ⇒ o6 | o3 ⇒ o7
+ | o4 ⇒ o0 | o5 ⇒ o1 | o6 ⇒ o2 | o7 ⇒ o3 ]
+ | o5 ⇒ match e2 with
+ [ o0 ⇒ o5 | o1 ⇒ o4 | o2 ⇒ o7 | o3 ⇒ o6
+ | o4 ⇒ o1 | o5 ⇒ o0 | o6 ⇒ o3 | o7 ⇒ o2 ]
+ | o6 ⇒ match e2 with
+ [ o0 ⇒ o6 | o1 ⇒ o7 | o2 ⇒ o4 | o3 ⇒ o5
+ | o4 ⇒ o2 | o5 ⇒ o3 | o6 ⇒ o0 | o7 ⇒ o1 ]
+ | o7 ⇒ match e2 with
+ [ o0 ⇒ o7 | o1 ⇒ o6 | o2 ⇒ o5 | o3 ⇒ o4
+ | o4 ⇒ o3 | o5 ⇒ o2 | o6 ⇒ o1 | o7 ⇒ o0 ]
+ ].
+
+(* operatore successore *)
+ndefinition succ_oct ≝
+λn.match n with
+ [ o0 ⇒ o1 | o1 ⇒ o2 | o2 ⇒ o3 | o3 ⇒ o4 | o4 ⇒ o5 | o5 ⇒ o6 | o6 ⇒ o7 | o7 ⇒ o0 ].
+
+(* ottali ricorsivi *)
+ninductive rec_oct : oct → Type ≝
+ oc_O : rec_oct o0
+| oc_S : ∀n.rec_oct n → rec_oct (succ_oct n).
+
+(* ottali → ottali ricorsivi *)
+ndefinition oct_to_recoct ≝
+λn.match n return λx.rec_oct x with
+ [ o0 ⇒ oc_O
+ | o1 ⇒ oc_S ? oc_O
+ | o2 ⇒ oc_S ? (oc_S ? oc_O)
+ | o3 ⇒ oc_S ? (oc_S ? (oc_S ? oc_O))
+ | o4 ⇒ oc_S ? (oc_S ? (oc_S ? (oc_S ? oc_O)))
+ | o5 ⇒ oc_S ? (oc_S ? (oc_S ? (oc_S ? (oc_S ? oc_O))))
+ | o6 ⇒ oc_S ? (oc_S ? (oc_S ? (oc_S ? (oc_S ? (oc_S ? oc_O)))))
+ | o7 ⇒ oc_S ? (oc_S ? (oc_S ? (oc_S ? (oc_S ? (oc_S ? (oc_S ? oc_O))))))
+ ].
+
+ndefinition oct_destruct_aux ≝
+Πn1,n2:oct.ΠP:Prop.n1 = n2 →
+ match eq_oct n1 n2 with [ true ⇒ P → P | false ⇒ P ].
+
+ndefinition oct_destruct : oct_destruct_aux.
+ #n1; #n2; #P; #H;
+ nrewrite < H;
+ nelim n1;
+ nnormalize;
+ napply (λx.x).
+nqed.
+
+nlemma eq_to_eqoct : ∀n1,n2.n1 = n2 → eq_oct n1 n2 = true.
+ #n1; #n2; #H;
+ nrewrite > H;
+ nelim n2;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma neqoct_to_neq : ∀n1,n2.eq_oct n1 n2 = false → n1 ≠ n2.
+ #n1; #n2; #H;
+ napply (not_to_not (n1 = n2) (eq_oct n1 n2 = true) …);
+ ##[ ##1: napply (eq_to_eqoct n1 n2)
+ ##| ##2: napply (eqfalse_to_neqtrue … H)
+ ##]
+nqed.
+
+nlemma eqoct_to_eq : ∀n1,n2.eq_oct n1 n2 = true → n1 = n2.
+ #n1; #n2;
+ ncases n1;
+ ncases n2;
+ nnormalize;
+ ##[ ##1,10,19,28,37,46,55,64: #H; napply refl_eq
+ ##| ##*: #H; ndestruct (*napply (bool_destruct … H)*)
+ ##]
+nqed.
+
+nlemma neq_to_neqoct : ∀n1,n2.n1 ≠ n2 → eq_oct n1 n2 = false.
+ #n1; #n2; #H;
+ napply (neqtrue_to_eqfalse (eq_oct n1 n2));
+ napply (not_to_not (eq_oct n1 n2 = true) (n1 = n2) ? H);
+ napply (eqoct_to_eq n1 n2).
+nqed.
+
+nlemma decidable_oct : ∀x,y:oct.decidable (x = y).
+ #x; #y; nnormalize;
+ napply (or2_elim (eq_oct x y = true) (eq_oct x y = false) ? (decidable_bexpr ?));
+ ##[ ##1: #H; napply (or2_intro1 (x = y) (x ≠ y) (eqoct_to_eq … H))
+ ##| ##2: #H; napply (or2_intro2 (x = y) (x ≠ y) (neqoct_to_neq … H))
+ ##]
+nqed.
+
+nlemma symmetric_eqoct : symmetricT oct bool eq_oct.
+ #n1; #n2;
+ napply (or2_elim (n1 = n2) (n1 ≠ n2) ? (decidable_oct n1 n2));
+ ##[ ##1: #H; nrewrite > H; napply refl_eq
+ ##| ##2: #H; nrewrite > (neq_to_neqoct n1 n2 H);
+ napply (symmetric_eq ? (eq_oct n2 n1) false);
+ napply (neq_to_neqoct n2 n1 (symmetric_neq ? n1 n2 H))
+ ##]
+nqed.
+
+nlemma oct_is_comparable : comparable.
+ @ oct
+ ##[ napply o0
+ ##| napply forall_oct
+ ##| napply eq_oct
+ ##| napply eqoct_to_eq
+ ##| napply eq_to_eqoct
+ ##| napply neqoct_to_neq
+ ##| napply neq_to_neqoct
+ ##| napply decidable_oct
+ ##| napply symmetric_eqoct
+ ##]
+nqed.
+
+unification hint 0 ≔ ⊢ carr oct_is_comparable ≡ oct.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/byte8.ma".
+include "common/nat.ma".
+
+(* **** *)
+(* WORD *)
+(* **** *)
+
+ndefinition word16 ≝ comp_num byte8.
+ndefinition mk_word16 ≝ λb1,b2.mk_comp_num byte8 b1 b2.
+
+(* \langle \rangle *)
+notation "〈x:y〉" non associative with precedence 80
+ for @{ mk_comp_num byte8 $x $y }.
+
+ndefinition word16_is_comparable_ext ≝ cn_is_comparable_ext byte8_is_comparable_ext.
+unification hint 0 ≔ ⊢ carr (comp_base word16_is_comparable_ext) ≡ comp_num (comp_num exadecim).
+unification hint 0 ≔ ⊢ carr (comp_base word16_is_comparable_ext) ≡ comp_num byte8.
+unification hint 0 ≔ ⊢ carr (comp_base word16_is_comparable_ext) ≡ word16.
+
+(* operatore estensione unsigned *)
+ndefinition extu_w16 ≝ λb2.〈zeroc ?:b2〉.
+ndefinition extu2_w16 ≝ λe2.〈zeroc ?:〈zeroc ?,e2〉〉.
+
+(* operatore estensione signed *)
+ndefinition exts_w16 ≝
+λb2.〈(match getMSBc ? b2 with
+ [ true ⇒ predc ? (zeroc ?) | false ⇒ zeroc ? ]):b2〉.
+ndefinition exts2_w16 ≝
+λe2.(match getMSBc ? e2 with
+ [ true ⇒ 〈predc ? (zeroc ?):〈predc ? (zeroc ?),e2〉〉
+ | false ⇒ 〈zeroc ?:〈zeroc ?,e2〉〉 ]).
+
+(* operatore moltiplicazione senza segno *)
+(* 〈a1,a2〉 * 〈b1,b2〉 = (a1*b1) x0 x0 + x0 (a1*b2) x0 + x0 (a2*b1) x0 + x0 x0 (a2*b2) *)
+ndefinition mulu_b8_aux ≝
+λw:word16.nat_it ? (rolc ?) w nat4.
+
+ndefinition mulu_b8 ≝
+λb1,b2:byte8.
+ plusc_d_d ? 〈(mulu_ex (cnH ? b1) (cnH ? b2)):zeroc ?〉
+ (plusc_d_d ? (mulu_b8_aux (extu_w16 (mulu_ex (cnH ? b1) (cnL ? b2))))
+ (plusc_d_d ? (mulu_b8_aux (extu_w16 (mulu_ex (cnL ? b1) (cnH ? b2))))
+ (extu_w16 (mulu_ex (cnL ? b1) (cnL ? b2))))).
+
+(* operatore moltiplicazione con segno *)
+(* x * y = sgn(x) * sgn(y) * |x| * |y| *)
+ndefinition muls_b8 ≝
+λb1,b2:byte8.
+(* ++/-- → +, +-/-+ → - *)
+ match (getMSBc ? b1) ⊙ (getMSBc ? b2) with
+ (* +- -+ → - *)
+ [ true ⇒ complc ?
+ (* ++/-- → + *)
+ | false ⇒ λx.x ] (mulu_b8 (absc ? b1) (absc ? b2)).
+
+(* divisione senza segno (secondo la logica delle ALU): (quoziente resto) overflow *)
+nlet rec div_b8_aux (divd:word16) (divs:word16) (molt:byte8) (q:byte8) (n:nat) on n ≝
+ let w' ≝ plusc_d_d ? divd (complc ? divs) in
+ match n with
+ [ O ⇒ match lec ? divs divd with
+ [ true ⇒ triple … (orc ? molt q) (cnL ? w') (⊖ (eqc ? (cnH ? w') (zeroc ?)))
+ | false ⇒ triple … q (cnL ? divd) (⊖ (eqc ? (cnH ? divd) (zeroc ?))) ]
+ | S n' ⇒ match lec ? divs divd with
+ [ true ⇒ div_b8_aux w' (rorc ? divs) (rorc ? molt) (orc ? molt q) n'
+ | false ⇒ div_b8_aux divd (rorc ? divs) (rorc ? molt) q n' ]].
+
+ndefinition div_b8 ≝
+λw:word16.λb:byte8.match eqc ? b (zeroc ?) with
+(* la combinazione n/0 e' illegale, segnala solo overflow senza dare risultato *)
+ [ true ⇒ triple … 〈xF,xF〉 (cnL ? w) true
+ | false ⇒ match eqc ? w (zeroc ?) with
+(* 0 diviso qualsiasi cosa diverso da 0 da' q=0 r=0 o=false *)
+ [ true ⇒ triple … (zeroc ?) (zeroc ?) false
+(* 1) e' una divisione sensata che produrra' overflow/risultato *)
+(* 2) parametri: dividendo, divisore, moltiplicatore, quoziente, contatore *)
+(* 3) ad ogni ciclo il divisore e il moltiplicatore vengono scalati di 1 a dx *)
+(* 4) il moltiplicatore e' la quantita' aggiunta al quoziente se il divisore *)
+(* puo' essere sottratto al dividendo *)
+ | false ⇒ div_b8_aux w (nat_it ? (rolc ?) (extu_w16 b) nat7) 〈x8,x0〉 (zeroc ?) nat7 ]].
+
+(* word16 ricorsive *)
+ninductive rec_word16 : word16 → Type ≝
+ w16_O : rec_word16 (zeroc ?)
+| w16_S : ∀n.rec_word16 n → rec_word16 (succc ? n).
+
+(* word16 → word16 ricorsive *)
+
+(* EX: ancora problema di tempi ???
+ndefinition w16_to_recw16_aux1_1 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x1,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S ? (w16_S ? (w16_S ? (w16_S ? (w16_S ? (w16_S ? (w16_S ? (w16_S ? (
+ w16_S ? (w16_S ? (w16_S ? (w16_S ? (w16_S ? (w16_S ? (w16_S ? (w16_S ? recw
+ ))))))))))))))).
+*)
+
+ndefinition w16_to_recw16_aux1_1 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x1,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x0,xF〉〉 (w16_S 〈n:〈x0,xE〉〉 (w16_S 〈n:〈x0,xD〉〉 (w16_S 〈n:〈x0,xC〉〉 (
+ w16_S 〈n:〈x0,xB〉〉 (w16_S 〈n:〈x0,xA〉〉 (w16_S 〈n:〈x0,x9〉〉 (w16_S 〈n:〈x0,x8〉〉 (
+ w16_S 〈n:〈x0,x7〉〉 (w16_S 〈n:〈x0,x6〉〉 (w16_S 〈n:〈x0,x5〉〉 (w16_S 〈n:〈x0,x4〉〉 (
+ w16_S 〈n:〈x0,x3〉〉 (w16_S 〈n:〈x0,x2〉〉 (w16_S 〈n:〈x0,x1〉〉 (w16_S 〈n:〈x0,x0〉〉 recw
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_2 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x2,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x1,xF〉〉 (w16_S 〈n:〈x1,xE〉〉 (w16_S 〈n:〈x1,xD〉〉 (w16_S 〈n:〈x1,xC〉〉 (
+ w16_S 〈n:〈x1,xB〉〉 (w16_S 〈n:〈x1,xA〉〉 (w16_S 〈n:〈x1,x9〉〉 (w16_S 〈n:〈x1,x8〉〉 (
+ w16_S 〈n:〈x1,x7〉〉 (w16_S 〈n:〈x1,x6〉〉 (w16_S 〈n:〈x1,x5〉〉 (w16_S 〈n:〈x1,x4〉〉 (
+ w16_S 〈n:〈x1,x3〉〉 (w16_S 〈n:〈x1,x2〉〉 (w16_S 〈n:〈x1,x1〉〉 (w16_S 〈n:〈x1,x0〉〉 (w16_to_recw16_aux1_1 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_3 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x3,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x2,xF〉〉 (w16_S 〈n:〈x2,xE〉〉 (w16_S 〈n:〈x2,xD〉〉 (w16_S 〈n:〈x2,xC〉〉 (
+ w16_S 〈n:〈x2,xB〉〉 (w16_S 〈n:〈x2,xA〉〉 (w16_S 〈n:〈x2,x9〉〉 (w16_S 〈n:〈x2,x8〉〉 (
+ w16_S 〈n:〈x2,x7〉〉 (w16_S 〈n:〈x2,x6〉〉 (w16_S 〈n:〈x2,x5〉〉 (w16_S 〈n:〈x2,x4〉〉 (
+ w16_S 〈n:〈x2,x3〉〉 (w16_S 〈n:〈x2,x2〉〉 (w16_S 〈n:〈x2,x1〉〉 (w16_S 〈n:〈x2,x0〉〉 (w16_to_recw16_aux1_2 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_4 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x4,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x3,xF〉〉 (w16_S 〈n:〈x3,xE〉〉 (w16_S 〈n:〈x3,xD〉〉 (w16_S 〈n:〈x3,xC〉〉 (
+ w16_S 〈n:〈x3,xB〉〉 (w16_S 〈n:〈x3,xA〉〉 (w16_S 〈n:〈x3,x9〉〉 (w16_S 〈n:〈x3,x8〉〉 (
+ w16_S 〈n:〈x3,x7〉〉 (w16_S 〈n:〈x3,x6〉〉 (w16_S 〈n:〈x3,x5〉〉 (w16_S 〈n:〈x3,x4〉〉 (
+ w16_S 〈n:〈x3,x3〉〉 (w16_S 〈n:〈x3,x2〉〉 (w16_S 〈n:〈x3,x1〉〉 (w16_S 〈n:〈x3,x0〉〉 (w16_to_recw16_aux1_3 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_5 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x5,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x4,xF〉〉 (w16_S 〈n:〈x4,xE〉〉 (w16_S 〈n:〈x4,xD〉〉 (w16_S 〈n:〈x4,xC〉〉 (
+ w16_S 〈n:〈x4,xB〉〉 (w16_S 〈n:〈x4,xA〉〉 (w16_S 〈n:〈x4,x9〉〉 (w16_S 〈n:〈x4,x8〉〉 (
+ w16_S 〈n:〈x4,x7〉〉 (w16_S 〈n:〈x4,x6〉〉 (w16_S 〈n:〈x4,x5〉〉 (w16_S 〈n:〈x4,x4〉〉 (
+ w16_S 〈n:〈x4,x3〉〉 (w16_S 〈n:〈x4,x2〉〉 (w16_S 〈n:〈x4,x1〉〉 (w16_S 〈n:〈x4,x0〉〉 (w16_to_recw16_aux1_4 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_6 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x6,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x5,xF〉〉 (w16_S 〈n:〈x5,xE〉〉 (w16_S 〈n:〈x5,xD〉〉 (w16_S 〈n:〈x5,xC〉〉 (
+ w16_S 〈n:〈x5,xB〉〉 (w16_S 〈n:〈x5,xA〉〉 (w16_S 〈n:〈x5,x9〉〉 (w16_S 〈n:〈x5,x8〉〉 (
+ w16_S 〈n:〈x5,x7〉〉 (w16_S 〈n:〈x5,x6〉〉 (w16_S 〈n:〈x5,x5〉〉 (w16_S 〈n:〈x5,x4〉〉 (
+ w16_S 〈n:〈x5,x3〉〉 (w16_S 〈n:〈x5,x2〉〉 (w16_S 〈n:〈x5,x1〉〉 (w16_S 〈n:〈x5,x0〉〉 (w16_to_recw16_aux1_5 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_7 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x7,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x6,xF〉〉 (w16_S 〈n:〈x6,xE〉〉 (w16_S 〈n:〈x6,xD〉〉 (w16_S 〈n:〈x6,xC〉〉 (
+ w16_S 〈n:〈x6,xB〉〉 (w16_S 〈n:〈x6,xA〉〉 (w16_S 〈n:〈x6,x9〉〉 (w16_S 〈n:〈x6,x8〉〉 (
+ w16_S 〈n:〈x6,x7〉〉 (w16_S 〈n:〈x6,x6〉〉 (w16_S 〈n:〈x6,x5〉〉 (w16_S 〈n:〈x6,x4〉〉 (
+ w16_S 〈n:〈x6,x3〉〉 (w16_S 〈n:〈x6,x2〉〉 (w16_S 〈n:〈x6,x1〉〉 (w16_S 〈n:〈x6,x0〉〉 (w16_to_recw16_aux1_6 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_8 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x8,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x7,xF〉〉 (w16_S 〈n:〈x7,xE〉〉 (w16_S 〈n:〈x7,xD〉〉 (w16_S 〈n:〈x7,xC〉〉 (
+ w16_S 〈n:〈x7,xB〉〉 (w16_S 〈n:〈x7,xA〉〉 (w16_S 〈n:〈x7,x9〉〉 (w16_S 〈n:〈x7,x8〉〉 (
+ w16_S 〈n:〈x7,x7〉〉 (w16_S 〈n:〈x7,x6〉〉 (w16_S 〈n:〈x7,x5〉〉 (w16_S 〈n:〈x7,x4〉〉 (
+ w16_S 〈n:〈x7,x3〉〉 (w16_S 〈n:〈x7,x2〉〉 (w16_S 〈n:〈x7,x1〉〉 (w16_S 〈n:〈x7,x0〉〉 (w16_to_recw16_aux1_7 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_9 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈x9,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x8,xF〉〉 (w16_S 〈n:〈x8,xE〉〉 (w16_S 〈n:〈x8,xD〉〉 (w16_S 〈n:〈x8,xC〉〉 (
+ w16_S 〈n:〈x8,xB〉〉 (w16_S 〈n:〈x8,xA〉〉 (w16_S 〈n:〈x8,x9〉〉 (w16_S 〈n:〈x8,x8〉〉 (
+ w16_S 〈n:〈x8,x7〉〉 (w16_S 〈n:〈x8,x6〉〉 (w16_S 〈n:〈x8,x5〉〉 (w16_S 〈n:〈x8,x4〉〉 (
+ w16_S 〈n:〈x8,x3〉〉 (w16_S 〈n:〈x8,x2〉〉 (w16_S 〈n:〈x8,x1〉〉 (w16_S 〈n:〈x8,x0〉〉 (w16_to_recw16_aux1_8 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_10 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈xA,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈x9,xF〉〉 (w16_S 〈n:〈x9,xE〉〉 (w16_S 〈n:〈x9,xD〉〉 (w16_S 〈n:〈x9,xC〉〉 (
+ w16_S 〈n:〈x9,xB〉〉 (w16_S 〈n:〈x9,xA〉〉 (w16_S 〈n:〈x9,x9〉〉 (w16_S 〈n:〈x9,x8〉〉 (
+ w16_S 〈n:〈x9,x7〉〉 (w16_S 〈n:〈x9,x6〉〉 (w16_S 〈n:〈x9,x5〉〉 (w16_S 〈n:〈x9,x4〉〉 (
+ w16_S 〈n:〈x9,x3〉〉 (w16_S 〈n:〈x9,x2〉〉 (w16_S 〈n:〈x9,x1〉〉 (w16_S 〈n:〈x9,x0〉〉 (w16_to_recw16_aux1_9 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_11 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈xB,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈xA,xF〉〉 (w16_S 〈n:〈xA,xE〉〉 (w16_S 〈n:〈xA,xD〉〉 (w16_S 〈n:〈xA,xC〉〉 (
+ w16_S 〈n:〈xA,xB〉〉 (w16_S 〈n:〈xA,xA〉〉 (w16_S 〈n:〈xA,x9〉〉 (w16_S 〈n:〈xA,x8〉〉 (
+ w16_S 〈n:〈xA,x7〉〉 (w16_S 〈n:〈xA,x6〉〉 (w16_S 〈n:〈xA,x5〉〉 (w16_S 〈n:〈xA,x4〉〉 (
+ w16_S 〈n:〈xA,x3〉〉 (w16_S 〈n:〈xA,x2〉〉 (w16_S 〈n:〈xA,x1〉〉 (w16_S 〈n:〈xA,x0〉〉 (w16_to_recw16_aux1_10 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_12 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈xC,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈xB,xF〉〉 (w16_S 〈n:〈xB,xE〉〉 (w16_S 〈n:〈xB,xD〉〉 (w16_S 〈n:〈xB,xC〉〉 (
+ w16_S 〈n:〈xB,xB〉〉 (w16_S 〈n:〈xB,xA〉〉 (w16_S 〈n:〈xB,x9〉〉 (w16_S 〈n:〈xB,x8〉〉 (
+ w16_S 〈n:〈xB,x7〉〉 (w16_S 〈n:〈xB,x6〉〉 (w16_S 〈n:〈xB,x5〉〉 (w16_S 〈n:〈xB,x4〉〉 (
+ w16_S 〈n:〈xB,x3〉〉 (w16_S 〈n:〈xB,x2〉〉 (w16_S 〈n:〈xB,x1〉〉 (w16_S 〈n:〈xB,x0〉〉 (w16_to_recw16_aux1_11 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_13 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈xD,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈xC,xF〉〉 (w16_S 〈n:〈xC,xE〉〉 (w16_S 〈n:〈xC,xD〉〉 (w16_S 〈n:〈xC,xC〉〉 (
+ w16_S 〈n:〈xC,xB〉〉 (w16_S 〈n:〈xC,xA〉〉 (w16_S 〈n:〈xC,x9〉〉 (w16_S 〈n:〈xC,x8〉〉 (
+ w16_S 〈n:〈xC,x7〉〉 (w16_S 〈n:〈xC,x6〉〉 (w16_S 〈n:〈xC,x5〉〉 (w16_S 〈n:〈xC,x4〉〉 (
+ w16_S 〈n:〈xC,x3〉〉 (w16_S 〈n:〈xC,x2〉〉 (w16_S 〈n:〈xC,x1〉〉 (w16_S 〈n:〈xC,x0〉〉 (w16_to_recw16_aux1_12 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_14 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈xE,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈xD,xF〉〉 (w16_S 〈n:〈xD,xE〉〉 (w16_S 〈n:〈xD,xD〉〉 (w16_S 〈n:〈xD,xC〉〉 (
+ w16_S 〈n:〈xD,xB〉〉 (w16_S 〈n:〈xD,xA〉〉 (w16_S 〈n:〈xD,x9〉〉 (w16_S 〈n:〈xD,x8〉〉 (
+ w16_S 〈n:〈xD,x7〉〉 (w16_S 〈n:〈xD,x6〉〉 (w16_S 〈n:〈xD,x5〉〉 (w16_S 〈n:〈xD,x4〉〉 (
+ w16_S 〈n:〈xD,x3〉〉 (w16_S 〈n:〈xD,x2〉〉 (w16_S 〈n:〈xD,x1〉〉 (w16_S 〈n:〈xD,x0〉〉 (w16_to_recw16_aux1_13 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1_15 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈n:〈xF,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈xE,xF〉〉 (w16_S 〈n:〈xE,xE〉〉 (w16_S 〈n:〈xE,xD〉〉 (w16_S 〈n:〈xE,xC〉〉 (
+ w16_S 〈n:〈xE,xB〉〉 (w16_S 〈n:〈xE,xA〉〉 (w16_S 〈n:〈xE,x9〉〉 (w16_S 〈n:〈xE,x8〉〉 (
+ w16_S 〈n:〈xE,x7〉〉 (w16_S 〈n:〈xE,x6〉〉 (w16_S 〈n:〈xE,x5〉〉 (w16_S 〈n:〈xE,x4〉〉 (
+ w16_S 〈n:〈xE,x3〉〉 (w16_S 〈n:〈xE,x2〉〉 (w16_S 〈n:〈xE,x1〉〉 (w16_S 〈n:〈xE,x0〉〉 (w16_to_recw16_aux1_14 ? recw)
+ ))))))))))))))).
+
+ndefinition w16_to_recw16_aux1 : Πn.rec_word16 〈n:〈x0,x0〉〉 → rec_word16 〈(succc ? n):〈x0,x0〉〉 ≝
+λn.λrecw:rec_word16 〈n:〈x0,x0〉〉.
+ w16_S 〈n:〈xF,xF〉〉 (w16_S 〈n:〈xF,xE〉〉 (w16_S 〈n:〈xF,xD〉〉 (w16_S 〈n:〈xF,xC〉〉 (
+ w16_S 〈n:〈xF,xB〉〉 (w16_S 〈n:〈xF,xA〉〉 (w16_S 〈n:〈xF,x9〉〉 (w16_S 〈n:〈xF,x8〉〉 (
+ w16_S 〈n:〈xF,x7〉〉 (w16_S 〈n:〈xF,x6〉〉 (w16_S 〈n:〈xF,x5〉〉 (w16_S 〈n:〈xF,x4〉〉 (
+ w16_S 〈n:〈xF,x3〉〉 (w16_S 〈n:〈xF,x2〉〉 (w16_S 〈n:〈xF,x1〉〉 (w16_S 〈n:〈xF,x0〉〉 (w16_to_recw16_aux1_15 ? recw)
+ ))))))))))))))).
+
+(* ... cifra byte superiore *)
+nlet rec w16_to_recw16_aux2 (n:byte8) (r:rec_byte8 n) on r ≝
+ match r return λx.λy:rec_byte8 x.rec_word16 〈x:〈x0,x0〉〉 with
+ [ b8_O ⇒ w16_O
+ | b8_S t n' ⇒ w16_to_recw16_aux1 ? (w16_to_recw16_aux2 t n')
+ ].
+
+(* ... cifra esadecimale n.2 *)
+ndefinition w16_to_recw16_aux3 ≝
+λb,n.λrecw:rec_word16 〈b:〈x0,x0〉〉.
+ match n return λx.rec_word16 〈b:〈x,x0〉〉 with
+ [ x0 ⇒ recw
+ | x1 ⇒ w16_to_recw16_aux1_1 ? recw
+ | x2 ⇒ w16_to_recw16_aux1_2 ? recw
+ | x3 ⇒ w16_to_recw16_aux1_3 ? recw
+ | x4 ⇒ w16_to_recw16_aux1_4 ? recw
+ | x5 ⇒ w16_to_recw16_aux1_5 ? recw
+ | x6 ⇒ w16_to_recw16_aux1_6 ? recw
+ | x7 ⇒ w16_to_recw16_aux1_7 ? recw
+ | x8 ⇒ w16_to_recw16_aux1_8 ? recw
+ | x9 ⇒ w16_to_recw16_aux1_9 ? recw
+ | xA ⇒ w16_to_recw16_aux1_10 ? recw
+ | xB ⇒ w16_to_recw16_aux1_11 ? recw
+ | xC ⇒ w16_to_recw16_aux1_12 ? recw
+ | xD ⇒ w16_to_recw16_aux1_13 ? recw
+ | xE ⇒ w16_to_recw16_aux1_14 ? recw
+ | xF ⇒ w16_to_recw16_aux1_15 ? recw
+ ].
+
+ndefinition w16_to_recw16_aux4_1 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x1〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x1〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? recw
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? recw
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? recw
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? recw
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? recw
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? recw
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? recw
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? recw
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? recw
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? recw
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? recw
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? recw
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? recw
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? recw
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? recw
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? recw
+ ].
+
+ndefinition w16_to_recw16_aux4_2 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x2〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x2〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_1 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_3 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x3〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x3〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_2 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_4 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x4〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x4〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_3 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_5 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x5〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x5〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_4 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_6 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x6〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x6〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_5 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_7 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x7〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x7〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_6 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_8 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x8〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x8〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_7 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_9 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,x9〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,x9〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_8 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_10 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,xA〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,xA〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_9 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_11 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,xB〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,xB〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_10 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_12 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,xC〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,xC〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_11 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_13 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,xD〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,xD〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_12 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_14 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,xE〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,xE〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_13 … recw)
+ ].
+
+ndefinition w16_to_recw16_aux4_15 : Πn,e.rec_word16 〈n:〈e,x0〉〉 → rec_word16 〈n:〈e,xF〉〉 ≝
+λn,e.
+ match e return λx.rec_word16 〈n:〈x,x0〉〉 → rec_word16 〈n:〈x,xF〉〉 with
+ [ x0 ⇒ λrecw:rec_word16 〈n:〈x0,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x1 ⇒ λrecw:rec_word16 〈n:〈x1,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x2 ⇒ λrecw:rec_word16 〈n:〈x2,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x3 ⇒ λrecw:rec_word16 〈n:〈x3,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x4 ⇒ λrecw:rec_word16 〈n:〈x4,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x5 ⇒ λrecw:rec_word16 〈n:〈x5,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x6 ⇒ λrecw:rec_word16 〈n:〈x6,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x7 ⇒ λrecw:rec_word16 〈n:〈x7,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x8 ⇒ λrecw:rec_word16 〈n:〈x8,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | x9 ⇒ λrecw:rec_word16 〈n:〈x9,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | xA ⇒ λrecw:rec_word16 〈n:〈xA,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | xB ⇒ λrecw:rec_word16 〈n:〈xB,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | xC ⇒ λrecw:rec_word16 〈n:〈xC,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | xD ⇒ λrecw:rec_word16 〈n:〈xD,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | xE ⇒ λrecw:rec_word16 〈n:〈xE,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ | xF ⇒ λrecw:rec_word16 〈n:〈xF,x0〉〉.w16_S ? (w16_to_recw16_aux4_14 … recw)
+ ].
+
+(* ... cifra esadecimale n.1 *)
+ndefinition w16_to_recw16_aux4 ≝
+λb,e,n.λrecw:rec_word16 〈b:〈e,x0〉〉.
+ match n return λx.rec_word16 〈b:〈e,x〉〉 with
+ [ x0 ⇒ recw
+ | x1 ⇒ w16_to_recw16_aux4_1 … recw
+ | x2 ⇒ w16_to_recw16_aux4_2 … recw
+ | x3 ⇒ w16_to_recw16_aux4_3 … recw
+ | x4 ⇒ w16_to_recw16_aux4_4 … recw
+ | x5 ⇒ w16_to_recw16_aux4_5 … recw
+ | x6 ⇒ w16_to_recw16_aux4_6 … recw
+ | x7 ⇒ w16_to_recw16_aux4_7 … recw
+ | x8 ⇒ w16_to_recw16_aux4_8 … recw
+ | x9 ⇒ w16_to_recw16_aux4_9 … recw
+ | xA ⇒ w16_to_recw16_aux4_10 … recw
+ | xB ⇒ w16_to_recw16_aux4_11 … recw
+ | xC ⇒ w16_to_recw16_aux4_12 … recw
+ | xD ⇒ w16_to_recw16_aux4_13 … recw
+ | xE ⇒ w16_to_recw16_aux4_14 … recw
+ | xF ⇒ w16_to_recw16_aux4_15 … recw
+ ].
+
+ndefinition w16_to_recw16 : Πw.rec_word16 w ≝
+λw.
+ match w with [ mk_comp_num h l ⇒
+ match l with [ mk_comp_num lh ll ⇒
+ w16_to_recw16_aux4 h lh ll (w16_to_recw16_aux3 h lh (w16_to_recw16_aux2 h (b8_to_recb8 h))) ]].
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/byte8.ma".
+
+(* ********* *)
+(* BYTE+WORD *)
+(* ********* *)
+
+nrecord word24 : Type ≝
+ {
+ w24x: byte8;
+ w24h: byte8;
+ w24l: byte8
+ }.
+
+(* \langle \rangle *)
+notation "〈x;y;z〉" non associative with precedence 80
+ for @{ 'mk_word24 $x $y $z }.
+interpretation "mk_word24" 'mk_word24 x y z = (mk_word24 x y z).
+
+(* operatore = *)
+ndefinition eq_w24 ≝
+λw1,w2.(eqc ? (w24x w1) (w24x w2)) ⊗
+ (eqc ? (w24h w1) (w24h w2)) ⊗
+ (eqc ? (w24l w1) (w24l w2)).
+
+nlemma word24_destruct_1 :
+∀x1,x2,y1,y2,z1,z2.
+ mk_word24 x1 y1 z1 = mk_word24 x2 y2 z2 → x1 = x2.
+ #x1; #x2; #y1; #y2; #z1; #z2; #H;
+ nchange with (match mk_word24 x2 y2 z2 with [ mk_word24 a _ _ ⇒ x1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma word24_destruct_2 :
+∀x1,x2,y1,y2,z1,z2.
+ mk_word24 x1 y1 z1 = mk_word24 x2 y2 z2 → y1 = y2.
+ #x1; #x2; #y1; #y2; #z1; #z2; #H;
+ nchange with (match mk_word24 x2 y2 z2 with [ mk_word24 _ a _ ⇒ y1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma word24_destruct_3 :
+∀x1,x2,y1,y2,z1,z2.
+ mk_word24 x1 y1 z1 = mk_word24 x2 y2 z2 → z1 = z2.
+ #x1; #x2; #y1; #y2; #z1; #z2; #H;
+ nchange with (match mk_word24 x2 y2 z2 with [ mk_word24 _ _ a ⇒ z1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma symmetric_eqw24 : symmetricT word24 bool eq_w24.
+ #b1; nelim b1; #e1; #e2; #e3;
+ #b2; nelim b2; #e4; #e5; #e6;
+ nchange with (((eqc ? e1 e4)⊗(eqc ? e2 e5)⊗(eqc ? e3 e6)) = ((eqc ? e4 e1)⊗(eqc ? e5 e2)⊗(eqc ? e6 e3)));
+ nrewrite > (symmetric_eqc ? e1 e4);
+ nrewrite > (symmetric_eqc ? e2 e5);
+ nrewrite > (symmetric_eqc ? e3 e6);
+ napply refl_eq.
+nqed.
+
+nlemma eqw24_to_eq : ∀b1,b2.(eq_w24 b1 b2 = true) → (b1 = b2).
+ #b1; nelim b1; #e1; #e2; #e3;
+ #b2; nelim b2; #e4; #e5; #e6;
+ nchange in ⊢ (% → ?) with (((eqc ? e1 e4)⊗(eqc ? e2 e5)⊗(eqc ? e3 e6)) = true);
+ #H;
+ nrewrite < (eqc_to_eq … (andb_true_true_r … H));
+ nrewrite < (eqc_to_eq … (andb_true_true_r … (andb_true_true_l … H)));
+ nrewrite < (eqc_to_eq … (andb_true_true_l … (andb_true_true_l … H)));
+ napply refl_eq.
+nqed.
+
+nlemma eq_to_eqw24 : ∀b1,b2.(b1 = b2) → (eq_w24 b1 b2 = true).
+ #b1; nelim b1; #e1; #e2; #e3;
+ #b2; nelim b2; #e4; #e5; #e6;
+ #H;
+ nchange with (((eqc ? e1 e4)⊗(eqc ? e2 e5)⊗(eqc ? e3 e6)) = true);
+ nrewrite < (word24_destruct_1 … H);
+ nrewrite < (word24_destruct_2 … H);
+ nrewrite < (word24_destruct_3 … H);
+ nrewrite > (eq_to_eqc ? e1 e1 (refl_eq …));
+ nrewrite > (eq_to_eqc ? e2 e2 (refl_eq …));
+ nrewrite > (eq_to_eqc ? e3 e3 (refl_eq …));
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+nlemma decidable_w24_aux1 :
+∀e1,e2,e3,e4,e5,e6.e1 ≠ e4 → (mk_word24 e1 e2 e3) ≠ (mk_word24 e4 e5 e6).
+ #e1; #e2; #e3; #e4; #e5; #e6;
+ nnormalize; #H; #H1;
+ napply (H (word24_destruct_1 … H1)).
+nqed.
+
+nlemma decidable_w24_aux2 :
+∀e1,e2,e3,e4,e5,e6.e2 ≠ e5 → (mk_word24 e1 e2 e3) ≠ (mk_word24 e4 e5 e6).
+ #e1; #e2; #e3; #e4; #e5; #e6;
+ nnormalize; #H; #H1;
+ napply (H (word24_destruct_2 … H1)).
+nqed.
+
+nlemma decidable_w24_aux3 :
+∀e1,e2,e3,e4,e5,e6.e3 ≠ e6 → (mk_word24 e1 e2 e3) ≠ (mk_word24 e4 e5 e6).
+ #e1; #e2; #e3; #e4; #e5; #e6;
+ nnormalize; #H; #H1;
+ napply (H (word24_destruct_3 … H1)).
+nqed.
+
+nlemma decidable_w24 : ∀b1,b2:word24.(decidable (b1 = b2)).
+ #b1; nelim b1; #e1; #e2; #e3;
+ #b2; nelim b2; #e4; #e5; #e6;
+ nnormalize;
+ napply (or2_elim (e1 = e4) (e1 ≠ e4) ? (decidable_c ? e1 e4) …);
+ ##[ ##2: #H; napply (or2_intro2 … (decidable_w24_aux1 e1 e2 e3 e4 e5 e6 H))
+ ##| ##1: #H; napply (or2_elim (e2 = e5) (e2 ≠ e5) ? (decidable_c ? e2 e5) …);
+ ##[ ##2: #H1; napply (or2_intro2 … (decidable_w24_aux2 e1 e2 e3 e4 e5 e6 H1))
+ ##| ##1: #H1; napply (or2_elim (e3 = e6) (e3 ≠ e6) ? (decidable_c ? e3 e6) …);
+ ##[ ##2: #H2; napply (or2_intro2 … (decidable_w24_aux3 e1 e2 e3 e4 e5 e6 H2))
+ ##| ##1: #H2; nrewrite > H; nrewrite > H1; nrewrite > H2;
+ napply (or2_intro1 … (refl_eq ? (mk_word24 e4 e5 e6)))
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neqw24_to_neq : ∀b1,b2.(eq_w24 b1 b2 = false) → (b1 ≠ b2).
+ #b1; nelim b1; #e1; #e2; #e3;
+ #b2; nelim b2; #e4; #e5; #e6;
+ #H;
+ nchange in H:(%) with (((eqc ? e1 e4)⊗(eqc ? e2 e5)⊗(eqc ? e3 e6)) = false);
+ #H1;
+ nrewrite > (word24_destruct_1 … H1) in H:(%);
+ nrewrite > (word24_destruct_2 … H1);
+ nrewrite > (word24_destruct_3 … H1);
+ nrewrite > (eq_to_eqc ? e4 e4 (refl_eq …));
+ nrewrite > (eq_to_eqc ? e5 e5 (refl_eq …));
+ nrewrite > (eq_to_eqc ? e6 e6 (refl_eq …));
+ #H; ndestruct.
+nqed.
+
+nlemma word24_destruct :
+∀e1,e2,e3,e4,e5,e6.
+ ((mk_word24 e1 e2 e3) ≠ (mk_word24 e4 e5 e6)) →
+ (Or3 (e1 ≠ e4) (e2 ≠ e5) (e3 ≠ e6)).
+ #e1; #e2; #e3; #e4; #e5; #e6;
+ nnormalize; #H;
+ napply (or2_elim (e1 = e4) (e1 ≠ e4) ? (decidable_c ? e1 e4) …);
+ ##[ ##2: #H1; napply (or3_intro1 … H1)
+ ##| ##1: #H1; napply (or2_elim (e2 = e5) (e2 ≠ e5) ? (decidable_c ? e2 e5) …);
+ ##[ ##2: #H2; napply (or3_intro2 … H2)
+ ##| ##1: #H2; napply (or2_elim (e3 = e6) (e3 ≠ e6) ? (decidable_c ? e3 e6) …);
+ ##[ ##2: #H3; napply (or3_intro3 … H3)
+ ##| ##1: #H3; nrewrite > H1 in H:(%);
+ nrewrite > H2; nrewrite > H3;
+ #H; nelim (H (refl_eq …))
+ ##]
+ ##]
+ ##]
+nqed.
+
+nlemma neq_to_neqw24 : ∀b1,b2.((b1 ≠ b2) → (eq_w24 b1 b2 = false)).
+ #b1; nelim b1; #e1; #e2; #e3;
+ #b2; nelim b2; #e4; #e5; #e6;
+ #H; nchange with (((eqc ? e1 e4)⊗(eqc ? e2 e5)⊗(eqc ? e3 e6)) = false);
+ napply (or3_elim (e1 ≠ e4) (e2 ≠ e5) (e3 ≠ e6) ? (word24_destruct e1 e2 e3 e4 e5 e6 … H) …);
+ ##[ ##1: #H1; nrewrite > (neq_to_neqc ? e1 e4 H1); nnormalize; napply refl_eq
+ ##| ##2: #H1; nrewrite > (neq_to_neqc ? e2 e5 H1);
+ nrewrite > (symmetric_andbool (eqc ? e1 e4) …);
+ nnormalize; napply refl_eq
+ ##| ##3: #H1; nrewrite > (neq_to_neqc ? e3 e6 H1);
+ nrewrite > (symmetric_andbool ((eqc ? e1 e4)⊗(eqc ? e2 e5)) …);
+ nnormalize; napply refl_eq
+ ##]
+nqed.
+
+nlemma word24_is_comparable : comparable.
+ @ word24
+ ##[ napply (mk_word24 (zeroc ?) (zeroc ?) (zeroc ?))
+ ##| napply (λP.forallc ?
+ (λx.forallc ?
+ (λh.forallc ?
+ (λl.P (mk_word24 x h l)))))
+ ##| napply eq_w24
+ ##| napply eqw24_to_eq
+ ##| napply eq_to_eqw24
+ ##| napply neqw24_to_neq
+ ##| napply neq_to_neqw24
+ ##| napply decidable_w24
+ ##| napply symmetric_eqw24
+ ##]
+nqed.
+
+unification hint 0 ≔ ⊢ carr word24_is_comparable ≡ word24.
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "num/word16.ma".
+
+(* ***** *)
+(* DWORD *)
+(* ***** *)
+
+ndefinition word32 ≝ comp_num word16.
+ndefinition mk_word32 ≝ λw1,w2.mk_comp_num word16 w1 w2.
+
+(* \langle \rangle *)
+notation "〈x.y〉" non associative with precedence 80
+ for @{ mk_comp_num word16 $x $y }.
+
+ndefinition word32_is_comparable_ext ≝ cn_is_comparable_ext word16_is_comparable_ext.
+unification hint 0 ≔ ⊢ carr (comp_base word32_is_comparable_ext) ≡ comp_num (comp_num (comp_num exadecim)).
+unification hint 0 ≔ ⊢ carr (comp_base word32_is_comparable_ext) ≡ comp_num (comp_num byte8).
+unification hint 0 ≔ ⊢ carr (comp_base word32_is_comparable_ext) ≡ comp_num word16.
+unification hint 0 ≔ ⊢ carr (comp_base word32_is_comparable_ext) ≡ word32.
+
+(* operatore estensione unsigned *)
+ndefinition extu_w32 ≝ λw2.〈zeroc ?.w2〉.
+ndefinition extu2_w32 ≝ λb2.〈zeroc ?.〈zeroc ?:b2〉〉.
+ndefinition extu3_w32 ≝ λe2.〈zeroc ?.〈zeroc ?:〈zeroc ?,e2〉〉〉.
+
+(* operatore estensione signed *)
+ndefinition exts_w32 ≝
+λw2.〈(match getMSBc ? w2 with
+ [ true ⇒ predc ? (zeroc ?) | false ⇒ zeroc ? ]).w2〉.
+ndefinition exts2_w32 ≝
+λb2.(match getMSBc ? b2 with
+ [ true ⇒ 〈predc ? (zeroc ?).〈predc ? (zeroc ?):b2〉〉
+ | false ⇒ 〈zeroc ?.〈zeroc ?:b2〉〉 ]).
+ndefinition exts3_w32 ≝
+λe2.(match getMSBc ? e2 with
+ [ true ⇒ 〈predc ? (zeroc ?).〈predc ? (zeroc ?):〈predc ? (zeroc ?),e2〉〉〉
+ | false ⇒ 〈zeroc ?.〈zeroc ?:〈zeroc ?,e2〉〉〉 ]).
+
+(* operatore moltiplicazione senza segno *)
+(* 〈a1,a2〉 * 〈b1,b2〉 = (a1*b1) x0 x0 + x0 (a1*b2) x0 + x0 (a2*b1) x0 + x0 x0 (a2*b2) *)
+ndefinition mulu_w16_aux ≝
+λw:word32.nat_it ? (rolc ?) w nat8.
+
+ndefinition mulu_w16 ≝
+λw1,w2:word16.
+ plusc_d_d ? 〈(mulu_b8 (cnH ? w1) (cnH ? w2)).zeroc ?〉
+ (plusc_d_d ? (mulu_w16_aux (extu_w32 (mulu_b8 (cnH ? w1) (cnL ? w2))))
+ (plusc_d_d ? (mulu_w16_aux (extu_w32 (mulu_b8 (cnL ? w1) (cnH ? w2))))
+ (extu_w32 (mulu_b8 (cnL ? w1) (cnL ? w2))))).
+
+(* operatore moltiplicazione con segno *)
+(* x * y = sgn(x) * sgn(y) * |x| * |y| *)
+ndefinition muls_w16 ≝
+λw1,w2:word16.
+(* ++/-- → +, +-/-+ → - *)
+ match (getMSBc ? w1) ⊙ (getMSBc ? w2) with
+ (* +- -+ → - *)
+ [ true ⇒ complc ?
+ (* ++/-- → + *)
+ | false ⇒ λx.x ] (mulu_w16 (absc ? w1) (absc ? w2)).
--- /dev/null
+baseuri=cic:/matita
--- /dev/null
+(**************************************************************************)
+(* ___ *)
+(* ||M|| *)
+(* ||A|| A project by Andrea Asperti *)
+(* ||T|| *)
+(* ||I|| Developers: *)
+(* ||T|| The HELM team. *)
+(* ||A|| http://helm.cs.unibo.it *)
+(* \ / *)
+(* \ / This file is distributed under the terms of the *)
+(* v GNU General Public License Version 2 *)
+(* *)
+(**************************************************************************)
+
+(* ********************************************************************** *)
+(* Progetto FreeScale *)
+(* *)
+(* Sviluppato da: Ing. Cosimo Oliboni, oliboni@cs.unibo.it *)
+(* Sviluppo: 2008-2010 *)
+(* *)
+(* ********************************************************************** *)
+
+include "common/nelist.ma".
+include "common/prod.ma".
+
+nlet rec nmember_natList (elem:nat) (l:ne_list nat) on l ≝
+ match l with
+ [ ne_nil h ⇒ ⊖(eqc ? elem h)
+ | ne_cons h t ⇒ match eqc ? elem h with
+ [ true ⇒ false | false ⇒ nmember_natList elem t ]
+ ].
+
+(* elem presente una ed una sola volta in l *)
+nlet rec member_natList (elem:nat) (l:ne_list nat) on l ≝
+ match l with
+ [ ne_nil h ⇒ eqc ? elem h
+ | ne_cons h t ⇒ match eqc ? elem h with
+ [ true ⇒ nmember_natList elem t | false ⇒ member_natList elem t ]
+ ].
+
+(* costruttore di un sottouniverso:
+ S_EL cioe' uno qualsiasi degli elementi del sottouniverso
+*)
+ninductive S_UN (l:ne_list nat) : Type ≝
+ S_EL : Πx:nat.((member_natList x l) = true) → S_UN l.
+
+ndefinition getelem : ∀l.∀e:S_UN l.nat.
+ #l; #s; nelim s;
+ #u; #dim;
+ napply u.
+nqed.
+
+ndefinition eq_SUN ≝ λl.λx,y:S_UN l.eq_nat (getelem ? x) (getelem ? y).
+
+ndefinition getdim : ∀l.∀e:S_UN l.member_natList (getelem ? e) l = true.
+ #l; #s; nelim s;
+ #u; #dim;
+ napply dim.
+nqed.
+
+nlemma SUN_destruct_1
+ : ∀l.∀e1,e2.∀dim1,dim2.S_EL l e1 dim1 = S_EL l e2 dim2 → e1 = e2.
+ #l; #e1; #e2; #dim1; #dim2; #H;
+ nchange with (match S_EL l e2 dim2 with [ S_EL a _ ⇒ e1 = a ]);
+ nrewrite < H;
+ nnormalize;
+ napply refl_eq.
+nqed.
+
+(* destruct universale *)
+ndefinition SUN_destruct : ∀l.∀x,y:S_UN l.∀P:Prop.x = y → match eq_SUN l x y with [ true ⇒ P → P | false ⇒ P ].
+ #l; #x; nelim x;
+ #u1; #dim1;
+ #y; nelim y;
+ #u2; #dim2;
+ #P;
+ nchange with (? → (match eq_nat u1 u2 with [ true ⇒ P → P | false ⇒ P ]));
+ #H;
+ nrewrite > (SUN_destruct_1 l … H);
+ nrewrite > (eq_to_eqc ? u2 u2 (refl_eq …));
+ nnormalize;
+ napply (λx.x).
+nqed.
+
+(* eq_to_eqxx universale *)
+nlemma eq_to_eqSUN : ∀l.∀x,y:S_UN l.x = y → eq_SUN l x y = true.
+ #l; #x; nelim x;
+ #u1; #dim1;
+ #y; nelim y;
+ #u2; #dim2;
+ nchange with (? → eqc ? u1 u2 = true);
+ #H; napply (eq_to_eqc ? u1 u2);
+ napply (SUN_destruct_1 l … H).
+nqed.
+
+(* neqxx_to_neq universale *)
+nlemma neqSUN_to_neq : ∀l.∀x,y:S_UN l.eq_SUN l x y = false → x ≠ y.
+ #l; #n1; #n2; #H;
+ napply (not_to_not (n1 = n2) (eq_SUN l n1 n2 = true) …);
+ ##[ ##1: napply (eq_to_eqSUN l n1 n2)
+ ##| ##2: napply (eqfalse_to_neqtrue … H)
+ ##]
+nqed.
+
+(* eqxx_to_eq universale *)
+(* !!! evidente ma come si fa? *)
+naxiom eqSUN_to_eq_aux : ∀l,x,y.((getelem l x) = (getelem l y)) → x = y.
+
+nlemma eqSUN_to_eq : ∀l.∀x,y:S_UN l.eq_SUN l x y = true → x = y.
+ #l; #x; #y;
+ nchange with ((eqc ? (getelem ? x) (getelem ? y) = true) → x = y);
+ #H; napply (eqSUN_to_eq_aux l x y (eqc_to_eq … H)).
+nqed.
+
+(* neq_to_neqxx universale *)
+nlemma neq_to_neqSUN : ∀l.∀x,y:S_UN l.x ≠ y → eq_SUN l x y = false.
+ #l; #n1; #n2; #H;
+ napply (neqtrue_to_eqfalse (eq_SUN l n1 n2));
+ napply (not_to_not (eq_SUN l n1 n2 = true) (n1 = n2) ? H);
+ napply (eqSUN_to_eq l n1 n2).
+nqed.
+
+(* decidibilita' universale *)
+nlemma decidable_SUN : ∀l.∀x,y:S_UN l.decidable (x = y).
+ #l; #x; #y; nnormalize;
+ napply (or2_elim (eq_SUN l x y = true) (eq_SUN l x y = false) ? (decidable_bexpr ?));
+ ##[ ##1: #H; napply (or2_intro1 (x = y) (x ≠ y) (eqSUN_to_eq l … H))
+ ##| ##2: #H; napply (or2_intro2 (x = y) (x ≠ y) (neqSUN_to_neq l … H))
+ ##]
+nqed.
+
+(* simmetria di uguaglianza universale *)
+nlemma symmetric_eqSUN : ∀l.symmetricT (S_UN l) bool (eq_SUN l).
+ #l; #n1; #n2;
+ napply (or2_elim (n1 = n2) (n1 ≠ n2) ? (decidable_SUN l n1 n2));
+ ##[ ##1: #H; nrewrite > H; napply refl_eq
+ ##| ##2: #H; nrewrite > (neq_to_neqSUN l n1 n2 H);
+ napply (symmetric_eq ? (eq_SUN l n2 n1) false);
+ napply (neq_to_neqSUN l n2 n1 (symmetric_neq ? n1 n2 H))
+ ##]
+nqed.
+
+(* scheletro di funzione generica ad 1 argomento *)
+nlet rec farg1_auxT (T:Type) (l:ne_list nat) on l ≝
+ match l with
+ [ ne_nil _ ⇒ T
+ | ne_cons _ t ⇒ ProdT T (farg1_auxT T t)
+ ].
+
+nlemma farg1_auxDim : ∀h,t,x.eqc ? x h = false → member_natList x (h§§t) = true → member_natList x t = true.
+ #h; #t; #x; #H; #H1;
+ nnormalize in H1:(%);
+ nrewrite > H in H1:(%);
+ nnormalize;
+ napply (λx.x).
+nqed.
+
+nlet rec farg1 (T:Type) (l:ne_list nat) on l ≝
+ match l with
+ [ ne_nil h ⇒ λarg:farg1_auxT T «£h».λx:S_UN «£h».arg
+ | ne_cons h t ⇒ λarg:farg1_auxT T (h§§t).λx:S_UN (h§§t).
+ match eqc ? (getelem ? x) h
+ return λy.eqc ? (getelem ? x) h = y → ?
+ with
+ [ true ⇒ λp:(eqc ? (getelem ? x) h = true).fst … arg
+ | false ⇒ λp:(eqc ? (getelem ? x) h = false).
+ farg1 T t
+ (snd … arg)
+ (S_EL t (getelem ? x) (farg1_auxDim h t (getelem ? x) p (getdim ? x)))
+ ] (refl_eq ? (eqc ? (getelem ? x) h))
+ ].
+
+(* scheletro di funzione generica a 2 argomenti *)
+nlet rec farg2 (T:Type) (l,lfix:ne_list nat) on l ≝
+ match l with
+ [ ne_nil h ⇒ λarg:farg1_auxT (farg1_auxT T lfix) «£h».λx:S_UN «£h».farg1 T lfix arg
+ | ne_cons h t ⇒ λarg:farg1_auxT (farg1_auxT T lfix) (h§§t).λx:S_UN (h§§t).
+ match eqc ? (getelem ? x) h
+ return λy.eqc ? (getelem ? x) h = y → ?
+ with
+ [ true ⇒ λp:(eqc ? (getelem ? x) h = true).farg1 T lfix (fst … arg)
+ | false ⇒ λp:(eqc ? (getelem ? x) h = false).
+ farg2 T t lfix
+ (snd … arg)
+ (S_EL t (getelem ? x) (farg1_auxDim h t (getelem ? x) p (getdim ? x)))
+ ] (refl_eq ? (eqc ? (getelem ? x) h))
+ ].
+
+(* esempio0: universo ottale *)
+ndefinition oct0 ≝ O.
+ndefinition oct1 ≝ nat1.
+ndefinition oct2 ≝ nat2.
+ndefinition oct3 ≝ nat3.
+ndefinition oct4 ≝ nat4.
+ndefinition oct5 ≝ nat5.
+ndefinition oct6 ≝ nat6.
+ndefinition oct7 ≝ nat7.
+
+ndefinition oct_UN ≝ « oct0 ; oct1 ; oct2 ; oct3 ; oct4 ; oct5 ; oct6 £ oct7 ».
+
+ndefinition uoct0 ≝ S_EL oct_UN oct0 (refl_eq …).
+ndefinition uoct1 ≝ S_EL oct_UN oct1 (refl_eq …).
+ndefinition uoct2 ≝ S_EL oct_UN oct2 (refl_eq …).
+ndefinition uoct3 ≝ S_EL oct_UN oct3 (refl_eq …).
+ndefinition uoct4 ≝ S_EL oct_UN oct4 (refl_eq …).
+ndefinition uoct5 ≝ S_EL oct_UN oct5 (refl_eq …).
+ndefinition uoct6 ≝ S_EL oct_UN oct6 (refl_eq …).
+ndefinition uoct7 ≝ S_EL oct_UN oct7 (refl_eq …).
+
+(* esempio1: NOT ottale *)
+ndefinition octNOT ≝
+ farg1 (S_UN oct_UN) oct_UN
+ (pair … uoct7 (pair … uoct6 (pair … uoct5 (pair … uoct4 (pair … uoct3 (pair … uoct2 (pair … uoct1 uoct0))))))).
+
+(* esempio2: AND ottale *)
+ndefinition octAND0 ≝ pair … uoct0 (pair … uoct0 (pair … uoct0 (pair … uoct0 (pair … uoct0 (pair … uoct0 (pair … uoct0 uoct0)))))).
+ndefinition octAND1 ≝ pair … uoct0 (pair … uoct1 (pair … uoct0 (pair … uoct1 (pair … uoct0 (pair … uoct1 (pair … uoct0 uoct1)))))).
+ndefinition octAND2 ≝ pair … uoct0 (pair … uoct0 (pair … uoct2 (pair … uoct2 (pair … uoct0 (pair … uoct0 (pair … uoct2 uoct2)))))).
+ndefinition octAND3 ≝ pair … uoct0 (pair … uoct1 (pair … uoct2 (pair … uoct3 (pair … uoct0 (pair … uoct1 (pair … uoct2 uoct3)))))).
+ndefinition octAND4 ≝ pair … uoct0 (pair … uoct0 (pair … uoct0 (pair … uoct0 (pair … uoct4 (pair … uoct4 (pair … uoct4 uoct4)))))).
+ndefinition octAND5 ≝ pair … uoct0 (pair … uoct1 (pair … uoct0 (pair … uoct1 (pair … uoct4 (pair … uoct5 (pair … uoct4 uoct5)))))).
+ndefinition octAND6 ≝ pair … uoct0 (pair … uoct0 (pair … uoct2 (pair … uoct2 (pair … uoct4 (pair … uoct4 (pair … uoct6 uoct6)))))).
+ndefinition octAND7 ≝ pair … uoct0 (pair … uoct1 (pair … uoct2 (pair … uoct3 (pair … uoct4 (pair … uoct5 (pair … uoct6 uoct7)))))).
+
+ndefinition octAND ≝
+ farg2 (S_UN oct_UN) oct_UN oct_UN
+ (pair … octAND0 (pair … octAND1 (pair … octAND2 (pair … octAND3 (pair … octAND4 (pair … octAND5 (pair … octAND6 octAND7))))))).
+
+(* ora e' possibile fare
+ octNOT uoctX
+ octAND uoctX uoctY
+*)