Skip to content

Commit 317c82b

Browse files
committed
Remove unsafe @pure: for max_exp10, @eval in a loop instead
1 parent 5877a58 commit 317c82b

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

src/FixedPointDecimals.jl

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

2828
export FixedDecimal, RoundThrows
2929

30-
using Base: decompose
31-
32-
const BitInteger = Union{Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64,
33-
UInt64, Int128, UInt128}
30+
using Base: decompose, BitInteger
3431

3532
# floats that support fma and are roughly IEEE-like
3633
const FMAFloat = Union{Float16, Float32, Float64, BigFloat}
@@ -472,8 +469,17 @@ end
472469
473470
The highest value of `x` which does not result in an overflow when evaluating `T(10)^x`. For
474471
types of `T` that do not overflow -1 will be returned.
472+
473+
NOTE: This function is expensive, since it contains a while-loop, but it is actually
474+
computing a constant value for types, so it really only needs to be run once per type.
475+
We achieve this by `@eval`ing new methods in a loop, below. Users can do this
476+
themselves to add more "frozen" methods for custom Integer types:
477+
```julia
478+
@eval FixedPointDecimals.max_exp10(::Type{CustomIntType}) = \$(max_exp10(CustomIntType))
479+
```
480+
This function does not have or depend on any side-effects.
475481
"""
476-
Base.@pure function max_exp10(::Type{T}) where {T <: Integer}
482+
function max_exp10(::Type{T}) where {T <: Integer}
477483
# This function is marked as `Base.@pure`. Even though it does call some generic
478484
# functions, they are all simple methods that should be able to be evaluated as
479485
# constants. This function does not have or depend on any side-effects.
@@ -494,9 +500,12 @@ Base.@pure function max_exp10(::Type{T}) where {T <: Integer}
494500
end
495501

496502
max_exp10(::Type{BigInt}) = -1
497-
# Freeze the evaluation for Int128, since max_exp10(Int128) is too compilicated to get
498-
# optimized away by the compiler during const-folding.
499-
@eval max_exp10(::Type{Int128}) = $(max_exp10(Int128))
503+
# Freeze the evaluation for BitInteger types, since max_exp10() is too compilicated to get
504+
# optimized away by the compiler during const-folding. (We can't freeze for user-defined
505+
# types because we don't know what they are yet.)
506+
for T in Base.BitInteger_types
507+
@eval max_exp10(::Type{$T}) = $(max_exp10(T))
508+
end
500509

501510
# coefficient is marked pure. This is needed to ensure that the result is always available
502511
# at compile time, and can therefore be used when optimizing mathematical operations.

0 commit comments

Comments
 (0)