Skip to content

Commit

Permalink
fix: only avoid short-circuiting when the function is identity
Browse files Browse the repository at this point in the history
Because the short-circuiting is promised by the docs.
  • Loading branch information
nsajko committed Jan 19, 2025
1 parent dfcbc18 commit 0626951
Showing 1 changed file with 39 additions and 25 deletions.
64 changes: 39 additions & 25 deletions base/anyall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,27 +114,34 @@ false
"""
any(f, itr) = _any(f, itr, :)

function _any(f, itr, ::Colon)
anymissing = false
for x in itr
v = f(x)
if ismissing(v)
anymissing = true
else
v && return true
for ItrT = (Tuple,Any)
# define a generic method and a specialized version for `Tuple`,
# whose method bodies are identical, while giving better effects to the later
@eval function _any(f, itr::$ItrT, ::Colon)
$(ItrT === Tuple ? :(@_terminates_locally_meta) : :nothing)
anymissing = false
for x in itr
v = f(x)
if ismissing(v)
anymissing = true
else
v && return true
end
end
return anymissing ? missing : false
end
return anymissing ? missing : false
end

function _any(f, itr::Tuple, ::Colon)
# When the function is side effect-free, we may avoid short-circuiting to help
# vectorize the loop.
function _any(::typeof(identity), itr::Tuple, ::Colon)
@_terminates_locally_meta
# avoid short-circuiting to help vectorization
r = false
anymissing = false
for i in eachindex(itr)
x = getfield(itr, i, false) # avoid `getindex` bounds checking to help vectorization
v = f(x)
# Avoid bounds checking to help vectorization. Use `getfield` directly,
# instead of `@inbounds itr[i]`, for better effects.
v = getfield(itr, i, false)
if ismissing(v)
anymissing = true
else
Expand Down Expand Up @@ -203,27 +210,34 @@ true
"""
all(f, itr) = _all(f, itr, :)

function _all(f, itr, ::Colon)
anymissing = false
for x in itr
v = f(x)
if ismissing(v)
anymissing = true
else
v || return false
for ItrT = (Tuple,Any)
# define a generic method and a specialized version for `Tuple`,
# whose method bodies are identical, while giving better effects to the later
@eval function _all(f, itr::$ItrT, ::Colon)
$(ItrT === Tuple ? :(@_terminates_locally_meta) : :nothing)
anymissing = false
for x in itr
v = f(x)
if ismissing(v)
anymissing = true
else
v || return false
end
end
return anymissing ? missing : true
end
return anymissing ? missing : true
end

# When the function is side effect-free, we may avoid short-circuiting to help
# vectorize the loop.
function _all(f, itr::Tuple, ::Colon)
@_terminates_locally_meta
# avoid short-circuiting to help vectorization
r = true
anymissing = false
for i in eachindex(itr)
x = getfield(itr, i, false) # avoid `getindex` bounds checking to help vectorization
v = f(x)
# Avoid bounds checking to help vectorization. Use `getfield` directly,
# instead of `@inbounds itr[i]`, for better effects.
v = getfield(itr, i, false)
if ismissing(v)
anymissing = true
else
Expand Down

0 comments on commit 0626951

Please sign in to comment.