Skip to content

Commit

Permalink
Correct exponent_max to conform to IEEE definition (#38929)
Browse files Browse the repository at this point in the history
* Exponent exponent_max returns actual maximum exponent, not the sentinel.


Co-authored-by: mschauer <[email protected]>
  • Loading branch information
musm and mschauer committed Dec 20, 2020
1 parent 1887550 commit 58d6684
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 6 deletions.
26 changes: 25 additions & 1 deletion base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,35 @@ for T in (Float16, Float32, Float64)
@eval exponent_bits(::Type{$T}) = $(sizeof(T)*8 - significand_bits(T) - 1)
@eval exponent_bias(::Type{$T}) = $(Int(exponent_one(T) >> significand_bits(T)))
# maximum float exponent
@eval exponent_max(::Type{$T}) = $(Int(exponent_mask(T) >> significand_bits(T)) - exponent_bias(T))
@eval exponent_max(::Type{$T}) = $(Int(exponent_mask(T) >> significand_bits(T)) - exponent_bias(T) - 1)
# maximum float exponent without bias
@eval exponent_raw_max(::Type{$T}) = $(Int(exponent_mask(T) >> significand_bits(T)))
end

"""
exponent_max(T)
Maximum [`exponent`](@ref) value for a floating point number of type `T`.
# Examples
```jldoctest
julia> Base.exponent_max(Float64)
1023
```
Note, `exponent_max(T) + 1` is a possible value of the exponent field
with bias, which might be used as sentinel value for `Inf` or `NaN`.
"""
function exponent_max end

"""
exponent_raw_max(T)
Maximum value of the [`exponent`](@ref) field for a floating point number of type `T` without bias,
i.e. the maximum integer value representable by [`exponent_bits(T)`](@ref) bits.
"""
function exponent_raw_max end

## conversions to floating-point ##

# TODO: deprecate in 2.0
Expand Down
2 changes: 1 addition & 1 deletion base/ryu/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ end
"""
function pow5invsplit_lookup end
for T in (Float64, Float32, Float16)
e2_max = exponent_max(T) - precision(T) - 2
e2_max = exponent_max(T) - precision(T) - 1
i_max = log10pow2(e2_max)
table_sym = Symbol("pow5invsplit_table_", string(T))
@eval const $table_sym = Tuple(Any[pow5invsplit($T, i) for i = 0:$i_max])
Expand Down
2 changes: 1 addition & 1 deletion base/special/exp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ for (func, base) in (:exp2=>Val(2), :exp=>Val(:ℯ), :exp10=>Val(10))
twopk = reinterpret(T, (N+Int32(151)) << Int32(23))
return (twopk*small_part)*(2f0^(-24))
end
N == exponent_max(T) && return small_part * T(2.0) * T(2.0)^(exponent_max(T) - 1)
N == (exponent_max(T)+1) && return small_part * T(2.0) * T(2.0)^exponent_max(T)
end
twopk = reinterpret(T, (N+Int32(127)) << Int32(23))
return twopk*small_part
Expand Down
6 changes: 3 additions & 3 deletions base/special/ldexp_exp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ function _frexp_exp(x::T) where T<:Union{Float32, Float64}
exp_x = exp(x - kr*log(T(2))) # exp_x*2^k = exp(x)

# Calculate the ks in exp_x*2^ks
ks = exponent_rshift(T, highword(exp_x)) - (exponent_bias(T) + (exponent_max(T) - 1)) + kr
ks = exponent_rshift(T, highword(exp_x)) - (exponent_bias(T) + exponent_max(T)) + kr

# Rescale exp_x to have exponent k2 = exponent_max(T) - 1
exp_x = modify_exponent(exp_x, UInt32(exponent_bias(T) + (exponent_max(T) - 1)))
# Rescale exp_x to have exponent k2 = exponent_max(T)
exp_x = modify_exponent(exp_x, UInt32(exponent_bias(T) + exponent_max(T)))
return exp_x, ks
end

4 comments on commit 58d6684

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily package evaluation, I will reply here when finished:

@nanosoldier runtests(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - successfully executed benchmarks. A full report can be found here. cc @christopher-dG

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your package evaluation job has completed - possible new issues were detected. A full report can be found here. cc @maleadt

Please sign in to comment.