Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast exp2(::Int) (fixs #17412) #17447

Merged
merged 10 commits into from
Aug 1, 2016
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -519,9 +519,9 @@ exponent_one(::Type{Float32}) = 0x3f80_0000
exponent_half(::Type{Float32}) = 0x3f00_0000
significand_mask(::Type{Float32}) = 0x007f_ffff

significand_bits{T<:AbstractFloat}(::Type{T}) = trailing_ones(significand_mask(T))
exponent_bits{T<:AbstractFloat}(::Type{T}) = sizeof(T)*8 - significand_bits(T) - 1
exponent_bias{T<:AbstractFloat}(::Type{T}) = Int(exponent_one(T) >> significand_bits(T))
@pure significand_bits{T<:AbstractFloat}(::Type{T}) = trailing_ones(significand_mask(T))
@pure exponent_bits{T<:AbstractFloat}(::Type{T}) = sizeof(T)*8 - significand_bits(T) - 1
@pure exponent_bias{T<:AbstractFloat}(::Type{T}) = Int(exponent_one(T) >> significand_bits(T))

## Array operations on floating point numbers ##

Expand Down
17 changes: 17 additions & 0 deletions base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,23 @@ for f in (:sinh, :cosh, :tanh, :atan, :asinh, :exp, :erf, :erfc, :expm1)
@eval ($f)(x::AbstractFloat) = error("not implemented for ", typeof(x))
end

#functions with special cases for integer arguements
@inline function exp2(x::Integer)
if x > 1023
Copy link
Contributor

Choose a reason for hiding this comment

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

no tabs here either

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm sorry. I did check that file. But apparently, I fail at using the retab command in vim.

Copy link
Contributor

Choose a reason for hiding this comment

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

no big deal, ci is relatively quiet atm

Inf64
Copy link
Contributor

Choose a reason for hiding this comment

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

should exp2(x::BigInt) return a BigFloat answer?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch.
I've added some test cases to test/bigint.jl to ensure this.

elseif x < -1074
Float64(0.0)
elseif x <= -1023
#Result will be a subnormal number
reinterpret(Float64, Int64(1) << (x + 1074))
else
#If x is a Int128, and is outside the range of Int64, then it is not -123<x<=1023
#We will cast everything to Int64 to avoid errors incase of Int128
reinterpret(Float64, (exponent_bias(Float64) + Int64(x)) << significand_bits(Float64))
end
end


# TODO: GNU libc has exp10 as an extension; should openlibm?
exp10(x::Float64) = 10.0^x
exp10(x::Float32) = 10.0f0^x
Expand Down
18 changes: 18 additions & 0 deletions test/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,24 @@ end
@test exp2(Float16(2.)) ≈ exp2(2.)
@test log(e) == 1

# check exp2(::Integer) matches exp2(::Float)"
for ii in -2048:2048
expected = exp2(float(ii))
@test(exp2(Int16(ii)) == expected)
@test(exp2(Int32(ii)) == expected)
@test(exp2(Int64(ii)) == expected)
@test(exp2(Int128(ii)) == expected)
if ii>=0
Copy link
Contributor

Choose a reason for hiding this comment

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

spaces around the >= would be a little easier to read (also [ci skip] worthy)

@test(exp2(UInt16(ii)) == expected)
@test(exp2(UInt32(ii)) == expected)
@test(exp2(UInt64(ii)) == expected)
@test(exp2(UInt128(ii)) == expected)
end
end

@test(exp2(false) == exp2(float(false)))
@test(exp2(true) == exp2(float(true)))

for T in (Int, Float64, BigFloat)
@test deg2rad(T(180)) ≈ 1pi
@test deg2rad(T[45, 60]) ≈ [pi/T(4), pi/T(3)]
Expand Down