@@ -35,6 +35,8 @@ export checked_abs, checked_add, checked_cld, checked_div, checked_fld,
35
35
checked_mod, checked_mul, checked_neg, checked_rem, checked_sub
36
36
37
37
using Base: decompose, BitInteger
38
+
39
+ import BitIntegers # For 128-bit _widemul / _widen
38
40
import Parsers
39
41
40
42
# floats that support fma and are roughly IEEE-like
@@ -118,6 +120,22 @@ function __init__()
118
120
return
119
121
end
120
122
123
+ # Custom widemul implementation to avoid the cost of widening to BigInt.
124
+ # FD{Int128} operations should widen to 256 bits internally, rather than to a BigInt.
125
+ const BitInteger128 = Union{Int128, UInt128}
126
+ _widemul (x, y) = widemul (x, y)
127
+ _widemul (x:: BitInteger128 , y) = _widemul (promote (x, y)... )
128
+ _widemul (x, y:: BitInteger128 ) = _widemul (promote (x, y)... )
129
+ _widemul (x:: Int128 , y:: Int128 ) = BitIntegers. Int256 (x) * BitIntegers. Int256 (y)
130
+ _widemul (x:: UInt128 , y:: UInt128 ) = BitIntegers. UInt256 (x) * BitIntegers. UInt256 (y)
131
+
132
+ # Custom widen implementation to avoid the cost of widening to BigInt.
133
+ # FD{Int128} operations should widen to 256 bits internally, rather than to a BigInt.
134
+ _widen (:: Type{Int128} ) = BitIntegers. Int256
135
+ _widen (:: Type{UInt128} ) = BitIntegers. UInt256
136
+ _widen (t) = widen (t)
137
+
138
+
121
139
(:: Type{T} )(x:: Real ) where {T <: FD } = convert (T, x)
122
140
123
141
floattype (:: Type{<:FD{T}} ) where {T<: Union{Int8, UInt8, Int16, UInt16} } = Float32
@@ -188,7 +206,7 @@ _round_to_nearest(q, r, d, m=RoundNearest) = _round_to_nearest(promote(q, r, d).
188
206
# correctness test suite.
189
207
function Base.:* (x:: FD{T, f} , y:: FD{T, f} ) where {T, f}
190
208
powt = coefficient (FD{T, f})
191
- quotient, remainder = fldmodinline (widemul (x. i, y. i), powt)
209
+ quotient, remainder = fldmodinline (_widemul (x. i, y. i), powt)
192
210
reinterpret (FD{T, f}, _round_to_nearest (quotient, remainder, powt))
193
211
end
194
212
@@ -416,7 +434,7 @@ function Base.checked_sub(x::T, y::T) where {T<:FD}
416
434
end
417
435
function Base. checked_mul (x:: FD{T,f} , y:: FD{T,f} ) where {T<: Integer ,f}
418
436
powt = coefficient (FD{T, f})
419
- quotient, remainder = fldmodinline (widemul (x. i, y. i), powt)
437
+ quotient, remainder = fldmodinline (_widemul (x. i, y. i), powt)
420
438
v = _round_to_nearest (quotient, remainder, powt)
421
439
typemin (T) <= v <= typemax (T) || Base. Checked. throw_overflowerr_binaryop (:* , x, y)
422
440
return reinterpret (FD{T, f}, T (v))
@@ -474,7 +492,7 @@ checked_rdiv(x::FD, y::FD) = checked_rdiv(promote(x, y)...)
474
492
475
493
function checked_rdiv (x:: FD{T,f} , y:: FD{T,f} ) where {T<: Integer ,f}
476
494
powt = coefficient (FD{T, f})
477
- quotient, remainder = fldmod (widemul (x. i, powt), y. i)
495
+ quotient, remainder = fldmod (_widemul (x. i, powt), y. i)
478
496
v = _round_to_nearest (quotient, remainder, y. i)
479
497
typemin (T) <= v <= typemax (T) || Base. Checked. throw_overflowerr_binaryop (:/ , x, y)
480
498
return reinterpret (FD{T, f}, v)
484
502
# FixedDecimal.
485
503
function checked_rdiv (x:: Integer , y:: FD{T, f} ) where {T<: Integer , f}
486
504
powt = coefficient (FD{T, f})
487
- powtsq = widemul (powt, powt)
488
- quotient, remainder = fldmod (widemul (x, powtsq), y. i)
505
+ powtsq = _widemul (powt, powt)
506
+ quotient, remainder = fldmod (_widemul (x, powtsq), y. i)
489
507
v = _round_to_nearest (quotient, remainder, y. i)
490
508
typemin (T) <= v <= typemax (T) || Base. Checked. throw_overflowerr_binaryop (:/ , x, y)
491
509
reinterpret (FD{T, f}, v)
@@ -722,7 +740,7 @@ NOTE: This function is expensive, since it contains a while-loop, but it is actu
722
740
This function does not have or depend on any side-effects.
723
741
"""
724
742
function max_exp10 (:: Type{T} ) where {T <: Integer }
725
- W = widen (T)
743
+ W = _widen (T)
726
744
type_max = W (typemax (T))
727
745
728
746
powt = one (W)
@@ -759,4 +777,4 @@ value(fd::FD) = fd.i
759
777
# for generic hashing
760
778
Base. decompose (fd:: FD ) = decompose (Rational (fd))
761
779
762
- end
780
+ end # module
0 commit comments