|
| 1 | +# |
| 2 | +# Date created: 2022-06-22 |
| 3 | +# Author: aradclif |
| 4 | +# |
| 5 | +# |
| 6 | +############################################################################################ |
| 7 | + |
| 8 | +function vfindextrema(f::F, initmin::Iₘᵢₙ, initmax::Iₘₐₓ, A::AbstractArray{T, N}) where {F, Iₘᵢₙ, Iₘₐₓ, T, N} |
| 9 | + Tₒ = Base.promote_op(f, T) |
| 10 | + mn, mx = initmin(Tₒ), initmax(Tₒ) |
| 11 | + i_mn, i_mx = firstindex(A), firstindex(A) |
| 12 | + @turbo for i ∈ eachindex(A) |
| 13 | + v = f(A[i]) |
| 14 | + newmin = v < mn |
| 15 | + newmax = v > mx |
| 16 | + i_mn = ifelse(newmin, i, i_mn) |
| 17 | + i_mx = ifelse(newmax, i, i_mx) |
| 18 | + mn = ifelse(newmin, v, mn) |
| 19 | + mx = ifelse(newmax, v, mx) |
| 20 | + end |
| 21 | + ((mn, i_mn), (mx, i_mx)) |
| 22 | +end |
| 23 | +vfindextrema(A) = vfindextrema(identity, typemax, typemin, A) |
| 24 | +vfindextrema(f, A) = vfindextrema(f, typemax, typemin, A) |
| 25 | + |
| 26 | +_rf_findextrema((((fm₁, im₁), (fx₁, ix₁))), (((fm₂, im₂), (fx₂, ix₂)))) = |
| 27 | + ((Base.isgreater(fm₁, fm₂) ? (fm₂, im₂) : (fm₁, im₁)), (isless(fx₁, fx₂) ? (fx₂, ix₂) : (fx₁, ix₁))) |
| 28 | +findextrema(f, domain) = mapfoldl(((k, v),) -> ((f(v), k), (f(v), k)), _rf_findextrema, pairs(domain)) |
| 29 | +findextrema(domain) = findextrema(identity, domain) |
| 30 | + |
| 31 | +vfindextrema2(A) = vfindmin(A), vfindmax(A) |
| 32 | +vfindextrema2(f, A) = vfindmin(f, A), vfindmax(f, A) |
| 33 | + |
| 34 | +@benchmark vfindextrema($x) |
| 35 | +@benchmark findextrema($x) |
| 36 | +findextrema(x) |
| 37 | +vfindextrema(x) |
| 38 | +@benchmark vfindmin($x) |
| 39 | +@benchmark vfindmax($x) |
| 40 | +for i = 1:20 |
| 41 | + for j = -1:1 |
| 42 | + N = (1 << i) + j |
| 43 | + x = rand(N) |
| 44 | + println("N = $N; vfindextrema (single pass):") |
| 45 | + @btime vfindextrema($x) |
| 46 | + println("N = $N; vfindextrema2 (two passes):") |
| 47 | + @btime vfindextrema2($x) |
| 48 | + end |
| 49 | +end |
0 commit comments