@@ -664,25 +664,54 @@ func (ac *arrayContainer) iandNot(a container) container {
664
664
}
665
665
666
666
func (ac * arrayContainer ) iandNotRun16 (rc * runContainer16 ) container {
667
- if len (ac .content ) == 0 {
667
+ // Fast path: if either the array container or the run container is empty, the result is the array.
668
+ if ac .isEmpty () || rc .isEmpty () {
668
669
// Empty
669
670
return ac
670
671
}
671
-
672
- for _ , run := range rc .iv {
673
- if run .start > ac .maximum () {
674
- // Since the runs are sorted, we can stop here. (No subsequent runs will
675
- // overlap with the array container.)
676
- break
677
- }
678
- if run .last () < ac .minimum () {
679
- // This run is entirely before the array container. We can skip it.
680
- continue
672
+ // Fast path: if the run container is full, the result is empty.
673
+ if rc .isFull () {
674
+ ac .content = ac .content [:0 ]
675
+ return ac
676
+ }
677
+ current_run := 0
678
+ // All values in [start_run, end_end] are part of the run
679
+ start_run := rc .iv [current_run ].start
680
+ end_end := start_run + rc .iv [current_run ].length
681
+ // We are going to read values in the array at index i, and we are
682
+ // going to write them at index pos. So we do in-place processing.
683
+ // We always have that pos <= i by construction. So we can either
684
+ // overwrite a value just read, or a value that was previous read.
685
+ pos := 0
686
+ i := 0
687
+ for ; i < len (ac .content ); i ++ {
688
+ if ac .content [i ] < start_run {
689
+ // the value in the array appears before the run [start_run, end_end]
690
+ ac .content [pos ] = ac .content [i ]
691
+ pos ++
692
+ } else if ac .content [i ] <= end_end {
693
+ // nothing to do, the value is in the array but also in the run.
694
+ } else {
695
+ // We have the value in the array after the run. We cannot tell
696
+ // whether we need to keep it or not. So let us move to another run.
697
+ if current_run + 1 < len (rc .iv ) {
698
+ current_run ++
699
+ start_run = rc .iv [current_run ].start
700
+ end_end = start_run + rc .iv [current_run ].length
701
+ i -- // retry with the same i
702
+ } else {
703
+ // We have exhausted the number of runs. We can keep the rest of the values
704
+ // from i to len(ac.content) - 1 inclusively.
705
+ break // We are done, the rest of the array will be kept
706
+ }
681
707
}
682
-
683
- out := ac .iremoveRange (int (run .start ), int (run .start )+ int (run .length )+ 1 ).(* arrayContainer )
684
- * ac = * out
685
708
}
709
+ for ; i < len (ac .content ); i ++ {
710
+ ac .content [pos ] = ac .content [i ]
711
+ pos ++
712
+ }
713
+ // We 'shink' the slice.
714
+ ac .content = ac .content [:pos ]
686
715
return ac
687
716
}
688
717
0 commit comments