Theory Bit_Comprehension_Int
section ‹Comprehension syntax for ‹int››
theory Bit_Comprehension_Int
imports
Bit_Comprehension
begin
instantiation int :: bit_comprehension
begin
definition
‹set_bits f = (
if ∃n. ∀m≥n. f m = f n then
let n = LEAST n. ∀m≥n. f m = f n
in signed_take_bit n (horner_sum of_bool 2 (map f [0..<Suc n]))
else 0 :: int)›
instance proof
fix k :: int
from int_bit_bound [of k]
obtain n where *: ‹⋀m. n ≤ m ⟹ bit k m ⟷ bit k n›
and **: ‹n > 0 ⟹ bit k (n - 1) ≠ bit k n›
by blast
have l: ‹(LEAST q. ∀m≥q. bit k m ⟷ bit k q) = n›
proof (rule Least_equality)
show "∀m≥n. bit k m = bit k n"
using * by blast
show "⋀y. ∀m≥y. bit k m = bit k y ⟹ n ≤ y"
by (metis "**" One_nat_def Suc_pred le_cases le0 neq0_conv not_less_eq_eq)
qed
have "signed_take_bit n (take_bit (Suc n) k) = k"
apply (rule bit_eqI)
by (metis "*" bit_signed_take_bit_iff bit_take_bit_iff leI lessI less_SucI min.absorb4 min.order_iff)
then show ‹set_bits (bit k) = k›
unfolding * set_bits_int_def horner_sum_bit_eq_take_bit l
using "*" by auto
qed
end
lemma int_set_bits_K_False [simp]: "(BITS _. False) = (0 :: int)"
by (simp add: set_bits_int_def)
lemma int_set_bits_K_True [simp]: "(BITS _. True) = (-1 :: int)"
by (simp add: set_bits_int_def)
lemma set_bits_code [code]:
"set_bits = Code.abort (STR ''set_bits is unsupported on type int'') (λ_. set_bits :: _ ⇒ int)"
by simp
lemma set_bits_int_unfold':
‹set_bits f =
(if ∃n. ∀n'≥n. ¬ f n' then
let n = LEAST n. ∀n'≥n. ¬ f n'
in horner_sum of_bool 2 (map f [0..<n])
else if ∃n. ∀n'≥n. f n' then
let n = LEAST n. ∀n'≥n. f n'
in signed_take_bit n (horner_sum of_bool 2 (map f [0..<n] @ [True]))
else 0 :: int)›
proof (cases ‹∃n. ∀m≥n. f m ⟷ f n›)
case True
then obtain q where q: ‹∀m≥q. f m ⟷ f q›
by blast
define n where ‹n = (LEAST n. ∀m≥n. f m ⟷ f n)›
have ‹∀m≥n. f m ⟷ f n›
unfolding n_def
using q by (rule LeastI [of _ q])
then have n: ‹⋀m. n ≤ m ⟹ f m ⟷ f n›
by blast
from n_def have n_eq: ‹(LEAST q. ∀m≥q. f m ⟷ f n) = n›
by (smt (verit, best) Least_le ‹∀m≥n. f m = f n› dual_order.antisym wellorder_Least_lemma(1))
show ?thesis
proof (cases ‹f n›)
case False
with n have *: ‹∃n. ∀n'≥n. ¬ f n'›
by blast
have **: ‹(LEAST n. ∀n'≥n. ¬ f n') = n›
using False n_eq by simp
from * False show ?thesis
unfolding set_bits_int_def n_def [symmetric] **
by (auto simp add: take_bit_horner_sum_bit_eq bit_horner_sum_bit_iff take_map
signed_take_bit_def set_bits_int_def horner_sum_bit_eq_take_bit simp del: upt.upt_Suc)
next
case True
with n obtain *: ‹∃n. ∀n'≥n. f n'› ‹¬ (∃n. ∀n'≥n. ¬ f n')›
by (metis linorder_linear)
have **: ‹(LEAST n. ∀n'≥n. f n') = n›
using True n_eq by simp
from * True show ?thesis
unfolding set_bits_int_def n_def [symmetric] **
by (auto simp add: take_bit_horner_sum_bit_eq
bit_horner_sum_bit_iff take_map
signed_take_bit_def set_bits_int_def
horner_sum_bit_eq_take_bit nth_append simp del: upt.upt_Suc)
qed
next
case False
then show ?thesis
by (auto simp add: set_bits_int_def)
qed
inductive wf_set_bits_int :: "(nat ⇒ bool) ⇒ bool"
for f :: "nat ⇒ bool"
where
zeros: "∀n' ≥ n. ¬ f n' ⟹ wf_set_bits_int f"
| ones: "∀n' ≥ n. f n' ⟹ wf_set_bits_int f"
lemma wf_set_bits_int_simps: "wf_set_bits_int f ⟷ (∃n. (∀n'≥n. ¬ f n') ∨ (∀n'≥n. f n'))"
by(auto simp add: wf_set_bits_int.simps)
lemma wf_set_bits_int_const [simp]: "wf_set_bits_int (λ_. b)"
by(cases b)(auto intro: wf_set_bits_int.intros)
lemma wf_set_bits_int_fun_upd [simp]:
"wf_set_bits_int (f(n := b)) ⟷ wf_set_bits_int f" (is "?lhs ⟷ ?rhs")
proof
assume ?lhs
then obtain n'
where "(∀n''≥n'. ¬ (f(n := b)) n'') ∨ (∀n''≥n'. (f(n := b)) n'')"
by(auto simp add: wf_set_bits_int_simps)
hence "(∀n''≥max (Suc n) n'. ¬ f n'') ∨ (∀n''≥max (Suc n) n'. f n'')" by auto
thus ?rhs by(auto simp only: wf_set_bits_int_simps)
next
assume ?rhs
then obtain n' where "(∀n''≥n'. ¬ f n'') ∨ (∀n''≥n'. f n'')" (is "?wf f n'")
by(auto simp add: wf_set_bits_int_simps)
hence "?wf (f(n := b)) (max (Suc n) n')" by auto
thus ?lhs by(auto simp only: wf_set_bits_int_simps)
qed
lemma wf_set_bits_int_Suc [simp]:
"wf_set_bits_int (λn. f (Suc n)) ⟷ wf_set_bits_int f" (is "?lhs ⟷ ?rhs")
by(auto simp add: wf_set_bits_int_simps intro: le_SucI dest: Suc_le_D)
context
fixes f
assumes wff: "wf_set_bits_int f"
begin
lemma int_set_bits_unfold_BIT:
"set_bits f = of_bool (f 0) + (2 :: int) * set_bits (f ∘ Suc)"
using wff proof cases
case (zeros n)
show ?thesis
proof(cases "∀n. ¬ f n")
case True
hence "f = (λ_. False)" by auto
thus ?thesis using True by(simp add: o_def)
next
case False
then obtain n' where "f n'" by blast
with zeros have "(LEAST n. ∀n'≥n. ¬ f n') = Suc (LEAST n. ∀n'≥Suc n. ¬ f n')"
by(auto intro: Least_Suc)
also have "(λn. ∀n'≥Suc n. ¬ f n') = (λn. ∀n'≥n. ¬ f (Suc n'))" by(auto dest: Suc_le_D)
also from zeros have "∀n'≥n. ¬ f (Suc n')" by auto
ultimately show ?thesis using zeros
apply (simp (no_asm_simp) add: set_bits_int_unfold' exI
del: upt.upt_Suc flip: map_map split del: if_split)
apply (simp only: map_Suc_upt upt_conv_Cons)
apply simp
done
qed
next
case (ones n)
show ?thesis
proof(cases "∀n. f n")
case True
hence "f = (λ_. True)" by auto
thus ?thesis using True by(simp add: o_def)
next
case False
then obtain n' where "¬ f n'" by blast
with ones have "(LEAST n. ∀n'≥n. f n') = Suc (LEAST n. ∀n'≥Suc n. f n')"
by(auto intro: Least_Suc)
also have "(λn. ∀n'≥Suc n. f n') = (λn. ∀n'≥n. f (Suc n'))" by(auto dest: Suc_le_D)
also from ones have "∀n'≥n. f (Suc n')" by auto
moreover from ones have "(∃n. ∀n'≥n. ¬ f n') = False"
by(auto intro!: exI[where x="max n m" for n m] simp add: max_def split: if_split_asm)
moreover hence "(∃n. ∀n'≥n. ¬ f (Suc n')) = False"
by(auto elim: allE[where x="Suc n" for n] dest: Suc_le_D)
ultimately show ?thesis using ones
apply (simp (no_asm_simp) add: set_bits_int_unfold' exI split del: if_split)
apply (auto simp add: Let_def hd_map map_tl[symmetric] map_map[symmetric] map_Suc_upt upt_conv_Cons signed_take_bit_Suc
not_le simp del: map_map)
done
qed
qed
lemma bin_last_set_bits [simp]:
"odd (set_bits f :: int) = f 0"
by (subst int_set_bits_unfold_BIT) simp_all
lemma bin_rest_set_bits [simp]:
"set_bits f div (2 :: int) = set_bits (f ∘ Suc)"
by (subst int_set_bits_unfold_BIT) simp_all
lemma bin_nth_set_bits [simp]:
"bit (set_bits f :: int) m ⟷ f m"
using wff proof (induction m arbitrary: f)
case 0
then show ?case
by (simp add: Bit_Comprehension_Int.bin_last_set_bits bit_0)
next
case Suc
from Suc.IH [of "f ∘ Suc"] Suc.prems show ?case
by (simp add: Bit_Comprehension_Int.bin_rest_set_bits comp_def bit_Suc)
qed
end
end