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