diff --git a/NEWS.md b/NEWS.md index c619d63364620..12b0d3a5b8c88 100644 --- a/NEWS.md +++ b/NEWS.md @@ -41,6 +41,7 @@ Standard library changes ------------------------ * `islowercase` and `isuppercase` are now compliant with the Unicode lower/uppercase categories ([#38574]). +* `iseven` and `isodd` functions now support non-`Integer` numeric types ([#38976]). #### Package Manager diff --git a/base/float.jl b/base/float.jl index d28bc17601a2b..cb4000b51fac2 100644 --- a/base/float.jl +++ b/base/float.jl @@ -763,6 +763,8 @@ function issubnormal(x::T) where {T<:IEEEFloat} end ispow2(x::AbstractFloat) = !iszero(x) && frexp(x)[1] == 0.5 +iseven(x::AbstractFloat) = isinteger(x) && (abs(x) > maxintfloat(x) || iseven(Integer(x))) +isodd(x::AbstractFloat) = isinteger(x) && abs(x) ≤ maxintfloat(x) && isodd(Integer(x)) @eval begin typemin(::Type{Float16}) = $(bitcast(Float16, 0xfc00)) diff --git a/base/int.jl b/base/int.jl index b3acd29c6492f..02a9ace0fe3f1 100644 --- a/base/int.jl +++ b/base/int.jl @@ -93,9 +93,9 @@ inv(x::Integer) = float(one(x)) / float(x) (/)(x::BitInteger, y::BitInteger) = float(x) / float(y) """ - isodd(x::Integer) -> Bool + isodd(x::Number) -> Bool -Return `true` if `x` is odd (that is, not divisible by 2), and `false` otherwise. +Return `true` if `x` is an odd integer (that is, an integer not divisible by 2), and `false` otherwise. # Examples ```jldoctest @@ -106,12 +106,13 @@ julia> isodd(10) false ``` """ -isodd(n::Integer) = rem(n, 2) != 0 +isodd(n::Number) = isreal(n) && isodd(real(n)) +isodd(n::Real) = isinteger(n) && !iszero(rem(Integer(n), 2)) """ - iseven(x::Integer) -> Bool + iseven(x::Number) -> Bool -Return `true` if `x` is even (that is, divisible by 2), and `false` otherwise. +Return `true` if `x` is an even integer (that is, an integer divisible by 2), and `false` otherwise. # Examples ```jldoctest @@ -122,7 +123,8 @@ julia> iseven(10) true ``` """ -iseven(n::Integer) = !isodd(n) +iseven(n::Number) = isreal(n) && iseven(real(n)) +iseven(n::Real) = isinteger(n) && iszero(rem(Integer(n), 2)) signbit(x::Integer) = x < 0 signbit(x::Unsigned) = false diff --git a/test/complex.jl b/test/complex.jl index 27fbcee370460..56c446896bf53 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -1205,9 +1205,12 @@ end # complex with non-concrete eltype @test_throws ErrorException complex(Union{Complex{Int}, Nothing}[]) -@testset "ispow2" begin +@testset "ispow2 and iseven/isodd" begin @test ispow2(4+0im) @test ispow2(0.25+0im) @test !ispow2(4+5im) @test !ispow2(7+0im) + @test iseven(6+0im) && !isodd(6+0im) + @test !iseven(7+0im) && isodd(7+0im) + @test !iseven(6+1im) && !isodd(7+1im) end diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 210b487f0f909..e3f3203e3c069 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -40,7 +40,7 @@ end end end -@testset "ispow2" begin +@testset "ispow2 and iseven/isodd" begin for T in (Float16,Float32,Float64,BigFloat) for x in (0.25, 1.0, 4.0, exp2(T(exponent(floatmax(T)))), exp2(T(exponent(floatmin(T))))) @test ispow2(T(x)) @@ -48,6 +48,15 @@ end for x in (1.5, 0.0, 7.0, NaN, Inf) @test !ispow2(T(x)) end + for x in (0, 134) + @test iseven(T(x)) && iseven(T(-x)) + @test isodd(T(x+1)) && isodd(T(-x-1)) + end + let x = maxintfloat(T) * π + @test iseven(x) && iseven(-x) + @test !isodd(x) && !isodd(-x) + end + @test !iseven(0.5) && !isodd(0.5) end end diff --git a/test/rational.jl b/test/rational.jl index 863ab6e1d27f8..961eb93a94ed9 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -595,11 +595,14 @@ end @test -2//3 * 0x1 == 0x1 * -2//3 == -2//3 end -@testset "ispow2" begin +@testset "ispow2 and iseven/isodd" begin @test ispow2(4//1) @test ispow2(1//8) @test !ispow2(3//8) @test !ispow2(0//1) + @test iseven(4//1) && !isodd(4//1) + @test !iseven(3//1) && isodd(3//1) + @test !iseven(3//8) && !isodd(3//8) end @testset "checked_den with different integer types" begin