@@ -42,3 +42,108 @@ func Unset(b *Bitmap, min, max uint32) iter.Seq[uint32] {
4242 }
4343 }
4444}
45+
46+ // Ranges iterates contiguous ranges of values present in the bitmap as
47+ // half-open [start, endExclusive) pairs. endExclusive is uint64 to represent
48+ // ranges that include MaxUint32. Ranges spanning container boundaries are merged.
49+ func (b * Bitmap ) Ranges () iter.Seq2 [uint32 , uint64 ] {
50+ return func (yield func (uint32 , uint64 ) bool ) {
51+ ra := & b .highlowcontainer
52+ keys := ra .keys
53+ containers := ra .containers
54+ n := len (keys )
55+
56+ var pendingStart , pendingEnd uint64
57+ hasPending := false
58+
59+ emit := func (rStart , rEnd uint64 ) bool {
60+ if hasPending && rStart <= pendingEnd {
61+ if rEnd > pendingEnd {
62+ pendingEnd = rEnd
63+ }
64+ return true
65+ }
66+ if hasPending {
67+ if ! yield (uint32 (pendingStart ), pendingEnd ) {
68+ return false
69+ }
70+ }
71+ pendingStart = rStart
72+ pendingEnd = rEnd
73+ hasPending = true
74+ return true
75+ }
76+
77+ for idx := 0 ; idx < n ; idx ++ {
78+ hs := uint64 (keys [idx ]) << 16
79+ c := containers [idx ]
80+
81+ switch t := c .(type ) {
82+ case * runContainer16 :
83+ for _ , iv := range t .iv {
84+ if ! emit (hs + uint64 (iv .start ), hs + uint64 (iv .start )+ uint64 (iv .length )+ 1 ) {
85+ return
86+ }
87+ }
88+
89+ case * bitmapContainer :
90+ bm := t .bitmap
91+ length := uint (len (bm ))
92+ pos := uint (0 )
93+
94+ for pos < length {
95+ if bm [pos ] == 0 {
96+ pos ++
97+ continue
98+ }
99+
100+ w := bm [pos ]
101+ lo := uint (countTrailingZeros (w ))
102+ bitStart := pos * 64 + lo
103+
104+ ones := uint (countTrailingOnes (w >> lo ))
105+ if lo + ones < 64 {
106+ if ! emit (hs | uint64 (bitStart ), hs | uint64 (bitStart + ones )) {
107+ return
108+ }
109+ pos = (bitStart + ones ) / 64
110+ } else {
111+ pos ++
112+ for pos < length && bm [pos ] == 0xFFFFFFFFFFFFFFFF {
113+ pos ++
114+ }
115+ var bitEnd uint
116+ if pos < length {
117+ bitEnd = pos * 64 + uint (countTrailingOnes (bm [pos ]))
118+ } else {
119+ bitEnd = length * 64
120+ }
121+ if ! emit (hs | uint64 (bitStart ), hs | uint64 (bitEnd )) {
122+ return
123+ }
124+ }
125+ }
126+
127+ case * arrayContainer :
128+ content := t .content
129+ i := 0
130+ for i < len (content ) {
131+ start := uint64 (content [i ])
132+ end := start + 1
133+ i ++
134+ for i < len (content ) && uint64 (content [i ]) == end {
135+ end ++
136+ i ++
137+ }
138+ if ! emit (hs | start , hs | end ) {
139+ return
140+ }
141+ }
142+ }
143+ }
144+
145+ if hasPending {
146+ yield (uint32 (pendingStart ), pendingEnd )
147+ }
148+ }
149+ }
0 commit comments