2
\$\begingroup\$

So, I wrote this function to sort three numbers in Julia. Any feedback on readability, performance, and Julian-ness would be appreciated.

function sort_asc(a, b, c)
    # defined in function so as not to overwrite Base.minmax
    minmax(x, y) = ifelse(x < y, (x, y), (y, x))

    l1, h1 = minmax(a, b)
    lo, h2 = minmax(l1, c)
    md, hi = minmax(h1, h2)

    return lo, md, hi
end
\$\endgroup\$
1
  • \$\begingroup\$ There's no need to swap x and y if they're equal, so I'd prefer less-or-equal instead of less-than. \$\endgroup\$
    – CiaPan
    Jul 19 at 13:37
1
\$\begingroup\$

As it turns out

function sort_asc(a, b, c)
    l1, h1 = minmax(a, b)
    lo, h2 = minmax(l1, c)
    md, hi = minmax(h1, h2)
    return lo, md, hi
end

results in the exact same native assembly instructions on my machine (compared to the branchless version). So, given its greater simplicity, I think this is the best version so far.

Here are comparisons to other implementations

function sort3(a, b, c)
    l1, h1 = minmax(a, b)
    lo, h2 = minmax(l1, c)
    md, hi = minmax(h1, h2)
    return lo, md, hi
end

@inline minmax_nb(x, y) = ifelse(isless(x, y), (x, y), (y, x))

function sort3_nb(a, b, c)
    l1, h1 = minmax_nb(a, b)
    lo, h2 = minmax_nb(l1, c)
    md, hi = minmax_nb(h1, h2)
    return lo, md, hi
end

function sort3_koen(a, b, c)
    lo, md = minmax(a, b)
    if md > c
        hi = md
        lo, md = minmax(lo, c)
    else
        hi = c
    end

    return lo, md, hi
end

Here is the benchmark code

using BenchmarkTools

function map_sort3!(f::F, out, data) where F
    @inbounds for i in eachindex(out, data)
        a, b, c = data[i]
        out[i]  = f(a, b, c)
    end
end

for f in [sort3, sort3_nb, sort3_koen]
    print(rpad(f, 12), ":")
    @btime map_sort3!($f, out, data) setup=begin
        data = [ntuple(i -> rand(Int), 3) for _ in 1:10_000]
        out = similar(data)
    end evals=1
end

And here are the results on my machine:

sort3       :  17.286 μs (0 allocations: 0 bytes)
sort3_nb    :  17.624 μs (0 allocations: 0 bytes)
sort3_koen  :  21.776 μs (0 allocations: 0 bytes)
\$\endgroup\$
0
\$\begingroup\$

I'd expect this to be marginally faster:

(lo,md) = minmax(a,b)
if md > c
       hi = md
       (lo,md) = minmax(lo,c)
else
       hi = c

I don't know where this sits in the scale of Julianesquinness since I'm not familiar with Julia (not even sure if my "if-else" adheres to its syntax, but the intention should be clear).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.