|
| 1 | +##### |
| 2 | +##### From TupleTools.jl |
| 3 | +##### |
| 4 | +function _split(t::Tuple) |
| 5 | + N = length(t) |
| 6 | + M = N >> 1 |
| 7 | + return ntuple(i -> t[i], M), ntuple(i -> t[i + M], N - M) |
| 8 | +end |
| 9 | +function _merge(t1::Tuple, t2::Tuple, lt, by, rev) |
| 10 | + if lt(by(first(t1)), by(first(t2))) != rev |
| 11 | + return (first(t1), _merge(tail(t1), t2, lt, by, rev)...) |
| 12 | + else |
| 13 | + return (first(t2), _merge(t1, tail(t2), lt, by, rev)...) |
| 14 | + end |
| 15 | +end |
| 16 | +_merge(::Tuple{}, t2::Tuple, lt, by, rev) = t2 |
| 17 | +_merge(t1::Tuple, ::Tuple{}, lt, by, rev) = t1 |
| 18 | +_merge(::Tuple{}, ::Tuple{}, lt, by, rev) = () |
| 19 | + |
| 20 | +tuple_sort(t::Tuple; lt=isless, by=identity, rev::Bool=false) = _tuple_sort(t, lt, by, rev) |
| 21 | +@inline function _tuple_sort(t::Tuple, lt=isless, by=identity, rev::Bool=false) |
| 22 | + t1, t2 = _split(t) |
| 23 | + t1s = _tuple_sort(t1, lt, by, rev) |
| 24 | + t2s = _tuple_sort(t2, lt, by, rev) |
| 25 | + return _merge(t1s, t2s, lt, by, rev) |
| 26 | +end |
| 27 | +_tuple_sort(t::Tuple{Any}, lt=isless, by=identity, rev::Bool=false) = t |
| 28 | +_tuple_sort(t::Tuple{}, lt=isless, by=identity, rev::Bool=false) = t |
| 29 | + |
| 30 | + |
| 31 | +###### |
| 32 | +###### tuple_union |
| 33 | +###### |
| 34 | + |
| 35 | +struct DistinctElems{T<:Tuple} |
| 36 | + elems::T |
| 37 | +end |
| 38 | +tuple_union(a::Tuple, b::Tuple) = distinct_elems(DistinctElems(()), a..., b...).elems |
| 39 | + |
| 40 | +distinct_elems(x::DistinctElems) = x |
| 41 | + |
| 42 | +distinct_elems(x::DistinctElems, r1) = |
| 43 | + r1 in x.elems ? x : DistinctElems((x.elems..., r1)) |
| 44 | + |
| 45 | +function distinct_elems(x::DistinctElems, r1, remaining...) |
| 46 | + return if r1 in x.elems |
| 47 | + distinct_elems(x, remaining...) |
| 48 | + else |
| 49 | + distinct_elems(DistinctElems((x.elems..., r1)), remaining...) |
| 50 | + end |
| 51 | +end |
0 commit comments