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


gtsam
Author(s):
autogenerated on Mon Jul 1 2024 03:06:04