Skip to content

Commit 89b7351

Browse files
committed
Add Prev function
1 parent 2abea6e commit 89b7351

File tree

3 files changed

+78
-32
lines changed

3 files changed

+78
-32
lines changed

bench_test.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,21 @@ func BenchmarkNext(b *testing.B) {
3838
s := BuildTestSet(b.N)
3939
b.StartTimer()
4040

41-
for n := s.Next(-1); n != -1; {
41+
for n := -2; n != -1; {
4242
n = s.Next(n)
4343
}
4444
}
4545

46+
func BenchmarkPrev(b *testing.B) {
47+
b.StopTimer()
48+
s := BuildTestSet(b.N)
49+
b.StartTimer()
50+
51+
for n := MaxInt; n != -1; {
52+
n = s.Prev(n)
53+
}
54+
}
55+
4656
func BenchmarkVisit(b *testing.B) {
4757
b.StopTimer()
4858
s := BuildTestSet(b.N) // As Visit is pretty fast, s can be pretty big.

set.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,31 @@ func (s *Set) Next(m int) int {
174174
return i<<shift + TrailingZeros(w)
175175
}
176176

177+
// Prev returns the previous element n, n < m, in the set,
178+
// or -1 if there is no such element.
179+
func (s *Set) Prev(m int) int {
180+
d := s.data
181+
len := len(d)
182+
if len == 0 || m <= 0 {
183+
return -1
184+
}
185+
i := len - 1
186+
if max := i<<shift + 63 - LeadingZeros(d[i]); m > max {
187+
return max
188+
}
189+
i = m >> shift
190+
t := bpw - uint(m&mask)
191+
w := d[i] << t >> t // Zero out bits for numbers ≥ m.
192+
for i > 0 && w == 0 {
193+
i--
194+
w = d[i]
195+
}
196+
if w == 0 {
197+
return -1
198+
}
199+
return i<<shift + 63 - LeadingZeros(w)
200+
}
201+
177202
// Visit calls the do function for each element of s in numerical order.
178203
// If do returns true, Visit returns immediately, skipping any remaining
179204
// elements, and returns true. It is safe for do to add or delete

set_test.go

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -212,45 +212,56 @@ func TestEmpty(t *testing.T) {
212212
}
213213
}
214214

215-
func TestNext(t *testing.T) {
215+
func TestNextPrev(t *testing.T) {
216216
for _, x := range []struct {
217217
s *Set
218218
m int
219219
nextN int
220+
prevN int
220221
}{
221-
{New(), 0, -1},
222-
{New(), -1, -1},
223-
224-
{New(1), -1, 1},
225-
{New(1), 0, 1},
226-
{New(1), 1, -1},
227-
{New(1), 2, -1},
228-
229-
{New(0, 2), -1, 0},
230-
{New(0, 2), 0, 2},
231-
{New(0, 2), 1, 2},
232-
{New(0, 2), 2, -1},
233-
{New(0, 2), 3, -1},
234-
235-
{New(63, 64), 62, 63},
236-
{New(63, 64), 63, 64},
237-
{New(63, 64), 64, -1},
238-
239-
{New(100, 300), MinInt, 100},
240-
{New(100, 300), 0, 100},
241-
{New(100, 300), 99, 100},
242-
{New(100, 300), 100, 300},
243-
{New(100, 300), 200, 300},
244-
{New(100, 300), 299, 300},
245-
{New(100, 300), 300, -1},
246-
{New(100, 300), 400, -1},
247-
{New(100, 300), MaxInt, -1},
222+
{New(), 1, -1, -1},
223+
{New(), 0, -1, -1},
224+
{New(), -1, -1, -1},
225+
226+
{New(1), -1, 1, -1},
227+
{New(1), 0, 1, -1},
228+
{New(1), 1, -1, -1},
229+
{New(1), 2, -1, 1},
230+
231+
{New(0, 2), -1, 0, -1},
232+
{New(0, 2), 0, 2, -1},
233+
{New(0, 2), 1, 2, 0},
234+
{New(0, 2), 2, -1, 0},
235+
{New(0, 2), 3, -1, 2},
236+
237+
{New(63, 64), 62, 63, -1},
238+
{New(63, 64), 63, 64, -1},
239+
{New(63, 64), 64, -1, 63},
240+
{New(63, 64), 65, -1, 64},
241+
242+
{New(100, 300), MinInt, 100, -1},
243+
{New(100, 300), -1, 100, -1},
244+
{New(100, 300), 0, 100, -1},
245+
{New(100, 300), 1, 100, -1},
246+
{New(100, 300), 99, 100, -1},
247+
{New(100, 300), 100, 300, -1},
248+
{New(100, 300), 101, 300, 100},
249+
{New(100, 300), 200, 300, 100},
250+
{New(100, 300), 299, 300, 100},
251+
{New(100, 300), 300, -1, 100},
252+
{New(100, 300), 301, -1, 300},
253+
{New(100, 300), 400, -1, 300},
254+
{New(100, 300), MaxInt, -1, 300},
248255
} {
249256
s := x.s
250257
m := x.m
251-
n := s.Next(m)
252-
if n != x.nextN {
253-
t.Errorf("%v.Next(%d) = %d; want %d", s, m, n, x.nextN)
258+
nextN := s.Next(m)
259+
if nextN != x.nextN {
260+
t.Errorf("%v.Next(%d) = %d; want %d", s, m, nextN, x.nextN)
261+
}
262+
prevN := s.Prev(m)
263+
if prevN != x.prevN {
264+
t.Errorf("%v.Prev(%d) = %d; want %d", s, m, prevN, x.prevN)
254265
}
255266
}
256267
}

0 commit comments

Comments
 (0)