(* $Id: sol.thy,v 1.2 2004/11/23 15:14:35 webertj Exp $ Author: Tobias Nipkow *) header {* BIGNAT - Specification and Verification *} (*<*) theory sol imports Main begin (*>*) subsection {* Representation *} types bigNat = "nat list" consts val :: "nat \<Rightarrow> bigNat \<Rightarrow> nat" primrec "val d [] = 0" "val d (n#ns) = n + d*(val d ns)" consts valid :: "nat \<Rightarrow> bigNat \<Rightarrow> bool" primrec "valid d [] = (0<d)" "valid d (n#ns) = ((n<d) \<and> (valid d ns))" text {*\subsection*{Auxiliary lemmas}*} lemma aux: "m < d * d \<Longrightarrow> m div d < (d::nat)" proof - assume m: "m < d * d" show ?thesis proof (rule classical) presume "d \<le> m div d" then have "d * d \<le> d * (m div d)" by simp also have "d * (m div d) \<le> m" by (simp add: mult_div_cancel) finally show ?thesis using m by arith qed auto qed lemma auxa:"a < d \<Longrightarrow> b < d \<Longrightarrow> (a + b) div d < (d::nat)" proof - assume a: "a < d" "b < d" { assume "d = 0" with a have ?thesis by simp } moreover { assume "d = 1" with a have ?thesis by simp } moreover { from a have "a + b < 2 * d" by simp also assume "2 <= d" then have "2 * d <= d * d" by simp finally have "a + b < d * d" . then have "(a + b) div d < d" by (rule aux) } ultimately show ?thesis by arith qed lemma auxb:"a < d \<Longrightarrow> b < d \<Longrightarrow> c < d \<Longrightarrow> (a + b + c) div d < (d::nat)" proof - assume a: "a < d" "b < d" "c < d" { assume "d = 0" with a have ?thesis by simp } moreover { assume "d = 1" with a have ?thesis by simp } moreover { assume "d = 2" with a have ?thesis by (cases a, auto) } moreover { from a have "a + b + c < 3 * d" by simp also assume "3 <= d" then have "3 * d <= d * d" by simp finally have "a + b + c < d * d" . then have "(a + b + c) div d < d" by (rule aux) } ultimately show ?thesis by arith qed lemma le_iff_lSuc:"(a \<le> b) = (a < Suc b)" by arith lemma auxc:" \<lbrakk> a \<le> d; b \<le> d; c \<le> d\<rbrakk> \<Longrightarrow> (a * b + c) div (Suc d) \<le> d" proof - assume a:"a \<le> d" and b:"b \<le> d" and c:"c \<le> d" then have d:"a * b + c <= d * d +d" by (auto intro: add_le_mono mult_le_mono) then have e:"d * d + d = d * (Suc d)" by clarsimp from d have f:"(a * b + c) div (Suc d) <= (d * Suc d) div (Suc d)" by (auto simp:e intro:div_le_mono) have "(d * Suc d) div (Suc d) = d" by (simp only:div_mult_self_is_m) with f show ?thesis by simp qed lemma auxd:" \<lbrakk> a < d; b < d; c < d\<rbrakk> \<Longrightarrow> (a * b + c) div d < (d::nat)" proof (cases d) assume "a < d" "d = 0" then show ?thesis by simp next fix n thm le_iff_lSuc[THEN iffD1] assume d:"d = Suc n" and a:"a < d" "b < d" "c < d" then show "(a * b + c) div d < d" by (auto dest:le_iff_lSuc[THEN iffD2] intro:le_iff_lSuc[THEN iffD1] auxc) qed subsection {* Addition *} consts add :: "nat * nat * bigNat * bigNat \<Rightarrow> bigNat" carry :: "nat \<Rightarrow> nat \<Rightarrow> bigNat \<Rightarrow> bigNat" recdef add "measure(%(d,c,xs,ys). size xs)" "add(d,c,[],ns) = carry d c ns" "add(d,c,ms,[]) = carry d c ms" "add(d,c,m#ms,n#ns) = ((m+n+c) mod d) # add(d,(m+n+c) div d,ms,ns)" primrec "carry d c [] = [c]" "carry d c (m#ms) = ((m+c) mod d) # carry d ((m+c) div d) ms" lemma val_carry[simp]: "\<And>c. val d (carry d c ms) = val d ms + c" proof (induct ms) case Nil show ?case by simp next case (Cons m ms c) thus ?case by (simp add:add_mult_distrib2) qed lemma val_add:"val d (add(d,c,ms,ns)) = val d ms + val d ns + c" proof (induct d c ms ns rule:add.induct) case 1 show ?case by simp next case (2 d c m ms) show ?case by (simp add:add_mult_distrib2) next case (3 d c m ms) show ?case by (simp add:add_mult_distrib2) next case (4 d c m ms n ns) thus ?case by (simp add:add_mult_distrib2) qed lemma carry_valid:"\<And>c. \<lbrakk> valid d ms; c < d \<rbrakk> \<Longrightarrow> valid d (carry d c ms)" apply (induct ms) apply (auto simp:auxa) done lemma add_valid:"\<lbrakk> valid d ms; valid d ns; c < d\<rbrakk> \<Longrightarrow> valid d (add(d,c,ns,ms))" apply (induct d c ms ns rule:add.induct) apply (auto intro:carry_valid simp:auxa auxb) apply (simp only:add_ac) done subsection {* Multiplication *} consts mult1 :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bigNat \<Rightarrow> bigNat" primrec "mult1 d c b [] = [c]" "mult1 d c b (a#as) = ((a*b+c) mod d) # (mult1 d ((a*b+c) div d) b as)" consts mult :: "nat \<Rightarrow> bigNat \<Rightarrow> bigNat \<Rightarrow> bigNat" primrec "mult d as [] = []" "mult d as (b#bs) = (add(d,0,(mult1 d 0 b as),0#mult d as bs))" lemma val_mult1[simp]:"\<And>c. val d (mult1 d c b as) = (val d as *b + c)" proof (induct as) case Nil show ?case by simp next case (Cons a as c) thus ?case by (simp add:add_mult_distrib add_mult_distrib2) qed lemma val_mult:"val d (mult d as bs) = val d as * val d bs" apply (induct bs) apply (auto simp add:add_mult_distrib2 val_add) done lemma mult1_valid:"\<And>c. \<lbrakk> valid d ms; n < d; c < d\<rbrakk> \<Longrightarrow> valid d (mult1 d c n ms)" apply (induct ms) apply (auto intro:auxd) done lemma mult_valid:"\<lbrakk> valid d ms; valid d ns\<rbrakk> \<Longrightarrow> valid d (mult d ns ms)" apply (induct ms) apply (auto) apply (rule add_valid) apply auto apply (rule mult1_valid) apply auto done end