# HG changeset patch # User desharna # Date 1628058436 -7200 # Node ID 58e208ad4bcf563c408c4fecacb7869971beafa3 # Parent 6c7feeef0ff237a19ad2afe0c762ce2dd69122a8# Parent 3146646a43a7961d74854a8bb98981f41faa572f merged diff -r 6c7feeef0ff2 -r 58e208ad4bcf src/HOL/Bit_Operations.thy --- a/src/HOL/Bit_Operations.thy Tue Aug 03 10:14:48 2021 +0200 +++ b/src/HOL/Bit_Operations.thy Wed Aug 04 08:27:16 2021 +0200 @@ -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 6c7feeef0ff2 -r 58e208ad4bcf src/HOL/Code_Numeral.thy --- a/src/HOL/Code_Numeral.thy Tue Aug 03 10:14:48 2021 +0200 +++ b/src/HOL/Code_Numeral.thy Wed Aug 04 08:27:16 2021 +0200 @@ -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 6c7feeef0ff2 -r 58e208ad4bcf src/HOL/Library/Word.thy --- a/src/HOL/Library/Word.thy Tue Aug 03 10:14:48 2021 +0200 +++ b/src/HOL/Library/Word.thy Wed Aug 04 08:27:16 2021 +0200 @@ -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 6c7feeef0ff2 -r 58e208ad4bcf src/HOL/Library/Z2.thy --- a/src/HOL/Library/Z2.thy Tue Aug 03 10:14:48 2021 +0200 +++ b/src/HOL/Library/Z2.thy Wed Aug 04 08:27:16 2021 +0200 @@ -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 6c7feeef0ff2 -r 58e208ad4bcf src/HOL/ROOT --- a/src/HOL/ROOT Tue Aug 03 10:14:48 2021 +0200 +++ b/src/HOL/ROOT Wed Aug 04 08:27:16 2021 +0200 @@ -646,7 +646,6 @@ Ballot BinEx Birthday_Paradox - Bit_Lists Bubblesort CTL Cartouche_Examples diff -r 6c7feeef0ff2 -r 58e208ad4bcf src/HOL/String.thy --- a/src/HOL/String.thy Tue Aug 03 10:14:48 2021 +0200 +++ b/src/HOL/String.thy Wed Aug 04 08:27:16 2021 +0200 @@ -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\ diff -r 6c7feeef0ff2 -r 58e208ad4bcf src/HOL/ex/Bit_Lists.thy --- a/src/HOL/ex/Bit_Lists.thy Tue Aug 03 10:14:48 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,356 +0,0 @@ - (* Author: Florian Haftmann, TUM -*) - -section \Proof(s) of concept for algebraically founded lists of bits\ - -theory Bit_Lists - imports - "HOL-Library.Word" "HOL-Library.More_List" -begin - -subsection \Fragments of algebraic bit representations\ - -context comm_semiring_1 -begin - -abbreviation (input) unsigned_of_bits :: "bool list \ 'a" - where "unsigned_of_bits \ horner_sum of_bool 2" - -lemma unsigned_of_bits_replicate_False [simp]: - "unsigned_of_bits (replicate n False) = 0" - by (induction n) simp_all - -end - -context unique_euclidean_semiring_with_bit_shifts -begin - -lemma unsigned_of_bits_append [simp]: - "unsigned_of_bits (bs @ cs) = unsigned_of_bits bs - + push_bit (length bs) (unsigned_of_bits cs)" - by (induction bs) (simp_all add: push_bit_double, - simp_all add: algebra_simps) - -lemma unsigned_of_bits_take [simp]: - "unsigned_of_bits (take n bs) = take_bit n (unsigned_of_bits bs)" -proof (induction bs arbitrary: n) - case Nil - then show ?case - by simp -next - case (Cons b bs) - then show ?case - by (cases n) (simp_all add: ac_simps take_bit_Suc) -qed - -lemma unsigned_of_bits_drop [simp]: - "unsigned_of_bits (drop n bs) = drop_bit n (unsigned_of_bits bs)" -proof (induction bs arbitrary: n) - case Nil - then show ?case - by simp -next - case (Cons b bs) - then show ?case - by (cases n) (simp_all add: drop_bit_Suc) -qed - -lemma bit_unsigned_of_bits_iff: - \bit (unsigned_of_bits bs) n \ nth_default False bs n\ -proof (induction bs arbitrary: n) - case Nil - then show ?case - by simp -next - case (Cons b bs) - then show ?case - by (cases n) (simp_all add: bit_Suc) -qed - -primrec n_bits_of :: "nat \ 'a \ bool list" - where - "n_bits_of 0 a = []" - | "n_bits_of (Suc n) a = odd a # n_bits_of n (a div 2)" - -lemma n_bits_of_eq_iff: - "n_bits_of n a = n_bits_of n b \ take_bit n a = take_bit n b" - apply (induction n arbitrary: a b) - apply (auto elim!: evenE oddE simp add: take_bit_Suc mod_2_eq_odd) - apply (metis dvd_triv_right even_plus_one_iff odd_iff_mod_2_eq_one) - apply (metis dvd_triv_right even_plus_one_iff odd_iff_mod_2_eq_one) - done - -lemma take_n_bits_of [simp]: - "take m (n_bits_of n a) = n_bits_of (min m n) a" -proof - - define q and v and w where "q = min m n" and "v = m - q" and "w = n - q" - then have "v = 0 \ w = 0" - by auto - then have "take (q + v) (n_bits_of (q + w) a) = n_bits_of q a" - by (induction q arbitrary: a) auto - with q_def v_def w_def show ?thesis - by simp -qed - -lemma unsigned_of_bits_n_bits_of [simp]: - "unsigned_of_bits (n_bits_of n a) = take_bit n a" - by (induction n arbitrary: a) (simp_all add: ac_simps take_bit_Suc mod_2_eq_odd) - -end - - -subsection \Syntactic bit representation\ - -class bit_representation = - fixes bits_of :: "'a \ bool list" - and of_bits :: "bool list \ 'a" - assumes of_bits_of [simp]: "of_bits (bits_of a) = a" - -instantiation nat :: bit_representation -begin - -fun bits_of_nat :: "nat \ bool list" - where "bits_of (n::nat) = - (if n = 0 then [] else odd n # bits_of (n div 2))" - -lemma bits_of_nat_simps [simp]: - "bits_of (0::nat) = []" - "n > 0 \ bits_of n = odd n # bits_of (n div 2)" for n :: nat - by simp_all - -declare bits_of_nat.simps [simp del] - -definition of_bits_nat :: "bool list \ nat" - where [simp]: "of_bits_nat = unsigned_of_bits" - \ \remove simp\ - -instance proof - show "of_bits (bits_of n) = n" for n :: nat - by (induction n rule: nat_bit_induct) simp_all -qed - -end - -lemma bit_of_bits_nat_iff: - \bit (of_bits bs :: nat) n \ nth_default False bs n\ - by (simp add: bit_unsigned_of_bits_iff) - -lemma bits_of_Suc_0 [simp]: - "bits_of (Suc 0) = [True]" - by simp - -lemma bits_of_1_nat [simp]: - "bits_of (1 :: nat) = [True]" - by simp - -lemma bits_of_nat_numeral_simps [simp]: - "bits_of (numeral Num.One :: nat) = [True]" (is ?One) - "bits_of (numeral (Num.Bit0 n) :: nat) = False # bits_of (numeral n :: nat)" (is ?Bit0) - "bits_of (numeral (Num.Bit1 n) :: nat) = True # bits_of (numeral n :: nat)" (is ?Bit1) -proof - - show ?One - by simp - define m :: nat where "m = numeral n" - then have "m > 0" and *: "numeral n = m" "numeral (Num.Bit0 n) = 2 * m" "numeral (Num.Bit1 n) = Suc (2 * m)" - by simp_all - from \m > 0\ show ?Bit0 ?Bit1 - by (simp_all add: *) -qed - -lemma unsigned_of_bits_of_nat [simp]: - "unsigned_of_bits (bits_of n) = n" for n :: nat - using of_bits_of [of n] by simp - -instantiation int :: bit_representation -begin - -fun bits_of_int :: "int \ bool list" - where "bits_of_int k = odd k # - (if k = 0 \ k = - 1 then [] else bits_of_int (k div 2))" - -lemma bits_of_int_simps [simp]: - "bits_of (0 :: int) = [False]" - "bits_of (- 1 :: int) = [True]" - "k \ 0 \ k \ - 1 \ bits_of k = odd k # bits_of (k div 2)" for k :: int - by simp_all - -lemma bits_of_not_Nil [simp]: - "bits_of k \ []" for k :: int - by simp - -declare bits_of_int.simps [simp del] - -definition of_bits_int :: "bool list \ int" - where "of_bits_int bs = (if bs = [] \ \ last bs then unsigned_of_bits bs - else unsigned_of_bits bs - 2 ^ length bs)" - -lemma of_bits_int_simps [simp]: - "of_bits [] = (0 :: int)" - "of_bits [False] = (0 :: int)" - "of_bits [True] = (- 1 :: int)" - "of_bits (bs @ [b]) = (unsigned_of_bits bs :: int) - (2 ^ length bs) * of_bool b" - "of_bits (False # bs) = 2 * (of_bits bs :: int)" - "bs \ [] \ of_bits (True # bs) = 1 + 2 * (of_bits bs :: int)" - by (simp_all add: of_bits_int_def push_bit_of_1) - -instance proof - show "of_bits (bits_of k) = k" for k :: int - by (induction k rule: int_bit_induct) simp_all -qed - -lemma bits_of_1_int [simp]: - "bits_of (1 :: int) = [True, False]" - by simp - -lemma bits_of_int_numeral_simps [simp]: - "bits_of (numeral Num.One :: int) = [True, False]" (is ?One) - "bits_of (numeral (Num.Bit0 n) :: int) = False # bits_of (numeral n :: int)" (is ?Bit0) - "bits_of (numeral (Num.Bit1 n) :: int) = True # bits_of (numeral n :: int)" (is ?Bit1) - "bits_of (- numeral (Num.Bit0 n) :: int) = False # bits_of (- numeral n :: int)" (is ?nBit0) - "bits_of (- numeral (Num.Bit1 n) :: int) = True # bits_of (- numeral (Num.inc n) :: int)" (is ?nBit1) -proof - - show ?One - by simp - define k :: int where "k = numeral n" - then have "k > 0" and *: "numeral n = k" "numeral (Num.Bit0 n) = 2 * k" "numeral (Num.Bit1 n) = 2 * k + 1" - "numeral (Num.inc n) = k + 1" - by (simp_all add: add_One) - have "- (2 * k) div 2 = - k" "(- (2 * k) - 1) div 2 = - k - 1" - by simp_all - with \k > 0\ show ?Bit0 ?Bit1 ?nBit0 ?nBit1 - by (simp_all add: *) -qed - -lemma bit_of_bits_int_iff: - \bit (of_bits bs :: int) n \ nth_default (bs \ [] \ last bs) bs n\ -proof (induction bs arbitrary: n) - case Nil - then show ?case - by simp -next - case (Cons b bs) - then show ?case - by (cases n; cases b; cases bs) (simp_all add: bit_Suc) -qed - -lemma of_bits_append [simp]: - "of_bits (bs @ cs) = of_bits bs + push_bit (length bs) (of_bits cs :: int)" - if "bs \ []" "\ last bs" -using that proof (induction bs rule: list_nonempty_induct) - case (single b) - then show ?case - by simp -next - case (cons b bs) - then show ?case - by (cases b) (simp_all add: push_bit_double) -qed - -lemma of_bits_replicate_False [simp]: - "of_bits (replicate n False) = (0 :: int)" - by (auto simp add: of_bits_int_def) - -lemma of_bits_drop [simp]: - "of_bits (drop n bs) = drop_bit n (of_bits bs :: int)" - if "n < length bs" -using that proof (induction bs arbitrary: n) - case Nil - then show ?case - by simp -next - case (Cons b bs) - show ?case - proof (cases n) - case 0 - then show ?thesis - by simp - next - case (Suc n) - with Cons.prems have "bs \ []" - by auto - with Suc Cons.IH [of n] Cons.prems show ?thesis - by (cases b) (simp_all add: drop_bit_Suc) - qed -qed - -end - -lemma unsigned_of_bits_eq_of_bits: - "unsigned_of_bits bs = (of_bits (bs @ [False]) :: int)" - by (simp add: of_bits_int_def) - -unbundle word.lifting - -instantiation word :: (len) bit_representation -begin - -lift_definition bits_of_word :: "'a word \ bool list" - is "n_bits_of LENGTH('a)" - by (simp add: n_bits_of_eq_iff) - -lift_definition of_bits_word :: "bool list \ 'a word" - is unsigned_of_bits . - -instance proof - fix a :: "'a word" - show "of_bits (bits_of a) = a" - by transfer simp -qed - -end - -lifting_update word.lifting -lifting_forget word.lifting - - -subsection \Bit representations with bit operations\ - -class semiring_bit_representation = semiring_bit_operations + bit_representation - opening bit_operations_syntax + - assumes and_eq: "length bs = length cs \ - of_bits bs AND of_bits cs = of_bits (map2 (\) bs cs)" - and or_eq: "length bs = length cs \ - of_bits bs OR of_bits cs = of_bits (map2 (\) bs cs)" - and xor_eq: "length bs = length cs \ - of_bits bs XOR of_bits cs = of_bits (map2 (\) bs cs)" - and push_bit_eq: "push_bit n a = of_bits (replicate n False @ bits_of a)" - and drop_bit_eq: "n < length (bits_of a) \ drop_bit n a = of_bits (drop n (bits_of a))" - -class ring_bit_representation = ring_bit_operations + semiring_bit_representation + - assumes not_eq: "not = of_bits \ map Not \ bits_of" - -instance nat :: semiring_bit_representation - by standard (simp_all add: bit_eq_iff bit_unsigned_of_bits_iff nth_default_map2 [of _ _ _ False False] - bit_and_iff bit_or_iff bit_xor_iff) - -instance int :: ring_bit_representation -including bit_operations_syntax proof - { - fix bs cs :: \bool list\ - assume \length bs = length cs\ - then have \cs = [] \ bs = []\ - by auto - with \length bs = length cs\ have \zip bs cs \ [] \ last (map2 (\) bs cs) \ (bs \ [] \ last bs) \ (cs \ [] \ last cs)\ - and \zip bs cs \ [] \ last (map2 (\) bs cs) \ (bs \ [] \ last bs) \ (cs \ [] \ last cs)\ - and \zip bs cs \ [] \ last (map2 (\) bs cs) \ ((bs \ [] \ last bs) \ (cs \ [] \ last cs))\ - by (auto simp add: last_map last_zip zip_eq_Nil_iff prod_eq_iff) - then show \of_bits bs AND of_bits cs = (of_bits (map2 (\) bs cs) :: int)\ - and \of_bits bs OR of_bits cs = (of_bits (map2 (\) bs cs) :: int)\ - and \of_bits bs XOR of_bits cs = (of_bits (map2 (\) bs cs) :: int)\ - by (simp_all add: fun_eq_iff bit_eq_iff bit_and_iff bit_or_iff bit_xor_iff bit_not_iff bit_of_bits_int_iff \length bs = length cs\ nth_default_map2 [of bs cs _ \bs \ [] \ last bs\ \cs \ [] \ last cs\]) - } - show \push_bit n k = of_bits (replicate n False @ bits_of k)\ - for k :: int and n :: nat - by (cases "n = 0") simp_all - show \drop_bit n k = of_bits (drop n (bits_of k))\ - if \n < length (bits_of k)\ for k :: int and n :: nat - using that by simp - show \(not :: int \ _) = of_bits \ map Not \ bits_of\ - proof (rule sym, rule ext) - fix k :: int - show \(of_bits \ map Not \ bits_of) k = NOT k\ - by (induction k rule: int_bit_induct) (simp_all add: not_int_def) - qed -qed - -end diff -r 6c7feeef0ff2 -r 58e208ad4bcf src/Tools/Haskell/Haskell.thy --- a/src/Tools/Haskell/Haskell.thy Tue Aug 03 10:14:48 2021 +0200 +++ b/src/Tools/Haskell/Haskell.thy Wed Aug 04 08:27:16 2021 +0200 @@ -1521,9 +1521,9 @@ Name, T, names, none, make, markup_element, markup_report, make_report ) where -import Isabelle.Library import qualified Isabelle.Bytes as Bytes -import Isabelle.Bytes (Bytes) +import qualified Isabelle.Name as Name +import Isabelle.Name (Name) import qualified Isabelle.Properties as Properties import qualified Isabelle.Markup as Markup import qualified Isabelle.XML.Encode as Encode @@ -1531,26 +1531,19 @@ import qualified Isabelle.YXML as YXML -type Name = (Bytes, (Bytes, Bytes)) -- external name, kind, internal name -data T = Completion Properties.T Int [Name] -- position, total length, names - -names :: Int -> Properties.T -> [Name] -> T +type Names = [(Name, (Name, Name))] -- external name, kind, internal name +data T = Completion Properties.T Int Names -- position, total length, names + +names :: Int -> Properties.T -> Names -> T names limit props names = Completion props (length names) (take limit names) none :: T none = names 0 [] [] -clean_name :: Bytes -> Bytes -clean_name bs = - if not (Bytes.null bs) && Bytes.last bs == u then - Bytes.unpack bs |> reverse |> dropWhile (== u) |> reverse |> Bytes.pack - else bs - where u = Bytes.byte '_' - -make :: Int -> (Bytes, Properties.T) -> ((Bytes -> Bool) -> [Name]) -> T +make :: Int -> (Name, Properties.T) -> ((Name -> Bool) -> Names) -> T make limit (name, props) make_names = if name /= "" && name /= "_" then - names limit props (make_names (Bytes.isPrefixOf (clean_name name))) + names limit props (make_names (Bytes.isPrefixOf (Name.clean name))) else none markup_element :: T -> (Markup.T, XML.Body) @@ -1565,12 +1558,12 @@ in (markup, body) else (Markup.empty, []) -markup_report :: [T] -> Bytes +markup_report :: [T] -> Name markup_report [] = Bytes.empty markup_report elems = YXML.string_of $ XML.Elem (Markup.report, map (XML.Elem . markup_element) elems) -make_report :: Int -> (Bytes, Properties.T) -> ((Bytes -> Bool) -> [Name]) -> Bytes +make_report :: Int -> (Name, Properties.T) -> ((Name -> Bool) -> Names) -> Name make_report limit name_props make_names = markup_report [make limit name_props make_names] \ @@ -1760,6 +1753,100 @@ big_list name prts = block (fbreaks (str name : prts)) \ +generate_file "Isabelle/Name.hs" = \ +{- Title: Isabelle/Name.hs + Author: Makarius + +Names of basic logical entities (variables etc.). + +See also \<^file>\$ISABELLE_HOME/src/Pure/name.ML\. +-} + +{-# LANGUAGE OverloadedStrings #-} + +module Isabelle.Name ( + Name, clean_index, clean, + Context, declare, is_declared, context, make_context, variant +) +where + +import Data.Word (Word8) +import qualified Data.Set as Set +import Data.Set (Set) +import qualified Isabelle.Bytes as Bytes +import Isabelle.Bytes (Bytes) +import qualified Isabelle.Symbol as Symbol +import Isabelle.Library + + +type Name = Bytes + + +{- suffix for internal names -} + +underscore :: Word8 +underscore = Bytes.byte '_' + +clean_index :: Name -> (Name, Int) +clean_index x = + if Bytes.null x || Bytes.last x /= underscore then (x, 0) + else + let + rev = reverse (Bytes.unpack x) + n = length (takeWhile (== underscore) rev) + y = Bytes.pack (reverse (drop n rev)) + in (y, n) + +clean :: Name -> Name +clean = fst . clean_index + + +{- context for used names -} + +data Context = Context (Set Name) + +declare :: Name -> Context -> Context +declare x (Context names) = Context (Set.insert x names) + +is_declared :: Context -> Name -> Bool +is_declared (Context names) x = Set.member x names + +context :: Context +context = Context (Set.fromList ["", "'"]) + +make_context :: [Name] -> Context +make_context used = fold declare used context + + +{- generating fresh names -} + +bump_init :: Name -> Name +bump_init str = str <> "a" + +bump_string :: Name -> Name +bump_string str = + let + a = Bytes.byte 'a' + z = Bytes.byte 'z' + bump (b : bs) | b == z = a : bump bs + bump (b : bs) | a <= b && b < z = b + 1 : bs + bump bs = a : bs + + rev = reverse (Bytes.unpack str) + part2 = reverse (takeWhile (Symbol.is_ascii_quasi . Bytes.char) rev) + part1 = reverse (bump (drop (length part2) rev)) + in Bytes.pack (part1 <> part2) + +variant :: Name -> Context -> (Name, Context) +variant name names = + let + vary bump x = if is_declared names x then bump x |> vary bump_string else x + (x, n) = clean_index name + x' = x |> vary bump_init + names' = declare x' names; + in (x' <> Bytes.pack (replicate n underscore), names') +\ + generate_file "Isabelle/Term.hs" = \ {- Title: Isabelle/Term.hs Author: Makarius @@ -1773,14 +1860,17 @@ {-# LANGUAGE OverloadedStrings #-} module Isabelle.Term ( - Name, Indexname, Sort, Typ(..), Term(..), Free, + Indexname, Sort, Typ(..), Term(..), + Free, lambda, declare_frees, incr_boundvars, subst_bound, dest_abs, type_op0, type_op1, op0, op1, op2, typed_op2, binder, dummyS, dummyT, is_dummyT, propT, is_propT, (-->), dest_funT, (--->), - aconv, list_comb, strip_comb, head_of, lambda + aconv, list_comb, strip_comb, head_of ) where -import Isabelle.Bytes (Bytes) +import Isabelle.Library +import qualified Isabelle.Name as Name +import Isabelle.Name (Name) infixr 5 --> infixr ---> @@ -1788,8 +1878,6 @@ {- types and terms -} -type Name = Bytes - type Indexname = (Name, Int) type Sort = [Name] @@ -1809,8 +1897,52 @@ | App (Term, Term) deriving (Show, Eq, Ord) + +{- free and bound variables -} + type Free = (Name, Typ) +lambda :: Free -> Term -> Term +lambda (name, typ) body = Abs (name, typ, abstract 0 body) + where + abstract lev (Free (x, ty)) | name == x && typ == ty = Bound lev + abstract lev (Abs (a, ty, t)) = Abs (a, ty, abstract (lev + 1) t) + abstract lev (App (t, u)) = App (abstract lev t, abstract lev u) + abstract _ t = t + +declare_frees :: Term -> Name.Context -> Name.Context +declare_frees (Free (x, _)) = Name.declare x +declare_frees (Abs (_, _, b)) = declare_frees b +declare_frees (App (t, u)) = declare_frees t #> declare_frees u +declare_frees _ = id + +incr_boundvars :: Int -> Term -> Term +incr_boundvars inc = if inc == 0 then id else incr 0 + where + incr lev (Bound i) = if i >= lev then Bound (i + inc) else Bound i + incr lev (Abs (a, ty, b)) = Abs (a, ty, incr (lev + 1) b) + incr lev (App (t, u)) = App (incr lev t, incr lev u) + incr _ t = t + +subst_bound :: Term -> Term -> Term +subst_bound arg = subst 0 + where + subst lev (Bound i) = + if i < lev then Bound i + else if i == lev then incr_boundvars lev arg + else Bound (i - 1) + subst lev (Abs (a, ty, b)) = Abs (a, ty, subst (lev + 1) b) + subst lev (App (t, u)) = App (subst lev t, subst lev u) + subst _ t = t + +dest_abs :: Name.Context -> Term -> Maybe (Free, Term) +dest_abs names (Abs (x, ty, b)) = + let + (x', _) = Name.variant x (declare_frees b names) + v = (x', ty) + in Just (v, subst_bound (Free v) b) +dest_abs _ _ = Nothing + {- type and term operators -} @@ -1906,14 +2038,6 @@ head_of :: Term -> Term head_of (App (f, _)) = head_of f head_of u = u - -lambda :: Free -> Term -> Term -lambda (name, typ) body = Abs (name, typ, abstract 0 body) - where - abstract lev (Free (x, ty)) | name == x && typ == ty = Bound lev - abstract lev (Abs (a, ty, t)) = Abs (a, ty, abstract (lev + 1) t) - abstract lev (App (t, u)) = App (abstract lev t, abstract lev u) - abstract _ t = t \ generate_file "Isabelle/Pure.hs" = \