test_eigen_matrix.py
Go to the documentation of this file.
1 from __future__ import annotations
2 
3 import pytest
4 
5 from pybind11_tests import ConstructorStats
6 
7 np = pytest.importorskip("numpy")
8 m = pytest.importorskip("pybind11_tests.eigen_matrix")
9 
10 
11 ref = np.array(
12  [
13  [0.0, 3, 0, 0, 0, 11],
14  [22, 0, 0, 0, 17, 11],
15  [7, 5, 0, 1, 0, 11],
16  [0, 0, 0, 0, 0, 11],
17  [0, 0, 14, 0, 8, 11],
18  ]
19 )
20 
21 
23  np.testing.assert_array_equal(mat, ref)
24 
25 
26 def assert_sparse_equal_ref(sparse_mat):
27  assert_equal_ref(sparse_mat.toarray())
28 
29 
30 def test_fixed():
31  assert_equal_ref(m.fixed_c())
32  assert_equal_ref(m.fixed_r())
33  assert_equal_ref(m.fixed_copy_r(m.fixed_r()))
34  assert_equal_ref(m.fixed_copy_c(m.fixed_c()))
35  assert_equal_ref(m.fixed_copy_r(m.fixed_c()))
36  assert_equal_ref(m.fixed_copy_c(m.fixed_r()))
37 
38 
39 def test_dense():
40  assert_equal_ref(m.dense_r())
41  assert_equal_ref(m.dense_c())
42  assert_equal_ref(m.dense_copy_r(m.dense_r()))
43  assert_equal_ref(m.dense_copy_c(m.dense_c()))
44  assert_equal_ref(m.dense_copy_r(m.dense_c()))
45  assert_equal_ref(m.dense_copy_c(m.dense_r()))
46 
47 
49  ref2 = np.array([[0.0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]])
50  np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2), ref2)
51  np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2), ref2)
52  np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2[:, 1]), ref2[:, [1]])
53  np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2[0, :]), ref2[[0], :])
54  np.testing.assert_array_equal(
55  m.partial_copy_four_rm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]
56  )
57  np.testing.assert_array_equal(
58  m.partial_copy_four_rm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]
59  )
60 
61  np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2), ref2)
62  np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2), ref2)
63  np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2[:, 1]), ref2[:, [1]])
64  np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2[0, :]), ref2[[0], :])
65  np.testing.assert_array_equal(
66  m.partial_copy_four_cm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]
67  )
68  np.testing.assert_array_equal(
69  m.partial_copy_four_cm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]
70  )
71 
72  # TypeError should be raise for a shape mismatch
73  functions = [
74  m.partial_copy_four_rm_r,
75  m.partial_copy_four_rm_c,
76  m.partial_copy_four_cm_r,
77  m.partial_copy_four_cm_c,
78  ]
79  matrix_with_wrong_shape = [[1, 2], [3, 4]]
80  for f in functions:
81  with pytest.raises(TypeError) as excinfo:
82  f(matrix_with_wrong_shape)
83  assert "incompatible function arguments" in str(excinfo.value)
84 
85 
87  zr = np.arange(30, dtype="float32").reshape(5, 6) # row-major
88  zc = zr.reshape(6, 5).transpose() # column-major
89 
90  m.fixed_mutator_r(zr)
91  m.fixed_mutator_c(zc)
92  m.fixed_mutator_a(zr)
93  m.fixed_mutator_a(zc)
94  with pytest.raises(TypeError) as excinfo:
95  m.fixed_mutator_r(zc)
96  assert (
97  "(arg0: numpy.ndarray[numpy.float32[5, 6],"
98  " flags.writeable, flags.c_contiguous]) -> None" in str(excinfo.value)
99  )
100  with pytest.raises(TypeError) as excinfo:
101  m.fixed_mutator_c(zr)
102  assert (
103  "(arg0: numpy.ndarray[numpy.float32[5, 6],"
104  " flags.writeable, flags.f_contiguous]) -> None" in str(excinfo.value)
105  )
106  with pytest.raises(TypeError) as excinfo:
107  m.fixed_mutator_a(np.array([[1, 2], [3, 4]], dtype="float32"))
108  assert "(arg0: numpy.ndarray[numpy.float32[5, 6], flags.writeable]) -> None" in str(
109  excinfo.value
110  )
111  zr.flags.writeable = False
112  with pytest.raises(TypeError):
113  m.fixed_mutator_r(zr)
114  with pytest.raises(TypeError):
115  m.fixed_mutator_a(zr)
116 
117 
119  assert m.cpp_copy(m.fixed_r()) == 22.0
120  assert m.cpp_copy(m.fixed_c()) == 22.0
121  z = np.array([[5.0, 6], [7, 8]])
122  assert m.cpp_copy(z) == 7.0
123  assert m.cpp_copy(m.get_cm_ref()) == 21.0
124  assert m.cpp_copy(m.get_rm_ref()) == 21.0
125  assert m.cpp_ref_c(m.get_cm_ref()) == 21.0
126  assert m.cpp_ref_r(m.get_rm_ref()) == 21.0
127  with pytest.raises(RuntimeError) as excinfo:
128  # Can't reference m.fixed_c: it contains floats, m.cpp_ref_any wants doubles
129  m.cpp_ref_any(m.fixed_c())
130  assert "Unable to cast Python instance" in str(excinfo.value)
131  with pytest.raises(RuntimeError) as excinfo:
132  # Can't reference m.fixed_r: it contains floats, m.cpp_ref_any wants doubles
133  m.cpp_ref_any(m.fixed_r())
134  assert "Unable to cast Python instance" in str(excinfo.value)
135  assert m.cpp_ref_any(m.ReturnTester.create()) == 1.0
136 
137  assert m.cpp_ref_any(m.get_cm_ref()) == 21.0
138  assert m.cpp_ref_any(m.get_cm_ref()) == 21.0
139 
140 
142  z = np.full((5, 6), 42.0)
143  z.flags.writeable = False
144  np.testing.assert_array_equal(z, m.fixed_copy_r(z))
145  np.testing.assert_array_equal(m.fixed_r_const(), m.fixed_r())
146  assert not m.fixed_r_const().flags.writeable
147  np.testing.assert_array_equal(m.fixed_copy_r(m.fixed_r_const()), m.fixed_r_const())
148 
149 
151  counting_mat = np.arange(9.0, dtype=np.float32).reshape((3, 3))
152  second_row = counting_mat[1, :]
153  second_col = counting_mat[:, 1]
154  np.testing.assert_array_equal(m.double_row(second_row), 2.0 * second_row)
155  np.testing.assert_array_equal(m.double_col(second_row), 2.0 * second_row)
156  np.testing.assert_array_equal(m.double_complex(second_row), 2.0 * second_row)
157  np.testing.assert_array_equal(m.double_row(second_col), 2.0 * second_col)
158  np.testing.assert_array_equal(m.double_col(second_col), 2.0 * second_col)
159  np.testing.assert_array_equal(m.double_complex(second_col), 2.0 * second_col)
160 
161  counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
162  slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
163  for ref_mat in slices:
164  np.testing.assert_array_equal(m.double_mat_cm(ref_mat), 2.0 * ref_mat)
165  np.testing.assert_array_equal(m.double_mat_rm(ref_mat), 2.0 * ref_mat)
166 
167  # Mutator:
168  m.double_threer(second_row)
169  m.double_threec(second_col)
170  np.testing.assert_array_equal(counting_mat, [[0.0, 2, 2], [6, 16, 10], [6, 14, 8]])
171 
172 
174  """Eigen doesn't support (as of yet) negative strides. When a function takes an Eigen matrix by
175  copy or const reference, we can pass a numpy array that has negative strides. Otherwise, an
176  exception will be thrown as Eigen will not be able to map the numpy array."""
177 
178  counting_mat = np.arange(9.0, dtype=np.float32).reshape((3, 3))
179  counting_mat = counting_mat[::-1, ::-1]
180  second_row = counting_mat[1, :]
181  second_col = counting_mat[:, 1]
182  np.testing.assert_array_equal(m.double_row(second_row), 2.0 * second_row)
183  np.testing.assert_array_equal(m.double_col(second_row), 2.0 * second_row)
184  np.testing.assert_array_equal(m.double_complex(second_row), 2.0 * second_row)
185  np.testing.assert_array_equal(m.double_row(second_col), 2.0 * second_col)
186  np.testing.assert_array_equal(m.double_col(second_col), 2.0 * second_col)
187  np.testing.assert_array_equal(m.double_complex(second_col), 2.0 * second_col)
188 
189  counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
190  counting_3d = counting_3d[::-1, ::-1, ::-1]
191  slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
192  for ref_mat in slices:
193  np.testing.assert_array_equal(m.double_mat_cm(ref_mat), 2.0 * ref_mat)
194  np.testing.assert_array_equal(m.double_mat_rm(ref_mat), 2.0 * ref_mat)
195 
196  # Mutator:
197  with pytest.raises(TypeError) as excinfo:
198  m.double_threer(second_row)
199  assert (
200  msg(excinfo.value)
201  == """
202  double_threer(): incompatible function arguments. The following argument types are supported:
203  1. (arg0: numpy.ndarray[numpy.float32[1, 3], flags.writeable]) -> None
204 
205  Invoked with: """
206  + repr(np.array([5.0, 4.0, 3.0], dtype="float32"))
207  )
208 
209  with pytest.raises(TypeError) as excinfo:
210  m.double_threec(second_col)
211  assert (
212  msg(excinfo.value)
213  == """
214  double_threec(): incompatible function arguments. The following argument types are supported:
215  1. (arg0: numpy.ndarray[numpy.float32[3, 1], flags.writeable]) -> None
216 
217  Invoked with: """
218  + repr(np.array([7.0, 4.0, 1.0], dtype="float32"))
219  )
220 
221 
223  with pytest.raises(RuntimeError) as excinfo:
224  m.block(ref, 0, 0, 0, 0)
225  assert str(excinfo.value) == "type_caster for Eigen::Ref made a copy."
226 
227 
229  assert np.all(m.diagonal(ref) == ref.diagonal())
230  assert np.all(m.diagonal_1(ref) == ref.diagonal(1))
231  for i in range(-5, 7):
232  assert np.all(m.diagonal_n(ref, i) == ref.diagonal(i)), f"m.diagonal_n({i})"
233 
234  # Must be order="F", otherwise the type_caster will make a copy and
235  # m.block() will return a dangling reference (heap-use-after-free).
236  rof = np.asarray(ref, order="F")
237  assert np.all(m.block(rof, 2, 1, 3, 3) == rof[2:5, 1:4])
238  assert np.all(m.block(rof, 1, 4, 4, 2) == rof[1:, 4:])
239  assert np.all(m.block(rof, 1, 4, 3, 2) == rof[1:4, 4:])
240 
241 
243  chols = [m.cholesky1, m.cholesky2, m.cholesky3, m.cholesky4]
244  for i, chol in enumerate(chols, start=1):
245  mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
246  assert np.all(
247  mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])
248  ), f"cholesky{i}"
249 
250 
251 def assign_both(a1, a2, r, c, v):
252  a1[r, c] = v
253  a2[r, c] = v
254 
255 
256 def array_copy_but_one(a, r, c, v):
257  z = np.array(a, copy=True)
258  z[r, c] = v
259  return z
260 
261 
263  """Tests various ways of returning references and non-referencing copies"""
264 
265  primary = np.ones((10, 10))
266  a = m.ReturnTester()
267  a_get1 = a.get()
268  assert not a_get1.flags.owndata
269  assert a_get1.flags.writeable
270  assign_both(a_get1, primary, 3, 3, 5)
271  a_get2 = a.get_ptr()
272  assert not a_get2.flags.owndata
273  assert a_get2.flags.writeable
274  assign_both(a_get1, primary, 2, 3, 6)
275 
276  a_view1 = a.view()
277  assert not a_view1.flags.owndata
278  assert not a_view1.flags.writeable
279  with pytest.raises(ValueError):
280  a_view1[2, 3] = 4
281  a_view2 = a.view_ptr()
282  assert not a_view2.flags.owndata
283  assert not a_view2.flags.writeable
284  with pytest.raises(ValueError):
285  a_view2[2, 3] = 4
286 
287  a_copy1 = a.copy_get()
288  assert a_copy1.flags.owndata
289  assert a_copy1.flags.writeable
290  np.testing.assert_array_equal(a_copy1, primary)
291  a_copy1[7, 7] = -44 # Shouldn't affect anything else
292  c1want = array_copy_but_one(primary, 7, 7, -44)
293  a_copy2 = a.copy_view()
294  assert a_copy2.flags.owndata
295  assert a_copy2.flags.writeable
296  np.testing.assert_array_equal(a_copy2, primary)
297  a_copy2[4, 4] = -22 # Shouldn't affect anything else
298  c2want = array_copy_but_one(primary, 4, 4, -22)
299 
300  a_ref1 = a.ref()
301  assert not a_ref1.flags.owndata
302  assert a_ref1.flags.writeable
303  assign_both(a_ref1, primary, 1, 1, 15)
304  a_ref2 = a.ref_const()
305  assert not a_ref2.flags.owndata
306  assert not a_ref2.flags.writeable
307  with pytest.raises(ValueError):
308  a_ref2[5, 5] = 33
309  a_ref3 = a.ref_safe()
310  assert not a_ref3.flags.owndata
311  assert a_ref3.flags.writeable
312  assign_both(a_ref3, primary, 0, 7, 99)
313  a_ref4 = a.ref_const_safe()
314  assert not a_ref4.flags.owndata
315  assert not a_ref4.flags.writeable
316  with pytest.raises(ValueError):
317  a_ref4[7, 0] = 987654321
318 
319  a_copy3 = a.copy_ref()
320  assert a_copy3.flags.owndata
321  assert a_copy3.flags.writeable
322  np.testing.assert_array_equal(a_copy3, primary)
323  a_copy3[8, 1] = 11
324  c3want = array_copy_but_one(primary, 8, 1, 11)
325  a_copy4 = a.copy_ref_const()
326  assert a_copy4.flags.owndata
327  assert a_copy4.flags.writeable
328  np.testing.assert_array_equal(a_copy4, primary)
329  a_copy4[8, 4] = 88
330  c4want = array_copy_but_one(primary, 8, 4, 88)
331 
332  a_block1 = a.block(3, 3, 2, 2)
333  assert not a_block1.flags.owndata
334  assert a_block1.flags.writeable
335  a_block1[0, 0] = 55
336  primary[3, 3] = 55
337  a_block2 = a.block_safe(2, 2, 3, 2)
338  assert not a_block2.flags.owndata
339  assert a_block2.flags.writeable
340  a_block2[2, 1] = -123
341  primary[4, 3] = -123
342  a_block3 = a.block_const(6, 7, 4, 3)
343  assert not a_block3.flags.owndata
344  assert not a_block3.flags.writeable
345  with pytest.raises(ValueError):
346  a_block3[2, 2] = -44444
347 
348  a_copy5 = a.copy_block(2, 2, 2, 3)
349  assert a_copy5.flags.owndata
350  assert a_copy5.flags.writeable
351  np.testing.assert_array_equal(a_copy5, primary[2:4, 2:5])
352  a_copy5[1, 1] = 777
353  c5want = array_copy_but_one(primary[2:4, 2:5], 1, 1, 777)
354 
355  a_corn1 = a.corners()
356  assert not a_corn1.flags.owndata
357  assert a_corn1.flags.writeable
358  a_corn1 *= 50
359  a_corn1[1, 1] = 999
360  primary[0, 0] = 50
361  primary[0, 9] = 50
362  primary[9, 0] = 50
363  primary[9, 9] = 999
364  a_corn2 = a.corners_const()
365  assert not a_corn2.flags.owndata
366  assert not a_corn2.flags.writeable
367  with pytest.raises(ValueError):
368  a_corn2[1, 0] = 51
369 
370  # All of the changes made all the way along should be visible everywhere
371  # now (except for the copies, of course)
372  np.testing.assert_array_equal(a_get1, primary)
373  np.testing.assert_array_equal(a_get2, primary)
374  np.testing.assert_array_equal(a_view1, primary)
375  np.testing.assert_array_equal(a_view2, primary)
376  np.testing.assert_array_equal(a_ref1, primary)
377  np.testing.assert_array_equal(a_ref2, primary)
378  np.testing.assert_array_equal(a_ref3, primary)
379  np.testing.assert_array_equal(a_ref4, primary)
380  np.testing.assert_array_equal(a_block1, primary[3:5, 3:5])
381  np.testing.assert_array_equal(a_block2, primary[2:5, 2:4])
382  np.testing.assert_array_equal(a_block3, primary[6:10, 7:10])
383  np.testing.assert_array_equal(
384  a_corn1, primary[0 :: primary.shape[0] - 1, 0 :: primary.shape[1] - 1]
385  )
386  np.testing.assert_array_equal(
387  a_corn2, primary[0 :: primary.shape[0] - 1, 0 :: primary.shape[1] - 1]
388  )
389 
390  np.testing.assert_array_equal(a_copy1, c1want)
391  np.testing.assert_array_equal(a_copy2, c2want)
392  np.testing.assert_array_equal(a_copy3, c3want)
393  np.testing.assert_array_equal(a_copy4, c4want)
394  np.testing.assert_array_equal(a_copy5, c5want)
395 
396 
397 def assert_keeps_alive(cl, method, *args):
398  cstats = ConstructorStats.get(cl)
399  start_with = cstats.alive()
400  a = cl()
401  assert cstats.alive() == start_with + 1
402  z = method(a, *args)
403  assert cstats.alive() == start_with + 1
404  del a
405  # Here's the keep alive in action:
406  assert cstats.alive() == start_with + 1
407  del z
408  # Keep alive should have expired:
409  assert cstats.alive() == start_with
410 
411 
413  a = m.ReturnTester()
414  cstats = ConstructorStats.get(m.ReturnTester)
415  assert cstats.alive() == 1
416  unsafe = [a.ref(), a.ref_const(), a.block(1, 2, 3, 4)]
417  copies = [
418  a.copy_get(),
419  a.copy_view(),
420  a.copy_ref(),
421  a.copy_ref_const(),
422  a.copy_block(4, 3, 2, 1),
423  ]
424  del a
425  assert cstats.alive() == 0
426  del unsafe
427  del copies
428 
429  for meth in [
430  m.ReturnTester.get,
431  m.ReturnTester.get_ptr,
432  m.ReturnTester.view,
433  m.ReturnTester.view_ptr,
434  m.ReturnTester.ref_safe,
435  m.ReturnTester.ref_const_safe,
436  m.ReturnTester.corners,
437  m.ReturnTester.corners_const,
438  ]:
439  assert_keeps_alive(m.ReturnTester, meth)
440 
441  for meth in [m.ReturnTester.block_safe, m.ReturnTester.block_const]:
442  assert_keeps_alive(m.ReturnTester, meth, 4, 3, 2, 1)
443 
444 
446  """Tests Eigen's ability to mutate numpy values"""
447 
448  orig = np.array([[1.0, 2, 3], [4, 5, 6], [7, 8, 9]])
449  zr = np.array(orig)
450  zc = np.array(orig, order="F")
451  m.add_rm(zr, 1, 0, 100)
452  assert np.all(zr == np.array([[1.0, 2, 3], [104, 5, 6], [7, 8, 9]]))
453  m.add_cm(zc, 1, 0, 200)
454  assert np.all(zc == np.array([[1.0, 2, 3], [204, 5, 6], [7, 8, 9]]))
455 
456  m.add_any(zr, 1, 0, 20)
457  assert np.all(zr == np.array([[1.0, 2, 3], [124, 5, 6], [7, 8, 9]]))
458  m.add_any(zc, 1, 0, 10)
459  assert np.all(zc == np.array([[1.0, 2, 3], [214, 5, 6], [7, 8, 9]]))
460 
461  # Can't reference a col-major array with a row-major Ref, and vice versa:
462  with pytest.raises(TypeError):
463  m.add_rm(zc, 1, 0, 1)
464  with pytest.raises(TypeError):
465  m.add_cm(zr, 1, 0, 1)
466 
467  # Overloads:
468  m.add1(zr, 1, 0, -100)
469  m.add2(zr, 1, 0, -20)
470  assert np.all(zr == orig)
471  m.add1(zc, 1, 0, -200)
472  m.add2(zc, 1, 0, -10)
473  assert np.all(zc == orig)
474 
475  # a non-contiguous slice (this won't work on either the row- or
476  # column-contiguous refs, but should work for the any)
477  cornersr = zr[0::2, 0::2]
478  cornersc = zc[0::2, 0::2]
479 
480  assert np.all(cornersr == np.array([[1.0, 3], [7, 9]]))
481  assert np.all(cornersc == np.array([[1.0, 3], [7, 9]]))
482 
483  with pytest.raises(TypeError):
484  m.add_rm(cornersr, 0, 1, 25)
485  with pytest.raises(TypeError):
486  m.add_cm(cornersr, 0, 1, 25)
487  with pytest.raises(TypeError):
488  m.add_rm(cornersc, 0, 1, 25)
489  with pytest.raises(TypeError):
490  m.add_cm(cornersc, 0, 1, 25)
491  m.add_any(cornersr, 0, 1, 25)
492  m.add_any(cornersc, 0, 1, 44)
493  assert np.all(zr == np.array([[1.0, 2, 28], [4, 5, 6], [7, 8, 9]]))
494  assert np.all(zc == np.array([[1.0, 2, 47], [4, 5, 6], [7, 8, 9]]))
495 
496  # You shouldn't be allowed to pass a non-writeable array to a mutating Eigen method:
497  zro = zr[0:4, 0:4]
498  zro.flags.writeable = False
499  with pytest.raises(TypeError):
500  m.add_rm(zro, 0, 0, 0)
501  with pytest.raises(TypeError):
502  m.add_any(zro, 0, 0, 0)
503  with pytest.raises(TypeError):
504  m.add1(zro, 0, 0, 0)
505  with pytest.raises(TypeError):
506  m.add2(zro, 0, 0, 0)
507 
508  # integer array shouldn't be passable to a double-matrix-accepting mutating func:
509  zi = np.array([[1, 2], [3, 4]])
510  with pytest.raises(TypeError):
511  m.add_rm(zi)
512 
513 
515  """Tests numpy mutating Eigen matrices (for returned Eigen::Ref<...>s)"""
516 
517  m.reset_refs() # In case another test already changed it
518 
519  zc = m.get_cm_ref()
520  zcro = m.get_cm_const_ref()
521  zr = m.get_rm_ref()
522  zrro = m.get_rm_const_ref()
523 
524  assert [zc[1, 2], zcro[1, 2], zr[1, 2], zrro[1, 2]] == [23] * 4
525 
526  assert not zc.flags.owndata
527  assert zc.flags.writeable
528  assert not zr.flags.owndata
529  assert zr.flags.writeable
530  assert not zcro.flags.owndata
531  assert not zcro.flags.writeable
532  assert not zrro.flags.owndata
533  assert not zrro.flags.writeable
534 
535  zc[1, 2] = 99
536  expect = np.array([[11.0, 12, 13], [21, 22, 99], [31, 32, 33]])
537  # We should have just changed zc, of course, but also zcro and the original eigen matrix
538  assert np.all(zc == expect)
539  assert np.all(zcro == expect)
540  assert np.all(m.get_cm_ref() == expect)
541 
542  zr[1, 2] = 99
543  assert np.all(zr == expect)
544  assert np.all(zrro == expect)
545  assert np.all(m.get_rm_ref() == expect)
546 
547  # Make sure the readonly ones are numpy-readonly:
548  with pytest.raises(ValueError):
549  zcro[1, 2] = 6
550  with pytest.raises(ValueError):
551  zrro[1, 2] = 6
552 
553  # We should be able to explicitly copy like this (and since we're copying,
554  # the const should drop away)
555  y1 = np.array(m.get_cm_const_ref())
556 
557  assert y1.flags.owndata
558  assert y1.flags.writeable
559  # We should get copies of the eigen data, which was modified above:
560  assert y1[1, 2] == 99
561  y1[1, 2] += 12
562  assert y1[1, 2] == 111
563  assert zc[1, 2] == 99 # Make sure we aren't referencing the original
564 
565 
567  """Tests a complex chain of nested eigen/numpy references"""
568 
569  m.reset_refs() # In case another test already changed it
570 
571  z = m.get_cm_ref() # numpy -> eigen
572  z[0, 2] -= 3
573  z2 = m.incr_matrix(z, 1) # numpy -> eigen -> numpy -> eigen
574  z2[1, 1] += 6
575  z3 = m.incr_matrix(z, 2) # (numpy -> eigen)^3
576  z3[2, 2] += -5
577  z4 = m.incr_matrix(z, 3) # (numpy -> eigen)^4
578  z4[1, 1] -= 1
579  z5 = m.incr_matrix(z, 4) # (numpy -> eigen)^5
580  z5[0, 0] = 0
581  assert np.all(z == z2)
582  assert np.all(z == z3)
583  assert np.all(z == z4)
584  assert np.all(z == z5)
585  expect = np.array([[0.0, 22, 20], [31, 37, 33], [41, 42, 38]])
586  assert np.all(z == expect)
587 
588  y = np.array(range(100), dtype="float64").reshape(10, 10)
589  y2 = m.incr_matrix_any(y, 10) # np -> eigen -> np
590  y3 = m.incr_matrix_any(
591  y2[0::2, 0::2], -33
592  ) # np -> eigen -> np slice -> np -> eigen -> np
593  y4 = m.even_rows(y3) # numpy -> eigen slice -> (... y3)
594  y5 = m.even_cols(y4) # numpy -> eigen slice -> (... y4)
595  y6 = m.incr_matrix_any(y5, 1000) # numpy -> eigen -> (... y5)
596 
597  # Apply same mutations using just numpy:
598  yexpect = np.array(range(100), dtype="float64").reshape(10, 10)
599  yexpect += 10
600  yexpect[0::2, 0::2] -= 33
601  yexpect[0::4, 0::4] += 1000
602  assert np.all(y6 == yexpect[0::4, 0::4])
603  assert np.all(y5 == yexpect[0::4, 0::4])
604  assert np.all(y4 == yexpect[0::4, 0::2])
605  assert np.all(y3 == yexpect[0::2, 0::2])
606  assert np.all(y2 == yexpect)
607  assert np.all(y == yexpect)
608 
609 
611  # get_elem requires a column-contiguous matrix reference, but should be
612  # callable with other types of matrix (via copying):
613  int_matrix_colmajor = np.array(
614  [[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype="l", order="F"
615  )
616  dbl_matrix_colmajor = np.array(
617  int_matrix_colmajor, dtype="double", order="F", copy=True
618  )
619  int_matrix_rowmajor = np.array(int_matrix_colmajor, order="C", copy=True)
620  dbl_matrix_rowmajor = np.array(
621  int_matrix_rowmajor, dtype="double", order="C", copy=True
622  )
623 
624  # All should be callable via get_elem:
625  assert m.get_elem(int_matrix_colmajor) == 8
626  assert m.get_elem(dbl_matrix_colmajor) == 8
627  assert m.get_elem(int_matrix_rowmajor) == 8
628  assert m.get_elem(dbl_matrix_rowmajor) == 8
629 
630  # All but the second should fail with m.get_elem_nocopy:
631  with pytest.raises(TypeError) as excinfo:
632  m.get_elem_nocopy(int_matrix_colmajor)
633  assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
634  assert ", flags.f_contiguous" in str(excinfo.value)
635  assert m.get_elem_nocopy(dbl_matrix_colmajor) == 8
636  with pytest.raises(TypeError) as excinfo:
637  m.get_elem_nocopy(int_matrix_rowmajor)
638  assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
639  assert ", flags.f_contiguous" in str(excinfo.value)
640  with pytest.raises(TypeError) as excinfo:
641  m.get_elem_nocopy(dbl_matrix_rowmajor)
642  assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
643  assert ", flags.f_contiguous" in str(excinfo.value)
644 
645  # For the row-major test, we take a long matrix in row-major, so only the third is allowed:
646  with pytest.raises(TypeError) as excinfo:
647  m.get_elem_rm_nocopy(int_matrix_colmajor)
648  assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
649  excinfo.value
650  )
651  assert ", flags.c_contiguous" in str(excinfo.value)
652  with pytest.raises(TypeError) as excinfo:
653  m.get_elem_rm_nocopy(dbl_matrix_colmajor)
654  assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
655  excinfo.value
656  )
657  assert ", flags.c_contiguous" in str(excinfo.value)
658  assert m.get_elem_rm_nocopy(int_matrix_rowmajor) == 8
659  with pytest.raises(TypeError) as excinfo:
660  m.get_elem_rm_nocopy(dbl_matrix_rowmajor)
661  assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
662  excinfo.value
663  )
664  assert ", flags.c_contiguous" in str(excinfo.value)
665 
666 
668  """Ensure the lifetime of temporary arrays created by the `Ref` caster
669 
670  The `Ref` caster sometimes creates a copy which needs to stay alive. This needs to
671  happen both for directs casts (just the array) or indirectly (e.g. list of arrays).
672  """
673 
674  a = np.full(shape=10, fill_value=8, dtype=np.int8)
675  assert m.get_elem_direct(a) == 8
676 
677  list_of_a = [a]
678  assert m.get_elem_indirect(list_of_a) == 8
679 
680 
682  assert np.all(m.incr_diag(7) == np.diag([1.0, 2, 3, 4, 5, 6, 7]))
683 
684  asymm = np.array([[1.0, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
685  symm_lower = np.array(asymm)
686  symm_upper = np.array(asymm)
687  for i in range(4):
688  for j in range(i + 1, 4):
689  symm_lower[i, j] = symm_lower[j, i]
690  symm_upper[j, i] = symm_upper[i, j]
691 
692  assert np.all(m.symmetric_lower(asymm) == symm_lower)
693  assert np.all(m.symmetric_upper(asymm) == symm_upper)
694 
695 
697  assert (
698  doc(m.double_col)
699  == """
700  double_col(arg0: numpy.ndarray[numpy.float32[m, 1]]) -> numpy.ndarray[numpy.float32[m, 1]]
701  """
702  )
703  assert (
704  doc(m.double_row)
705  == """
706  double_row(arg0: numpy.ndarray[numpy.float32[1, n]]) -> numpy.ndarray[numpy.float32[1, n]]
707  """
708  )
709  assert doc(m.double_complex) == (
710  """
711  double_complex(arg0: numpy.ndarray[numpy.complex64[m, 1]])"""
712  """ -> numpy.ndarray[numpy.complex64[m, 1]]
713  """
714  )
715  assert doc(m.double_mat_rm) == (
716  """
717  double_mat_rm(arg0: numpy.ndarray[numpy.float32[m, n]])"""
718  """ -> numpy.ndarray[numpy.float32[m, n]]
719  """
720  )
721 
722 
723 def test_defaults(doc):
724  assert "\n" not in str(doc(m.defaults_mat))
725  assert "\n" not in str(doc(m.defaults_vec))
726 
727 
729  a = np.array([[1.0, 2], [3, 4], [5, 6]])
730  b = np.ones((2, 1))
731 
732  assert np.all(m.matrix_multiply(a, b) == np.array([[3.0], [7], [11]]))
733  assert np.all(m.matrix_multiply(A=a, B=b) == np.array([[3.0], [7], [11]]))
734  assert np.all(m.matrix_multiply(B=b, A=a) == np.array([[3.0], [7], [11]]))
735 
736  with pytest.raises(ValueError) as excinfo:
737  m.matrix_multiply(b, a)
738  assert str(excinfo.value) == "Nonconformable matrices!"
739 
740  with pytest.raises(ValueError) as excinfo:
741  m.matrix_multiply(A=b, B=a)
742  assert str(excinfo.value) == "Nonconformable matrices!"
743 
744  with pytest.raises(ValueError) as excinfo:
745  m.matrix_multiply(B=a, A=b)
746  assert str(excinfo.value) == "Nonconformable matrices!"
747 
748 
750  pytest.importorskip("scipy")
751  assert_sparse_equal_ref(m.sparse_r())
752  assert_sparse_equal_ref(m.sparse_c())
753  assert_sparse_equal_ref(m.sparse_copy_r(m.sparse_r()))
754  assert_sparse_equal_ref(m.sparse_copy_c(m.sparse_c()))
755  assert_sparse_equal_ref(m.sparse_copy_r(m.sparse_c()))
756  assert_sparse_equal_ref(m.sparse_copy_c(m.sparse_r()))
757 
758 
760  pytest.importorskip("scipy")
761  assert (
762  doc(m.sparse_copy_r)
763  == """
764  sparse_copy_r(arg0: scipy.sparse.csr_matrix[numpy.float32]) -> scipy.sparse.csr_matrix[numpy.float32]
765  """
766  )
767  assert (
768  doc(m.sparse_copy_c)
769  == """
770  sparse_copy_c(arg0: scipy.sparse.csc_matrix[numpy.float32]) -> scipy.sparse.csc_matrix[numpy.float32]
771  """
772  )
773 
774 
776  """Ignore strides on a length-1 dimension (even if they would be incompatible length > 1)"""
777  assert np.all(m.iss738_f1(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]]))
778  assert np.all(
779  m.iss738_f1(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]])
780  )
781 
782  assert np.all(m.iss738_f2(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]]))
783  assert np.all(
784  m.iss738_f2(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]])
785  )
786 
787 
788 @pytest.mark.parametrize("func", [m.iss738_f1, m.iss738_f2])
789 @pytest.mark.parametrize("sizes", [(0, 2), (2, 0)])
790 def test_zero_length(func, sizes):
791  """Ignore strides on a length-0 dimension (even if they would be incompatible length > 1)"""
792  assert np.all(func(np.zeros(sizes)) == np.zeros(sizes))
793 
794 
796  """Issue 1105: 1xN or Nx1 input arrays weren't accepted for eigen
797  compile-time row vectors or column vector"""
798  assert m.iss1105_row(np.ones((1, 7)))
799  assert m.iss1105_col(np.ones((7, 1)))
800 
801  # These should still fail (incompatible dimensions):
802  with pytest.raises(TypeError) as excinfo:
803  m.iss1105_row(np.ones((7, 1)))
804  assert "incompatible function arguments" in str(excinfo.value)
805  with pytest.raises(TypeError) as excinfo:
806  m.iss1105_col(np.ones((1, 7)))
807  assert "incompatible function arguments" in str(excinfo.value)
808 
809 
811  """Using Eigen types as member variables requires a class-specific
812  operator new with proper alignment"""
813 
814  o = m.CustomOperatorNew()
815  np.testing.assert_allclose(o.a, 0.0)
816  np.testing.assert_allclose(o.b.diagonal(), 1.0)
test_eigen_matrix.test_cpp_casting
def test_cpp_casting()
Definition: test_eigen_matrix.py:118
test_eigen_matrix.test_fixed
def test_fixed()
Definition: test_eigen_matrix.py:30
test_eigen_matrix.assert_equal_ref
def assert_equal_ref(mat)
Definition: test_eigen_matrix.py:22
test_eigen_matrix.test_dense_signature
def test_dense_signature(doc)
Definition: test_eigen_matrix.py:696
test_eigen_matrix.test_partially_fixed
def test_partially_fixed()
Definition: test_eigen_matrix.py:48
test_eigen_matrix.test_nonunit_stride_from_python
def test_nonunit_stride_from_python()
Definition: test_eigen_matrix.py:150
test_eigen_matrix.test_eigen_ref_to_python
def test_eigen_ref_to_python()
Definition: test_eigen_matrix.py:242
test_eigen_matrix.assert_keeps_alive
def assert_keeps_alive(cl, method, *args)
Definition: test_eigen_matrix.py:397
test_eigen_matrix.test_named_arguments
def test_named_arguments()
Definition: test_eigen_matrix.py:728
test_eigen_matrix.test_special_matrix_objects
def test_special_matrix_objects()
Definition: test_eigen_matrix.py:681
test_eigen_matrix.test_issue1105
def test_issue1105()
Definition: test_eigen_matrix.py:795
test_eigen_matrix.test_defaults
def test_defaults(doc)
Definition: test_eigen_matrix.py:723
gtsam::reshape
Reshape< OutM, OutN, OutOptions, InM, InN, InOptions >::ReshapedType reshape(const Eigen::Matrix< double, InM, InN, InOptions > &m)
Definition: base/Matrix.h:281
test_eigen_matrix.test_numpy_ref_mutators
def test_numpy_ref_mutators()
Definition: test_eigen_matrix.py:514
test_eigen_matrix.test_eigen_ref_mutators
def test_eigen_ref_mutators()
Definition: test_eigen_matrix.py:445
gtsam::range
Double_ range(const Point2_ &p, const Point2_ &q)
Definition: slam/expressions.h:30
test_eigen_matrix.test_zero_length
def test_zero_length(func, sizes)
Definition: test_eigen_matrix.py:790
test_eigen_matrix.test_issue738
def test_issue738()
Definition: test_eigen_matrix.py:775
doc
Annotation for documentation.
Definition: attr.h:45
test_eigen_matrix.test_negative_stride_from_python
def test_negative_stride_from_python(msg)
Definition: test_eigen_matrix.py:173
test_eigen_matrix.test_mutator_descriptors
def test_mutator_descriptors()
Definition: test_eigen_matrix.py:86
test_eigen_matrix.test_eigen_ref_life_support
def test_eigen_ref_life_support()
Definition: test_eigen_matrix.py:667
test_eigen_matrix.assert_sparse_equal_ref
def assert_sparse_equal_ref(sparse_mat)
Definition: test_eigen_matrix.py:26
test_eigen_matrix.test_nocopy_wrapper
def test_nocopy_wrapper()
Definition: test_eigen_matrix.py:610
test_eigen_matrix.test_nonunit_stride_to_python
def test_nonunit_stride_to_python()
Definition: test_eigen_matrix.py:228
test_eigen_matrix.test_sparse
def test_sparse()
Definition: test_eigen_matrix.py:749
cl
Definition: cxx11_tensor_builtins_sycl.cpp:30
test_eigen_matrix.test_both_ref_mutators
def test_both_ref_mutators()
Definition: test_eigen_matrix.py:566
test_eigen_matrix.test_dense
def test_dense()
Definition: test_eigen_matrix.py:39
test_eigen_matrix.test_eigen_keepalive
def test_eigen_keepalive()
Definition: test_eigen_matrix.py:412
test_eigen_matrix.test_block_runtime_error_type_caster_eigen_ref_made_a_copy
def test_block_runtime_error_type_caster_eigen_ref_made_a_copy()
Definition: test_eigen_matrix.py:222
str
Definition: pytypes.h:1558
tree::f
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Definition: testExpression.cpp:218
test_eigen_matrix.assign_both
def assign_both(a1, a2, r, c, v)
Definition: test_eigen_matrix.py:251
test_eigen_matrix.test_sparse_signature
def test_sparse_signature(doc)
Definition: test_eigen_matrix.py:759
test_eigen_matrix.array_copy_but_one
def array_copy_but_one(a, r, c, v)
Definition: test_eigen_matrix.py:256
test_eigen_matrix.test_pass_readonly_array
def test_pass_readonly_array()
Definition: test_eigen_matrix.py:141
ConstructorStats::get
static ConstructorStats & get(std::type_index type)
Definition: constructor_stats.h:163
func
Definition: benchGeometry.cpp:23
test_eigen_matrix.test_custom_operator_new
def test_custom_operator_new()
Definition: test_eigen_matrix.py:810
test_eigen_matrix.test_eigen_return_references
def test_eigen_return_references()
Definition: test_eigen_matrix.py:262
pybind11.msg
msg
Definition: wrap/pybind11/pybind11/__init__.py:6
repr
str repr(handle h)
Definition: pytypes.h:2467


gtsam
Author(s):
autogenerated on Thu Jul 4 2024 03:06:01