SCM Repository
Annotation of /branches/vis12/src/compiler/fields/rational.sml
Parent Directory
|
Revision Log
Revision 1950 - (view) (download)
1 : | jhr | 115 | (* rational.sml |
2 : | * | ||
3 : | jhr | 435 | * COPYRIGHT (c) 2010 The Diderot Project (http://diderot-language.cs.uchicago.edu) |
4 : | jhr | 115 | * All rights reserved. |
5 : | * | ||
6 : | * Support for rational numbers. | ||
7 : | *) | ||
8 : | |||
9 : | signature RATIONAL = | ||
10 : | sig | ||
11 : | |||
12 : | eqtype rat | ||
13 : | |||
14 : | jhr | 138 | val zero : rat |
15 : | |||
16 : | jhr | 461 | val explode : rat -> {sign : int, num : IntInf.int, denom : IntInf.int} |
17 : | |||
18 : | jhr | 115 | val ~ : rat -> rat |
19 : | val + : rat * rat -> rat | ||
20 : | val - : rat * rat -> rat | ||
21 : | val * : rat * rat -> rat | ||
22 : | val div : rat * rat -> rat | ||
23 : | |||
24 : | (* | ||
25 : | val min : rat * rat -> rat | ||
26 : | val max : rat * rat -> rat | ||
27 : | *) | ||
28 : | val abs : rat -> rat | ||
29 : | |||
30 : | val sign : rat -> int | ||
31 : | val sameSign : rat * rat -> bool | ||
32 : | |||
33 : | (* | ||
34 : | val > : rat * rat -> bool | ||
35 : | val >= : rat * rat -> bool | ||
36 : | val < : rat * rat -> bool | ||
37 : | val <= : rat * rat -> bool | ||
38 : | jhr | 118 | *) |
39 : | jhr | 115 | |
40 : | jhr | 1950 | val isZero : rat -> bool |
41 : | |||
42 : | jhr | 115 | val compare : rat * rat -> order |
43 : | |||
44 : | val / : LargeInt.int * LargeInt.int -> rat | ||
45 : | |||
46 : | val fromInt : int -> rat | ||
47 : | val fromLargeInt : LargeInt.int -> rat | ||
48 : | |||
49 : | val toString : rat -> string | ||
50 : | |||
51 : | jhr | 138 | val toReal : rat -> real |
52 : | |||
53 : | jhr | 115 | end |
54 : | |||
55 : | structure Rational :> RATIONAL = | ||
56 : | struct | ||
57 : | |||
58 : | structure II = IntInf | ||
59 : | |||
60 : | (* invariants: | ||
61 : | * denom > 0 | ||
62 : | * gcd(num, denom) = 1 | ||
63 : | *) | ||
64 : | datatype rat = R of {num : II.int, denom : II.int} | ||
65 : | |||
66 : | jhr | 466 | fun explode (R{num, denom}) = |
67 : | jhr | 461 | if (num < 0) |
68 : | jhr | 466 | then {sign = ~1, num = ~num, denom = denom} |
69 : | jhr | 461 | else if (num = 0) |
70 : | then {sign = 0, num = 0, denom = 0} | ||
71 : | else {sign = 1, num = num, denom = denom} | ||
72 : | |||
73 : | jhr | 115 | val zero = R{num=0, denom=1} |
74 : | |||
75 : | jhr | 1950 | fun isZero (R{num, ...}) = (num = 0) |
76 : | |||
77 : | jhr | 115 | fun gcd (a : II.int, 0) = a |
78 : | | gcd (a, b) = if (a > b) | ||
79 : | then gcd(a-b, b) | ||
80 : | else gcd(a, b-a) | ||
81 : | |||
82 : | fun mkRat (0, _) = zero | ||
83 : | | mkRat (n, 1) = R{num=n, denom=1} | ||
84 : | | mkRat (num, denom) = let | ||
85 : | val d = gcd(II.abs num, denom) | ||
86 : | in | ||
87 : | R{num = num div d, denom = denom div d} | ||
88 : | end | ||
89 : | |||
90 : | fun neg (R{num, denom}) = R{num = ~num, denom = denom} | ||
91 : | |||
92 : | fun add (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = let | ||
93 : | val d = gcd(d1, d2) | ||
94 : | val a1 = d2 div d | ||
95 : | val a2 = d1 div d | ||
96 : | val lcm = a1 * d1 | ||
97 : | in | ||
98 : | jhr | 116 | mkRat (a1*n1 + a2*n2, lcm) |
99 : | jhr | 115 | end |
100 : | |||
101 : | fun sub (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = let | ||
102 : | val d = gcd(d1, d2) | ||
103 : | val a1 = d2 div d | ||
104 : | val a2 = d1 div d | ||
105 : | val lcm = a1 * d1 | ||
106 : | in | ||
107 : | jhr | 116 | mkRat (a1*n1 - a2*n2, lcm) |
108 : | jhr | 115 | end |
109 : | |||
110 : | fun mul (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = | ||
111 : | mkRat (n1*n2, d1*d2) | ||
112 : | |||
113 : | fun divide (_, R{num=0, ...}) = raise Div | ||
114 : | | divide (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = let | ||
115 : | val n = n1 * d2 | ||
116 : | val d = n2 * d1 | ||
117 : | in | ||
118 : | if (d < 0) then mkRat(~n, ~d) else mkRat(n, d) | ||
119 : | end | ||
120 : | |||
121 : | fun abs (R{num, denom}) = R{num = II.abs num, denom = denom} | ||
122 : | |||
123 : | fun sign (R{num, ...}) = II.sign num | ||
124 : | |||
125 : | fun sameSign (R{num=n1, ...}, R{num=n2, ...}) = II.sameSign(n1, n2) | ||
126 : | |||
127 : | jhr | 118 | fun compare (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = ( |
128 : | case Int.compare(II.sign n1, II.sign n2) | ||
129 : | of EQUAL => | ||
130 : | if (d1 = d2) | ||
131 : | then II.compare(n1, n2) | ||
132 : | else let | ||
133 : | val d = gcd(d1, d2) | ||
134 : | val a1 = d2 div d | ||
135 : | val a2 = d1 div d | ||
136 : | in | ||
137 : | II.compare(a1*n1, a2*n2) | ||
138 : | end | ||
139 : | | order => order | ||
140 : | (* end case *)) | ||
141 : | |||
142 : | jhr | 115 | (* |
143 : | val > : rat * rat -> bool | ||
144 : | val >= : rat * rat -> bool | ||
145 : | val < : rat * rat -> bool | ||
146 : | val <= : rat * rat -> bool | ||
147 : | |||
148 : | val min : rat * rat -> rat | ||
149 : | val max : rat * rat -> rat | ||
150 : | *) | ||
151 : | |||
152 : | fun fromInt n = mkRat(II.fromInt n, 1) | ||
153 : | fun fromLargeInt n = mkRat(n, 1) | ||
154 : | |||
155 : | fun toString (R{num, denom = 1}) = II.toString num | ||
156 : | | toString (R{num, denom}) = | ||
157 : | String.concat[II.toString num, "/", II.toString denom] | ||
158 : | |||
159 : | jhr | 138 | fun toReal (R{num, denom = 1}) = Real.fromLargeInt num |
160 : | | toReal (R{num, denom}) = Real.fromLargeInt num / Real.fromLargeInt denom | ||
161 : | |||
162 : | fun op / (_, 0) = raise Div | ||
163 : | | op / (a, b) = if (b < 0) | ||
164 : | then mkRat(~a, ~b) | ||
165 : | else mkRat(a, b) | ||
166 : | |||
167 : | jhr | 115 | (* bind operators *) |
168 : | val ~ : rat -> rat = neg | ||
169 : | val op + : rat * rat -> rat = add | ||
170 : | val op - : rat * rat -> rat = sub | ||
171 : | val op * : rat * rat -> rat = mul | ||
172 : | val op div : rat * rat -> rat = divide | ||
173 : | (* | ||
174 : | val > : rat * rat -> bool | ||
175 : | val >= : rat * rat -> bool | ||
176 : | val < : rat * rat -> bool | ||
177 : | val <= : rat * rat -> bool | ||
178 : | *) | ||
179 : | |||
180 : | end |
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |