| author | berghofe | 
| Wed, 07 Feb 2007 17:41:11 +0100 | |
| changeset 22270 | 4ccb7e6be929 | 
| parent 22067 | 39d5d42116c4 | 
| child 22384 | 33a46e6c7f04 | 
| permissions | -rw-r--r-- | 
| 19039 | 1 | (* Title: HOL/Library/ExecutableRat.thy | 
| 2 | ID: $Id$ | |
| 3 | Author: Florian Haftmann, TU Muenchen | |
| 4 | *) | |
| 5 | ||
| 6 | header {* Executable implementation of rational numbers in HOL *}
 | |
| 7 | ||
| 8 | theory ExecutableRat | |
| 9 | imports "~~/src/HOL/Real/Rational" "~~/src/HOL/NumberTheory/IntPrimes" | |
| 10 | begin | |
| 11 | ||
| 12 | text {*
 | |
| 22067 | 13 |   Actually \emph{nothing} is proved about the implementation.
 | 
| 19039 | 14 | *} | 
| 15 | ||
| 22067 | 16 | subsection {* Representation and operations of executable rationals *}
 | 
| 19039 | 17 | |
| 22067 | 18 | datatype erat = Rat bool nat nat | 
| 19039 | 19 | |
| 20701 | 20 | axiomatization | 
| 21 | div_zero :: erat | |
| 22 | ||
| 22067 | 23 | fun | 
| 24 | common :: "(nat * nat) \<Rightarrow> (nat * nat) \<Rightarrow> (nat * nat) * nat" where | |
| 25 | "common (p1, q1) (p2, q2) = ( | |
| 26 | let | |
| 27 | q' = q1 * q2 div gcd (q1, q2) | |
| 28 | in ((p1 * (q' div q1), p2 * (q' div q2)), q'))" | |
| 29 | ||
| 30 | definition | |
| 31 | minus_sign :: "nat \<Rightarrow> nat \<Rightarrow> bool * nat" where | |
| 32 | "minus_sign n m = (if n < m then (False, m - n) else (True, n - m))" | |
| 33 | ||
| 34 | fun | |
| 35 | add_sign :: "bool * nat \<Rightarrow> bool * nat \<Rightarrow> bool * nat" where | |
| 36 | "add_sign (True, n) (True, m) = (True, n + m)" | |
| 37 | "add_sign (False, n) (False, m) = (False, n + m)" | |
| 38 | "add_sign (True, n) (False, m) = minus_sign n m" | |
| 39 | "add_sign (False, n) (True, m) = minus_sign m n" | |
| 40 | ||
| 41 | definition | |
| 42 | erat_of_quotient :: "int \<Rightarrow> int \<Rightarrow> erat" where | |
| 43 | "erat_of_quotient k1 k2 = ( | |
| 44 | let | |
| 45 | l1 = nat (abs k1); | |
| 46 | l2 = nat (abs k2); | |
| 47 | m = gcd (l1, l2) | |
| 48 | in Rat (k1 \<le> 0 \<longleftrightarrow> k2 \<le> 0) (l1 div m) (l2 div m))" | |
| 49 | ||
| 50 | instance erat :: zero | |
| 51 | zero_rat_def: "0 \<equiv> Rat True 0 1" .. | |
| 52 | ||
| 53 | instance erat :: one | |
| 54 | one_rat_def: "1 \<equiv> Rat True 1 1" .. | |
| 55 | ||
| 56 | instance erat :: plus | |
| 57 | add_rat_def: "r + s \<equiv> case r of Rat a1 p1 q1 \<Rightarrow> case s of Rat a2 p2 q2 \<Rightarrow> | |
| 19039 | 58 | let | 
| 22067 | 59 | ((r1, r2), den) = common (p1, q1) (p2, q2); | 
| 60 | (sign, num) = add_sign (a1, r1) (a2, r2) | |
| 61 | in Rat sign num den" .. | |
| 62 | ||
| 63 | instance erat :: minus | |
| 64 | uminus_rat_def: "- r \<equiv> case r of Rat a p q \<Rightarrow> | |
| 65 | if p = 0 then Rat True 0 1 | |
| 66 | else Rat (\<not> a) p q" .. | |
| 67 | ||
| 68 | instance erat :: times | |
| 69 | times_rat_def: "r * s \<equiv> case r of Rat a1 p1 q1 \<Rightarrow> case s of Rat a2 p2 q2 \<Rightarrow> | |
| 70 | let | |
| 71 | p = p1 * p2; | |
| 72 | q = q1 * q2; | |
| 73 | m = gcd (p, q) | |
| 74 | in Rat (a1 = a2) (p div m) (q div m)" .. | |
| 75 | ||
| 76 | instance erat :: inverse | |
| 77 | inverse_rat_def: "inverse r \<equiv> case r of Rat a p q \<Rightarrow> | |
| 20701 | 78 | if p = 0 then div_zero | 
| 22067 | 79 | else Rat a q p" .. | 
| 80 | ||
| 81 | instance erat :: ord | |
| 82 | le_rat_def: "r1 \<le> r2 \<equiv> case r1 of Rat a1 p1 q1 \<Rightarrow> case r2 of Rat a2 p2 q2 \<Rightarrow> | |
| 19039 | 83 | (\<not> a1 \<and> a2) \<or> | 
| 84 | (\<not> (a1 \<and> \<not> a2) \<and> | |
| 85 | (let | |
| 22067 | 86 | ((r1, r2), dummy) = common (p1, q1) (p2, q2) | 
| 87 | in if a1 then r1 \<le> r2 else r2 \<le> r1))" .. | |
| 19039 | 88 | |
| 19791 | 89 | |
| 22067 | 90 | subsection {* Code generator setup *}
 | 
| 91 | ||
| 92 | subsubsection {* code lemmas *}
 | |
| 20701 | 93 | |
| 20934 | 94 | lemma number_of_rat [code unfold]: | 
| 95 | "(number_of k \<Colon> rat) \<equiv> Fract k 1" | |
| 20701 | 96 | unfolding Fract_of_int_eq rat_number_of_def by simp | 
| 97 | ||
| 22067 | 98 | lemma rat_minus [code func]: | 
| 99 | "(a\<Colon>rat) - b = a + (- b)" unfolding ab_group_add_class.diff_minus .. | |
| 100 | ||
| 101 | lemma rat_divide [code func]: | |
| 102 | "(a\<Colon>rat) / b = a * inverse b" unfolding divide_inverse .. | |
| 20934 | 103 | |
| 20701 | 104 | instance rat :: eq .. | 
| 105 | ||
| 22067 | 106 | subsubsection {* names *}
 | 
| 20701 | 107 | |
| 21191 | 108 | code_modulename SML | 
| 109 | ExecutableRat Rational | |
| 20701 | 110 | |
| 21911 
e29bcab0c81c
added OCaml code generation (without dictionaries)
 haftmann parents: 
21545diff
changeset | 111 | code_modulename OCaml | 
| 
e29bcab0c81c
added OCaml code generation (without dictionaries)
 haftmann parents: 
21545diff
changeset | 112 | ExecutableRat Rational | 
| 
e29bcab0c81c
added OCaml code generation (without dictionaries)
 haftmann parents: 
21545diff
changeset | 113 | |
| 20701 | 114 | |
| 22067 | 115 | subsubsection {* rat as abstype *}
 | 
| 20934 | 116 | |
| 21191 | 117 | lemma [code func]: -- {* prevents eq constraint *}
 | 
| 118 | shows "All = All" | |
| 119 | and "contents = contents" by rule+ | |
| 120 | ||
| 22067 | 121 | code_const div_zero | 
| 122 | (SML "raise/ Fail/ \"Division by zero\"") | |
| 123 | (OCaml "failwith \"Division by zero\"") | |
| 124 | (Haskell "error/ \"Division by zero\"") | |
| 125 | ||
| 20934 | 126 | code_abstype rat erat where | 
| 22067 | 127 | Fract \<equiv> erat_of_quotient | 
| 20934 | 128 | "0 \<Colon> rat" \<equiv> "0 \<Colon> erat" | 
| 129 | "1 \<Colon> rat" \<equiv> "1 \<Colon> erat" | |
| 130 | "op + \<Colon> rat \<Rightarrow> rat \<Rightarrow> rat" \<equiv> "op + \<Colon> erat \<Rightarrow> erat \<Rightarrow> erat" | |
| 131 | "uminus \<Colon> rat \<Rightarrow> rat" \<equiv> "uminus \<Colon> erat \<Rightarrow> erat" | |
| 132 | "op * \<Colon> rat \<Rightarrow> rat \<Rightarrow> rat" \<equiv> "op * \<Colon> erat \<Rightarrow> erat \<Rightarrow> erat" | |
| 133 | "inverse \<Colon> rat \<Rightarrow> rat" \<equiv> "inverse \<Colon> erat \<Rightarrow> erat" | |
| 134 | "op \<le> \<Colon> rat \<Rightarrow> rat \<Rightarrow> bool" \<equiv> "op \<le> \<Colon> erat \<Rightarrow> erat \<Rightarrow> bool" | |
| 22067 | 135 | "op = \<Colon> rat \<Rightarrow> rat \<Rightarrow> bool" \<equiv> "op = \<Colon> erat \<Rightarrow> erat \<Rightarrow> bool" | 
| 19791 | 136 | |
| 137 | types_code | |
| 138 |   rat ("{*erat*}")
 | |
| 139 | ||
| 140 | consts_code | |
| 22067 | 141 |   div_zero ("(raise/ (Fail/ \"Division by zero\"))")
 | 
| 142 |   Fract ("({*erat_of_quotient*} (_) (_))")
 | |
| 143 |   HOL.zero :: rat ("({*Rat True 0 1*})")
 | |
| 144 |   HOL.one :: rat ("({*Rat True 1 1*})")
 | |
| 145 |   HOL.plus :: "rat \<Rightarrow> rat \<Rightarrow> rat" ("({*op + \<Colon> erat \<Rightarrow> erat \<Rightarrow> erat*} (_) (_))")
 | |
| 146 |   HOL.uminus :: "rat \<Rightarrow> rat" ("({*uminus \<Colon> erat \<Rightarrow> erat*} (_))")
 | |
| 147 |   HOL.times :: "rat \<Rightarrow> rat \<Rightarrow> rat" ("({*op * \<Colon> erat \<Rightarrow> erat \<Rightarrow> erat*} (_) (_))")
 | |
| 148 |   HOL.inverse :: "rat \<Rightarrow> rat" ("({*inverse \<Colon> erat \<Rightarrow> erat*} (_))")
 | |
| 149 |   Orderings.less_eq :: "rat \<Rightarrow> rat \<Rightarrow> bool" ("({*op \<le> \<Colon> erat \<Rightarrow> erat \<Rightarrow> bool*} (_) (_))")
 | |
| 150 |   "op =" :: "rat \<Rightarrow> rat \<Rightarrow> bool" ("({*op = \<Colon> erat \<Rightarrow> erat \<Rightarrow> bool*} (_) (_))")
 | |
| 19889 | 151 | |
| 19039 | 152 | end |