37 |
37 |
38 datatype rat = Rat of bool * IntInf.int * IntInf.int; |
38 datatype rat = Rat of bool * IntInf.int * IntInf.int; |
39 |
39 |
40 exception DIVZERO; |
40 exception DIVZERO; |
41 |
41 |
42 val zero = Rat (true, 0, 1); |
42 val zero = Rat (true, IntInf.fromInt 0, IntInf.fromInt 1); |
43 |
43 |
44 val one = Rat (true, 1, 1); |
44 val one = Rat (true, IntInf.fromInt 1, IntInf.fromInt 1); |
45 |
45 |
46 fun rat_of_intinf i = |
46 fun rat_of_intinf i = |
47 if i < 0 |
47 if i < IntInf.fromInt 0 |
48 then Rat (false, ~i, 1) |
48 then Rat (false, ~i, IntInf.fromInt 1) |
49 else Rat (true, i, 1); |
49 else Rat (true, i, IntInf.fromInt 1); |
50 |
50 |
51 fun rat_of_int i = rat_of_intinf (IntInf.fromInt i); |
51 fun rat_of_int i = rat_of_intinf (IntInf.fromInt i); |
52 |
52 |
53 fun norm (a, 0, q) = |
53 fun norm (a, p, q) = |
54 Rat (true, 0, 1) |
54 if p = IntInf.fromInt 0 then Rat (true, IntInf.fromInt 0, IntInf.fromInt 1) |
55 | norm (a, p, q) = |
55 else |
56 let |
56 let |
57 val absp = abs p |
57 val absp = abs p |
58 val m = gcd (absp, q) |
58 val m = gcd (absp, q) |
59 in Rat(a = (0 <= p), absp div m, q div m) end; |
59 in Rat(a = (IntInf.fromInt 0 <= p), absp div m, q div m) end; |
60 |
60 |
61 fun common (p1, q1, p2, q2) = |
61 fun common (p1, q1, p2, q2) = |
62 let val q' = lcm (q1, q2) |
62 let val q' = lcm (q1, q2) |
63 in (p1 * (q' div q1), p2 * (q' div q2), q') end |
63 in (p1 * (q' div q1), p2 * (q' div q2), q') end |
64 |
64 |
65 fun rat_of_quotient (p, 0) = |
65 fun rat_of_quotient (p, q) = |
66 raise DIVZERO |
66 if q = IntInf.fromInt 0 then raise DIVZERO |
67 | rat_of_quotient (p, q) = |
67 else norm (IntInf.fromInt 0 <= q, p, abs q); |
68 norm (0 <= q, p, abs q); |
|
69 |
68 |
70 fun quotient_of_rat (Rat (a, p, q)) = (if a then p else ~p, q); |
69 fun quotient_of_rat (Rat (a, p, q)) = (if a then p else ~p, q); |
71 |
70 |
72 fun string_of_rat r = |
71 fun string_of_rat r = |
73 let val (p, q) = quotient_of_rat r |
72 let val (p, q) = quotient_of_rat r |
102 in norm (true, num, den) end; |
101 in norm (true, num, den) end; |
103 |
102 |
104 fun mult (Rat (a1, p1, q1), Rat (a2, p2, q2)) = |
103 fun mult (Rat (a1, p1, q1), Rat (a2, p2, q2)) = |
105 norm (a1=a2, p1*p2, q1*q2); |
104 norm (a1=a2, p1*p2, q1*q2); |
106 |
105 |
107 fun neg (r as Rat (_, 0, _)) = r |
106 fun neg (r as Rat (b, p, q)) = |
108 | neg (Rat (b, p, q)) = |
107 if p = IntInf.fromInt 0 then r |
109 Rat (not b, p, q); |
108 else Rat (not b, p, q); |
110 |
109 |
111 fun inv (Rat (a, 0, q)) = |
110 fun inv (Rat (a, p, q)) = |
112 raise DIVZERO |
111 if p = IntInf.fromInt 0 then raise DIVZERO |
113 | inv (Rat (a, p, q)) = |
112 else Rat (a, q, p); |
114 Rat (a, q, p) |
|
115 |
113 |
116 fun ge0 (Rat (a, _, _)) = a; |
114 fun ge0 (Rat (a, _, _)) = a; |
117 fun gt0 (Rat (a, p, _)) = a andalso p > 0; |
115 fun gt0 (Rat (a, p, _)) = a andalso p > IntInf.fromInt 0; |
118 |
116 |
119 fun roundup (r as Rat (_, _, 1)) = r |
117 fun roundup (r as Rat (a, p, q)) = |
120 | roundup (Rat (a, p, q)) = |
118 if q = IntInf.fromInt 1 then r |
121 let |
119 else |
122 fun round true q = Rat (true, q+1, 1) |
120 let |
123 | round false 0 = Rat (true, 0 ,1) |
121 fun round true q = Rat (true, q + IntInf.fromInt 1, IntInf.fromInt 1) |
124 | round false q = Rat (false, q, 1) |
122 | round false q = |
125 in round a (p div q) end; |
123 if q = IntInf.fromInt 0 |
|
124 then Rat (true, IntInf.fromInt 0, IntInf.fromInt 1) |
|
125 else Rat (false, q, IntInf.fromInt 1); |
|
126 in round a (p div q) end; |
126 |
127 |
127 fun rounddown (r as Rat (_, _, 1)) = r |
128 fun rounddown (r as Rat (a, p, q)) = |
128 | rounddown (Rat (a, p, q)) = |
129 if q = IntInf.fromInt 1 then r |
129 let |
130 else |
130 fun round true q = Rat (true, q, 1) |
131 let |
131 | round false q = Rat (false, q+1, 1) |
132 fun round true q = Rat (true, q, IntInf.fromInt 1) |
132 in round a (p div q) end; |
133 | round false q = Rat (false, q + IntInf.fromInt 1, IntInf.fromInt 1) |
|
134 in round a (p div q) end; |
133 |
135 |
134 end; |
136 end; |