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

SCM Repository

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

Annotation of /trunk/src/compiler/fields/rational.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 466 - (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 :     val compare : rat * rat -> order
41 :    
42 :     val / : LargeInt.int * LargeInt.int -> rat
43 :    
44 :     val fromInt : int -> rat
45 :     val fromLargeInt : LargeInt.int -> rat
46 :    
47 :     val toString : rat -> string
48 :    
49 : jhr 138 val toReal : rat -> real
50 :    
51 : jhr 115 end
52 :    
53 :     structure Rational :> RATIONAL =
54 :     struct
55 :    
56 :     structure II = IntInf
57 :    
58 :     (* invariants:
59 :     * denom > 0
60 :     * gcd(num, denom) = 1
61 :     *)
62 :     datatype rat = R of {num : II.int, denom : II.int}
63 :    
64 : jhr 466 fun explode (R{num, denom}) =
65 : jhr 461 if (num < 0)
66 : jhr 466 then {sign = ~1, num = ~num, denom = denom}
67 : jhr 461 else if (num = 0)
68 :     then {sign = 0, num = 0, denom = 0}
69 :     else {sign = 1, num = num, denom = denom}
70 :    
71 : jhr 115 val zero = R{num=0, denom=1}
72 :    
73 :     fun gcd (a : II.int, 0) = a
74 :     | gcd (a, b) = if (a > b)
75 :     then gcd(a-b, b)
76 :     else gcd(a, b-a)
77 :    
78 :     fun mkRat (0, _) = zero
79 :     | mkRat (n, 1) = R{num=n, denom=1}
80 :     | mkRat (num, denom) = let
81 :     val d = gcd(II.abs num, denom)
82 :     in
83 :     R{num = num div d, denom = denom div d}
84 :     end
85 :    
86 :     fun neg (R{num, denom}) = R{num = ~num, denom = denom}
87 :    
88 :     fun add (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = let
89 :     val d = gcd(d1, d2)
90 :     val a1 = d2 div d
91 :     val a2 = d1 div d
92 :     val lcm = a1 * d1
93 :     in
94 : jhr 116 mkRat (a1*n1 + a2*n2, lcm)
95 : jhr 115 end
96 :    
97 :     fun sub (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = let
98 :     val d = gcd(d1, d2)
99 :     val a1 = d2 div d
100 :     val a2 = d1 div d
101 :     val lcm = a1 * d1
102 :     in
103 : jhr 116 mkRat (a1*n1 - a2*n2, lcm)
104 : jhr 115 end
105 :    
106 :     fun mul (R{num=n1, denom=d1}, R{num=n2, denom=d2}) =
107 :     mkRat (n1*n2, d1*d2)
108 :    
109 :     fun divide (_, R{num=0, ...}) = raise Div
110 :     | divide (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = let
111 :     val n = n1 * d2
112 :     val d = n2 * d1
113 :     in
114 :     if (d < 0) then mkRat(~n, ~d) else mkRat(n, d)
115 :     end
116 :    
117 :     fun abs (R{num, denom}) = R{num = II.abs num, denom = denom}
118 :    
119 :     fun sign (R{num, ...}) = II.sign num
120 :    
121 :     fun sameSign (R{num=n1, ...}, R{num=n2, ...}) = II.sameSign(n1, n2)
122 :    
123 : jhr 118 fun compare (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = (
124 :     case Int.compare(II.sign n1, II.sign n2)
125 :     of EQUAL =>
126 :     if (d1 = d2)
127 :     then II.compare(n1, n2)
128 :     else let
129 :     val d = gcd(d1, d2)
130 :     val a1 = d2 div d
131 :     val a2 = d1 div d
132 :     in
133 :     II.compare(a1*n1, a2*n2)
134 :     end
135 :     | order => order
136 :     (* end case *))
137 :    
138 : jhr 115 (*
139 :     val > : rat * rat -> bool
140 :     val >= : rat * rat -> bool
141 :     val < : rat * rat -> bool
142 :     val <= : rat * rat -> bool
143 :    
144 :     val min : rat * rat -> rat
145 :     val max : rat * rat -> rat
146 :     *)
147 :    
148 :     fun fromInt n = mkRat(II.fromInt n, 1)
149 :     fun fromLargeInt n = mkRat(n, 1)
150 :    
151 :     fun toString (R{num, denom = 1}) = II.toString num
152 :     | toString (R{num, denom}) =
153 :     String.concat[II.toString num, "/", II.toString denom]
154 :    
155 : jhr 138 fun toReal (R{num, denom = 1}) = Real.fromLargeInt num
156 :     | toReal (R{num, denom}) = Real.fromLargeInt num / Real.fromLargeInt denom
157 :    
158 :     fun op / (_, 0) = raise Div
159 :     | op / (a, b) = if (b < 0)
160 :     then mkRat(~a, ~b)
161 :     else mkRat(a, b)
162 :    
163 : jhr 115 (* bind operators *)
164 :     val ~ : rat -> rat = neg
165 :     val op + : rat * rat -> rat = add
166 :     val op - : rat * rat -> rat = sub
167 :     val op * : rat * rat -> rat = mul
168 :     val op div : rat * rat -> rat = divide
169 :     (*
170 :     val > : rat * rat -> bool
171 :     val >= : rat * rat -> bool
172 :     val < : rat * rat -> bool
173 :     val <= : rat * rat -> bool
174 :     *)
175 :    
176 :     end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0