Skip to content

Commit

Permalink
Define isone for base types (JuliaLang#22846)
Browse files Browse the repository at this point in the history
  • Loading branch information
Evey Dee authored and rfourquet committed Jul 28, 2017
1 parent c6e51d0 commit b11aec6
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 6 deletions.
1 change: 1 addition & 0 deletions base/bool.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ sign(x::Bool) = x
abs(x::Bool) = x
abs2(x::Bool) = x
iszero(x::Bool) = !x
isone(x::Bool) = x

<(x::Bool, y::Bool) = y&!x
<=(x::Bool, y::Bool) = y|!x
Expand Down
1 change: 1 addition & 0 deletions base/complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ isfinite(z::Complex) = isfinite(real(z)) & isfinite(imag(z))
isnan(z::Complex) = isnan(real(z)) | isnan(imag(z))
isinf(z::Complex) = isinf(real(z)) | isinf(imag(z))
iszero(z::Complex) = iszero(real(z)) & iszero(imag(z))
isone(z::Complex) = isone(real(z)) & iszero(imag(z))

"""
complex(r, [i])
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ export
isreal,
issubnormal,
iszero,
isone,
lcm,
ldexp,
leading_ones,
Expand Down
4 changes: 3 additions & 1 deletion base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor,
ndigits, promote_rule, rem, show, isqrt, string, powermod,
sum, trailing_zeros, trailing_ones, count_ones, base, tryparse_internal,
bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0zpb,
widen, signed, unsafe_trunc, trunc, iszero, big, flipsign, signbit, hastypemax
widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit,
hastypemax

if Clong == Int32
const ClongMax = Union{Int8, Int16, Int32}
Expand Down Expand Up @@ -561,6 +562,7 @@ binomial(n::BigInt, k::Integer) = k < 0 ? BigInt(0) : binomial(n, UInt(k))
==(x::BigInt, f::CdoubleMax) = isnan(f) ? false : cmp(x,f) == 0
==(f::CdoubleMax, x::BigInt) = isnan(f) ? false : cmp(x,f) == 0
iszero(x::BigInt) = x.size == 0
isone(x::BigInt) = x == Culong(1)

<=(x::BigInt, y::BigInt) = cmp(x,y) <= 0
<=(x::BigInt, i::Integer) = cmp(x,i) <= 0
Expand Down
1 change: 1 addition & 0 deletions base/irrationals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ end
isfinite(::Irrational) = true
isinteger(::Irrational) = false
iszero(::Irrational) = false
isone(::Irrational) = false

hash(x::Irrational, h::UInt) = 3*object_id(x) - h

Expand Down
40 changes: 40 additions & 0 deletions base/linalg/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ const DOT_CUTOFF = 128
const ASUM_CUTOFF = 32
const NRM2_CUTOFF = 32

# Generic cross-over constant based on benchmarking on a single thread with an i7 CPU @ 2.5GHz
# L1 cache: 32K, L2 cache: 256K, L3 cache: 6144K
# This constant should ideally be determined by the actual CPU cache size
const ISONE_CUTOFF = 2^21 # 2M

function scale!(X::Array{T}, s::T) where T<:BlasFloat
s == 0 && return fill!(X, zero(T))
s == 1 && return X
Expand All @@ -29,6 +34,41 @@ function scale!(X::Array{T}, s::Real) where T<:BlasComplex
X
end


function isone(A::StridedMatrix)
m, n = size(A)
m != n && return false # only square matrices can satisfy x == one(x)
if sizeof(A) < ISONE_CUTOFF
_isone_triacheck(A, m)
else
_isone_cachefriendly(A, m)
end
end

@inline function _isone_triacheck(A::StridedMatrix, m::Int)
@inbounds for i in 1:m, j in i:m
if i == j
isone(A[i,i]) || return false
else
iszero(A[i,j]) && iszero(A[j,i]) || return false
end
end
return true
end

# Inner loop over rows to be friendly to the CPU cache
@inline function _isone_cachefriendly(A::StridedMatrix, m::Int)
@inbounds for i in 1:m, j in 1:m
if i == j
isone(A[i,i]) || return false
else
iszero(A[j,i]) || return false
end
end
return true
end


"""
isposdef!(A) -> Bool
Expand Down
6 changes: 3 additions & 3 deletions base/linalg/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import Base: A_mul_Bt, At_ldiv_Bt, A_rdiv_Bc, At_ldiv_B, Ac_mul_Bc, A_mul_Bc, Ac
Ac_ldiv_B, Ac_ldiv_Bc, At_mul_Bt, A_rdiv_Bt, At_mul_B
import Base: USE_BLAS64, abs, big, broadcast, ceil, conj, convert, copy, copy!,
ctranspose, eltype, eye, findmax, findmin, fill!, floor, full, getindex,
hcat, imag, indices, inv, isapprox, kron, length, IndexStyle, map,
hcat, imag, indices, inv, isapprox, isone, IndexStyle, kron, length, map,
ndims, oneunit, parent, power_by_squaring, print_matrix, promote_rule, real, round,
setindex!, show, similar, size, transpose, trunc, typed_hcat
using Base: promote_op, _length, iszero, @pure, @propagate_inbounds, IndexLinear,
reduce, hvcat_fill, typed_vcat, promote_typeof
using Base: hvcat_fill, iszero, IndexLinear, _length, promote_op, promote_typeof,
@propagate_inbounds, @pure, reduce, typed_vcat
# We use `_length` because of non-1 indices; releases after julia 0.5
# can go back to `length`. `_length(A)` is equivalent to `length(linearindices(A))`.

Expand Down
4 changes: 3 additions & 1 deletion base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import
eps, signbit, sin, cos, sincos, tan, sec, csc, cot, acos, asin, atan,
cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, atan2,
cbrt, typemax, typemin, unsafe_trunc, realmin, realmax, rounding,
setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero, big
setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero,
isone, big

import Base.Rounding: rounding_raw, setrounding_raw

Expand Down Expand Up @@ -853,6 +854,7 @@ end
isfinite(x::BigFloat) = !isinf(x) && !isnan(x)

iszero(x::BigFloat) = x == Clong(0)
isone(x::BigFloat) = x == Clong(1)

@eval typemax(::Type{BigFloat}) = $(BigFloat( Inf))
@eval typemin(::Type{BigFloat}) = $(BigFloat(-Inf))
Expand Down
18 changes: 18 additions & 0 deletions base/number.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,27 @@ isinteger(x::Integer) = true
Return `true` if `x == zero(x)`; if `x` is an array, this checks whether
all of the elements of `x` are zero.
```jldoctest
julia> iszero(0.0)
true
```
"""
iszero(x) = x == zero(x) # fallback method

"""
isone(x)
Return `true` if `x == one(x)`; if `x` is an array, this checks whether
`x` is an identity matrix.
```jldoctest
julia> isone(1.0)
true
```
"""
isone(x) = x == one(x) # fallback method

size(x::Number) = ()
size(x::Number,d) = convert(Int,d)<1 ? throw(BoundsError()) : 1
indices(x::Number) = ()
Expand Down
1 change: 1 addition & 0 deletions base/rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ function ^(z::Complex{<:Rational}, n::Integer)
end

iszero(x::Rational) = iszero(numerator(x))
isone(x::Rational) = isone(numerator(x)) & isone(denominator(x))

function lerpi(j::Integer, d::Integer, a::Rational, b::Rational)
((d-j)*a)/d + (j*b)/d
Expand Down
1 change: 1 addition & 0 deletions doc/src/stdlib/numbers.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Base.isfinite
Base.isinf
Base.isnan
Base.iszero
Base.isone
Base.nextfloat
Base.prevfloat
Base.isinteger
Expand Down
13 changes: 12 additions & 1 deletion test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const ≣ = isequal # convenient for comparing NaNs
@test_throws InexactError Bool(1//2)

@test iszero(false) && !iszero(true)
@test isone(true) && !isone(false)

# basic arithmetic
@test 2 + 3 == 5
Expand Down Expand Up @@ -2942,28 +2943,38 @@ module M20889 # do we get the expected behavior without importing Base.^?
Base.Test.@test PR20889(2)^3 == 5
end

@testset "iszero" begin
@testset "iszero & isone" begin
# Numeric scalars
for T in [Float16, Float32, Float64, BigFloat,
Int8, Int16, Int32, Int64, Int128, BigInt,
UInt8, UInt16, UInt32, UInt64, UInt128]
@test iszero(T(0))
@test isone(T(1))
@test iszero(Complex{T}(0))
@test isone(Complex{T}(1))
if T <: Integer
@test iszero(Rational{T}(0))
@test isone(Rational{T}(1))
elseif T <: AbstractFloat
@test iszero(T(-0.0))
@test iszero(Complex{T}(-0.0))
end
end
@test !iszero(nextfloat(BigFloat(0)))
@test !isone(nextfloat(BigFloat(1)))
for x in (π, e, γ, catalan, φ)
@test !iszero(x)
@test !isone(x)
end

# Array reduction
@test !iszero([0, 1, 2, 3])
@test iszero(zeros(Int, 5))
@test !isone(tril(ones(Int, 5, 5)))
@test !isone(triu(ones(Int, 5, 5)))
@test !isone(zeros(Int, 5, 5))
@test isone(eye(Int, 5, 5))
@test isone(eye(Int, 1000, 1000)) # sizeof(X) > 2M == ISONE_CUTOFF
end

f20065(B, i) = UInt8(B[i])
Expand Down

0 comments on commit b11aec6

Please sign in to comment.