roaringbitmap 0.1__tar.gz → 0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: roaringbitmap
3
- Version: 0.1
3
+ Version: 0.3
4
4
  Summary: Roaring Bitmap
5
5
  Home-page: https://github.com/andreasvc/roaringbitmap/
6
6
  Author: Andreas van Cranenburgh
@@ -47,6 +47,8 @@ Description: Roaring Bitmap in Cython
47
47
  >>> RoaringBitmap(range(10)) & RoaringBitmap(range(5, 15))
48
48
  RoaringBitmap({5, 6, 7, 8, 9})
49
49
 
50
+ For API documentation cf. https://pythonhosted.org/roaringbitmap/
51
+
50
52
  Benchmarks
51
53
  ----------
52
54
  Output of ``$ python benchmarks.py``::
@@ -102,4 +104,3 @@ Classifier: Operating System :: POSIX
102
104
  Classifier: Programming Language :: Python :: 2.7
103
105
  Classifier: Programming Language :: Python :: 3.3
104
106
  Classifier: Programming Language :: Cython
105
- Requires: cython (>=0.20)
@@ -39,6 +39,8 @@ Python set containing (unsigned) 32-bit integers::
39
39
  >>> RoaringBitmap(range(10)) & RoaringBitmap(range(5, 15))
40
40
  RoaringBitmap({5, 6, 7, 8, 9})
41
41
 
42
+ For API documentation cf. https://pythonhosted.org/roaringbitmap/
43
+
42
44
  Benchmarks
43
45
  ----------
44
46
  Output of ``$ python benchmarks.py``::
@@ -3,15 +3,20 @@ import os
3
3
  import sys
4
4
  from distutils.core import setup
5
5
  from distutils.extension import Extension
6
- try:
7
- from Cython.Build import cythonize
8
- from Cython.Distutils import build_ext
9
- except ImportError as err:
10
- print('ERROR: Cython not found.')
11
- sys.exit(1)
6
+ USE_CYTHON = '--with-cython' in sys.argv
7
+ if USE_CYTHON:
8
+ sys.argv.remove('--with-cython')
9
+ try:
10
+ from Cython.Build import cythonize
11
+ from Cython.Distutils import build_ext
12
+ except ImportError:
13
+ raise ValueError('could not import Cython.')
14
+ cmdclass = dict(build_ext=build_ext)
15
+ else:
16
+ cmdclass = dict()
12
17
 
13
18
  metadata = dict(name='roaringbitmap',
14
- version='0.1',
19
+ version='0.3',
15
20
  description='Roaring Bitmap',
16
21
  long_description=open('README.rst').read(),
17
22
  author='Andreas van Cranenburgh',
@@ -26,9 +31,6 @@ metadata = dict(name='roaringbitmap',
26
31
  'Programming Language :: Python :: 3.3',
27
32
  'Programming Language :: Cython',
28
33
  ],
29
- requires=[
30
- 'cython (>=0.20)',
31
- ],
32
34
  )
33
35
 
34
36
  # some of these directives increase performance,
@@ -51,19 +53,27 @@ directives = {
51
53
 
52
54
  if __name__ == '__main__':
53
55
  os.environ['GCC_COLORS'] = 'auto'
54
- extensions = [Extension(
55
- '*',
56
- sources=['src/*.pyx'],
57
- extra_compile_args=['-O3', '-DNDEBUG', '-march=native'],
58
- # extra_compile_args=['-O0', '-g'],
59
- # extra_link_args=['-g'],
60
- )]
56
+ if USE_CYTHON:
57
+ extensions = [Extension(
58
+ '*',
59
+ sources=['src/*.pyx'],
60
+ extra_compile_args=['-O3', '-DNDEBUG', '-march=native'],
61
+ # extra_compile_args=['-O0', '-g'],
62
+ # extra_link_args=['-g'],
63
+ )]
64
+ ext_modules = cythonize(
65
+ extensions,
66
+ annotate=True,
67
+ compiler_directives=directives,
68
+ language_level=3,
69
+ )
70
+ else:
71
+ ext_modules = [Extension(
72
+ 'roaringbitmap',
73
+ sources=['src/roaringbitmap.c'],
74
+ extra_compile_args=['-O3', '-DNDEBUG', '-march=native'],
75
+ )]
61
76
  setup(
62
- cmdclass=dict(build_ext=build_ext),
63
- ext_modules=cythonize(
64
- extensions,
65
- annotate=True,
66
- compiler_directives=directives,
67
- language_level=3,
68
- ),
77
+ cmdclass=cmdclass,
78
+ ext_modules=ext_modules,
69
79
  **metadata)
@@ -100,9 +100,9 @@ cdef int advance(uint16_t *data, int pos, int length, uint16_t minitem):
100
100
  return upper
101
101
  if data[upper] < minitem:
102
102
  return length
103
- lower += spansize // 2
103
+ lower += spansize >> 1
104
104
  while lower + 1 != upper:
105
- mid = (lower + upper) // 2
105
+ mid = (<unsigned int>lower + <unsigned int>upper) >> 1
106
106
  if data[mid] == minitem:
107
107
  return mid
108
108
  elif data[mid] < minitem:
@@ -27,7 +27,7 @@ extern "C" {
27
27
 
28
28
  #ifdef BITCOUNT_VS_X86
29
29
  #include <intrin.h>
30
- #pragma intrinsic(_BitScanForward,_BitScanReverse,__popcnt)
30
+ #pragma intrinsic(_BitScanForward64,_BitScanReverse64,__popcnt64)
31
31
  #endif
32
32
 
33
33
  #include <limits.h>
@@ -43,10 +43,10 @@ unsigned int bit_popcount_general(uint64_t);
43
43
  bit position. If v is 0, the result is undefined. */
44
44
  BITCOUNT_INLINE unsigned int bit_clz(uint64_t v) {
45
45
  #if defined(BITCOUNT_GCC)
46
- return __builtin_clzl(v);
46
+ return __builtin_clzll(v);
47
47
  #elif defined(BITCOUNT_VS_X86)
48
48
  uint64_t result;
49
- _BitScanReverse(&result, v);
49
+ _BitScanReverse64(&result, v);
50
50
  return BITCOUNT_BITS - 1 - result;
51
51
  #else
52
52
  return bit_clz_general(v);
@@ -57,10 +57,10 @@ BITCOUNT_INLINE unsigned int bit_clz(uint64_t v) {
57
57
  bit position. If v is 0, the result is undefined. */
58
58
  BITCOUNT_INLINE unsigned int bit_ctz(uint64_t v) {
59
59
  #if defined(BITCOUNT_GCC)
60
- return __builtin_ctzl(v);
60
+ return __builtin_ctzll(v);
61
61
  #elif defined(BITCOUNT_VS_X86)
62
62
  uint64_t result;
63
- _BitScanForward(&result, v);
63
+ _BitScanForward64(&result, v);
64
64
  return result;
65
65
  #else
66
66
  return bit_ctz_general(v);
@@ -70,9 +70,9 @@ BITCOUNT_INLINE unsigned int bit_ctz(uint64_t v) {
70
70
  /* Returns the number of 1-bits in v. */
71
71
  BITCOUNT_INLINE unsigned int bit_popcount(uint64_t v) {
72
72
  #if defined(BITCOUNT_GCC)
73
- return __builtin_popcountl(v);
73
+ return __builtin_popcountll(v);
74
74
  #elif defined(BITCOUNT_VS_X86)
75
- return __popcnt(v);
75
+ return __popcnt64(v);
76
76
  #else
77
77
  return bit_popcount_general(v);
78
78
  #endif
@@ -44,7 +44,7 @@ cdef inline int iteratesetbits(uint64_t *vec, int slots,
44
44
  return -1
45
45
  cur[0] = vec[idx[0]]
46
46
  tmp = bit_ctz(cur[0]) # index of right-most 1-bit in current slot
47
- cur[0] ^= 1UL << tmp # TOGGLEBIT(cur, tmp)
47
+ cur[0] ^= 1ULL << tmp # TOGGLEBIT(cur, tmp)
48
48
  return idx[0] * BITSIZE + tmp
49
49
 
50
50
 
@@ -60,7 +60,7 @@ cdef inline int iterateunsetbits(uint64_t *vec, int slots,
60
60
  return -1
61
61
  cur[0] = ~vec[idx[0]]
62
62
  tmp = bit_ctz(cur[0]) # index of right-most 0-bit in current slot
63
- cur[0] ^= 1UL << tmp # TOGGLEBIT(cur, tmp)
63
+ cur[0] ^= 1ULL << tmp # TOGGLEBIT(cur, tmp)
64
64
  return idx[0] * BITSIZE + tmp
65
65
 
66
66
 
@@ -90,7 +90,7 @@ cdef inline int reviteratesetbits(uint64_t *vec, uint64_t *cur, int *idx):
90
90
  return -1
91
91
  cur[0] = vec[idx[0]]
92
92
  tmp = BITSIZE - bit_clz(cur[0]) - 1 # index of left-most 1-bit in cur
93
- cur[0] &= ~(1UL << tmp) # CLEARBIT(cur, tmp)
93
+ cur[0] &= ~(1ULL << tmp) # CLEARBIT(cur, tmp)
94
94
  return idx[0] * BITSIZE + tmp
95
95
 
96
96
 
@@ -3,7 +3,6 @@ cdef inline Block new_Block(uint16_t key):
3
3
  block.key = key
4
4
  block.state = POSITIVE
5
5
  block.cardinality = 0
6
- block.buf = array.clone(ushortarray, 0, False)
7
6
  return block
8
7
 
9
8
 
@@ -17,7 +16,7 @@ cdef class Block(object):
17
16
  cdef uint8_t state # either DENSE, INVERTED, or POSITIVE
18
17
  cdef uint16_t key # the high bits of elements in this block
19
18
  cdef uint32_t cardinality # the number of elements
20
- cdef array.array buf # bitvector, positive sparse, or inverted sparse
19
+ cdef array.array buf # data: sparse array or fixed-size bitvector
21
20
 
22
21
  def __cinit__(self):
23
22
  pass
@@ -86,6 +85,27 @@ cdef class Block(object):
86
85
  del self.buf[i]
87
86
  self.cardinality -= 1
88
87
 
88
+ cdef _and(self, Block other):
89
+ cdef Block result
90
+ cdef int n
91
+ if self.state == DENSE:
92
+ if other.state == POSITIVE:
93
+ result = new_Block(self.key)
94
+ result.buf = array.clone(ushortarray, other.cardinality, False)
95
+ result.state = POSITIVE
96
+ result.cardinality = 0
97
+ for n in range(other.cardinality):
98
+ if TESTBIT(self.buf.data.as_ulongs,
99
+ other.buf.data.as_ushorts[n]):
100
+ result.buf.data.as_ushorts[self.cardinality
101
+ ] = other.buf.data.as_ushorts[n]
102
+ result.cardinality += 1
103
+ array.resize(result.buf, result.cardinality)
104
+ return result
105
+ result = self.copy()
106
+ result &= other
107
+ return result
108
+
89
109
  cdef iand(self, Block other):
90
110
  cdef array.array tmp
91
111
  cdef int length, n
@@ -99,9 +119,9 @@ cdef class Block(object):
99
119
  tmp.data.as_ushorts[self.cardinality
100
120
  ] = other.buf.data.as_ushorts[n]
101
121
  self.cardinality += 1
102
- array.resize(tmp, self.cardinality)
103
- self.state = POSITIVE
104
122
  self.buf = tmp
123
+ array.resize(self.buf, self.cardinality)
124
+ self.state = POSITIVE
105
125
  elif other.state == DENSE:
106
126
  self.cardinality = bitsetintersectinplace(
107
127
  self.buf.data.as_ulongs,
@@ -114,22 +134,19 @@ cdef class Block(object):
114
134
  other.buf.data.as_ushorts[n])
115
135
  self.cardinality -= 1
116
136
  elif other.state == DENSE:
137
+ tmp = array.clone(ushortarray, BITMAPSIZE // sizeof(short), False)
117
138
  if self.state == INVERTED:
118
- tmp = array.clone(ushortarray, BITMAPSIZE, False)
119
- memset(tmp.data.as_uchars, 255, BLOCKSIZE // sizeof(char))
139
+ memset(tmp.data.as_chars, 255, BITMAPSIZE)
120
140
  for n in range(BLOCKSIZE - self.cardinality):
121
- CLEARBIT(tmp.data.as_ulongs,
122
- self.buf.data.as_ushorts[n])
141
+ CLEARBIT(tmp.data.as_ulongs, self.buf.data.as_ushorts[n])
123
142
  else: # self.state == POSITIVE:
124
- tmp = array.clone(ushortarray, BITMAPSIZE, True)
143
+ memset(tmp.data.as_chars, 0, BITMAPSIZE)
125
144
  for n in range(self.cardinality):
126
- SETBIT(tmp.data.as_ulongs,
127
- self.buf.data.as_ushorts[n])
145
+ SETBIT(tmp.data.as_ulongs, self.buf.data.as_ushorts[n])
146
+ self.buf = tmp
128
147
  self.cardinality = bitsetintersectinplace(
129
- tmp.data.as_ulongs,
130
- other.buf.data.as_ulongs)
148
+ self.buf.data.as_ulongs, other.buf.data.as_ulongs)
131
149
  self.state = DENSE
132
- self.buf = tmp
133
150
  elif self.state == POSITIVE and other.state == POSITIVE:
134
151
  length = intersect2by2(
135
152
  self.buf.data.as_ushorts,
@@ -148,9 +165,9 @@ cdef class Block(object):
148
165
  BLOCKSIZE - self.cardinality,
149
166
  BLOCKSIZE - other.cardinality,
150
167
  tmp.data.as_ushorts)
151
- array.resize(tmp, length)
152
- self.cardinality = BLOCKSIZE - length
153
168
  self.buf = tmp
169
+ array.resize(self.buf, length)
170
+ self.cardinality = BLOCKSIZE - length
154
171
  elif self.state == INVERTED and other.state == POSITIVE:
155
172
  tmp = array.clone(ushortarray,
156
173
  max(BLOCKSIZE - self.cardinality, other.cardinality),
@@ -161,10 +178,10 @@ cdef class Block(object):
161
178
  other.cardinality,
162
179
  BLOCKSIZE - self.cardinality,
163
180
  tmp.data.as_ushorts)
164
- array.resize(tmp, length)
181
+ self.buf = tmp
182
+ array.resize(self.buf, length)
165
183
  self.state = POSITIVE
166
184
  self.cardinality = length
167
- self.buf = tmp
168
185
  elif self.state == POSITIVE and other.state == INVERTED:
169
186
  length = difference(
170
187
  self.buf.data.as_ushorts,
@@ -187,20 +204,22 @@ cdef class Block(object):
187
204
  other.buf.data.as_ushorts,
188
205
  self.cardinality, other.cardinality,
189
206
  tmp.data.as_ushorts)
190
- array.resize(tmp, self.cardinality)
191
207
  self.buf = tmp
208
+ array.resize(self.buf, self.cardinality)
192
209
  elif other.state == DENSE:
193
- tmp = array.copy(other.buf)
210
+ tmp = array.clone(ushortarray, BITMAPSIZE // sizeof(short),
211
+ False)
212
+ memcpy(tmp.data.as_chars, other.buf.data.as_chars,
213
+ BITMAPSIZE)
194
214
  length = other.cardinality
195
- array.resize(tmp, length + self.cardinality)
196
215
  for n in range(self.cardinality):
197
216
  if not TESTBIT(tmp.data.as_ulongs,
198
217
  self.buf.data.as_ushorts[n]):
218
+ SETBIT(tmp.data.as_ulongs, self.buf.data.as_ushorts[n])
199
219
  length += 1
200
- SETBIT(tmp.data.as_ulongs, self.buf.data.as_ushorts[n])
220
+ self.buf = tmp
201
221
  self.state = DENSE
202
222
  self.cardinality = length
203
- self.buf = tmp
204
223
  elif other.state == INVERTED:
205
224
  tmp = array.clone(ushortarray, BLOCKSIZE - self.cardinality,
206
225
  False)
@@ -210,10 +229,10 @@ cdef class Block(object):
210
229
  BLOCKSIZE - other.cardinality,
211
230
  self.cardinality,
212
231
  tmp.data.as_ushorts)
213
- array.resize(tmp, length)
232
+ self.buf = tmp
233
+ array.resize(self.buf, length)
214
234
  self.state = INVERTED
215
235
  self.cardinality = BLOCKSIZE - length
216
- self.buf = tmp
217
236
  elif self.state == DENSE:
218
237
  if other.state == POSITIVE:
219
238
  for n in range(other.cardinality):
@@ -235,10 +254,10 @@ cdef class Block(object):
235
254
  tmp.data.as_ushorts[length] = (
236
255
  other.buf.data.as_ushorts[n])
237
256
  length += 1
238
- array.resize(tmp, length)
257
+ self.buf = tmp
258
+ array.resize(self.buf, length)
239
259
  self.cardinality = BLOCKSIZE - length
240
260
  self.state = INVERTED
241
- self.buf = tmp
242
261
  elif self.state == INVERTED:
243
262
  if other.state == POSITIVE:
244
263
  length = difference(
@@ -258,9 +277,9 @@ cdef class Block(object):
258
277
  tmp.data.as_ushorts[length] = (
259
278
  self.buf.data.as_ushorts[n])
260
279
  length += 1
261
- array.resize(tmp, length)
262
- self.cardinality = BLOCKSIZE - length
263
280
  self.buf = tmp
281
+ array.resize(self.buf, length)
282
+ self.cardinality = BLOCKSIZE - length
264
283
  elif other.state == INVERTED:
265
284
  length = intersect2by2(self.buf.data.as_ushorts,
266
285
  other.buf.data.as_ushorts,
@@ -322,9 +341,9 @@ cdef class Block(object):
322
341
  BLOCKSIZE - self.cardinality,
323
342
  BLOCKSIZE - other.cardinality,
324
343
  tmp.data.as_ushorts)
325
- array.resize(tmp, length)
326
- self.cardinality = BLOCKSIZE - length
327
344
  self.buf = tmp
345
+ array.resize(self.buf, length)
346
+ self.cardinality = BLOCKSIZE - length
328
347
  elif self.state == INVERTED and other.state == POSITIVE:
329
348
  length = intersect2by2(
330
349
  self.buf.data.as_ushorts,
@@ -361,7 +380,7 @@ cdef class Block(object):
361
380
  if TESTBIT(self.buf.data.as_ulongs,
362
381
  other.buf.data.as_ushorts[n]):
363
382
  CLEARBIT(self.buf.data.as_ulongs,
364
- self.buf.data.as_ushorts[n])
383
+ other.buf.data.as_ushorts[n])
365
384
  self.cardinality -= 1
366
385
  elif self.state == INVERTED and other.state == DENSE:
367
386
  self.todense()
@@ -381,9 +400,9 @@ cdef class Block(object):
381
400
  self.cardinality,
382
401
  other.cardinality,
383
402
  tmp.data.as_ushorts)
384
- array.resize(tmp, length)
385
- self.cardinality = length
386
403
  self.buf = tmp
404
+ array.resize(self.buf, length)
405
+ self.cardinality = length
387
406
  elif self.state == INVERTED and other.state == INVERTED:
388
407
  tmp = array.clone(ushortarray,
389
408
  BLOCKSIZE - (self.cardinality + other.cardinality),
@@ -394,9 +413,9 @@ cdef class Block(object):
394
413
  BLOCKSIZE - self.cardinality,
395
414
  BLOCKSIZE - other.cardinality,
396
415
  tmp.data.as_ushorts)
397
- array.resize(tmp, length)
398
- self.cardinality = BLOCKSIZE - length
399
416
  self.buf = tmp
417
+ array.resize(self.buf, length)
418
+ self.cardinality = BLOCKSIZE - length
400
419
  elif self.state == INVERTED and other.state == POSITIVE:
401
420
  self.todense()
402
421
  self.ixor(other)
@@ -407,44 +426,6 @@ cdef class Block(object):
407
426
  return
408
427
  self.resize()
409
428
 
410
- cdef flip(self):
411
- """In-place complement of this block."""
412
- if self.state == DENSE:
413
- for n in range(BITNSLOTS(BLOCKSIZE)):
414
- self.buf.data.as_ulongs[n] = ~self.buf.data.as_ulongs[n]
415
- elif self.state == POSITIVE:
416
- self.state = INVERTED
417
- elif self.state == INVERTED:
418
- self.state = POSITIVE
419
- # FIXME: need notion of maximium element
420
- self.cardinality = BLOCKSIZE - self.cardinality
421
-
422
- cdef resize(self):
423
- """Convert between dense, sparse, inverted sparse as needed."""
424
- if self.state == DENSE:
425
- if self.cardinality < MAXARRAYLENGTH:
426
- self.toposarray()
427
- elif self.cardinality > BLOCKSIZE - MAXARRAYLENGTH:
428
- self.toinvarray()
429
- elif self.state == INVERTED:
430
- if (MAXARRAYLENGTH < self.cardinality
431
- < BLOCKSIZE - MAXARRAYLENGTH):
432
- self.todense()
433
- elif self.cardinality < MAXARRAYLENGTH:
434
- # shouldn't happen?
435
- raise ValueError
436
- elif self.state == POSITIVE:
437
- if MAXARRAYLENGTH < self.cardinality < BLOCKSIZE - MAXARRAYLENGTH:
438
- # To dense bitvector
439
- self.todense()
440
- elif self.cardinality > BLOCKSIZE - MAXARRAYLENGTH:
441
- # shouldn't happen?
442
- raise ValueError
443
-
444
- def size(self):
445
- """Return memory usage."""
446
- return 2 * len(self.buf)
447
-
448
429
  cdef issubset(self, Block other):
449
430
  cdef int n, m = 0
450
431
  if self.key != other.key or self.cardinality > other.cardinality:
@@ -594,7 +575,7 @@ cdef class Block(object):
594
575
  elif self.state == POSITIVE:
595
576
  return self.buf.data.as_ushorts[i]
596
577
  elif self.state == DENSE:
597
- for n in range(BITMAPSIZE):
578
+ for n in range(BITNSLOTS(BLOCKSIZE)):
598
579
  w = bit_popcount(self.buf.data.as_ulongs[n])
599
580
  if w > i:
600
581
  return BITSIZE * n + select64(
@@ -608,18 +589,55 @@ cdef class Block(object):
608
589
  return self.buf.data.as_ushorts[len(self.buf) - 1] + (
609
590
  i - len(self.buf))
610
591
 
592
+ cdef flip(self):
593
+ """In-place complement of this block."""
594
+ if self.state == DENSE:
595
+ for n in range(BITNSLOTS(BLOCKSIZE)):
596
+ self.buf.data.as_ulongs[n] = ~self.buf.data.as_ulongs[n]
597
+ elif self.state == POSITIVE:
598
+ self.state = INVERTED
599
+ elif self.state == INVERTED:
600
+ self.state = POSITIVE
601
+ # FIXME: need notion of maximium element
602
+ self.cardinality = BLOCKSIZE - self.cardinality
603
+
604
+ cdef resize(self):
605
+ """Convert between dense, sparse, inverted sparse as needed."""
606
+ if self.state == DENSE:
607
+ if self.cardinality < MAXARRAYLENGTH:
608
+ self.toposarray()
609
+ elif self.cardinality > BLOCKSIZE - MAXARRAYLENGTH:
610
+ self.toinvarray()
611
+ elif self.state == INVERTED:
612
+ if (MAXARRAYLENGTH < self.cardinality
613
+ < BLOCKSIZE - MAXARRAYLENGTH):
614
+ self.todense()
615
+ elif self.cardinality < MAXARRAYLENGTH:
616
+ # shouldn't happen?
617
+ raise ValueError
618
+ elif self.state == POSITIVE:
619
+ if MAXARRAYLENGTH < self.cardinality < BLOCKSIZE - MAXARRAYLENGTH:
620
+ # To dense bitvector
621
+ self.todense()
622
+ elif self.cardinality > BLOCKSIZE - MAXARRAYLENGTH:
623
+ # shouldn't happen?
624
+ raise ValueError
625
+
626
+ def __sizeof__(self):
627
+ """Return memory usage in bytes."""
628
+ return (sizeof(self.state) + sizeof(self.key)
629
+ + sizeof(self.cardinality) + sys.getsizeof(self.buf))
630
+
611
631
  cdef todense(self):
612
632
  # To dense bitvector
613
- cdef array.array tmp
614
633
  cdef int n
634
+ tmp = array.clone(ushortarray, BITMAPSIZE // sizeof(short), False)
615
635
  if self.state == INVERTED:
616
- tmp = array.clone(ushortarray, BITMAPSIZE, False)
617
- memset(tmp.data.as_uchars, 255, BLOCKSIZE // sizeof(char))
636
+ memset(tmp.data.as_chars, 255, BITMAPSIZE)
618
637
  for n in range(BLOCKSIZE - self.cardinality):
619
- CLEARBIT(tmp.data.as_ulongs,
620
- self.buf.data.as_ushorts[n])
638
+ CLEARBIT(tmp.data.as_ulongs, self.buf.data.as_ushorts[n])
621
639
  else: # self.state == POSITIVE:
622
- tmp = array.clone(ushortarray, BITMAPSIZE, True)
640
+ memset(tmp.data.as_chars, 0, BITMAPSIZE)
623
641
  for n in range(self.cardinality):
624
642
  SETBIT(tmp.data.as_ulongs, self.buf.data.as_ushorts[n])
625
643
  self.state = DENSE
@@ -755,15 +773,21 @@ cdef class Block(object):
755
773
  elif self.state == POSITIVE:
756
774
  return 'array(%r)' % self.buf
757
775
 
776
+ cdef allocarray(self):
777
+ self.buf = array.clone(ushortarray, 0, False)
778
+
758
779
  def __reduce__(self):
759
- return (Block, None, (self.key, self.state,
760
- self.cardinality, self.buf))
761
-
762
- def __setstate__(self, key, state, cardinality, buf):
763
- self.key = key
764
- self.state = state
765
- self.cardinality = cardinality
766
- self.buf = buf
780
+ return (Block, (), dict(
781
+ key=self.key,
782
+ state=self.state,
783
+ cardinality=self.cardinality,
784
+ buf=self.buf))
785
+
786
+ def __setstate__(self, state):
787
+ self.key = state['key']
788
+ self.state = state['state']
789
+ self.cardinality = state['cardinality']
790
+ self.buf = state['buf']
767
791
 
768
792
 
769
793
  cdef inline int min(int a, int b):
@@ -1,7 +1,7 @@
1
1
 
2
2
  /* http://c-faq.com/misc/bitsets.html */
3
3
  #define BITSIZE (8 * sizeof(uint64_t))
4
- #define BITMASK(b) (1UL << ((b) % BITSIZE))
4
+ #define BITMASK(b) (1ULL << ((b) % BITSIZE))
5
5
  #define BITSLOT(b) ((b) / BITSIZE)
6
6
  #define SETBIT(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
7
7
  #define TOGGLEBIT(a, b) ((a)[BITSLOT(b)] ^= BITMASK(b))