test_numpy_dtypes.py
Go to the documentation of this file.
1 import re
2 
3 import pytest
4 
5 import env # noqa: F401
6 from pybind11_tests import numpy_dtypes as m
7 
8 np = pytest.importorskip("numpy")
9 
10 
11 @pytest.fixture(scope="module")
13  ld = np.dtype("longdouble")
14  return np.dtype(
15  {
16  "names": ["bool_", "uint_", "float_", "ldbl_"],
17  "formats": ["?", "u4", "f4", f"f{ld.itemsize}"],
18  "offsets": [0, 4, 8, (16 if ld.alignment > 4 else 12)],
19  }
20  )
21 
22 
23 @pytest.fixture(scope="module")
25  return np.dtype([("bool_", "?"), ("uint_", "u4"), ("float_", "f4"), ("ldbl_", "g")])
26 
27 
28 def dt_fmt():
29  from sys import byteorder
30 
31  e = "<" if byteorder == "little" else ">"
32  return (
33  "{{'names':['bool_','uint_','float_','ldbl_'],"
34  "'formats':['?','" + e + "u4','" + e + "f4','" + e + "f{}'],"
35  "'offsets':[0,4,8,{}],'itemsize':{}}}"
36  )
37 
38 
40  ld = np.dtype("longdouble")
41  simple_ld_off = 12 + 4 * (ld.alignment > 4)
42  return dt_fmt().format(ld.itemsize, simple_ld_off, simple_ld_off + ld.itemsize)
43 
44 
46  from sys import byteorder
47 
48  return "[('bool_','?'),('uint_','{e}u4'),('float_','{e}f4'),('ldbl_','{e}f{}')]".format(
49  np.dtype("longdouble").itemsize, e="<" if byteorder == "little" else ">"
50  )
51 
52 
54  return (
55  12
56  + 4 * (np.dtype("uint64").alignment > 4)
57  + 8
58  + 8 * (np.dtype("longdouble").alignment > 8)
59  )
60 
61 
63  ld = np.dtype("longdouble")
64  partial_ld_off = partial_ld_offset()
65  partial_size = partial_ld_off + ld.itemsize
66  partial_end_padding = partial_size % np.dtype("uint64").alignment
67  return dt_fmt().format(
68  ld.itemsize, partial_ld_off, partial_size + partial_end_padding
69  )
70 
71 
73  ld = np.dtype("longdouble")
74  partial_nested_off = 8 + 8 * (ld.alignment > 8)
75  partial_ld_off = partial_ld_offset()
76  partial_size = partial_ld_off + ld.itemsize
77  partial_end_padding = partial_size % np.dtype("uint64").alignment
78  partial_nested_size = partial_nested_off * 2 + partial_size + partial_end_padding
79  return "{{'names':['a'],'formats':[{}],'offsets':[{}],'itemsize':{}}}".format(
80  partial_dtype_fmt(), partial_nested_off, partial_nested_size
81  )
82 
83 
84 def assert_equal(actual, expected_data, expected_dtype):
85  np.testing.assert_equal(actual, np.array(expected_data, dtype=expected_dtype))
86 
87 
89  with pytest.raises(RuntimeError) as excinfo:
90  m.get_format_unbound()
91  assert re.match(
92  "^NumPy type info missing for .*UnboundStruct.*$", str(excinfo.value)
93  )
94 
95  ld = np.dtype("longdouble")
96  ldbl_fmt = ("4x" if ld.alignment > 4 else "") + ld.char
97  ss_fmt = "^T{?:bool_:3xI:uint_:f:float_:" + ldbl_fmt + ":ldbl_:}"
98  dbl = np.dtype("double")
99  end_padding = ld.itemsize % np.dtype("uint64").alignment
100  partial_fmt = (
101  "^T{?:bool_:3xI:uint_:f:float_:"
102  + str(4 * (dbl.alignment > 4) + dbl.itemsize + 8 * (ld.alignment > 8))
103  + "xg:ldbl_:"
104  + (str(end_padding) + "x}" if end_padding > 0 else "}")
105  )
106  nested_extra = str(max(8, ld.alignment))
107  assert m.print_format_descriptors() == [
108  ss_fmt,
109  "^T{?:bool_:I:uint_:f:float_:g:ldbl_:}",
110  "^T{" + ss_fmt + ":a:^T{?:bool_:I:uint_:f:float_:g:ldbl_:}:b:}",
111  partial_fmt,
112  "^T{" + nested_extra + "x" + partial_fmt + ":a:" + nested_extra + "x}",
113  "^T{3s:a:3s:b:}",
114  "^T{(3)4s:a:(2)i:b:(3)B:c:1x(4, 2)f:d:}",
115  "^T{q:e1:B:e2:}",
116  "^T{Zf:cflt:Zd:cdbl:}",
117  ]
118 
119 
120 def test_dtype(simple_dtype):
121  from sys import byteorder
122 
123  e = "<" if byteorder == "little" else ">"
124 
125  assert [x.replace(" ", "") for x in m.print_dtypes()] == [
128  f"[('a',{simple_dtype_fmt()}),('b',{packed_dtype_fmt()})]",
131  "[('a','S3'),('b','S3')]",
132  (
133  "{{'names':['a','b','c','d'],"
134  + "'formats':[('S4',(3,)),('"
135  + e
136  + "i4',(2,)),('u1',(3,)),('"
137  + e
138  + "f4',(4,2))],"
139  + "'offsets':[0,12,20,24],'itemsize':56}}"
140  ).format(e=e),
141  "[('e1','" + e + "i8'),('e2','u1')]",
142  "[('x','i1'),('y','" + e + "u8')]",
143  "[('cflt','" + e + "c8'),('cdbl','" + e + "c16')]",
144  ]
145 
146  d1 = np.dtype(
147  {
148  "names": ["a", "b"],
149  "formats": ["int32", "float64"],
150  "offsets": [1, 10],
151  "itemsize": 20,
152  }
153  )
154  d2 = np.dtype([("a", "i4"), ("b", "f4")])
155  assert m.test_dtype_ctors() == [
156  np.dtype("int32"),
157  np.dtype("float64"),
158  np.dtype("bool"),
159  d1,
160  d1,
161  np.dtype("uint32"),
162  d2,
163  np.dtype("d"),
164  ]
165 
166  assert m.test_dtype_methods() == [
167  np.dtype("int32"),
168  simple_dtype,
169  False,
170  True,
171  np.dtype("int32").itemsize,
172  simple_dtype.itemsize,
173  ]
174 
175  assert m.trailing_padding_dtype() == m.buffer_to_dtype(
176  np.zeros(1, m.trailing_padding_dtype())
177  )
178 
179  expected_chars = "bhilqBHILQefdgFDG?MmO"
180  assert m.test_dtype_kind() == list("iiiiiuuuuuffffcccbMmO")
181  assert m.test_dtype_char_() == list(expected_chars)
182  assert m.test_dtype_num() == [np.dtype(ch).num for ch in expected_chars]
183  assert m.test_dtype_byteorder() == [np.dtype(ch).byteorder for ch in expected_chars]
184  assert m.test_dtype_alignment() == [np.dtype(ch).alignment for ch in expected_chars]
185  assert m.test_dtype_flags() == [chr(np.dtype(ch).flags) for ch in expected_chars]
186 
187 
188 def test_recarray(simple_dtype, packed_dtype):
189  elements = [(False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)]
190 
191  for func, dtype in [
192  (m.create_rec_simple, simple_dtype),
193  (m.create_rec_packed, packed_dtype),
194  ]:
195  arr = func(0)
196  assert arr.dtype == dtype
197  assert_equal(arr, [], simple_dtype)
198  assert_equal(arr, [], packed_dtype)
199 
200  arr = func(3)
201  assert arr.dtype == dtype
202  assert_equal(arr, elements, simple_dtype)
203  assert_equal(arr, elements, packed_dtype)
204 
205  # Show what recarray's look like in NumPy.
206  assert type(arr[0]) == np.void
207  assert type(arr[0].item()) == tuple
208 
209  if dtype == simple_dtype:
210  assert m.print_rec_simple(arr) == [
211  "s:0,0,0,-0",
212  "s:1,1,1.5,-2.5",
213  "s:0,2,3,-5",
214  ]
215  else:
216  assert m.print_rec_packed(arr) == [
217  "p:0,0,0,-0",
218  "p:1,1,1.5,-2.5",
219  "p:0,2,3,-5",
220  ]
221 
222  nested_dtype = np.dtype([("a", simple_dtype), ("b", packed_dtype)])
223 
224  arr = m.create_rec_nested(0)
225  assert arr.dtype == nested_dtype
226  assert_equal(arr, [], nested_dtype)
227 
228  arr = m.create_rec_nested(3)
229  assert arr.dtype == nested_dtype
230  assert_equal(
231  arr,
232  [
233  ((False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5)),
234  ((True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)),
235  ((False, 2, 3.0, -5.0), (True, 3, 4.5, -7.5)),
236  ],
237  nested_dtype,
238  )
239  assert m.print_rec_nested(arr) == [
240  "n:a=s:0,0,0,-0;b=p:1,1,1.5,-2.5",
241  "n:a=s:1,1,1.5,-2.5;b=p:0,2,3,-5",
242  "n:a=s:0,2,3,-5;b=p:1,3,4.5,-7.5",
243  ]
244 
245  arr = m.create_rec_partial(3)
246  assert str(arr.dtype).replace(" ", "") == partial_dtype_fmt()
247  partial_dtype = arr.dtype
248  assert "" not in arr.dtype.fields
249  assert partial_dtype.itemsize > simple_dtype.itemsize
250  assert_equal(arr, elements, simple_dtype)
251  assert_equal(arr, elements, packed_dtype)
252 
253  arr = m.create_rec_partial_nested(3)
254  assert str(arr.dtype).replace(" ", "") == partial_nested_fmt()
255  assert "" not in arr.dtype.fields
256  assert "" not in arr.dtype.fields["a"][0].fields
257  assert arr.dtype.itemsize > partial_dtype.itemsize
258  np.testing.assert_equal(arr["a"], m.create_rec_partial(3))
259 
260 
262  data = np.arange(1, 7, dtype="int32")
263  for i in range(8):
264  np.testing.assert_array_equal(m.test_array_ctors(10 + i), data.reshape((3, 2)))
265  np.testing.assert_array_equal(m.test_array_ctors(20 + i), data.reshape((3, 2)))
266  for i in range(5):
267  np.testing.assert_array_equal(m.test_array_ctors(30 + i), data)
268  np.testing.assert_array_equal(m.test_array_ctors(40 + i), data)
269 
270 
272  arr = m.create_string_array(True)
273  assert str(arr.dtype) == "[('a', 'S3'), ('b', 'S3')]"
274  assert m.print_string_array(arr) == [
275  "a='',b=''",
276  "a='a',b='a'",
277  "a='ab',b='ab'",
278  "a='abc',b='abc'",
279  ]
280  dtype = arr.dtype
281  assert arr["a"].tolist() == [b"", b"a", b"ab", b"abc"]
282  assert arr["b"].tolist() == [b"", b"a", b"ab", b"abc"]
283  arr = m.create_string_array(False)
284  assert dtype == arr.dtype
285 
286 
288  from sys import byteorder
289 
290  e = "<" if byteorder == "little" else ">"
291 
292  arr = m.create_array_array(3)
293  assert str(arr.dtype).replace(" ", "") == (
294  "{{'names':['a','b','c','d'],"
295  + "'formats':[('S4',(3,)),('"
296  + e
297  + "i4',(2,)),('u1',(3,)),('{e}f4',(4,2))],"
298  + "'offsets':[0,12,20,24],'itemsize':56}}"
299  ).format(e=e)
300  assert m.print_array_array(arr) == [
301  "a={{A,B,C,D},{K,L,M,N},{U,V,W,X}},b={0,1},"
302  + "c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}",
303  "a={{W,X,Y,Z},{G,H,I,J},{Q,R,S,T}},b={1000,1001},"
304  + "c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}",
305  "a={{S,T,U,V},{C,D,E,F},{M,N,O,P}},b={2000,2001},"
306  + "c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}",
307  ]
308  assert arr["a"].tolist() == [
309  [b"ABCD", b"KLMN", b"UVWX"],
310  [b"WXYZ", b"GHIJ", b"QRST"],
311  [b"STUV", b"CDEF", b"MNOP"],
312  ]
313  assert arr["b"].tolist() == [[0, 1], [1000, 1001], [2000, 2001]]
314  assert m.create_array_array(0).dtype == arr.dtype
315 
316 
318  from sys import byteorder
319 
320  e = "<" if byteorder == "little" else ">"
321 
322  arr = m.create_enum_array(3)
323  dtype = arr.dtype
324  assert dtype == np.dtype([("e1", e + "i8"), ("e2", "u1")])
325  assert m.print_enum_array(arr) == ["e1=A,e2=X", "e1=B,e2=Y", "e1=A,e2=X"]
326  assert arr["e1"].tolist() == [-1, 1, -1]
327  assert arr["e2"].tolist() == [1, 2, 1]
328  assert m.create_enum_array(0).dtype == dtype
329 
330 
332  from sys import byteorder
333 
334  e = "<" if byteorder == "little" else ">"
335 
336  arr = m.create_complex_array(3)
337  dtype = arr.dtype
338  assert dtype == np.dtype([("cflt", e + "c8"), ("cdbl", e + "c16")])
339  assert m.print_complex_array(arr) == [
340  "c:(0,0.25),(0.5,0.75)",
341  "c:(1,1.25),(1.5,1.75)",
342  "c:(2,2.25),(2.5,2.75)",
343  ]
344  assert arr["cflt"].tolist() == [0.0 + 0.25j, 1.0 + 1.25j, 2.0 + 2.25j]
345  assert arr["cdbl"].tolist() == [0.5 + 0.75j, 1.5 + 1.75j, 2.5 + 2.75j]
346  assert m.create_complex_array(0).dtype == dtype
347 
348 
349 def test_signature(doc):
350  assert (
351  doc(m.create_rec_nested)
352  == "create_rec_nested(arg0: int) -> numpy.ndarray[NestedStruct]"
353  )
354 
355 
357  n = 3
358  arrays = [
359  m.create_rec_simple(n),
360  m.create_rec_packed(n),
361  m.create_rec_nested(n),
362  m.create_enum_array(n),
363  ]
364  funcs = [m.f_simple, m.f_packed, m.f_nested]
365 
366  for i, func in enumerate(funcs):
367  for j, arr in enumerate(arrays):
368  if i == j and i < 2:
369  assert [func(arr[k]) for k in range(n)] == [k * 10 for k in range(n)]
370  else:
371  with pytest.raises(TypeError) as excinfo:
372  func(arr[0])
373  assert "incompatible function arguments" in str(excinfo.value)
374 
375 
377  n = 3
378  array = m.create_rec_simple(n)
379  values = m.f_simple_vectorized(array)
380  np.testing.assert_array_equal(values, [0, 10, 20])
381  array_2 = m.f_simple_pass_thru_vectorized(array)
382  np.testing.assert_array_equal(array, array_2)
383 
384 
386  s = m.SimpleStruct()
387  assert s.astuple() == (False, 0, 0.0, 0.0)
388  assert m.SimpleStruct.fromtuple(s.astuple()).astuple() == s.astuple()
389 
390  s.uint_ = 2
391  assert m.f_simple(s) == 20
392 
393  # Try as recarray of shape==(1,).
394  s_recarray = np.array([(False, 2, 0.0, 0.0)], dtype=simple_dtype)
395  # Show that this will work for vectorized case.
396  np.testing.assert_array_equal(m.f_simple_vectorized(s_recarray), [20])
397 
398  # Show as a scalar that inherits from np.generic.
399  s_scalar = s_recarray[0]
400  assert isinstance(s_scalar, np.void)
401  assert m.f_simple(s_scalar) == 20
402 
403  # Show that an *array* scalar (np.ndarray.shape == ()) does not convert.
404  # More specifically, conversion to SimpleStruct is not implicit.
405  s_recarray_scalar = s_recarray.reshape(())
406  assert isinstance(s_recarray_scalar, np.ndarray)
407  assert s_recarray_scalar.dtype == simple_dtype
408  with pytest.raises(TypeError) as excinfo:
409  m.f_simple(s_recarray_scalar)
410  assert "incompatible function arguments" in str(excinfo.value)
411  # Explicitly convert to m.SimpleStruct.
412  assert m.f_simple(m.SimpleStruct.fromtuple(s_recarray_scalar.item())) == 20
413 
414  # Show that an array of dtype=object does *not* convert.
415  s_array_object = np.array([s])
416  assert s_array_object.dtype == object
417  with pytest.raises(TypeError) as excinfo:
418  m.f_simple_vectorized(s_array_object)
419  assert "incompatible function arguments" in str(excinfo.value)
420  # Explicitly convert to `np.array(..., dtype=simple_dtype)`
421  s_array = np.array([s.astuple()], dtype=simple_dtype)
422  np.testing.assert_array_equal(m.f_simple_vectorized(s_array), [20])
423 
424 
426  with pytest.raises(RuntimeError) as excinfo:
427  m.register_dtype()
428  assert "dtype is already registered" in str(excinfo.value)
429 
430 
431 @pytest.mark.xfail("env.PYPY")
433  from sys import getrefcount
434 
435  fmt = "f4"
436  pytest.gc_collect()
437  start = getrefcount(fmt)
438  d = m.dtype_wrapper(fmt)
439  assert d is np.dtype("f4")
440  del d
441  pytest.gc_collect()
442  assert getrefcount(fmt) == start
443 
444 
446  assert all(m.compare_buffer_info())
#define max(a, b)
Definition: datatypes.h:20
static const Eigen::internal::all_t all
def test_cls_and_dtype_conversion(simple_dtype)
Annotation for documentation.
Definition: attr.h:42
bool isinstance(handle obj)
Definition: pytypes.h:700
def test_dtype(simple_dtype)
Definition: pytypes.h:1403
Definition: pytypes.h:1979
def assert_equal(actual, expected_data, expected_dtype)
Double_ range(const Point2_ &p, const Point2_ &q)
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
Definition: pytypes.h:1370
def test_recarray(simple_dtype, packed_dtype)


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:37:46