-
Notifications
You must be signed in to change notification settings - Fork 41
/
groupjoin.jl
65 lines (56 loc) · 1.87 KB
/
groupjoin.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Important, for broadcast joins we cannot assume c and d have same number of columns:
# c could have more columns than d
rowcmp(::Tuple, i, ::Tuple{}, j) = 0
function rowcmp(tc::Tuple, i, td::Tuple, j)
c, d = tc[1], td[1]
let k = rowcmp(c, i, d, j)
(k == 0) ? rowcmp(tail(tc), i, tail(td), j) : k
end
end
function rowcmp(c::StructVector, i, d::StructVector, j)
tc = Tuple(fieldarrays(c))
td = Tuple(fieldarrays(d))
return rowcmp(tc, i, td, j)
end
@inline function rowcmp(c::AbstractVector, i, d::AbstractVector, j)
cmp(c[i], d[j])
end
struct GroupJoinPerm{LP<:GroupPerm, RP<:GroupPerm}
left::LP
right::RP
end
GroupJoinPerm(lkeys::AbstractVector, rkeys::AbstractVector, lperm=sortperm(lkeys), rperm=sortperm(rkeys)) =
GroupJoinPerm(GroupPerm(lkeys, lperm), GroupPerm(rkeys, rperm))
function _pick(s, a, b)
if a === nothing && b === nothing
return nothing
elseif a === nothing
return (1:0, b[1]), (1, a, b)
elseif b === nothing
return (a[1], 1:0), (-1, a, b)
else
lp = sortperm(s.left)
rp = sortperm(s.right)
cmp = rowcmp(parent(s.left), lp[first(a[1])], parent(s.right), rp[first(b[1])])
if cmp < 0
return (a[1], 1:0), (-1, a, b)
elseif cmp == 0
return (a[1], b[1]), (0, a, b)
else
return (1:0, b[1]), (1, a, b)
end
end
end
function Base.iterate(s::GroupJoinPerm)
l = iterate(s.left)
r = iterate(s.right)
_pick(s, l, r)
end
function Base.iterate(s::GroupJoinPerm, (select, l, r))
(select <= 0) && (l = iterate(s.left, l[2]))
(select >= 0) && (r = iterate(s.right, r[2]))
_pick(s, l, r)
end
Base.IteratorSize(::Type{<:GroupJoinPerm}) = Base.SizeUnknown()
Base.IteratorEltype(::Type{<:GroupJoinPerm}) = Base.HasEltype()
Base.eltype(::Type{<:GroupJoinPerm}) = Tuple{UnitRange{Int}, UnitRange{Int}}