@@ -36,9 +36,11 @@ export checked_abs, checked_add, checked_cld, checked_div, checked_fld,
36
36
37
37
using Base: decompose, BitInteger
38
38
39
- import BitIntegers # For 128-bit _widemul / _widen
39
+ using BitIntegers: BitIntegers, UInt256, Int256
40
40
import Parsers
41
41
42
+ include (" fldmod-by-const.jl" )
43
+
42
44
# floats that support fma and are roughly IEEE-like
43
45
const FMAFloat = Union{Float16, Float32, Float64, BigFloat}
44
46
@@ -129,8 +131,10 @@ _widemul(x::Unsigned,y::Signed) = signed(_widen(x)) * _widen(y)
129
131
130
132
# Custom widen implementation to avoid the cost of widening to BigInt.
131
133
# FD{Int128} operations should widen to 256 bits internally, rather than to a BigInt.
132
- _widen (:: Type{Int128} ) = BitIntegers. Int256
133
- _widen (:: Type{UInt128} ) = BitIntegers. UInt256
134
+ _widen (:: Type{Int128} ) = Int256
135
+ _widen (:: Type{UInt128} ) = UInt256
136
+ _widen (:: Type{Int256} ) = BitIntegers. Int512
137
+ _widen (:: Type{UInt256} ) = BitIntegers. UInt512
134
138
_widen (t:: Type ) = widen (t)
135
139
_widen (x:: T ) where {T} = (_widen (T))(x)
136
140
@@ -196,18 +200,12 @@ function _round_to_nearest(quotient::T,
196
200
end
197
201
_round_to_nearest (q, r, d, m= RoundNearest) = _round_to_nearest (promote (q, r, d)... , m)
198
202
199
- # In many of our calls to fldmod, `y` is a constant (the coefficient, 10^f). However, since
200
- # `fldmod` is sometimes not being inlined, that constant information is not available to the
201
- # optimizer. We need an inlined version of fldmod so that the compiler can replace expensive
202
- # divide-by-power-of-ten instructions with the cheaper multiply-by-inverse-coefficient.
203
- @inline fldmodinline (x,y) = (fld (x,y), mod (x,y))
204
-
205
203
# multiplication rounds to nearest even representation
206
204
# TODO : can we use floating point to speed this up? after we build a
207
205
# correctness test suite.
208
206
function Base.:* (x:: FD{T, f} , y:: FD{T, f} ) where {T, f}
209
207
powt = coefficient (FD{T, f})
210
- quotient, remainder = fldmodinline (_widemul (x. i, y. i), powt)
208
+ quotient, remainder = fldmod_by_const (_widemul (x. i, y. i), Val ( powt) )
211
209
reinterpret (FD{T, f}, _round_to_nearest (quotient, remainder, powt))
212
210
end
213
211
@@ -234,12 +232,12 @@ function Base.round(x::FD{T, f},
234
232
RoundingMode{:NearestTiesUp },
235
233
RoundingMode{:NearestTiesAway }}= RoundNearest) where {T, f}
236
234
powt = coefficient (FD{T, f})
237
- quotient, remainder = fldmodinline (x. i, powt)
235
+ quotient, remainder = fldmod_by_const (x. i, Val ( powt) )
238
236
FD {T, f} (_round_to_nearest (quotient, remainder, powt, m))
239
237
end
240
238
function Base. ceil (x:: FD{T, f} ) where {T, f}
241
239
powt = coefficient (FD{T, f})
242
- quotient, remainder = fldmodinline (x. i, powt)
240
+ quotient, remainder = fldmod_by_const (x. i, Val ( powt) )
243
241
if remainder > 0
244
242
FD {T, f} (quotient + one (quotient))
245
243
else
@@ -435,7 +433,7 @@ function Base.checked_sub(x::T, y::T) where {T<:FD}
435
433
end
436
434
function Base. checked_mul (x:: FD{T,f} , y:: FD{T,f} ) where {T<: Integer ,f}
437
435
powt = coefficient (FD{T, f})
438
- quotient, remainder = fldmodinline (_widemul (x. i, y. i), powt)
436
+ quotient, remainder = fldmod_by_const (_widemul (x. i, y. i), Val ( powt) )
439
437
v = _round_to_nearest (quotient, remainder, powt)
440
438
typemin (T) <= v <= typemax (T) || Base. Checked. throw_overflowerr_binaryop (:* , x, y)
441
439
return reinterpret (FD{T, f}, T (v))
0 commit comments