diff -r eaac77208cf9 -r 4b011fa5e83b src/HOL/Word/Word.thy --- a/src/HOL/Word/Word.thy Mon Sep 07 16:14:32 2020 +0000 +++ b/src/HOL/Word/Word.thy Tue Sep 08 11:39:16 2020 +0000 @@ -24,7 +24,9 @@ (simp_all add: signed_take_bit_eq_iff_take_bit_eq) -subsection \Type definition and fundamental arithmetic\ +subsection \Fundamentals\ + +subsubsection \Type definition\ quotient_type (overloaded) 'a word = int / \\k l. take_bit LENGTH('a) k = take_bit LENGTH('a::len) l\ morphisms rep Word by (auto intro!: equivpI reflpI sympI transpI) @@ -32,6 +34,9 @@ hide_const (open) rep \ \only for foundational purpose\ hide_const (open) Word \ \only for code generation\ + +subsubsection \Basic arithmetic\ + instantiation word :: (len) comm_ring_1 begin @@ -64,17 +69,68 @@ context includes lifting_syntax - notes power_transfer [transfer_rule] + notes + power_transfer [transfer_rule] + transfer_rule_of_bool [transfer_rule] + transfer_rule_numeral [transfer_rule] + transfer_rule_of_nat [transfer_rule] + transfer_rule_of_int [transfer_rule] + begin lemma power_transfer_word [transfer_rule]: \(pcr_word ===> (=) ===> pcr_word) (^) (^)\ by transfer_prover +lemma [transfer_rule]: + \((=) ===> pcr_word) of_bool of_bool\ + by transfer_prover + +lemma [transfer_rule]: + \((=) ===> pcr_word) numeral numeral\ + by transfer_prover + +lemma [transfer_rule]: + \((=) ===> pcr_word) int of_nat\ + by transfer_prover + +lemma [transfer_rule]: + \((=) ===> pcr_word) (\k. k) of_int\ +proof - + have \((=) ===> pcr_word) of_int of_int\ + by transfer_prover + then show ?thesis by (simp add: id_def) +qed + +lemma [transfer_rule]: + \(pcr_word ===> (\)) even ((dvd) 2 :: 'a::len word \ bool)\ +proof - + have even_word_unfold: "even k \ (\l. take_bit LENGTH('a) k = take_bit LENGTH('a) (2 * l))" (is "?P \ ?Q") + for k :: int + proof + assume ?P + then show ?Q + by auto + next + assume ?Q + then obtain l where "take_bit LENGTH('a) k = take_bit LENGTH('a) (2 * l)" .. + then have "even (take_bit LENGTH('a) k)" + by simp + then show ?P + by simp + qed + show ?thesis by (simp only: even_word_unfold [abs_def] dvd_def [where ?'a = "'a word", abs_def]) + transfer_prover +qed + end - -subsection \Basic code generation setup\ +lemma word_exp_length_eq_0 [simp]: + \(2 :: 'a::len word) ^ LENGTH('a) = 0\ + by transfer simp + + +subsubsection \Basic code generation setup\ lift_definition uint :: \'a::len word \ int\ is \take_bit LENGTH('a)\ . @@ -133,566 +189,42 @@ by transfer (simp add: take_bit_mult) -subsection \Conversions including casts\ - -context - includes lifting_syntax - notes - transfer_rule_of_bool [transfer_rule] - transfer_rule_numeral [transfer_rule] - transfer_rule_of_nat [transfer_rule] - transfer_rule_of_int [transfer_rule] -begin - -lemma [transfer_rule]: - \((=) ===> pcr_word) of_bool of_bool\ - by transfer_prover - -lemma [transfer_rule]: - \((=) ===> pcr_word) numeral numeral\ - by transfer_prover - -lemma [transfer_rule]: - \((=) ===> pcr_word) int of_nat\ - by transfer_prover - -lemma [transfer_rule]: - \((=) ===> pcr_word) (\k. k) of_int\ -proof - - have \((=) ===> pcr_word) of_int of_int\ - by transfer_prover - then show ?thesis by (simp add: id_def) -qed - -end - -lemma word_exp_length_eq_0 [simp]: - \(2 :: 'a::len word) ^ LENGTH('a) = 0\ - by transfer simp - -lemma uint_nonnegative: "0 \ uint w" - by transfer simp - -lemma uint_bounded: "uint w < 2 ^ LENGTH('a)" - for w :: "'a::len word" - by transfer (simp add: take_bit_eq_mod) - -lemma uint_idem: "uint w mod 2 ^ LENGTH('a) = uint w" - for w :: "'a::len word" - using uint_nonnegative uint_bounded by (rule mod_pos_pos_trivial) - -lemma word_uint_eqI: "uint a = uint b \ a = b" - by transfer simp - -lemma word_uint_eq_iff: "a = b \ uint a = uint b" - using word_uint_eqI by auto +subsubsection \Basic conversions\ lift_definition word_of_int :: \int \ 'a::len word\ is \\k. k\ . -lemma Word_eq_word_of_int [code_post]: - \Word.Word = word_of_int\ - by rule (transfer, rule) - -lemma uint_word_of_int_eq [code]: - \uint (word_of_int k :: 'a::len word) = take_bit LENGTH('a) k\ - by transfer rule - -lemma uint_word_of_int: "uint (word_of_int k :: 'a::len word) = k mod 2 ^ LENGTH('a)" - by (simp add: uint_word_of_int_eq take_bit_eq_mod) - -lemma word_of_int_uint: "word_of_int (uint w) = w" - by transfer simp - -lemma split_word_all: "(\x::'a::len word. PROP P x) \ (\x. PROP P (word_of_int x))" -proof - fix x :: "'a word" - assume "\x. PROP P (word_of_int x)" - then have "PROP P (word_of_int (uint x))" . - then show "PROP P x" by (simp add: word_of_int_uint) -qed +lift_definition unat :: \'a::len word \ nat\ + is \nat \ take_bit LENGTH('a)\ + by simp lift_definition sint :: \'a::len word \ int\ \ \treats the most-significant bit as a sign bit\ is \signed_take_bit (LENGTH('a) - 1)\ by (simp add: signed_take_bit_decr_length_iff) -lemma sint_uint [code]: - \sint w = signed_take_bit (LENGTH('a) - 1) (uint w)\ - for w :: \'a::len word\ - by (cases \LENGTH('a)\; transfer) (simp_all add: signed_take_bit_take_bit) - -lift_definition unat :: \'a::len word \ nat\ - is \nat \ take_bit LENGTH('a)\ - by transfer simp - lemma nat_uint_eq [simp]: \nat (uint w) = unat w\ by transfer simp -lemma unat_eq_nat_uint [code]: - \unat w = nat (uint w)\ - by simp - -lift_definition ucast :: \'a::len word \ 'b::len word\ - is \take_bit LENGTH('a)\ - by simp - -lemma ucast_eq [code]: - \ucast w = word_of_int (uint w)\ - by transfer simp - -lift_definition scast :: \'a::len word \ 'b::len word\ - is \signed_take_bit (LENGTH('a) - 1)\ - by (simp flip: signed_take_bit_decr_length_iff) - -lemma scast_eq [code]: - \scast w = word_of_int (sint w)\ - by transfer simp - -lemma uint_0_eq [simp]: - \uint 0 = 0\ - by transfer simp - -lemma uint_1_eq [simp]: - \uint 1 = 1\ - by transfer simp - -lemma word_m1_wi: "- 1 = word_of_int (- 1)" +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_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 uint_0_iff: "uint x = 0 \ x = 0" - by (simp add: word_uint_eq_iff) - -lemma unat_0_iff: "unat x = 0 \ x = 0" - by transfer (auto intro: antisym) - -lemma unat_0 [simp]: "unat 0 = 0" - by transfer simp - -lemma unat_gt_0: "0 < unat x \ x \ 0" - by (auto simp: unat_0_iff [symmetric]) - -lemma ucast_0 [simp]: "ucast 0 = 0" - by transfer simp - -lemma sint_0 [simp]: "sint 0 = 0" - by (simp add: sint_uint) - -lemma scast_0 [simp]: "scast 0 = 0" - by transfer simp - -lemma sint_n1 [simp] : "sint (- 1) = - 1" - by transfer simp - -lemma scast_n1 [simp]: "scast (- 1) = - 1" - by transfer simp - -lemma uint_1: "uint (1::'a::len word) = 1" - by (fact uint_1_eq) - -lemma unat_1 [simp]: "unat (1::'a::len word) = 1" - by transfer simp - -lemma ucast_1 [simp]: "ucast (1::'a::len word) = 1" - by transfer simp - -instantiation word :: (len) size -begin - -lift_definition size_word :: \'a word \ nat\ - is \\_. LENGTH('a)\ .. - -instance .. - -end - -lemma word_size [code]: - \size w = LENGTH('a)\ for w :: \'a::len word\ - by (fact size_word.rep_eq) - -lemma word_size_gt_0 [iff]: "0 < size w" - for w :: "'a::len word" - by (simp add: word_size) - -lemmas lens_gt_0 = word_size_gt_0 len_gt_0 - -lemma lens_not_0 [iff]: - \size w \ 0\ for w :: \'a::len word\ - by auto - -lift_definition source_size :: \('a::len word \ 'b) \ nat\ - is \\_. LENGTH('a)\ . - -lift_definition target_size :: \('a \ 'b::len word) \ nat\ - is \\_. LENGTH('b)\ .. - -lift_definition is_up :: \('a::len word \ 'b::len word) \ bool\ - is \\_. LENGTH('a) \ LENGTH('b)\ .. - -lift_definition is_down :: \('a::len word \ 'b::len word) \ bool\ - is \\_. LENGTH('a) \ LENGTH('b)\ .. - -lemma is_up_eq: - \is_up f \ source_size f \ target_size f\ - for f :: \'a::len word \ 'b::len word\ - by (simp add: source_size.rep_eq target_size.rep_eq is_up.rep_eq) - -lemma is_down_eq: - \is_down f \ target_size f \ source_size f\ - for f :: \'a::len word \ 'b::len word\ - by (simp add: source_size.rep_eq target_size.rep_eq is_down.rep_eq) - -lift_definition word_int_case :: \(int \ 'b) \ 'a::len word \ 'b\ - is \\f. f \ take_bit LENGTH('a)\ by simp - -lemma word_int_case_eq_uint [code]: - \word_int_case f w = f (uint w)\ - by transfer simp - -translations - "case x of XCONST of_int y \ b" \ "CONST word_int_case (\y. b) x" - "case x of (XCONST of_int :: 'a) y \ b" \ "CONST word_int_case (\y. b) x" - - -subsection \Type-definition locale instantiations\ - -definition uints :: "nat \ int set" - \ \the sets of integers representing the words\ - where "uints n = range (take_bit n)" - -definition sints :: "nat \ int set" - where "sints n = range (signed_take_bit (n - 1))" - -lemma uints_num: "uints n = {i. 0 \ i \ i < 2 ^ n}" - by (simp add: uints_def range_bintrunc) - -lemma sints_num: "sints n = {i. - (2 ^ (n - 1)) \ i \ i < 2 ^ (n - 1)}" - by (simp add: sints_def range_sbintrunc) - -definition unats :: "nat \ nat set" - where "unats n = {i. i < 2 ^ n}" - -\ \naturals\ -lemma uints_unats: "uints n = int ` unats n" - apply (unfold unats_def uints_num) - apply safe - apply (rule_tac image_eqI) - apply (erule_tac nat_0_le [symmetric]) - by auto - -lemma unats_uints: "unats n = nat ` uints n" - by (auto simp: uints_unats image_iff) - -lemma td_ext_uint: - "td_ext (uint :: 'a word \ int) word_of_int (uints (LENGTH('a::len))) - (\w::int. w mod 2 ^ LENGTH('a))" - apply (unfold td_ext_def') - apply transfer - apply (simp add: uints_num take_bit_eq_mod) - done - -interpretation word_uint: - td_ext - "uint::'a::len word \ int" - word_of_int - "uints (LENGTH('a::len))" - "\w. w mod 2 ^ LENGTH('a::len)" - by (fact td_ext_uint) - -lemmas td_uint = word_uint.td_thm -lemmas int_word_uint = word_uint.eq_norm - -lemma td_ext_ubin: - "td_ext (uint :: 'a word \ int) word_of_int (uints (LENGTH('a::len))) - (take_bit (LENGTH('a)))" - apply standard - apply transfer - apply simp - done - -interpretation word_ubin: - td_ext - "uint::'a::len word \ int" - word_of_int - "uints (LENGTH('a::len))" - "take_bit (LENGTH('a::len))" - by (fact td_ext_ubin) - -lemma td_ext_unat [OF refl]: - "n = LENGTH('a::len) \ - td_ext (unat :: 'a word \ nat) of_nat (unats n) (\i. i mod 2 ^ n)" - apply (standard; transfer) - apply (simp_all add: unats_def take_bit_int_less_exp take_bit_of_nat take_bit_eq_self) - apply (simp add: take_bit_eq_mod) - done - -lemmas unat_of_nat = td_ext_unat [THEN td_ext.eq_norm] - -interpretation word_unat: - td_ext - "unat::'a::len word \ nat" - of_nat - "unats (LENGTH('a::len))" - "\i. i mod 2 ^ LENGTH('a::len)" - by (rule td_ext_unat) - -lemmas td_unat = word_unat.td_thm - -lemmas unat_lt2p [iff] = word_unat.Rep [unfolded unats_def mem_Collect_eq] - -lemma unat_le: "y \ unat z \ y \ unats (LENGTH('a))" - for z :: "'a::len word" - apply (unfold unats_def) - apply clarsimp - apply (rule xtrans, rule unat_lt2p, assumption) - done - -lemma td_ext_sbin: - "td_ext (sint :: 'a word \ int) word_of_int (sints (LENGTH('a::len))) - (signed_take_bit (LENGTH('a) - 1))" - apply (unfold td_ext_def' sint_uint) - apply (simp add : word_ubin.eq_norm) - apply (cases "LENGTH('a)") - apply (auto simp add : sints_def) - apply (rule sym [THEN trans]) - apply (rule word_ubin.Abs_norm) - apply (simp only: bintrunc_sbintrunc) - apply (drule sym) - apply simp - done - -lemma td_ext_sint: - "td_ext (sint :: 'a word \ int) word_of_int (sints (LENGTH('a::len))) - (\w. (w + 2 ^ (LENGTH('a) - 1)) mod 2 ^ LENGTH('a) - - 2 ^ (LENGTH('a) - 1))" - using td_ext_sbin [where ?'a = 'a] by (simp add: no_sbintr_alt2) - -text \ - We do \sint\ before \sbin\, before \sint\ is the user version - and interpretations do not produce thm duplicates. I.e. - we get the name \word_sint.Rep_eqD\, but not \word_sbin.Req_eqD\, - because the latter is the same thm as the former. -\ -interpretation word_sint: - td_ext - "sint ::'a::len word \ int" - word_of_int - "sints (LENGTH('a::len))" - "\w. (w + 2^(LENGTH('a::len) - 1)) mod 2^LENGTH('a::len) - - 2 ^ (LENGTH('a::len) - 1)" - by (rule td_ext_sint) - -interpretation word_sbin: - td_ext - "sint ::'a::len word \ int" - word_of_int - "sints (LENGTH('a::len))" - "signed_take_bit (LENGTH('a::len) - 1)" - by (rule td_ext_sbin) - -lemmas int_word_sint = td_ext_sint [THEN td_ext.eq_norm] - -lemmas td_sint = word_sint.td - - -subsection \Arithmetic operations\ - -instantiation word :: (len) "{neg_numeral, modulo, comm_monoid_mult, comm_ring}" -begin - -lift_definition divide_word :: "'a word \ 'a word \ 'a word" - is "\a b. take_bit LENGTH('a) a div take_bit LENGTH('a) b" - by simp - -lift_definition modulo_word :: "'a word \ 'a word \ 'a word" - is "\a b. take_bit LENGTH('a) a mod take_bit LENGTH('a) b" - by simp - -instance - by standard (transfer, simp add: algebra_simps)+ - -end - -lemma word_div_def [code]: - "a div b = word_of_int (uint a div uint b)" - by transfer rule - -lemma word_mod_def [code]: - "a mod b = word_of_int (uint a mod uint b)" - by transfer rule - - - -text \Legacy theorems:\ - -lemma word_add_def [code]: - "a + b = word_of_int (uint a + uint b)" - by transfer (simp add: take_bit_add) - -lemma word_sub_wi [code]: - "a - b = word_of_int (uint a - uint b)" - by transfer (simp add: take_bit_diff) - -lemma word_mult_def [code]: - "a * b = word_of_int (uint a * uint b)" - by transfer (simp add: take_bit_eq_mod mod_simps) - -lemma word_minus_def [code]: - "- a = word_of_int (- uint a)" - by transfer (simp add: take_bit_minus) - -lemma word_0_wi: - "0 = word_of_int 0" - by transfer simp - -lemma word_1_wi: - "1 = word_of_int 1" - by transfer simp - -lift_definition word_succ :: "'a::len word \ 'a word" is "\x. x + 1" - by (auto simp add: take_bit_eq_mod intro: mod_add_cong) - -lift_definition word_pred :: "'a::len word \ 'a word" is "\x. x - 1" - by (auto simp add: take_bit_eq_mod intro: mod_diff_cong) - -lemma word_succ_alt [code]: - "word_succ a = word_of_int (uint a + 1)" - by transfer (simp add: take_bit_eq_mod mod_simps) - -lemma word_pred_alt [code]: - "word_pred a = word_of_int (uint a - 1)" - by transfer (simp add: take_bit_eq_mod mod_simps) - -lemmas word_arith_wis = - word_add_def word_sub_wi word_mult_def - word_minus_def word_succ_alt word_pred_alt - word_0_wi word_1_wi - -lemma wi_homs: - shows wi_hom_add: "word_of_int a + word_of_int b = word_of_int (a + b)" - and wi_hom_sub: "word_of_int a - word_of_int b = word_of_int (a - b)" - and wi_hom_mult: "word_of_int a * word_of_int b = word_of_int (a * b)" - and wi_hom_neg: "- word_of_int a = word_of_int (- a)" - and wi_hom_succ: "word_succ (word_of_int a) = word_of_int (a + 1)" - and wi_hom_pred: "word_pred (word_of_int a) = word_of_int (a - 1)" - by (transfer, simp)+ - -lemmas wi_hom_syms = wi_homs [symmetric] - -lemmas word_of_int_homs = wi_homs word_0_wi word_1_wi - -lemmas word_of_int_hom_syms = word_of_int_homs [symmetric] - -instance word :: (len) comm_monoid_add .. - -instance word :: (len) semiring_numeral .. - -lemma word_of_nat: "of_nat n = word_of_int (int n)" - by (induct n) (auto simp add : word_of_int_hom_syms) - -lemma word_of_int: "of_int = word_of_int" - apply (rule ext) - apply (case_tac x rule: int_diff_cases) - apply (simp add: word_of_nat wi_hom_sub) - done - -lemma word_of_int_eq: - "word_of_int = of_int" - by (rule ext) (transfer, rule) - -definition udvd :: "'a::len word \ 'a::len word \ bool" (infixl "udvd" 50) - where "a udvd b = (\n\0. uint b = n * uint a)" - -context - includes lifting_syntax -begin - -lemma [transfer_rule]: - \(pcr_word ===> (\)) even ((dvd) 2 :: 'a::len word \ bool)\ -proof - - have even_word_unfold: "even k \ (\l. take_bit LENGTH('a) k = take_bit LENGTH('a) (2 * l))" (is "?P \ ?Q") - for k :: int - proof - assume ?P - then show ?Q - by auto - next - assume ?Q - then obtain l where "take_bit LENGTH('a) k = take_bit LENGTH('a) (2 * l)" .. - then have "even (take_bit LENGTH('a) k)" - by simp - then show ?P - by simp - qed - show ?thesis by (simp only: even_word_unfold [abs_def] dvd_def [where ?'a = "'a word", abs_def]) - transfer_prover -qed - -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 - -lemma exp_eq_zero_iff: - \2 ^ n = (0 :: 'a::len word) \ n \ LENGTH('a)\ - by transfer simp - -lemma double_eq_zero_iff: - \2 * a = 0 \ a = 0 \ a = 2 ^ (LENGTH('a) - Suc 0)\ - for a :: \'a::len word\ -proof - - define n where \n = LENGTH('a) - Suc 0\ - then have *: \LENGTH('a) = Suc n\ - by simp - have \a = 0\ if \2 * a = 0\ and \a \ 2 ^ (LENGTH('a) - Suc 0)\ - using that by transfer - (auto simp add: take_bit_eq_0_iff take_bit_eq_mod *) - moreover have \2 ^ LENGTH('a) = (0 :: 'a word)\ - by transfer simp - then have \2 * 2 ^ (LENGTH('a) - Suc 0) = (0 :: 'a word)\ - by (simp add: *) - ultimately show ?thesis - by auto -qed - - -subsection \Ordering\ +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) + + +subsubsection \Basic ordering\ instantiation word :: (len) linorder begin @@ -728,10 +260,6 @@ \a > 0 \ a \ 0\ for a :: \'a::len 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) @@ -740,14 +268,6 @@ \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 @@ -756,96 +276,59 @@ \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) - -lift_definition word_sle :: \'a::len word \ 'a word \ bool\ (\(_/ <=s _)\ [50, 51] 50) - is \\k l. signed_take_bit (LENGTH('a) - 1) k \ signed_take_bit (LENGTH('a) - 1) l\ - by (simp flip: signed_take_bit_decr_length_iff) - -lemma word_sle_eq [code]: - \a <=s b \ sint a \ sint b\ - by transfer simp - -lift_definition word_sless :: \'a::len word \ 'a word \ bool\ (\(_/ [50, 51] 50) - is \\k l. signed_take_bit (LENGTH('a) - 1) k < signed_take_bit (LENGTH('a) - 1) l\ - by (simp flip: signed_take_bit_decr_length_iff) - -lemma word_sless_eq: - \x x <=s y \ x \ y\ - by transfer (simp add: signed_take_bit_decr_length_iff less_le) - -lemma [code]: - \a sint a < sint b\ - by transfer simp - -lemma word_less_alt: "a < b \ uint a < uint b" - by (fact word_less_def) - -lemma signed_linorder: "class.linorder word_sle word_sless" - by (standard; transfer) (auto simp add: signed_take_bit_decr_length_iff) - -interpretation signed: linorder "word_sle" "word_sless" - by (rule signed_linorder) - -lemma word_zero_le [simp]: "0 \ y" - for y :: "'a::len word" - by transfer simp - -lemma word_m1_ge [simp] : "word_pred 0 \ y" (* FIXME: delete *) - by transfer (simp add: take_bit_minus_one_eq_mask mask_eq_exp_minus_1 bintr_lt2p) - -lemma word_n1_ge [simp]: "y \ -1" - for y :: "'a::len word" - by (fact word_order.extremum) - -lemmas word_not_simps [simp] = - word_zero_le [THEN leD] word_m1_ge [THEN leD] word_n1_ge [THEN leD] - -lemma word_gt_0: "0 < y \ 0 \ y" - for y :: "'a::len word" - by (simp add: less_le) - -lemmas word_gt_0_no [simp] = word_gt_0 [of "numeral y"] for y - -lemma word_sless_alt: "a sint a < sint b" - by (auto simp add: word_sle_eq word_sless_eq less_le) - -lemma word_le_nat_alt: "a \ b \ unat a \ unat b" - by transfer (simp add: nat_le_eq_zle) - -lemma word_less_nat_alt: "a < b \ unat a < unat b" - by transfer (auto simp add: less_le [of 0]) - -lemmas unat_mono = word_less_nat_alt [THEN iffD1] - -instance word :: (len) wellorder -proof - fix P :: "'a word \ bool" and a - assume *: "(\b. (\a. a < b \ P a) \ P b)" - have "wf (measure unat)" .. - moreover have "{(a, b :: ('a::len) word). a < b} \ measure unat" - by (auto simp add: word_less_nat_alt) - ultimately have "wf {(a, b :: ('a::len) word). a < b}" - by (rule wf_subset) - then show "P a" using * - by induction blast -qed - -lemma wi_less: - "(word_of_int n < (word_of_int m :: 'a::len word)) = - (n mod 2 ^ LENGTH('a) < m mod 2 ^ LENGTH('a))" - unfolding word_less_alt by (simp add: word_uint.eq_norm) - -lemma wi_le: - "(word_of_int n \ (word_of_int m :: 'a::len word)) = - (n mod 2 ^ LENGTH('a) \ m mod 2 ^ LENGTH('a))" - unfolding word_le_def by (simp add: word_uint.eq_norm) - subsection \Bit-wise operations\ +instantiation word :: (len) semiring_modulo +begin + +lift_definition divide_word :: \'a word \ 'a word \ 'a word\ + is \\a b. take_bit LENGTH('a) a div take_bit LENGTH('a) b\ + by simp + +lift_definition modulo_word :: \'a word \ 'a word \ 'a word\ + is \\a b. take_bit LENGTH('a) a mod take_bit LENGTH('a) b\ + by simp + +instance 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 + +end + +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 + 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)\ @@ -1126,6 +609,376 @@ \\ bit w LENGTH('a)\ for w :: \'a::len word\ by transfer simp + +subsection \Conversions including casts\ + +lemma uint_nonnegative: "0 \ uint w" + by transfer simp + +lemma uint_bounded: "uint w < 2 ^ LENGTH('a)" + for w :: "'a::len word" + by transfer (simp add: take_bit_eq_mod) + +lemma uint_idem: "uint w mod 2 ^ LENGTH('a) = uint w" + for w :: "'a::len word" + using uint_nonnegative uint_bounded by (rule mod_pos_pos_trivial) + +lemma word_uint_eqI: "uint a = uint b \ a = b" + by transfer simp + +lemma word_uint_eq_iff: "a = b \ uint a = uint b" + using word_uint_eqI by auto + +lemma Word_eq_word_of_int [code_post]: + \Word.Word = word_of_int\ + by rule (transfer, rule) + +lemma uint_word_of_int_eq [code]: + \uint (word_of_int k :: 'a::len word) = take_bit LENGTH('a) k\ + by transfer rule + +lemma uint_word_of_int: "uint (word_of_int k :: 'a::len word) = k mod 2 ^ LENGTH('a)" + by (simp add: uint_word_of_int_eq take_bit_eq_mod) + +lemma word_of_int_uint: "word_of_int (uint w) = w" + by transfer simp + +lemma word_div_def [code]: + "a div b = word_of_int (uint a div uint b)" + by transfer rule + +lemma word_mod_def [code]: + "a mod b = word_of_int (uint a mod uint b)" + by transfer rule + +lemma split_word_all: "(\x::'a::len word. PROP P x) \ (\x. PROP P (word_of_int x))" +proof + fix x :: "'a word" + assume "\x. PROP P (word_of_int x)" + then have "PROP P (word_of_int (uint x))" . + then show "PROP P x" by (simp add: word_of_int_uint) +qed + +lemma sint_uint [code]: + \sint w = signed_take_bit (LENGTH('a) - 1) (uint w)\ + for w :: \'a::len word\ + by (cases \LENGTH('a)\; transfer) (simp_all add: signed_take_bit_take_bit) + +lemma unat_eq_nat_uint [code]: + \unat w = nat (uint w)\ + by simp + +lift_definition ucast :: \'a::len word \ 'b::len word\ + is \take_bit LENGTH('a)\ + by simp + +lemma ucast_eq [code]: + \ucast w = word_of_int (uint w)\ + by transfer simp + +lift_definition scast :: \'a::len word \ 'b::len word\ + is \signed_take_bit (LENGTH('a) - 1)\ + by (simp flip: signed_take_bit_decr_length_iff) + +lemma scast_eq [code]: + \scast w = word_of_int (sint w)\ + by transfer simp + +lemma uint_0_eq [simp]: + \uint 0 = 0\ + by transfer simp + +lemma uint_1_eq [simp]: + \uint 1 = 1\ + by transfer simp + +lemma word_m1_wi: "- 1 = word_of_int (- 1)" + by transfer rule + +lemma uint_0_iff: "uint x = 0 \ x = 0" + by (simp add: word_uint_eq_iff) + +lemma unat_0_iff: "unat x = 0 \ x = 0" + by transfer (auto intro: antisym) + +lemma unat_0 [simp]: "unat 0 = 0" + by transfer simp + +lemma unat_gt_0: "0 < unat x \ x \ 0" + by (auto simp: unat_0_iff [symmetric]) + +lemma ucast_0 [simp]: "ucast 0 = 0" + by transfer simp + +lemma sint_0 [simp]: "sint 0 = 0" + by (simp add: sint_uint) + +lemma scast_0 [simp]: "scast 0 = 0" + by transfer simp + +lemma sint_n1 [simp] : "sint (- 1) = - 1" + by transfer simp + +lemma scast_n1 [simp]: "scast (- 1) = - 1" + by transfer simp + +lemma uint_1: "uint (1::'a::len word) = 1" + by (fact uint_1_eq) + +lemma unat_1 [simp]: "unat (1::'a::len word) = 1" + by transfer simp + +lemma ucast_1 [simp]: "ucast (1::'a::len word) = 1" + by transfer simp + +instantiation word :: (len) size +begin + +lift_definition size_word :: \'a word \ nat\ + is \\_. LENGTH('a)\ .. + +instance .. + +end + +lemma word_size [code]: + \size w = LENGTH('a)\ for w :: \'a::len word\ + by (fact size_word.rep_eq) + +lemma word_size_gt_0 [iff]: "0 < size w" + for w :: "'a::len word" + by (simp add: word_size) + +lemmas lens_gt_0 = word_size_gt_0 len_gt_0 + +lemma lens_not_0 [iff]: + \size w \ 0\ for w :: \'a::len word\ + by auto + +lift_definition source_size :: \('a::len word \ 'b) \ nat\ + is \\_. LENGTH('a)\ . + +lift_definition target_size :: \('a \ 'b::len word) \ nat\ + is \\_. LENGTH('b)\ .. + +lift_definition is_up :: \('a::len word \ 'b::len word) \ bool\ + is \\_. LENGTH('a) \ LENGTH('b)\ .. + +lift_definition is_down :: \('a::len word \ 'b::len word) \ bool\ + is \\_. LENGTH('a) \ LENGTH('b)\ .. + +lemma is_up_eq: + \is_up f \ source_size f \ target_size f\ + for f :: \'a::len word \ 'b::len word\ + by (simp add: source_size.rep_eq target_size.rep_eq is_up.rep_eq) + +lemma is_down_eq: + \is_down f \ target_size f \ source_size f\ + for f :: \'a::len word \ 'b::len word\ + by (simp add: source_size.rep_eq target_size.rep_eq is_down.rep_eq) + +lift_definition word_int_case :: \(int \ 'b) \ 'a::len word \ 'b\ + is \\f. f \ take_bit LENGTH('a)\ by simp + +lemma word_int_case_eq_uint [code]: + \word_int_case f w = f (uint w)\ + by transfer simp + +translations + "case x of XCONST of_int y \ b" \ "CONST word_int_case (\y. b) x" + "case x of (XCONST of_int :: 'a) y \ b" \ "CONST word_int_case (\y. b) x" + + +subsection \Arithmetic operations\ + +text \Legacy theorems:\ + +lemma word_add_def [code]: + "a + b = word_of_int (uint a + uint b)" + by transfer (simp add: take_bit_add) + +lemma word_sub_wi [code]: + "a - b = word_of_int (uint a - uint b)" + by transfer (simp add: take_bit_diff) + +lemma word_mult_def [code]: + "a * b = word_of_int (uint a * uint b)" + by transfer (simp add: take_bit_eq_mod mod_simps) + +lemma word_minus_def [code]: + "- a = word_of_int (- uint a)" + by transfer (simp add: take_bit_minus) + +lemma word_0_wi: + "0 = word_of_int 0" + by transfer simp + +lemma word_1_wi: + "1 = word_of_int 1" + by transfer simp + +lift_definition word_succ :: "'a::len word \ 'a word" is "\x. x + 1" + by (auto simp add: take_bit_eq_mod intro: mod_add_cong) + +lift_definition word_pred :: "'a::len word \ 'a word" is "\x. x - 1" + by (auto simp add: take_bit_eq_mod intro: mod_diff_cong) + +lemma word_succ_alt [code]: + "word_succ a = word_of_int (uint a + 1)" + by transfer (simp add: take_bit_eq_mod mod_simps) + +lemma word_pred_alt [code]: + "word_pred a = word_of_int (uint a - 1)" + by transfer (simp add: take_bit_eq_mod mod_simps) + +lemmas word_arith_wis = + word_add_def word_sub_wi word_mult_def + word_minus_def word_succ_alt word_pred_alt + word_0_wi word_1_wi + +lemma wi_homs: + shows wi_hom_add: "word_of_int a + word_of_int b = word_of_int (a + b)" + and wi_hom_sub: "word_of_int a - word_of_int b = word_of_int (a - b)" + and wi_hom_mult: "word_of_int a * word_of_int b = word_of_int (a * b)" + and wi_hom_neg: "- word_of_int a = word_of_int (- a)" + and wi_hom_succ: "word_succ (word_of_int a) = word_of_int (a + 1)" + and wi_hom_pred: "word_pred (word_of_int a) = word_of_int (a - 1)" + by (transfer, simp)+ + +lemmas wi_hom_syms = wi_homs [symmetric] + +lemmas word_of_int_homs = wi_homs word_0_wi word_1_wi + +lemmas word_of_int_hom_syms = word_of_int_homs [symmetric] + +lemma word_of_nat: "of_nat n = word_of_int (int n)" + by (induct n) (auto simp add : word_of_int_hom_syms) + +lemma word_of_int: "of_int = word_of_int" + apply (rule ext) + apply (case_tac x rule: int_diff_cases) + apply (simp add: word_of_nat wi_hom_sub) + done + +lemma word_of_int_eq: + "word_of_int = of_int" + by (rule ext) (transfer, rule) + +definition udvd :: "'a::len word \ 'a::len word \ bool" (infixl "udvd" 50) + where "a udvd b = (\n\0. uint b = n * uint a)" + +lemma exp_eq_zero_iff: + \2 ^ n = (0 :: 'a::len word) \ n \ LENGTH('a)\ + by transfer simp + +lemma double_eq_zero_iff: + \2 * a = 0 \ a = 0 \ a = 2 ^ (LENGTH('a) - Suc 0)\ + for a :: \'a::len word\ +proof - + define n where \n = LENGTH('a) - Suc 0\ + then have *: \LENGTH('a) = Suc n\ + by simp + have \a = 0\ if \2 * a = 0\ and \a \ 2 ^ (LENGTH('a) - Suc 0)\ + using that by transfer + (auto simp add: take_bit_eq_0_iff take_bit_eq_mod *) + moreover have \2 ^ LENGTH('a) = (0 :: 'a word)\ + by transfer simp + then have \2 * 2 ^ (LENGTH('a) - Suc 0) = (0 :: 'a word)\ + by (simp add: *) + ultimately show ?thesis + by auto +qed + + +subsection \Ordering\ + +lift_definition word_sle :: \'a::len word \ 'a word \ bool\ (\(_/ <=s _)\ [50, 51] 50) + is \\k l. signed_take_bit (LENGTH('a) - 1) k \ signed_take_bit (LENGTH('a) - 1) l\ + by (simp flip: signed_take_bit_decr_length_iff) + +lemma word_sle_eq [code]: + \a <=s b \ sint a \ sint b\ + by transfer simp + +lift_definition word_sless :: \'a::len word \ 'a word \ bool\ (\(_/ [50, 51] 50) + is \\k l. signed_take_bit (LENGTH('a) - 1) k < signed_take_bit (LENGTH('a) - 1) l\ + by (simp flip: signed_take_bit_decr_length_iff) + +lemma word_sless_eq: + \x x <=s y \ x \ y\ + by transfer (simp add: signed_take_bit_decr_length_iff less_le) + +lemma [code]: + \a sint a < sint b\ + by transfer simp + +lemma word_less_alt: "a < b \ uint a < uint b" + by (fact word_less_def) + +lemma signed_linorder: "class.linorder word_sle word_sless" + by (standard; transfer) (auto simp add: signed_take_bit_decr_length_iff) + +interpretation signed: linorder "word_sle" "word_sless" + by (rule signed_linorder) + +lemma word_zero_le [simp]: "0 \ y" + for y :: "'a::len word" + by transfer simp + +lemma word_m1_ge [simp] : "word_pred 0 \ y" (* FIXME: delete *) + by transfer (simp add: take_bit_minus_one_eq_mask mask_eq_exp_minus_1 bintr_lt2p) + +lemma word_n1_ge [simp]: "y \ -1" + for y :: "'a::len word" + by (fact word_order.extremum) + +lemmas word_not_simps [simp] = + word_zero_le [THEN leD] word_m1_ge [THEN leD] word_n1_ge [THEN leD] + +lemma word_gt_0: "0 < y \ 0 \ y" + for y :: "'a::len word" + by (simp add: less_le) + +lemmas word_gt_0_no [simp] = word_gt_0 [of "numeral y"] for y + +lemma word_sless_alt: "a sint a < sint b" + by transfer simp + +lemma word_le_nat_alt: "a \ b \ unat a \ unat b" + by transfer (simp add: nat_le_eq_zle) + +lemma word_less_nat_alt: "a < b \ unat a < unat b" + by transfer (auto simp add: less_le [of 0]) + +lemmas unat_mono = word_less_nat_alt [THEN iffD1] + +instance word :: (len) wellorder +proof + fix P :: "'a word \ bool" and a + assume *: "(\b. (\a. a < b \ P a) \ P b)" + have "wf (measure unat)" .. + moreover have "{(a, b :: ('a::len) word). a < b} \ measure unat" + by (auto simp add: word_less_nat_alt) + ultimately have "wf {(a, b :: ('a::len) word). a < b}" + by (rule wf_subset) + then show "P a" using * + by induction blast +qed + +lemma wi_less: + "(word_of_int n < (word_of_int m :: 'a::len word)) = + (n mod 2 ^ LENGTH('a) < m mod 2 ^ LENGTH('a))" + by transfer (simp add: take_bit_eq_mod) + +lemma wi_le: + "(word_of_int n \ (word_of_int m :: 'a::len word)) = + (n mod 2 ^ LENGTH('a) \ m mod 2 ^ LENGTH('a))" + by transfer (simp add: take_bit_eq_mod) + + +subsection \Bit-wise operations\ + + lemma uint_take_bit_eq [code]: \uint (take_bit n w) = take_bit n (uint w)\ by transfer (simp add: ac_simps) @@ -1475,6 +1328,147 @@ qed +subsection \Type-definition locale instantiations\ + +definition uints :: "nat \ int set" + \ \the sets of integers representing the words\ + where "uints n = range (take_bit n)" + +definition sints :: "nat \ int set" + where "sints n = range (signed_take_bit (n - 1))" + +lemma uints_num: "uints n = {i. 0 \ i \ i < 2 ^ n}" + by (simp add: uints_def range_bintrunc) + +lemma sints_num: "sints n = {i. - (2 ^ (n - 1)) \ i \ i < 2 ^ (n - 1)}" + by (simp add: sints_def range_sbintrunc) + +definition unats :: "nat \ nat set" + where "unats n = {i. i < 2 ^ n}" + +\ \naturals\ +lemma uints_unats: "uints n = int ` unats n" + apply (unfold unats_def uints_num) + apply safe + apply (rule_tac image_eqI) + apply (erule_tac nat_0_le [symmetric]) + by auto + +lemma unats_uints: "unats n = nat ` uints n" + by (auto simp: uints_unats image_iff) + +lemma td_ext_uint: + "td_ext (uint :: 'a word \ int) word_of_int (uints (LENGTH('a::len))) + (\w::int. w mod 2 ^ LENGTH('a))" + apply (unfold td_ext_def') + apply transfer + apply (simp add: uints_num take_bit_eq_mod) + done + +interpretation word_uint: + td_ext + "uint::'a::len word \ int" + word_of_int + "uints (LENGTH('a::len))" + "\w. w mod 2 ^ LENGTH('a::len)" + by (fact td_ext_uint) + +lemmas td_uint = word_uint.td_thm +lemmas int_word_uint = word_uint.eq_norm + +lemma td_ext_ubin: + "td_ext (uint :: 'a word \ int) word_of_int (uints (LENGTH('a::len))) + (take_bit (LENGTH('a)))" + apply standard + apply transfer + apply simp + done + +interpretation word_ubin: + td_ext + "uint::'a::len word \ int" + word_of_int + "uints (LENGTH('a::len))" + "take_bit (LENGTH('a::len))" + by (fact td_ext_ubin) + +lemma td_ext_unat [OF refl]: + "n = LENGTH('a::len) \ + td_ext (unat :: 'a word \ nat) of_nat (unats n) (\i. i mod 2 ^ n)" + apply (standard; transfer) + apply (simp_all add: unats_def take_bit_int_less_exp take_bit_of_nat take_bit_eq_self) + apply (simp add: take_bit_eq_mod) + done + +lemmas unat_of_nat = td_ext_unat [THEN td_ext.eq_norm] + +interpretation word_unat: + td_ext + "unat::'a::len word \ nat" + of_nat + "unats (LENGTH('a::len))" + "\i. i mod 2 ^ LENGTH('a::len)" + by (rule td_ext_unat) + +lemmas td_unat = word_unat.td_thm + +lemmas unat_lt2p [iff] = word_unat.Rep [unfolded unats_def mem_Collect_eq] + +lemma unat_le: "y \ unat z \ y \ unats (LENGTH('a))" + for z :: "'a::len word" + apply (unfold unats_def) + apply clarsimp + apply (rule xtrans, rule unat_lt2p, assumption) + done + +lemma td_ext_sbin: + "td_ext (sint :: 'a word \ int) word_of_int (sints (LENGTH('a::len))) + (signed_take_bit (LENGTH('a) - 1))" + apply (unfold td_ext_def' sint_uint) + apply (simp add : word_ubin.eq_norm) + apply (cases "LENGTH('a)") + apply (auto simp add : sints_def) + apply (rule sym [THEN trans]) + apply (rule word_ubin.Abs_norm) + apply (simp only: bintrunc_sbintrunc) + apply (drule sym) + apply simp + done + +lemma td_ext_sint: + "td_ext (sint :: 'a word \ int) word_of_int (sints (LENGTH('a::len))) + (\w. (w + 2 ^ (LENGTH('a) - 1)) mod 2 ^ LENGTH('a) - + 2 ^ (LENGTH('a) - 1))" + using td_ext_sbin [where ?'a = 'a] by (simp add: no_sbintr_alt2) + +text \ + We do \sint\ before \sbin\, before \sint\ is the user version + and interpretations do not produce thm duplicates. I.e. + we get the name \word_sint.Rep_eqD\, but not \word_sbin.Req_eqD\, + because the latter is the same thm as the former. +\ +interpretation word_sint: + td_ext + "sint ::'a::len word \ int" + word_of_int + "sints (LENGTH('a::len))" + "\w. (w + 2^(LENGTH('a::len) - 1)) mod 2^LENGTH('a::len) - + 2 ^ (LENGTH('a::len) - 1)" + by (rule td_ext_sint) + +interpretation word_sbin: + td_ext + "sint ::'a::len word \ int" + word_of_int + "sints (LENGTH('a::len))" + "signed_take_bit (LENGTH('a::len) - 1)" + by (rule td_ext_sbin) + +lemmas int_word_sint = td_ext_sint [THEN td_ext.eq_norm] + +lemmas td_sint = word_sint.td + + subsection \More shift operations\ lift_definition sshiftr1 :: \'a::len word \ 'a word\