# HG changeset patch # User haftmann # Date 1592471250 0 # Node ID ac6f9738c20099bd969d325cfc05fe5a2fb40a82 # Parent c9251bc7da4e7c2af22be76504b1017891f48db8 essential instance about bit structure diff -r c9251bc7da4e -r ac6f9738c200 src/HOL/Word/Word.thy --- a/src/HOL/Word/Word.thy Thu Jun 18 09:07:29 2020 +0000 +++ b/src/HOL/Word/Word.thy Thu Jun 18 09:07:30 2020 +0000 @@ -286,6 +286,7 @@ end + text \Legacy theorems:\ lemma word_arith_wis [code]: @@ -406,6 +407,44 @@ end +instance word :: (len) semiring_modulo +proof + show "a div b * b + a mod b = a" for a b :: "'a word" + proof transfer + fix k l :: int + define r :: int where "r = 2 ^ LENGTH('a)" + then have r: "take_bit LENGTH('a) k = k mod r" for k + by (simp add: take_bit_eq_mod) + have "k mod r = ((k mod r) div (l mod r) * (l mod r) + + (k mod r) mod (l mod r)) mod r" + by (simp add: div_mult_mod_eq) + also have "... = (((k mod r) div (l mod r) * (l mod r)) mod r + + (k mod r) mod (l mod r)) mod r" + by (simp add: mod_add_left_eq) + also have "... = (((k mod r) div (l mod r) * l) mod r + + (k mod r) mod (l mod r)) mod r" + by (simp add: mod_mult_right_eq) + finally have "k mod r = ((k mod r) div (l mod r) * l + + (k mod r) mod (l mod r)) mod r" + by (simp add: mod_simps) + with r show "take_bit LENGTH('a) (take_bit LENGTH('a) k div take_bit LENGTH('a) l * l + + take_bit LENGTH('a) k mod take_bit LENGTH('a) l) = take_bit LENGTH('a) k" + by simp + qed +qed + +instance word :: (len) semiring_parity +proof + show "\ 2 dvd (1::'a word)" + by transfer simp + show even_iff_mod_2_eq_0: "2 dvd a \ a mod 2 = 0" + for a :: "'a word" + by transfer (simp_all add: mod_2_eq_odd take_bit_Suc) + show "\ 2 dvd a \ a mod 2 = 1" + for a :: "'a word" + by transfer (simp_all add: mod_2_eq_odd take_bit_Suc) +qed + subsection \Ordering\ @@ -433,6 +472,42 @@ "a < b \ uint a < uint b" by transfer rule +lemma word_greater_zero_iff: + \a > 0 \ a \ 0\ for a :: \'a::len0 word\ + by transfer (simp add: less_le) + +lemma of_nat_word_eq_iff: + \of_nat m = (of_nat n :: 'a::len word) \ take_bit LENGTH('a) m = take_bit LENGTH('a) n\ + by transfer (simp add: take_bit_of_nat) + +lemma of_nat_word_less_eq_iff: + \of_nat m \ (of_nat n :: 'a::len word) \ take_bit LENGTH('a) m \ take_bit LENGTH('a) n\ + by transfer (simp add: take_bit_of_nat) + +lemma of_nat_word_less_iff: + \of_nat m < (of_nat n :: 'a::len word) \ take_bit LENGTH('a) m < take_bit LENGTH('a) n\ + by transfer (simp add: take_bit_of_nat) + +lemma of_nat_word_eq_0_iff: + \of_nat n = (0 :: 'a::len word) \ 2 ^ LENGTH('a) dvd n\ + using of_nat_word_eq_iff [where ?'a = 'a, of n 0] by (simp add: take_bit_eq_0_iff) + +lemma of_int_word_eq_iff: + \of_int k = (of_int l :: 'a::len word) \ take_bit LENGTH('a) k = take_bit LENGTH('a) l\ + by transfer rule + +lemma of_int_word_less_eq_iff: + \of_int k \ (of_int l :: 'a::len word) \ take_bit LENGTH('a) k \ take_bit LENGTH('a) l\ + by transfer rule + +lemma of_int_word_less_iff: + \of_int k < (of_int l :: 'a::len word) \ take_bit LENGTH('a) k < take_bit LENGTH('a) l\ + by transfer rule + +lemma of_int_word_eq_0_iff: + \of_int k = (0 :: 'a::len word) \ 2 ^ LENGTH('a) dvd k\ + using of_int_word_eq_iff [where ?'a = 'a, of k 0] by (simp add: take_bit_eq_0_iff) + definition word_sle :: "'a::len word \ 'a word \ bool" ("(_/ <=s _)" [50, 51] 50) where "a <=s b \ sint a \ sint b" @@ -442,6 +517,224 @@ subsection \Bit-wise operations\ +lemma word_bit_induct [case_names zero even odd]: + \P a\ if word_zero: \P 0\ + and word_even: \\a. P a \ 0 < a \ a < 2 ^ (LENGTH('a) - 1) \ P (2 * a)\ + and word_odd: \\a. P a \ a < 2 ^ (LENGTH('a) - 1) \ P (1 + 2 * a)\ + for P and a :: \'a::len word\ +proof - + define m :: nat where \m = LENGTH('a) - 1\ + then have l: \LENGTH('a) = Suc m\ + by simp + define n :: nat where \n = unat a\ + then have \n < 2 ^ LENGTH('a)\ + by (unfold unat_def) (transfer, simp add: take_bit_eq_mod) + then have \n < 2 * 2 ^ m\ + by (simp add: l) + then have \P (of_nat n)\ + proof (induction n rule: nat_bit_induct) + case zero + show ?case + by simp (rule word_zero) + next + case (even n) + then have \n < 2 ^ m\ + by simp + with even.IH have \P (of_nat n)\ + by simp + moreover from \n < 2 ^ m\ even.hyps have \0 < (of_nat n :: 'a word)\ + by (auto simp add: word_greater_zero_iff of_nat_word_eq_0_iff l) + moreover from \n < 2 ^ m\ have \(of_nat n :: 'a word) < 2 ^ (LENGTH('a) - 1)\ + using of_nat_word_less_iff [where ?'a = 'a, of n \2 ^ m\] + by (cases \m = 0\) (simp_all add: not_less take_bit_eq_self ac_simps l) + ultimately have \P (2 * of_nat n)\ + by (rule word_even) + then show ?case + by simp + next + case (odd n) + then have \Suc n \ 2 ^ m\ + by simp + with odd.IH have \P (of_nat n)\ + by simp + moreover from \Suc n \ 2 ^ m\ have \(of_nat n :: 'a word) < 2 ^ (LENGTH('a) - 1)\ + using of_nat_word_less_iff [where ?'a = 'a, of n \2 ^ m\] + by (cases \m = 0\) (simp_all add: not_less take_bit_eq_self ac_simps l) + ultimately have \P (1 + 2 * of_nat n)\ + by (rule word_odd) + then show ?case + by simp + qed + moreover have \of_nat (nat (uint a)) = a\ + by transfer simp + ultimately show ?thesis + by (simp add: n_def unat_def) +qed + +lemma bit_word_half_eq: + \(of_bool b + a * 2) div 2 = a\ + if \a < 2 ^ (LENGTH('a) - Suc 0)\ + for a :: \'a::len word\ +proof (cases \2 \ LENGTH('a::len)\) + case False + have \of_bool (odd k) < (1 :: int) \ even k\ for k :: int + by auto + with False that show ?thesis + by transfer (simp add: eq_iff) +next + case True + obtain n where length: \LENGTH('a) = Suc n\ + by (cases \LENGTH('a)\) simp_all + show ?thesis proof (cases b) + case False + moreover have \a * 2 div 2 = a\ + using that proof transfer + fix k :: int + from length have \k * 2 mod 2 ^ LENGTH('a) = (k mod 2 ^ n) * 2\ + by simp + moreover assume \take_bit LENGTH('a) k < take_bit LENGTH('a) (2 ^ (LENGTH('a) - Suc 0))\ + with \LENGTH('a) = Suc n\ + have \k mod 2 ^ LENGTH('a) = k mod 2 ^ n\ + by (simp add: take_bit_eq_mod divmod_digit_0) + ultimately have \take_bit LENGTH('a) (k * 2) = take_bit LENGTH('a) k * 2\ + by (simp add: take_bit_eq_mod) + with True show \take_bit LENGTH('a) (take_bit LENGTH('a) (k * 2) div take_bit LENGTH('a) 2) + = take_bit LENGTH('a) k\ + by simp + qed + ultimately show ?thesis + by simp + next + case True + moreover have \(1 + a * 2) div 2 = a\ + using that proof transfer + fix k :: int + from length have \(1 + k * 2) mod 2 ^ LENGTH('a) = 1 + (k mod 2 ^ n) * 2\ + using pos_zmod_mult_2 [of \2 ^ n\ k] by (simp add: ac_simps) + moreover assume \take_bit LENGTH('a) k < take_bit LENGTH('a) (2 ^ (LENGTH('a) - Suc 0))\ + with \LENGTH('a) = Suc n\ + have \k mod 2 ^ LENGTH('a) = k mod 2 ^ n\ + by (simp add: take_bit_eq_mod divmod_digit_0) + ultimately have \take_bit LENGTH('a) (1 + k * 2) = 1 + take_bit LENGTH('a) k * 2\ + by (simp add: take_bit_eq_mod) + with True show \take_bit LENGTH('a) (take_bit LENGTH('a) (1 + k * 2) div take_bit LENGTH('a) 2) + = take_bit LENGTH('a) k\ + by (auto simp add: take_bit_Suc) + qed + ultimately show ?thesis + by simp + qed +qed + +lemma even_mult_exp_div_word_iff: + \even (a * 2 ^ m div 2 ^ n) \ \ ( + m \ n \ + n < LENGTH('a) \ odd (a div 2 ^ (n - m)))\ for a :: \'a::len word\ + by transfer + (auto simp flip: drop_bit_eq_div simp add: even_drop_bit_iff_not_bit bit_take_bit_iff, + simp_all flip: push_bit_eq_mult add: bit_push_bit_iff_int) + +instance word :: (len) semiring_bits +proof + show \P a\ if stable: \\a. a div 2 = a \ P a\ + and rec: \\a b. P a \ (of_bool b + 2 * a) div 2 = a \ P (of_bool b + 2 * a)\ + for P and a :: \'a word\ + proof (induction a rule: word_bit_induct) + case zero + have \0 div 2 = (0::'a word)\ + by transfer simp + with stable [of 0] show ?case + by simp + next + case (even a) + with rec [of a False] show ?case + using bit_word_half_eq [of a False] by (simp add: ac_simps) + next + case (odd a) + with rec [of a True] show ?case + using bit_word_half_eq [of a True] by (simp add: ac_simps) + qed + show \0 div a = 0\ + for a :: \'a word\ + by transfer simp + show \a div 1 = a\ + for a :: \'a word\ + by transfer simp + show \a mod b div b = 0\ + for a b :: \'a word\ + apply transfer + apply (simp add: take_bit_eq_mod) + apply (subst (3) mod_pos_pos_trivial [of _ \2 ^ LENGTH('a)\]) + apply simp_all + apply (metis le_less mod_by_0 pos_mod_conj zero_less_numeral zero_less_power) + using pos_mod_bound [of \2 ^ LENGTH('a)\] apply simp + proof - + fix aa :: int and ba :: int + have f1: "\i n. (i::int) mod 2 ^ n = 0 \ 0 < i mod 2 ^ n" + by (metis le_less take_bit_eq_mod take_bit_nonnegative) + have "(0::int) < 2 ^ len_of (TYPE('a)::'a itself) \ ba mod 2 ^ len_of (TYPE('a)::'a itself) \ 0 \ aa mod 2 ^ len_of (TYPE('a)::'a itself) mod (ba mod 2 ^ len_of (TYPE('a)::'a itself)) < 2 ^ len_of (TYPE('a)::'a itself)" + by (metis (no_types) mod_by_0 unique_euclidean_semiring_numeral_class.pos_mod_bound zero_less_numeral zero_less_power) + then show "aa mod 2 ^ len_of (TYPE('a)::'a itself) mod (ba mod 2 ^ len_of (TYPE('a)::'a itself)) < 2 ^ len_of (TYPE('a)::'a itself)" + using f1 by (meson le_less less_le_trans unique_euclidean_semiring_numeral_class.pos_mod_bound) + qed + show \(1 + a) div 2 = a div 2\ + if \even a\ + for a :: \'a word\ + using that by transfer (auto dest: le_Suc_ex simp add: take_bit_Suc) + show \(2 :: 'a word) ^ m div 2 ^ n = of_bool ((2 :: 'a word) ^ m \ 0 \ n \ m) * 2 ^ (m - n)\ + for m n :: nat + by transfer (simp, simp add: exp_div_exp_eq) + show "a div 2 ^ m div 2 ^ n = a div 2 ^ (m + n)" + for a :: "'a word" and m n :: nat + apply transfer + apply (auto simp add: not_less take_bit_drop_bit ac_simps simp flip: drop_bit_eq_div) + apply (simp add: drop_bit_take_bit) + done + show "a mod 2 ^ m mod 2 ^ n = a mod 2 ^ min m n" + for a :: "'a word" and m n :: nat + by transfer (auto simp flip: take_bit_eq_mod simp add: ac_simps) + show \a * 2 ^ m mod 2 ^ n = a mod 2 ^ (n - m) * 2 ^ m\ + if \m \ n\ for a :: "'a word" and m n :: nat + using that apply transfer + apply (auto simp flip: take_bit_eq_mod) + apply (auto simp flip: push_bit_eq_mult simp add: push_bit_take_bit split: split_min_lin) + done + show \a div 2 ^ n mod 2 ^ m = a mod (2 ^ (n + m)) div 2 ^ n\ + for a :: "'a word" and m n :: nat + by transfer (auto simp add: not_less take_bit_drop_bit ac_simps simp flip: take_bit_eq_mod drop_bit_eq_div split: split_min_lin) + show \even ((2 ^ m - 1) div (2::'a word) ^ n) \ 2 ^ n = (0::'a word) \ m \ n\ + for m n :: nat + by transfer (auto simp add: take_bit_of_mask even_mask_div_iff) + show \even (a * 2 ^ m div 2 ^ n) \ n < m \ (2::'a word) ^ n = 0 \ m \ n \ even (a div 2 ^ (n - m))\ + for a :: \'a word\ and m n :: nat + proof transfer + show \even (take_bit LENGTH('a) (k * 2 ^ m) div take_bit LENGTH('a) (2 ^ n)) \ + n < m + \ take_bit LENGTH('a) ((2::int) ^ n) = take_bit LENGTH('a) 0 + \ (m \ n \ even (take_bit LENGTH('a) k div take_bit LENGTH('a) (2 ^ (n - m))))\ + for m n :: nat and k l :: int + by (auto simp flip: take_bit_eq_mod drop_bit_eq_div push_bit_eq_mult + simp add: div_push_bit_of_1_eq_drop_bit drop_bit_take_bit drop_bit_push_bit_int [of n m]) + qed +qed + +context + includes lifting_syntax +begin + +lemma transfer_rule_bit_word [transfer_rule]: + \((pcr_word :: int \ 'a::len word \ bool) ===> (=)) (\k n. n < LENGTH('a) \ bit k n) bit\ +proof - + let ?t = \\a n. odd (take_bit LENGTH('a) a div take_bit LENGTH('a) ((2::int) ^ n))\ + have \((pcr_word :: int \ 'a word \ bool) ===> (=)) ?t bit\ + by (unfold bit_def) transfer_prover + also have \?t = (\k n. n < LENGTH('a) \ bit k n)\ + by (simp add: fun_eq_iff bit_take_bit_iff flip: bit_def) + finally show ?thesis . +qed + +end + definition shiftl1 :: "'a::len0 word \ 'a word" where "shiftl1 w = word_of_int (uint w BIT False)"