mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 17:15:56 +00:00
Simplify unionArrayArray
Also short-circuit it in some cases.
This commit is contained in:
parent
1af016df84
commit
83aa505673
1 changed files with 65 additions and 54 deletions
|
|
@ -3688,41 +3688,43 @@ func union(a, b *Container) *Container {
|
|||
|
||||
func unionArrayArray(a, b *Container) *Container {
|
||||
statsHit("union/ArrayArray")
|
||||
aa, ab := a.array(), b.array()
|
||||
na, nb := len(aa), len(ab)
|
||||
output := make([]uint16, na+nb)
|
||||
n := 0
|
||||
for i, j := 0, 0; ; {
|
||||
if i >= na && j >= nb {
|
||||
break
|
||||
} else if i < na && j >= nb {
|
||||
output[n] = aa[i]
|
||||
n++
|
||||
i++
|
||||
continue
|
||||
} else if i >= na && j < nb {
|
||||
output[n] = ab[j]
|
||||
n++
|
||||
j++
|
||||
continue
|
||||
}
|
||||
|
||||
va, vb := aa[i], ab[j]
|
||||
if a.N() == 0 {
|
||||
return b
|
||||
}
|
||||
if b.N() == 0 {
|
||||
return a
|
||||
}
|
||||
s1, s2 := a.array(), b.array()
|
||||
n1, n2 := len(s1), len(s2)
|
||||
output := make([]uint16, 0, n1+n2)
|
||||
i, j := 0, 0
|
||||
for {
|
||||
va, vb := s1[i], s2[j]
|
||||
if va < vb {
|
||||
output[n] = va
|
||||
n++
|
||||
output = append(output, va)
|
||||
i++
|
||||
} else if va > vb {
|
||||
output[n] = vb
|
||||
n++
|
||||
output = append(output, vb)
|
||||
j++
|
||||
} else {
|
||||
output[n] = va
|
||||
n++
|
||||
i, j = i+1, j+1
|
||||
output = append(output, va)
|
||||
i++
|
||||
j++
|
||||
}
|
||||
// It's possible we hit the ends at the same time,
|
||||
// in which case the append will copy 0 items. This
|
||||
// is cheaper than performing a separate conditional
|
||||
// check every time...
|
||||
if j >= n2 {
|
||||
output = append(output, s1[i:]...)
|
||||
break
|
||||
}
|
||||
if i >= n1 {
|
||||
output = append(output, s2[j:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
return NewContainerArray(output[:n])
|
||||
return NewContainerArray(output)
|
||||
}
|
||||
|
||||
// unionArrayArrayInPlace does what it sounds like -- tries to combine
|
||||
|
|
@ -3730,47 +3732,56 @@ func unionArrayArray(a, b *Container) *Container {
|
|||
// of a good array size, so it could be up to twice that size, temporarily.
|
||||
func unionArrayArrayInPlace(a, b *Container) *Container {
|
||||
statsHit("union/ArrayArrayInPlace")
|
||||
aa, ab := a.array(), b.array()
|
||||
na, nb := len(aa), len(ab)
|
||||
output := make([]uint16, na+nb)
|
||||
outN := 0
|
||||
for i, j := 0, 0; ; {
|
||||
if i >= na && j >= nb {
|
||||
break
|
||||
} else if i < na && j >= nb {
|
||||
copy(output[outN:], aa[i:])
|
||||
outN += na - i
|
||||
break
|
||||
} else if i >= na && j < nb {
|
||||
copy(output[outN:], ab[j:])
|
||||
outN += nb - j
|
||||
break
|
||||
if a.N() == 0 {
|
||||
if b.N() != 0 {
|
||||
// for InPlace, we actually want to ensure that
|
||||
// we update a, as long as it's not frozen.
|
||||
a = a.Thaw()
|
||||
a.setArray(b.array())
|
||||
return a.optimize()
|
||||
}
|
||||
|
||||
va, vb := aa[i], ab[j]
|
||||
return a
|
||||
}
|
||||
if b.N() == 0 {
|
||||
return a
|
||||
}
|
||||
s1, s2 := a.array(), b.array()
|
||||
n1, n2 := len(s1), len(s2)
|
||||
output := make([]uint16, 0, n1+n2)
|
||||
i, j := 0, 0
|
||||
for {
|
||||
va, vb := s1[i], s2[j]
|
||||
if va < vb {
|
||||
output[outN] = va
|
||||
outN++
|
||||
output = append(output, va)
|
||||
i++
|
||||
} else if va > vb {
|
||||
output[outN] = vb
|
||||
outN++
|
||||
output = append(output, vb)
|
||||
j++
|
||||
} else {
|
||||
output[outN] = va
|
||||
outN++
|
||||
output = append(output, va)
|
||||
i++
|
||||
j++
|
||||
}
|
||||
// It's possible we hit the ends at the same time,
|
||||
// in which case the append will copy 0 items. This
|
||||
// is cheaper than performing a separate conditional
|
||||
// check every time...
|
||||
if j >= n2 {
|
||||
output = append(output, s1[i:]...)
|
||||
break
|
||||
}
|
||||
if i >= n1 {
|
||||
output = append(output, s2[j:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
// a union can't omit anything that was previously in a, so if
|
||||
// the output is the same length, nothing changed.
|
||||
if len(output) != int(a.N()) {
|
||||
a = a.Thaw()
|
||||
a.setArray(output[:outN])
|
||||
a = a.optimize()
|
||||
a.setArray(output)
|
||||
}
|
||||
return a
|
||||
return a.optimize()
|
||||
}
|
||||
|
||||
// unionArrayRun optimistically assumes that the result will be a run container,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue