Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Annotation of /branches/vis12/src/compiler/fields/rational.sml
ViewVC logotype

Annotation of /branches/vis12/src/compiler/fields/rational.sml

Parent Directory Parent Directory | Revision Log 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