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 3 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
19 changes: 19 additions & 0 deletions test/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,25 @@ end
@test exp2(Float16(2.)) ≈ exp2(2.)
@test log(e) == 1

@testset "check exp2(::Int) matches exp2(::Float)" begin
Copy link
Contributor

Choose a reason for hiding this comment

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

see #17165 for what's needed to use testsets in base. they're too noisy at the moment, can't use them just yet

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, I was looking for that, but couldn't find. Thanks.

for ii in -2048:2048
expected = exp2(float(ii))
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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I should have checked that.
Is there a way to use make check-whitespace do it?

Copy link
Contributor

@tkelman tkelman Jul 16, 2016

Choose a reason for hiding this comment

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

search the git log for the last commit I made on master that removed a bunch of tabs, there's a grep command there that I use once in a while to find things that slip through. there are a few files that are either full of tabs that I haven't changed, or have a small number of them for testing purposes though. wouldn't be a bad idea to make check-whitespace check for more things. better idea would be to replace it with a fix-whitespace script that we just run once a week or so.

@test(exp2(Int16(ii)) == expected)
@test(exp2(Int32(ii)) == expected)
@test(exp2(Int64(ii)) == expected)
@test(exp2(Int128(ii)) == expected)
if ii>=0
@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)))
end

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