diff -r febdd4eead56 -r a851ce626b78 src/HOL/Library/Bit_Operations.thy --- a/src/HOL/Library/Bit_Operations.thy Sat Jul 11 06:21:02 2020 +0000 +++ b/src/HOL/Library/Bit_Operations.thy Sat Jul 11 06:21:04 2020 +0000 @@ -9,6 +9,43 @@ Main begin +subsection \Preliminiaries\ \ \TODO move\ + +lemma take_bit_int_less_exp: + \take_bit n k < 2 ^ n\ for k :: int + by (simp add: take_bit_eq_mod) + +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_greater_eq: + \k + 2 ^ n \ take_bit n k\ if \k < 0\ for k :: int +proof - + have \k + 2 ^ n \ take_bit n (k + 2 ^ n)\ + proof (cases \k > - (2 ^ n)\) + case False + then have \k + 2 ^ n \ 0\ + by simp + also note take_bit_nonnegative + finally show ?thesis . + next + case True + with that have \0 \ k + 2 ^ n\ and \k + 2 ^ n < 2 ^ n\ + by simp_all + then show ?thesis + by (simp only: take_bit_eq_mod mod_pos_pos_trivial) + qed + then show ?thesis + by (simp add: take_bit_eq_mod) +qed + +lemma take_bit_less_eq: + \take_bit n k \ k - 2 ^ n\ if \2 ^ n \ k\ and \n > 0\ for k :: int + using that zmod_le_nonneg_dividend [of \k - 2 ^ n\ \2 ^ n\] + by (simp add: take_bit_eq_mod) + + subsection \Bit operations\ class semiring_bit_operations = semiring_bit_shifts + @@ -240,29 +277,17 @@ \take_bit n (- 1) = mask n\ by (simp add: bit_eq_iff bit_mask_iff bit_take_bit_iff conj_commute) +lemma minus_exp_eq_not_mask: + \- (2 ^ n) = NOT (mask n)\ + by (rule bit_eqI) (simp add: bit_minus_iff bit_not_iff flip: mask_eq_exp_minus_1) + lemma push_bit_minus_one_eq_not_mask: \push_bit n (- 1) = NOT (mask n)\ -proof (rule bit_eqI) - fix m - assume \2 ^ m \ 0\ - show \bit (push_bit n (- 1)) m \ bit (NOT (mask n)) m\ - proof (cases \n \ m\) - case True - moreover define q where \q = m - n\ - ultimately have \m = n + q\ \m - n = q\ - by simp_all - with \2 ^ m \ 0\ have \2 ^ n * 2 ^ q \ 0\ - by (simp add: power_add) - then have \2 ^ q \ 0\ - using mult_not_zero by blast - with \m - n = q\ show ?thesis - by (auto simp add: bit_not_iff bit_mask_iff bit_push_bit_iff not_less) - next - case False - then show ?thesis - by (simp add: bit_not_iff bit_mask_iff bit_push_bit_iff not_le) - qed -qed + by (simp add: push_bit_eq_mult minus_exp_eq_not_mask) + +lemma take_bit_not_mask_eq_0: + \take_bit m (NOT (mask n)) = 0\ if \n \ m\ + by (rule bit_eqI) (use that in \simp add: bit_take_bit_iff bit_not_iff bit_mask_iff\) definition set_bit :: \nat \ 'a \ 'a\ where \set_bit n a = a OR push_bit n 1\ @@ -645,6 +670,10 @@ \k XOR l < 0 \ (k < 0) \ (l < 0)\ for k l :: int by (subst Not_eq_iff [symmetric]) (auto simp add: not_less) +lemma mask_nonnegative: + \(mask n :: int) \ 0\ + by (simp add: mask_eq_exp_minus_1) + lemma set_bit_nonnegative_int_iff [simp]: \set_bit n k \ 0 \ k \ 0\ for k :: int by (simp add: set_bit_def) @@ -724,6 +753,194 @@ qed +subsection \Taking bit with sign propagation\ + +definition signed_take_bit :: "nat \ int \ int" + where \signed_take_bit n k = take_bit n k OR (NOT (mask n) * of_bool (bit k n))\ + +lemma signed_take_bit_eq: + \signed_take_bit n k = take_bit n k\ if \\ bit k n\ + using that by (simp add: signed_take_bit_def) + +lemma signed_take_bit_eq_or: + \signed_take_bit n k = take_bit n k OR NOT (mask n)\ if \bit k n\ + using that by (simp add: signed_take_bit_def) + +lemma signed_take_bit_0 [simp]: + \signed_take_bit 0 k = - (k mod 2)\ + by (simp add: signed_take_bit_def odd_iff_mod_2_eq_one) + +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) + +lemma signed_take_bit_Suc: + \signed_take_bit (Suc n) k = k mod 2 + 2 * signed_take_bit n (k div 2)\ + by (unfold signed_take_bit_def or_int_rec [of \take_bit (Suc n) k\]) + (simp add: bit_Suc take_bit_Suc even_or_iff even_mask_iff odd_iff_mod_2_eq_one not_int_div_2 mask_half_int) + +lemma signed_take_bit_rec: + \signed_take_bit n k = (if n = 0 then - (k mod 2) else k mod 2 + 2 * signed_take_bit (n - 1) (k div 2))\ + by (cases n) (simp_all add: signed_take_bit_Suc) + +lemma bit_signed_take_bit_iff: + \bit (signed_take_bit m k) n = bit k (min m n)\ + by (simp add: signed_take_bit_def bit_or_iff bit_take_bit_iff bit_not_iff bit_mask_iff min_def) + +text \Modulus centered around 0\ + +lemma signed_take_bit_eq_take_bit_minus: + \signed_take_bit n k = take_bit (Suc n) k - 2 ^ Suc n * of_bool (bit k n)\ +proof (cases \bit k n\) + case True + have \signed_take_bit n k = take_bit (Suc n) k OR NOT (mask (Suc n))\ + by (rule bit_eqI) (auto simp add: bit_signed_take_bit_iff min_def bit_take_bit_iff bit_or_iff bit_not_iff bit_mask_iff less_Suc_eq True) + then have \signed_take_bit n k = take_bit (Suc n) k + NOT (mask (Suc n))\ + by (simp add: disjunctive_add bit_take_bit_iff bit_not_iff bit_mask_iff) + with True show ?thesis + by (simp flip: minus_exp_eq_not_mask) +next + case False + then show ?thesis + by (simp add: bit_eq_iff bit_take_bit_iff bit_signed_take_bit_iff min_def) + (auto intro: bit_eqI simp add: less_Suc_eq) +qed + +lemma signed_take_bit_eq_take_bit_shift: + \signed_take_bit n k = take_bit (Suc n) (k + 2 ^ n) - 2 ^ n\ +proof - + have *: \take_bit n k OR 2 ^ n = take_bit n k + 2 ^ n\ + by (simp add: disjunctive_add bit_exp_iff bit_take_bit_iff) + have \take_bit n k - 2 ^ n = take_bit n k + NOT (mask n)\ + by (simp add: minus_exp_eq_not_mask) + also have \\ = take_bit n k OR NOT (mask n)\ + by (rule disjunctive_add) + (simp add: bit_exp_iff bit_take_bit_iff bit_not_iff bit_mask_iff) + finally have **: \take_bit n k - 2 ^ n = take_bit n k OR NOT (mask n)\ . + have \take_bit (Suc n) (k + 2 ^ n) = take_bit (Suc n) (take_bit (Suc n) k + take_bit (Suc n) (2 ^ n))\ + by (simp only: take_bit_add) + also have \take_bit (Suc n) k = 2 ^ n * of_bool (bit k n) + take_bit n k\ + by (simp add: take_bit_Suc_from_most) + finally have \take_bit (Suc n) (k + 2 ^ n) = take_bit (Suc n) (2 ^ (n + of_bool (bit k n)) + take_bit n k)\ + by (simp add: ac_simps) + also have \2 ^ (n + of_bool (bit k n)) + take_bit n k = 2 ^ (n + of_bool (bit k n)) OR take_bit n k\ + by (rule disjunctive_add) + (auto simp add: disjunctive_add bit_take_bit_iff bit_double_iff bit_exp_iff) + finally show ?thesis + using * ** by (simp add: signed_take_bit_def take_bit_Suc min_def ac_simps) +qed + +lemma signed_take_bit_of_0 [simp]: + \signed_take_bit n 0 = 0\ + by (simp add: signed_take_bit_def) + +lemma signed_take_bit_of_minus_1 [simp]: + \signed_take_bit n (- 1) = - 1\ + by (simp add: signed_take_bit_def take_bit_minus_one_eq_mask) + +lemma signed_take_bit_eq_iff_take_bit_eq: + \signed_take_bit n k = signed_take_bit n l \ take_bit (Suc n) k = take_bit (Suc n) l\ +proof (cases \bit k n \ bit l n\) + case True + moreover have \take_bit n k OR NOT (mask n) = take_bit n k - 2 ^ n\ + for k :: int + by (auto simp add: disjunctive_add [symmetric] bit_not_iff bit_mask_iff bit_take_bit_iff minus_exp_eq_not_mask) + ultimately show ?thesis + by (simp add: signed_take_bit_def take_bit_Suc_from_most) +next + case False + then have \signed_take_bit n k \ signed_take_bit n l\ and \take_bit (Suc n) k \ take_bit (Suc n) l\ + by (auto simp add: bit_eq_iff bit_take_bit_iff bit_signed_take_bit_iff min_def) + then show ?thesis + by simp +qed + +lemma signed_take_bit_signed_take_bit [simp]: + \signed_take_bit m (signed_take_bit n k) = signed_take_bit (min m n) k\ + by (rule bit_eqI) (auto simp add: bit_signed_take_bit_iff min_def bit_or_iff bit_not_iff bit_mask_iff bit_take_bit_iff) + +lemma take_bit_signed_take_bit: + \take_bit m (signed_take_bit n k) = take_bit m k\ if \m \ n\ + using that by (auto simp add: bit_eq_iff bit_take_bit_iff bit_signed_take_bit_iff min_def) + +lemma take_bit_Suc_signed_take_bit [simp]: + \take_bit (Suc n) (signed_take_bit n a) = take_bit (Suc n) a\ + by (rule bit_eqI) (auto simp add: bit_take_bit_iff bit_signed_take_bit_iff min_def less_Suc_eq) + +lemma signed_take_bit_take_bit: + \signed_take_bit m (take_bit n k) = (if n \ m then take_bit n else signed_take_bit m) k\ + by (rule bit_eqI) (auto simp add: bit_signed_take_bit_iff min_def bit_take_bit_iff) + +lemma signed_take_bit_nonnegative_iff [simp]: + \0 \ signed_take_bit n k \ \ bit k n\ + by (simp add: signed_take_bit_def not_less mask_nonnegative) + +lemma signed_take_bit_negative_iff [simp]: + \signed_take_bit n k < 0 \ bit k n\ + by (simp add: signed_take_bit_def not_less mask_nonnegative) + +lemma signed_take_bit_greater_eq: + \k + 2 ^ Suc n \ signed_take_bit n k\ if \k < - (2 ^ n)\ + using that take_bit_greater_eq [of \k + 2 ^ n\ \Suc n\] + by (simp add: signed_take_bit_eq_take_bit_shift) + +lemma signed_take_bit_less_eq: + \signed_take_bit n k \ k - 2 ^ Suc n\ if \k \ 2 ^ n\ + using that take_bit_less_eq [of \Suc n\ \k + 2 ^ n\] + by (simp add: signed_take_bit_eq_take_bit_shift) + +lemma signed_take_bit_Suc_1 [simp]: + \signed_take_bit (Suc n) 1 = 1\ + by (simp add: signed_take_bit_Suc) + +lemma signed_take_bit_Suc_bit0 [simp]: + \signed_take_bit (Suc n) (numeral (Num.Bit0 k)) = signed_take_bit n (numeral k) * 2\ + by (simp add: signed_take_bit_Suc) + +lemma signed_take_bit_Suc_bit1 [simp]: + \signed_take_bit (Suc n) (numeral (Num.Bit1 k)) = signed_take_bit n (numeral k) * 2 + 1\ + by (simp add: signed_take_bit_Suc) + +lemma signed_take_bit_Suc_minus_bit0 [simp]: + \signed_take_bit (Suc n) (- numeral (Num.Bit0 k)) = signed_take_bit n (- numeral k) * 2\ + by (simp add: signed_take_bit_Suc) + +lemma signed_take_bit_Suc_minus_bit1 [simp]: + \signed_take_bit (Suc n) (- numeral (Num.Bit1 k)) = signed_take_bit n (- numeral k - 1) * 2 + 1\ + by (simp add: signed_take_bit_Suc) + +lemma signed_take_bit_numeral_bit0 [simp]: + \signed_take_bit (numeral l) (numeral (Num.Bit0 k)) = signed_take_bit (pred_numeral l) (numeral k) * 2\ + by (simp add: signed_take_bit_rec) + +lemma signed_take_bit_numeral_bit1 [simp]: + \signed_take_bit (numeral l) (numeral (Num.Bit1 k)) = signed_take_bit (pred_numeral l) (numeral k) * 2 + 1\ + by (simp add: signed_take_bit_rec) + +lemma signed_take_bit_numeral_minus_bit0 [simp]: + \signed_take_bit (numeral l) (- numeral (Num.Bit0 k)) = signed_take_bit (pred_numeral l) (- numeral k) * 2\ + by (simp add: signed_take_bit_rec) + +lemma signed_take_bit_numeral_minus_bit1 [simp]: + \signed_take_bit (numeral l) (- numeral (Num.Bit1 k)) = signed_take_bit (pred_numeral l) (- numeral k - 1) * 2 + 1\ + by (simp add: signed_take_bit_rec) + +lemma signed_take_bit_code [code]: + \signed_take_bit n k = + (let l = k AND mask (Suc n) + in if bit l n then l - (push_bit n 2) else l)\ +proof - + have *: \(k AND mask (Suc n)) - 2 * 2 ^ n = k AND mask (Suc n) OR NOT (mask (Suc n))\ + apply (subst disjunctive_add [symmetric]) + apply (simp_all add: bit_and_iff bit_mask_iff bit_not_iff) + apply (simp flip: minus_exp_eq_not_mask) + done + show ?thesis + by (rule bit_eqI) + (auto simp add: Let_def bit_and_iff bit_signed_take_bit_iff push_bit_eq_mult min_def not_le bit_mask_iff bit_exp_iff less_Suc_eq * bit_or_iff bit_not_iff) +qed + + subsection \Instance \<^typ>\nat\\ instantiation nat :: semiring_bit_operations