Cool, that is twice as fast as this:
function _up_nmin!(a, n, min_vals, min_idxs)
@inbounds for (idx, val) in pairs(a)
if val < min_vals[n]
i = searchsortedfirst(min_vals, val)
for j = n:-1:i+1
min_vals[j] = min_vals[j-1]
min_idxs[j] = min_idxs[j-1]
end
min_vals[i] = val
min_idxs[i] = idx
end
end
return nothing
end
function nmin(a::AbstractArray{T,N}, n::Integer) where {T,N}
min_vals = [ typemax(T) for _ in 1:n ]
min_idxs = Vector{CartesianIndex{N}}(undef, n)
_up_nmin!(a, n, min_vals, min_idxs)
return min_idxs, min_vals
end
I guess because here I’m tracking the values as well and keeping them in order?
julia> @btime nmin($A,5)
85.279 ms (2 allocations: 352 bytes)
(CartesianIndex{5}[CartesianIndex(96, 7, 6, 18, 1), CartesianIndex(45, 31, 8, 38, 8), CartesianIndex(84, 23, 3, 12, 8), CartesianIndex(89, 25, 7, 39, 1), CartesianIndex(1, 4, 5, 10, 6)], [5.279682058212387e-8, 5.647766321281722e-8, 1.2348968225772694e-7, 1.2398590831796952e-7, 1.354943585107904e-7])
julia> @btime argsmallest($A,5)
41.264 ms (161 allocations: 14.95 KiB)
5-element Vector{CartesianIndex{5}}:
CartesianIndex(96, 7, 6, 18, 1)
CartesianIndex(45, 31, 8, 38, 8)
CartesianIndex(84, 23, 3, 12, 8)
CartesianIndex(89, 25, 7, 39, 1)
CartesianIndex(1, 4, 5, 10, 6)