# HG changeset patch # User haftmann # Date 1627998802 0 # Node ID 3146646a43a7961d74854a8bb98981f41faa572f # Parent 2ab5dacdb1f64513cc1ef218bf61f1b5dfa4d55f simplified hierarchy of type classes for bit operations diff -r 2ab5dacdb1f6 -r 3146646a43a7 src/HOL/Bit_Operations.thy --- a/src/HOL/Bit_Operations.thy Tue Aug 03 13:53:22 2021 +0000 +++ b/src/HOL/Bit_Operations.thy Tue Aug 03 13:53:22 2021 +0000 @@ -610,27 +610,154 @@ end -class semiring_bit_shifts = semiring_bits + - fixes push_bit :: \nat \ 'a \ 'a\ - assumes push_bit_eq_mult: \push_bit n a = a * 2 ^ n\ - fixes drop_bit :: \nat \ 'a \ 'a\ - assumes drop_bit_eq_div: \drop_bit n a = a div 2 ^ n\ - fixes take_bit :: \nat \ 'a \ 'a\ - assumes take_bit_eq_mod: \take_bit n a = a mod 2 ^ n\ +lemma bit_not_int_iff': + \bit (- k - 1) n \ \ bit k n\ + for k :: int +proof (induction n arbitrary: k) + case 0 + show ?case + by simp +next + case (Suc n) + have \- k - 1 = - (k + 2) + 1\ + by simp + also have \(- (k + 2) + 1) div 2 = - (k div 2) - 1\ + proof (cases \even k\) + case True + then have \- k div 2 = - (k div 2)\ + by rule (simp flip: mult_minus_right) + with True show ?thesis + by simp + next + case False + have \4 = 2 * (2::int)\ + by simp + also have \2 * 2 div 2 = (2::int)\ + by (simp only: nonzero_mult_div_cancel_left) + finally have *: \4 div 2 = (2::int)\ . + from False obtain l where k: \k = 2 * l + 1\ .. + then have \- k - 2 = 2 * - (l + 2) + 1\ + by simp + then have \(- k - 2) div 2 + 1 = - (k div 2) - 1\ + by (simp flip: mult_minus_right add: *) (simp add: k) + with False show ?thesis + by simp + qed + finally have \(- k - 1) div 2 = - (k div 2) - 1\ . + with Suc show ?case + by (simp add: bit_Suc) +qed + +lemma bit_nat_iff [bit_simps]: + \bit (nat k) n \ k \ 0 \ bit k n\ +proof (cases \k \ 0\) + case True + moreover define m where \m = nat k\ + ultimately have \k = int m\ + by simp + then show ?thesis + by (simp add: bit_simps) +next + case False + then show ?thesis + by simp +qed + + +subsection \Bit operations\ + +class semiring_bit_operations = semiring_bits + + fixes "and" :: \'a \ 'a \ 'a\ (infixr \AND\ 64) + and or :: \'a \ 'a \ 'a\ (infixr \OR\ 59) + and xor :: \'a \ 'a \ 'a\ (infixr \XOR\ 59) + and mask :: \nat \ 'a\ + and set_bit :: \nat \ 'a \ 'a\ + and unset_bit :: \nat \ 'a \ 'a\ + and flip_bit :: \nat \ 'a \ 'a\ + and push_bit :: \nat \ 'a \ 'a\ + and drop_bit :: \nat \ 'a \ 'a\ + and take_bit :: \nat \ 'a \ 'a\ + assumes bit_and_iff [bit_simps]: \bit (a AND b) n \ bit a n \ bit b n\ + and bit_or_iff [bit_simps]: \bit (a OR b) n \ bit a n \ bit b n\ + and bit_xor_iff [bit_simps]: \bit (a XOR b) n \ bit a n \ bit b n\ + and mask_eq_exp_minus_1: \mask n = 2 ^ n - 1\ + and set_bit_eq_or: \set_bit n a = a OR push_bit n 1\ + and bit_unset_bit_iff [bit_simps]: \bit (unset_bit m a) n \ bit a n \ m \ n\ + and flip_bit_eq_xor: \flip_bit n a = a XOR push_bit n 1\ + and push_bit_eq_mult: \push_bit n a = a * 2 ^ n\ + and drop_bit_eq_div: \drop_bit n a = a div 2 ^ n\ + and take_bit_eq_mod: \take_bit n a = a mod 2 ^ n\ begin text \ + We want the bitwise operations to bind slightly weaker + than \+\ and \-\. + Logically, \<^const>\push_bit\, \<^const>\drop_bit\ and \<^const>\take_bit\ are just aliases; having them as separate operations makes proofs easier, otherwise proof automation would fiddle with concrete expressions \<^term>\2 ^ n\ in a way obfuscating the basic algebraic relationships between those operations. - Having - them as definitional class operations - takes into account that specific instances of these can be implemented + + For the sake of code generation operations + are specified as definitional class operations, + taking into account that specific instances of these can be implemented differently wrt. code generation. \ +sublocale "and": semilattice \(AND)\ + by standard (auto simp add: bit_eq_iff bit_and_iff) + +sublocale or: semilattice_neutr \(OR)\ 0 + by standard (auto simp add: bit_eq_iff bit_or_iff) + +sublocale xor: comm_monoid \(XOR)\ 0 + by standard (auto simp add: bit_eq_iff bit_xor_iff) + +lemma even_and_iff: + \even (a AND b) \ even a \ even b\ + using bit_and_iff [of a b 0] by auto + +lemma even_or_iff: + \even (a OR b) \ even a \ even b\ + using bit_or_iff [of a b 0] by auto + +lemma even_xor_iff: + \even (a XOR b) \ (even a \ even b)\ + using bit_xor_iff [of a b 0] by auto + +lemma zero_and_eq [simp]: + \0 AND a = 0\ + by (simp add: bit_eq_iff bit_and_iff) + +lemma and_zero_eq [simp]: + \a AND 0 = 0\ + by (simp add: bit_eq_iff bit_and_iff) + +lemma one_and_eq: + \1 AND a = a mod 2\ + by (simp add: bit_eq_iff bit_and_iff) (auto simp add: bit_1_iff) + +lemma and_one_eq: + \a AND 1 = a mod 2\ + using one_and_eq [of a] by (simp add: ac_simps) + +lemma one_or_eq: + \1 OR a = a + of_bool (even a)\ + by (simp add: bit_eq_iff bit_or_iff add.commute [of _ 1] even_bit_succ_iff) (auto simp add: bit_1_iff) + +lemma or_one_eq: + \a OR 1 = a + of_bool (even a)\ + using one_or_eq [of a] by (simp add: ac_simps) + +lemma one_xor_eq: + \1 XOR a = a + of_bool (even a) - of_bool (odd a)\ + by (simp add: bit_eq_iff bit_xor_iff add.commute [of _ 1] even_bit_succ_iff) (auto simp add: bit_1_iff odd_bit_iff_bit_pred elim: oddE) + +lemma xor_one_eq: + \a XOR 1 = a + of_bool (even a) - of_bool (odd a)\ + using one_xor_eq [of a] by (simp add: ac_simps) + lemma bit_iff_odd_drop_bit: \bit a n \ odd (drop_bit n a)\ by (simp add: bit_iff_odd drop_bit_eq_div) @@ -893,558 +1020,6 @@ \drop_bit m (2 ^ n) = of_bool (m \ n \ 2 ^ n \ 0) * 2 ^ (n - m)\ by (rule bit_eqI) (auto simp add: bit_simps) -end - -instantiation nat :: semiring_bit_shifts -begin - -definition push_bit_nat :: \nat \ nat \ nat\ - where \push_bit_nat n m = m * 2 ^ n\ - -definition drop_bit_nat :: \nat \ nat \ nat\ - where \drop_bit_nat n m = m div 2 ^ n\ - -definition take_bit_nat :: \nat \ nat \ nat\ - where \take_bit_nat n m = m mod 2 ^ n\ - -instance - by standard (simp_all add: push_bit_nat_def drop_bit_nat_def take_bit_nat_def) - -end - -context semiring_bit_shifts -begin - -lemma push_bit_of_nat: - \push_bit n (of_nat m) = of_nat (push_bit n m)\ - by (simp add: push_bit_eq_mult semiring_bit_shifts_class.push_bit_eq_mult) - -lemma of_nat_push_bit: - \of_nat (push_bit m n) = push_bit m (of_nat n)\ - by (simp add: push_bit_eq_mult semiring_bit_shifts_class.push_bit_eq_mult) - -lemma take_bit_of_nat: - \take_bit n (of_nat m) = of_nat (take_bit n m)\ - by (rule bit_eqI) (simp add: bit_take_bit_iff Bit_Operations.bit_take_bit_iff bit_of_nat_iff) - -lemma of_nat_take_bit: - \of_nat (take_bit n m) = take_bit n (of_nat m)\ - by (rule bit_eqI) (simp add: bit_take_bit_iff Bit_Operations.bit_take_bit_iff bit_of_nat_iff) - -end - -instantiation int :: semiring_bit_shifts -begin - -definition push_bit_int :: \nat \ int \ int\ - where \push_bit_int n k = k * 2 ^ n\ - -definition drop_bit_int :: \nat \ int \ int\ - where \drop_bit_int n k = k div 2 ^ n\ - -definition take_bit_int :: \nat \ int \ int\ - where \take_bit_int n k = k mod 2 ^ n\ - -instance - by standard (simp_all add: push_bit_int_def drop_bit_int_def take_bit_int_def) - -end - -lemma bit_push_bit_iff_nat: - \bit (push_bit m q) n \ m \ n \ bit q (n - m)\ for q :: nat - by (auto simp add: bit_push_bit_iff) - -lemma bit_push_bit_iff_int: - \bit (push_bit m k) n \ m \ n \ bit k (n - m)\ for k :: int - by (auto simp add: bit_push_bit_iff) - -lemma take_bit_nat_less_exp [simp]: - \take_bit n m < 2 ^ n\ for n m ::nat - by (simp add: take_bit_eq_mod) - -lemma take_bit_nonnegative [simp]: - \take_bit n k \ 0\ for k :: int - by (simp add: take_bit_eq_mod) - -lemma not_take_bit_negative [simp]: - \\ take_bit n k < 0\ for k :: int - by (simp add: not_less) - -lemma take_bit_int_less_exp [simp]: - \take_bit n k < 2 ^ n\ for k :: int - by (simp add: take_bit_eq_mod) - -lemma take_bit_nat_eq_self_iff: - \take_bit n m = m \ m < 2 ^ n\ (is \?P \ ?Q\) - for n m :: nat -proof - assume ?P - moreover note take_bit_nat_less_exp [of n m] - ultimately show ?Q - by simp -next - assume ?Q - then show ?P - by (simp add: take_bit_eq_mod) -qed - -lemma take_bit_nat_eq_self: - \take_bit n m = m\ if \m < 2 ^ n\ for m n :: nat - using that by (simp add: take_bit_nat_eq_self_iff) - -lemma take_bit_int_eq_self_iff: - \take_bit n k = k \ 0 \ k \ k < 2 ^ n\ (is \?P \ ?Q\) - for k :: int -proof - assume ?P - moreover note take_bit_int_less_exp [of n k] take_bit_nonnegative [of n k] - ultimately show ?Q - by simp -next - assume ?Q - then show ?P - by (simp add: take_bit_eq_mod) -qed - -lemma take_bit_int_eq_self: - \take_bit n k = k\ if \0 \ k\ \k < 2 ^ n\ for k :: int - using that by (simp add: take_bit_int_eq_self_iff) - -lemma take_bit_nat_less_eq_self [simp]: - \take_bit n m \ m\ for n m :: nat - by (simp add: take_bit_eq_mod) - -lemma take_bit_nat_less_self_iff: - \take_bit n m < m \ 2 ^ n \ m\ (is \?P \ ?Q\) - for m n :: nat -proof - assume ?P - then have \take_bit n m \ m\ - by simp - then show \?Q\ - by (simp add: take_bit_nat_eq_self_iff) -next - have \take_bit n m < 2 ^ n\ - by (fact take_bit_nat_less_exp) - also assume ?Q - finally show ?P . -qed - -class unique_euclidean_semiring_with_bit_shifts = - unique_euclidean_semiring_with_nat + semiring_bit_shifts -begin - -lemma take_bit_of_exp [simp]: - \take_bit m (2 ^ n) = of_bool (n < m) * 2 ^ n\ - by (simp add: take_bit_eq_mod exp_mod_exp) - -lemma take_bit_of_2 [simp]: - \take_bit n 2 = of_bool (2 \ n) * 2\ - using take_bit_of_exp [of n 1] by simp - -lemma take_bit_of_mask: - \take_bit m (2 ^ n - 1) = 2 ^ min m n - 1\ - by (simp add: take_bit_eq_mod mask_mod_exp) - -lemma push_bit_eq_0_iff [simp]: - "push_bit n a = 0 \ a = 0" - by (simp add: push_bit_eq_mult) - -lemma take_bit_add: - "take_bit n (take_bit n a + take_bit n b) = take_bit n (a + b)" - by (simp add: take_bit_eq_mod mod_simps) - -lemma take_bit_of_1_eq_0_iff [simp]: - "take_bit n 1 = 0 \ n = 0" - by (simp add: take_bit_eq_mod) - -lemma take_bit_Suc_1 [simp]: - \take_bit (Suc n) 1 = 1\ - by (simp add: take_bit_Suc) - -lemma take_bit_Suc_bit0 [simp]: - \take_bit (Suc n) (numeral (Num.Bit0 k)) = take_bit n (numeral k) * 2\ - by (simp add: take_bit_Suc numeral_Bit0_div_2) - -lemma take_bit_Suc_bit1 [simp]: - \take_bit (Suc n) (numeral (Num.Bit1 k)) = take_bit n (numeral k) * 2 + 1\ - by (simp add: take_bit_Suc numeral_Bit1_div_2 mod_2_eq_odd) - -lemma take_bit_numeral_1 [simp]: - \take_bit (numeral l) 1 = 1\ - by (simp add: take_bit_rec [of \numeral l\ 1]) - -lemma take_bit_numeral_bit0 [simp]: - \take_bit (numeral l) (numeral (Num.Bit0 k)) = take_bit (pred_numeral l) (numeral k) * 2\ - by (simp add: take_bit_rec numeral_Bit0_div_2) - -lemma take_bit_numeral_bit1 [simp]: - \take_bit (numeral l) (numeral (Num.Bit1 k)) = take_bit (pred_numeral l) (numeral k) * 2 + 1\ - by (simp add: take_bit_rec numeral_Bit1_div_2 mod_2_eq_odd) - -lemma drop_bit_Suc_bit0 [simp]: - \drop_bit (Suc n) (numeral (Num.Bit0 k)) = drop_bit n (numeral k)\ - by (simp add: drop_bit_Suc numeral_Bit0_div_2) - -lemma drop_bit_Suc_bit1 [simp]: - \drop_bit (Suc n) (numeral (Num.Bit1 k)) = drop_bit n (numeral k)\ - by (simp add: drop_bit_Suc numeral_Bit1_div_2) - -lemma drop_bit_numeral_bit0 [simp]: - \drop_bit (numeral l) (numeral (Num.Bit0 k)) = drop_bit (pred_numeral l) (numeral k)\ - by (simp add: drop_bit_rec numeral_Bit0_div_2) - -lemma drop_bit_numeral_bit1 [simp]: - \drop_bit (numeral l) (numeral (Num.Bit1 k)) = drop_bit (pred_numeral l) (numeral k)\ - by (simp add: drop_bit_rec numeral_Bit1_div_2) - -lemma drop_bit_of_nat: - "drop_bit n (of_nat m) = of_nat (drop_bit n m)" - by (simp add: drop_bit_eq_div Bit_Operations.drop_bit_eq_div of_nat_div [of m "2 ^ n"]) - -lemma bit_of_nat_iff_bit [bit_simps]: - \bit (of_nat m) n \ bit m n\ -proof - - have \even (m div 2 ^ n) \ even (of_nat (m div 2 ^ n))\ - by simp - also have \of_nat (m div 2 ^ n) = of_nat m div of_nat (2 ^ n)\ - by (simp add: of_nat_div) - finally show ?thesis - by (simp add: bit_iff_odd semiring_bits_class.bit_iff_odd) -qed - -lemma of_nat_drop_bit: - \of_nat (drop_bit m n) = drop_bit m (of_nat n)\ - by (simp add: drop_bit_eq_div semiring_bit_shifts_class.drop_bit_eq_div of_nat_div) - -lemma bit_push_bit_iff_of_nat_iff [bit_simps]: - \bit (push_bit m (of_nat r)) n \ m \ n \ bit (of_nat r) (n - m)\ - by (auto simp add: bit_push_bit_iff) - -lemma take_bit_sum: - "take_bit n a = (\k = 0..k = 0..k = Suc 0..k = Suc 0..k = 0..bit (numeral m :: int) n \ bit (numeral m :: nat) n\ - using bit_of_nat_iff_bit [of \numeral m\ n] by simp - -lemma bit_not_int_iff': - \bit (- k - 1) n \ \ bit k n\ - for k :: int -proof (induction n arbitrary: k) - case 0 - show ?case - by simp -next - case (Suc n) - have \- k - 1 = - (k + 2) + 1\ - by simp - also have \(- (k + 2) + 1) div 2 = - (k div 2) - 1\ - proof (cases \even k\) - case True - then have \- k div 2 = - (k div 2)\ - by rule (simp flip: mult_minus_right) - with True show ?thesis - by simp - next - case False - have \4 = 2 * (2::int)\ - by simp - also have \2 * 2 div 2 = (2::int)\ - by (simp only: nonzero_mult_div_cancel_left) - finally have *: \4 div 2 = (2::int)\ . - from False obtain l where k: \k = 2 * l + 1\ .. - then have \- k - 2 = 2 * - (l + 2) + 1\ - by simp - then have \(- k - 2) div 2 + 1 = - (k div 2) - 1\ - by (simp flip: mult_minus_right add: *) (simp add: k) - with False show ?thesis - by simp - qed - finally have \(- k - 1) div 2 = - (k div 2) - 1\ . - with Suc show ?case - by (simp add: bit_Suc) -qed - -lemma bit_minus_int_iff [bit_simps]: - \bit (- k) n \ \ bit (k - 1) n\ - for k :: int - using bit_not_int_iff' [of \k - 1\] by simp - -lemma bit_nat_iff [bit_simps]: - \bit (nat k) n \ k \ 0 \ bit k n\ -proof (cases \k \ 0\) - case True - moreover define m where \m = nat k\ - ultimately have \k = int m\ - by simp - then show ?thesis - by (simp add: bit_simps) -next - case False - then show ?thesis - by simp -qed - -lemma bit_numeral_int_simps [simp]: - \bit (1 :: int) (numeral n) \ bit (0 :: int) (pred_numeral n)\ - \bit (numeral (num.Bit0 w) :: int) (numeral n) \ bit (numeral w :: int) (pred_numeral n)\ - \bit (numeral (num.Bit1 w) :: int) (numeral n) \ bit (numeral w :: int) (pred_numeral n)\ - \bit (numeral (Num.BitM w) :: int) (numeral n) \ \ bit (- numeral w :: int) (pred_numeral n)\ - \bit (- numeral (num.Bit0 w) :: int) (numeral n) \ bit (- numeral w :: int) (pred_numeral n)\ - \bit (- numeral (num.Bit1 w) :: int) (numeral n) \ \ bit (numeral w :: int) (pred_numeral n)\ - \bit (- numeral (Num.BitM w) :: int) (numeral n) \ bit (- (numeral w) :: int) (pred_numeral n)\ - by (simp_all add: bit_1_iff numeral_eq_Suc bit_Suc add_One sub_inc_One_eq bit_minus_int_iff) - -lemma bit_numeral_Bit0_Suc_iff [simp]: - \bit (numeral (Num.Bit0 m) :: int) (Suc n) \ bit (numeral m :: int) n\ - by (simp add: bit_Suc) - -lemma bit_numeral_Bit1_Suc_iff [simp]: - \bit (numeral (Num.Bit1 m) :: int) (Suc n) \ bit (numeral m :: int) n\ - by (simp add: bit_Suc) - -lemma push_bit_nat_eq: - \push_bit n (nat k) = nat (push_bit n k)\ - by (cases \k \ 0\) (simp_all add: push_bit_eq_mult nat_mult_distrib not_le mult_nonneg_nonpos2) - -lemma drop_bit_nat_eq: - \drop_bit n (nat k) = nat (drop_bit n k)\ - apply (cases \k \ 0\) - apply (simp_all add: drop_bit_eq_div nat_div_distrib nat_power_eq not_le) - apply (simp add: divide_int_def) - done - -lemma take_bit_nat_eq: - \take_bit n (nat k) = nat (take_bit n k)\ if \k \ 0\ - using that by (simp add: take_bit_eq_mod nat_mod_distrib nat_power_eq) - -lemma nat_take_bit_eq: - \nat (take_bit n k) = take_bit n (nat k)\ - if \k \ 0\ - using that by (simp add: take_bit_eq_mod nat_mod_distrib nat_power_eq) - -lemma not_exp_less_eq_0_int [simp]: - \\ 2 ^ n \ (0::int)\ - by (simp add: power_le_zero_eq) - -lemma half_nonnegative_int_iff [simp]: - \k div 2 \ 0 \ k \ 0\ for k :: int -proof (cases \k \ 0\) - case True - then show ?thesis - by (auto simp add: divide_int_def sgn_1_pos) -next - case False - then show ?thesis - by (auto simp add: divide_int_def not_le elim!: evenE) -qed - -lemma half_negative_int_iff [simp]: - \k div 2 < 0 \ k < 0\ for k :: int - by (subst Not_eq_iff [symmetric]) (simp add: not_less) - -lemma push_bit_of_Suc_0 [simp]: - "push_bit n (Suc 0) = 2 ^ n" - using push_bit_of_1 [where ?'a = nat] by simp - -lemma take_bit_of_Suc_0 [simp]: - "take_bit n (Suc 0) = of_bool (0 < n)" - using take_bit_of_1 [where ?'a = nat] by simp - -lemma drop_bit_of_Suc_0 [simp]: - "drop_bit n (Suc 0) = of_bool (n = 0)" - using drop_bit_of_1 [where ?'a = nat] by simp - -lemma push_bit_minus_one: - "push_bit n (- 1 :: int) = - (2 ^ n)" - by (simp add: push_bit_eq_mult) - -lemma minus_1_div_exp_eq_int: - \- 1 div (2 :: int) ^ n = - 1\ - by (induction n) (use div_exp_eq [symmetric, of \- 1 :: int\ 1] in \simp_all add: ac_simps\) - -lemma drop_bit_minus_one [simp]: - \drop_bit n (- 1 :: int) = - 1\ - by (simp add: drop_bit_eq_div minus_1_div_exp_eq_int) - -lemma take_bit_Suc_from_most: - \take_bit (Suc n) k = 2 ^ n * of_bool (bit k n) + take_bit n k\ for k :: int - by (simp only: take_bit_eq_mod power_Suc2) (simp_all add: bit_iff_odd odd_iff_mod_2_eq_one zmod_zmult2_eq) - -lemma take_bit_minus: - \take_bit n (- take_bit n k) = take_bit n (- k)\ - for k :: int - by (simp add: take_bit_eq_mod mod_minus_eq) - -lemma take_bit_diff: - \take_bit n (take_bit n k - take_bit n l) = take_bit n (k - l)\ - for k l :: int - by (simp add: take_bit_eq_mod mod_diff_eq) - -lemma bit_imp_take_bit_positive: - \0 < take_bit m k\ if \n < m\ and \bit k n\ for k :: int -proof (rule ccontr) - assume \\ 0 < take_bit m k\ - then have \take_bit m k = 0\ - by (auto simp add: not_less intro: order_antisym) - then have \bit (take_bit m k) n = bit 0 n\ - by simp - with that show False - by (simp add: bit_take_bit_iff) -qed - -lemma take_bit_mult: - \take_bit n (take_bit n k * take_bit n l) = take_bit n (k * l)\ - for k l :: int - by (simp add: take_bit_eq_mod mod_mult_eq) - -lemma (in ring_1) of_nat_nat_take_bit_eq [simp]: - \of_nat (nat (take_bit n k)) = of_int (take_bit n k)\ - by simp - -lemma take_bit_minus_small_eq: - \take_bit n (- k) = 2 ^ n - k\ if \0 < k\ \k \ 2 ^ n\ for k :: int -proof - - define m where \m = nat k\ - with that have \k = int m\ and \0 < m\ and \m \ 2 ^ n\ - by simp_all - have \(2 ^ n - m) mod 2 ^ n = 2 ^ n - m\ - using \0 < m\ by simp - then have \int ((2 ^ n - m) mod 2 ^ n) = int (2 ^ n - m)\ - by simp - then have \(2 ^ n - int m) mod 2 ^ n = 2 ^ n - int m\ - using \m \ 2 ^ n\ by (simp only: of_nat_mod of_nat_diff) simp - with \k = int m\ have \(2 ^ n - k) mod 2 ^ n = 2 ^ n - k\ - by simp - then show ?thesis - by (simp add: take_bit_eq_mod) -qed - -lemma drop_bit_push_bit_int: - \drop_bit m (push_bit n k) = drop_bit (m - n) (push_bit (n - m) k)\ for k :: int - by (cases \m \ n\) (auto simp add: mult.left_commute [of _ \2 ^ n\] mult.commute [of _ \2 ^ n\] mult.assoc - mult.commute [of k] drop_bit_eq_div push_bit_eq_mult not_le power_add dest!: le_Suc_ex less_imp_Suc_add) - -lemma push_bit_nonnegative_int_iff [simp]: - \push_bit n k \ 0 \ k \ 0\ for k :: int - by (simp add: push_bit_eq_mult zero_le_mult_iff) - -lemma push_bit_negative_int_iff [simp]: - \push_bit n k < 0 \ k < 0\ for k :: int - by (subst Not_eq_iff [symmetric]) (simp add: not_less) - -lemma drop_bit_nonnegative_int_iff [simp]: - \drop_bit n k \ 0 \ k \ 0\ for k :: int - by (induction n) (simp_all add: drop_bit_Suc drop_bit_half) - -lemma drop_bit_negative_int_iff [simp]: - \drop_bit n k < 0 \ k < 0\ for k :: int - by (subst Not_eq_iff [symmetric]) (simp add: not_less) - - -subsection \Bit operations\ - -class semiring_bit_operations = semiring_bit_shifts + - fixes "and" :: \'a \ 'a \ 'a\ (infixr \AND\ 64) - and or :: \'a \ 'a \ 'a\ (infixr \OR\ 59) - and xor :: \'a \ 'a \ 'a\ (infixr \XOR\ 59) - and mask :: \nat \ 'a\ - and set_bit :: \nat \ 'a \ 'a\ - and unset_bit :: \nat \ 'a \ 'a\ - and flip_bit :: \nat \ 'a \ 'a\ - assumes bit_and_iff [bit_simps]: \bit (a AND b) n \ bit a n \ bit b n\ - and bit_or_iff [bit_simps]: \bit (a OR b) n \ bit a n \ bit b n\ - and bit_xor_iff [bit_simps]: \bit (a XOR b) n \ bit a n \ bit b n\ - and mask_eq_exp_minus_1: \mask n = 2 ^ n - 1\ - and set_bit_eq_or: \set_bit n a = a OR push_bit n 1\ - and bit_unset_bit_iff [bit_simps]: \bit (unset_bit m a) n \ bit a n \ m \ n\ - and flip_bit_eq_xor: \flip_bit n a = a XOR push_bit n 1\ -begin - -text \ - We want the bitwise operations to bind slightly weaker - than \+\ and \-\. - For the sake of code generation - the operations \<^const>\and\, \<^const>\or\ and \<^const>\xor\ - are specified as definitional class operations. -\ - -sublocale "and": semilattice \(AND)\ - by standard (auto simp add: bit_eq_iff bit_and_iff) - -sublocale or: semilattice_neutr \(OR)\ 0 - by standard (auto simp add: bit_eq_iff bit_or_iff) - -sublocale xor: comm_monoid \(XOR)\ 0 - by standard (auto simp add: bit_eq_iff bit_xor_iff) - -lemma even_and_iff: - \even (a AND b) \ even a \ even b\ - using bit_and_iff [of a b 0] by auto - -lemma even_or_iff: - \even (a OR b) \ even a \ even b\ - using bit_or_iff [of a b 0] by auto - -lemma even_xor_iff: - \even (a XOR b) \ (even a \ even b)\ - using bit_xor_iff [of a b 0] by auto - -lemma zero_and_eq [simp]: - \0 AND a = 0\ - by (simp add: bit_eq_iff bit_and_iff) - -lemma and_zero_eq [simp]: - \a AND 0 = 0\ - by (simp add: bit_eq_iff bit_and_iff) - -lemma one_and_eq: - \1 AND a = a mod 2\ - by (simp add: bit_eq_iff bit_and_iff) (auto simp add: bit_1_iff) - -lemma and_one_eq: - \a AND 1 = a mod 2\ - using one_and_eq [of a] by (simp add: ac_simps) - -lemma one_or_eq: - \1 OR a = a + of_bool (even a)\ - by (simp add: bit_eq_iff bit_or_iff add.commute [of _ 1] even_bit_succ_iff) (auto simp add: bit_1_iff) - -lemma or_one_eq: - \a OR 1 = a + of_bool (even a)\ - using one_or_eq [of a] by (simp add: ac_simps) - -lemma one_xor_eq: - \1 XOR a = a + of_bool (even a) - of_bool (odd a)\ - by (simp add: bit_eq_iff bit_xor_iff add.commute [of _ 1] even_bit_succ_iff) (auto simp add: bit_1_iff odd_bit_iff_bit_pred elim: oddE) - -lemma xor_one_eq: - \a XOR 1 = a + of_bool (even a) - of_bool (odd a)\ - using one_xor_eq [of a] by (simp add: ac_simps) - lemma take_bit_and [simp]: \take_bit n (a AND b) = take_bit n a AND take_bit n b\ by (auto simp add: bit_eq_iff bit_take_bit_iff bit_and_iff) @@ -1693,7 +1268,6 @@ \take_bit n (flip_bit m a) = (if n \ m then take_bit n a else flip_bit m (take_bit n a))\ by (rule bit_eqI) (auto simp add: bit_take_bit_iff bit_flip_bit_iff) - end class ring_bit_operations = semiring_bit_operations + ring_parity + @@ -1780,7 +1354,7 @@ \NOT (a - b) = NOT a + b\ using not_add_distrib [of a \- b\] by simp -lemma (in ring_bit_operations) and_eq_minus_1_iff: +lemma and_eq_minus_1_iff: \a AND b = - 1 \ a = - 1 \ b = - 1\ proof assume \a = - 1 \ b = - 1\ @@ -1875,79 +1449,6 @@ subsection \Instance \<^typ>\int\\ -lemma int_bit_bound: - fixes k :: int - obtains n where \\m. n \ m \ bit k m \ bit k n\ - and \n > 0 \ bit k (n - 1) \ bit k n\ -proof - - obtain q where *: \\m. q \ m \ bit k m \ bit k q\ - proof (cases \k \ 0\) - case True - moreover from power_gt_expt [of 2 \nat k\] - have \nat k < 2 ^ nat k\ - by simp - then have \int (nat k) < int (2 ^ nat k)\ - by (simp only: of_nat_less_iff) - ultimately have *: \k div 2 ^ nat k = 0\ - by simp - show thesis - proof (rule that [of \nat k\]) - fix m - assume \nat k \ m\ - then show \bit k m \ bit k (nat k)\ - by (auto simp add: * bit_iff_odd power_add zdiv_zmult2_eq dest!: le_Suc_ex) - qed - next - case False - moreover from power_gt_expt [of 2 \nat (- k)\] - have \nat (- k) < 2 ^ nat (- k)\ - by simp - then have \int (nat (- k)) < int (2 ^ nat (- k))\ - by (simp only: of_nat_less_iff) - ultimately have \- k div - (2 ^ nat (- k)) = - 1\ - by (subst div_pos_neg_trivial) simp_all - then have *: \k div 2 ^ nat (- k) = - 1\ - by simp - show thesis - proof (rule that [of \nat (- k)\]) - fix m - assume \nat (- k) \ m\ - then show \bit k m \ bit k (nat (- k))\ - by (auto simp add: * bit_iff_odd power_add zdiv_zmult2_eq minus_1_div_exp_eq_int dest!: le_Suc_ex) - qed - qed - show thesis - proof (cases \\m. bit k m \ bit k q\) - case True - then have \bit k 0 \ bit k q\ - by blast - with True that [of 0] show thesis - by simp - next - case False - then obtain r where **: \bit k r \ bit k q\ - by blast - have \r < q\ - by (rule ccontr) (use * [of r] ** in simp) - define N where \N = {n. n < q \ bit k n \ bit k q}\ - moreover have \finite N\ \r \ N\ - using ** N_def \r < q\ by auto - moreover define n where \n = Suc (Max N)\ - ultimately have \\m. n \ m \ bit k m \ bit k n\ - apply auto - apply (metis (full_types, lifting) "*" Max_ge_iff Suc_n_not_le_n \finite N\ all_not_in_conv mem_Collect_eq not_le) - apply (metis "*" Max_ge Suc_n_not_le_n \finite N\ linorder_not_less mem_Collect_eq) - apply (metis "*" Max_ge Suc_n_not_le_n \finite N\ linorder_not_less mem_Collect_eq) - apply (metis (full_types, lifting) "*" Max_ge_iff Suc_n_not_le_n \finite N\ all_not_in_conv mem_Collect_eq not_le) - done - have \bit k (Max N) \ bit k n\ - by (metis (mono_tags, lifting) "*" Max_in N_def \\m. n \ m \ bit k m = bit k n\ \finite N\ \r \ N\ empty_iff le_cases mem_Collect_eq) - show thesis apply (rule that [of n]) - using \\m. n \ m \ bit k m = bit k n\ apply blast - using \bit k (Max N) \ bit k n\ n_def by auto - qed -qed - instantiation int :: ring_bit_operations begin @@ -2083,6 +1584,15 @@ definition mask_int :: \nat \ int\ where \mask n = (2 :: int) ^ n - 1\ +definition push_bit_int :: \nat \ int \ int\ + where \push_bit_int n k = k * 2 ^ n\ + +definition drop_bit_int :: \nat \ int \ int\ + where \drop_bit_int n k = k div 2 ^ n\ + +definition take_bit_int :: \nat \ int \ int\ + where \take_bit_int n k = k mod 2 ^ n\ + definition set_bit_int :: \nat \ int \ int\ where \set_bit n k = k OR push_bit n 1\ for k :: int @@ -2108,12 +1618,48 @@ by (simp add: unset_bit_int_def) also have \NOT (push_bit m 1 :: int) = - (push_bit m 1 + 1)\ by (simp add: not_int_def) - finally show ?thesis by (simp only: bit_simps bit_and_int_iff) (auto simp add: bit_simps) + finally show ?thesis by (simp only: bit_simps bit_and_int_iff) + (auto simp add: bit_simps bit_not_int_iff' push_bit_int_def) qed -qed (simp_all add: bit_not_int_iff mask_int_def set_bit_int_def flip_bit_int_def) +qed (simp_all add: bit_not_int_iff mask_int_def set_bit_int_def flip_bit_int_def + push_bit_int_def drop_bit_int_def take_bit_int_def) end +lemma bit_push_bit_iff_int: + \bit (push_bit m k) n \ m \ n \ bit k (n - m)\ for k :: int + by (auto simp add: bit_push_bit_iff) + +lemma take_bit_nonnegative [simp]: + \take_bit n k \ 0\ for k :: int + by (simp add: take_bit_eq_mod) + +lemma not_take_bit_negative [simp]: + \\ take_bit n k < 0\ for k :: int + by (simp add: not_less) + +lemma take_bit_int_less_exp [simp]: + \take_bit n k < 2 ^ n\ for k :: int + by (simp add: take_bit_eq_mod) + +lemma take_bit_int_eq_self_iff: + \take_bit n k = k \ 0 \ k \ k < 2 ^ n\ (is \?P \ ?Q\) + for k :: int +proof + assume ?P + moreover note take_bit_int_less_exp [of n k] take_bit_nonnegative [of n k] + ultimately show ?Q + by simp +next + assume ?Q + then show ?P + by (simp add: take_bit_eq_mod) +qed + +lemma take_bit_int_eq_self: + \take_bit n k = k\ if \0 \ k\ \k < 2 ^ n\ for k :: int + using that by (simp add: take_bit_int_eq_self_iff) + lemma mask_half_int: \mask n div 2 = (mask (n - 1) :: int)\ by (cases n) (simp_all add: mask_eq_exp_minus_1 algebra_simps) @@ -2183,7 +1729,7 @@ case (odd k) from odd.IH [of \l div 2\] odd.hyps odd.prems show ?case - by (simp add: and_int_rec [of _ l]) + by (simp add: and_int_rec [of _ l]) linarith qed lemma or_nonnegative_int_iff [simp]: @@ -2208,7 +1754,7 @@ case (even k) from even.IH [of \l div 2\] even.hyps even.prems show ?case - by (simp add: or_int_rec [of _ l]) + by (simp add: or_int_rec [of _ l]) linarith next case (odd k) from odd.IH [of \l div 2\] odd.hyps odd.prems @@ -2335,6 +1881,92 @@ by (auto simp add: and_int_rec [of _ y] or_int_rec [of _ y] elim: oddE) qed +lemma push_bit_minus_one: + "push_bit n (- 1 :: int) = - (2 ^ n)" + by (simp add: push_bit_eq_mult) + +lemma minus_1_div_exp_eq_int: + \- 1 div (2 :: int) ^ n = - 1\ + by (induction n) (use div_exp_eq [symmetric, of \- 1 :: int\ 1] in \simp_all add: ac_simps\) + +lemma drop_bit_minus_one [simp]: + \drop_bit n (- 1 :: int) = - 1\ + by (simp add: drop_bit_eq_div minus_1_div_exp_eq_int) + +lemma take_bit_Suc_from_most: + \take_bit (Suc n) k = 2 ^ n * of_bool (bit k n) + take_bit n k\ for k :: int + by (simp only: take_bit_eq_mod power_Suc2) (simp_all add: bit_iff_odd odd_iff_mod_2_eq_one zmod_zmult2_eq) + +lemma take_bit_minus: + \take_bit n (- take_bit n k) = take_bit n (- k)\ + for k :: int + by (simp add: take_bit_eq_mod mod_minus_eq) + +lemma take_bit_diff: + \take_bit n (take_bit n k - take_bit n l) = take_bit n (k - l)\ + for k l :: int + by (simp add: take_bit_eq_mod mod_diff_eq) + +lemma bit_imp_take_bit_positive: + \0 < take_bit m k\ if \n < m\ and \bit k n\ for k :: int +proof (rule ccontr) + assume \\ 0 < take_bit m k\ + then have \take_bit m k = 0\ + by (auto simp add: not_less intro: order_antisym) + then have \bit (take_bit m k) n = bit 0 n\ + by simp + with that show False + by (simp add: bit_take_bit_iff) +qed + +lemma take_bit_mult: + \take_bit n (take_bit n k * take_bit n l) = take_bit n (k * l)\ + for k l :: int + by (simp add: take_bit_eq_mod mod_mult_eq) + +lemma (in ring_1) of_nat_nat_take_bit_eq [simp]: + \of_nat (nat (take_bit n k)) = of_int (take_bit n k)\ + by simp + +lemma take_bit_minus_small_eq: + \take_bit n (- k) = 2 ^ n - k\ if \0 < k\ \k \ 2 ^ n\ for k :: int +proof - + define m where \m = nat k\ + with that have \k = int m\ and \0 < m\ and \m \ 2 ^ n\ + by simp_all + have \(2 ^ n - m) mod 2 ^ n = 2 ^ n - m\ + using \0 < m\ by simp + then have \int ((2 ^ n - m) mod 2 ^ n) = int (2 ^ n - m)\ + by simp + then have \(2 ^ n - int m) mod 2 ^ n = 2 ^ n - int m\ + using \m \ 2 ^ n\ by (simp only: of_nat_mod of_nat_diff) simp + with \k = int m\ have \(2 ^ n - k) mod 2 ^ n = 2 ^ n - k\ + by simp + then show ?thesis + by (simp add: take_bit_eq_mod) +qed + +lemma drop_bit_push_bit_int: + \drop_bit m (push_bit n k) = drop_bit (m - n) (push_bit (n - m) k)\ for k :: int + by (cases \m \ n\) (auto simp add: mult.left_commute [of _ \2 ^ n\] mult.commute [of _ \2 ^ n\] mult.assoc + mult.commute [of k] drop_bit_eq_div push_bit_eq_mult not_le power_add dest!: le_Suc_ex less_imp_Suc_add) + +lemma push_bit_nonnegative_int_iff [simp]: + \push_bit n k \ 0 \ k \ 0\ for k :: int + by (simp add: push_bit_eq_mult zero_le_mult_iff power_le_zero_eq) + +lemma push_bit_negative_int_iff [simp]: + \push_bit n k < 0 \ k < 0\ for k :: int + by (subst Not_eq_iff [symmetric]) (simp add: not_less) + +lemma drop_bit_nonnegative_int_iff [simp]: + \drop_bit n k \ 0 \ k \ 0\ for k :: int + by (induction n) (auto simp add: drop_bit_Suc drop_bit_half) + +lemma drop_bit_negative_int_iff [simp]: + \drop_bit n k < 0 \ k < 0\ for k :: int + by (subst Not_eq_iff [symmetric]) (simp add: not_less) + lemma set_bit_nonnegative_int_iff [simp]: \set_bit n k \ 0 \ k \ 0\ for k :: int by (simp add: set_bit_def) @@ -2413,13 +2045,311 @@ qed qed +lemma and_int_unfold [code]: + \k AND l = (if k = 0 \ l = 0 then 0 else if k = - 1 then l else if l = - 1 then k + else (k mod 2) * (l mod 2) + 2 * ((k div 2) AND (l div 2)))\ for k l :: int + by (auto simp add: and_int_rec [of k l] zmult_eq_1_iff elim: oddE) + +lemma or_int_unfold [code]: + \k OR l = (if k = - 1 \ l = - 1 then - 1 else if k = 0 then l else if l = 0 then k + else max (k mod 2) (l mod 2) + 2 * ((k div 2) OR (l div 2)))\ for k l :: int + by (auto simp add: or_int_rec [of k l] elim: oddE) + +lemma xor_int_unfold [code]: + \k XOR l = (if k = - 1 then NOT l else if l = - 1 then NOT k else if k = 0 then l else if l = 0 then k + else \k mod 2 - l mod 2\ + 2 * ((k div 2) XOR (l div 2)))\ for k l :: int + by (auto simp add: xor_int_rec [of k l] not_int_def elim!: oddE) + + +subsection \Instance \<^typ>\nat\\ + +instantiation nat :: semiring_bit_operations +begin + +definition and_nat :: \nat \ nat \ nat\ + where \m AND n = nat (int m AND int n)\ for m n :: nat + +definition or_nat :: \nat \ nat \ nat\ + where \m OR n = nat (int m OR int n)\ for m n :: nat + +definition xor_nat :: \nat \ nat \ nat\ + where \m XOR n = nat (int m XOR int n)\ for m n :: nat + +definition mask_nat :: \nat \ nat\ + where \mask n = (2 :: nat) ^ n - 1\ + +definition push_bit_nat :: \nat \ nat \ nat\ + where \push_bit_nat n m = m * 2 ^ n\ + +definition drop_bit_nat :: \nat \ nat \ nat\ + where \drop_bit_nat n m = m div 2 ^ n\ + +definition take_bit_nat :: \nat \ nat \ nat\ + where \take_bit_nat n m = m mod 2 ^ n\ + +definition set_bit_nat :: \nat \ nat \ nat\ + where \set_bit m n = n OR push_bit m 1\ for m n :: nat + +definition unset_bit_nat :: \nat \ nat \ nat\ + where \unset_bit m n = nat (unset_bit m (int n))\ for m n :: nat + +definition flip_bit_nat :: \nat \ nat \ nat\ + where \flip_bit m n = n XOR push_bit m 1\ for m n :: nat + +instance proof + fix m n q :: nat + show \bit (m AND n) q \ bit m q \ bit n q\ + by (simp add: and_nat_def bit_simps) + show \bit (m OR n) q \ bit m q \ bit n q\ + by (simp add: or_nat_def bit_simps) + show \bit (m XOR n) q \ bit m q \ bit n q\ + by (simp add: xor_nat_def bit_simps) + show \bit (unset_bit m n) q \ bit n q \ m \ q\ + by (simp add: unset_bit_nat_def bit_simps) +qed (simp_all add: mask_nat_def set_bit_nat_def flip_bit_nat_def push_bit_nat_def drop_bit_nat_def take_bit_nat_def) + +end + +lemma take_bit_nat_less_exp [simp]: + \take_bit n m < 2 ^ n\ for n m ::nat + by (simp add: take_bit_eq_mod) + +lemma take_bit_nat_eq_self_iff: + \take_bit n m = m \ m < 2 ^ n\ (is \?P \ ?Q\) + for n m :: nat +proof + assume ?P + moreover note take_bit_nat_less_exp [of n m] + ultimately show ?Q + by simp +next + assume ?Q + then show ?P + by (simp add: take_bit_eq_mod) +qed + +lemma take_bit_nat_eq_self: + \take_bit n m = m\ if \m < 2 ^ n\ for m n :: nat + using that by (simp add: take_bit_nat_eq_self_iff) + +lemma take_bit_nat_less_eq_self [simp]: + \take_bit n m \ m\ for n m :: nat + by (simp add: take_bit_eq_mod) + +lemma take_bit_nat_less_self_iff: + \take_bit n m < m \ 2 ^ n \ m\ (is \?P \ ?Q\) + for m n :: nat +proof + assume ?P + then have \take_bit n m \ m\ + by simp + then show \?Q\ + by (simp add: take_bit_nat_eq_self_iff) +next + have \take_bit n m < 2 ^ n\ + by (fact take_bit_nat_less_exp) + also assume ?Q + finally show ?P . +qed + +lemma bit_push_bit_iff_nat: + \bit (push_bit m q) n \ m \ n \ bit q (n - m)\ for q :: nat + by (auto simp add: bit_push_bit_iff) + +lemma and_nat_rec: + \m AND n = of_bool (odd m \ odd n) + 2 * ((m div 2) AND (n div 2))\ for m n :: nat + apply (simp add: and_nat_def and_int_rec [of \int m\ \int n\] zdiv_int nat_add_distrib nat_mult_distrib) + apply (subst nat_add_distrib) + apply auto + done + +lemma or_nat_rec: + \m OR n = of_bool (odd m \ odd n) + 2 * ((m div 2) OR (n div 2))\ for m n :: nat + apply (simp add: or_nat_def or_int_rec [of \int m\ \int n\] zdiv_int nat_add_distrib nat_mult_distrib) + apply (subst nat_add_distrib) + apply auto + done + +lemma xor_nat_rec: + \m XOR n = of_bool (odd m \ odd n) + 2 * ((m div 2) XOR (n div 2))\ for m n :: nat + apply (simp add: xor_nat_def xor_int_rec [of \int m\ \int n\] zdiv_int nat_add_distrib nat_mult_distrib) + apply (subst nat_add_distrib) + apply auto + done + +lemma Suc_0_and_eq [simp]: + \Suc 0 AND n = n mod 2\ + using one_and_eq [of n] by simp + +lemma and_Suc_0_eq [simp]: + \n AND Suc 0 = n mod 2\ + using and_one_eq [of n] by simp + +lemma Suc_0_or_eq: + \Suc 0 OR n = n + of_bool (even n)\ + using one_or_eq [of n] by simp + +lemma or_Suc_0_eq: + \n OR Suc 0 = n + of_bool (even n)\ + using or_one_eq [of n] by simp + +lemma Suc_0_xor_eq: + \Suc 0 XOR n = n + of_bool (even n) - of_bool (odd n)\ + using one_xor_eq [of n] by simp + +lemma xor_Suc_0_eq: + \n XOR Suc 0 = n + of_bool (even n) - of_bool (odd n)\ + using xor_one_eq [of n] by simp + +lemma and_nat_unfold [code]: + \m AND n = (if m = 0 \ n = 0 then 0 else (m mod 2) * (n mod 2) + 2 * ((m div 2) AND (n div 2)))\ + for m n :: nat + by (auto simp add: and_nat_rec [of m n] elim: oddE) + +lemma or_nat_unfold [code]: + \m OR n = (if m = 0 then n else if n = 0 then m + else max (m mod 2) (n mod 2) + 2 * ((m div 2) OR (n div 2)))\ for m n :: nat + by (auto simp add: or_nat_rec [of m n] elim: oddE) + +lemma xor_nat_unfold [code]: + \m XOR n = (if m = 0 then n else if n = 0 then m + else (m mod 2 + n mod 2) mod 2 + 2 * ((m div 2) XOR (n div 2)))\ for m n :: nat + by (auto simp add: xor_nat_rec [of m n] elim!: oddE) + +lemma [code]: + \unset_bit 0 m = 2 * (m div 2)\ + \unset_bit (Suc n) m = m mod 2 + 2 * unset_bit n (m div 2)\ + by (simp_all add: unset_bit_Suc) + + +subsection \Common algebraic structure\ + +class unique_euclidean_semiring_with_bit_operations = + unique_euclidean_semiring_with_nat + semiring_bit_operations +begin + +lemma take_bit_of_exp [simp]: + \take_bit m (2 ^ n) = of_bool (n < m) * 2 ^ n\ + by (simp add: take_bit_eq_mod exp_mod_exp) + +lemma take_bit_of_2 [simp]: + \take_bit n 2 = of_bool (2 \ n) * 2\ + using take_bit_of_exp [of n 1] by simp + +lemma take_bit_of_mask: + \take_bit m (2 ^ n - 1) = 2 ^ min m n - 1\ + by (simp add: take_bit_eq_mod mask_mod_exp) + +lemma push_bit_eq_0_iff [simp]: + "push_bit n a = 0 \ a = 0" + by (simp add: push_bit_eq_mult) + +lemma take_bit_add: + "take_bit n (take_bit n a + take_bit n b) = take_bit n (a + b)" + by (simp add: take_bit_eq_mod mod_simps) + +lemma take_bit_of_1_eq_0_iff [simp]: + "take_bit n 1 = 0 \ n = 0" + by (simp add: take_bit_eq_mod) + +lemma take_bit_Suc_1 [simp]: + \take_bit (Suc n) 1 = 1\ + by (simp add: take_bit_Suc) + +lemma take_bit_Suc_bit0 [simp]: + \take_bit (Suc n) (numeral (Num.Bit0 k)) = take_bit n (numeral k) * 2\ + by (simp add: take_bit_Suc numeral_Bit0_div_2) + +lemma take_bit_Suc_bit1 [simp]: + \take_bit (Suc n) (numeral (Num.Bit1 k)) = take_bit n (numeral k) * 2 + 1\ + by (simp add: take_bit_Suc numeral_Bit1_div_2 mod_2_eq_odd) + +lemma take_bit_numeral_1 [simp]: + \take_bit (numeral l) 1 = 1\ + by (simp add: take_bit_rec [of \numeral l\ 1]) + +lemma take_bit_numeral_bit0 [simp]: + \take_bit (numeral l) (numeral (Num.Bit0 k)) = take_bit (pred_numeral l) (numeral k) * 2\ + by (simp add: take_bit_rec numeral_Bit0_div_2) + +lemma take_bit_numeral_bit1 [simp]: + \take_bit (numeral l) (numeral (Num.Bit1 k)) = take_bit (pred_numeral l) (numeral k) * 2 + 1\ + by (simp add: take_bit_rec numeral_Bit1_div_2 mod_2_eq_odd) + +lemma drop_bit_Suc_bit0 [simp]: + \drop_bit (Suc n) (numeral (Num.Bit0 k)) = drop_bit n (numeral k)\ + by (simp add: drop_bit_Suc numeral_Bit0_div_2) + +lemma drop_bit_Suc_bit1 [simp]: + \drop_bit (Suc n) (numeral (Num.Bit1 k)) = drop_bit n (numeral k)\ + by (simp add: drop_bit_Suc numeral_Bit1_div_2) + +lemma drop_bit_numeral_bit0 [simp]: + \drop_bit (numeral l) (numeral (Num.Bit0 k)) = drop_bit (pred_numeral l) (numeral k)\ + by (simp add: drop_bit_rec numeral_Bit0_div_2) + +lemma drop_bit_numeral_bit1 [simp]: + \drop_bit (numeral l) (numeral (Num.Bit1 k)) = drop_bit (pred_numeral l) (numeral k)\ + by (simp add: drop_bit_rec numeral_Bit1_div_2) + +lemma drop_bit_of_nat: + "drop_bit n (of_nat m) = of_nat (drop_bit n m)" + by (simp add: drop_bit_eq_div Bit_Operations.drop_bit_eq_div of_nat_div [of m "2 ^ n"]) + +lemma bit_of_nat_iff_bit [bit_simps]: + \bit (of_nat m) n \ bit m n\ +proof - + have \even (m div 2 ^ n) \ even (of_nat (m div 2 ^ n))\ + by simp + also have \of_nat (m div 2 ^ n) = of_nat m div of_nat (2 ^ n)\ + by (simp add: of_nat_div) + finally show ?thesis + by (simp add: bit_iff_odd semiring_bits_class.bit_iff_odd) +qed + +lemma of_nat_drop_bit: + \of_nat (drop_bit m n) = drop_bit m (of_nat n)\ + by (simp add: drop_bit_eq_div Bit_Operations.drop_bit_eq_div of_nat_div) + +lemma bit_push_bit_iff_of_nat_iff [bit_simps]: + \bit (push_bit m (of_nat r)) n \ m \ n \ bit (of_nat r) (n - m)\ + by (auto simp add: bit_push_bit_iff) + +lemma take_bit_sum: + "take_bit n a = (\k = 0..k = 0..k = Suc 0..k = Suc 0..k = 0..More properties\ + lemma take_bit_eq_mask_iff: \take_bit n k = mask n \ take_bit n (k + 1) = 0\ (is \?P \ ?Q\) for k :: int proof assume ?P then have \take_bit n (take_bit n k + take_bit n 1) = 0\ - by (simp add: mask_eq_exp_minus_1) + by (simp add: mask_eq_exp_minus_1 take_bit_eq_0_iff) then show ?Q by (simp only: take_bit_add) next @@ -2480,11 +2410,11 @@ lemma push_bit_of_int: \push_bit n (of_int k) = of_int (push_bit n k)\ - by (simp add: push_bit_eq_mult semiring_bit_shifts_class.push_bit_eq_mult) + by (simp add: push_bit_eq_mult Bit_Operations.push_bit_eq_mult) lemma of_int_push_bit: \of_int (push_bit n k) = push_bit n (of_int k)\ - by (simp add: push_bit_eq_mult semiring_bit_shifts_class.push_bit_eq_mult) + by (simp add: push_bit_eq_mult Bit_Operations.push_bit_eq_mult) lemma take_bit_of_int: \take_bit n (of_int k) = of_int (take_bit n k)\ @@ -2628,6 +2558,33 @@ \Num.sub n num.One = NOT (- numeral n :: int)\ by (simp add: not_int_def) +lemma bit_numeral_int_iff [bit_simps]: + \bit (numeral m :: int) n \ bit (numeral m :: nat) n\ + using bit_of_nat_iff_bit [of \numeral m\ n] by simp + +lemma bit_minus_int_iff [bit_simps]: + \bit (- k) n \ \ bit (k - 1) n\ + for k :: int + using bit_not_int_iff' [of \k - 1\] by simp + +lemma bit_numeral_int_simps [simp]: + \bit (1 :: int) (numeral n) \ bit (0 :: int) (pred_numeral n)\ + \bit (numeral (num.Bit0 w) :: int) (numeral n) \ bit (numeral w :: int) (pred_numeral n)\ + \bit (numeral (num.Bit1 w) :: int) (numeral n) \ bit (numeral w :: int) (pred_numeral n)\ + \bit (numeral (Num.BitM w) :: int) (numeral n) \ \ bit (- numeral w :: int) (pred_numeral n)\ + \bit (- numeral (num.Bit0 w) :: int) (numeral n) \ bit (- numeral w :: int) (pred_numeral n)\ + \bit (- numeral (num.Bit1 w) :: int) (numeral n) \ \ bit (numeral w :: int) (pred_numeral n)\ + \bit (- numeral (Num.BitM w) :: int) (numeral n) \ bit (- (numeral w) :: int) (pred_numeral n)\ + by (simp_all add: bit_1_iff numeral_eq_Suc bit_Suc add_One sub_inc_One_eq bit_minus_int_iff) + +lemma bit_numeral_Bit0_Suc_iff [simp]: + \bit (numeral (Num.Bit0 m) :: int) (Suc n) \ bit (numeral m :: int) n\ + by (simp add: bit_Suc) + +lemma bit_numeral_Bit1_Suc_iff [simp]: + \bit (numeral (Num.Bit1 m) :: int) (Suc n) \ bit (numeral m :: int) n\ + by (simp add: bit_Suc) + lemma int_not_numerals [simp]: \NOT (numeral (Num.Bit0 n) :: int) = - numeral (Num.Bit1 n)\ \NOT (numeral (Num.Bit1 n) :: int) = - numeral (Num.inc (num.Bit1 n))\ @@ -2744,6 +2701,203 @@ end +context semiring_bit_operations +begin + +lemma push_bit_of_nat: + \push_bit n (of_nat m) = of_nat (push_bit n m)\ + by (simp add: push_bit_eq_mult Bit_Operations.push_bit_eq_mult) + +lemma of_nat_push_bit: + \of_nat (push_bit m n) = push_bit m (of_nat n)\ + by (simp add: push_bit_eq_mult Bit_Operations.push_bit_eq_mult) + +lemma take_bit_of_nat: + \take_bit n (of_nat m) = of_nat (take_bit n m)\ + by (rule bit_eqI) (simp add: bit_take_bit_iff Bit_Operations.bit_take_bit_iff bit_of_nat_iff) + +lemma of_nat_take_bit: + \of_nat (take_bit n m) = take_bit n (of_nat m)\ + by (rule bit_eqI) (simp add: bit_take_bit_iff Bit_Operations.bit_take_bit_iff bit_of_nat_iff) + +end + +lemma push_bit_nat_eq: + \push_bit n (nat k) = nat (push_bit n k)\ + by (cases \k \ 0\) (simp_all add: push_bit_eq_mult nat_mult_distrib not_le mult_nonneg_nonpos2) + +lemma drop_bit_nat_eq: + \drop_bit n (nat k) = nat (drop_bit n k)\ + apply (cases \k \ 0\) + apply (simp_all add: drop_bit_eq_div nat_div_distrib nat_power_eq not_le) + apply (simp add: divide_int_def) + done + +lemma take_bit_nat_eq: + \take_bit n (nat k) = nat (take_bit n k)\ if \k \ 0\ + using that by (simp add: take_bit_eq_mod nat_mod_distrib nat_power_eq) + +lemma nat_take_bit_eq: + \nat (take_bit n k) = take_bit n (nat k)\ + if \k \ 0\ + using that by (simp add: take_bit_eq_mod nat_mod_distrib nat_power_eq) + +lemma not_exp_less_eq_0_int [simp]: + \\ 2 ^ n \ (0::int)\ + by (simp add: power_le_zero_eq) + +lemma half_nonnegative_int_iff [simp]: + \k div 2 \ 0 \ k \ 0\ for k :: int +proof (cases \k \ 0\) + case True + then show ?thesis + by (auto simp add: divide_int_def sgn_1_pos) +next + case False + then show ?thesis + by (auto simp add: divide_int_def not_le elim!: evenE) +qed + +lemma half_negative_int_iff [simp]: + \k div 2 < 0 \ k < 0\ for k :: int + by (subst Not_eq_iff [symmetric]) (simp add: not_less) + +lemma push_bit_of_Suc_0 [simp]: + "push_bit n (Suc 0) = 2 ^ n" + using push_bit_of_1 [where ?'a = nat] by simp + +lemma take_bit_of_Suc_0 [simp]: + "take_bit n (Suc 0) = of_bool (0 < n)" + using take_bit_of_1 [where ?'a = nat] by simp + +lemma drop_bit_of_Suc_0 [simp]: + "drop_bit n (Suc 0) = of_bool (n = 0)" + using drop_bit_of_1 [where ?'a = nat] by simp + +lemma int_bit_bound: + fixes k :: int + obtains n where \\m. n \ m \ bit k m \ bit k n\ + and \n > 0 \ bit k (n - 1) \ bit k n\ +proof - + obtain q where *: \\m. q \ m \ bit k m \ bit k q\ + proof (cases \k \ 0\) + case True + moreover from power_gt_expt [of 2 \nat k\] + have \nat k < 2 ^ nat k\ + by simp + then have \int (nat k) < int (2 ^ nat k)\ + by (simp only: of_nat_less_iff) + ultimately have *: \k div 2 ^ nat k = 0\ + by simp + show thesis + proof (rule that [of \nat k\]) + fix m + assume \nat k \ m\ + then show \bit k m \ bit k (nat k)\ + by (auto simp add: * bit_iff_odd power_add zdiv_zmult2_eq dest!: le_Suc_ex) + qed + next + case False + moreover from power_gt_expt [of 2 \nat (- k)\] + have \nat (- k) < 2 ^ nat (- k)\ + by simp + then have \int (nat (- k)) < int (2 ^ nat (- k))\ + by (simp only: of_nat_less_iff) + ultimately have \- k div - (2 ^ nat (- k)) = - 1\ + by (subst div_pos_neg_trivial) simp_all + then have *: \k div 2 ^ nat (- k) = - 1\ + by simp + show thesis + proof (rule that [of \nat (- k)\]) + fix m + assume \nat (- k) \ m\ + then show \bit k m \ bit k (nat (- k))\ + by (auto simp add: * bit_iff_odd power_add zdiv_zmult2_eq minus_1_div_exp_eq_int dest!: le_Suc_ex) + qed + qed + show thesis + proof (cases \\m. bit k m \ bit k q\) + case True + then have \bit k 0 \ bit k q\ + by blast + with True that [of 0] show thesis + by simp + next + case False + then obtain r where **: \bit k r \ bit k q\ + by blast + have \r < q\ + by (rule ccontr) (use * [of r] ** in simp) + define N where \N = {n. n < q \ bit k n \ bit k q}\ + moreover have \finite N\ \r \ N\ + using ** N_def \r < q\ by auto + moreover define n where \n = Suc (Max N)\ + ultimately have \\m. n \ m \ bit k m \ bit k n\ + apply auto + apply (metis (full_types, lifting) "*" Max_ge_iff Suc_n_not_le_n \finite N\ all_not_in_conv mem_Collect_eq not_le) + apply (metis "*" Max_ge Suc_n_not_le_n \finite N\ linorder_not_less mem_Collect_eq) + apply (metis "*" Max_ge Suc_n_not_le_n \finite N\ linorder_not_less mem_Collect_eq) + apply (metis (full_types, lifting) "*" Max_ge_iff Suc_n_not_le_n \finite N\ all_not_in_conv mem_Collect_eq not_le) + done + have \bit k (Max N) \ bit k n\ + by (metis (mono_tags, lifting) "*" Max_in N_def \\m. n \ m \ bit k m = bit k n\ \finite N\ \r \ N\ empty_iff le_cases mem_Collect_eq) + show thesis apply (rule that [of n]) + using \\m. n \ m \ bit k m = bit k n\ apply blast + using \bit k (Max N) \ bit k n\ n_def by auto + qed +qed + +context semiring_bit_operations +begin + +lemma of_nat_and_eq: + \of_nat (m AND n) = of_nat m AND of_nat n\ + by (rule bit_eqI) (simp add: bit_of_nat_iff bit_and_iff Bit_Operations.bit_and_iff) + +lemma of_nat_or_eq: + \of_nat (m OR n) = of_nat m OR of_nat n\ + by (rule bit_eqI) (simp add: bit_of_nat_iff bit_or_iff Bit_Operations.bit_or_iff) + +lemma of_nat_xor_eq: + \of_nat (m XOR n) = of_nat m XOR of_nat n\ + by (rule bit_eqI) (simp add: bit_of_nat_iff bit_xor_iff Bit_Operations.bit_xor_iff) + +end + +context ring_bit_operations +begin + +lemma of_nat_mask_eq: + \of_nat (mask n) = mask n\ + by (induction n) (simp_all add: mask_Suc_double Bit_Operations.mask_Suc_double of_nat_or_eq) + +end + +lemma Suc_mask_eq_exp: + \Suc (mask n) = 2 ^ n\ + by (simp add: mask_eq_exp_minus_1) + +lemma less_eq_mask: + \n \ mask n\ + by (simp add: mask_eq_exp_minus_1 le_diff_conv2) + (metis Suc_mask_eq_exp diff_Suc_1 diff_le_diff_pow diff_zero le_refl not_less_eq_eq power_0) + +lemma less_mask: + \n < mask n\ if \Suc 0 < n\ +proof - + define m where \m = n - 2\ + with that have *: \n = m + 2\ + by simp + have \Suc (Suc (Suc m)) < 4 * 2 ^ m\ + by (induction m) simp_all + then have \Suc (m + 2) < Suc (mask (m + 2))\ + by (simp add: Suc_mask_eq_exp) + then have \m + 2 < mask (m + 2)\ + by (simp add: less_le) + with * show ?thesis + by simp +qed + subsection \Bit concatenation\ @@ -3140,156 +3294,11 @@ qed -subsection \Instance \<^typ>\nat\\ - -instantiation nat :: semiring_bit_operations -begin - -definition and_nat :: \nat \ nat \ nat\ - where \m AND n = nat (int m AND int n)\ for m n :: nat - -definition or_nat :: \nat \ nat \ nat\ - where \m OR n = nat (int m OR int n)\ for m n :: nat - -definition xor_nat :: \nat \ nat \ nat\ - where \m XOR n = nat (int m XOR int n)\ for m n :: nat - -definition mask_nat :: \nat \ nat\ - where \mask n = (2 :: nat) ^ n - 1\ - -definition set_bit_nat :: \nat \ nat \ nat\ - where \set_bit m n = n OR push_bit m 1\ for m n :: nat - -definition unset_bit_nat :: \nat \ nat \ nat\ - where \unset_bit m n = (if bit n m then n - push_bit m 1 else n)\ for m n :: nat - -definition flip_bit_nat :: \nat \ nat \ nat\ - where \flip_bit m n = n XOR push_bit m 1\ for m n :: nat - -instance proof - fix m n q :: nat - show \bit (m AND n) q \ bit m q \ bit n q\ - by (simp add: and_nat_def bit_simps) - show \bit (m OR n) q \ bit m q \ bit n q\ - by (simp add: or_nat_def bit_simps) - show \bit (m XOR n) q \ bit m q \ bit n q\ - by (simp add: xor_nat_def bit_simps) - show \bit (unset_bit m n) q \ bit n q \ m \ q\ - proof (cases \bit n m\) - case False - then show ?thesis by (auto simp add: unset_bit_nat_def) - next - case True - have \push_bit m (drop_bit m n) + take_bit m n = n\ - by (fact bits_ident) - also from \bit n m\ have \drop_bit m n = 2 * drop_bit (Suc m) n + 1\ - by (simp add: drop_bit_Suc drop_bit_half even_drop_bit_iff_not_bit ac_simps) - finally have \push_bit m (2 * drop_bit (Suc m) n) + take_bit m n + push_bit m 1 = n\ - by (simp only: push_bit_add ac_simps) - then have \n - push_bit m 1 = push_bit m (2 * drop_bit (Suc m) n) + take_bit m n\ - by simp - then have \n - push_bit m 1 = push_bit m (2 * drop_bit (Suc m) n) OR take_bit m n\ - by (simp add: or_nat_def bit_simps flip: disjunctive_add) - with \bit n m\ show ?thesis - by (auto simp add: unset_bit_nat_def or_nat_def bit_simps) - qed -qed (simp_all add: mask_nat_def set_bit_nat_def flip_bit_nat_def) - -end - -lemma and_nat_rec: - \m AND n = of_bool (odd m \ odd n) + 2 * ((m div 2) AND (n div 2))\ for m n :: nat - by (simp add: and_nat_def and_int_rec [of \int m\ \int n\] zdiv_int nat_add_distrib nat_mult_distrib) - -lemma or_nat_rec: - \m OR n = of_bool (odd m \ odd n) + 2 * ((m div 2) OR (n div 2))\ for m n :: nat - by (simp add: or_nat_def or_int_rec [of \int m\ \int n\] zdiv_int nat_add_distrib nat_mult_distrib) - -lemma xor_nat_rec: - \m XOR n = of_bool (odd m \ odd n) + 2 * ((m div 2) XOR (n div 2))\ for m n :: nat - by (simp add: xor_nat_def xor_int_rec [of \int m\ \int n\] zdiv_int nat_add_distrib nat_mult_distrib) - -lemma Suc_0_and_eq [simp]: - \Suc 0 AND n = n mod 2\ - using one_and_eq [of n] by simp - -lemma and_Suc_0_eq [simp]: - \n AND Suc 0 = n mod 2\ - using and_one_eq [of n] by simp - -lemma Suc_0_or_eq: - \Suc 0 OR n = n + of_bool (even n)\ - using one_or_eq [of n] by simp - -lemma or_Suc_0_eq: - \n OR Suc 0 = n + of_bool (even n)\ - using or_one_eq [of n] by simp - -lemma Suc_0_xor_eq: - \Suc 0 XOR n = n + of_bool (even n) - of_bool (odd n)\ - using one_xor_eq [of n] by simp - -lemma xor_Suc_0_eq: - \n XOR Suc 0 = n + of_bool (even n) - of_bool (odd n)\ - using xor_one_eq [of n] by simp +subsection \Horner sums\ context semiring_bit_operations begin -lemma of_nat_and_eq: - \of_nat (m AND n) = of_nat m AND of_nat n\ - by (rule bit_eqI) (simp add: bit_of_nat_iff bit_and_iff Bit_Operations.bit_and_iff) - -lemma of_nat_or_eq: - \of_nat (m OR n) = of_nat m OR of_nat n\ - by (rule bit_eqI) (simp add: bit_of_nat_iff bit_or_iff Bit_Operations.bit_or_iff) - -lemma of_nat_xor_eq: - \of_nat (m XOR n) = of_nat m XOR of_nat n\ - by (rule bit_eqI) (simp add: bit_of_nat_iff bit_xor_iff Bit_Operations.bit_xor_iff) - -end - -context ring_bit_operations -begin - -lemma of_nat_mask_eq: - \of_nat (mask n) = mask n\ - by (induction n) (simp_all add: mask_Suc_double Bit_Operations.mask_Suc_double of_nat_or_eq) - -end - -lemma Suc_mask_eq_exp: - \Suc (mask n) = 2 ^ n\ - by (simp add: mask_eq_exp_minus_1) - -lemma less_eq_mask: - \n \ mask n\ - by (simp add: mask_eq_exp_minus_1 le_diff_conv2) - (metis Suc_mask_eq_exp diff_Suc_1 diff_le_diff_pow diff_zero le_refl not_less_eq_eq power_0) - -lemma less_mask: - \n < mask n\ if \Suc 0 < n\ -proof - - define m where \m = n - 2\ - with that have *: \n = m + 2\ - by simp - have \Suc (Suc (Suc m)) < 4 * 2 ^ m\ - by (induction m) simp_all - then have \Suc (m + 2) < Suc (mask (m + 2))\ - by (simp add: Suc_mask_eq_exp) - then have \m + 2 < mask (m + 2)\ - by (simp add: less_le) - with * show ?thesis - by simp -qed - - -subsection \Horner sums\ - -context semiring_bit_shifts -begin - lemma horner_sum_bit_eq_take_bit: \horner_sum of_bool 2 (map (bit a) [0.. proof (induction a arbitrary: n rule: bits_induct) @@ -3321,7 +3330,7 @@ end -context unique_euclidean_semiring_with_bit_shifts +context unique_euclidean_semiring_with_bit_operations begin lemma bit_horner_sum_bit_iff [bit_simps]: @@ -3556,6 +3565,8 @@ \<^item> (Bounded) conversion from and to a list of bits: @{thm horner_sum_bit_eq_take_bit [where ?'a = int, no_vars]} \ +find_theorems \(_ AND _) * _ = _\ + no_notation "and" (infixr \AND\ 64) and or (infixr \OR\ 59) diff -r 2ab5dacdb1f6 -r 3146646a43a7 src/HOL/Code_Numeral.thy --- a/src/HOL/Code_Numeral.thy Tue Aug 03 13:53:22 2021 +0000 +++ b/src/HOL/Code_Numeral.thy Tue Aug 03 13:53:22 2021 +0000 @@ -293,12 +293,36 @@ instance integer :: unique_euclidean_ring_with_nat by (standard; transfer) (simp_all add: of_nat_div division_segment_int_def) -instantiation integer :: semiring_bit_shifts +instantiation integer :: ring_bit_operations begin lift_definition bit_integer :: \integer \ nat \ bool\ is bit . +lift_definition not_integer :: \integer \ integer\ + is not . + +lift_definition and_integer :: \integer \ integer \ integer\ + is \and\ . + +lift_definition or_integer :: \integer \ integer \ integer\ + is or . + +lift_definition xor_integer :: \integer \ integer \ integer\ + is xor . + +lift_definition mask_integer :: \nat \ integer\ + is mask . + +lift_definition set_bit_integer :: \nat \ integer \ integer\ + is set_bit . + +lift_definition unset_bit_integer :: \nat \ integer \ integer\ + is unset_bit . + +lift_definition flip_bit_integer :: \nat \ integer \ integer\ + is flip_bit . + lift_definition push_bit_integer :: \nat \ integer \ integer\ is push_bit . @@ -312,18 +336,47 @@ (fact bit_eq_rec bits_induct bit_iff_odd push_bit_eq_mult drop_bit_eq_div take_bit_eq_mod bits_div_0 bits_div_by_1 bits_mod_div_trivial even_succ_div_2 exp_div_exp_eq div_exp_eq mod_exp_eq mult_exp_mod_exp_eq div_exp_mod_exp_eq - even_mask_div_iff even_mult_exp_div_exp_iff)+ + even_mask_div_iff even_mult_exp_div_exp_iff + bit_and_iff bit_or_iff bit_xor_iff mask_eq_exp_minus_1 + set_bit_def bit_unset_bit_iff flip_bit_def bit_not_iff minus_eq_not_minus_1)+ end -instance integer :: unique_euclidean_semiring_with_bit_shifts .. +instance integer :: unique_euclidean_semiring_with_bit_operations .. + +context + includes bit_operations_syntax +begin lemma [code]: \bit k n \ odd (drop_bit n k)\ + \NOT k = - k - 1\ + \mask n = 2 ^ n - (1 :: integer)\ + \set_bit n k = k OR push_bit n 1\ + \unset_bit n k = k AND NOT (push_bit n 1)\ + \flip_bit n k = k XOR push_bit n 1\ \push_bit n k = k * 2 ^ n\ \drop_bit n k = k div 2 ^ n\ \take_bit n k = k mod 2 ^ n\ for k :: integer - by (fact bit_iff_odd_drop_bit push_bit_eq_mult drop_bit_eq_div take_bit_eq_mod)+ + by (fact bit_iff_odd_drop_bit not_eq_complement mask_eq_exp_minus_1 + set_bit_eq_or unset_bit_eq_and_not flip_bit_eq_xor push_bit_eq_mult drop_bit_eq_div take_bit_eq_mod)+ + +lemma [code]: + \k AND l = (if k = 0 \ l = 0 then 0 else if k = - 1 then l else if l = - 1 then k + else (k mod 2) * (l mod 2) + 2 * ((k div 2) AND (l div 2)))\ for k l :: integer + by transfer (fact and_int_unfold) + +lemma [code]: + \k OR l = (if k = - 1 \ l = - 1 then - 1 else if k = 0 then l else if l = 0 then k + else max (k mod 2) (l mod 2) + 2 * ((k div 2) OR (l div 2)))\ for k l :: integer + by transfer (fact or_int_unfold) + +lemma [code]: + \k XOR l = (if k = - 1 then NOT l else if l = - 1 then NOT k else if k = 0 then l else if l = 0 then k + else \k mod 2 - l mod 2\ + 2 * ((k div 2) XOR (l div 2)))\ for k l :: integer + by transfer (fact xor_int_unfold) + +end instantiation integer :: unique_euclidean_semiring_numeral begin @@ -1018,12 +1071,33 @@ instance natural :: unique_euclidean_semiring_with_nat by (standard; transfer) simp_all -instantiation natural :: semiring_bit_shifts +instantiation natural :: semiring_bit_operations begin lift_definition bit_natural :: \natural \ nat \ bool\ is bit . +lift_definition and_natural :: \natural \ natural \ natural\ + is \and\ . + +lift_definition or_natural :: \natural \ natural \ natural\ + is or . + +lift_definition xor_natural :: \natural \ natural \ natural\ + is xor . + +lift_definition mask_natural :: \nat \ natural\ + is mask . + +lift_definition set_bit_natural :: \nat \ natural \ natural\ + is set_bit . + +lift_definition unset_bit_natural :: \nat \ natural \ natural\ + is unset_bit . + +lift_definition flip_bit_natural :: \nat \ natural \ natural\ + is flip_bit . + lift_definition push_bit_natural :: \nat \ natural \ natural\ is push_bit . @@ -1037,18 +1111,49 @@ (fact bit_eq_rec bits_induct bit_iff_odd push_bit_eq_mult drop_bit_eq_div take_bit_eq_mod bits_div_0 bits_div_by_1 bits_mod_div_trivial even_succ_div_2 exp_div_exp_eq div_exp_eq mod_exp_eq mult_exp_mod_exp_eq div_exp_mod_exp_eq - even_mask_div_iff even_mult_exp_div_exp_iff)+ + even_mask_div_iff even_mult_exp_div_exp_iff bit_and_iff bit_or_iff bit_xor_iff + mask_eq_exp_minus_1 set_bit_def bit_unset_bit_iff flip_bit_def)+ end -instance natural :: unique_euclidean_semiring_with_bit_shifts .. +instance natural :: unique_euclidean_semiring_with_bit_operations .. + +context + includes bit_operations_syntax +begin lemma [code]: \bit m n \ odd (drop_bit n m)\ + \mask n = 2 ^ n - (1 :: integer)\ + \set_bit n m = m OR push_bit n 1\ + \flip_bit n m = m XOR push_bit n 1\ \push_bit n m = m * 2 ^ n\ \drop_bit n m = m div 2 ^ n\ \take_bit n m = m mod 2 ^ n\ for m :: natural - by (fact bit_iff_odd_drop_bit push_bit_eq_mult drop_bit_eq_div take_bit_eq_mod)+ + by (fact bit_iff_odd_drop_bit mask_eq_exp_minus_1 + set_bit_eq_or flip_bit_eq_xor push_bit_eq_mult drop_bit_eq_div take_bit_eq_mod)+ + +lemma [code]: + \m AND n = (if m = 0 \ n = 0 then 0 + else (m mod 2) * (n mod 2) + 2 * ((m div 2) AND (n div 2)))\ for m n :: natural + by transfer (fact and_nat_unfold) + +lemma [code]: + \m OR n = (if m = 0 then n else if n = 0 then m + else max (m mod 2) (n mod 2) + 2 * ((m div 2) OR (n div 2)))\ for m n :: natural + by transfer (fact or_nat_unfold) + +lemma [code]: + \m XOR n = (if m = 0 then n else if n = 0 then m + else (m mod 2 + n mod 2) mod 2 + 2 * ((m div 2) XOR (n div 2)))\ for m n :: natural + by transfer (fact xor_nat_unfold) + +lemma [code]: + \unset_bit 0 m = 2 * (m div 2)\ + \unset_bit (Suc n) m = m mod 2 + 2 * unset_bit n (m div 2)\ for m :: natural + by (transfer; simp add: unset_bit_Suc)+ + +end lift_definition natural_of_integer :: "integer \ natural" is "nat :: int \ nat" @@ -1142,6 +1247,10 @@ "integer_of_natural (natural_of_integer k) = max 0 k" by simp +lemma [code]: + \integer_of_natural (mask n) = mask n\ + by transfer (simp add: mask_eq_exp_minus_1 of_nat_diff) + lemma [code_abbrev]: "natural_of_integer (Code_Numeral.Pos k) = numeral k" by transfer simp @@ -1211,83 +1320,6 @@ "modulo :: natural \ _" integer_of_natural natural_of_integer - -subsection \Bit operations\ - -instantiation integer :: ring_bit_operations -begin - -lift_definition not_integer :: \integer \ integer\ - is not . - -lift_definition and_integer :: \integer \ integer \ integer\ - is \and\ . - -lift_definition or_integer :: \integer \ integer \ integer\ - is or . - -lift_definition xor_integer :: \integer \ integer \ integer\ - is xor . - -lift_definition mask_integer :: \nat \ integer\ - is mask . - -lift_definition set_bit_integer :: \nat \ integer \ integer\ - is set_bit . - -lift_definition unset_bit_integer :: \nat \ integer \ integer\ - is unset_bit . - -lift_definition flip_bit_integer :: \nat \ integer \ integer\ - is flip_bit . - -instance by (standard; transfer) - (simp_all add: minus_eq_not_minus_1 mask_eq_exp_minus_1 - bit_not_iff bit_and_iff bit_or_iff bit_xor_iff - set_bit_def bit_unset_bit_iff flip_bit_def) - -end - -lemma [code]: - \mask n = 2 ^ n - (1::integer)\ - by (simp add: mask_eq_exp_minus_1) - -instantiation natural :: semiring_bit_operations -begin - -lift_definition and_natural :: \natural \ natural \ natural\ - is \and\ . - -lift_definition or_natural :: \natural \ natural \ natural\ - is or . - -lift_definition xor_natural :: \natural \ natural \ natural\ - is xor . - -lift_definition mask_natural :: \nat \ natural\ - is mask . - -lift_definition set_bit_natural :: \nat \ natural \ natural\ - is set_bit . - -lift_definition unset_bit_natural :: \nat \ natural \ natural\ - is unset_bit . - -lift_definition flip_bit_natural :: \nat \ natural \ natural\ - is flip_bit . - -instance by (standard; transfer) - (simp_all add: mask_eq_exp_minus_1 - bit_and_iff bit_or_iff bit_xor_iff - set_bit_def bit_unset_bit_iff flip_bit_def) - -end - -lemma [code]: - \integer_of_natural (mask n) = mask n\ - by transfer (simp add: mask_eq_exp_minus_1 of_nat_diff) - - lifting_update integer.lifting lifting_forget integer.lifting diff -r 2ab5dacdb1f6 -r 3146646a43a7 src/HOL/Library/Word.thy --- a/src/HOL/Library/Word.thy Tue Aug 03 13:53:22 2021 +0000 +++ b/src/HOL/Library/Word.thy Tue Aug 03 13:53:22 2021 +0000 @@ -928,59 +928,6 @@ \ n < LENGTH('a) \ bit (- numeral w :: int) n\ by transfer simp -instantiation word :: (len) semiring_bit_shifts -begin - -lift_definition push_bit_word :: \nat \ 'a word \ 'a word\ - is push_bit -proof - - show \take_bit LENGTH('a) (push_bit n k) = take_bit LENGTH('a) (push_bit n l)\ - if \take_bit LENGTH('a) k = take_bit LENGTH('a) l\ for k l :: int and n :: nat - proof - - from that - have \take_bit (LENGTH('a) - n) (take_bit LENGTH('a) k) - = take_bit (LENGTH('a) - n) (take_bit LENGTH('a) l)\ - by simp - moreover have \min (LENGTH('a) - n) LENGTH('a) = LENGTH('a) - n\ - by simp - ultimately show ?thesis - by (simp add: take_bit_push_bit) - qed -qed - -lift_definition drop_bit_word :: \nat \ 'a word \ 'a word\ - is \\n. drop_bit n \ take_bit LENGTH('a)\ - by (simp add: take_bit_eq_mod) - -lift_definition take_bit_word :: \nat \ 'a word \ 'a word\ - is \\n. take_bit (min LENGTH('a) n)\ - by (simp add: ac_simps) (simp only: flip: take_bit_take_bit) - -instance proof - show \push_bit n a = a * 2 ^ n\ for n :: nat and a :: \'a word\ - by transfer (simp add: push_bit_eq_mult) - show \drop_bit n a = a div 2 ^ n\ for n :: nat and a :: \'a word\ - by transfer (simp flip: drop_bit_eq_div add: drop_bit_take_bit) - show \take_bit n a = a mod 2 ^ n\ for n :: nat and a :: \'a word\ - by transfer (auto simp flip: take_bit_eq_mod) -qed - -end - -lemma [code]: - \push_bit n w = w * 2 ^ n\ for w :: \'a::len word\ - by (fact push_bit_eq_mult) - -lemma [code]: - \Word.the_int (drop_bit n w) = drop_bit n (Word.the_int w)\ - by transfer (simp add: drop_bit_take_bit min_def le_less less_diff_conv) - -lemma [code]: - \Word.the_int (take_bit n w) = (if n < LENGTH('a::len) then take_bit n (Word.the_int w) else Word.the_int w)\ - for w :: \'a::len word\ - by transfer (simp add: not_le not_less ac_simps min_absorb2) - - instantiation word :: (len) ring_bit_operations begin @@ -1016,12 +963,53 @@ is flip_bit by (simp add: flip_bit_def) -instance by (standard; transfer) - (auto simp add: minus_eq_not_minus_1 mask_eq_exp_minus_1 - bit_simps set_bit_def flip_bit_def) +lift_definition push_bit_word :: \nat \ 'a word \ 'a word\ + is push_bit +proof - + show \take_bit LENGTH('a) (push_bit n k) = take_bit LENGTH('a) (push_bit n l)\ + if \take_bit LENGTH('a) k = take_bit LENGTH('a) l\ for k l :: int and n :: nat + proof - + from that + have \take_bit (LENGTH('a) - n) (take_bit LENGTH('a) k) + = take_bit (LENGTH('a) - n) (take_bit LENGTH('a) l)\ + by simp + moreover have \min (LENGTH('a) - n) LENGTH('a) = LENGTH('a) - n\ + by simp + ultimately show ?thesis + by (simp add: take_bit_push_bit) + qed +qed + +lift_definition drop_bit_word :: \nat \ 'a word \ 'a word\ + is \\n. drop_bit n \ take_bit LENGTH('a)\ + by (simp add: take_bit_eq_mod) + +lift_definition take_bit_word :: \nat \ 'a word \ 'a word\ + is \\n. take_bit (min LENGTH('a) n)\ + by (simp add: ac_simps) (simp only: flip: take_bit_take_bit) + +instance apply (standard; transfer) + apply (auto simp add: minus_eq_not_minus_1 mask_eq_exp_minus_1 + bit_simps set_bit_def flip_bit_def take_bit_drop_bit + simp flip: drop_bit_eq_div take_bit_eq_mod) + apply (simp_all add: drop_bit_take_bit flip: push_bit_eq_mult) + done end +lemma [code]: + \push_bit n w = w * 2 ^ n\ for w :: \'a::len word\ + by (fact push_bit_eq_mult) + +lemma [code]: + \Word.the_int (drop_bit n w) = drop_bit n (Word.the_int w)\ + by transfer (simp add: drop_bit_take_bit min_def le_less less_diff_conv) + +lemma [code]: + \Word.the_int (take_bit n w) = (if n < LENGTH('a::len) then take_bit n (Word.the_int w) else Word.the_int w)\ + for w :: \'a::len word\ + by transfer (simp add: not_le not_less ac_simps min_absorb2) + lemma [code_abbrev]: \push_bit n 1 = (2 :: 'a::len word) ^ n\ by (fact push_bit_of_1) @@ -1114,7 +1102,7 @@ end -context semiring_bit_shifts +context semiring_bit_operations begin lemma unsigned_push_bit_eq: @@ -1144,7 +1132,7 @@ end -context unique_euclidean_semiring_with_bit_shifts +context unique_euclidean_semiring_with_bit_operations begin lemma unsigned_drop_bit_eq: @@ -1400,7 +1388,7 @@ by (simp add: of_nat_mod) qed -context semiring_bit_shifts +context semiring_bit_operations begin lemma unsigned_ucast_eq: diff -r 2ab5dacdb1f6 -r 3146646a43a7 src/HOL/Library/Z2.thy --- a/src/HOL/Library/Z2.thy Tue Aug 03 13:53:22 2021 +0000 +++ b/src/HOL/Library/Z2.thy Tue Aug 03 13:53:22 2021 +0000 @@ -43,7 +43,7 @@ \a \ 0 \ a = 1\ for a :: bit by (cases a) simp_all -lemma bit_not_one_imp [simp]: +lemma bit_not_one_iff [simp]: \a \ 1 \ a = 0\ for a :: bit by (cases a) simp_all @@ -144,6 +144,24 @@ \a ^ n = of_bool (odd a \ n = 0)\ for a :: bit by (cases a) simp_all +instantiation bit :: field +begin + +definition uminus_bit :: \bit \ bit\ + where [simp]: \uminus_bit = id\ + +definition inverse_bit :: \bit \ bit\ + where [simp]: \inverse_bit = id\ + +instance + apply standard + apply simp_all + apply (simp only: Z2.bit_eq_iff even_add) + apply simp + done + +end + instantiation bit :: semiring_bits begin @@ -158,30 +176,16 @@ end -instantiation bit :: semiring_bit_shifts -begin - -definition push_bit_bit :: \nat \ bit \ bit\ - where [simp]: \push_bit n b = of_bool (odd b \ n = 0)\ for b :: bit - -definition drop_bit_bit :: \nat \ bit \ bit\ - where [simp]: \drop_bit_bit = push_bit\ - -definition take_bit_bit :: \nat \ bit \ bit\ - where [simp]: \take_bit n b = of_bool (odd b \ n > 0)\ for b :: bit - -instance - by standard simp_all - -end - -instantiation bit :: semiring_bit_operations +instantiation bit :: ring_bit_operations begin context includes bit_operations_syntax begin +definition not_bit :: \bit \ bit\ + where [simp]: \NOT b = of_bool (even b)\ for b :: bit + definition and_bit :: \bit \ bit \ bit\ where [simp]: \b AND c = of_bool (odd b \ odd c)\ for b c :: bit @@ -203,10 +207,22 @@ definition flip_bit_bit :: \nat \ bit \ bit\ where [simp]: \flip_bit n b = of_bool ((n = 0) \ odd b)\ for b :: bit +definition push_bit_bit :: \nat \ bit \ bit\ + where [simp]: \push_bit n b = of_bool (odd b \ n = 0)\ for b :: bit + +definition drop_bit_bit :: \nat \ bit \ bit\ + where [simp]: \drop_bit n b = of_bool (odd b \ n = 0)\ for b :: bit + +definition take_bit_bit :: \nat \ bit \ bit\ + where [simp]: \take_bit n b = of_bool (odd b \ n > 0)\ for b :: bit + end instance - by standard auto + apply standard + apply auto + apply (simp only: Z2.bit_eq_iff even_add even_zero) + done end @@ -218,30 +234,6 @@ \(*) = (Bit_Operations.and :: bit \ _)\ by (simp add: fun_eq_iff) -instantiation bit :: field -begin - -definition uminus_bit :: \bit \ bit\ - where [simp]: \uminus_bit = id\ - -definition inverse_bit :: \bit \ bit\ - where [simp]: \inverse_bit = id\ - -instance - by standard simp_all - -end - -instantiation bit :: ring_bit_operations -begin - -definition not_bit :: \bit \ bit\ - where [simp]: \NOT b = of_bool (even b)\ for b :: bit - -instance - by standard auto - -end lemma bit_numeral_even [simp]: "numeral (Num.Bit0 w) = (0 :: bit)" by (simp only: Z2.bit_eq_iff even_numeral) simp diff -r 2ab5dacdb1f6 -r 3146646a43a7 src/HOL/String.thy --- a/src/HOL/String.thy Tue Aug 03 13:53:22 2021 +0000 +++ b/src/HOL/String.thy Tue Aug 03 13:53:22 2021 +0000 @@ -38,7 +38,7 @@ end -context unique_euclidean_semiring_with_bit_shifts +context unique_euclidean_semiring_with_bit_operations begin definition char_of :: \'a \ char\