| 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 {*
 | 
|  |     13 |   Actually nothing is proved about the implementation.
 | 
|  |     14 | *}
 | 
|  |     15 | 
 | 
|  |     16 | datatype erat = Rat bool int int
 | 
|  |     17 | 
 | 
|  |     18 | instance erat :: zero by intro_classes
 | 
|  |     19 | instance erat :: one by intro_classes
 | 
|  |     20 | instance erat :: plus by intro_classes
 | 
|  |     21 | instance erat :: minus by intro_classes
 | 
|  |     22 | instance erat :: times by intro_classes
 | 
|  |     23 | instance erat :: inverse by intro_classes
 | 
|  |     24 | instance erat :: ord by intro_classes
 | 
|  |     25 | 
 | 
|  |     26 | consts
 | 
|  |     27 |   norm :: "erat \<Rightarrow> erat"
 | 
|  |     28 |   common :: "(int * int) * (int * int) \<Rightarrow> (int * int) * int"
 | 
|  |     29 |   of_quotient :: "int * int \<Rightarrow> erat"
 | 
|  |     30 |   of_rat :: "rat \<Rightarrow> erat"
 | 
|  |     31 |   to_rat :: "erat \<Rightarrow> rat"
 | 
|  |     32 | 
 | 
|  |     33 | defs
 | 
|  |     34 |   norm_def [simp]: "norm r == case r of (Rat a p q) \<Rightarrow>
 | 
|  |     35 |      if p = 0 then Rat True 0 1
 | 
|  |     36 |      else
 | 
|  |     37 |        let
 | 
|  |     38 |          absp = abs p
 | 
|  |     39 |        in let
 | 
|  |     40 |          m = zgcd (absp, q)
 | 
|  |     41 |        in Rat (a = (0 <= p)) (absp div m) (q div m)"
 | 
|  |     42 |   common_def [simp]: "common r == case r of ((p1, q1), (p2, q2)) \<Rightarrow>
 | 
|  |     43 |        let q' = q1 * q2 div int (gcd (nat q1, nat q2))
 | 
|  |     44 |        in ((p1 * (q' div q1), p2 * (q' div q2)), q')"
 | 
|  |     45 |   of_quotient_def [simp]: "of_quotient r == case r of (a, b) \<Rightarrow>
 | 
|  |     46 |        norm (Rat True a b)"
 | 
|  |     47 |   of_rat_def [simp]: "of_rat r == of_quotient (THE s. s : Rep_Rat r)"
 | 
|  |     48 |   to_rat_def [simp]: "to_rat r == case r of (Rat a p q) \<Rightarrow>
 | 
|  |     49 |        if a then Fract p q else Fract (uminus p) q"
 | 
|  |     50 | 
 | 
|  |     51 | consts
 | 
|  |     52 |   zero :: erat
 | 
|  |     53 |   one :: erat
 | 
|  |     54 |   add :: "erat \<Rightarrow> erat \<Rightarrow> erat"
 | 
|  |     55 |   neg :: "erat \<Rightarrow> erat"
 | 
|  |     56 |   mult :: "erat \<Rightarrow> erat \<Rightarrow> erat"
 | 
|  |     57 |   inv :: "erat \<Rightarrow> erat"
 | 
|  |     58 |   le :: "erat \<Rightarrow> erat \<Rightarrow> bool"
 | 
|  |     59 | 
 | 
|  |     60 | defs (overloaded)
 | 
|  |     61 |   zero_rat_def [simp]: "0 == Rat False 0 1"
 | 
|  |     62 |   one_rat_def [simp]: "1 == Rat False 1 1"
 | 
|  |     63 |   add_rat_def [simp]: "r + s == case r of Rat a1 p1 q1 \<Rightarrow> case s of Rat a2 p2 q2 \<Rightarrow>
 | 
|  |     64 |         let
 | 
|  |     65 |           ((r1, r2), den) = common ((p1, q1), (p2, q2))
 | 
|  |     66 |         in let
 | 
|  |     67 |           num = (if a1 then r1 else -r1) + (if a2 then r2 else -r2)
 | 
|  |     68 |         in norm (Rat True num den)"
 | 
|  |     69 |   uminus_rat_def [simp]: "- r == case r of Rat a p q \<Rightarrow>
 | 
|  |     70 |         if p = 0 then Rat a p q
 | 
|  |     71 |         else Rat (\<not> a) p q"
 | 
|  |     72 |   times_rat_def [simp]: "r * s == case r of Rat a1 p1 q1 \<Rightarrow> case s of Rat a2 p2 q2 \<Rightarrow>
 | 
|  |     73 |         norm (Rat (a1 = a2) (p1 * p2) (q1 * q2))"
 | 
|  |     74 |   inverse_rat_def [simp]: "inverse r == case r of Rat a p q \<Rightarrow>
 | 
|  |     75 |         if p = 0 then arbitrary
 | 
|  |     76 |         else Rat a q p"
 | 
|  |     77 |   le_rat_def [simp]: "r <= s == case r of Rat a1 p1 q1 \<Rightarrow> case s of Rat a2 p2 q2 \<Rightarrow>
 | 
|  |     78 |         (\<not> a1 \<and> a2) \<or>
 | 
|  |     79 |         (\<not> (a1 \<and> \<not> a2) \<and>
 | 
|  |     80 |           (let
 | 
|  |     81 |             ((r1, r2), dummy) = common ((p1, q1), (p2, q2))
 | 
|  |     82 |           in if a1 then r1 <= r2 else r2 <= r1))"
 | 
|  |     83 | 
 | 
|  |     84 | code_syntax_tyco rat
 | 
|  |     85 |   ml (target_atom "{*erat*}")
 | 
|  |     86 |   haskell (target_atom "{*erat*}")
 | 
|  |     87 | 
 | 
|  |     88 | code_alias
 | 
|  |     89 |   (* an intermediate solution until name resolving of ad-hoc overloaded
 | 
|  |     90 |      constants is refined *)
 | 
|  |     91 |   "HOL.inverse" "Rational.inverse"
 | 
|  |     92 |   "HOL.divide" "Rational.divide"
 | 
|  |     93 | 
 | 
|  |     94 | code_syntax_const
 | 
|  |     95 |   Fract
 | 
|  |     96 |     ml ("{*of_quotient*}")
 | 
|  |     97 |     haskell ("{*of_quotient*}")
 | 
| 19137 |     98 |   "0 :: rat"
 | 
| 19039 |     99 |     ml ("{*0::erat*}")
 | 
|  |    100 |     haskell ("{*1::erat*}")
 | 
| 19137 |    101 |   "1 :: rat"
 | 
| 19039 |    102 |     ml ("{*1::erat*}")
 | 
|  |    103 |     haskell ("{*1::erat*}")
 | 
| 19137 |    104 |   "op + :: rat \<Rightarrow> rat \<Rightarrow> rat"
 | 
| 19039 |    105 |     ml ("{*op + :: erat \<Rightarrow> erat \<Rightarrow> erat*}")
 | 
|  |    106 |     haskell ("{*op + :: erat \<Rightarrow> erat \<Rightarrow> erat*}")
 | 
| 19137 |    107 |   "uminus :: rat \<Rightarrow> rat"
 | 
| 19039 |    108 |     ml ("{*uminus :: erat \<Rightarrow> erat*}")
 | 
|  |    109 |     haskell ("{*uminus :: erat \<Rightarrow> erat*}")
 | 
| 19137 |    110 |   "op * :: rat \<Rightarrow> rat \<Rightarrow> rat"
 | 
| 19039 |    111 |     ml ("{*op * :: erat \<Rightarrow> erat \<Rightarrow> erat*}")
 | 
|  |    112 |     haskell ("{*op * :: erat \<Rightarrow> erat \<Rightarrow> erat*}")
 | 
| 19137 |    113 |   "inverse :: rat \<Rightarrow> rat"
 | 
| 19039 |    114 |     ml ("{*inverse :: erat \<Rightarrow> erat*}")
 | 
|  |    115 |     haskell ("{*inverse :: erat \<Rightarrow> erat*}")
 | 
| 19137 |    116 |   "divide :: rat \<Rightarrow> rat \<Rightarrow> rat"
 | 
| 19039 |    117 |     ml ("{*op * :: erat \<Rightarrow> erat \<Rightarrow> erat*}/ _/ ({*inverse :: erat \<Rightarrow> erat*}/ _)")
 | 
|  |    118 |     haskell ("{*op * :: erat \<Rightarrow> erat \<Rightarrow> erat*}/ _/ ({*inverse :: erat \<Rightarrow> erat*}/ _)")
 | 
| 19137 |    119 |   "op <= :: rat \<Rightarrow> rat \<Rightarrow> bool"
 | 
| 19039 |    120 |     ml ("{*op <= :: erat \<Rightarrow> erat \<Rightarrow> bool*}")
 | 
|  |    121 |     haskell ("{*op <= :: erat \<Rightarrow> erat \<Rightarrow> bool*}")
 | 
|  |    122 | 
 | 
|  |    123 | end
 | 
|  |    124 | 
 |