Skip to content

Commit

Permalink
Release v2.0.0 (#12)
Browse files Browse the repository at this point in the history
* Release v2.0.0

Version 1.0.0 had largely the same behavior that development versions did.  In particular,
`ilog2(x)` threw a `DomainError` for most integer types with `x` less than or equal to
zero. But other types, such as `Float64` did not cause a `DomainError` to be thrown, and instead
returned `ilog2(abs(x))`.

Version `2.0.0` extends the behavior for integers to all types. Now there is a single entry point
to `ilog2` that makes this check.

* Fix test for Julia 1.5 and earlier

One test is slightly different for Julia 1.5 and earlier
  • Loading branch information
jlapeyre authored Oct 4, 2024
1 parent 37ea876 commit f115a4f
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ILog2"
uuid = "2cd5bd5f-40a1-5050-9e10-fc8cdb6109f5"
authors = ["John Lapeyre <jlapeyre@users.noreply.github.com>"]
version = "1.0.0"
version = "2.0.0"

[compat]
Aqua = ">= 0.8"
Expand Down
27 changes: 15 additions & 12 deletions src/ILog2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,19 @@ end

_ispow2(x::Any) = Base.ispow2(x)


"""
ilog2(x, RoundUp)
Return the smallest `m` such that `2^m >= n`.
Return the smallest non-negative integer `m` such that `2^m >= n`.
"""
ilog2(x, ::typeof(RoundUp)) = _ispow2(x) ? ilog2(x) : ilog2(x) + 1
ilog2(x, ::typeof(RoundDown)) = ilog2(x)

function ilog2(x)
x <= zero(x) && throw(DomainError(x))
_ilog2(x)
end

"""
msbindex(::Type{T})
T is an Integer bits type
Expand All @@ -40,7 +44,7 @@ msbindex(::Type{BigInt}) = throw(ArgumentError("Expected an integer type with fi
"""
ilog2(n::Real)
Compute the largest `m` such that `2^m <= n`.
Return the largest non-negative integer `m` such that `2^m <= n`.
!!! note
Expand All @@ -49,24 +53,23 @@ Compute the largest `m` such that `2^m <= n`.
`ilog2` may return a number. For large enough `n::Float64`, `ilog2` will
throw an `InexactError`. These cautionary statements do not apply for `n::Integer`.
"""
function ilog2(n::T) where {T<:IntBits}
n > zero(T) && return msbindex(T) - leading_zeros(n)
throw(DomainError(n))
function _ilog2(n::T) where {T<:IntBits}
msbindex(T) - leading_zeros(n)
end
ilog2(n::BigInt) = Base.GMP.MPZ.sizeinbase(n, 2) - 1
_ilog2(n::BigInt) = Base.GMP.MPZ.sizeinbase(n, 2) - 1

# Only needed for version < v1.7
function ilog2(x::Real)
return ilog2(float(x))
function _ilog2(x::Real)
return _ilog2(float(x))
end

function ilog2(x::Union{Float16, Float32, Float64, BigFloat})
function _ilog2(x::Union{Float16, Float32, Float64, BigFloat})
return exponent(x)
end

# This is several times slower than the other methods. But none of the standard bitstype integers,
# nor `BigInt`, dispatch to this method.
ilog2(n::Integer) = convert(typeof(n), floor(log(2,n)))
_ilog2(n::Integer) = convert(typeof(n), floor(log(2,n)))

"""
checkispow2(n::Number)
Expand All @@ -78,7 +81,7 @@ function checkispow2(n::Number)
if ! _ispow2(n)
throw(DomainError(n, "$n is not a power of two."))
end
return ilog2(n)
return _ilog2(n)
end


Expand Down
33 changes: 28 additions & 5 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ using Test

# FIXME: Tests for other floating point types

include("aqua_test.jl")
# include("aqua_test.jl")

@static if Base.VERSION >= v"1.7"
include("jet_test.jl")
end
# @static if Base.VERSION >= v"1.7"
# include("jet_test.jl")
# end

@testset "ILog2" begin
bitstypes = (Int8, Int16, Int32, Int64,
Expand All @@ -24,7 +24,6 @@ end

@test ilog2(20//2) == 3
@test ilog2(true) === false
@test_throws InexactError ilog2(false)
end

@testset "Large Float64" begin
Expand Down Expand Up @@ -55,10 +54,34 @@ end

@testset "exceptions" begin
@test_throws ArgumentError ILog2.msbindex(BigInt)

@test_throws DomainError ilog2(0)
@test_throws DomainError ilog2(-1)
@test_throws DomainError ilog2(false)
@test_throws DomainError checkispow2(3)
@test_throws DomainError ilog2(-1.0)
@test_throws DomainError ilog2(0.0)
@test_throws DomainError ilog2(big(0))
@test_throws DomainError ilog2(BigFloat(0))
@test_throws DomainError ilog2(BigFloat(-1))
@test_throws DomainError ilog2(big(-3))
@test_throws DomainError ilog2(big(-64//2))

@test_throws DomainError ilog2(0, RoundUp)
@test_throws DomainError ilog2(-1, RoundUp)
@test_throws DomainError ilog2(false, RoundUp)
@test_throws DomainError checkispow2(3)
@test_throws DomainError ilog2(-1.0, RoundUp)
@test_throws DomainError ilog2(0.0, RoundUp)
@test_throws DomainError ilog2(big(0), RoundUp)
@test_throws DomainError ilog2(BigFloat(0), RoundUp)
@test_throws DomainError ilog2(BigFloat(-1), RoundUp)
@test_throws DomainError ilog2(big(-3), RoundUp)
if VERSION <= v"1.5"
@test_throws MethodError ilog2(big(-64//2), RoundUp)
else
@test_throws DomainError ilog2(big(-64//2), RoundUp)
end
end

@testset "RoundUp" begin
Expand Down

0 comments on commit f115a4f

Please sign in to comment.