bitarray 3.12.2__cp314-cp314-pyemscripten_2026_0_wasm32.whl
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.
- bitarray/__init__.py +66 -0
- bitarray/__init__.pyi +176 -0
- bitarray/_bitarray.cpython-314-wasm32-emscripten.so +0 -0
- bitarray/_util.cpython-314-wasm32-emscripten.so +0 -0
- bitarray/bitarray.h +357 -0
- bitarray/bitfields.py +447 -0
- bitarray/py.typed +0 -0
- bitarray/pythoncapi_compat.h +3138 -0
- bitarray/test_281.pickle +0 -0
- bitarray/test_bitarray.py +5788 -0
- bitarray/test_bitfields.py +721 -0
- bitarray/test_free_threading.py +840 -0
- bitarray/test_util.py +3166 -0
- bitarray/util.py +694 -0
- bitarray/util.pyi +86 -0
- bitarray-3.12.2.dist-info/METADATA +1134 -0
- bitarray-3.12.2.dist-info/RECORD +20 -0
- bitarray-3.12.2.dist-info/WHEEL +5 -0
- bitarray-3.12.2.dist-info/licenses/LICENSE +46 -0
- bitarray-3.12.2.dist-info/top_level.txt +1 -0
bitarray/__init__.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Copyright (c) 2008 - 2026, Ilan Schnell; All Rights Reserved
|
|
2
|
+
"""
|
|
3
|
+
This package defines an object type which can efficiently represent
|
|
4
|
+
a bitarray. Bitarrays are sequence types and behave very much like lists.
|
|
5
|
+
|
|
6
|
+
Please find a description of this package at:
|
|
7
|
+
|
|
8
|
+
https://github.com/ilanschnell/bitarray
|
|
9
|
+
|
|
10
|
+
Author: Ilan Schnell
|
|
11
|
+
"""
|
|
12
|
+
from collections import namedtuple
|
|
13
|
+
|
|
14
|
+
from bitarray._bitarray import (
|
|
15
|
+
bitarray, decodetree, decodeiterator, _bitarray_reconstructor,
|
|
16
|
+
get_default_endian, bits2bytes, BITARRAY_VERSION as __version__
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = ['bitarray', 'frozenbitarray', 'decodetree', 'decodeiterator',
|
|
20
|
+
'bits2bytes']
|
|
21
|
+
|
|
22
|
+
BufferInfo = namedtuple('BufferInfo',
|
|
23
|
+
['address', 'nbytes', 'endian', 'padbits',
|
|
24
|
+
'alloc', 'readonly', 'imported', 'exports'])
|
|
25
|
+
|
|
26
|
+
class frozenbitarray(bitarray):
|
|
27
|
+
"""frozenbitarray(initializer=0, /, endian='big', buffer=None) -> \
|
|
28
|
+
frozenbitarray
|
|
29
|
+
|
|
30
|
+
Return a `frozenbitarray` object. Initialized the same way a `bitarray`
|
|
31
|
+
object is initialized. A `frozenbitarray` is immutable and hashable,
|
|
32
|
+
and may therefore be used as a dictionary key.
|
|
33
|
+
"""
|
|
34
|
+
def __init__(self, *args, **kwargs):
|
|
35
|
+
self._freeze()
|
|
36
|
+
|
|
37
|
+
def __repr__(self):
|
|
38
|
+
return 'frozen' + bitarray.__repr__(self)
|
|
39
|
+
|
|
40
|
+
def __hash__(self):
|
|
41
|
+
"Return hash(self)."
|
|
42
|
+
# ensure hash is independent of endianness
|
|
43
|
+
a = bitarray(self, 'big')
|
|
44
|
+
return hash((len(a), a.tobytes()))
|
|
45
|
+
|
|
46
|
+
# Technically the code below is not necessary, as all these methods will
|
|
47
|
+
# raise a TypeError on read-only memory. However, with a different error
|
|
48
|
+
# message.
|
|
49
|
+
def __delitem__(self, *args, **kwargs):
|
|
50
|
+
"" # no docstring
|
|
51
|
+
raise TypeError("frozenbitarray is immutable")
|
|
52
|
+
|
|
53
|
+
append = bytereverse = clear = extend = encode = fill = __delitem__
|
|
54
|
+
frombytes = fromfile = insert = invert = pack = pop = __delitem__
|
|
55
|
+
remove = rotate = reverse = setall = sort = __setitem__ = __delitem__
|
|
56
|
+
__iadd__ = __iand__ = __imul__ = __ior__ = __ixor__ = __delitem__
|
|
57
|
+
__ilshift__ = __irshift__ = __delitem__
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test(verbosity=1):
|
|
61
|
+
"""test(verbosity=1) -> TextTestResult
|
|
62
|
+
|
|
63
|
+
Run self-test, and return `unittest.runner.TextTestResult` object.
|
|
64
|
+
"""
|
|
65
|
+
from bitarray import test_bitarray
|
|
66
|
+
return test_bitarray.run(verbosity=verbosity)
|
bitarray/__init__.pyi
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Copyright (c) 2021 - 2026, Ilan Schnell; All Rights Reserved
|
|
2
|
+
#
|
|
3
|
+
# This stub, as well as util.pyi, are tested with Python 3.10 and mypy 1.11.2
|
|
4
|
+
|
|
5
|
+
from abc import ABCMeta
|
|
6
|
+
from collections.abc import Iterable, Iterator, Sequence
|
|
7
|
+
from unittest.runner import TextTestResult
|
|
8
|
+
|
|
9
|
+
from typing import Any, BinaryIO, Dict, Union, overload, NamedTuple
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
CodeDict = Dict[Any, bitarray]
|
|
13
|
+
# Python 3.12 has abc.Buffer which should be used instead
|
|
14
|
+
BytesLike = Union[bytes, bytearray]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BufferInfo(NamedTuple):
|
|
18
|
+
address: int
|
|
19
|
+
nbytes: int
|
|
20
|
+
endian: str
|
|
21
|
+
padbits: int
|
|
22
|
+
alloc: int
|
|
23
|
+
readonly: bool
|
|
24
|
+
imported: bool
|
|
25
|
+
exports: int
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class decodetree:
|
|
29
|
+
def __init__(self, code: CodeDict) -> None: ...
|
|
30
|
+
def nodes(self) -> tuple[int, int, int]: ...
|
|
31
|
+
def todict(self) -> CodeDict: ...
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class decodeiterator(Iterator, metaclass=ABCMeta):
|
|
35
|
+
@property
|
|
36
|
+
def index(self) -> int: ...
|
|
37
|
+
def skipbits(self, count: int = ...) -> bitarray: ...
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class bitarray:
|
|
41
|
+
def __init__(self,
|
|
42
|
+
initializer: Union[int, str, Iterable[int], None] = ...,
|
|
43
|
+
endian: Union[str, None] = ...,
|
|
44
|
+
buffer: Any = ...) -> None: ...
|
|
45
|
+
|
|
46
|
+
def all(self) -> bool: ...
|
|
47
|
+
def any(self) -> bool: ...
|
|
48
|
+
def append(self, value: int) -> None: ...
|
|
49
|
+
def buffer_info(self) -> BufferInfo: ...
|
|
50
|
+
def bytereverse(self,
|
|
51
|
+
start: int = ...,
|
|
52
|
+
stop: int = ...) -> None: ...
|
|
53
|
+
|
|
54
|
+
def clear(self) -> None: ...
|
|
55
|
+
def copy(self) -> bitarray: ...
|
|
56
|
+
def count(self,
|
|
57
|
+
sub_bitarray: Union[bitarray, int] = ...,
|
|
58
|
+
start: int = ...,
|
|
59
|
+
stop: int = ...,
|
|
60
|
+
step: int = ...) -> int: ...
|
|
61
|
+
|
|
62
|
+
def encode(self, code: CodeDict, x: Iterable) -> None: ...
|
|
63
|
+
def decode(self,
|
|
64
|
+
code: Union[CodeDict, decodetree]) -> decodeiterator: ...
|
|
65
|
+
|
|
66
|
+
def extend(self, x: Union[str, Iterable[int]]) -> None: ...
|
|
67
|
+
def fill(self, m: int = ...) -> int: ...
|
|
68
|
+
def find(self,
|
|
69
|
+
sub_bitarray: Union[bitarray, int],
|
|
70
|
+
start: int = ...,
|
|
71
|
+
stop: int = ...,
|
|
72
|
+
right: int = ...) -> int: ...
|
|
73
|
+
|
|
74
|
+
def frombytes(self, a: BytesLike) -> None: ...
|
|
75
|
+
def fromfile(self, f: BinaryIO, n: int = ...) -> None: ...
|
|
76
|
+
def index(self,
|
|
77
|
+
sub_bitarray: Union[bitarray, int],
|
|
78
|
+
start: int = ...,
|
|
79
|
+
stop: int = ...,
|
|
80
|
+
right: int = ...) -> int: ...
|
|
81
|
+
|
|
82
|
+
def insert(self, i: int, value: int) -> None: ...
|
|
83
|
+
def invert(self, i: int = ...) -> None: ...
|
|
84
|
+
|
|
85
|
+
def search(self,
|
|
86
|
+
sub_bitarray: Union[bitarray, int],
|
|
87
|
+
start: int = ...,
|
|
88
|
+
stop: int = ...,
|
|
89
|
+
right: int = ...) -> Iterator[int]: ...
|
|
90
|
+
|
|
91
|
+
def pack(self, b: BytesLike) -> None: ...
|
|
92
|
+
def pop(self, i: int = ...) -> int: ...
|
|
93
|
+
def remove(self, value: int) -> None: ...
|
|
94
|
+
def rotate(self, k: int = ...) -> None: ...
|
|
95
|
+
def reverse(self) -> None: ...
|
|
96
|
+
|
|
97
|
+
def setall(self, value: int) -> None: ...
|
|
98
|
+
def sort(self, reverse: int) -> None: ...
|
|
99
|
+
def to01(self,
|
|
100
|
+
group: int = ...,
|
|
101
|
+
sep: str = ...) -> str: ...
|
|
102
|
+
def tobytes(self) -> bytes: ...
|
|
103
|
+
def tofile(self, f: BinaryIO) -> None: ...
|
|
104
|
+
def tolist(self) -> list[int]: ...
|
|
105
|
+
def unpack(self,
|
|
106
|
+
zero: bytes = ...,
|
|
107
|
+
one: bytes = ...) -> bytes: ...
|
|
108
|
+
|
|
109
|
+
def __len__(self) -> int: ...
|
|
110
|
+
def __iter__(self) -> Iterator[int]: ...
|
|
111
|
+
@overload
|
|
112
|
+
def __getitem__(self, i: int) -> int: ...
|
|
113
|
+
@overload
|
|
114
|
+
def __getitem__(self,
|
|
115
|
+
s: Union[slice, bitarray, Sequence]) -> bitarray: ...
|
|
116
|
+
@overload
|
|
117
|
+
def __setitem__(self,
|
|
118
|
+
i: Union[int, slice, Sequence],
|
|
119
|
+
o: int) -> None: ...
|
|
120
|
+
@overload
|
|
121
|
+
def __setitem__(self,
|
|
122
|
+
s: Union[slice, bitarray, Sequence],
|
|
123
|
+
o: bitarray) -> None: ...
|
|
124
|
+
def __delitem__(self,
|
|
125
|
+
i: Union[int, slice, bitarray, Sequence]) -> None: ...
|
|
126
|
+
|
|
127
|
+
def __buffer__(self, flags: int, /) -> memoryview: ...
|
|
128
|
+
def __release_buffer__(self, buffer: memoryview, /) -> None: ...
|
|
129
|
+
|
|
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: ...
|
|
135
|
+
|
|
136
|
+
def __ge__(self, other: bitarray) -> bool: ...
|
|
137
|
+
def __gt__(self, other: bitarray) -> bool: ...
|
|
138
|
+
def __le__(self, other: bitarray) -> bool: ...
|
|
139
|
+
def __lt__(self, other: bitarray) -> bool: ...
|
|
140
|
+
|
|
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: ...
|
|
152
|
+
|
|
153
|
+
# data descriptors
|
|
154
|
+
@property
|
|
155
|
+
def endian(self) -> str: ...
|
|
156
|
+
@property
|
|
157
|
+
def nbytes(self) -> int: ...
|
|
158
|
+
@property
|
|
159
|
+
def padbits(self) -> int: ...
|
|
160
|
+
@property
|
|
161
|
+
def readonly(self) -> bool: ...
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class frozenbitarray(bitarray):
|
|
165
|
+
def __hash__(self) -> int: ...
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
__version__: str
|
|
169
|
+
def bits2bytes(n: int) -> int: ...
|
|
170
|
+
def get_default_endian() -> str: ...
|
|
171
|
+
def test(verbosity: int = ...) -> TextTestResult: ...
|
|
172
|
+
def _bitarray_reconstructor(cls: type,
|
|
173
|
+
buffer: bytes,
|
|
174
|
+
endian: str,
|
|
175
|
+
padbits: int,
|
|
176
|
+
readonly: int) -> bitarray: ...
|
|
Binary file
|
|
Binary file
|
bitarray/bitarray.h
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2008 - 2026, Ilan Schnell; All Rights Reserved
|
|
3
|
+
bitarray is published under the PSF license.
|
|
4
|
+
|
|
5
|
+
Author: Ilan Schnell
|
|
6
|
+
*/
|
|
7
|
+
#define BITARRAY_VERSION "3.12.2"
|
|
8
|
+
|
|
9
|
+
#ifdef STDC_HEADERS
|
|
10
|
+
# include <stddef.h>
|
|
11
|
+
#else
|
|
12
|
+
# ifdef HAVE_SYS_TYPES_H
|
|
13
|
+
# include <sys/types.h> /* For size_t */
|
|
14
|
+
# endif
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
/* Compatibility with Visual Studio 2013 and older which don't support
|
|
18
|
+
the inline keyword in C (only in C++): use __inline instead.
|
|
19
|
+
(copied from pythoncapi_compat.h) */
|
|
20
|
+
#if (defined(_MSC_VER) && _MSC_VER < 1900 \
|
|
21
|
+
&& !defined(__cplusplus) && !defined(inline))
|
|
22
|
+
#define inline __inline
|
|
23
|
+
#endif
|
|
24
|
+
|
|
25
|
+
#ifdef _MSC_VER
|
|
26
|
+
#include <intrin.h> /* For _byteswap_uint64() */
|
|
27
|
+
#endif
|
|
28
|
+
|
|
29
|
+
/* --- bitarrayobject --- */
|
|
30
|
+
|
|
31
|
+
/* .ob_size is the buffer size (in bytes), not the number of elements.
|
|
32
|
+
The number of elements (bits) is .nbits. */
|
|
33
|
+
typedef struct {
|
|
34
|
+
PyObject_VAR_HEAD
|
|
35
|
+
char *ob_item; /* buffer */
|
|
36
|
+
Py_ssize_t allocated; /* allocated buffer size (in bytes) */
|
|
37
|
+
Py_ssize_t nbits; /* length of bitarray, i.e. elements */
|
|
38
|
+
int endian; /* bit-endianness of bitarray */
|
|
39
|
+
int ob_exports; /* how many buffer exports */
|
|
40
|
+
PyObject *weakreflist; /* list of weak references */
|
|
41
|
+
Py_buffer *buffer; /* used when importing a buffer */
|
|
42
|
+
int readonly; /* buffer is readonly */
|
|
43
|
+
} bitarrayobject;
|
|
44
|
+
|
|
45
|
+
/* --- bit-endianness --- */
|
|
46
|
+
#define ENDIAN_LITTLE 0
|
|
47
|
+
#define ENDIAN_BIG 1
|
|
48
|
+
/* default bit-endianness */
|
|
49
|
+
#define ENDIAN_DEFAULT ENDIAN_BIG
|
|
50
|
+
|
|
51
|
+
#define IS_LE(self) ((self)->endian == ENDIAN_LITTLE)
|
|
52
|
+
#define IS_BE(self) ((self)->endian == ENDIAN_BIG)
|
|
53
|
+
|
|
54
|
+
/* endianness as string */
|
|
55
|
+
#define ENDIAN_STR(endian) ((endian) == ENDIAN_LITTLE ? "little" : "big")
|
|
56
|
+
|
|
57
|
+
/* number of pad bits */
|
|
58
|
+
#define PADBITS(self) ((8 - (self)->nbits % 8) % 8)
|
|
59
|
+
|
|
60
|
+
/* number of bytes necessary to store given number of bits */
|
|
61
|
+
#define BYTES(bits) (((size_t) (bits) + 7) >> 3)
|
|
62
|
+
|
|
63
|
+
/* we're not using bitmask_table here, as it is actually slower */
|
|
64
|
+
#define BITMASK(self, i) (((char) 1) << ((self)->endian == ENDIAN_LITTLE ? \
|
|
65
|
+
((i) % 8) : (7 - (i) % 8)))
|
|
66
|
+
|
|
67
|
+
/* buffer as uint64 array */
|
|
68
|
+
#define WBUFF(self) ((uint64_t *) (self)->ob_item)
|
|
69
|
+
|
|
70
|
+
/* assert that .nbits is in agreement with .ob_size */
|
|
71
|
+
#define assert_nbits(self) assert(BYTES((self)->nbits) == Py_SIZE(self))
|
|
72
|
+
|
|
73
|
+
/* ------------ low level access to bits in bitarrayobject ------------- */
|
|
74
|
+
|
|
75
|
+
static inline int
|
|
76
|
+
getbit(bitarrayobject *self, Py_ssize_t i)
|
|
77
|
+
{
|
|
78
|
+
assert_nbits(self);
|
|
79
|
+
assert(0 <= i && i < self->nbits);
|
|
80
|
+
return self->ob_item[i >> 3] & BITMASK(self, i) ? 1 : 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static inline void
|
|
84
|
+
setbit(bitarrayobject *self, Py_ssize_t i, int vi)
|
|
85
|
+
{
|
|
86
|
+
char *cp, mask;
|
|
87
|
+
|
|
88
|
+
assert_nbits(self);
|
|
89
|
+
assert(0 <= i && i < self->nbits);
|
|
90
|
+
assert(self->readonly == 0);
|
|
91
|
+
|
|
92
|
+
mask = BITMASK(self, i);
|
|
93
|
+
cp = self->ob_item + (i >> 3);
|
|
94
|
+
if (vi)
|
|
95
|
+
*cp |= mask;
|
|
96
|
+
else
|
|
97
|
+
*cp &= ~mask;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static const char bitmask_table[2][8] = {
|
|
101
|
+
{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* little endian */
|
|
102
|
+
{0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* big endian */
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/* character with n leading ones is: ones_table[endian][n] */
|
|
106
|
+
static const char ones_table[2][8] = {
|
|
107
|
+
{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}, /* little endian */
|
|
108
|
+
{0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}, /* big endian */
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/* Return last byte in buffer with pad bits zeroed out.
|
|
112
|
+
If the length of the bitarray is a multiple of 8 (which includes an empty
|
|
113
|
+
bitarray), 0 is returned. */
|
|
114
|
+
static inline char
|
|
115
|
+
zlc(bitarrayobject *self) /* zlc = zeroed last char */
|
|
116
|
+
{
|
|
117
|
+
const int r = self->nbits % 8; /* index into mask table */
|
|
118
|
+
|
|
119
|
+
if (r == 0)
|
|
120
|
+
return 0;
|
|
121
|
+
return self->ob_item[Py_SIZE(self) - 1] & ones_table[IS_BE(self)][r];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Return a uint64_t word representing the last (up to 63) remaining bits
|
|
125
|
+
of the buffer. All missing bytes (to complete the word) and padbits are
|
|
126
|
+
treated as zeros.
|
|
127
|
+
If the length of the bitarray is a multiple of 64 (which also includes
|
|
128
|
+
an empty bitarray), 0 is returned. */
|
|
129
|
+
static inline uint64_t
|
|
130
|
+
zlw(bitarrayobject *self) /* zlw = zeroed last word */
|
|
131
|
+
{
|
|
132
|
+
const size_t nbits = self->nbits;
|
|
133
|
+
const size_t nw = (nbits / 64) * 8; /* bytes in complete words */
|
|
134
|
+
const size_t nr = (nbits % 64) / 8; /* complete remaining bytes */
|
|
135
|
+
uint64_t res = 0;
|
|
136
|
+
|
|
137
|
+
assert(nw + nr == nbits / 8 && 8 * (nw + nr) + nbits % 8 == nbits);
|
|
138
|
+
if (nr)
|
|
139
|
+
memcpy((char *) &res, self->ob_item + nw, nr);
|
|
140
|
+
if (nbits % 8)
|
|
141
|
+
*(((char *) &res) + nr) = zlc(self);
|
|
142
|
+
|
|
143
|
+
return res;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* unless buffer is readonly, zero out pad bits - self->nbits is unchanged */
|
|
147
|
+
static inline void
|
|
148
|
+
set_padbits(bitarrayobject *self)
|
|
149
|
+
{
|
|
150
|
+
if (self->readonly == 0) {
|
|
151
|
+
int r = self->nbits % 8; /* index into mask table */
|
|
152
|
+
if (r)
|
|
153
|
+
self->ob_item[Py_SIZE(self) - 1] &= ones_table[IS_BE(self)][r];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* population count - number of 1's in uint64 */
|
|
158
|
+
static inline int
|
|
159
|
+
popcnt_64(uint64_t x)
|
|
160
|
+
{
|
|
161
|
+
#if (defined(__clang__) || defined(__GNUC__))
|
|
162
|
+
return __builtin_popcountll(x);
|
|
163
|
+
#else
|
|
164
|
+
/* https://en.wikipedia.org/wiki/Hamming_weight popcount64c */
|
|
165
|
+
const uint64_t m1 = 0x5555555555555555;
|
|
166
|
+
const uint64_t m2 = 0x3333333333333333;
|
|
167
|
+
const uint64_t m4 = 0x0f0f0f0f0f0f0f0f;
|
|
168
|
+
const uint64_t h01 = 0x0101010101010101;
|
|
169
|
+
|
|
170
|
+
x -= (x >> 1) & m1;
|
|
171
|
+
x = (x & m2) + ((x >> 2) & m2);
|
|
172
|
+
x = (x + (x >> 4)) & m4;
|
|
173
|
+
return (x * h01) >> 56;
|
|
174
|
+
#endif
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
static inline int
|
|
178
|
+
parity_64(uint64_t x)
|
|
179
|
+
{
|
|
180
|
+
#if (defined(__clang__) || defined(__GNUC__))
|
|
181
|
+
return __builtin_parityll(x);
|
|
182
|
+
#else
|
|
183
|
+
int i;
|
|
184
|
+
for (i = 32; i > 0; i /= 2)
|
|
185
|
+
x ^= x >> i;
|
|
186
|
+
return x & 1;
|
|
187
|
+
#endif
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
static inline uint64_t
|
|
191
|
+
builtin_bswap64(uint64_t word)
|
|
192
|
+
{
|
|
193
|
+
#if (defined(__clang__) || \
|
|
194
|
+
(defined(__GNUC__) \
|
|
195
|
+
&& ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))))
|
|
196
|
+
/* __builtin_bswap64() is available since GCC 4.3 */
|
|
197
|
+
# define HAVE_BUILTIN_BSWAP64 1
|
|
198
|
+
return __builtin_bswap64(word);
|
|
199
|
+
#elif defined(_MSC_VER)
|
|
200
|
+
# define HAVE_BUILTIN_BSWAP64 1
|
|
201
|
+
return _byteswap_uint64(word);
|
|
202
|
+
#else
|
|
203
|
+
# define HAVE_BUILTIN_BSWAP64 0
|
|
204
|
+
Py_UNREACHABLE();
|
|
205
|
+
#endif
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* reverse order of first n bytes of p */
|
|
209
|
+
static inline void
|
|
210
|
+
swap_bytes(char *p, Py_ssize_t n)
|
|
211
|
+
{
|
|
212
|
+
Py_ssize_t i, j;
|
|
213
|
+
for (i = 0, j = n - 1; i < j; i++, j--) {
|
|
214
|
+
char t = p[i];
|
|
215
|
+
p[i] = p[j];
|
|
216
|
+
p[j] = t;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* write 256 characters into table for given kernel operation */
|
|
221
|
+
static inline void
|
|
222
|
+
setup_table(char *table, char kop)
|
|
223
|
+
{
|
|
224
|
+
int k;
|
|
225
|
+
for (k = 0; k < 256; k++) {
|
|
226
|
+
char t = 0, j;
|
|
227
|
+
for (j = 0; j < 8; j++) {
|
|
228
|
+
if (k & 1 << j) {
|
|
229
|
+
/* j are the indices of active bits in k (little endian) */
|
|
230
|
+
switch (kop) {
|
|
231
|
+
case 'a': t += j; break; /* add active indices */
|
|
232
|
+
case 'A': t += 7 - j; break; /* 'a' for big endian */
|
|
233
|
+
case 's': t += j * j; /* add squares of active indices */
|
|
234
|
+
break;
|
|
235
|
+
case 'S': t += (7-j) * (7-j); /* 's' for big endian */
|
|
236
|
+
break;
|
|
237
|
+
case 'x': t ^= j; break; /* xor active indices */
|
|
238
|
+
case 'X': t ^= 7 - j; break; /* 'x' for big endian */
|
|
239
|
+
case 'c': t++; break; /* bit count */
|
|
240
|
+
case 'p': t ^= 1; break; /* parity */
|
|
241
|
+
case 'r': t |= 128 >> j; break; /* reverse bits */
|
|
242
|
+
default: Py_UNREACHABLE();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
table[k] = t;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* Return distance [0..7] to next aligned pointer.
|
|
251
|
+
While on modern compilers uint64_t pointers may be misaligned, it may
|
|
252
|
+
cause problems on older ones. Moreover, it may lead to slowdown (even
|
|
253
|
+
on modern compilers). */
|
|
254
|
+
static inline int
|
|
255
|
+
to_aligned(void *p)
|
|
256
|
+
{
|
|
257
|
+
int r = ((uintptr_t) p) % 8;
|
|
258
|
+
return (8 - r) % 8;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* population count of n words starting at uint64_t pointer w */
|
|
262
|
+
static inline Py_ssize_t
|
|
263
|
+
popcnt_words(uint64_t *w, Py_ssize_t n)
|
|
264
|
+
{
|
|
265
|
+
Py_ssize_t cnt = 0;
|
|
266
|
+
|
|
267
|
+
assert(n >= 0);
|
|
268
|
+
assert(n == 0 || ((uintptr_t) w) % 8 == 0);
|
|
269
|
+
while (n--)
|
|
270
|
+
cnt += popcnt_64(*w++);
|
|
271
|
+
return cnt;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Adjust slice indices to length and make step positive.
|
|
275
|
+
A positive step will produce simpler loops over items when their
|
|
276
|
+
order is irrelevant. Also, for example, for step = -1, we can now
|
|
277
|
+
use set_span() in set_range().
|
|
278
|
+
*/
|
|
279
|
+
static inline Py_ssize_t
|
|
280
|
+
adjust_slice(Py_ssize_t length,
|
|
281
|
+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
|
|
282
|
+
{
|
|
283
|
+
Py_ssize_t slicelength;
|
|
284
|
+
|
|
285
|
+
assert(*step != 0 && length >= 0);
|
|
286
|
+
|
|
287
|
+
slicelength = PySlice_AdjustIndices(length, start, stop, *step);
|
|
288
|
+
|
|
289
|
+
if (*step < 0) { /* make step positive */
|
|
290
|
+
*stop = *start + 1;
|
|
291
|
+
*start = *stop + *step * (slicelength - 1) - 1;
|
|
292
|
+
*step = -(*step);
|
|
293
|
+
}
|
|
294
|
+
#ifndef NDEBUG
|
|
295
|
+
assert(*start >= 0 && *stop >= 0 && *step > 0 && slicelength >= 0);
|
|
296
|
+
assert((slicelength == 0) == (*stop <= *start));
|
|
297
|
+
if (slicelength) {
|
|
298
|
+
assert(*start <= length && *stop <= length);
|
|
299
|
+
if (*step == 1)
|
|
300
|
+
assert(*stop - *start == slicelength);
|
|
301
|
+
}
|
|
302
|
+
#endif
|
|
303
|
+
|
|
304
|
+
return slicelength;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/* convert Python object to C int at address *vi -
|
|
308
|
+
return 1 on success, 0 on failure (and set exception) */
|
|
309
|
+
static inline int
|
|
310
|
+
conv_pybit(PyObject *value, int *vi)
|
|
311
|
+
{
|
|
312
|
+
Py_ssize_t n;
|
|
313
|
+
|
|
314
|
+
n = PyNumber_AsSsize_t(value, NULL);
|
|
315
|
+
if (n == -1 && PyErr_Occurred())
|
|
316
|
+
return 0;
|
|
317
|
+
|
|
318
|
+
if (n < 0 || n > 1) {
|
|
319
|
+
PyErr_Format(PyExc_ValueError, "bit must be 0 or 1, got %zd", n);
|
|
320
|
+
return 0;
|
|
321
|
+
}
|
|
322
|
+
*vi = (int) n;
|
|
323
|
+
return 1;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* Return 0 if bitarrays have equal length and bit-endianness.
|
|
327
|
+
Otherwise, set exception and return -1. */
|
|
328
|
+
static inline int
|
|
329
|
+
ensure_eq_size_endian(bitarrayobject *a, bitarrayobject *b)
|
|
330
|
+
{
|
|
331
|
+
if (a->nbits != b->nbits) {
|
|
332
|
+
PyErr_SetString(PyExc_ValueError,
|
|
333
|
+
"bitarrays of equal length expected");
|
|
334
|
+
return -1;
|
|
335
|
+
}
|
|
336
|
+
if (a->endian != b->endian) {
|
|
337
|
+
PyErr_SetString(PyExc_ValueError,
|
|
338
|
+
"bitarrays of equal bit-endianness expected");
|
|
339
|
+
return -1;
|
|
340
|
+
}
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/* Equivalent to: import bitarray; return getattr(bitarray, name) */
|
|
345
|
+
static inline PyObject *
|
|
346
|
+
bitarray_module_attr(char *name)
|
|
347
|
+
{
|
|
348
|
+
PyObject *bitarray_module, *result;
|
|
349
|
+
|
|
350
|
+
bitarray_module = PyImport_ImportModule("bitarray");
|
|
351
|
+
if (bitarray_module == NULL)
|
|
352
|
+
return NULL;
|
|
353
|
+
|
|
354
|
+
result = PyObject_GetAttrString(bitarray_module, name);
|
|
355
|
+
Py_DECREF(bitarray_module);
|
|
356
|
+
return result;
|
|
357
|
+
}
|