Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 313 lines (261 sloc) 10.082 kb
fde191e adds_license_headers [skip ci]
peter1000 authored
1 # This file is a part of Julia. License is MIT: http://julialang.org/license
2
3904340 @JeffBezanson fix codegen bug in immutable types containing references. fixes #2490
JeffBezanson authored
3 immutable Rational{T<:Integer} <: Real
a4f49ca @JeffBezanson implementing typevar bounds, and T<:Int syntax for static parameters
JeffBezanson authored
4 num::T
5 den::T
5bf8a52 @JeffBezanson changing convert() to use the new dispatch-on-type, .convert fields gone
JeffBezanson authored
6
cb53fd6 @JeffBezanson rewriting all julia constructors for new design
JeffBezanson authored
7 function Rational(num::T, den::T)
8f554df @jakebolewski Try and remove as many generic error() messages from base as possible
jakebolewski authored
8 num == den == zero(T) && throw(ArgumentError("invalid rational: zero($T)//zero($T)"))
118c071 @StefanKarpinski rational: print ±1//0 as ±1//0 instead of ±Inf
StefanKarpinski authored
9 g = den < 0 ? -gcd(den, num) : gcd(den, num)
8762711 @JeffBezanson adding which(f, args...)
JeffBezanson authored
10 new(div(num, g), div(den, g))
4a0fe53 @StefanKarpinski Fix Rational,Float promotion.
StefanKarpinski authored
11 end
70efab8 @StefanKarpinski Fairly resonable Rational number type.
StefanKarpinski authored
12 end
ae44b3a @StefanKarpinski Rename: Int => Integer, Uint => Unsigned.
StefanKarpinski authored
13 Rational{T<:Integer}(n::T, d::T) = Rational{T}(n,d)
14 Rational(n::Integer, d::Integer) = Rational(promote(n,d)...)
15 Rational(n::Integer) = Rational(n,one(n))
70efab8 @StefanKarpinski Fairly resonable Rational number type.
StefanKarpinski authored
16
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
17 function divgcd(x::Integer,y::Integer)
18 g = gcd(x,y)
19 div(x,g), div(y,g)
20 end
21
4bd8386 @StefanKarpinski Bit of cleanup in rational.jl.
StefanKarpinski authored
22 //(n::Integer, d::Integer ) = Rational(n,d)
42e5048 @StefanKarpinski Add support for constructing complex rationals.
StefanKarpinski authored
23
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
24 function //(x::Rational, y::Integer )
25 xn,yn = divgcd(x.num,y)
26 xn//checked_mul(x.den,yn)
27 end
28 function //(x::Integer, y::Rational)
29 xn,yn = divgcd(x,y.num)
30 checked_mul(xn,y.den)//yn
31 end
32 function //(x::Rational, y::Rational)
33 xn,yn = divgcd(x.num,y.num)
34 xd,yd = divgcd(x.den,y.den)
35 checked_mul(xn,yd)//checked_mul(xd,yn)
36 end
37
38 //(x::Complex, y::Real ) = complex(real(x)//y,imag(x)//y)
39 function //(x::Number, y::Complex)
40 xr = complex(Rational(real(x)),Rational(imag(x)))
41 yr = complex(Rational(real(y)),Rational(imag(y)))
42 xr // yr
43 end
44 function //{Ra<:Rational,Rb<:Rational}(x::Complex{Ra}, y::Complex{Rb})
42e5048 @StefanKarpinski Add support for constructing complex rationals.
StefanKarpinski authored
45 xy = x*y'
46 yy = real(y*y')
47 complex(real(xy)//yy, imag(xy)//yy)
48 end
70efab8 @StefanKarpinski Fairly resonable Rational number type.
StefanKarpinski authored
49
3434c2c @stevengj add broadcasting .//
stevengj authored
50 //(X::AbstractArray, y::Number) = X .// y
51 .//(X::AbstractArray, y::Number) = reshape([ x // y for x in X ], size(X))
52 .//(y::Number, X::AbstractArray) = reshape([ y // x for x in X ], size(X))
53
3458af5 @vtjnash Require io::IO as first argument for show
vtjnash authored
54 function show(io::IO, x::Rational)
118c071 @StefanKarpinski rational: print ±1//0 as ±1//0 instead of ±Inf
StefanKarpinski authored
55 show(io, num(x))
56 print(io, "//")
57 show(io, den(x))
329ffb5 @StefanKarpinski Fix & improve use of promotion for Complex and Rational types.
StefanKarpinski authored
58 end
70efab8 @StefanKarpinski Fairly resonable Rational number type.
StefanKarpinski authored
59
5ef0d8f @JeffBezanson fix #7564
JeffBezanson authored
60 convert{T<:Integer}(::Type{Rational{T}}, x::Rational) = Rational{T}(convert(T,x.num),convert(T,x.den))
61 convert{T<:Integer}(::Type{Rational{T}}, x::Integer) = Rational{T}(convert(T,x), convert(T,1))
6125749 @StefanKarpinski rationals: make conversion from float to rational exact.
StefanKarpinski authored
62
63 convert(::Type{Rational}, x::Rational) = x
64 convert(::Type{Rational}, x::Integer) = convert(Rational{typeof(x)},x)
65
68d4986 @simonbyrne Make Bool conversion consistent with other conversions
simonbyrne authored
66 convert(::Type{Bool}, x::Rational) = x==0 ? false : x==1 ? true : throw(InexactError()) # to resolve ambiguity
6125749 @StefanKarpinski rationals: make conversion from float to rational exact.
StefanKarpinski authored
67 convert{T<:Integer}(::Type{T}, x::Rational) = (isinteger(x) ? convert(T, x.num) : throw(InexactError()))
d265f4d @StefanKarpinski Rational: improved conversion to FloatingPoint.
StefanKarpinski authored
68
69 convert(::Type{FloatingPoint}, x::Rational) = float(x.num)/float(x.den)
005197a @carlobaldassi Better fix of Rational-to-BigFloat ambiguity warning
carlobaldassi authored
70 function convert{T<:FloatingPoint,S}(::Type{T}, x::Rational{S})
d265f4d @StefanKarpinski Rational: improved conversion to FloatingPoint.
StefanKarpinski authored
71 P = promote_type(T,S)
0f44abb @stevengj fix convert(T<:FloatingPoint, ::Rational) to return a result of type …
stevengj authored
72 convert(T, convert(P,x.num)/convert(P,x.den))
d265f4d @StefanKarpinski Rational: improved conversion to FloatingPoint.
StefanKarpinski authored
73 end
6125749 @StefanKarpinski rationals: make conversion from float to rational exact.
StefanKarpinski authored
74
75 function convert{T<:Integer}(::Type{Rational{T}}, x::FloatingPoint)
55ff643 @nolta fix #3412 (rational type is non-functional for Int < 64 bit)
nolta authored
76 r = rationalize(T, x, tol=0)
f8f0b03 @simonbyrne Adds explicit Rational{BigInt} convert method. Indirectly addresses #…
simonbyrne authored
77 x == convert(typeof(x), r) || throw(InexactError())
55ff643 @nolta fix #3412 (rational type is non-functional for Int < 64 bit)
nolta authored
78 r
6125749 @StefanKarpinski rationals: make conversion from float to rational exact.
StefanKarpinski authored
79 end
af2ca43 @StefanKarpinski convert(Rational, x::Float32) => Rational{Int32} on 32-bit platforms.
StefanKarpinski authored
80 convert(::Type{Rational}, x::Float64) = convert(Rational{Int64}, x)
81 convert(::Type{Rational}, x::Float32) = convert(Rational{Int}, x)
6125749 @StefanKarpinski rationals: make conversion from float to rational exact.
StefanKarpinski authored
82
83 promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{S}) = Rational{promote_type(T,S)}
84 promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{Rational{S}}) = Rational{promote_type(T,S)}
d6bc393 @StefanKarpinski promote(rational,float) => float again [#3378]
StefanKarpinski authored
85 promote_rule{T<:Integer,S<:FloatingPoint}(::Type{Rational{T}}, ::Type{S}) = promote_type(T,S)
6125749 @StefanKarpinski rationals: make conversion from float to rational exact.
StefanKarpinski authored
86
ce3f003 @JeffBezanson also export widemul (ref #6169)
JeffBezanson authored
87 widen{T}(::Type{Rational{T}}) = Rational{widen(T)}
88
6125749 @StefanKarpinski rationals: make conversion from float to rational exact.
StefanKarpinski authored
89 function rationalize{T<:Integer}(::Type{T}, x::FloatingPoint; tol::Real=eps(x))
7dd4145 @nolta fix #5935 (rationalize returns curious/incorrect values)
nolta authored
90 tol < 0 && throw(ArgumentError("negative tolerance"))
91 isnan(x) && return zero(T)//zero(T)
92 isinf(x) && return (x < 0 ? -one(T) : one(T))//zero(T)
f765ad8 @simonbyrne remove bigfloat dependence from rationalize
simonbyrne authored
93
94 p, q = (x < 0 ? -one(T) : one(T)), zero(T)
95 pp, qq = zero(T), one(T)
96
97 x = abs(x)
98 a = trunc(x)
99 r = x-a
100 y = one(x)
101
102 nt, t, tt = tol, zero(tol), zero(tol)
103
104 while r > nt
7dd4145 @nolta fix #5935 (rationalize returns curious/incorrect values)
nolta authored
105 try
f765ad8 @simonbyrne remove bigfloat dependence from rationalize
simonbyrne authored
106 ia = convert(T,a)
f1eca72 @simonbyrne fix try/catch error
simonbyrne authored
107 np = checked_add(checked_mul(ia,p),pp)
108 nq = checked_add(checked_mul(ia,q),qq)
109 p, pp = np, p
110 q, qq = nq, q
7dd4145 @nolta fix #5935 (rationalize returns curious/incorrect values)
nolta authored
111 catch e
f765ad8 @simonbyrne remove bigfloat dependence from rationalize
simonbyrne authored
112 isa(e,InexactError) || isa(e,OverflowError) || rethrow(e)
113 return p // q
7dd4145 @nolta fix #5935 (rationalize returns curious/incorrect values)
nolta authored
114 end
f765ad8 @simonbyrne remove bigfloat dependence from rationalize
simonbyrne authored
115
116 t, tt = nt, t
117 x, y = y, r
118
119 a, r = divrem(x,y)
120 nt = a*t + tt
121 end
122
123 # find optimal semiconvergent
124 # smallest a such that x-a*y < a*t+tt
125 a = cld(x-tt,y+t)
126 try
127 ia = convert(T,a)
f1eca72 @simonbyrne fix try/catch error
simonbyrne authored
128 np = checked_add(checked_mul(ia,p),pp)
129 nq = checked_add(checked_mul(ia,q),qq)
130 return np // nq
f765ad8 @simonbyrne remove bigfloat dependence from rationalize
simonbyrne authored
131 catch e
132 isa(e,InexactError) || isa(e,OverflowError) || rethrow(e)
133 return p // q
53af5d6 @StefanKarpinski Conversion from Float to Rational.
StefanKarpinski authored
134 end
135 end
7dd4145 @nolta fix #5935 (rationalize returns curious/incorrect values)
nolta authored
136 rationalize(x::FloatingPoint; kvs...) = rationalize(Int, x; kvs...)
e84315f @StefanKarpinski Only allow construction of Rationals in lowest terms.
StefanKarpinski authored
137
ae44b3a @StefanKarpinski Rename: Int => Integer, Uint => Unsigned.
StefanKarpinski authored
138 num(x::Integer) = x
139 den(x::Integer) = one(x)
329ffb5 @StefanKarpinski Fix & improve use of promotion for Complex and Rational types.
StefanKarpinski authored
140 num(x::Rational) = x.num
141 den(x::Rational) = x.den
82b1b4f @StefanKarpinski Rational: 0//0 is an error; fixes to rational conversion.
StefanKarpinski authored
142
4849ad7 @StefanKarpinski Simplified (and more correct) sign function for Rational.
StefanKarpinski authored
143 sign(x::Rational) = sign(x.num)
3228819 @StefanKarpinski More comprehensive tests for sign and signbit.
StefanKarpinski authored
144 signbit(x::Rational) = signbit(x.num)
24057e4 @StefanKarpinski Implement type-preserving copysign for non-floats.
StefanKarpinski authored
145 copysign(x::Rational, y::Real) = copysign(x.num,y) // x.den
146 copysign(x::Rational, y::Rational) = copysign(x.num,y.num) // x.den
82cb6bd @JeffBezanson extending generic type matching to find parameter assignments that
JeffBezanson authored
147
ae44b3a @StefanKarpinski Rename: Int => Integer, Uint => Unsigned.
StefanKarpinski authored
148 typemin{T<:Integer}(::Type{Rational{T}}) = -one(T)//zero(T)
149 typemax{T<:Integer}(::Type{Rational{T}}) = one(T)//zero(T)
82b1b4f @StefanKarpinski Rational: 0//0 is an error; fixes to rational conversion.
StefanKarpinski authored
150
9db1071 @simonbyrne rename isinteger/realvalued -> isinteger/real, isela -> iseltype
simonbyrne authored
151 isinteger(x::Rational) = x.den == 1
6f480df @StefanKarpinski Fix hashing for large ints and rational numbers.
StefanKarpinski authored
152
2c4e9e1 @StefanKarpinski Remove parens around operators; use 2(x+1) form.
StefanKarpinski authored
153 -(x::Rational) = (-x.num) // x.den
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
154 function -{T<:Signed}(x::Rational{T})
155 x.num == typemin(T) && throw(OverflowError())
156 (-x.num) // x.den
157 end
158 function -{T<:Unsigned}(x::Rational{T})
159 x.num != zero(T) && throw(OverflowError())
160 x
161 end
162
163 for (op,chop) in ((:+,:checked_add), (:-,:checked_sub),
164 (:rem,:rem), (:mod,:mod))
bec6fc5 @GunnarFarneback Avoid some overflow situations in lcm and rational +, -, rem, mod.
GunnarFarneback authored
165 @eval begin
166 function ($op)(x::Rational, y::Rational)
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
167 xd, yd = divgcd(x.den, y.den)
168 Rational(($chop)(checked_mul(x.num,yd), checked_mul(y.num,xd)), checked_mul(x.den,yd))
bec6fc5 @GunnarFarneback Avoid some overflow situations in lcm and rational +, -, rem, mod.
GunnarFarneback authored
169 end
170 end
171 end
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
172
173 function *(x::Rational, y::Rational)
174 xn,yd = divgcd(x.num,y.den)
175 xd,yn = divgcd(x.den,y.num)
176 checked_mul(xn,yn) // checked_mul(xd,yd)
177 end
178 /(x::Rational, y::Rational) = x//y
96339c9 @JeffBezanson use Complex instead of ComplexPair
JeffBezanson authored
179 /(x::Rational, z::Complex ) = inv(z/x)
6d3f8d4 @StefanKarpinski More complete arithmetics and promotions for ints, floats, and rats.
StefanKarpinski authored
180
a6c0250 @eschnett Implement `fma`
eschnett authored
181 fma(x::Rational, y::Rational, z::Rational) = x*y+z
182
f2f6351 @JeffBezanson === fallback can now replace == definitions for basic integer types
JeffBezanson authored
183 ==(x::Rational, y::Rational) = (x.den == y.den) & (x.num == y.num)
d4c4d2a @JeffBezanson fix overflows in rational comparisons. part of #2960
JeffBezanson authored
184 < (x::Rational, y::Rational) = x.den == y.den ? x.num < y.num :
185 widemul(x.num,y.den) < widemul(x.den,y.num)
186 <=(x::Rational, y::Rational) = x.den == y.den ? x.num <= y.num :
187 widemul(x.num,y.den) <= widemul(x.den,y.num)
892a1d3 @simonbyrne fix rational vs float comparisons (attempt 2)
simonbyrne authored
188
189
190 ==(x::Rational, y::Integer ) = (x.den == 1) & (x.num == y)
191 ==(x::Integer , y::Rational) = y == x
192 < (x::Rational, y::Integer ) = x.num < widemul(x.den,y)
193 < (x::Integer , y::Rational) = widemul(x,y.den) < y.num
d4c4d2a @JeffBezanson fix overflows in rational comparisons. part of #2960
JeffBezanson authored
194 <=(x::Rational, y::Integer ) = x.num <= widemul(x.den,y)
195 <=(x::Integer , y::Rational) = widemul(x,y.den) <= y.num
892a1d3 @simonbyrne fix rational vs float comparisons (attempt 2)
simonbyrne authored
196
197 function ==(x::FloatingPoint, q::Rational)
198 if isfinite(x)
199 (count_ones(q.den) == 1) & (x*q.den == q.num)
200 else
201 x == q.num/q.den
202 end
203 end
204
205 ==(q::Rational, x::FloatingPoint) = x == q
206
207 for rel in (:<,:<=,:cmp)
208 for (Tx,Ty) in ((Rational,FloatingPoint), (FloatingPoint,Rational))
209 @eval function ($rel)(x::$Tx, y::$Ty)
210 if isnan(x) || isnan(y)
211 $(rel == :cmp ? :(throw(DomainError())) : :(return false))
212 end
213
214 xn, xp, xd = decompose(x)
215 yn, yp, yd = decompose(y)
216
217 if xd < 0
218 xn = -xn
219 xd = -xd
220 end
221 if yd < 0
222 yn = -yn
223 yd = -yd
224 end
225
226 xc, yc = widemul(xn,yd), widemul(yn,xd)
227 xs, ys = sign(xc), sign(yc)
228
229 if xs != ys
230 return ($rel)(xs,ys)
231 elseif xs == 0
232 # both are zero or ±Inf
233 return ($rel)(xn,yn)
234 end
235
236 xb, yb = ndigits0z(xc,2) + xp, ndigits0z(yc,2) + yp
237
238 if xb == yb
239 xc, yc = promote(xc,yc)
240 if xp > yp
241 xc = (xc<<(xp-yp))
242 else
243 yc = (yc<<(yp-xp))
244 end
245 return ($rel)(xc,yc)
246 else
247 return xc > 0 ? ($rel)(xb,yb) : ($rel)(yb,xb)
248 end
249 end
250 end
251 end
252
253 # needed to avoid ambiguity between ==(x::Real, z::Complex) and ==(x::Rational, y::Number)
254 ==(z::Complex , x::Rational) = isreal(z) & (real(z) == x)
255 ==(x::Rational, z::Complex ) = isreal(z) & (real(z) == x)
c94aa9a @StefanKarpinski Better fld operation support for Rational (and thereby better mod).
StefanKarpinski authored
256
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
257 for op in (:div, :fld, :cld)
258 @eval begin
259 function ($op)(x::Rational, y::Integer )
260 xn,yn = divgcd(x.num,y)
261 ($op)(xn, checked_mul(x.den,yn))
262 end
263 function ($op)(x::Integer, y::Rational)
264 xn,yn = divgcd(x,y.num)
265 ($op)(checked_mul(xn,y.den), yn)
266 end
267 function ($op)(x::Rational, y::Rational)
268 xn,yn = divgcd(x.num,y.num)
269 xd,yd = divgcd(x.den,y.den)
270 ($op)(checked_mul(xn,yd), checked_mul(xd,yn))
271 end
272 end
273 end
d887aba @eschnett Implement cld
eschnett authored
274
a4ed7d4 @simonbyrne Changes behaviour of round to use default rounding mode (#8750).
simonbyrne authored
275 trunc{T}(::Type{T}, x::Rational) = convert(T,div(x.num,x.den))
276 floor{T}(::Type{T}, x::Rational) = convert(T,fld(x.num,x.den))
277 ceil {T}(::Type{T}, x::Rational) = convert(T,cld(x.num,x.den))
278
2999af2 @simonbyrne make rounding name modes consistent with symbols
simonbyrne authored
279 function round{T}(::Type{T}, x::Rational, ::RoundingMode{:Nearest})
a4ed7d4 @simonbyrne Changes behaviour of round to use default rounding mode (#8750).
simonbyrne authored
280 q,r = divrem(x.num,x.den)
281 s = abs(r) < (x.den+one(x.den)+iseven(q))>>1 ? q : q+copysign(one(q),x.num)
282 convert(T,s)
283 end
284 round{T}(::Type{T}, x::Rational) = round(T,x,RoundNearest)
2999af2 @simonbyrne make rounding name modes consistent with symbols
simonbyrne authored
285 function round{T}(::Type{T}, x::Rational, ::RoundingMode{:NearestTiesAway})
a4ed7d4 @simonbyrne Changes behaviour of round to use default rounding mode (#8750).
simonbyrne authored
286 q,r = divrem(x.num,x.den)
287 s = abs(r) < (x.den+one(x.den))>>1 ? q : q+copysign(one(q),x.num)
288 convert(T,s)
289 end
2999af2 @simonbyrne make rounding name modes consistent with symbols
simonbyrne authored
290 function round{T}(::Type{T}, x::Rational, ::RoundingMode{:NearestTiesUp})
a4ed7d4 @simonbyrne Changes behaviour of round to use default rounding mode (#8750).
simonbyrne authored
291 q,r = divrem(x.num,x.den)
292 s = abs(r) < (x.den+one(x.den)+(x.num<0))>>1 ? q : q+copysign(one(q),x.num)
293 convert(T,s)
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
294 end
0b89c34 @StefanKarpinski Better length calculation for non-integer ranges.
StefanKarpinski authored
295
aebf40f @simonbyrne itrunc -> trunc, etc, improve iround
simonbyrne authored
296 trunc{T}(x::Rational{T}) = Rational(trunc(T,x))
297 floor{T}(x::Rational{T}) = Rational(floor(T,x))
298 ceil {T}(x::Rational{T}) = Rational(ceil(T,x))
299 round{T}(x::Rational{T}) = Rational(round(T,x))
0b89c34 @StefanKarpinski Better length calculation for non-integer ranges.
StefanKarpinski authored
300
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
301 function ^(x::Rational, n::Integer)
302 n >= 0 ? power_by_squaring(x,n) : power_by_squaring(inv(x),-n)
303 end
8049e73 @JeffBezanson fix #1403
JeffBezanson authored
304
305 ^(x::Number, y::Rational) = x^(y.num/y.den)
8282780 @stevengj ^(x,y::Rational) should promote y to correct type relative to typeof(…
stevengj authored
306 ^{T<:FloatingPoint}(x::T, y::Rational) = x^(convert(T,y.num)/y.den)
307 ^{T<:FloatingPoint}(x::Complex{T}, y::Rational) = x^(convert(T,y.num)/y.den)
06530b6 @JeffBezanson more improvements to complex ^, for #3246
JeffBezanson authored
308
77a8888 @StefanKarpinski MathConst special behavior: e^x = exp(x)
StefanKarpinski authored
309 ^{T<:Rational}(z::Complex{T}, n::Bool) = n ? z : one(z) # to resolve ambiguity
bd9e36a @simonbyrne make rational arithmetic use checked ops
simonbyrne authored
310 function ^{T<:Rational}(z::Complex{T}, n::Integer)
311 n >= 0 ? power_by_squaring(z,n) : power_by_squaring(inv(z),-n)
312 end
Something went wrong with that request. Please try again.