bitarray 3.12.1__tar.gz → 3.12.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.
Files changed (26) hide show
  1. {bitarray-3.12.1 → bitarray-3.12.3}/PKG-INFO +21 -65
  2. {bitarray-3.12.1 → bitarray-3.12.3}/README.rst +20 -64
  3. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/__init__.pyi +22 -20
  4. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/_bitarray.c +68 -48
  5. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/_util.c +75 -32
  6. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/bitarray.h +36 -10
  7. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/pythoncapi_compat.h +823 -399
  8. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/test_bitarray.py +139 -34
  9. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/test_util.py +67 -4
  10. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray.egg-info/PKG-INFO +21 -65
  11. {bitarray-3.12.1 → bitarray-3.12.3}/LICENSE +0 -0
  12. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/__init__.py +0 -0
  13. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/bitfields.py +0 -0
  14. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/py.typed +0 -0
  15. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/test_281.pickle +0 -0
  16. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/test_bitfields.py +0 -0
  17. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/test_free_threading.py +0 -0
  18. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/util.py +0 -0
  19. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray/util.pyi +0 -0
  20. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray.egg-info/SOURCES.txt +0 -0
  21. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray.egg-info/dependency_links.txt +0 -0
  22. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray.egg-info/not-zip-safe +0 -0
  23. {bitarray-3.12.1 → bitarray-3.12.3}/bitarray.egg-info/top_level.txt +0 -0
  24. {bitarray-3.12.1 → bitarray-3.12.3}/pyproject.toml +0 -0
  25. {bitarray-3.12.1 → bitarray-3.12.3}/setup.cfg +0 -0
  26. {bitarray-3.12.1 → bitarray-3.12.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bitarray
3
- Version: 3.12.1
3
+ Version: 3.12.3
4
4
  Summary: efficient arrays of booleans -- C extension
5
5
  Home-page: https://github.com/ilanschnell/bitarray
6
6
  Author: Ilan Schnell
@@ -57,7 +57,9 @@ Key features
57
57
  their in-place versions ``&=``, ``|=``, ``^=``, ``<<=``, ``>>=``).
58
58
  * `Free-threading support <https://github.com/ilanschnell/bitarray/blob/master/doc/free_threading.rst>`__
59
59
  (for GIL-disabled CPython 3.14 and later)
60
- * Fast methods for encoding and decoding variable-length prefix codes.
60
+ * Written to `support all platforms supported by CPython and PyPy <https://github.com/ilanschnell/bitarray/blob/master/doc/platforms.rst>`__.
61
+ * Fast methods for encoding and decoding variable-length
62
+ `prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__.
61
63
  * Bitarray objects support the `buffer protocol <https://github.com/ilanschnell/bitarray/blob/master/doc/buffer.rst>`__
62
64
  (both importing and exporting buffers).
63
65
  * Efficient packing and unpacking for interoperability with byte-oriented
@@ -91,7 +93,7 @@ versions. Which means you can simply:
91
93
 
92
94
  .. code-block:: shell-session
93
95
 
94
- $ pip install bitarray
96
+ $ python -m pip install bitarray
95
97
 
96
98
  Once you have installed the package, you may want to test it:
97
99
 
@@ -100,26 +102,27 @@ Once you have installed the package, you may want to test it:
100
102
  $ python -c 'import bitarray; bitarray.test()'
101
103
  bitarray is installed in: /Users/ilan/bitarray/bitarray
102
104
  sys.prefix: /Users/ilan/miniforge
103
- bitarray version: 3.12.1
105
+ bitarray version: 3.12.3
106
+ platform.machine(): arm64
107
+ platform.platform(): macOS-14.3-arm64-arm-64bit-Mach-O
108
+ sys.platform: darwin
104
109
  sys.version: 3.15.0 (main, Oct 9 2026) [Clang 21.1.8]
105
110
  sys.abiflags: ''
106
111
  sys._is_gil_enabled(): True
107
112
  pointer size: 64 bit
108
- sizeof(size_t): 8
109
- sizeof(bitarrayobject): 80
110
113
  HAVE_BUILTIN_BSWAP64: 1
111
114
  default bit-endianness: big
112
115
  machine byte-order: little
113
116
  Py_GIL_DISABLED: 0
114
117
  Py_DEBUG: 0
115
118
  DEBUG: 0
116
- .....................................s...................................
117
- ..........s.....................................s........................
119
+ .........................................................................
120
+ ................................................s........................
118
121
  ......s.........................................................
119
122
  ----------------------------------------------------------------------
120
- Ran 711 tests in 0.161s
123
+ Ran 723 tests in 0.163s
121
124
 
122
- OK (skipped=4)
125
+ OK (skipped=2)
123
126
 
124
127
  The ``test()`` function is part of the API. It will return
125
128
  a ``unittest.runner.TextTestResult`` object, such that one can verify that
@@ -289,59 +292,6 @@ this topic, please read `buffer protocol <https://github.com/ilanschnell/bitarra
289
292
  to memory-map a file to a bitarray: `mmapped-file.py <https://github.com/ilanschnell/bitarray/blob/master/examples/mmapped-file.py>`__
290
293
 
291
294
 
292
- Variable-length prefix codes
293
- ----------------------------
294
-
295
- The ``.encode()`` method takes a dictionary mapping symbols to bitarrays
296
- and an iterable, and extends the bitarray object with the encoded symbols
297
- found while iterating. For example:
298
-
299
- .. code-block:: python
300
-
301
- >>> d = {'H':bitarray('111'), 'e':bitarray('0'),
302
- ... 'l':bitarray('110'), 'o':bitarray('10')}
303
- ...
304
- >>> a = bitarray()
305
- >>> a.encode(d, 'Hello')
306
- >>> a
307
- bitarray('111011011010')
308
-
309
- Note that the string ``'Hello'`` is an iterable, but the symbols are not
310
- limited to characters, in fact any immutable Python object can be a symbol.
311
- Taking the same dictionary, we can apply the ``.decode()`` method which will
312
- return an iterable of the symbols:
313
-
314
- .. code-block:: python
315
-
316
- >>> list(a.decode(d))
317
- ['H', 'e', 'l', 'l', 'o']
318
- >>> ''.join(a.decode(d))
319
- 'Hello'
320
-
321
- Symbols are not limited to being characters.
322
- The above dictionary ``d`` can be efficiently constructed using the function
323
- ``bitarray.util.huffman_code()``. I also wrote `Huffman coding in Python
324
- using bitarray <http://ilan.schnell-web.net/prog/huffman/>`__ for more
325
- background information.
326
-
327
- When the codes are large, and you have many decode calls, most time will
328
- be spent creating the (same) internal decode tree objects. In this case,
329
- it will be much faster to create a ``decodetree`` object, which can be
330
- passed to bitarray's ``.decode()`` method, instead of passing the prefix
331
- code dictionary to those methods itself:
332
-
333
- .. code-block:: python
334
-
335
- >>> from bitarray import bitarray, decodetree
336
- >>> t = decodetree({'a': bitarray('0'), 'b': bitarray('1')})
337
- >>> a = bitarray('0110')
338
- >>> list(a.decode(t))
339
- ['a', 'b', 'b', 'a']
340
-
341
- The sole purpose of the immutable ``decodetree`` object is to be passed
342
- to bitarray's ``.decode()`` method.
343
-
344
-
345
295
  Frozenbitarrays
346
296
  ---------------
347
297
 
@@ -364,7 +314,7 @@ and can therefore be used as a dictionary key:
364
314
  Reference
365
315
  =========
366
316
 
367
- bitarray version: 3.12.1 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
317
+ bitarray version: 3.12.3 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
368
318
 
369
319
  In the following, ``item`` and ``value`` are usually a single bit -
370
320
  an integer 0 or 1.
@@ -475,7 +425,7 @@ bitarray methods:
475
425
  corresponding symbols.
476
426
  The prefix code length cannot exceed 256 bits.
477
427
 
478
- See also: `Bitarray 3 transition <https://github.com/ilanschnell/bitarray/blob/master/doc/bitarray3.rst>`__
428
+ See also: `Bitarray 3 transition <https://github.com/ilanschnell/bitarray/blob/master/doc/bitarray3.rst>`__, `Variable-length prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__
479
429
 
480
430
  New in version 3.0: returns iterator (equivalent to past ``.iterdecode()``)
481
431
 
@@ -487,6 +437,8 @@ bitarray methods:
487
437
  iterate over the iterable object with symbols, and extend bitarray
488
438
  with corresponding bitarray for each symbol.
489
439
 
440
+ See also: `Variable-length prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__
441
+
490
442
 
491
443
  ``extend(iterable, /)``
492
444
  Append items from iterable to the end of the bitarray.
@@ -725,6 +677,8 @@ Other objects:
725
677
  create a binary tree object to be passed to ``.decode()``.
726
678
  The prefix code length cannot exceed 256 bits.
727
679
 
680
+ See also: `Variable-length prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__
681
+
728
682
  New in version 1.6
729
683
 
730
684
 
@@ -911,6 +865,8 @@ This sub-module was added in version 1.2.
911
865
  frozenbitarrays (with given bit-endianness). Note that the symbols are not
912
866
  limited to being strings. Symbols may be any hashable object.
913
867
 
868
+ See also: `Variable-length prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__
869
+
914
870
  New in version 3.10: return a codedict mapping to frozenbitarrays
915
871
 
916
872
 
@@ -21,7 +21,9 @@ Key features
21
21
  their in-place versions ``&=``, ``|=``, ``^=``, ``<<=``, ``>>=``).
22
22
  * `Free-threading support <https://github.com/ilanschnell/bitarray/blob/master/doc/free_threading.rst>`__
23
23
  (for GIL-disabled CPython 3.14 and later)
24
- * Fast methods for encoding and decoding variable-length prefix codes.
24
+ * Written to `support all platforms supported by CPython and PyPy <https://github.com/ilanschnell/bitarray/blob/master/doc/platforms.rst>`__.
25
+ * Fast methods for encoding and decoding variable-length
26
+ `prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__.
25
27
  * Bitarray objects support the `buffer protocol <https://github.com/ilanschnell/bitarray/blob/master/doc/buffer.rst>`__
26
28
  (both importing and exporting buffers).
27
29
  * Efficient packing and unpacking for interoperability with byte-oriented
@@ -55,7 +57,7 @@ versions. Which means you can simply:
55
57
 
56
58
  .. code-block:: shell-session
57
59
 
58
- $ pip install bitarray
60
+ $ python -m pip install bitarray
59
61
 
60
62
  Once you have installed the package, you may want to test it:
61
63
 
@@ -64,26 +66,27 @@ Once you have installed the package, you may want to test it:
64
66
  $ python -c 'import bitarray; bitarray.test()'
65
67
  bitarray is installed in: /Users/ilan/bitarray/bitarray
66
68
  sys.prefix: /Users/ilan/miniforge
67
- bitarray version: 3.12.1
69
+ bitarray version: 3.12.3
70
+ platform.machine(): arm64
71
+ platform.platform(): macOS-14.3-arm64-arm-64bit-Mach-O
72
+ sys.platform: darwin
68
73
  sys.version: 3.15.0 (main, Oct 9 2026) [Clang 21.1.8]
69
74
  sys.abiflags: ''
70
75
  sys._is_gil_enabled(): True
71
76
  pointer size: 64 bit
72
- sizeof(size_t): 8
73
- sizeof(bitarrayobject): 80
74
77
  HAVE_BUILTIN_BSWAP64: 1
75
78
  default bit-endianness: big
76
79
  machine byte-order: little
77
80
  Py_GIL_DISABLED: 0
78
81
  Py_DEBUG: 0
79
82
  DEBUG: 0
80
- .....................................s...................................
81
- ..........s.....................................s........................
83
+ .........................................................................
84
+ ................................................s........................
82
85
  ......s.........................................................
83
86
  ----------------------------------------------------------------------
84
- Ran 711 tests in 0.161s
87
+ Ran 723 tests in 0.163s
85
88
 
86
- OK (skipped=4)
89
+ OK (skipped=2)
87
90
 
88
91
  The ``test()`` function is part of the API. It will return
89
92
  a ``unittest.runner.TextTestResult`` object, such that one can verify that
@@ -253,59 +256,6 @@ this topic, please read `buffer protocol <https://github.com/ilanschnell/bitarra
253
256
  to memory-map a file to a bitarray: `mmapped-file.py <https://github.com/ilanschnell/bitarray/blob/master/examples/mmapped-file.py>`__
254
257
 
255
258
 
256
- Variable-length prefix codes
257
- ----------------------------
258
-
259
- The ``.encode()`` method takes a dictionary mapping symbols to bitarrays
260
- and an iterable, and extends the bitarray object with the encoded symbols
261
- found while iterating. For example:
262
-
263
- .. code-block:: python
264
-
265
- >>> d = {'H':bitarray('111'), 'e':bitarray('0'),
266
- ... 'l':bitarray('110'), 'o':bitarray('10')}
267
- ...
268
- >>> a = bitarray()
269
- >>> a.encode(d, 'Hello')
270
- >>> a
271
- bitarray('111011011010')
272
-
273
- Note that the string ``'Hello'`` is an iterable, but the symbols are not
274
- limited to characters, in fact any immutable Python object can be a symbol.
275
- Taking the same dictionary, we can apply the ``.decode()`` method which will
276
- return an iterable of the symbols:
277
-
278
- .. code-block:: python
279
-
280
- >>> list(a.decode(d))
281
- ['H', 'e', 'l', 'l', 'o']
282
- >>> ''.join(a.decode(d))
283
- 'Hello'
284
-
285
- Symbols are not limited to being characters.
286
- The above dictionary ``d`` can be efficiently constructed using the function
287
- ``bitarray.util.huffman_code()``. I also wrote `Huffman coding in Python
288
- using bitarray <http://ilan.schnell-web.net/prog/huffman/>`__ for more
289
- background information.
290
-
291
- When the codes are large, and you have many decode calls, most time will
292
- be spent creating the (same) internal decode tree objects. In this case,
293
- it will be much faster to create a ``decodetree`` object, which can be
294
- passed to bitarray's ``.decode()`` method, instead of passing the prefix
295
- code dictionary to those methods itself:
296
-
297
- .. code-block:: python
298
-
299
- >>> from bitarray import bitarray, decodetree
300
- >>> t = decodetree({'a': bitarray('0'), 'b': bitarray('1')})
301
- >>> a = bitarray('0110')
302
- >>> list(a.decode(t))
303
- ['a', 'b', 'b', 'a']
304
-
305
- The sole purpose of the immutable ``decodetree`` object is to be passed
306
- to bitarray's ``.decode()`` method.
307
-
308
-
309
259
  Frozenbitarrays
310
260
  ---------------
311
261
 
@@ -328,7 +278,7 @@ and can therefore be used as a dictionary key:
328
278
  Reference
329
279
  =========
330
280
 
331
- bitarray version: 3.12.1 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
281
+ bitarray version: 3.12.3 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
332
282
 
333
283
  In the following, ``item`` and ``value`` are usually a single bit -
334
284
  an integer 0 or 1.
@@ -439,7 +389,7 @@ bitarray methods:
439
389
  corresponding symbols.
440
390
  The prefix code length cannot exceed 256 bits.
441
391
 
442
- See also: `Bitarray 3 transition <https://github.com/ilanschnell/bitarray/blob/master/doc/bitarray3.rst>`__
392
+ See also: `Bitarray 3 transition <https://github.com/ilanschnell/bitarray/blob/master/doc/bitarray3.rst>`__, `Variable-length prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__
443
393
 
444
394
  New in version 3.0: returns iterator (equivalent to past ``.iterdecode()``)
445
395
 
@@ -451,6 +401,8 @@ bitarray methods:
451
401
  iterate over the iterable object with symbols, and extend bitarray
452
402
  with corresponding bitarray for each symbol.
453
403
 
404
+ See also: `Variable-length prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__
405
+
454
406
 
455
407
  ``extend(iterable, /)``
456
408
  Append items from iterable to the end of the bitarray.
@@ -689,6 +641,8 @@ Other objects:
689
641
  create a binary tree object to be passed to ``.decode()``.
690
642
  The prefix code length cannot exceed 256 bits.
691
643
 
644
+ See also: `Variable-length prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__
645
+
692
646
  New in version 1.6
693
647
 
694
648
 
@@ -875,6 +829,8 @@ This sub-module was added in version 1.2.
875
829
  frozenbitarrays (with given bit-endianness). Note that the symbols are not
876
830
  limited to being strings. Symbols may be any hashable object.
877
831
 
832
+ See also: `Variable-length prefix codes <https://github.com/ilanschnell/bitarray/blob/master/doc/prefix_codes.rst>`__
833
+
878
834
  New in version 3.10: return a codedict mapping to frozenbitarrays
879
835
 
880
836
 
@@ -6,9 +6,11 @@ from abc import ABCMeta
6
6
  from collections.abc import Iterable, Iterator, Sequence
7
7
  from unittest.runner import TextTestResult
8
8
 
9
- from typing import Any, BinaryIO, Dict, Union, overload, NamedTuple
9
+ from typing import Any, BinaryIO, Dict, Union, overload, NamedTuple, TypeVar
10
10
 
11
11
 
12
+ _BitarrayT = TypeVar("_BitarrayT", bound="bitarray")
13
+
12
14
  CodeDict = Dict[Any, bitarray]
13
15
  # Python 3.12 has abc.Buffer which should be used instead
14
16
  BytesLike = Union[bytes, bytearray]
@@ -52,7 +54,7 @@ class bitarray:
52
54
  stop: int = ...) -> None: ...
53
55
 
54
56
  def clear(self) -> None: ...
55
- def copy(self) -> bitarray: ...
57
+ def copy(self: _BitarrayT) -> _BitarrayT: ...
56
58
  def count(self,
57
59
  sub_bitarray: Union[bitarray, int] = ...,
58
60
  start: int = ...,
@@ -111,8 +113,8 @@ class bitarray:
111
113
  @overload
112
114
  def __getitem__(self, i: int) -> int: ...
113
115
  @overload
114
- def __getitem__(self,
115
- s: Union[slice, bitarray, Sequence]) -> bitarray: ...
116
+ def __getitem__(self: _BitarrayT,
117
+ s: Union[slice, bitarray, Sequence]) -> _BitarrayT: ...
116
118
  @overload
117
119
  def __setitem__(self,
118
120
  i: Union[int, slice, Sequence],
@@ -127,28 +129,28 @@ class bitarray:
127
129
  def __buffer__(self, flags: int, /) -> memoryview: ...
128
130
  def __release_buffer__(self, buffer: memoryview, /) -> None: ...
129
131
 
130
- def __add__(self, other: bitarray) -> bitarray: ...
131
- def __iadd__(self, other: bitarray) -> bitarray: ...
132
- def __mul__(self, n: int) -> bitarray: ...
133
- def __imul__(self, n: int) -> bitarray: ...
134
- def __rmul__(self, n: int) -> bitarray: ...
132
+ def __add__(self: _BitarrayT, other: bitarray) -> _BitarrayT: ...
133
+ def __iadd__(self: _BitarrayT, other: bitarray) -> _BitarrayT: ...
134
+ def __mul__(self: _BitarrayT, n: int) -> _BitarrayT: ...
135
+ def __imul__(self: _BitarrayT, n: int) -> _BitarrayT: ...
136
+ def __rmul__(self: _BitarrayT, n: int) -> _BitarrayT: ...
135
137
 
136
138
  def __ge__(self, other: bitarray) -> bool: ...
137
139
  def __gt__(self, other: bitarray) -> bool: ...
138
140
  def __le__(self, other: bitarray) -> bool: ...
139
141
  def __lt__(self, other: bitarray) -> bool: ...
140
142
 
141
- def __and__(self, other: bitarray) -> bitarray: ...
142
- def __or__(self, other: bitarray) -> bitarray: ...
143
- def __xor__(self, other: bitarray) -> bitarray: ...
144
- def __iand__(self, other: bitarray) -> bitarray: ...
145
- def __ior__(self, other: bitarray) -> bitarray: ...
146
- def __ixor__(self, other: bitarray) -> bitarray: ...
147
- def __invert__(self) -> bitarray: ...
148
- def __lshift__(self, n: int) -> bitarray: ...
149
- def __rshift__(self, n: int) -> bitarray: ...
150
- def __ilshift__(self, n: int) -> bitarray: ...
151
- def __irshift__(self, n: int) -> bitarray: ...
143
+ def __and__(self: _BitarrayT, other: bitarray) -> _BitarrayT: ...
144
+ def __or__(self: _BitarrayT, other: bitarray) -> _BitarrayT: ...
145
+ def __xor__(self: _BitarrayT, other: bitarray) -> _BitarrayT: ...
146
+ def __iand__(self: _BitarrayT, other: bitarray) -> _BitarrayT: ...
147
+ def __ior__(self: _BitarrayT, other: bitarray) -> _BitarrayT: ...
148
+ def __ixor__(self: _BitarrayT, other: bitarray) -> _BitarrayT: ...
149
+ def __invert__(self: _BitarrayT) -> _BitarrayT: ...
150
+ def __lshift__(self: _BitarrayT, n: int) -> _BitarrayT: ...
151
+ def __rshift__(self: _BitarrayT, n: int) -> _BitarrayT: ...
152
+ def __ilshift__(self: _BitarrayT, n: int) -> _BitarrayT: ...
153
+ def __irshift__(self: _BitarrayT, n: int) -> _BitarrayT: ...
152
154
 
153
155
  # data descriptors
154
156
  @property
@@ -224,19 +224,19 @@ bytereverse(char *p, Py_ssize_t n)
224
224
  static void
225
225
  shift_r8le(unsigned char *buff, Py_ssize_t n, int k)
226
226
  {
227
- Py_ssize_t w = 0;
227
+ Py_ssize_t w = 0, r = n;
228
228
 
229
229
  #if HAVE_BUILTIN_BSWAP64 || PY_LITTLE_ENDIAN /* use shift word */
230
230
  w = n / 8; /* number of words used for shifting */
231
- n %= 8; /* number of remaining bytes */
231
+ r = n % 8; /* number of remaining bytes */
232
232
  #endif
233
- while (n--) { /* shift in byte-range(8 * w, n) */
234
- Py_ssize_t i = n + 8 * w;
233
+ while (r--) { /* shift in byte-range(8 * w, n) */
234
+ Py_ssize_t i = r + 8 * w;
235
235
  buff[i] <<= k; /* shift byte */
236
- if (n || w) /* add shifted next lower byte */
236
+ if (r || w) /* add shifted next lower byte */
237
237
  buff[i] |= buff[i - 1] >> (8 - k);
238
238
  }
239
- assert(w == 0 || ((uintptr_t) buff) % 4 == 0);
239
+ assert(w == 0 || ((uintptr_t) buff) % 8 == 0);
240
240
  while (w--) { /* shift in word-range(0, w) */
241
241
  uint64_t *p = ((uint64_t *) buff) + w;
242
242
  #if HAVE_BUILTIN_BSWAP64 && PY_BIG_ENDIAN
@@ -254,19 +254,19 @@ shift_r8le(unsigned char *buff, Py_ssize_t n, int k)
254
254
  static void
255
255
  shift_r8be(unsigned char *buff, Py_ssize_t n, int k)
256
256
  {
257
- Py_ssize_t w = 0;
257
+ Py_ssize_t w = 0, r = n;
258
258
 
259
259
  #if HAVE_BUILTIN_BSWAP64 || PY_BIG_ENDIAN /* use shift word */
260
260
  w = n / 8; /* number of words used for shifting */
261
- n %= 8; /* number of remaining bytes */
261
+ r = n % 8; /* number of remaining bytes */
262
262
  #endif
263
- while (n--) { /* shift in byte-range(8 * w, n) */
264
- Py_ssize_t i = n + 8 * w;
263
+ while (r--) { /* shift in byte-range(8 * w, n) */
264
+ Py_ssize_t i = r + 8 * w;
265
265
  buff[i] >>= k; /* shift byte */
266
- if (n || w) /* add shifted next lower byte */
266
+ if (r || w) /* add shifted next lower byte */
267
267
  buff[i] |= buff[i - 1] << (8 - k);
268
268
  }
269
- assert(w == 0 || ((uintptr_t) buff) % 4 == 0);
269
+ assert(w == 0 || ((uintptr_t) buff) % 8 == 0);
270
270
  while (w--) { /* shift in word-range(0, w) */
271
271
  uint64_t *p = ((uint64_t *) buff) + w;
272
272
  #if HAVE_BUILTIN_BSWAP64 && PY_LITTLE_ENDIAN
@@ -285,7 +285,7 @@ shift_r8be(unsigned char *buff, Py_ssize_t n, int k)
285
285
  static void
286
286
  shift_r8(bitarrayobject *self, Py_ssize_t a, Py_ssize_t b, int k)
287
287
  {
288
- unsigned char *buff = (unsigned char *) self->ob_item + a;
288
+ unsigned char *buff;
289
289
  Py_ssize_t n = b - a; /* number of bytes to be shifted */
290
290
  Py_ssize_t s = 0; /* distance to next aligned pointer */
291
291
 
@@ -296,8 +296,11 @@ shift_r8(bitarrayobject *self, Py_ssize_t a, Py_ssize_t b, int k)
296
296
  if (k == 0 || n <= 0)
297
297
  return;
298
298
 
299
+ assert(Py_SIZE(self));
300
+ buff = (unsigned char *) self->ob_item + a;
301
+
299
302
  if (n >= 8) {
300
- s = to_aligned((void *) buff);
303
+ s = to_aligned(buff);
301
304
  buff += s; /* align pointer for casting to (uint64_t *) */
302
305
  n -= s;
303
306
  }
@@ -464,14 +467,18 @@ invert_span(bitarrayobject *self, Py_ssize_t a, Py_ssize_t b)
464
467
  assert(self->readonly == 0);
465
468
 
466
469
  if (n >= 64) {
467
- const Py_ssize_t wa = (a + 63) / 64; /* word-range(wa, wb) */
468
- const Py_ssize_t wb = b / 64;
469
- uint64_t *wbuff = WBUFF(self);
470
+ uint64_t *words;
471
+ Py_ssize_t p1, p2, w;
472
+
473
+ w = aligned_words(self->ob_item, BYTES(a), b / 8, &p1, &p2);
474
+
475
+ invert_span(self, a, 8 * p1);
476
+
477
+ words = w ? (uint64_t *) (self->ob_item + p1) : NULL;
478
+ for (i = 0; i < w; i++)
479
+ words[i] = ~words[i];
470
480
 
471
- invert_span(self, a, 64 * wa);
472
- for (i = wa; i < wb; i++)
473
- wbuff[i] = ~wbuff[i];
474
- invert_span(self, 64 * wb, b);
481
+ invert_span(self, 8 * p2, b);
475
482
  }
476
483
  else if (n >= 8) {
477
484
  const Py_ssize_t ca = BYTES(a); /* char-range(ca, cb) */
@@ -574,15 +581,14 @@ count_span(bitarrayobject *self, Py_ssize_t a, Py_ssize_t b)
574
581
  assert(0 <= b && b <= self->nbits);
575
582
 
576
583
  if (n >= 64) {
577
- Py_ssize_t p = BYTES(a), w; /* first full byte */
578
- p += to_aligned((void *) (self->ob_item + p)); /* align pointer */
579
- w = (b / 8 - p) / 8; /* number of (full) words to count */
584
+ Py_ssize_t p1, p2, w;
580
585
 
581
- assert(8 * p - a < 64 && b - (8 * (p + 8 * w)) < 64 && w >= 0);
586
+ w = aligned_words(self->ob_item, BYTES(a), b / 8, &p1, &p2);
582
587
 
583
- cnt += count_span(self, a, 8 * p);
584
- cnt += popcnt_words((uint64_t *) (self->ob_item + p), w);
585
- cnt += count_span(self, 8 * (p + 8 * w), b);
588
+ cnt += count_span(self, a, 8 * p1);
589
+ if (w)
590
+ cnt += popcnt_words((uint64_t *) (self->ob_item + p1), w);
591
+ cnt += count_span(self, 8 * p2, b);
586
592
  }
587
593
  else if (n >= 8) {
588
594
  const Py_ssize_t ca = BYTES(a); /* char-range(ca, cb) */
@@ -636,31 +642,36 @@ static Py_ssize_t
636
642
  find_bit_words(bitarrayobject *self, int vi,
637
643
  Py_ssize_t a, Py_ssize_t b, int right)
638
644
  {
639
- const Py_ssize_t wa = (a + 63) / 64; /* word-range(wa, wb) */
640
- const Py_ssize_t wb = b / 64;
641
- const uint64_t *wbuff = WBUFF(self);
642
- const uint64_t w = vi ? 0 : ~0;
643
- Py_ssize_t res, i;
645
+ const uint64_t word = vi ? 0 : ~0;
646
+ const uint64_t *words;
647
+ Py_ssize_t p1, p2, n, q, res, i;
648
+
649
+ n = aligned_words(self->ob_item, BYTES(a), b / 8, &p1, &p2);
650
+ words = n ? (uint64_t *) (self->ob_item + p1) : NULL;
644
651
 
645
652
  if (right) {
646
- if ((res = find_bit(self, vi, 64 * wb, b, 1)) >= 0)
653
+ if ((res = find_bit(self, vi, 8 * p2, b, 1)) >= 0)
647
654
  return res;
648
655
 
649
- for (i = wb - 1; i >= wa; i--) { /* skip uint64 words */
650
- if (w ^ wbuff[i])
651
- return find_bit(self, vi, 64 * i, 64 * i + 64, 1);
656
+ for (i = n - 1; i >= 0; i--) { /* skip uint64 words */
657
+ if (word ^ words[i]) {
658
+ q = 8 * p1 + 64 * i;
659
+ return find_bit(self, vi, q, q + 64, 1);
660
+ }
652
661
  }
653
- return find_bit(self, vi, a, 64 * wa, 1);
662
+ return find_bit(self, vi, a, 8 * p1, 1);
654
663
  }
655
664
  else {
656
- if ((res = find_bit(self, vi, a, 64 * wa, 0)) >= 0)
665
+ if ((res = find_bit(self, vi, a, 8 * p1, 0)) >= 0)
657
666
  return res;
658
667
 
659
- for (i = wa; i < wb; i++) { /* skip uint64 words */
660
- if (w ^ wbuff[i])
661
- return find_bit(self, vi, 64 * i, 64 * i + 64, 0);
668
+ for (i = 0; i < n; i++) { /* skip uint64 words */
669
+ if (word ^ words[i]) {
670
+ q = 8 * p1 + 64 * i;
671
+ return find_bit(self, vi, q, q + 64, 0);
672
+ }
662
673
  }
663
- return find_bit(self, vi, 64 * wb, b, 0);
674
+ return find_bit(self, vi, 8 * p2, b, 0);
664
675
  }
665
676
  }
666
677
 
@@ -3428,16 +3439,25 @@ bitwise_lock_held(bitarrayobject *self,
3428
3439
  bitarrayobject *other, const char oper)
3429
3440
  {
3430
3441
  const Py_ssize_t nbytes = Py_SIZE(self);
3431
- const Py_ssize_t cwords = nbytes / 8; /* complete 64-bit words */
3432
- Py_ssize_t i;
3442
+ Py_ssize_t cwords, i;
3433
3443
  char *buff_s = self->ob_item;
3434
3444
  char *buff_o = other->ob_item;
3435
- uint64_t *wbuff_s = WBUFF(self);
3436
- uint64_t *wbuff_o = WBUFF(other);
3445
+ uint64_t *wbuff_s, *wbuff_o;
3437
3446
 
3438
3447
  assert(self->nbits == other->nbits);
3439
3448
  assert(self->endian == other->endian);
3440
3449
  assert(self->readonly == 0);
3450
+
3451
+ if (((uintptr_t) buff_s) % 8 == 0 &&
3452
+ ((uintptr_t) buff_o) % 8 == 0) {
3453
+ cwords = nbytes / 8; /* complete aligned 64-bit words */
3454
+ wbuff_s = WBUFF(self);
3455
+ wbuff_o = WBUFF(other);
3456
+ }
3457
+ else {
3458
+ cwords = 0;
3459
+ }
3460
+
3441
3461
  switch (oper) {
3442
3462
  case '&':
3443
3463
  for (i = 0; i < cwords; i++)
@@ -5120,7 +5140,7 @@ static PyTypeObject Bitarray_Type = {
5120
5140
  &bitarray_as_number, /* tp_as_number */
5121
5141
  &bitarray_as_sequence, /* tp_as_sequence */
5122
5142
  &bitarray_as_mapping, /* tp_as_mapping */
5123
- PyObject_HashNotImplemented, /* tp_hash */
5143
+ 0, /* tp_hash */
5124
5144
  0, /* tp_call */
5125
5145
  0, /* tp_str */
5126
5146
  PyObject_GenericGetAttr, /* tp_getattro */