bitarray 3.6.0__tar.gz → 3.6.1__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.
- {bitarray-3.6.0 → bitarray-3.6.1}/PKG-INFO +5 -12
- {bitarray-3.6.0 → bitarray-3.6.1}/README.rst +4 -11
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/_bitarray.c +0 -45
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/_util.c +76 -63
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/bitarray.h +16 -8
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/test_util.py +123 -70
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/util.py +51 -4
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray.egg-info/PKG-INFO +5 -12
- {bitarray-3.6.0 → bitarray-3.6.1}/LICENSE +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/__init__.py +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/__init__.pyi +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/py.typed +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/pythoncapi_compat.h +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/test_281.pickle +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/test_bitarray.py +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray/util.pyi +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray.egg-info/SOURCES.txt +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray.egg-info/dependency_links.txt +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray.egg-info/not-zip-safe +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/bitarray.egg-info/top_level.txt +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/pyproject.toml +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/setup.cfg +0 -0
- {bitarray-3.6.0 → bitarray-3.6.1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bitarray
|
|
3
|
-
Version: 3.6.
|
|
3
|
+
Version: 3.6.1
|
|
4
4
|
Summary: efficient arrays of booleans -- C extension
|
|
5
5
|
Home-page: https://github.com/ilanschnell/bitarray
|
|
6
6
|
Author: Ilan Schnell
|
|
@@ -83,20 +83,13 @@ versions. Which means you can simply:
|
|
|
83
83
|
|
|
84
84
|
$ pip install bitarray
|
|
85
85
|
|
|
86
|
-
In addition, conda packages are available (both the default Anaconda
|
|
87
|
-
repository as well as conda-forge support bitarray):
|
|
88
|
-
|
|
89
|
-
.. code-block:: shell-session
|
|
90
|
-
|
|
91
|
-
$ conda install bitarray
|
|
92
|
-
|
|
93
86
|
Once you have installed the package, you may want to test it:
|
|
94
87
|
|
|
95
88
|
.. code-block:: shell-session
|
|
96
89
|
|
|
97
90
|
$ python -c 'import bitarray; bitarray.test()'
|
|
98
91
|
bitarray is installed in: /Users/ilan/bitarray/bitarray
|
|
99
|
-
bitarray version: 3.6.
|
|
92
|
+
bitarray version: 3.6.1
|
|
100
93
|
sys.version: 3.13.5 (main, Jun 16 2025) [Clang 18.1.8]
|
|
101
94
|
sys.prefix: /Users/ilan/miniforge
|
|
102
95
|
pointer size: 64 bit
|
|
@@ -110,7 +103,7 @@ Once you have installed the package, you may want to test it:
|
|
|
110
103
|
.........................................................................
|
|
111
104
|
................................................................
|
|
112
105
|
----------------------------------------------------------------------
|
|
113
|
-
Ran
|
|
106
|
+
Ran 591 tests in 0.163s
|
|
114
107
|
|
|
115
108
|
OK
|
|
116
109
|
|
|
@@ -427,7 +420,7 @@ and can therefore be used as a dictionary key:
|
|
|
427
420
|
Reference
|
|
428
421
|
=========
|
|
429
422
|
|
|
430
|
-
bitarray version: 3.6.
|
|
423
|
+
bitarray version: 3.6.1 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
|
|
431
424
|
|
|
432
425
|
In the following, ``item`` and ``value`` are usually a single bit -
|
|
433
426
|
an integer 0 or 1.
|
|
@@ -1003,7 +996,7 @@ This sub-module was added in version 1.2.
|
|
|
1003
996
|
|
|
1004
997
|
``sum_indices(a, /)`` -> int
|
|
1005
998
|
Return sum of indices of all active bits in bitarray ``a``.
|
|
1006
|
-
|
|
999
|
+
Equivalent to ``sum(i for i, v in enumerate(a) if v)``.
|
|
1007
1000
|
|
|
1008
1001
|
New in version 3.6
|
|
1009
1002
|
|
|
@@ -51,20 +51,13 @@ versions. Which means you can simply:
|
|
|
51
51
|
|
|
52
52
|
$ pip install bitarray
|
|
53
53
|
|
|
54
|
-
In addition, conda packages are available (both the default Anaconda
|
|
55
|
-
repository as well as conda-forge support bitarray):
|
|
56
|
-
|
|
57
|
-
.. code-block:: shell-session
|
|
58
|
-
|
|
59
|
-
$ conda install bitarray
|
|
60
|
-
|
|
61
54
|
Once you have installed the package, you may want to test it:
|
|
62
55
|
|
|
63
56
|
.. code-block:: shell-session
|
|
64
57
|
|
|
65
58
|
$ python -c 'import bitarray; bitarray.test()'
|
|
66
59
|
bitarray is installed in: /Users/ilan/bitarray/bitarray
|
|
67
|
-
bitarray version: 3.6.
|
|
60
|
+
bitarray version: 3.6.1
|
|
68
61
|
sys.version: 3.13.5 (main, Jun 16 2025) [Clang 18.1.8]
|
|
69
62
|
sys.prefix: /Users/ilan/miniforge
|
|
70
63
|
pointer size: 64 bit
|
|
@@ -78,7 +71,7 @@ Once you have installed the package, you may want to test it:
|
|
|
78
71
|
.........................................................................
|
|
79
72
|
................................................................
|
|
80
73
|
----------------------------------------------------------------------
|
|
81
|
-
Ran
|
|
74
|
+
Ran 591 tests in 0.163s
|
|
82
75
|
|
|
83
76
|
OK
|
|
84
77
|
|
|
@@ -395,7 +388,7 @@ and can therefore be used as a dictionary key:
|
|
|
395
388
|
Reference
|
|
396
389
|
=========
|
|
397
390
|
|
|
398
|
-
bitarray version: 3.6.
|
|
391
|
+
bitarray version: 3.6.1 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
|
|
399
392
|
|
|
400
393
|
In the following, ``item`` and ``value`` are usually a single bit -
|
|
401
394
|
an integer 0 or 1.
|
|
@@ -971,7 +964,7 @@ This sub-module was added in version 1.2.
|
|
|
971
964
|
|
|
972
965
|
``sum_indices(a, /)`` -> int
|
|
973
966
|
Return sum of indices of all active bits in bitarray ``a``.
|
|
974
|
-
|
|
967
|
+
Equivalent to ``sum(i for i, v in enumerate(a) if v)``.
|
|
975
968
|
|
|
976
969
|
New in version 3.6
|
|
977
970
|
|
|
@@ -4195,44 +4195,6 @@ Return tuple containing:\n\
|
|
|
4195
4195
|
7. PY_LITTLE_ENDIAN\n\
|
|
4196
4196
|
8. PY_BIG_ENDIAN");
|
|
4197
4197
|
|
|
4198
|
-
/* ---------- module functions exposed in debug mode for testing ------- */
|
|
4199
|
-
|
|
4200
|
-
#ifndef NDEBUG
|
|
4201
|
-
|
|
4202
|
-
static PyObject *
|
|
4203
|
-
module_setup_table(PyObject *module, PyObject *obj)
|
|
4204
|
-
{
|
|
4205
|
-
char table[256];
|
|
4206
|
-
Py_UCS4 ch;
|
|
4207
|
-
|
|
4208
|
-
assert(PyUnicode_Check(obj));
|
|
4209
|
-
assert(PyUnicode_GET_LENGTH(obj) == 1);
|
|
4210
|
-
ch = PyUnicode_READ_CHAR(obj, 0);
|
|
4211
|
-
|
|
4212
|
-
setup_table(table, ch);
|
|
4213
|
-
return PyBytes_FromStringAndSize(table, 256);
|
|
4214
|
-
}
|
|
4215
|
-
|
|
4216
|
-
/* Return zlw(a) as a new bitarray, rather than an int object.
|
|
4217
|
-
This makes testing easier, because the int result would depend
|
|
4218
|
-
on the machine byteorder. */
|
|
4219
|
-
static PyObject *
|
|
4220
|
-
module_zlw(PyObject *module, PyObject *obj)
|
|
4221
|
-
{
|
|
4222
|
-
bitarrayobject *a, *res;
|
|
4223
|
-
uint64_t w;
|
|
4224
|
-
|
|
4225
|
-
assert(bitarray_Check(obj));
|
|
4226
|
-
a = (bitarrayobject *) obj;
|
|
4227
|
-
w = zlw(a);
|
|
4228
|
-
if ((res = newbitarrayobject(&Bitarray_Type, 64, a->endian)) == NULL)
|
|
4229
|
-
return NULL;
|
|
4230
|
-
memcpy(res->ob_item, &w, 8);
|
|
4231
|
-
return (PyObject *) res;
|
|
4232
|
-
}
|
|
4233
|
-
|
|
4234
|
-
#endif /* NDEBUG */
|
|
4235
|
-
|
|
4236
4198
|
|
|
4237
4199
|
static PyMethodDef module_functions[] = {
|
|
4238
4200
|
{"bits2bytes", (PyCFunction) bits2bytes, METH_O,
|
|
@@ -4246,13 +4208,6 @@ static PyMethodDef module_functions[] = {
|
|
|
4246
4208
|
set_default_endian_doc},
|
|
4247
4209
|
{"_sysinfo", (PyCFunction) sysinfo, METH_NOARGS,
|
|
4248
4210
|
sysinfo_doc},
|
|
4249
|
-
|
|
4250
|
-
#ifndef NDEBUG
|
|
4251
|
-
/* functions exposed in debug mode for testing */
|
|
4252
|
-
{"_setup_table", (PyCFunction) module_setup_table, METH_O, 0},
|
|
4253
|
-
{"_zlw", (PyCFunction) module_zlw, METH_O, 0},
|
|
4254
|
-
#endif
|
|
4255
|
-
|
|
4256
4211
|
{NULL, NULL} /* sentinel */
|
|
4257
4212
|
};
|
|
4258
4213
|
|
|
@@ -265,71 +265,58 @@ Return parity of bitarray `a`.\n\
|
|
|
265
265
|
`parity(a)` is equivalent to `a.count() % 2` but more efficient.");
|
|
266
266
|
|
|
267
267
|
|
|
268
|
+
/* Internal functions, like sum_indices(), but bitarrays are limited in
|
|
269
|
+
size. For details see: devel/test_sum_indices.py
|
|
270
|
+
*/
|
|
268
271
|
static PyObject *
|
|
269
|
-
|
|
270
|
-
{
|
|
271
|
-
PyObject *res, *tmp = PyLong_FromUnsignedLongLong(i);
|
|
272
|
-
|
|
273
|
-
res = PyNumber_Add(number, tmp);
|
|
274
|
-
Py_DECREF(tmp);
|
|
275
|
-
Py_DECREF(number);
|
|
276
|
-
return res;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
static PyObject *
|
|
280
|
-
sum_indices(PyObject *module, PyObject *obj)
|
|
272
|
+
ssqi(PyObject *module, PyObject *args)
|
|
281
273
|
{
|
|
282
|
-
static char
|
|
283
|
-
static int setup = -1; /* endianness of
|
|
284
|
-
PyObject *res;
|
|
274
|
+
static char count_table[256], sum_table[256], sum_sqr_table[256];
|
|
275
|
+
static int setup = -1; /* endianness of tables */
|
|
285
276
|
bitarrayobject *a;
|
|
286
|
-
|
|
277
|
+
uint64_t nbytes, i;
|
|
287
278
|
uint64_t sm = 0; /* accumulated sum */
|
|
279
|
+
int mode = 1;
|
|
288
280
|
|
|
289
|
-
if (
|
|
281
|
+
if (!PyArg_ParseTuple(args, "O!|i", bitarray_type,
|
|
282
|
+
(PyObject *) &a, &mode))
|
|
290
283
|
return NULL;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
a
|
|
294
|
-
|
|
295
|
-
set_padbits(a);
|
|
284
|
+
if (mode < 1 || mode > 2)
|
|
285
|
+
return PyErr_Format(PyExc_ValueError, "unexpected mode %d", mode);
|
|
286
|
+
if (((uint64_t) a->nbits) > (mode == 1 ? 6074001000LLU : 3810778LLU))
|
|
287
|
+
return PyErr_Format(PyExc_OverflowError, "ssqi %zd", a->nbits);
|
|
296
288
|
|
|
297
289
|
if (setup != a->endian) {
|
|
298
|
-
setup_table(
|
|
290
|
+
setup_table(count_table, 'c');
|
|
291
|
+
setup_table(sum_table, IS_LE(a) ? 'a' : 'A');
|
|
292
|
+
setup_table(sum_sqr_table, IS_LE(a) ? 's' : 'S');
|
|
299
293
|
setup = a->endian;
|
|
300
294
|
}
|
|
301
295
|
|
|
296
|
+
nbytes = Py_SIZE(a);
|
|
297
|
+
set_padbits(a);
|
|
302
298
|
for (i = 0; i < nbytes; i++) {
|
|
303
299
|
unsigned char c = a->ob_item[i];
|
|
304
|
-
if (
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if ((res = add_uint64(res, sm)) == NULL)
|
|
314
|
-
return NULL;
|
|
315
|
-
sm = 0;
|
|
300
|
+
if (c) {
|
|
301
|
+
uint64_t k = count_table[c], z1 = sum_table[c];
|
|
302
|
+
if (mode == 1) {
|
|
303
|
+
sm += k * 8LLU * i + z1;
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
uint64_t z2 = (unsigned char) sum_sqr_table[c];
|
|
307
|
+
sm += (k * 64LLU * i + 16LLU * z1) * i + z2;
|
|
308
|
+
}
|
|
316
309
|
}
|
|
317
310
|
}
|
|
318
|
-
return
|
|
311
|
+
return PyLong_FromUnsignedLongLong(sm);
|
|
319
312
|
}
|
|
320
313
|
|
|
321
|
-
PyDoc_STRVAR(sum_indices_doc,
|
|
322
|
-
"sum_indices(a, /) -> int\n\
|
|
323
|
-
\n\
|
|
324
|
-
Return sum of indices of all active bits in bitarray `a`.\n\
|
|
325
|
-
This is equivalent to `sum(i for i, v in enumerate(a) if v)`.");
|
|
326
|
-
|
|
327
314
|
|
|
328
315
|
static PyObject *
|
|
329
316
|
xor_indices(PyObject *module, PyObject *obj)
|
|
330
317
|
{
|
|
331
|
-
static char
|
|
332
|
-
static int setup = -1; /* endianness of
|
|
318
|
+
static char parity_table[256], xor_table[256];
|
|
319
|
+
static int setup = -1; /* endianness of xor_table */
|
|
333
320
|
bitarrayobject *a;
|
|
334
321
|
Py_ssize_t res = 0, nbytes, i;
|
|
335
322
|
|
|
@@ -341,15 +328,16 @@ xor_indices(PyObject *module, PyObject *obj)
|
|
|
341
328
|
set_padbits(a);
|
|
342
329
|
|
|
343
330
|
if (setup != a->endian) {
|
|
344
|
-
setup_table(
|
|
331
|
+
setup_table(xor_table, IS_LE(a) ? 'x' : 'X');
|
|
332
|
+
setup_table(parity_table, 'p');
|
|
345
333
|
setup = a->endian;
|
|
346
334
|
}
|
|
347
335
|
|
|
348
336
|
for (i = 0; i < nbytes; i++) {
|
|
349
337
|
unsigned char c = a->ob_item[i];
|
|
350
|
-
if (
|
|
338
|
+
if (parity_table[c])
|
|
351
339
|
res ^= i << 3;
|
|
352
|
-
res ^=
|
|
340
|
+
res ^= xor_table[c];
|
|
353
341
|
}
|
|
354
342
|
return PyLong_FromSsize_t(res);
|
|
355
343
|
}
|
|
@@ -2103,14 +2091,43 @@ static PyTypeObject CHDI_Type = {
|
|
|
2103
2091
|
|
|
2104
2092
|
#ifndef NDEBUG
|
|
2105
2093
|
|
|
2094
|
+
static PyObject *
|
|
2095
|
+
module_setup_table(PyObject *module, PyObject *obj)
|
|
2096
|
+
{
|
|
2097
|
+
char table[256];
|
|
2098
|
+
|
|
2099
|
+
assert(PyUnicode_Check(obj));
|
|
2100
|
+
assert(PyUnicode_GET_LENGTH(obj) == 1);
|
|
2101
|
+
setup_table(table, PyUnicode_READ_CHAR(obj, 0));
|
|
2102
|
+
return PyBytes_FromStringAndSize(table, 256);
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
/* Return zlw(a) as a new bitarray, rather than an int object.
|
|
2106
|
+
This makes testing easier, because the int result would depend
|
|
2107
|
+
on the machine byteorder. */
|
|
2108
|
+
static PyObject *
|
|
2109
|
+
module_zlw(PyObject *module, PyObject *obj)
|
|
2110
|
+
{
|
|
2111
|
+
bitarrayobject *a, *res;
|
|
2112
|
+
uint64_t w;
|
|
2113
|
+
|
|
2114
|
+
assert(bitarray_Check(obj));
|
|
2115
|
+
a = (bitarrayobject *) obj;
|
|
2116
|
+
w = zlw(a);
|
|
2117
|
+
if ((res = new_bitarray(64, Py_None, -1)) == NULL)
|
|
2118
|
+
return NULL;
|
|
2119
|
+
res->endian = a->endian;
|
|
2120
|
+
memcpy(res->ob_item, &w, 8);
|
|
2121
|
+
return (PyObject *) res;
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2106
2124
|
static PyObject *
|
|
2107
2125
|
module_cfw(PyObject *module, PyObject *args) /* count_from_word() */
|
|
2108
2126
|
{
|
|
2109
2127
|
bitarrayobject *a;
|
|
2110
2128
|
Py_ssize_t i;
|
|
2111
2129
|
|
|
2112
|
-
if (!PyArg_ParseTuple(args, "O!n",
|
|
2113
|
-
bitarray_type, (PyObject *) &a, &i))
|
|
2130
|
+
if (!PyArg_ParseTuple(args, "O!n", bitarray_type, (PyObject *) &a, &i))
|
|
2114
2131
|
return NULL;
|
|
2115
2132
|
return PyLong_FromSsize_t(count_from_word(a, i));
|
|
2116
2133
|
}
|
|
@@ -2156,12 +2173,8 @@ static PyMethodDef module_functions[] = {
|
|
|
2156
2173
|
METH_VARARGS, ones_doc},
|
|
2157
2174
|
{"count_n", (PyCFunction) count_n, METH_VARARGS, count_n_doc},
|
|
2158
2175
|
{"parity", (PyCFunction) parity, METH_O, parity_doc},
|
|
2159
|
-
{"
|
|
2160
|
-
|
|
2161
|
-
METH_O, sum_indices_doc},
|
|
2162
|
-
{"xor_indices",
|
|
2163
|
-
(PyCFunction) xor_indices,
|
|
2164
|
-
METH_O, xor_indices_doc},
|
|
2176
|
+
{"_ssqi", (PyCFunction) ssqi, METH_VARARGS, 0},
|
|
2177
|
+
{"xor_indices", (PyCFunction) xor_indices, METH_O, xor_indices_doc},
|
|
2165
2178
|
{"count_and", (PyCFunction) count_and, METH_VARARGS, count_and_doc},
|
|
2166
2179
|
{"count_or", (PyCFunction) count_or, METH_VARARGS, count_or_doc},
|
|
2167
2180
|
{"count_xor", (PyCFunction) count_xor, METH_VARARGS, count_xor_doc},
|
|
@@ -2171,10 +2184,8 @@ static PyMethodDef module_functions[] = {
|
|
|
2171
2184
|
(PyCFunction) correspond_all,
|
|
2172
2185
|
METH_VARARGS, correspond_all_doc},
|
|
2173
2186
|
{"byteswap", (PyCFunction) byteswap, METH_VARARGS, byteswap_doc},
|
|
2174
|
-
{"serialize",
|
|
2175
|
-
{"deserialize",
|
|
2176
|
-
(PyCFunction) deserialize,
|
|
2177
|
-
METH_O, deserialize_doc},
|
|
2187
|
+
{"serialize", (PyCFunction) serialize, METH_O, serialize_doc},
|
|
2188
|
+
{"deserialize", (PyCFunction) deserialize, METH_O, deserialize_doc},
|
|
2178
2189
|
{"ba2hex", (PyCFunction) ba2hex, METH_KEYWORDS |
|
|
2179
2190
|
METH_VARARGS, ba2hex_doc},
|
|
2180
2191
|
{"hex2ba", (PyCFunction) hex2ba, METH_KEYWORDS |
|
|
@@ -2193,10 +2204,12 @@ static PyMethodDef module_functions[] = {
|
|
|
2193
2204
|
|
|
2194
2205
|
#ifndef NDEBUG
|
|
2195
2206
|
/* functions exposed in debug mode for testing */
|
|
2196
|
-
{"
|
|
2197
|
-
{"
|
|
2198
|
-
{"
|
|
2199
|
-
{"
|
|
2207
|
+
{"_setup_table", (PyCFunction) module_setup_table, METH_O, 0},
|
|
2208
|
+
{"_zlw", (PyCFunction) module_zlw, METH_O, 0},
|
|
2209
|
+
{"_cfw", (PyCFunction) module_cfw, METH_VARARGS, 0},
|
|
2210
|
+
{"_read_n", (PyCFunction) module_read_n, METH_VARARGS, 0},
|
|
2211
|
+
{"_write_n", (PyCFunction) module_write_n, METH_VARARGS, 0},
|
|
2212
|
+
{"_sc_rts", (PyCFunction) module_sc_rts, METH_O, 0},
|
|
2200
2213
|
#endif
|
|
2201
2214
|
|
|
2202
2215
|
{NULL, NULL} /* sentinel */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Author: Ilan Schnell
|
|
6
6
|
*/
|
|
7
|
-
#define BITARRAY_VERSION "3.6.
|
|
7
|
+
#define BITARRAY_VERSION "3.6.1"
|
|
8
8
|
|
|
9
9
|
#ifdef STDC_HEADERS
|
|
10
10
|
# include <stddef.h>
|
|
@@ -229,20 +229,28 @@ swap_bytes(char *p, Py_ssize_t n)
|
|
|
229
229
|
static inline void
|
|
230
230
|
setup_table(char *table, char kop)
|
|
231
231
|
{
|
|
232
|
-
int
|
|
232
|
+
int k;
|
|
233
233
|
for (k = 0; k < 256; k++) {
|
|
234
|
-
|
|
234
|
+
char t = 0, j;
|
|
235
235
|
for (j = 0; j < 8; j++) {
|
|
236
236
|
if (k & 1 << j)
|
|
237
|
+
/* j are the indices of active bits in k (little endian) */
|
|
237
238
|
switch (kop) {
|
|
238
|
-
case 'a':
|
|
239
|
-
case 'A':
|
|
240
|
-
case '
|
|
241
|
-
|
|
242
|
-
case '
|
|
239
|
+
case 'a': t += j; break; /* add active indices */
|
|
240
|
+
case 'A': t += 7 - j; break; /* 'a' for big endian */
|
|
241
|
+
case 's': t += j * j; /* add squares of active indices */
|
|
242
|
+
break;
|
|
243
|
+
case 'S': t += (7-j) * (7-j); /* 's' for big endian */
|
|
244
|
+
break;
|
|
245
|
+
case 'x': t ^= j; break; /* xor active indices */
|
|
246
|
+
case 'X': t ^= 7 - j; break; /* 'x' for big endian */
|
|
247
|
+
case 'c': t++; break; /* bit count */
|
|
248
|
+
case 'p': t ^= 1; break; /* parity */
|
|
249
|
+
case 'r': t |= 128 >> j; break; /* reverse bits */
|
|
243
250
|
default: Py_UNREACHABLE();
|
|
244
251
|
}
|
|
245
252
|
}
|
|
253
|
+
table[k] = t;
|
|
246
254
|
}
|
|
247
255
|
}
|
|
248
256
|
|
|
@@ -17,7 +17,8 @@ import unittest
|
|
|
17
17
|
from io import StringIO
|
|
18
18
|
from functools import reduce
|
|
19
19
|
from string import hexdigits
|
|
20
|
-
from random import choice, getrandbits, randrange, randint, random,
|
|
20
|
+
from random import (choice, getrandbits, randrange, randint, random, sample,
|
|
21
|
+
seed)
|
|
21
22
|
from collections import Counter
|
|
22
23
|
|
|
23
24
|
from bitarray import (bitarray, frozenbitarray, decodetree, bits2bytes,
|
|
@@ -36,7 +37,7 @@ from bitarray.util import (
|
|
|
36
37
|
_huffman_tree, huffman_code, canonical_huffman, canonical_decode,
|
|
37
38
|
)
|
|
38
39
|
|
|
39
|
-
from bitarray.util import _Random # type: ignore
|
|
40
|
+
from bitarray.util import _Random, _ssqi # type: ignore
|
|
40
41
|
|
|
41
42
|
# ---------------------------------------------------------------------------
|
|
42
43
|
|
|
@@ -147,6 +148,7 @@ class Random_K_Tests(unittest.TestCase):
|
|
|
147
148
|
self.assertRaises(TypeError, R, 4)
|
|
148
149
|
self.assertRaises(TypeError, R, 1, "0.5")
|
|
149
150
|
self.assertRaises(TypeError, R, 1, p=1)
|
|
151
|
+
self.assertRaises(TypeError, R, 11, 5.5) # see issue #239
|
|
150
152
|
self.assertRaises(ValueError, R, -1, 0)
|
|
151
153
|
for k in -1, 11: # k is not 0 <= k <= n
|
|
152
154
|
self.assertRaises(ValueError, R, 10, k)
|
|
@@ -157,6 +159,12 @@ class Random_K_Tests(unittest.TestCase):
|
|
|
157
159
|
self.assertEqual(R(n, k=n), ones(n))
|
|
158
160
|
|
|
159
161
|
def test_count(self):
|
|
162
|
+
for n in range(10): # test explicitly for small n
|
|
163
|
+
for k in range(n + 1):
|
|
164
|
+
a = random_k(n, k)
|
|
165
|
+
self.assertEqual(len(a), n)
|
|
166
|
+
self.assertEqual(a.count(), k)
|
|
167
|
+
|
|
160
168
|
for _ in range(100):
|
|
161
169
|
n = randrange(10_000)
|
|
162
170
|
k = randint(0, n)
|
|
@@ -358,7 +366,7 @@ class Random_P_Tests(unittest.TestCase):
|
|
|
358
366
|
|
|
359
367
|
def test_small_p_limit(self):
|
|
360
368
|
# For understanding how the algorithm works, see ./doc/random_p.rst
|
|
361
|
-
# Also, see VerificationTests in
|
|
369
|
+
# Also, see VerificationTests in devel/test_random.py
|
|
362
370
|
r = _Random()
|
|
363
371
|
limit = 1.0 / (r.K + 1) # lower limit for p
|
|
364
372
|
self.assertTrue(r.SMALL_P > limit)
|
|
@@ -1022,50 +1030,114 @@ class ParityTests(unittest.TestCase, Util):
|
|
|
1022
1030
|
|
|
1023
1031
|
# ---------------------------------------------------------------------------
|
|
1024
1032
|
|
|
1025
|
-
class
|
|
1033
|
+
class SumIndicesUtil(unittest.TestCase):
|
|
1026
1034
|
|
|
1027
|
-
def
|
|
1028
|
-
for s,
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1035
|
+
def check_explicit(self, S):
|
|
1036
|
+
for s, r1, r2 in [
|
|
1037
|
+
("", 0, 0), ("0", 0, 0), ("1", 0, 0), ("11", 1, 1),
|
|
1038
|
+
("011", 3, 5), ("001", 2, 4), ("0001100", 7, 25),
|
|
1039
|
+
("00001111", 22, 126), ("01100111 1101", 49, 381),
|
|
1040
|
+
]:
|
|
1041
|
+
for a in [bitarray(s, choice(['little', 'big'])),
|
|
1042
|
+
frozenbitarray(s, choice(['little', 'big']))]:
|
|
1043
|
+
self.assertEqual(S(a, 1), r1)
|
|
1044
|
+
self.assertEqual(S(a, 2), r2)
|
|
1045
|
+
self.assertEqual(a, bitarray(s))
|
|
1033
1046
|
|
|
1034
|
-
def
|
|
1035
|
-
S = sum_indices
|
|
1047
|
+
def check_wrong_args(self, S):
|
|
1036
1048
|
self.assertRaises(TypeError, S, '')
|
|
1037
|
-
self.assertRaises(TypeError, S, 1)
|
|
1049
|
+
self.assertRaises(TypeError, S, 1.0)
|
|
1038
1050
|
self.assertRaises(TypeError, S)
|
|
1039
|
-
|
|
1051
|
+
for mode in -1, 0, 3, 4:
|
|
1052
|
+
self.assertRaises(ValueError, S, bitarray("110"), mode)
|
|
1053
|
+
|
|
1054
|
+
def check_urandom(self, S, n):
|
|
1055
|
+
a = urandom_2(n)
|
|
1056
|
+
self.assertEqual(S(a, 1), sum(i for i, v in enumerate(a) if v))
|
|
1057
|
+
self.assertEqual(S(a, 2), sum(i * i for i, v in enumerate(a) if v))
|
|
1058
|
+
|
|
1059
|
+
def check_sparse(self, S, n, k, mode=1, freeze=False, inv=False):
|
|
1060
|
+
a = zeros(n, choice(['little', 'big']))
|
|
1061
|
+
self.assertEqual(S(a, mode), 0)
|
|
1062
|
+
self.assertFalse(a.any())
|
|
1063
|
+
|
|
1064
|
+
indices = sample(range(n), k)
|
|
1065
|
+
a[indices] = 1
|
|
1066
|
+
res = sum(indices) if mode == 1 else sum(i * i for i in indices)
|
|
1067
|
+
|
|
1068
|
+
if inv:
|
|
1069
|
+
a.invert()
|
|
1070
|
+
sum_ones = 3 if mode == 1 else 2 * n - 1
|
|
1071
|
+
sum_ones *= n * (n - 1)
|
|
1072
|
+
sum_ones //= 6
|
|
1073
|
+
res = sum_ones - res
|
|
1040
1074
|
|
|
1041
|
-
|
|
1075
|
+
if freeze:
|
|
1076
|
+
a = frozenbitarray(a)
|
|
1077
|
+
|
|
1078
|
+
c = a.copy()
|
|
1079
|
+
self.assertEqual(a.count(), n - k if inv else k)
|
|
1080
|
+
self.assertEqual(S(a, mode), res)
|
|
1081
|
+
self.assertEqual(a, c)
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
class SSQI_Tests(SumIndicesUtil):
|
|
1085
|
+
|
|
1086
|
+
# Additional tests for _ssqi() in: devel/test_sum_indices.py
|
|
1087
|
+
|
|
1088
|
+
def test_explicit(self):
|
|
1089
|
+
self.check_explicit(_ssqi)
|
|
1090
|
+
|
|
1091
|
+
def test_wrong_args(self):
|
|
1092
|
+
self.check_wrong_args(_ssqi)
|
|
1093
|
+
|
|
1094
|
+
def test_small(self):
|
|
1042
1095
|
a = bitarray()
|
|
1043
|
-
|
|
1044
|
-
for i in range(
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
n = 100_000
|
|
1053
|
-
a = bitarray(n)
|
|
1054
|
-
self.assertEqual(sum_indices(a), 0)
|
|
1055
|
-
a.setall(1)
|
|
1056
|
-
self.assertEqual(sum_indices(a), n * (n - 1) // 2)
|
|
1096
|
+
sm1 = sm2 = 0
|
|
1097
|
+
for i in range(100):
|
|
1098
|
+
v = getrandbits(1)
|
|
1099
|
+
a.append(v)
|
|
1100
|
+
if v:
|
|
1101
|
+
sm1 += i
|
|
1102
|
+
sm2 += i * i
|
|
1103
|
+
self.assertEqual(_ssqi(a, 1), sm1)
|
|
1104
|
+
self.assertEqual(_ssqi(a, 2), sm2)
|
|
1057
1105
|
|
|
1058
|
-
def
|
|
1059
|
-
|
|
1060
|
-
a = urandom_2(n)
|
|
1061
|
-
self.assertEqual(sum_indices(a),
|
|
1062
|
-
sum(i for i, v in enumerate(a) if v))
|
|
1106
|
+
def test_urandom(self):
|
|
1107
|
+
self.check_urandom(_ssqi, 10_037)
|
|
1063
1108
|
|
|
1064
|
-
def
|
|
1065
|
-
for
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1109
|
+
def test_sparse(self):
|
|
1110
|
+
for _ in range(5):
|
|
1111
|
+
mode = randint(1, 2)
|
|
1112
|
+
freeze = getrandbits(1)
|
|
1113
|
+
inv = getrandbits(1)
|
|
1114
|
+
self.check_sparse(_ssqi, n=1_000_003, k=400,
|
|
1115
|
+
mode=mode, freeze=freeze, inv=inv)
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
class SumIndicesTests(SumIndicesUtil):
|
|
1119
|
+
|
|
1120
|
+
# Additional tests in: devel/test_sum_indices.py
|
|
1121
|
+
|
|
1122
|
+
def test_explicit(self):
|
|
1123
|
+
self.check_explicit(sum_indices)
|
|
1124
|
+
|
|
1125
|
+
def test_wrong_args(self):
|
|
1126
|
+
self.check_wrong_args(sum_indices)
|
|
1127
|
+
|
|
1128
|
+
def test_ones(self):
|
|
1129
|
+
for mode in 1, 2:
|
|
1130
|
+
self.check_sparse(sum_indices, n=1_600_037, k=0,
|
|
1131
|
+
mode=mode, freeze=True, inv=True)
|
|
1132
|
+
|
|
1133
|
+
def test_sparse(self):
|
|
1134
|
+
for _ in range(20):
|
|
1135
|
+
n = choice([500_029, 600_011]) # below and above block size
|
|
1136
|
+
k = randrange(1_000)
|
|
1137
|
+
mode = randint(1, 2)
|
|
1138
|
+
freeze = getrandbits(1)
|
|
1139
|
+
inv = getrandbits(1)
|
|
1140
|
+
self.check_sparse(sum_indices, n, k, mode, freeze, inv)
|
|
1069
1141
|
|
|
1070
1142
|
# ---------------------------------------------------------------------------
|
|
1071
1143
|
|
|
@@ -1075,8 +1147,9 @@ class XoredIndicesTests(unittest.TestCase, Util):
|
|
|
1075
1147
|
for s, r in [("", 0), ("0", 0), ("1", 0), ("11", 1),
|
|
1076
1148
|
("011", 3), ("001", 2), ("0001100", 7),
|
|
1077
1149
|
("01100111 1101", 13)]:
|
|
1078
|
-
a
|
|
1079
|
-
|
|
1150
|
+
for a in [bitarray(s, self.random_endian()),
|
|
1151
|
+
frozenbitarray(s, self.random_endian())]:
|
|
1152
|
+
self.assertEqual(xor_indices(a), r)
|
|
1080
1153
|
|
|
1081
1154
|
def test_wrong_args(self):
|
|
1082
1155
|
X = xor_indices
|
|
@@ -1099,22 +1172,18 @@ class XoredIndicesTests(unittest.TestCase, Util):
|
|
|
1099
1172
|
self.assertEqual(lst[i], x)
|
|
1100
1173
|
|
|
1101
1174
|
def test_large_random(self):
|
|
1102
|
-
n =
|
|
1103
|
-
a
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1175
|
+
n = 10_037
|
|
1176
|
+
for a in [urandom_2(n), frozenbitarray(urandom_2(n))]:
|
|
1177
|
+
res = reduce(operator.xor, (i for i, v in enumerate(a) if v))
|
|
1178
|
+
b = a.copy()
|
|
1179
|
+
self.assertEqual(xor_indices(a), res)
|
|
1180
|
+
self.assertEqual(a, b)
|
|
1108
1181
|
|
|
1109
1182
|
def test_random(self):
|
|
1110
1183
|
for a in self.randombitarrays():
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
c
|
|
1114
|
-
elif cnt == 1:
|
|
1115
|
-
c = a.index(1)
|
|
1116
|
-
else:
|
|
1117
|
-
c = reduce(operator.xor, (i for i, v in enumerate(a) if v))
|
|
1184
|
+
c = 0
|
|
1185
|
+
for i, v in enumerate(a):
|
|
1186
|
+
c ^= i * v
|
|
1118
1187
|
self.assertEqual(xor_indices(a), c)
|
|
1119
1188
|
|
|
1120
1189
|
def test_flips(self):
|
|
@@ -2239,22 +2308,6 @@ class MixedTests(unittest.TestCase, Util):
|
|
|
2239
2308
|
c <<= n
|
|
2240
2309
|
self.assertEqual(ba2int(c), i << n)
|
|
2241
2310
|
|
|
2242
|
-
def test_primes(self): # Sieve of Eratosthenes
|
|
2243
|
-
sieve = ones(10000)
|
|
2244
|
-
sieve[:2] = 0 # zero and one are not prime
|
|
2245
|
-
for i in range(2, 100):
|
|
2246
|
-
if sieve[i]:
|
|
2247
|
-
sieve[i * i::i] = 0
|
|
2248
|
-
# primes up to 40
|
|
2249
|
-
self.assertEqual(list(sieve.search(1, 0, 40)),
|
|
2250
|
-
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37])
|
|
2251
|
-
# there are 1229 primes between 1 and 10000
|
|
2252
|
-
self.assertEqual(sieve.count(1), 1229)
|
|
2253
|
-
# there are 119 primes between 4000 and 5000
|
|
2254
|
-
self.assertEqual(sieve.count(1, 4000, 5000), 119)
|
|
2255
|
-
# the 1000th prime is 7919
|
|
2256
|
-
self.assertEqual(count_n(sieve, 1000) - 1, 7919)
|
|
2257
|
-
|
|
2258
2311
|
# ---------------------------------------------------------------------------
|
|
2259
2312
|
|
|
2260
2313
|
class SerializationTests(unittest.TestCase, Util):
|
|
@@ -15,7 +15,7 @@ import random
|
|
|
15
15
|
from bitarray import bitarray, bits2bytes
|
|
16
16
|
|
|
17
17
|
from bitarray._util import (
|
|
18
|
-
zeros, ones, count_n, parity,
|
|
18
|
+
zeros, ones, count_n, parity, _ssqi, xor_indices,
|
|
19
19
|
count_and, count_or, count_xor, any_and, subset,
|
|
20
20
|
correspond_all, byteswap,
|
|
21
21
|
serialize, deserialize,
|
|
@@ -69,6 +69,9 @@ when Python version is too low.
|
|
|
69
69
|
raise NotImplementedError("bitarray.util.random_k() requires "
|
|
70
70
|
"Python 3.9 or higher")
|
|
71
71
|
r = _Random(__n, endian)
|
|
72
|
+
if not isinstance(k, int):
|
|
73
|
+
raise TypeError("int expected, got '%s'" % type(k).__name__)
|
|
74
|
+
|
|
72
75
|
return r.random_k(k)
|
|
73
76
|
|
|
74
77
|
|
|
@@ -97,7 +100,7 @@ class _Random:
|
|
|
97
100
|
# individually in the test class Random_P_Tests in 'test_util.py'.
|
|
98
101
|
# The test class also contains many comments and explanations.
|
|
99
102
|
# To better understand how the algorithm works, see ./doc/random_p.rst
|
|
100
|
-
# See also, VerificationTests in
|
|
103
|
+
# See also, VerificationTests in devel/test_random.py
|
|
101
104
|
|
|
102
105
|
# maximal number of calls to .random_half() in .combine()
|
|
103
106
|
M = 8
|
|
@@ -165,7 +168,7 @@ class _Random:
|
|
|
165
168
|
a.invert() # use in-place to avoid copying
|
|
166
169
|
return a
|
|
167
170
|
|
|
168
|
-
# decide on sequence, see VerificationTests
|
|
171
|
+
# decide on sequence, see VerificationTests devel/test_random.py
|
|
169
172
|
if k < 16 or k * self.K < 3 * n:
|
|
170
173
|
i = 0
|
|
171
174
|
else:
|
|
@@ -225,7 +228,7 @@ class _Random:
|
|
|
225
228
|
|
|
226
229
|
# calculate operator sequence
|
|
227
230
|
i = int(p * self.K)
|
|
228
|
-
if p * (self.K + 1) > i + 1: # see
|
|
231
|
+
if p * (self.K + 1) > i + 1: # see devel/test_random.py
|
|
229
232
|
i += 1
|
|
230
233
|
seq = self.op_seq(i)
|
|
231
234
|
q = i / self.K
|
|
@@ -247,6 +250,50 @@ class _Random:
|
|
|
247
250
|
return a
|
|
248
251
|
|
|
249
252
|
|
|
253
|
+
def sum_indices(__a, __mode=1):
|
|
254
|
+
"""sum_indices(a, /) -> int
|
|
255
|
+
|
|
256
|
+
Return sum of indices of all active bits in bitarray `a`.
|
|
257
|
+
Equivalent to `sum(i for i, v in enumerate(a) if v)`.
|
|
258
|
+
"""
|
|
259
|
+
if __mode not in (1, 2):
|
|
260
|
+
raise ValueError("unexpected mode %r" % __mode)
|
|
261
|
+
|
|
262
|
+
# For details see: devel/test_sum_indices.py
|
|
263
|
+
n = 1 << 19 # block size 512 Kbits
|
|
264
|
+
if len(__a) <= n: # shortcut for single block
|
|
265
|
+
return _ssqi(__a, __mode)
|
|
266
|
+
|
|
267
|
+
# Constants
|
|
268
|
+
m = n // 8 # block size in bytes
|
|
269
|
+
o1 = n * (n - 1) // 2
|
|
270
|
+
o2 = o1 * (2 * n - 1) // 3
|
|
271
|
+
|
|
272
|
+
nblocks = (len(__a) + n - 1) // n
|
|
273
|
+
padbits = __a.padbits
|
|
274
|
+
sm = 0
|
|
275
|
+
for i in range(nblocks):
|
|
276
|
+
# use memoryview to avoid copying memory
|
|
277
|
+
v = memoryview(__a)[i * m : (i + 1) * m]
|
|
278
|
+
block = bitarray(None, __a.endian, buffer=v)
|
|
279
|
+
if padbits and i == nblocks - 1:
|
|
280
|
+
if block.readonly:
|
|
281
|
+
block = bitarray(block)
|
|
282
|
+
block[-padbits:] = 0
|
|
283
|
+
|
|
284
|
+
k = block.count()
|
|
285
|
+
if k:
|
|
286
|
+
y = n * i
|
|
287
|
+
z1 = o1 if k == n else _ssqi(block)
|
|
288
|
+
if __mode == 1:
|
|
289
|
+
sm += k * y + z1
|
|
290
|
+
else:
|
|
291
|
+
z2 = o2 if k == n else _ssqi(block, 2)
|
|
292
|
+
sm += (k * y + 2 * z1) * y + z2
|
|
293
|
+
|
|
294
|
+
return sm
|
|
295
|
+
|
|
296
|
+
|
|
250
297
|
def pprint(__a, stream=None, group=8, indent=4, width=80):
|
|
251
298
|
"""pprint(bitarray, /, stream=None, group=8, indent=4, width=80)
|
|
252
299
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bitarray
|
|
3
|
-
Version: 3.6.
|
|
3
|
+
Version: 3.6.1
|
|
4
4
|
Summary: efficient arrays of booleans -- C extension
|
|
5
5
|
Home-page: https://github.com/ilanschnell/bitarray
|
|
6
6
|
Author: Ilan Schnell
|
|
@@ -83,20 +83,13 @@ versions. Which means you can simply:
|
|
|
83
83
|
|
|
84
84
|
$ pip install bitarray
|
|
85
85
|
|
|
86
|
-
In addition, conda packages are available (both the default Anaconda
|
|
87
|
-
repository as well as conda-forge support bitarray):
|
|
88
|
-
|
|
89
|
-
.. code-block:: shell-session
|
|
90
|
-
|
|
91
|
-
$ conda install bitarray
|
|
92
|
-
|
|
93
86
|
Once you have installed the package, you may want to test it:
|
|
94
87
|
|
|
95
88
|
.. code-block:: shell-session
|
|
96
89
|
|
|
97
90
|
$ python -c 'import bitarray; bitarray.test()'
|
|
98
91
|
bitarray is installed in: /Users/ilan/bitarray/bitarray
|
|
99
|
-
bitarray version: 3.6.
|
|
92
|
+
bitarray version: 3.6.1
|
|
100
93
|
sys.version: 3.13.5 (main, Jun 16 2025) [Clang 18.1.8]
|
|
101
94
|
sys.prefix: /Users/ilan/miniforge
|
|
102
95
|
pointer size: 64 bit
|
|
@@ -110,7 +103,7 @@ Once you have installed the package, you may want to test it:
|
|
|
110
103
|
.........................................................................
|
|
111
104
|
................................................................
|
|
112
105
|
----------------------------------------------------------------------
|
|
113
|
-
Ran
|
|
106
|
+
Ran 591 tests in 0.163s
|
|
114
107
|
|
|
115
108
|
OK
|
|
116
109
|
|
|
@@ -427,7 +420,7 @@ and can therefore be used as a dictionary key:
|
|
|
427
420
|
Reference
|
|
428
421
|
=========
|
|
429
422
|
|
|
430
|
-
bitarray version: 3.6.
|
|
423
|
+
bitarray version: 3.6.1 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
|
|
431
424
|
|
|
432
425
|
In the following, ``item`` and ``value`` are usually a single bit -
|
|
433
426
|
an integer 0 or 1.
|
|
@@ -1003,7 +996,7 @@ This sub-module was added in version 1.2.
|
|
|
1003
996
|
|
|
1004
997
|
``sum_indices(a, /)`` -> int
|
|
1005
998
|
Return sum of indices of all active bits in bitarray ``a``.
|
|
1006
|
-
|
|
999
|
+
Equivalent to ``sum(i for i, v in enumerate(a) if v)``.
|
|
1007
1000
|
|
|
1008
1001
|
New in version 3.6
|
|
1009
1002
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|