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 138 - (view) (download)
Original Path: trunk/src/compiler/common/rational.sml

1 : jhr 115 (* rational.sml
2 :     *
3 :     * COPYRIGHT (c) 2010 The Diderot Project (http://diderot.cs.uchicago.edu)
4 :     * 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 115 val ~ : rat -> rat
17 :     val + : rat * rat -> rat
18 :     val - : rat * rat -> rat
19 :     val * : rat * rat -> rat
20 :     val div : rat * rat -> rat
21 :    
22 :     (*
23 :     val min : rat * rat -> rat
24 :     val max : rat * rat -> rat
25 :     *)
26 :     val abs : rat -> rat
27 :    
28 :     val sign : rat -> int
29 :     val sameSign : rat * rat -> bool
30 :    
31 :     (*
32 :     val > : rat * rat -> bool
33 :     val >= : rat * rat -> bool
34 :     val < : rat * rat -> bool
35 :     val <= : rat * rat -> bool
36 : jhr 118 *)
37 : jhr 115
38 :     val compare : rat * rat -> order
39 :    
40 :     val / : LargeInt.int * LargeInt.int -> rat
41 :    
42 :     val fromInt : int -> rat
43 :     val fromLargeInt : LargeInt.int -> rat
44 :    
45 :     val toString : rat -> string
46 :    
47 : jhr 138 val toReal : rat -> real
48 :    
49 : jhr 115 end
50 :    
51 :     structure Rational :> RATIONAL =
52 :     struct
53 :    
54 :     structure II = IntInf
55 :    
56 :     (* invariants:
57 :     * denom > 0
58 :     * gcd(num, denom) = 1
59 :     *)
60 :     datatype rat = R of {num : II.int, denom : II.int}
61 :    
62 :     val zero = R{num=0, denom=1}
63 :    
64 :     fun gcd (a : II.int, 0) = a
65 :     | gcd (a, b) = if (a > b)
66 :     then gcd(a-b, b)
67 :     else gcd(a, b-a)
68 :    
69 :     fun mkRat (0, _) = zero
70 :     | mkRat (n, 1) = R{num=n, denom=1}
71 :     | mkRat (num, denom) = let
72 :     val d = gcd(II.abs num, denom)
73 :     in
74 :     R{num = num div d, denom = denom div d}
75 :     end
76 :    
77 :     fun neg (R{num, denom}) = R{num = ~num, denom = denom}
78 :    
79 :     fun add (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = let
80 :     val d = gcd(d1, d2)
81 :     val a1 = d2 div d
82 :     val a2 = d1 div d
83 :     val lcm = a1 * d1
84 :     in
85 : jhr 116 mkRat (a1*n1 + a2*n2, lcm)
86 : jhr 115 end
87 :    
88 :     fun sub (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 mul (R{num=n1, denom=d1}, R{num=n2, denom=d2}) =
98 :     mkRat (n1*n2, d1*d2)
99 :    
100 :     fun divide (_, R{num=0, ...}) = raise Div
101 :     | divide (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = let
102 :     val n = n1 * d2
103 :     val d = n2 * d1
104 :     in
105 :     if (d < 0) then mkRat(~n, ~d) else mkRat(n, d)
106 :     end
107 :    
108 :     fun abs (R{num, denom}) = R{num = II.abs num, denom = denom}
109 :    
110 :     fun sign (R{num, ...}) = II.sign num
111 :    
112 :     fun sameSign (R{num=n1, ...}, R{num=n2, ...}) = II.sameSign(n1, n2)
113 :    
114 : jhr 118 fun compare (R{num=n1, denom=d1}, R{num=n2, denom=d2}) = (
115 :     case Int.compare(II.sign n1, II.sign n2)
116 :     of EQUAL =>
117 :     if (d1 = d2)
118 :     then II.compare(n1, n2)
119 :     else let
120 :     val d = gcd(d1, d2)
121 :     val a1 = d2 div d
122 :     val a2 = d1 div d
123 :     in
124 :     II.compare(a1*n1, a2*n2)
125 :     end
126 :     | order => order
127 :     (* end case *))
128 :    
129 : jhr 115 (*
130 :     val > : rat * rat -> bool
131 :     val >= : rat * rat -> bool
132 :     val < : rat * rat -> bool
133 :     val <= : rat * rat -> bool
134 :    
135 :     val min : rat * rat -> rat
136 :     val max : rat * rat -> rat
137 :     *)
138 :    
139 :     fun fromInt n = mkRat(II.fromInt n, 1)
140 :     fun fromLargeInt n = mkRat(n, 1)
141 :    
142 :     fun toString (R{num, denom = 1}) = II.toString num
143 :     | toString (R{num, denom}) =
144 :     String.concat[II.toString num, "/", II.toString denom]
145 :    
146 : jhr 138 fun toReal (R{num, denom = 1}) = Real.fromLargeInt num
147 :     | toReal (R{num, denom}) = Real.fromLargeInt num / Real.fromLargeInt denom
148 :    
149 :     fun op / (_, 0) = raise Div
150 :     | op / (a, b) = if (b < 0)
151 :     then mkRat(~a, ~b)
152 :     else mkRat(a, b)
153 :    
154 : jhr 115 (* bind operators *)
155 :     val ~ : rat -> rat = neg
156 :     val op + : rat * rat -> rat = add
157 :     val op - : rat * rat -> rat = sub
158 :     val op * : rat * rat -> rat = mul
159 :     val op div : rat * rat -> rat = divide
160 :     (*
161 :     val > : rat * rat -> bool
162 :     val >= : rat * rat -> bool
163 :     val < : rat * rat -> bool
164 :     val <= : rat * rat -> bool
165 :     *)
166 :    
167 :     end

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