numcodecs 0.13.1__cp313-cp313-win_amd64.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.

Potentially problematic release.


This version of numcodecs might be problematic. Click here for more details.

Files changed (74) hide show
  1. numcodecs/__init__.py +143 -0
  2. numcodecs/_shuffle.cp313-win_amd64.pyd +0 -0
  3. numcodecs/abc.py +126 -0
  4. numcodecs/astype.py +76 -0
  5. numcodecs/base64.py +27 -0
  6. numcodecs/bitround.py +79 -0
  7. numcodecs/blosc.cp313-win_amd64.pyd +0 -0
  8. numcodecs/bz2.py +45 -0
  9. numcodecs/categorize.py +101 -0
  10. numcodecs/checksum32.py +94 -0
  11. numcodecs/compat.py +208 -0
  12. numcodecs/compat_ext.cp313-win_amd64.pyd +0 -0
  13. numcodecs/delta.py +97 -0
  14. numcodecs/fixedscaleoffset.py +132 -0
  15. numcodecs/fletcher32.cp313-win_amd64.pyd +0 -0
  16. numcodecs/gzip.py +52 -0
  17. numcodecs/jenkins.cp313-win_amd64.pyd +0 -0
  18. numcodecs/json.py +107 -0
  19. numcodecs/lz4.cp313-win_amd64.pyd +0 -0
  20. numcodecs/lzma.py +69 -0
  21. numcodecs/msgpacks.py +86 -0
  22. numcodecs/ndarray_like.py +65 -0
  23. numcodecs/packbits.py +85 -0
  24. numcodecs/pcodec.py +89 -0
  25. numcodecs/pickles.py +55 -0
  26. numcodecs/quantize.py +100 -0
  27. numcodecs/registry.py +72 -0
  28. numcodecs/shuffle.py +61 -0
  29. numcodecs/tests/__init__.py +3 -0
  30. numcodecs/tests/common.py +354 -0
  31. numcodecs/tests/package_with_entrypoint/__init__.py +11 -0
  32. numcodecs/tests/package_with_entrypoint-0.1.dist-info/entry_points.txt +2 -0
  33. numcodecs/tests/test_astype.py +74 -0
  34. numcodecs/tests/test_base64.py +81 -0
  35. numcodecs/tests/test_bitround.py +81 -0
  36. numcodecs/tests/test_blosc.py +277 -0
  37. numcodecs/tests/test_bz2.py +66 -0
  38. numcodecs/tests/test_categorize.py +87 -0
  39. numcodecs/tests/test_checksum32.py +58 -0
  40. numcodecs/tests/test_compat.py +108 -0
  41. numcodecs/tests/test_delta.py +60 -0
  42. numcodecs/tests/test_entrypoints.py +24 -0
  43. numcodecs/tests/test_entrypoints_backport.py +35 -0
  44. numcodecs/tests/test_fixedscaleoffset.py +69 -0
  45. numcodecs/tests/test_fletcher32.py +56 -0
  46. numcodecs/tests/test_gzip.py +110 -0
  47. numcodecs/tests/test_jenkins.py +150 -0
  48. numcodecs/tests/test_json.py +85 -0
  49. numcodecs/tests/test_lz4.py +83 -0
  50. numcodecs/tests/test_lzma.py +90 -0
  51. numcodecs/tests/test_msgpacks.py +123 -0
  52. numcodecs/tests/test_ndarray_like.py +48 -0
  53. numcodecs/tests/test_packbits.py +39 -0
  54. numcodecs/tests/test_pcodec.py +80 -0
  55. numcodecs/tests/test_pickles.py +61 -0
  56. numcodecs/tests/test_quantize.py +76 -0
  57. numcodecs/tests/test_registry.py +40 -0
  58. numcodecs/tests/test_shuffle.py +168 -0
  59. numcodecs/tests/test_vlen_array.py +97 -0
  60. numcodecs/tests/test_vlen_bytes.py +93 -0
  61. numcodecs/tests/test_vlen_utf8.py +91 -0
  62. numcodecs/tests/test_zfpy.py +98 -0
  63. numcodecs/tests/test_zlib.py +94 -0
  64. numcodecs/tests/test_zstd.py +92 -0
  65. numcodecs/version.py +16 -0
  66. numcodecs/vlen.cp313-win_amd64.pyd +0 -0
  67. numcodecs/zfpy.py +111 -0
  68. numcodecs/zlib.py +42 -0
  69. numcodecs/zstd.cp313-win_amd64.pyd +0 -0
  70. numcodecs-0.13.1.dist-info/LICENSE.txt +21 -0
  71. numcodecs-0.13.1.dist-info/METADATA +64 -0
  72. numcodecs-0.13.1.dist-info/RECORD +74 -0
  73. numcodecs-0.13.1.dist-info/WHEEL +5 -0
  74. numcodecs-0.13.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,354 @@
1
+ import array
2
+ import json as _json
3
+ import os
4
+ from glob import glob
5
+
6
+ import numpy as np
7
+ import pytest
8
+ from numpy.testing import assert_array_almost_equal, assert_array_equal
9
+
10
+ # star import needed for repr tests so eval finds names
11
+ from numcodecs import * # noqa: F403
12
+ from numcodecs.compat import ensure_bytes, ensure_ndarray
13
+ from numcodecs.registry import get_codec
14
+
15
+ greetings = [
16
+ '¡Hola mundo!',
17
+ 'Hej Världen!',
18
+ 'Servus Woid!',
19
+ 'Hei maailma!',
20
+ 'Xin chào thế giới',
21
+ 'Njatjeta Botë!',
22
+ 'Γεια σου κόσμε!',
23
+ 'こんにちは世界',
24
+ '世界,你好!',
25
+ 'Helló, világ!',
26
+ 'Zdravo svete!',
27
+ 'เฮลโลเวิลด์',
28
+ ]
29
+
30
+
31
+ def compare_arrays(arr, res, precision=None):
32
+ # ensure numpy array with matching dtype
33
+ res = ensure_ndarray(res).view(arr.dtype)
34
+
35
+ # convert to correct shape
36
+ if arr.flags.f_contiguous:
37
+ order = 'F'
38
+ else:
39
+ order = 'C'
40
+ res = res.reshape(arr.shape, order=order)
41
+
42
+ # exact compare
43
+ if precision is None:
44
+ assert_array_equal(arr, res)
45
+
46
+ # fuzzy compare
47
+ else:
48
+ assert_array_almost_equal(arr, res, decimal=precision)
49
+
50
+
51
+ def check_encode_decode(arr, codec, precision=None):
52
+ # N.B., watch out here with blosc compressor, if the itemsize of
53
+ # the source buffer is different then the results of encoding
54
+ # (i.e., compression) may be different. Hence we *do not* require that
55
+ # the results of encoding be identical for all possible inputs, rather
56
+ # we just require that the results of the encode/decode round-trip can
57
+ # be compared to the original array.
58
+
59
+ # encoding should support any object exporting the buffer protocol
60
+
61
+ # test encoding of numpy array
62
+ enc = codec.encode(arr)
63
+ dec = codec.decode(enc)
64
+ compare_arrays(arr, dec, precision=precision)
65
+
66
+ # test encoding of bytes
67
+ buf = arr.tobytes(order='A')
68
+ enc = codec.encode(buf)
69
+ dec = codec.decode(enc)
70
+ compare_arrays(arr, dec, precision=precision)
71
+
72
+ # test encoding of bytearray
73
+ buf = bytearray(arr.tobytes(order='A'))
74
+ enc = codec.encode(buf)
75
+ dec = codec.decode(enc)
76
+ compare_arrays(arr, dec, precision=precision)
77
+
78
+ # test encoding of array.array
79
+ buf = array.array('b', arr.tobytes(order='A'))
80
+ enc = codec.encode(buf)
81
+ dec = codec.decode(enc)
82
+ compare_arrays(arr, dec, precision=precision)
83
+
84
+ # decoding should support any object exporting the buffer protocol,
85
+
86
+ # setup
87
+ enc_bytes = ensure_bytes(enc)
88
+
89
+ # test decoding of raw bytes
90
+ dec = codec.decode(enc_bytes)
91
+ compare_arrays(arr, dec, precision=precision)
92
+
93
+ # test decoding of bytearray
94
+ dec = codec.decode(bytearray(enc_bytes))
95
+ compare_arrays(arr, dec, precision=precision)
96
+
97
+ # test decoding of array.array
98
+ buf = array.array('b', enc_bytes)
99
+ dec = codec.decode(buf)
100
+ compare_arrays(arr, dec, precision=precision)
101
+
102
+ # test decoding of numpy array
103
+ buf = np.frombuffer(enc_bytes, dtype='u1')
104
+ dec = codec.decode(buf)
105
+ compare_arrays(arr, dec, precision=precision)
106
+
107
+ # test decoding directly into numpy array
108
+ out = np.empty_like(arr)
109
+ codec.decode(enc_bytes, out=out)
110
+ compare_arrays(arr, out, precision=precision)
111
+
112
+ # test decoding directly into bytearray
113
+ out = bytearray(arr.nbytes)
114
+ codec.decode(enc_bytes, out=out)
115
+ # noinspection PyTypeChecker
116
+ compare_arrays(arr, out, precision=precision)
117
+
118
+
119
+ def check_encode_decode_partial(arr, codec, precision=None):
120
+ # N.B., watch out here with blosc compressor, if the itemsize of
121
+ # the source buffer is different then the results of encoding
122
+ # (i.e., compression) may be different. Hence we *do not* require that
123
+ # the results of encoding be identical for all possible inputs, rather
124
+ # we just require that the results of the encode/decode round-trip can
125
+ # be compared to the original array.
126
+
127
+ itemsize = arr.itemsize
128
+ start, nitems = 5, 10
129
+ compare_arr = arr[start : start + nitems]
130
+ # test encoding of numpy array
131
+ enc = codec.encode(arr)
132
+ dec = codec.decode_partial(enc, start, nitems)
133
+ compare_arrays(compare_arr, dec, precision=precision)
134
+
135
+ # out = np.empty_like(compare_arr)
136
+ out = np.empty_like(compare_arr)
137
+ print(len(out))
138
+
139
+ # test partial decode of encoded bytes
140
+ buf = arr.tobytes(order='A')
141
+ enc = codec.encode(buf)
142
+ dec = codec.decode_partial(enc, start * itemsize, nitems * itemsize, out=out)
143
+ compare_arrays(compare_arr, dec, precision=precision)
144
+
145
+ # test partial decode of encoded bytearray
146
+ buf = bytearray(arr.tobytes(order='A'))
147
+ enc = codec.encode(buf)
148
+ dec = codec.decode_partial(enc, start * itemsize, nitems * itemsize, out=out)
149
+ compare_arrays(compare_arr, dec, precision=precision)
150
+
151
+ # test partial decode of encoded array.array
152
+ buf = array.array('b', arr.tobytes(order='A'))
153
+ enc = codec.encode(buf)
154
+ dec = codec.decode_partial(enc, start * itemsize, nitems * itemsize, out=out)
155
+ compare_arrays(compare_arr, dec, precision=precision)
156
+
157
+ # # decoding should support any object exporting the buffer protocol,
158
+
159
+ # # setup
160
+ enc_bytes = ensure_bytes(enc)
161
+
162
+ # test decoding of raw bytes into numpy array
163
+ dec = codec.decode_partial(enc_bytes, start * itemsize, nitems * itemsize, out=out)
164
+ compare_arrays(compare_arr, dec, precision=precision)
165
+
166
+ # test partial decoding of bytearray
167
+ dec = codec.decode_partial(bytearray(enc_bytes), start * itemsize, nitems * itemsize, out=out)
168
+ compare_arrays(compare_arr, dec, precision=precision)
169
+
170
+ # test partial decoding of array.array
171
+ buf = array.array('b', enc_bytes)
172
+ dec = codec.decode_partial(buf, start * itemsize, nitems * itemsize, out=out)
173
+ compare_arrays(compare_arr, dec, precision=precision)
174
+
175
+ # test decoding of numpy array into numpy array
176
+ buf = np.frombuffer(enc_bytes, dtype='u1')
177
+ dec = codec.decode_partial(buf, start * itemsize, nitems * itemsize, out=out)
178
+ compare_arrays(compare_arr, dec, precision=precision)
179
+
180
+ # test decoding directly into bytearray
181
+ out = bytearray(compare_arr.nbytes)
182
+ codec.decode_partial(enc_bytes, start * itemsize, nitems * itemsize, out=out)
183
+ # noinspection PyTypeChecker
184
+ compare_arrays(compare_arr, out, precision=precision)
185
+
186
+
187
+ def assert_array_items_equal(res, arr):
188
+ assert isinstance(res, np.ndarray)
189
+ res = res.reshape(-1, order='A')
190
+ arr = arr.reshape(-1, order='A')
191
+ assert res.shape == arr.shape
192
+ assert res.dtype == arr.dtype
193
+
194
+ # numpy asserts don't compare object arrays
195
+ # properly; assert that we have the same nans
196
+ # and values
197
+ arr = arr.ravel().tolist()
198
+ res = res.ravel().tolist()
199
+ for a, r in zip(arr, res, strict=True):
200
+ if isinstance(a, np.ndarray):
201
+ assert_array_equal(a, r)
202
+ elif a != a:
203
+ assert r != r
204
+ else:
205
+ assert a == r
206
+
207
+
208
+ def check_encode_decode_array(arr, codec):
209
+ enc = codec.encode(arr)
210
+ dec = codec.decode(enc)
211
+ assert_array_items_equal(arr, dec)
212
+
213
+ out = np.empty_like(arr)
214
+ codec.decode(enc, out=out)
215
+ assert_array_items_equal(arr, out)
216
+
217
+ enc = codec.encode(arr)
218
+ dec = codec.decode(ensure_ndarray(enc))
219
+ assert_array_items_equal(arr, dec)
220
+
221
+
222
+ def check_encode_decode_array_to_bytes(arr, codec):
223
+ enc = codec.encode(arr)
224
+ dec = codec.decode(enc)
225
+ assert_array_items_equal(arr, dec)
226
+
227
+ out = np.empty_like(arr)
228
+ codec.decode(enc, out=out)
229
+ assert_array_items_equal(arr, out)
230
+
231
+
232
+ def check_config(codec):
233
+ config = codec.get_config()
234
+ # round-trip through JSON to check serialization
235
+ config = _json.loads(_json.dumps(config))
236
+ assert codec == get_codec(config)
237
+
238
+
239
+ def check_repr(stmt):
240
+ # check repr matches instantiation statement
241
+ codec = eval(stmt)
242
+ actual = repr(codec)
243
+ assert stmt == actual
244
+
245
+
246
+ def check_backwards_compatibility(codec_id, arrays, codecs, precision=None, prefix=None):
247
+ # setup directory to hold data fixture
248
+ if prefix:
249
+ fixture_dir = os.path.join('fixture', codec_id, prefix)
250
+ else:
251
+ fixture_dir = os.path.join('fixture', codec_id)
252
+ if not os.path.exists(fixture_dir): # pragma: no cover
253
+ os.makedirs(fixture_dir)
254
+
255
+ # save fixture data
256
+ for i, arr in enumerate(arrays):
257
+ arr_fn = os.path.join(fixture_dir, f'array.{i:02d}.npy')
258
+ if not os.path.exists(arr_fn): # pragma: no cover
259
+ np.save(arr_fn, arr)
260
+
261
+ # load fixture data
262
+ for arr_fn in glob(os.path.join(fixture_dir, 'array.*.npy')):
263
+ # setup
264
+ i = int(arr_fn.split('.')[-2])
265
+ arr = np.load(arr_fn, allow_pickle=True)
266
+ arr_bytes = arr.tobytes(order='A')
267
+ if arr.flags.f_contiguous:
268
+ order = 'F'
269
+ else:
270
+ order = 'C'
271
+
272
+ for j, codec in enumerate(codecs):
273
+ if codec is None:
274
+ pytest.skip("codec has been removed")
275
+
276
+ # setup a directory to hold encoded data
277
+ codec_dir = os.path.join(fixture_dir, f'codec.{j:02d}')
278
+ if not os.path.exists(codec_dir): # pragma: no cover
279
+ os.makedirs(codec_dir)
280
+
281
+ # file with codec configuration information
282
+ codec_fn = os.path.join(codec_dir, 'config.json')
283
+ # one time save config
284
+ if not os.path.exists(codec_fn): # pragma: no cover
285
+ with open(codec_fn, mode='w') as cf:
286
+ _json.dump(codec.get_config(), cf, sort_keys=True, indent=4)
287
+ # load config and compare with expectation
288
+ with open(codec_fn) as cf:
289
+ config = _json.load(cf)
290
+ assert codec == get_codec(config)
291
+
292
+ enc_fn = os.path.join(codec_dir, f'encoded.{i:02d}.dat')
293
+
294
+ # one time encode and save array
295
+ if not os.path.exists(enc_fn): # pragma: no cover
296
+ enc = codec.encode(arr)
297
+ enc = ensure_bytes(enc)
298
+ with open(enc_fn, mode='wb') as ef:
299
+ ef.write(enc)
300
+
301
+ # load and decode data
302
+ with open(enc_fn, mode='rb') as ef:
303
+ enc = ef.read()
304
+ dec = codec.decode(enc)
305
+ dec_arr = ensure_ndarray(dec).reshape(-1, order='A')
306
+ dec_arr = dec_arr.view(dtype=arr.dtype).reshape(arr.shape, order=order)
307
+ if precision and precision[j] is not None:
308
+ assert_array_almost_equal(arr, dec_arr, decimal=precision[j])
309
+ elif arr.dtype == 'object':
310
+ assert_array_items_equal(arr, dec_arr)
311
+ else:
312
+ assert_array_equal(arr, dec_arr)
313
+ assert arr_bytes == ensure_bytes(dec)
314
+
315
+
316
+ def check_err_decode_object_buffer(compressor):
317
+ # cannot decode directly into object array, leads to segfaults
318
+ a = np.arange(10)
319
+ enc = compressor.encode(a)
320
+ out = np.empty(10, dtype=object)
321
+ with pytest.raises(TypeError):
322
+ compressor.decode(enc, out=out)
323
+
324
+
325
+ def check_err_encode_object_buffer(compressor):
326
+ # compressors cannot encode object array
327
+ a = np.array(['foo', 'bar', 'baz'], dtype=object)
328
+ with pytest.raises(TypeError):
329
+ compressor.encode(a)
330
+
331
+
332
+ def check_max_buffer_size(codec):
333
+ for max_buffer_size in (4, 64, 1024):
334
+ old_max_buffer_size = codec.max_buffer_size
335
+ try:
336
+ codec.max_buffer_size = max_buffer_size
337
+ # Just up the max_buffer_size is fine.
338
+ codec.encode(np.zeros(max_buffer_size - 1, dtype=np.int8))
339
+ codec.encode(np.zeros(max_buffer_size, dtype=np.int8))
340
+
341
+ buffers = [
342
+ bytes(b"x" * (max_buffer_size + 1)),
343
+ np.zeros(max_buffer_size + 1, dtype=np.int8),
344
+ np.zeros(max_buffer_size + 2, dtype=np.int8),
345
+ np.zeros(max_buffer_size, dtype=np.int16),
346
+ np.zeros(max_buffer_size, dtype=np.int32),
347
+ ]
348
+ for buf in buffers:
349
+ with pytest.raises(ValueError):
350
+ codec.encode(buf)
351
+ with pytest.raises(ValueError):
352
+ codec.decode(buf)
353
+ finally:
354
+ codec.max_buffer_size = old_max_buffer_size
@@ -0,0 +1,11 @@
1
+ from numcodecs.abc import Codec
2
+
3
+
4
+ class TestCodec(Codec):
5
+ codec_id = "test"
6
+
7
+ def encode(self, buf): # pragma: no cover
8
+ pass
9
+
10
+ def decode(self, buf, out=None): # pragma: no cover
11
+ pass
@@ -0,0 +1,2 @@
1
+ [numcodecs.codecs]
2
+ test = package_with_entrypoint:TestCodec
@@ -0,0 +1,74 @@
1
+ import numpy as np
2
+ from numpy.testing import assert_array_equal
3
+
4
+ from numcodecs.astype import AsType
5
+ from numcodecs.tests.common import (
6
+ check_backwards_compatibility,
7
+ check_config,
8
+ check_encode_decode,
9
+ check_repr,
10
+ )
11
+
12
+ # mix of dtypes: integer, float
13
+ # mix of shapes: 1D, 2D, 3D
14
+ # mix of orders: C, F
15
+ arrays = [
16
+ np.arange(1000, dtype='i4'),
17
+ np.linspace(1000, 1001, 1000, dtype='f8').reshape(100, 10),
18
+ np.random.normal(loc=1000, scale=1, size=(10, 10, 10)),
19
+ np.random.randint(0, 200, size=1000, dtype='u2').reshape(100, 10, order='F'),
20
+ ]
21
+
22
+
23
+ def test_encode_decode():
24
+ for arr in arrays:
25
+ codec = AsType(encode_dtype=arr.dtype, decode_dtype=arr.dtype)
26
+ check_encode_decode(arr, codec)
27
+
28
+
29
+ def test_decode():
30
+ encode_dtype, decode_dtype = '<i4', '<i8'
31
+ codec = AsType(encode_dtype=encode_dtype, decode_dtype=decode_dtype)
32
+ arr = np.arange(10, 20, 1, dtype=encode_dtype)
33
+ expect = arr.astype(decode_dtype)
34
+ actual = codec.decode(arr)
35
+ assert_array_equal(expect, actual)
36
+ assert np.dtype(decode_dtype) == actual.dtype
37
+
38
+
39
+ def test_encode():
40
+ encode_dtype, decode_dtype = '<i4', '<i8'
41
+ codec = AsType(encode_dtype=encode_dtype, decode_dtype=decode_dtype)
42
+ arr = np.arange(10, 20, 1, dtype=decode_dtype)
43
+ expect = arr.astype(encode_dtype)
44
+ actual = codec.encode(arr)
45
+ assert_array_equal(expect, actual)
46
+ assert np.dtype(encode_dtype) == actual.dtype
47
+
48
+
49
+ def test_config():
50
+ encode_dtype, decode_dtype = '<i4', '<i8'
51
+ codec = AsType(encode_dtype=encode_dtype, decode_dtype=decode_dtype)
52
+ check_config(codec)
53
+
54
+
55
+ def test_repr():
56
+ check_repr("AsType(encode_dtype='<i4', decode_dtype='<i2')")
57
+
58
+
59
+ def test_backwards_compatibility():
60
+ # integers
61
+ arrs = [
62
+ np.arange(1000, dtype='<i4'),
63
+ np.random.randint(0, 200, size=1000, dtype='i4').astype('<i4').reshape(100, 10, order='F'),
64
+ ]
65
+ codec = AsType(encode_dtype='<i2', decode_dtype='<i4')
66
+ check_backwards_compatibility(AsType.codec_id, arrs, [codec], prefix='i')
67
+
68
+ # floats
69
+ arrs = [
70
+ np.linspace(1000, 1001, 1000, dtype='<f8').reshape(100, 10, order='F'),
71
+ np.random.normal(loc=1000, scale=1, size=(10, 10, 10)).astype('<f8'),
72
+ ]
73
+ codec = AsType(encode_dtype='<f4', decode_dtype='<f8')
74
+ check_backwards_compatibility(AsType.codec_id, arrs, [codec], precision=[3], prefix='f')
@@ -0,0 +1,81 @@
1
+ import itertools
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from numcodecs.base64 import Base64
7
+ from numcodecs.tests.common import (
8
+ check_backwards_compatibility,
9
+ check_encode_decode,
10
+ check_err_decode_object_buffer,
11
+ check_err_encode_object_buffer,
12
+ check_repr,
13
+ )
14
+
15
+ codecs = [
16
+ Base64(),
17
+ ]
18
+
19
+
20
+ # mix of dtypes: integer, float, bool, string
21
+ # mix of shapes: 1D, 2D, 3D
22
+ # mix of orders: C, F
23
+ arrays = [
24
+ np.arange(1000, dtype="i4"),
25
+ np.linspace(1000, 1001, 1000, dtype="f8"),
26
+ np.random.normal(loc=1000, scale=1, size=(100, 10)),
27
+ np.random.randint(0, 2, size=1000, dtype=bool).reshape(100, 10, order="F"),
28
+ np.random.choice([b"a", b"bb", b"ccc"], size=1000).reshape(10, 10, 10),
29
+ np.random.randint(0, 2**60, size=1000, dtype="u8").view("M8[ns]"),
30
+ np.random.randint(0, 2**60, size=1000, dtype="u8").view("m8[ns]"),
31
+ np.random.randint(0, 2**25, size=1000, dtype="u8").view("M8[m]"),
32
+ np.random.randint(0, 2**25, size=1000, dtype="u8").view("m8[m]"),
33
+ np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").view("M8[ns]"),
34
+ np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").view("m8[ns]"),
35
+ np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").view("M8[m]"),
36
+ np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").view("m8[m]"),
37
+ ]
38
+
39
+
40
+ def test_encode_decode():
41
+ for arr, codec in itertools.product(arrays, codecs):
42
+ check_encode_decode(arr, codec)
43
+
44
+
45
+ def test_repr():
46
+ check_repr("Base64()")
47
+
48
+
49
+ def test_eq():
50
+ assert Base64() == Base64()
51
+ assert not Base64() != Base64()
52
+ assert Base64() != "foo"
53
+ assert "foo" != Base64()
54
+ assert not Base64() == "foo"
55
+
56
+
57
+ def test_backwards_compatibility():
58
+ check_backwards_compatibility(Base64.codec_id, arrays, codecs)
59
+
60
+
61
+ def test_err_decode_object_buffer():
62
+ check_err_decode_object_buffer(Base64())
63
+
64
+
65
+ def test_err_encode_object_buffer():
66
+ check_err_encode_object_buffer(Base64())
67
+
68
+
69
+ def test_err_encode_list():
70
+ data = ["foo", "bar", "baz"]
71
+ for codec in codecs:
72
+ with pytest.raises(TypeError):
73
+ codec.encode(data)
74
+
75
+
76
+ def test_err_encode_non_contiguous():
77
+ # non-contiguous memory
78
+ arr = np.arange(1000, dtype="i4")[::2]
79
+ for codec in codecs:
80
+ with pytest.raises(ValueError):
81
+ codec.encode(arr)
@@ -0,0 +1,81 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from numcodecs.bitround import BitRound, max_bits
5
+
6
+ # adapted from https://github.com/milankl/BitInformation.jl/blob/main/test/round_nearest.jl
7
+
8
+
9
+ # TODO: add other dtypes
10
+ @pytest.fixture(params=["float32", "float64"])
11
+ def dtype(request):
12
+ return request.param
13
+
14
+
15
+ def round(data, keepbits):
16
+ codec = BitRound(keepbits=keepbits)
17
+ data = data.copy() # otherwise overwrites the input
18
+ encoded = codec.encode(data)
19
+ return codec.decode(encoded)
20
+
21
+
22
+ def test_round_zero_to_zero(dtype):
23
+ a = np.zeros((3, 2), dtype=dtype)
24
+ # Don't understand Milan's original test:
25
+ # How is it possible to have negative keepbits?
26
+ # for k in range(-5, 50):
27
+ for k in range(0, max_bits[dtype]):
28
+ ar = round(a, k)
29
+ np.testing.assert_equal(a, ar)
30
+
31
+
32
+ def test_round_one_to_one(dtype):
33
+ a = np.ones((3, 2), dtype=dtype)
34
+ for k in range(0, max_bits[dtype]):
35
+ ar = round(a, k)
36
+ np.testing.assert_equal(a, ar)
37
+
38
+
39
+ def test_round_minus_one_to_minus_one(dtype):
40
+ a = -np.ones((3, 2), dtype=dtype)
41
+ for k in range(0, max_bits[dtype]):
42
+ ar = round(a, k)
43
+ np.testing.assert_equal(a, ar)
44
+
45
+
46
+ def test_no_rounding(dtype):
47
+ a = np.random.random_sample((300, 200)).astype(dtype)
48
+ keepbits = max_bits[dtype]
49
+ ar = round(a, keepbits)
50
+ np.testing.assert_equal(a, ar)
51
+
52
+
53
+ APPROX_KEEPBITS = {"float32": 11, "float64": 18}
54
+
55
+
56
+ def test_approx_equal(dtype):
57
+ a = np.random.random_sample((300, 200)).astype(dtype)
58
+ ar = round(a, APPROX_KEEPBITS[dtype])
59
+ # Mimic julia behavior - https://docs.julialang.org/en/v1/base/math/#Base.isapprox
60
+ rtol = np.sqrt(np.finfo(np.float32).eps)
61
+ # This gets us much closer but still failing for ~6% of the array
62
+ # It does pass if we add 1 to keepbits (11 instead of 10)
63
+ # Is there an off-by-one issue here?
64
+ np.testing.assert_allclose(a, ar, rtol=rtol)
65
+
66
+
67
+ def test_idempotence(dtype):
68
+ a = np.random.random_sample((300, 200)).astype(dtype)
69
+ for k in range(20):
70
+ ar = round(a, k)
71
+ ar2 = round(a, k)
72
+ np.testing.assert_equal(ar, ar2)
73
+
74
+
75
+ def test_errors():
76
+ with pytest.raises(ValueError):
77
+ BitRound(keepbits=99).encode(np.array([0], dtype="float32"))
78
+ with pytest.raises(TypeError):
79
+ BitRound(keepbits=10).encode(np.array([0]))
80
+ with pytest.raises(ValueError):
81
+ BitRound(-1)