Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
609 lines
9.1 KiB
609 lines
9.1 KiB
package roaring |
|
|
|
func equal(a, b []uint16) bool { |
|
if len(a) != len(b) { |
|
return false |
|
} |
|
for i := range a { |
|
if a[i] != b[i] { |
|
return false |
|
} |
|
} |
|
return true |
|
} |
|
|
|
func difference(set1 []uint16, set2 []uint16, buffer []uint16) int { |
|
if 0 == len(set2) { |
|
for k := 0; k < len(set1); k++ { |
|
buffer[k] = set1[k] |
|
} |
|
return len(set1) |
|
} |
|
if 0 == len(set1) { |
|
return 0 |
|
} |
|
pos := 0 |
|
k1 := 0 |
|
k2 := 0 |
|
buffer = buffer[:cap(buffer)] |
|
s1 := set1[k1] |
|
s2 := set2[k2] |
|
for { |
|
if s1 < s2 { |
|
buffer[pos] = s1 |
|
pos++ |
|
k1++ |
|
if k1 >= len(set1) { |
|
break |
|
} |
|
s1 = set1[k1] |
|
} else if s1 == s2 { |
|
k1++ |
|
k2++ |
|
if k1 >= len(set1) { |
|
break |
|
} |
|
s1 = set1[k1] |
|
if k2 >= len(set2) { |
|
for ; k1 < len(set1); k1++ { |
|
buffer[pos] = set1[k1] |
|
pos++ |
|
} |
|
break |
|
} |
|
s2 = set2[k2] |
|
} else { // if (val1>val2) |
|
k2++ |
|
if k2 >= len(set2) { |
|
for ; k1 < len(set1); k1++ { |
|
buffer[pos] = set1[k1] |
|
pos++ |
|
} |
|
break |
|
} |
|
s2 = set2[k2] |
|
} |
|
} |
|
return pos |
|
|
|
} |
|
|
|
func exclusiveUnion2by2(set1 []uint16, set2 []uint16, buffer []uint16) int { |
|
if 0 == len(set2) { |
|
buffer = buffer[:len(set1)] |
|
copy(buffer, set1[:]) |
|
return len(set1) |
|
} |
|
if 0 == len(set1) { |
|
buffer = buffer[:len(set2)] |
|
copy(buffer, set2[:]) |
|
return len(set2) |
|
} |
|
pos := 0 |
|
k1 := 0 |
|
k2 := 0 |
|
s1 := set1[k1] |
|
s2 := set2[k2] |
|
buffer = buffer[:cap(buffer)] |
|
for { |
|
if s1 < s2 { |
|
buffer[pos] = s1 |
|
pos++ |
|
k1++ |
|
if k1 >= len(set1) { |
|
for ; k2 < len(set2); k2++ { |
|
buffer[pos] = set2[k2] |
|
pos++ |
|
} |
|
break |
|
} |
|
s1 = set1[k1] |
|
} else if s1 == s2 { |
|
k1++ |
|
k2++ |
|
if k1 >= len(set1) { |
|
for ; k2 < len(set2); k2++ { |
|
buffer[pos] = set2[k2] |
|
pos++ |
|
} |
|
break |
|
} |
|
if k2 >= len(set2) { |
|
for ; k1 < len(set1); k1++ { |
|
buffer[pos] = set1[k1] |
|
pos++ |
|
} |
|
break |
|
} |
|
s1 = set1[k1] |
|
s2 = set2[k2] |
|
} else { // if (val1>val2) |
|
buffer[pos] = s2 |
|
pos++ |
|
k2++ |
|
if k2 >= len(set2) { |
|
for ; k1 < len(set1); k1++ { |
|
buffer[pos] = set1[k1] |
|
pos++ |
|
} |
|
break |
|
} |
|
s2 = set2[k2] |
|
} |
|
} |
|
return pos |
|
} |
|
|
|
func union2by2(set1 []uint16, set2 []uint16, buffer []uint16) int { |
|
pos := 0 |
|
k1 := 0 |
|
k2 := 0 |
|
if 0 == len(set2) { |
|
buffer = buffer[:len(set1)] |
|
copy(buffer, set1[:]) |
|
return len(set1) |
|
} |
|
if 0 == len(set1) { |
|
buffer = buffer[:len(set2)] |
|
copy(buffer, set2[:]) |
|
return len(set2) |
|
} |
|
s1 := set1[k1] |
|
s2 := set2[k2] |
|
buffer = buffer[:cap(buffer)] |
|
for { |
|
if s1 < s2 { |
|
buffer[pos] = s1 |
|
pos++ |
|
k1++ |
|
if k1 >= len(set1) { |
|
copy(buffer[pos:], set2[k2:]) |
|
pos += len(set2) - k2 |
|
break |
|
} |
|
s1 = set1[k1] |
|
} else if s1 == s2 { |
|
buffer[pos] = s1 |
|
pos++ |
|
k1++ |
|
k2++ |
|
if k1 >= len(set1) { |
|
copy(buffer[pos:], set2[k2:]) |
|
pos += len(set2) - k2 |
|
break |
|
} |
|
if k2 >= len(set2) { |
|
copy(buffer[pos:], set1[k1:]) |
|
pos += len(set1) - k1 |
|
break |
|
} |
|
s1 = set1[k1] |
|
s2 = set2[k2] |
|
} else { // if (set1[k1]>set2[k2]) |
|
buffer[pos] = s2 |
|
pos++ |
|
k2++ |
|
if k2 >= len(set2) { |
|
copy(buffer[pos:], set1[k1:]) |
|
pos += len(set1) - k1 |
|
break |
|
} |
|
s2 = set2[k2] |
|
} |
|
} |
|
return pos |
|
} |
|
|
|
func union2by2Cardinality(set1 []uint16, set2 []uint16) int { |
|
pos := 0 |
|
k1 := 0 |
|
k2 := 0 |
|
if 0 == len(set2) { |
|
return len(set1) |
|
} |
|
if 0 == len(set1) { |
|
return len(set2) |
|
} |
|
s1 := set1[k1] |
|
s2 := set2[k2] |
|
for { |
|
if s1 < s2 { |
|
pos++ |
|
k1++ |
|
if k1 >= len(set1) { |
|
pos += len(set2) - k2 |
|
break |
|
} |
|
s1 = set1[k1] |
|
} else if s1 == s2 { |
|
pos++ |
|
k1++ |
|
k2++ |
|
if k1 >= len(set1) { |
|
pos += len(set2) - k2 |
|
break |
|
} |
|
if k2 >= len(set2) { |
|
pos += len(set1) - k1 |
|
break |
|
} |
|
s1 = set1[k1] |
|
s2 = set2[k2] |
|
} else { // if (set1[k1]>set2[k2]) |
|
pos++ |
|
k2++ |
|
if k2 >= len(set2) { |
|
pos += len(set1) - k1 |
|
break |
|
} |
|
s2 = set2[k2] |
|
} |
|
} |
|
return pos |
|
} |
|
|
|
func intersection2by2( |
|
set1 []uint16, |
|
set2 []uint16, |
|
buffer []uint16) int { |
|
|
|
if len(set1)*64 < len(set2) { |
|
return onesidedgallopingintersect2by2(set1, set2, buffer) |
|
} else if len(set2)*64 < len(set1) { |
|
return onesidedgallopingintersect2by2(set2, set1, buffer) |
|
} else { |
|
return localintersect2by2(set1, set2, buffer) |
|
} |
|
} |
|
|
|
func intersection2by2Cardinality( |
|
set1 []uint16, |
|
set2 []uint16) int { |
|
|
|
if len(set1)*64 < len(set2) { |
|
return onesidedgallopingintersect2by2Cardinality(set1, set2) |
|
} else if len(set2)*64 < len(set1) { |
|
return onesidedgallopingintersect2by2Cardinality(set2, set1) |
|
} else { |
|
return localintersect2by2Cardinality(set1, set2) |
|
} |
|
} |
|
|
|
func intersects2by2( |
|
set1 []uint16, |
|
set2 []uint16) bool { |
|
// could be optimized if one set is much larger than the other one |
|
if (0 == len(set1)) || (0 == len(set2)) { |
|
return false |
|
} |
|
k1 := 0 |
|
k2 := 0 |
|
s1 := set1[k1] |
|
s2 := set2[k2] |
|
mainwhile: |
|
for { |
|
|
|
if s2 < s1 { |
|
for { |
|
k2++ |
|
if k2 == len(set2) { |
|
break mainwhile |
|
} |
|
s2 = set2[k2] |
|
if s2 >= s1 { |
|
break |
|
} |
|
} |
|
} |
|
if s1 < s2 { |
|
for { |
|
k1++ |
|
if k1 == len(set1) { |
|
break mainwhile |
|
} |
|
s1 = set1[k1] |
|
if s1 >= s2 { |
|
break |
|
} |
|
} |
|
|
|
} else { |
|
// (set2[k2] == set1[k1]) |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
func localintersect2by2( |
|
set1 []uint16, |
|
set2 []uint16, |
|
buffer []uint16) int { |
|
|
|
if (0 == len(set1)) || (0 == len(set2)) { |
|
return 0 |
|
} |
|
k1 := 0 |
|
k2 := 0 |
|
pos := 0 |
|
buffer = buffer[:cap(buffer)] |
|
s1 := set1[k1] |
|
s2 := set2[k2] |
|
mainwhile: |
|
for { |
|
if s2 < s1 { |
|
for { |
|
k2++ |
|
if k2 == len(set2) { |
|
break mainwhile |
|
} |
|
s2 = set2[k2] |
|
if s2 >= s1 { |
|
break |
|
} |
|
} |
|
} |
|
if s1 < s2 { |
|
for { |
|
k1++ |
|
if k1 == len(set1) { |
|
break mainwhile |
|
} |
|
s1 = set1[k1] |
|
if s1 >= s2 { |
|
break |
|
} |
|
} |
|
|
|
} else { |
|
// (set2[k2] == set1[k1]) |
|
buffer[pos] = s1 |
|
pos++ |
|
k1++ |
|
if k1 == len(set1) { |
|
break |
|
} |
|
s1 = set1[k1] |
|
k2++ |
|
if k2 == len(set2) { |
|
break |
|
} |
|
s2 = set2[k2] |
|
} |
|
} |
|
return pos |
|
} |
|
|
|
func localintersect2by2Cardinality( |
|
set1 []uint16, |
|
set2 []uint16) int { |
|
|
|
if (0 == len(set1)) || (0 == len(set2)) { |
|
return 0 |
|
} |
|
k1 := 0 |
|
k2 := 0 |
|
pos := 0 |
|
s1 := set1[k1] |
|
s2 := set2[k2] |
|
mainwhile: |
|
for { |
|
if s2 < s1 { |
|
for { |
|
k2++ |
|
if k2 == len(set2) { |
|
break mainwhile |
|
} |
|
s2 = set2[k2] |
|
if s2 >= s1 { |
|
break |
|
} |
|
} |
|
} |
|
if s1 < s2 { |
|
for { |
|
k1++ |
|
if k1 == len(set1) { |
|
break mainwhile |
|
} |
|
s1 = set1[k1] |
|
if s1 >= s2 { |
|
break |
|
} |
|
} |
|
|
|
} else { |
|
// (set2[k2] == set1[k1]) |
|
pos++ |
|
k1++ |
|
if k1 == len(set1) { |
|
break |
|
} |
|
s1 = set1[k1] |
|
k2++ |
|
if k2 == len(set2) { |
|
break |
|
} |
|
s2 = set2[k2] |
|
} |
|
} |
|
return pos |
|
} |
|
|
|
func advanceUntil( |
|
array []uint16, |
|
pos int, |
|
length int, |
|
min uint16) int { |
|
lower := pos + 1 |
|
|
|
if lower >= length || array[lower] >= min { |
|
return lower |
|
} |
|
|
|
spansize := 1 |
|
|
|
for lower+spansize < length && array[lower+spansize] < min { |
|
spansize *= 2 |
|
} |
|
var upper int |
|
if lower+spansize < length { |
|
upper = lower + spansize |
|
} else { |
|
upper = length - 1 |
|
} |
|
|
|
if array[upper] == min { |
|
return upper |
|
} |
|
|
|
if array[upper] < min { |
|
// means |
|
// array |
|
// has no |
|
// item |
|
// >= min |
|
// pos = array.length; |
|
return length |
|
} |
|
|
|
// we know that the next-smallest span was too small |
|
lower += (spansize >> 1) |
|
|
|
mid := 0 |
|
for lower+1 != upper { |
|
mid = (lower + upper) >> 1 |
|
if array[mid] == min { |
|
return mid |
|
} else if array[mid] < min { |
|
lower = mid |
|
} else { |
|
upper = mid |
|
} |
|
} |
|
return upper |
|
|
|
} |
|
|
|
func onesidedgallopingintersect2by2( |
|
smallset []uint16, |
|
largeset []uint16, |
|
buffer []uint16) int { |
|
|
|
if 0 == len(smallset) { |
|
return 0 |
|
} |
|
buffer = buffer[:cap(buffer)] |
|
k1 := 0 |
|
k2 := 0 |
|
pos := 0 |
|
s1 := largeset[k1] |
|
s2 := smallset[k2] |
|
mainwhile: |
|
|
|
for { |
|
if s1 < s2 { |
|
k1 = advanceUntil(largeset, k1, len(largeset), s2) |
|
if k1 == len(largeset) { |
|
break mainwhile |
|
} |
|
s1 = largeset[k1] |
|
} |
|
if s2 < s1 { |
|
k2++ |
|
if k2 == len(smallset) { |
|
break mainwhile |
|
} |
|
s2 = smallset[k2] |
|
} else { |
|
|
|
buffer[pos] = s2 |
|
pos++ |
|
k2++ |
|
if k2 == len(smallset) { |
|
break |
|
} |
|
s2 = smallset[k2] |
|
k1 = advanceUntil(largeset, k1, len(largeset), s2) |
|
if k1 == len(largeset) { |
|
break mainwhile |
|
} |
|
s1 = largeset[k1] |
|
} |
|
|
|
} |
|
return pos |
|
} |
|
|
|
func onesidedgallopingintersect2by2Cardinality( |
|
smallset []uint16, |
|
largeset []uint16) int { |
|
|
|
if 0 == len(smallset) { |
|
return 0 |
|
} |
|
k1 := 0 |
|
k2 := 0 |
|
pos := 0 |
|
s1 := largeset[k1] |
|
s2 := smallset[k2] |
|
mainwhile: |
|
|
|
for { |
|
if s1 < s2 { |
|
k1 = advanceUntil(largeset, k1, len(largeset), s2) |
|
if k1 == len(largeset) { |
|
break mainwhile |
|
} |
|
s1 = largeset[k1] |
|
} |
|
if s2 < s1 { |
|
k2++ |
|
if k2 == len(smallset) { |
|
break mainwhile |
|
} |
|
s2 = smallset[k2] |
|
} else { |
|
|
|
pos++ |
|
k2++ |
|
if k2 == len(smallset) { |
|
break |
|
} |
|
s2 = smallset[k2] |
|
k1 = advanceUntil(largeset, k1, len(largeset), s2) |
|
if k1 == len(largeset) { |
|
break mainwhile |
|
} |
|
s1 = largeset[k1] |
|
} |
|
|
|
} |
|
return pos |
|
} |
|
|
|
func binarySearch(array []uint16, ikey uint16) int { |
|
low := 0 |
|
high := len(array) - 1 |
|
for low+16 <= high { |
|
middleIndex := int(uint32(low+high) >> 1) |
|
middleValue := array[middleIndex] |
|
if middleValue < ikey { |
|
low = middleIndex + 1 |
|
} else if middleValue > ikey { |
|
high = middleIndex - 1 |
|
} else { |
|
return middleIndex |
|
} |
|
} |
|
for ; low <= high; low++ { |
|
val := array[low] |
|
if val >= ikey { |
|
if val == ikey { |
|
return low |
|
} |
|
break |
|
} |
|
} |
|
return -(low + 1) |
|
}
|
|
|