Skip to content

Commit ce86ba1

Browse files
committed
fixing issue 486
1 parent b25cb8b commit ce86ba1

File tree

4 files changed

+77
-24
lines changed

4 files changed

+77
-24
lines changed

roaring.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1477,7 +1477,6 @@ main:
14771477
}
14781478
s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
14791479
} else {
1480-
14811480
answer.highlowcontainer.appendContainer(s1, x1.highlowcontainer.getContainerAtIndex(pos1).or(x2.highlowcontainer.getContainerAtIndex(pos2)), false)
14821481
pos1++
14831482
pos2++
@@ -1516,6 +1515,7 @@ main:
15161515
if !C.isEmpty() {
15171516
answer.highlowcontainer.appendContainer(s1, C, false)
15181517
}
1518+
15191519
pos1++
15201520
pos2++
15211521
if (pos1 == length1) || (pos2 == length2) {

roaring_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,54 @@ import (
1515
"github.com/stretchr/testify/require"
1616
)
1717

18+
var bm1Arr = []uint32{279981785, 279982923, 279988809, 279995913}
19+
20+
const bm2Bytes = "OzAAAAGwEO2EbwQBdgoADXZFAFR2BABadgYAYnaiAAZ3GwAjdx0AQndaAJ533AB8eA4AjHgUAKJ4IQDFeA8B1nkLAON5FgD7eRQAEXoDABZ6AAAYeggAInpRAHV6BwB+egMAg3oFAIp6NgDCegYAynoVAOF6AQDkehYA/HpCAEF7ZACnewMArXsBALB7CQC7ewUAw3sJAM97DwDgewIA5HsQAPZ7BQD9exEAEHwDABV8CgAhfBMANnwFAD18EwBTfA0AY3w4AJ18HwC+fHwAPH0QAE99YgCzfQMAuH1DAP19sACvfhkAyn4dAOl+SQA0f3sAsX+lAFiAhgDggB0A/4AIAAmBBQAQgRQAJoEcAESBpgDsgQ8A/YGUAJOCNgDLgjUAAoNKAE6DJwB3g6gAIYQBACSEIQBHhAsAVIQSAGiEIQCLhNMAYIVVALeFBAC9hSQA44V8AGGGDwByhhAAhIYZAJ+GRgDnhhsABIdJAE+HGQBqhxgAhIcJAI+HOQDKhxYA4oc1ABmIDQAoiAQALogbAEuIcAC9iA0AzIgYAOaIEgD6iCoAJokaAEKJawKvizkA6ouLAHeMJQCejFIA8owGAPqMFAAQjRIAJI0MADKNFgBKjQEATY0IAFiNFwBxjQoAfY0EAIONYQDmjQAA6I06ACSOKgFQj8YAGJAzAE2QFQBkkHQA2pA7ABeRPwBYkQUAX5FdAL6RQwADkhYAG5IMACmSfgCpkhQAv5JlACaTEAA4k5wA1pMzAAuUBgATlEoAX5ROAa+VTQD+lRMAE5YzAEiWRACOlmwA/JYOAAyXAAAOlw8AH5cHACiXAAArlwkANpcBADmXBQBAlxYAWJcxAIuXEwCglxUAt5ccANWXAADXlxoA85cIAP2XMQAwmIAAsphyACaZdACdmU4A7ZkXAAaaVABcmhcAdZocAJOaFgCrmhYAw5osAPGaGgANmwEAEJsRACObBwAsmxwASpsDAE+bBQBWmw0AZZtmAM2bOQAInFIAXJwCAGCcOgCcnMkAZ50FAG6dGgCKnRQAoJ08AN6dAADgnQ0A750hABKeUABknhIAeJ42ALCebAAenzEAUZ8AAFOfCABdn4UA5J8AAOafQwAroCMAUKAEAFagQACYoBUAsKAxAOOgIgAHoQQADaEkADOhCQA+oQQARKEJAE+hPQCOoZ4ALqKMALyiKAHmo7oAoqQgAMSkUQAXpUEAWqW/ABumNgBTphkAbqZXAMemMwH8pwkAB6gMABWoTQBkqCgAjqg6AMqoHwDrqGwAWalEAJ+pEgCzqRIAx6kmAO+pPwAwqioAXKoSAHCqLQCfqkYA56pBACqrEgA+qyYAZqsrAJOrKAC9qwAAv6sdAN6rBwDnqxIA+6sCAP+rBQAGrBMAG6wRAC6sAAAwrA8AQawSAFWsEwBqrAQAcKwTAIWsJwCurBAAwKwMAM6sAADQrAMA1awLAOKsEwD3rAgAAa0oACutCwA5rQgAQ60qAG+tBAB1rQIAea0JAIStJQCrrQgAta0hANitCgDlrQsA8q0fABOuJgA8rhgAV64NAGauHQCFrioAsa4UAMeuGQDirhoA/q4PAA+vBQAWryYAP68TAFSvAwBZrwQAX68AAGGvGgB9rxAAj68DAJSvMADGrxQA3K8uAA2wBwAWsAsAI7AAACWwKABPsBUAZrABAGmwDQB4sCAAm7AIAKWwBwCusAEAsbATAMewIADpsBMA/rADAAOxGQAesQAAILEUADaxAAA4sRUAT7EfAHCxBgB4sRUAj7EXAKixCgC0sQEAt7EqAOOxGwAAsiEAI7ITADiyFgBQsgEAU7IOAGOyEwB4sgQAfrIAAIGyGgCdsgMAorIMALCyAwC1sgEAuLITAM2yFwDmshQA/LIEAAKzAQAFsxQAG7MNACqzCAA0swgAPrMAAEGzAABDswAARbMBAEizGQBjswYAa7MEAHGzCwB+swEAgbMEAIezEwCcsw0Aq7MHALSzCAC+swMAw7MDAMizAwDNswYA1bMUAOuzCQD2swEA+bMAAPuzDAAJtAcAErQAABS0AQAYtAsAJbQEACy0DQA7tBAATbQZAGi0IACKtAQAkLQCAJS0AQCXtAQAnbQAAJ+0BQCmtBMAu7QOAMu0GgDntAkA8rQCAPa0JQAdtQAAH7UHACi1FgBAtQoATbUKAFm1AABbtRgAdbUTAIq1GwCntQMArLUCALC1OQDrtXAAXbYAAF+2KACJtjUAwLYgAOK2OgAetxAAMLcWAEi3AABKt0cAk7cVAKq3KQDVtxIA6bcSAP23AAD/twcACLg0AD64RgCGuDEAubgkAN+4CQDquBQAALkKAAy5DwAduQAAH7kIACu5CAA3uQgAQbkCAEW5AABIuQkAVbkKAGG5AQBkuQcAbrkBAHO5FACJuQIAjbkAAJC5AwCVuQMAmrkAAJy5AgChuQMAqLkHALG5AAC0uQIAuLkHAMO5JQDquQIA8LkXAAm6AAALugkAFroDABu6BQAiugIAKLoIADS6AQA3ugUAProKAEq6AQBNugAAULoJAFy6AQBfugUAZroKAHK6AgB6ugAAfLoUAJK6AgCYugcAoboAAKS6FAC6ugEAvboAAL+6BQDGugEAyboBAMy6BwDVug8A5roAAOi6CADyug0AAbsBAAS7DgAUuxcALbsAADC7BAA2uwIAO7sCAEC7GwBduykAiLsqALS7gwA5vFAAi7wEAJG8JAC3vEIA+7wGAAO9EAAVvQUAHL0SADC9CgA8vTIAcL0KAHy9AQB/vRcAmL0TAK29GwDKvVoAJr4iAEq+DABYvlcCscDiAJXBeAAPwh0ALsInAFfCEABpwgQAb8IJAHrCBwCDwgUAisIRAJ3CEgCxwgQAt8IYANHCEADjwgcA7cIAAPDCKwAdwx8APsMAAEDDSACKwwMAj8MWAKfDCgCzwzMA6MP8AObEcABYxQEAW8UEAGHFDABvxQUAdsUQAIjFDQCXxQ0ApsUYAMDFAADCxSEA5cUAAOfFCgDzxQkA/sUFAAXGBQAMxgcAFcYNACTGKwBRxjIAhcYEAIvGNQDCxmwAMMfSAATIXQBjyAMAaMgVAH/IFwCYyCYAwMgGAMjICwDVyA4A5cggAAfJCAARyRcAKskSAD7JAQBByQoATckXAGbJGgCCyQAAhMkLAJLJFQCpyRMAvskEAMTJWAEeywAAIMsnAEnLAQBMyw8AXcsUAHPLLQCiyw8As8sAALXLAAC4yxoA1MsmAP3LAgABzCsAL8x8AK3MGADHzAMAzMwLANnMCwDnzBcAAM0QABLNGQAtzQoAOc0GAEHNEQBUzQkAX80TAHXNFQCMzQoAmc1JAOXNDADzzScAHM4qAEjOiwDVzgQA284NAOrOdwJj0Q0ActEBAHXRTQDE0QcAzdFQAB/SEAAx0joBbdOhABDUJwA51HMArtSSAELV6gAu1gcAN9YYAFHWIwB21gMAe9YAAH3WAwCC1hsAn9YKAKvWAQCu1gcAt9YBALrWBwDD1gEAxtYJANLWGwDv1gIA89YAAPXWFwAO1wAAENcCABTXFgAs1zoAaNdBAKvXnwBM2AEAT9gGAFfYJwCA2HkA+9idAJrZGgC22QEBudoVANDaOQAL22wAedu8ADfcLABl3CYAjdwcAKvcFgDD3EwAEd1fAHLdTQDB3R8A4t0fAAPenACh3jEA1N4SAOjehQBv3wAAcd9AALPfAQC23xsA098zAAjgEgAc4AIAIOADACXgBQAs4AAAL+ADADTgBAA64AAAPOAKAEjgCQBT4AcAXOAHAGXgHQCE4AAAhuAKAJLgFQCp4A0AuOAkAN7gAwDk4A4A9OAlABvhGQA24RcAT+ECAFPhGABt4QAAb+EbAIzhCwCZ4QUAoOEGAKjhFwDB4QAAw+EBAMbhDgDW4QsA4+EdAALiAwAH4gsAFOIDABniIgA94gEAQOIhAGPiEAB14i0ApOISALjiFADO4gwA3OITAPHiAQD04gYA/OIZABfjAQAa4wIAHuMBACHjBgAp4wQAL+MKADvjDABJ4wwAV+MOAGfjBQBu4wEAceMAAHPjBQB64woAhuMBAInjBwCT4w4Ao+MIAK3jAgCx4wcAuuMDAL/jCgDL4wAAzeMAAM/jBADW4wMA2+MEAOHjBADn4woA8+MCAPfjBQD+4wIAA+QEAArkEAAc5AAAIuQEACjkCgA05AAAOOQDAD7kDABM5AAATuQAAFDkAwBW5AMAW+QEAGHkBQBo5AoAdOQAAHjkAwB+5AwAjOQAAJDkAwCV5AQAnOQGAKTkAQCn5AQAreQDALTkCgDA5AkAy+QEANHkBQDY5AcA4eQHAOrkAgDu5AAA8OQCAPTkBgD85A4ADOUDABHlDQAg5TMAVeUdAHTlBAB65QIAfuUQAJDlFgCo5RAAuuUIAMTlCQDP5SsA/OUdABvmCQAm5hoAQuYSAFbmHAB05ikAn+YSALTmLgDl5g0A9OYxACfnAQAq5wIALuc+AG7nDgF+6BQAlOguAMToqQBv6QwAfekaAJnphwAj6rEA1uoeAPbqTwBH64YAz+sIANnrPgAZ7CYAQewnAGrsBABw7BwAjuwCAJLsCwCf7AIAo+xGAOvsNAAh7QAAI+07AGDtBQBn7S0Alu0GAJ7tLwDP7RYA5+0MAPXtJgAd7iIAQe4BAETuEQBY7g0AZ+4NAHbuLACk7jIA2O4UAO7uJgAW7xIAKu8zAF/vcQDS7yUA+e8RAA3wAgAR8BIAJfAqAFHwBABX8BAAafAfAIrwAQCN8BIAofALAK7wIwDT8A0A4vAHAOvwEgD/8AUABvETABvxCwAp8TsAZvEwAJjxHgC48QAAuvEiAN7xAwDj8Q0A8vEDAPfxBwAA8hsAHfISADHyBAA38hMATfIGAFXyEgBp8j4AqfICAK3yTgD98hsAGvNqAIbzCgCS8xMAp/MAAKrzAwCv8wkAuvMBAL7zAADA8wEAw/MBAMbzBQDN8wAA0fMAANTzAgDY8wEA2/MIAOXzAADn8wYA7/MAAPLzAwD38wMA/PMEAAT0AQAH9A0AGPQGACD0BgAo9AAALPQBAC/0AwA09AcAQPQDAEj0BgBQ9AEAU/QGAFv0CABn9AAAafQEAG/0AQB09AUAe/QEAIH0AQCF9AIAifQCAI/0AACS9AQAmPQCAJz0DgCt9AIAsfQFALj0AAC69AQAwvQEAMj0AgDM9AMA0fQCANb0AQDZ9AQA3/QBAOT0BQDr9AcA9PQHAP70AgAD9QEABvUCAAr1EQAf9Q8AMPUDADf1BAA99QUARPUGAE31AgBR9QYAWfULAGb1AQBq9RIAfvUNAI31BACV9Q8ApvUDAKz1AwCx9QYAufUGAMH1DADP9QkA2vUBAN31EADw9QMA9fUCAPn1AQD99QkACPYAAAr2BwAT9gYAG/YGACP2AAAl9gQAK/YCADD2AAAy9gcAO/YGAET2AABG9gMAS/YAAE32AwBS9gMAV/YIAGL2AABk9hEAd/YDAHz2AAB+9gMAg/YFAIr2BgCS9gEAlvYAAJj2EQCr9gEArvYHALj2AAC69gYAwvYNANH2DADg9gsA7fYBAPD2AgD09gAA9vYBAPn2AQD89goACPcDAA33CgAZ9wEAHPcBAB/3AQAi9wsAL/cCADP3AAA29wwARPcBAEf3AQBK9wwAWPcBAFv3AQBe9wkAafcAAGv3BABy9wkAffcAAH/3DACN9wEAkPcEAJb3CQCh9wAApPcDAKn3DAC39xAAyfcBAMz3EQDf9xIA9PcYAA74AAAQ+AsAHvgGACf4EQA8+AQAQvgOAFL4AABU+BYAbfgBAHD4DgCA+AsAjfgRAKD4AwCm+BEAuvgmAOL4FAD4+BQADvkJABr5CgAm+UIAavmEAPD5CwD9+TYANfoJAEH6LQBw+i0An/oLAKz6PwDt+hoACft4AIP7BgCL+xMBoPwYALr8UwAP/RIAI/0KAC/9BwA4/QkAQ/0kAGn9HgCJ/RsApv2yAFr+AQBd/gIAYf4IAGv+CgB3/gAAef5oAOP+EAD1/mIAWf+CAN3/BwDm/xkA"
21+
22+
func TestRoaring_OrThenAnd(t *testing.T) {
23+
bm1 := BitmapOf(bm1Arr...)
24+
require.NoError(t, bm1.Validate())
25+
26+
bm2 := New()
27+
_, err := bm2.FromBase64(bm2Bytes)
28+
require.NoError(t, err)
29+
require.NoError(t, bm2.Validate())
30+
31+
orBm := Or(bm1, bm2) // this can be FastOr, bm1.Or(bm2)
32+
require.NoError(t, orBm.Validate())
33+
34+
mask := New()
35+
mask.AddRange(279_900_001, 280_000_001)
36+
mask.Or(orBm) // this can be roaring.And(mask, orBm)
37+
38+
require.NoError(t, mask.Validate()) // <-- fails here
39+
}
40+
41+
func TestRoaring_OrThenAnd_RunOptimize(t *testing.T) {
42+
bm1 := BitmapOf(bm1Arr...)
43+
require.NoError(t, bm1.Validate())
44+
45+
fmt.Printf("%v\n", bm1)
46+
bm2 := New()
47+
bm2.FromBase64(bm2Bytes) // this shows that data is not corrupted
48+
bm2 = BitmapOf(bm2.ToArray()...)
49+
require.NoError(t, bm2.Validate())
50+
51+
bm2.RunOptimize()
52+
require.NoError(t, bm2.Validate())
53+
54+
orBm := Or(bm1, bm2)
55+
require.NoError(t, orBm.Validate())
56+
57+
mask := New()
58+
mask.AddRange(279_900_001, 280_000_001)
59+
require.NoError(t, mask.Validate())
60+
61+
mask.And(orBm)
62+
63+
require.NoError(t, mask.Validate())
64+
}
65+
1866
func TestSplitter_BrokeBm(t *testing.T) {
1967
bm1 := NewBitmap()
2068
bm2 := NewBitmap()

runcontainer.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,7 +1823,11 @@ func (rc *runContainer16) and(a container) container {
18231823
}
18241824
switch c := a.(type) {
18251825
case *runContainer16:
1826-
return rc.intersect(c)
1826+
// Important: there is no reason to believe that the
1827+
// result of intersecting two run containers is itself
1828+
// a run container. Hence we convert to efficient container.
1829+
// We only use run containers when they are efficient.
1830+
return rc.intersect(c).toEfficientContainer()
18271831
case *arrayContainer:
18281832
return rc.andArray(c)
18291833
case *bitmapContainer:
@@ -1885,7 +1889,11 @@ func (rc *runContainer16) iand(a container) container {
18851889
}
18861890
switch c := a.(type) {
18871891
case *runContainer16:
1888-
return rc.inplaceIntersect(c)
1892+
// Important: there is no reason to believe that the
1893+
// result of intersecting two run containers is itself
1894+
// a run container. Hence we convert to efficient container.
1895+
// We only use run containers when they are efficient.
1896+
return rc.inplaceIntersect(c).toEfficientContainer()
18891897
case *arrayContainer:
18901898
// inplace intersection with array is not supported
18911899
// It is likely not very useful either.
@@ -2198,7 +2206,7 @@ func (rc *runContainer16) ior(a container) container {
21982206
case *arrayContainer:
21992207
return rc.iorArray(c)
22002208
case *bitmapContainer:
2201-
return rc.iorBitmapContainer(c)
2209+
return rc.orBitmapContainer(c)
22022210
}
22032211
panic("unsupported container type")
22042212
}
@@ -2213,13 +2221,14 @@ func (rc *runContainer16) inplaceUnion(rc2 *runContainer16) container {
22132221
return rc
22142222
}
22152223

2216-
func (rc *runContainer16) iorBitmapContainer(bc *bitmapContainer) container {
2217-
it := bc.getShortIterator()
2218-
for it.hasNext() {
2219-
rc.Add(it.next())
2220-
}
2221-
return rc
2222-
}
2224+
// Such code should not be used as it will not preserve the container invariants:
2225+
//func (rc *runContainer16) iorBitmapContainer(bc *bitmapContainer) container {
2226+
// it := bc.getShortIterator()
2227+
// for it.hasNext() {
2228+
// rc.Add(it.next())
2229+
// }
2230+
// return rc
2231+
//}
22232232

22242233
func (rc *runContainer16) iorArray(ac *arrayContainer) container {
22252234
if rc.isEmpty() {

runcontainer_test.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,10 +1058,6 @@ func TestRle16RandomInplaceUnionAgainstOtherContainers012(t *testing.T) {
10581058
b = append(b, uint16(r1))
10591059
mb[r1] = true
10601060
}
1061-
1062-
// showArray16(a, "a")
1063-
// showArray16(b, "b")
1064-
10651061
// hash version of union
10661062
hashi := make(map[int]bool)
10671063
for k := range ma {
@@ -1092,21 +1088,21 @@ func TestRle16RandomInplaceUnionAgainstOtherContainers012(t *testing.T) {
10921088
// vs runContainer
10931089
rcb := newRunContainer16FromVals(false, b...)
10941090

1095-
rcVsBcUnion.ior(bc)
1096-
rcVsAcUnion.ior(ac)
1097-
rcVsRcbUnion.ior(rcb)
1091+
rcVsBcUnionAnswer := rcVsBcUnion.ior(bc)
1092+
rcVsAcUnionAnswer := rcVsAcUnion.ior(ac)
1093+
rcVsRcbUnionAnswer := rcVsRcbUnion.ior(rcb)
10981094

10991095
for k := range hashi {
1100-
assert.True(t, rcVsBcUnion.contains(uint16(k)))
1096+
assert.True(t, rcVsBcUnionAnswer.contains(uint16(k)))
11011097

1102-
assert.True(t, rcVsAcUnion.contains(uint16(k)))
1098+
assert.True(t, rcVsAcUnionAnswer.contains(uint16(k)))
11031099

1104-
assert.True(t, rcVsRcbUnion.contains(uint16(k)))
1100+
assert.True(t, rcVsRcbUnionAnswer.contains(uint16(k)))
11051101
}
11061102

1107-
assert.Equal(t, len(hashi), rcVsBcUnion.getCardinality())
1108-
assert.Equal(t, len(hashi), rcVsAcUnion.getCardinality())
1109-
assert.Equal(t, len(hashi), rcVsRcbUnion.getCardinality())
1103+
assert.Equal(t, len(hashi), rcVsBcUnionAnswer.getCardinality())
1104+
assert.Equal(t, len(hashi), rcVsAcUnionAnswer.getCardinality())
1105+
assert.Equal(t, len(hashi), rcVsRcbUnionAnswer.getCardinality())
11101106
}
11111107
}
11121108

0 commit comments

Comments
 (0)