Skip to content

Commit

Permalink
Add Roaring Next/Previous Interface + Java Port of Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bstrausser committed Jun 8, 2024
1 parent feb68fd commit bc1f8bd
Show file tree
Hide file tree
Showing 13 changed files with 857 additions and 274 deletions.
77 changes: 52 additions & 25 deletions arraycontainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,26 @@ func (ac *arrayContainer) minimum() uint16 {
return ac.content[0] // assume not empty
}

func (ac *arrayContainer) safeMinimum() (uint16, error) {
if len(ac.content) == 0 {
return 0, errors.New("empty array")
}

return ac.minimum(), nil
}

func (ac *arrayContainer) maximum() uint16 {
return ac.content[len(ac.content)-1] // assume not empty
}

func (ac *arrayContainer) safeMaximum() (uint16, error) {
if len(ac.content) == 0 {
return 0, errors.New("empty array")
}

return ac.maximum(), nil
}

func (ac *arrayContainer) getSizeInBytes() int {
return ac.getCardinality() * 2
}
Expand Down Expand Up @@ -975,35 +991,40 @@ func (ac *arrayContainer) realloc(size int) {
// Ex: target=4 ac=[2,3,4,6,7] returns 4
// Ex: target=5 ac=[2,3,4,6,7] returns 4
// Ex: target=6 ac=[2,3,4,6,7] returns 6
// Ex: target=8 ac=[2,3,4,6,7] returns 7
// Ex: target=1 ac=[2,3,4,6,7] returns -1
// Ex: target=0 ac=[2,3,4,6,7] returns -1
func (ac *arrayContainer) previousValue(target uint16) int {
result := binarySearchUntil(ac.content, target)

if result.index == len(ac.content) {
return int(ac.maximum())
}

if result.outOfBounds() {
return -1
}

return int(result.value)
}

// previousAbsentValue returns either the target if not found or the next larger missing value.
// If the target is out of bounds a -1 is returned
// Ex: target=4 ac=[1,2,3,4,6,7] returns -1
// Ex: target=4 ac=[1,2,3,4,6,7] returns 0
// Ex: target=5 ac=[1,2,3,4,6,7] returns 5
// Ex: target=6 ac=[1,2,3,4,6,7] returns 5
// Ex: target=8 ac=[1,2,3,4,6,7] returns -1
// Ex: target=8 ac=[1,2,3,4,6,7] returns 8
func (ac *arrayContainer) previousAbsentValue(target uint16) int {
cardinality := len(ac.content)

if cardinality == 0 {
return -1
return int(target)
}

if target <= ac.minimum() {
return -1
}
if target > ac.maximum() {
return -1
return int(target)
}

result := binarySearchPast(ac.content, target)

if result.notFound() {
Expand All @@ -1017,7 +1038,7 @@ func (ac *arrayContainer) previousAbsentValue(target uint16) int {
}
}

low := 0
low := -1
high := result.index

// This uses the pigeon-hole principle.
Expand All @@ -1037,11 +1058,8 @@ func (ac *arrayContainer) previousAbsentValue(target uint16) int {
}
}

if low == 0 {
if high == 1 {
return -1
}
return int(ac.content[high] - 1)
if high == 0 {
return int(ac.minimum()) - 1
}

return int(ac.content[high] - 1)
Expand All @@ -1051,16 +1069,18 @@ func (ac *arrayContainer) previousAbsentValue(target uint16) int {
// If the target is out of bounds a -1 is returned
// Ex: target=4 ac=[1,2,3,4,6,7] returns 5
// Ex: target=5 ac=[1,2,3,4,6,7] returns 5
// Ex: target=0 ac=[1,2,3,4,6,7] returns -1
// Ex: target=8 ac=[1,2,3,4,6,7] returns -1
// Ex: target=0 ac=[1,2,3,4,6,7] returns 0
// Ex: target=8 ac=[1,2,3,4,6,7] returns 8
func (ac *arrayContainer) nextAbsentValue(target uint16) int {
cardinality := len(ac.content)
if target < ac.minimum() {
return -1

if cardinality == 0 {
return int(target)
}
if target > ac.maximum() {
return -1
if target < ac.minimum() {
return int(target)
}

result := binarySearchPast(ac.content, target)

if result.notFound() {
Expand Down Expand Up @@ -1102,26 +1122,33 @@ func (ac *arrayContainer) nextAbsentValue(target uint16) int {

// nextValue returns either the target if found or the next larger value.
// if the target is out of bounds a -1 is returned
//
// Ex: target=4 ac=[1,2,3,4,6,7] returns 4
// Ex: target=5 ac=[1,2,3,4,6,7] returns 6
// Ex: target=6 ac=[1,2,3,4,6,7] returns 6
// Ex: target=0 ac=[1,2,3,4,6,7] returns 1
// Ex: target=100 ac=[1,2,3,4,6,7] returns -1
func (ac *arrayContainer) nextValue(target uint16) int {
cardinality := len(ac.content)
if cardinality == 0 {
return -1
}

if target < ac.minimum() {
return -1
}
if target > ac.maximum() {
return -1
}
//if target < ac.minimum() {
// return -1
//}
//if target > ac.maximum() {
// return -1
// }

result := binarySearchUntil(ac.content, target)
if result.exactMatch {
return int(result.value)
}

if !result.exactMatch && result.index == -1 {
return int(ac.content[0])
}
if result.outOfBounds() {
return -1
}
Expand Down
Loading

0 comments on commit bc1f8bd

Please sign in to comment.