Actually, here’s a version with just 2 allocations:
function locate_vector3(
values::AbstractVector{<:Real},
gridpoints;
locate_below::Bool=false,
locate_above::Bool=false,
)
function incrementalsearch(low, value, gridpoints)
while value >= gridpoints[low + 1]
low += 1
end
return low
end
indices = fill(1, size(values))
weights = fill((NaN, NaN), size(values))
low = 1
high = length(gridpoints) - 1
for ix in eachindex(values)
if values[ix] <= gridpoints[1]
if !locate_below
weights[ix] = (1.0, 0.0)
end
elseif values[ix] >= gridpoints[end]
indices[ix:end] .= length(gridpoints) - 1
if !locate_above
weights[ix:end] .= Ref((0.0, 1.0))
end
break
elseif low == high
indices[ix] = high
else
indices[ix] = low = incrementalsearch(low, values[ix], gridpoints)
end
end
for i in eachindex(weights)
w = weights[i]
if isnan(w[1])
grid1 = gridpoints[indices[i]]
grid2 = gridpoints[indices[i]+1]
val = values[i]
weights[i] = ((grid2 - val) / (grid2 - grid1),
(val - grid1) / (grid2 - grid1))
end
end
return indices, weights
end
1.7.2> @btime locate_vector3($values, $gridpoints; locate_above=true);
575.275 ns (2 allocations: 2.64 KiB)