Theory Karatsuba_Code_Nat
section "Code Generation"
theory Karatsuba_Code_Nat
imports Main "HOL-Library.Code_Binary_Nat" Karatsuba
begin
text "In this theory, the Karatsuba Multiplication implemented in @{text Karatsuba} is used for code
generation. This is not really practical (except beginning at ~3000 decimal digits), but merely a
nice gimmick."
fun from_numeral :: "num ⇒ nat_lsbf" where
"from_numeral num.One = [True]"
| "from_numeral (num.Bit0 x) = False # from_numeral x"
| "from_numeral (num.Bit1 x) = True # from_numeral x"
lemma from_numeral_nonempty: "from_numeral x ≠ []"
by (induction x rule: from_numeral.induct; simp)
lemma from_numeral_truncated: "truncated (from_numeral x)"
unfolding truncated_iff
by (induction x rule: from_numeral.induct; simp add: from_numeral_nonempty)
lemma to_nat_from_numeral_neq_zero: "to_nat (from_numeral x) ≠ 0"
using to_nat_zero_iff from_numeral_truncated from_numeral_nonempty by simp
fun to_numeral_of_truncated :: "nat_lsbf ⇒ num" where
"to_numeral_of_truncated [] = num.One"
| "to_numeral_of_truncated [True] = num.One"
| "to_numeral_of_truncated (True # xs) = num.Bit1 (to_numeral_of_truncated xs)"
| "to_numeral_of_truncated (False # xs) = num.Bit0 (to_numeral_of_truncated xs)"
lemma to_numeral_of_truncated_from_numeral:
"to_numeral_of_truncated (from_numeral x) = x"
apply (induction x)
subgoal by simp
subgoal by simp
subgoal for x by (cases "from_numeral x"; simp)
done
lemma nat_of_num_to_numeral_of_truncated:
assumes "truncated xs"
assumes "xs ≠ []"
shows "nat_of_num (to_numeral_of_truncated xs) = to_nat xs"
using assms proof (induction xs rule: to_numeral_of_truncated.induct)
case 1
then show ?case by blast
next
case 2
then show ?case by simp
next
case (3 v va)
note truncated_Cons_imp_truncated_tl[OF "3.prems"(1)]
from "3.IH"[OF this] show ?case by simp
next
case (4 xs)
from "4.prems"(1) have "xs ≠ []"
apply (intro ccontr[of "xs ≠ []"])
by (simp add: truncated_iff)
note truncated_Cons_imp_truncated_tl[OF "4.prems"(1)]
from "4.IH"[OF this ‹xs ≠ []›] show ?case by simp
qed
definition to_numeral :: "nat_lsbf ⇒ num" where
"to_numeral xs = (let xs' = Nat_LSBF.truncate xs in to_numeral_of_truncated xs')"
lemma to_numeral_from_numeral: "to_numeral (from_numeral x) = x"
unfolding to_numeral_def Let_def
using from_numeral_truncated to_numeral_of_truncated_from_numeral
by simp
lemma nat_of_num_to_numeral:
assumes "to_nat xs ≠ 0"
shows "nat_of_num (to_numeral xs) = to_nat xs"
unfolding to_numeral_def Let_def
using assms nat_of_num_to_numeral_of_truncated[of "truncate xs", OF truncate_truncate]
unfolding nat_lsbf.to_f_elem
using to_nat_zero_iff
by simp
lemma l0:
assumes "truncated xs"
shows "to_numeral_of_truncated xs = num_of_nat (to_nat xs)"
using assms
by (metis nat_of_num_inverse nat_of_num_to_numeral_of_truncated num_of_nat.simps(1) to_nat.simps(1) to_numeral_of_truncated.simps(1))
lemma l1: "to_numeral xs = num_of_nat (to_nat xs)"
unfolding to_numeral_def Let_def
using l0[of "truncate xs"] truncate_truncate[of xs] nat_lsbf.to_f_elem
by simp
lemma l2: "to_nat (from_numeral x) = nat_of_num x"
by (metis nat_of_num_to_numeral to_nat_from_numeral_neq_zero to_numeral_from_numeral)
lemma[code]:
"(x::num) * y = to_numeral (karatsuba_mul_nat (from_numeral x) (from_numeral y))"
unfolding l1 karatsuba_mul_nat_correct l2 times_num_def by (rule refl)
end