@@ -27,10 +27,7 @@ module FixedPointDecimals
27
27
28
28
export FixedDecimal, RoundThrows
29
29
30
- import Base: reinterpret, zero, one, abs, sign, == , < , <= , + , - , / , * , div, rem, divrem,
31
- fld, mod, fldmod, fld1, mod1, fldmod1, isinteger, typemin, typemax,
32
- print, show, string, convert, parse, promote_rule, min, max,
33
- floatmin, floatmax, trunc, round, floor, ceil, eps, float, widemul, decompose
30
+ using Base: decompose
34
31
35
32
const BitInteger = Union{Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64,
36
33
UInt64, Int128, UInt128}
@@ -114,22 +111,22 @@ floattype(::Type{<:FD{T}}) where {T<:Integer} = Float64
114
111
floattype (:: Type{<:FD{BigInt}} ) = BigFloat
115
112
116
113
# basic operators
117
- - (x:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, - x. i)
118
- abs (x:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, abs (x. i))
114
+ Base.: - (x:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, - x. i)
115
+ Base . abs (x:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, abs (x. i))
119
116
120
- + (x:: FD{T, f} , y:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, x. i+ y. i)
121
- - (x:: FD{T, f} , y:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, x. i- y. i)
117
+ Base.: + (x:: FD{T, f} , y:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, x. i+ y. i)
118
+ Base.: - (x:: FD{T, f} , y:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, x. i- y. i)
122
119
123
120
# wide multiplication
124
- Base. @pure function widemul (x:: FD{<:Any, f} , y:: FD{<:Any, g} ) where {f, g}
121
+ Base. @pure function Base . widemul (x:: FD{<:Any, f} , y:: FD{<:Any, g} ) where {f, g}
125
122
i = widemul (x. i, y. i)
126
123
reinterpret (FD{typeof (i), f + g}, i)
127
124
end
128
- Base. @pure function widemul (x:: FD{T, f} , y:: Integer ) where {T, f}
125
+ Base. @pure function Base . widemul (x:: FD{T, f} , y:: Integer ) where {T, f}
129
126
i = widemul (x. i, y)
130
127
reinterpret (FD{typeof (i), f}, i)
131
128
end
132
- Base. @pure widemul (x:: Integer , y:: FD ) = widemul (y, x)
129
+ Base. @pure Base . widemul (x:: Integer , y:: FD ) = widemul (y, x)
133
130
134
131
"""
135
132
_round_to_even(quotient, remainder, divisor)
@@ -160,48 +157,48 @@ _round_to_even(q, r, d) = _round_to_even(promote(q, r, d)...)
160
157
# multiplication rounds to nearest even representation
161
158
# TODO : can we use floating point to speed this up? after we build a
162
159
# correctness test suite.
163
- function * (x:: FD{T, f} , y:: FD{T, f} ) where {T, f}
160
+ function Base.: * (x:: FD{T, f} , y:: FD{T, f} ) where {T, f}
164
161
powt = coefficient (FD{T, f})
165
162
quotient, remainder = fldmodinline (widemul (x. i, y. i), powt)
166
163
reinterpret (FD{T, f}, _round_to_even (quotient, remainder, powt))
167
164
end
168
165
169
166
# these functions are needed to avoid InexactError when converting from the
170
167
# integer type
171
- * (x:: Integer , y:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, T (x * y. i))
172
- * (x:: FD{T, f} , y:: Integer ) where {T, f} = reinterpret (FD{T, f}, T (x. i * y))
168
+ Base.: * (x:: Integer , y:: FD{T, f} ) where {T, f} = reinterpret (FD{T, f}, T (x * y. i))
169
+ Base.: * (x:: FD{T, f} , y:: Integer ) where {T, f} = reinterpret (FD{T, f}, T (x. i * y))
173
170
174
- function / (x:: FD{T, f} , y:: FD{T, f} ) where {T, f}
171
+ function Base.: / (x:: FD{T, f} , y:: FD{T, f} ) where {T, f}
175
172
powt = coefficient (FD{T, f})
176
173
quotient, remainder = fldmod (widemul (x. i, powt), y. i)
177
174
reinterpret (FD{T, f}, T (_round_to_even (quotient, remainder, y. i)))
178
175
end
179
176
180
177
# These functions allow us to perform division with integers outside of the range of the
181
178
# FixedDecimal.
182
- function / (x:: Integer , y:: FD{T, f} ) where {T, f}
179
+ function Base.: / (x:: Integer , y:: FD{T, f} ) where {T, f}
183
180
powt = coefficient (FD{T, f})
184
181
powtsq = widemul (powt, powt)
185
182
quotient, remainder = fldmod (widemul (x, powtsq), y. i)
186
183
reinterpret (FD{T, f}, T (_round_to_even (quotient, remainder, y. i)))
187
184
end
188
185
189
- function / (x:: FD{T, f} , y:: Integer ) where {T, f}
186
+ function Base.: / (x:: FD{T, f} , y:: Integer ) where {T, f}
190
187
quotient, remainder = fldmod (x. i, y)
191
188
reinterpret (FD{T, f}, T (_round_to_even (quotient, remainder, y)))
192
189
end
193
190
194
191
# integerification
195
- trunc (x:: FD{T, f} ) where {T, f} = FD {T, f} (div (x. i, coefficient (FD{T, f})))
196
- floor (x:: FD{T, f} ) where {T, f} = FD {T, f} (fld (x. i, coefficient (FD{T, f})))
192
+ Base . trunc (x:: FD{T, f} ) where {T, f} = FD {T, f} (div (x. i, coefficient (FD{T, f})))
193
+ Base . floor (x:: FD{T, f} ) where {T, f} = FD {T, f} (fld (x. i, coefficient (FD{T, f})))
197
194
198
195
# TODO : round with number of digits; should be easy
199
- function round (x:: FD{T, f} , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
196
+ function Base . round (x:: FD{T, f} , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
200
197
powt = coefficient (FD{T, f})
201
198
quotient, remainder = fldmodinline (x. i, powt)
202
199
FD {T, f} (_round_to_even (quotient, remainder, powt))
203
200
end
204
- function ceil (x:: FD{T, f} ) where {T, f}
201
+ function Base . ceil (x:: FD{T, f} ) where {T, f}
205
202
powt = coefficient (FD{T, f})
206
203
quotient, remainder = fldmodinline (x. i, powt)
207
204
if remainder > 0
@@ -243,44 +240,44 @@ end
243
240
_apply_exact_float (f, :: Type{T} , x:: Real , i:: Integer ) where T = f (T, x, i)
244
241
245
242
for fn in [:trunc , :floor , :ceil ]
246
- @eval ($ fn (:: Type{TI} , x:: FD ):: TI ) where {TI <: Integer } = $ fn (x)
243
+ @eval (Base. $ fn (:: Type{TI} , x:: FD ):: TI ) where {TI <: Integer } = $ fn (x)
247
244
248
245
# round/trunc/ceil/flooring to FD; generic
249
- @eval function $fn (:: Type{FD{T, f}} , x:: Real ) where {T, f}
246
+ @eval function Base . $fn (:: Type{FD{T, f}} , x:: Real ) where {T, f}
250
247
powt = coefficient (FD{T, f})
251
248
# Use machine Float64 if possible, but fall back to BigFloat if we need
252
249
# more precision. 4f bits suffices.
253
250
val = _apply_exact_float ($ (Symbol (fn, " mul" )), T, x, powt)
254
251
reinterpret (FD{T, f}, val)
255
252
end
256
253
end
257
- function round (:: Type{TI} , x:: FD , :: RoundingMode{:Nearest} = RoundNearest) where {TI <: Integer }
254
+ function Base . round (:: Type{TI} , x:: FD , :: RoundingMode{:Nearest} = RoundNearest) where {TI <: Integer }
258
255
convert (TI, round (x)):: TI
259
256
end
260
- function round (:: Type{FD{T, f}} , x:: Real , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
257
+ function Base . round (:: Type{FD{T, f}} , x:: Real , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
261
258
reinterpret (FD{T, f}, round (T, x * coefficient (FD{T, f})))
262
259
end
263
260
264
261
# needed to avoid ambiguity
265
- function round (:: Type{FD{T, f}} , x:: Rational , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
262
+ function Base . round (:: Type{FD{T, f}} , x:: Rational , :: RoundingMode{:Nearest} = RoundNearest) where {T, f}
266
263
reinterpret (FD{T, f}, round (T, x * coefficient (FD{T, f})))
267
264
end
268
265
269
266
# conversions and promotions
270
- convert (:: Type{FD{T, f}} , x:: FD{T, f} ) where {T, f} = x # Converting an FD to itself is a no-op
267
+ Base . convert (:: Type{FD{T, f}} , x:: FD{T, f} ) where {T, f} = x # Converting an FD to itself is a no-op
271
268
272
- function convert (:: Type{FD{T, f}} , x:: Integer ) where {T, f}
269
+ function Base . convert (:: Type{FD{T, f}} , x:: Integer ) where {T, f}
273
270
reinterpret (FD{T, f}, T (widemul (x, coefficient (FD{T, f}))))
274
271
end
275
272
276
- convert (:: Type{T} , x:: AbstractFloat ) where {T <: FD } = round (T, x)
273
+ Base . convert (:: Type{T} , x:: AbstractFloat ) where {T <: FD } = round (T, x)
277
274
278
- function convert (:: Type{FD{T, f}} , x:: Rational ) where {T, f}
275
+ function Base . convert (:: Type{FD{T, f}} , x:: Rational ) where {T, f}
279
276
powt = coefficient (FD{T, f})
280
277
reinterpret (FD{T, f}, T (x * powt)):: FD{T, f}
281
278
end
282
279
283
- function convert (:: Type{FD{T, f}} , x:: FD{U, g} ) where {T, f, U, g}
280
+ function Base . convert (:: Type{FD{T, f}} , x:: FD{U, g} ) where {T, f, U, g}
284
281
if f ≥ g
285
282
# Compute `10^(f - g)` without overflow
286
283
powt = div (coefficient (FD{T, f}), coefficient (FD{U, g}))
@@ -298,7 +295,7 @@ function convert(::Type{FD{T, f}}, x::FD{U, g}) where {T, f, U, g}
298
295
end
299
296
300
297
for remfn in [:rem , :mod , :mod1 , :min , :max ]
301
- @eval $ remfn (x:: T , y:: T ) where {T <: FD } = reinterpret (T, $ remfn (x. i, y. i))
298
+ @eval Base. $ remfn (x:: T , y:: T ) where {T <: FD } = reinterpret (T, $ remfn (x. i, y. i))
302
299
end
303
300
# TODO : When we upgrade to a min julia version >=1.4 (i.e Julia 2.0), this block can be
304
301
# dropped in favor of three-argument `div`, below.
@@ -313,33 +310,33 @@ if VERSION >= v"1.4.0-"
313
310
Base. div (x:: T , y:: T , r:: RoundingMode ) where {T <: FD } = T (div (x. i, y. i, r))
314
311
end
315
312
316
- convert (:: Type{AbstractFloat} , x:: FD ) = convert (floattype (typeof (x)), x)
317
- function convert (:: Type{TF} , x:: FD{T, f} ) where {TF <: AbstractFloat , T, f}
313
+ Base . convert (:: Type{AbstractFloat} , x:: FD ) = convert (floattype (typeof (x)), x)
314
+ function Base . convert (:: Type{TF} , x:: FD{T, f} ) where {TF <: AbstractFloat , T, f}
318
315
convert (TF, x. i / coefficient (FD{T, f})):: TF
319
316
end
320
317
321
- function convert (:: Type{TF} , x:: FD{T, f} ) where {TF <: BigFloat , T, f}
318
+ function Base . convert (:: Type{TF} , x:: FD{T, f} ) where {TF <: BigFloat , T, f}
322
319
convert (TF, BigInt (x. i) / BigInt (coefficient (FD{T, f}))):: TF
323
320
end
324
321
325
- function convert (:: Type{TI} , x:: FD{T, f} ) where {TI <: Integer , T, f}
322
+ function Base . convert (:: Type{TI} , x:: FD{T, f} ) where {TI <: Integer , T, f}
326
323
isinteger (x) || throw (InexactError (:convert , TI, x))
327
324
convert (TI, div (x. i, coefficient (FD{T, f}))):: TI
328
325
end
329
326
330
- function convert (:: Type{TR} , x:: FD{T, f} ) where {TR <: Rational , T, f}
327
+ function Base . convert (:: Type{TR} , x:: FD{T, f} ) where {TR <: Rational , T, f}
331
328
convert (TR, x. i // coefficient (FD{T, f})):: TR
332
329
end
333
330
334
331
(:: Type{T} )(x:: FD ) where {T<: Union{AbstractFloat,Integer,Rational} } = convert (T, x)
335
332
336
- promote_rule (:: Type{FD{T, f}} , :: Type{<:Integer} ) where {T, f} = FD{T, f}
337
- promote_rule (:: Type{<:FD} , :: Type{TF} ) where {TF <: AbstractFloat } = TF
338
- promote_rule (:: Type{<:FD} , :: Type{Rational{TR}} ) where {TR} = Rational{TR}
333
+ Base . promote_rule (:: Type{FD{T, f}} , :: Type{<:Integer} ) where {T, f} = FD{T, f}
334
+ Base . promote_rule (:: Type{<:FD} , :: Type{TF} ) where {TF <: AbstractFloat } = TF
335
+ Base . promote_rule (:: Type{<:FD} , :: Type{Rational{TR}} ) where {TR} = Rational{TR}
339
336
340
337
# TODO : decide if these are the right semantics;
341
338
# right now we pick the bigger int type and the bigger decimal point
342
- Base. @pure function promote_rule (:: Type{FD{T, f}} , :: Type{FD{U, g}} ) where {T, f, U, g}
339
+ Base. @pure function Base . promote_rule (:: Type{FD{T, f}} , :: Type{FD{U, g}} ) where {T, f, U, g}
343
340
FD{promote_type (T, U), max (f, g)}
344
341
end
345
342
@@ -348,24 +345,24 @@ Base.zero(::Type{FD{T, f}}) where {T, f} = reinterpret(FD{T, f}, zero(T))
348
345
Base. one (:: Type{FD{T, f}} ) where {T, f} = reinterpret (FD{T, f}, coefficient (FD{T, f}))
349
346
350
347
# comparison
351
- == (x:: T , y:: T ) where {T <: FD } = x. i == y. i
352
- < (x:: T , y:: T ) where {T <: FD } = x. i < y. i
353
- <= (x:: T , y:: T ) where {T <: FD } = x. i <= y. i
348
+ Base.:( == ) (x:: T , y:: T ) where {T <: FD } = x. i == y. i
349
+ Base.:( < ) (x:: T , y:: T ) where {T <: FD } = x. i < y. i
350
+ Base.:( <= ) (x:: T , y:: T ) where {T <: FD } = x. i <= y. i
354
351
355
352
# predicates and traits
356
- isinteger (x:: FD{T, f} ) where {T, f} = rem (x. i, coefficient (FD{T, f})) == 0
357
- typemin (:: Type{FD{T, f}} ) where {T, f} = reinterpret (FD{T, f}, typemin (T))
358
- typemax (:: Type{FD{T, f}} ) where {T, f}= reinterpret (FD{T, f}, typemax (T))
359
- eps (:: Type{T} ) where {T <: FD } = reinterpret (T, 1 )
360
- eps (x:: FD ) = eps (typeof (x))
361
- floatmin (:: Type{T} ) where {T <: FD } = eps (T)
362
- floatmax (:: Type{T} ) where {T <: FD } = typemax (T)
353
+ Base . isinteger (x:: FD{T, f} ) where {T, f} = rem (x. i, coefficient (FD{T, f})) == 0
354
+ Base . typemin (:: Type{FD{T, f}} ) where {T, f} = reinterpret (FD{T, f}, typemin (T))
355
+ Base . typemax (:: Type{FD{T, f}} ) where {T, f}= reinterpret (FD{T, f}, typemax (T))
356
+ Base . eps (:: Type{T} ) where {T <: FD } = reinterpret (T, 1 )
357
+ Base . eps (x:: FD ) = eps (typeof (x))
358
+ Base . floatmin (:: Type{T} ) where {T <: FD } = eps (T)
359
+ Base . floatmax (:: Type{T} ) where {T <: FD } = typemax (T)
363
360
364
361
# printing
365
- function print (io:: IO , x:: FD{T, 0} ) where T
362
+ function Base . print (io:: IO , x:: FD{T, 0} ) where T
366
363
print (io, x. i)
367
364
end
368
- function print (io:: IO , x:: FD{T, f} ) where {T, f}
365
+ function Base . print (io:: IO , x:: FD{T, f} ) where {T, f}
369
366
iscompact = get (io, :compact , false )
370
367
371
368
# note: a is negative if x.i == typemin(x.i)
@@ -387,7 +384,7 @@ function print(io::IO, x::FD{T, f}) where {T, f}
387
384
print (io, integer, ' .' , fractionchars)
388
385
end
389
386
390
- function show (io:: IO , x:: FD{T, f} ) where {T, f}
387
+ function Base . show (io:: IO , x:: FD{T, f} ) where {T, f}
391
388
iscompact = get (io, :compact , false )
392
389
if ! iscompact
393
390
print (io, " FixedDecimal{$T ,$f }(" )
@@ -407,7 +404,7 @@ Raises an `InexactError` if any rounding is necessary.
407
404
"""
408
405
const RoundThrows = RoundingMode {:Throw} ()
409
406
410
- function parse (:: Type{FD{T, f}} , str:: AbstractString , mode:: RoundingMode = RoundNearest) where {T, f}
407
+ function Base . parse (:: Type{FD{T, f}} , str:: AbstractString , mode:: RoundingMode = RoundNearest) where {T, f}
411
408
if ! (mode in [RoundThrows, RoundNearest, RoundToZero])
412
409
throw (ArgumentError (" Unhandled rounding mode $mode " ))
413
410
end
@@ -514,6 +511,6 @@ Base.@pure coefficient(fd::FD{T, f}) where {T, f} = coefficient(FD{T, f})
514
511
value (fd:: FD ) = fd. i
515
512
516
513
# for generic hashing
517
- decompose (fd:: FD ) = decompose (Rational (fd))
514
+ Base . decompose (fd:: FD ) = decompose (Rational (fd))
518
515
519
516
end
0 commit comments