wenzelm@45692: (* Title: HOL/Library/Saturated.thy wenzelm@45692: Author: Brian Huffman wenzelm@45692: Author: Peter Gammie wenzelm@45692: Author: Florian Haftmann wenzelm@45692: *) haftmann@44819: haftmann@44819: header {* Saturated arithmetic *} haftmann@44819: haftmann@44819: theory Saturated haftmann@44819: imports Main "~~/src/HOL/Library/Numeral_Type" "~~/src/HOL/Word/Type_Length" haftmann@44819: begin haftmann@44819: haftmann@44819: subsection {* The type of saturated naturals *} haftmann@44819: haftmann@44819: typedef (open) ('a::len) sat = "{.. len_of TYPE('a)}" haftmann@44819: morphisms nat_of Abs_sat haftmann@44819: by auto haftmann@44819: haftmann@44819: lemma sat_eqI: haftmann@44819: "nat_of m = nat_of n \ m = n" haftmann@44819: by (simp add: nat_of_inject) haftmann@44819: haftmann@44819: lemma sat_eq_iff: haftmann@44819: "m = n \ nat_of m = nat_of n" haftmann@44819: by (simp add: nat_of_inject) haftmann@44819: huffman@44883: lemma Abs_sat_nat_of [code abstype]: haftmann@44819: "Abs_sat (nat_of n) = n" haftmann@44819: by (fact nat_of_inverse) haftmann@44819: huffman@44883: definition Abs_sat' :: "nat \ 'a::len sat" where huffman@44883: "Abs_sat' n = Abs_sat (min (len_of TYPE('a)) n)" haftmann@44819: huffman@44883: lemma nat_of_Abs_sat' [simp]: huffman@44883: "nat_of (Abs_sat' n :: ('a::len) sat) = min (len_of TYPE('a)) n" huffman@44883: unfolding Abs_sat'_def by (rule Abs_sat_inverse) simp haftmann@44819: haftmann@44819: lemma nat_of_le_len_of [simp]: haftmann@44819: "nat_of (n :: ('a::len) sat) \ len_of TYPE('a)" haftmann@44819: using nat_of [where x = n] by simp haftmann@44819: haftmann@44819: lemma min_len_of_nat_of [simp]: haftmann@44819: "min (len_of TYPE('a)) (nat_of (n::('a::len) sat)) = nat_of n" haftmann@44819: by (rule min_max.inf_absorb2 [OF nat_of_le_len_of]) haftmann@44819: haftmann@44819: lemma min_nat_of_len_of [simp]: haftmann@44819: "min (nat_of (n::('a::len) sat)) (len_of TYPE('a)) = nat_of n" haftmann@44819: by (subst min_max.inf.commute) simp haftmann@44819: huffman@44883: lemma Abs_sat'_nat_of [simp]: huffman@44883: "Abs_sat' (nat_of n) = n" huffman@44883: by (simp add: Abs_sat'_def nat_of_inverse) haftmann@44819: haftmann@44819: instantiation sat :: (len) linorder haftmann@44819: begin haftmann@44819: haftmann@44819: definition haftmann@44819: less_eq_sat_def: "x \ y \ nat_of x \ nat_of y" haftmann@44819: haftmann@44819: definition haftmann@44819: less_sat_def: "x < y \ nat_of x < nat_of y" haftmann@44819: haftmann@44819: instance haftmann@44819: by default (auto simp add: less_eq_sat_def less_sat_def not_le sat_eq_iff min_max.le_infI1 nat_mult_commute) haftmann@44819: haftmann@44819: end haftmann@44819: huffman@44849: instantiation sat :: (len) "{minus, comm_semiring_1}" haftmann@44819: begin haftmann@44819: haftmann@44819: definition huffman@44883: "0 = Abs_sat' 0" haftmann@44819: haftmann@44819: definition huffman@44883: "1 = Abs_sat' 1" haftmann@44819: haftmann@44819: lemma nat_of_zero_sat [simp, code abstract]: haftmann@44819: "nat_of 0 = 0" haftmann@44819: by (simp add: zero_sat_def) haftmann@44819: haftmann@44819: lemma nat_of_one_sat [simp, code abstract]: haftmann@44819: "nat_of 1 = min 1 (len_of TYPE('a))" haftmann@44819: by (simp add: one_sat_def) haftmann@44819: haftmann@44819: definition huffman@44883: "x + y = Abs_sat' (nat_of x + nat_of y)" haftmann@44819: haftmann@44819: lemma nat_of_plus_sat [simp, code abstract]: haftmann@44819: "nat_of (x + y) = min (nat_of x + nat_of y) (len_of TYPE('a))" haftmann@44819: by (simp add: plus_sat_def) haftmann@44819: haftmann@44819: definition huffman@44883: "x - y = Abs_sat' (nat_of x - nat_of y)" haftmann@44819: haftmann@44819: lemma nat_of_minus_sat [simp, code abstract]: haftmann@44819: "nat_of (x - y) = nat_of x - nat_of y" haftmann@44819: proof - haftmann@44819: from nat_of_le_len_of [of x] have "nat_of x - nat_of y \ len_of TYPE('a)" by arith haftmann@44819: then show ?thesis by (simp add: minus_sat_def) haftmann@44819: qed haftmann@44819: haftmann@44819: definition huffman@44883: "x * y = Abs_sat' (nat_of x * nat_of y)" haftmann@44819: haftmann@44819: lemma nat_of_times_sat [simp, code abstract]: haftmann@44819: "nat_of (x * y) = min (nat_of x * nat_of y) (len_of TYPE('a))" haftmann@44819: by (simp add: times_sat_def) haftmann@44819: haftmann@44819: instance proof haftmann@44819: fix a b c :: "('a::len) sat" haftmann@44819: show "a * b * c = a * (b * c)" haftmann@44819: proof(cases "a = 0") haftmann@44819: case True thus ?thesis by (simp add: sat_eq_iff) haftmann@44819: next haftmann@44819: case False show ?thesis haftmann@44819: proof(cases "c = 0") haftmann@44819: case True thus ?thesis by (simp add: sat_eq_iff) haftmann@44819: next haftmann@44819: case False with `a \ 0` show ?thesis haftmann@44819: by (simp add: sat_eq_iff nat_mult_min_left nat_mult_min_right mult_assoc min_max.inf_assoc min_max.inf_absorb2) haftmann@44819: qed haftmann@44819: qed haftmann@44819: next haftmann@44819: fix a :: "('a::len) sat" haftmann@44819: show "1 * a = a" haftmann@44819: apply (simp add: sat_eq_iff) haftmann@44819: apply (metis One_nat_def len_gt_0 less_Suc0 less_zeroE linorder_not_less min_max.le_iff_inf min_nat_of_len_of nat_mult_1_right nat_mult_commute) haftmann@44819: done haftmann@44819: next haftmann@44819: fix a b c :: "('a::len) sat" haftmann@44819: show "(a + b) * c = a * c + b * c" haftmann@44819: proof(cases "c = 0") haftmann@44819: case True thus ?thesis by (simp add: sat_eq_iff) haftmann@44819: next haftmann@44819: case False thus ?thesis huffman@44848: by (simp add: sat_eq_iff nat_mult_min_left add_mult_distrib min_add_distrib_left min_add_distrib_right min_max.inf_assoc min_max.inf_absorb2) haftmann@44819: qed haftmann@44819: qed (simp_all add: sat_eq_iff mult.commute) haftmann@44819: haftmann@44819: end haftmann@44819: haftmann@44819: instantiation sat :: (len) ordered_comm_semiring haftmann@44819: begin haftmann@44819: haftmann@44819: instance haftmann@44819: by default (auto simp add: less_eq_sat_def less_sat_def not_le sat_eq_iff min_max.le_infI1 nat_mult_commute) haftmann@44819: haftmann@44819: end haftmann@44819: huffman@44883: lemma Abs_sat'_eq_of_nat: "Abs_sat' n = of_nat n" huffman@44849: by (rule sat_eqI, induct n, simp_all) huffman@44849: huffman@44883: abbreviation Sat :: "nat \ 'a::len sat" where huffman@44883: "Sat \ of_nat" huffman@44883: huffman@44883: lemma nat_of_Sat [simp]: huffman@44883: "nat_of (Sat n :: ('a::len) sat) = min (len_of TYPE('a)) n" huffman@44883: by (rule nat_of_Abs_sat' [unfolded Abs_sat'_eq_of_nat]) huffman@44883: huffman@44849: instantiation sat :: (len) number_semiring haftmann@44819: begin haftmann@44819: haftmann@44819: definition haftmann@44819: number_of_sat_def [code del]: "number_of = Sat \ nat" haftmann@44819: huffman@44849: instance huffman@44883: by default (simp add: number_of_sat_def) haftmann@44819: haftmann@44819: end haftmann@44819: haftmann@44819: lemma [code abstract]: haftmann@44819: "nat_of (number_of n :: ('a::len) sat) = min (nat n) (len_of TYPE('a))" haftmann@44819: unfolding number_of_sat_def by simp haftmann@44819: haftmann@44819: instance sat :: (len) finite haftmann@44819: proof haftmann@44819: show "finite (UNIV::'a sat set)" haftmann@44819: unfolding type_definition.univ [OF type_definition_sat] haftmann@44819: using finite by simp haftmann@44819: qed haftmann@44819: haftmann@44819: instantiation sat :: (len) equal haftmann@44819: begin haftmann@44819: haftmann@44819: definition haftmann@44819: "HOL.equal A B \ nat_of A = nat_of B" haftmann@44819: haftmann@44819: instance proof haftmann@44819: qed (simp add: equal_sat_def nat_of_inject) haftmann@44819: haftmann@44819: end haftmann@44819: haftmann@44819: instantiation sat :: (len) "{bounded_lattice, distrib_lattice}" haftmann@44819: begin haftmann@44819: haftmann@44819: definition haftmann@44819: "(inf :: 'a sat \ 'a sat \ 'a sat) = min" haftmann@44819: haftmann@44819: definition haftmann@44819: "(sup :: 'a sat \ 'a sat \ 'a sat) = max" haftmann@44819: haftmann@44819: definition haftmann@44819: "bot = (0 :: 'a sat)" haftmann@44819: haftmann@44819: definition haftmann@44819: "top = Sat (len_of TYPE('a))" haftmann@44819: haftmann@44819: instance proof haftmann@44819: qed (simp_all add: inf_sat_def sup_sat_def bot_sat_def top_sat_def min_max.sup_inf_distrib1, haftmann@44819: simp_all add: less_eq_sat_def) haftmann@44819: haftmann@44819: end haftmann@44819: haftmann@44819: instantiation sat :: (len) complete_lattice haftmann@44819: begin haftmann@44819: haftmann@44819: definition haftmann@45994: "Inf (A :: 'a sat set) = Finite_Set.fold min top A" haftmann@44819: haftmann@44819: definition haftmann@45994: "Sup (A :: 'a sat set) = Finite_Set.fold max bot A" haftmann@44819: haftmann@44819: instance proof haftmann@44819: fix x :: "'a sat" haftmann@44819: fix A :: "'a sat set" haftmann@44819: note finite haftmann@44819: moreover assume "x \ A" haftmann@45994: ultimately have "Finite_Set.fold min top A \ min x top" by (rule min_max.fold_inf_le_inf) haftmann@44819: then show "Inf A \ x" by (simp add: Inf_sat_def) haftmann@44819: next haftmann@44819: fix z :: "'a sat" haftmann@44819: fix A :: "'a sat set" haftmann@44819: note finite haftmann@44819: moreover assume z: "\x. x \ A \ z \ x" haftmann@45994: ultimately have "min z top \ Finite_Set.fold min top A" by (blast intro: min_max.inf_le_fold_inf) haftmann@44819: then show "z \ Inf A" by (simp add: Inf_sat_def min_def) haftmann@44819: next haftmann@44819: fix x :: "'a sat" haftmann@44819: fix A :: "'a sat set" haftmann@44819: note finite haftmann@44819: moreover assume "x \ A" haftmann@45994: ultimately have "max x bot \ Finite_Set.fold max bot A" by (rule min_max.sup_le_fold_sup) haftmann@44819: then show "x \ Sup A" by (simp add: Sup_sat_def) haftmann@44819: next haftmann@44819: fix z :: "'a sat" haftmann@44819: fix A :: "'a sat set" haftmann@44819: note finite haftmann@44819: moreover assume z: "\x. x \ A \ x \ z" haftmann@45994: ultimately have "Finite_Set.fold max bot A \ max z bot" by (blast intro: min_max.fold_sup_le_sup) haftmann@44819: then show "Sup A \ z" by (simp add: Sup_sat_def max_def bot_unique) haftmann@44819: qed haftmann@44819: haftmann@44819: end haftmann@44819: haftmann@44819: end