Skip to content

Commit 5877a58

Browse files
committed
Explicitly extend Base functions (Base.foo(...) = ...) instead of imports.
Style concensus seems to be that extending via `imports` should be discouraged since it can lead to both accidentally extending functions, and accidentally _not_ extending the intended functions. This is a style-only change; there should be no substantive change at all.
1 parent b32b8b9 commit 5877a58

File tree

1 file changed

+53
-56
lines changed

1 file changed

+53
-56
lines changed

src/FixedPointDecimals.jl

Lines changed: 53 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ module FixedPointDecimals
2727

2828
export FixedDecimal, RoundThrows
2929

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
3431

3532
const BitInteger = Union{Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64,
3633
UInt64, Int128, UInt128}
@@ -114,22 +111,22 @@ floattype(::Type{<:FD{T}}) where {T<:Integer} = Float64
114111
floattype(::Type{<:FD{BigInt}}) = BigFloat
115112

116113
# 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))
119116

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)
122119

123120
# 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}
125122
i = widemul(x.i, y.i)
126123
reinterpret(FD{typeof(i), f + g}, i)
127124
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}
129126
i = widemul(x.i, y)
130127
reinterpret(FD{typeof(i), f}, i)
131128
end
132-
Base.@pure widemul(x::Integer, y::FD) = widemul(y, x)
129+
Base.@pure Base.widemul(x::Integer, y::FD) = widemul(y, x)
133130

134131
"""
135132
_round_to_even(quotient, remainder, divisor)
@@ -160,48 +157,48 @@ _round_to_even(q, r, d) = _round_to_even(promote(q, r, d)...)
160157
# multiplication rounds to nearest even representation
161158
# TODO: can we use floating point to speed this up? after we build a
162159
# 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}
164161
powt = coefficient(FD{T, f})
165162
quotient, remainder = fldmodinline(widemul(x.i, y.i), powt)
166163
reinterpret(FD{T, f}, _round_to_even(quotient, remainder, powt))
167164
end
168165

169166
# these functions are needed to avoid InexactError when converting from the
170167
# 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))
173170

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}
175172
powt = coefficient(FD{T, f})
176173
quotient, remainder = fldmod(widemul(x.i, powt), y.i)
177174
reinterpret(FD{T, f}, T(_round_to_even(quotient, remainder, y.i)))
178175
end
179176

180177
# These functions allow us to perform division with integers outside of the range of the
181178
# FixedDecimal.
182-
function /(x::Integer, y::FD{T, f}) where {T, f}
179+
function Base.:/(x::Integer, y::FD{T, f}) where {T, f}
183180
powt = coefficient(FD{T, f})
184181
powtsq = widemul(powt, powt)
185182
quotient, remainder = fldmod(widemul(x, powtsq), y.i)
186183
reinterpret(FD{T, f}, T(_round_to_even(quotient, remainder, y.i)))
187184
end
188185

189-
function /(x::FD{T, f}, y::Integer) where {T, f}
186+
function Base.:/(x::FD{T, f}, y::Integer) where {T, f}
190187
quotient, remainder = fldmod(x.i, y)
191188
reinterpret(FD{T, f}, T(_round_to_even(quotient, remainder, y)))
192189
end
193190

194191
# 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})))
197194

198195
# 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}
200197
powt = coefficient(FD{T, f})
201198
quotient, remainder = fldmodinline(x.i, powt)
202199
FD{T, f}(_round_to_even(quotient, remainder, powt))
203200
end
204-
function ceil(x::FD{T, f}) where {T, f}
201+
function Base.ceil(x::FD{T, f}) where {T, f}
205202
powt = coefficient(FD{T, f})
206203
quotient, remainder = fldmodinline(x.i, powt)
207204
if remainder > 0
@@ -243,44 +240,44 @@ end
243240
_apply_exact_float(f, ::Type{T}, x::Real, i::Integer) where T = f(T, x, i)
244241

245242
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)
247244

248245
# 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}
250247
powt = coefficient(FD{T, f})
251248
# Use machine Float64 if possible, but fall back to BigFloat if we need
252249
# more precision. 4f bits suffices.
253250
val = _apply_exact_float($(Symbol(fn, "mul")), T, x, powt)
254251
reinterpret(FD{T, f}, val)
255252
end
256253
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}
258255
convert(TI, round(x))::TI
259256
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}
261258
reinterpret(FD{T, f}, round(T, x * coefficient(FD{T, f})))
262259
end
263260

264261
# 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}
266263
reinterpret(FD{T, f}, round(T, x * coefficient(FD{T, f})))
267264
end
268265

269266
# 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
271268

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}
273270
reinterpret(FD{T, f}, T(widemul(x, coefficient(FD{T, f}))))
274271
end
275272

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)
277274

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}
279276
powt = coefficient(FD{T, f})
280277
reinterpret(FD{T, f}, T(x * powt))::FD{T, f}
281278
end
282279

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}
284281
if f g
285282
# Compute `10^(f - g)` without overflow
286283
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}
298295
end
299296

300297
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))
302299
end
303300
# TODO: When we upgrade to a min julia version >=1.4 (i.e Julia 2.0), this block can be
304301
# dropped in favor of three-argument `div`, below.
@@ -313,33 +310,33 @@ if VERSION >= v"1.4.0-"
313310
Base.div(x::T, y::T, r::RoundingMode) where {T <: FD} = T(div(x.i, y.i, r))
314311
end
315312

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}
318315
convert(TF, x.i / coefficient(FD{T, f}))::TF
319316
end
320317

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}
322319
convert(TF, BigInt(x.i) / BigInt(coefficient(FD{T, f})))::TF
323320
end
324321

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}
326323
isinteger(x) || throw(InexactError(:convert, TI, x))
327324
convert(TI, div(x.i, coefficient(FD{T, f})))::TI
328325
end
329326

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}
331328
convert(TR, x.i // coefficient(FD{T, f}))::TR
332329
end
333330

334331
(::Type{T})(x::FD) where {T<:Union{AbstractFloat,Integer,Rational}} = convert(T, x)
335332

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}
339336

340337
# TODO: decide if these are the right semantics;
341338
# 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}
343340
FD{promote_type(T, U), max(f, g)}
344341
end
345342

@@ -348,24 +345,24 @@ Base.zero(::Type{FD{T, f}}) where {T, f} = reinterpret(FD{T, f}, zero(T))
348345
Base.one(::Type{FD{T, f}}) where {T, f} = reinterpret(FD{T, f}, coefficient(FD{T, f}))
349346

350347
# 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
354351

355352
# 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)
363360

364361
# printing
365-
function print(io::IO, x::FD{T, 0}) where T
362+
function Base.print(io::IO, x::FD{T, 0}) where T
366363
print(io, x.i)
367364
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}
369366
iscompact = get(io, :compact, false)
370367

371368
# 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}
387384
print(io, integer, '.', fractionchars)
388385
end
389386

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}
391388
iscompact = get(io, :compact, false)
392389
if !iscompact
393390
print(io, "FixedDecimal{$T,$f}(")
@@ -407,7 +404,7 @@ Raises an `InexactError` if any rounding is necessary.
407404
"""
408405
const RoundThrows = RoundingMode{:Throw}()
409406

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}
411408
if !(mode in [RoundThrows, RoundNearest, RoundToZero])
412409
throw(ArgumentError("Unhandled rounding mode $mode"))
413410
end
@@ -514,6 +511,6 @@ Base.@pure coefficient(fd::FD{T, f}) where {T, f} = coefficient(FD{T, f})
514511
value(fd::FD) = fd.i
515512

516513
# for generic hashing
517-
decompose(fd::FD) = decompose(Rational(fd))
514+
Base.decompose(fd::FD) = decompose(Rational(fd))
518515

519516
end

0 commit comments

Comments
 (0)