Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:53

0001 import sys
0002 
0003 import pytest
0004 
0005 np = pytest.importorskip("numpy")
0006 eigen_tensor = pytest.importorskip("pybind11_tests.eigen_tensor")
0007 submodules = [eigen_tensor.c_style, eigen_tensor.f_style]
0008 try:
0009     import eigen_tensor_avoid_stl_array as avoid
0010 
0011     submodules += [avoid.c_style, avoid.f_style]
0012 except ImportError as e:
0013     # Ensure config, build, toolchain, etc. issues are not masked here:
0014     raise RuntimeError(
0015         "import eigen_tensor_avoid_stl_array FAILED, while "
0016         "import pybind11_tests.eigen_tensor succeeded. "
0017         "Please ensure that "
0018         "test_eigen_tensor.cpp & "
0019         "eigen_tensor_avoid_stl_array.cpp "
0020         "are built together (or both are not built if Eigen is not available)."
0021     ) from e
0022 
0023 tensor_ref = np.empty((3, 5, 2), dtype=np.int64)
0024 
0025 for i in range(tensor_ref.shape[0]):
0026     for j in range(tensor_ref.shape[1]):
0027         for k in range(tensor_ref.shape[2]):
0028             tensor_ref[i, j, k] = i * (5 * 2) + j * 2 + k
0029 
0030 indices = (2, 3, 1)
0031 
0032 
0033 @pytest.fixture(autouse=True)
0034 def cleanup():
0035     for module in submodules:
0036         module.setup()
0037 
0038     yield
0039 
0040     for module in submodules:
0041         assert module.is_ok()
0042 
0043 
0044 def test_import_avoid_stl_array():
0045     pytest.importorskip("eigen_tensor_avoid_stl_array")
0046     assert len(submodules) == 4
0047 
0048 
0049 def assert_equal_tensor_ref(mat, writeable=True, modified=None):
0050     assert mat.flags.writeable == writeable
0051 
0052     copy = np.array(tensor_ref)
0053     if modified is not None:
0054         copy[indices] = modified
0055 
0056     np.testing.assert_array_equal(mat, copy)
0057 
0058 
0059 @pytest.mark.parametrize("m", submodules)
0060 @pytest.mark.parametrize("member_name", ["member", "member_view"])
0061 def test_reference_internal(m, member_name):
0062 
0063     if not hasattr(sys, "getrefcount"):
0064         pytest.skip("No reference counting")
0065     foo = m.CustomExample()
0066     counts = sys.getrefcount(foo)
0067     mem = getattr(foo, member_name)
0068     assert_equal_tensor_ref(mem, writeable=False)
0069     new_counts = sys.getrefcount(foo)
0070     assert new_counts == counts + 1
0071     assert_equal_tensor_ref(mem, writeable=False)
0072     del mem
0073     assert sys.getrefcount(foo) == counts
0074 
0075 
0076 assert_equal_funcs = [
0077     "copy_tensor",
0078     "copy_fixed_tensor",
0079     "copy_const_tensor",
0080     "move_tensor_copy",
0081     "move_fixed_tensor_copy",
0082     "take_tensor",
0083     "take_fixed_tensor",
0084     "reference_tensor",
0085     "reference_tensor_v2",
0086     "reference_fixed_tensor",
0087     "reference_view_of_tensor",
0088     "reference_view_of_tensor_v3",
0089     "reference_view_of_tensor_v5",
0090     "reference_view_of_fixed_tensor",
0091 ]
0092 
0093 assert_equal_const_funcs = [
0094     "reference_view_of_tensor_v2",
0095     "reference_view_of_tensor_v4",
0096     "reference_view_of_tensor_v6",
0097     "reference_const_tensor",
0098     "reference_const_tensor_v2",
0099 ]
0100 
0101 
0102 @pytest.mark.parametrize("m", submodules)
0103 @pytest.mark.parametrize("func_name", assert_equal_funcs + assert_equal_const_funcs)
0104 def test_convert_tensor_to_py(m, func_name):
0105     writeable = func_name in assert_equal_funcs
0106     assert_equal_tensor_ref(getattr(m, func_name)(), writeable=writeable)
0107 
0108 
0109 @pytest.mark.parametrize("m", submodules)
0110 def test_bad_cpp_to_python_casts(m):
0111 
0112     with pytest.raises(
0113         RuntimeError, match="Cannot use reference internal when there is no parent"
0114     ):
0115         m.reference_tensor_internal()
0116 
0117     with pytest.raises(RuntimeError, match="Cannot move from a constant reference"):
0118         m.move_const_tensor()
0119 
0120     with pytest.raises(
0121         RuntimeError, match="Cannot take ownership of a const reference"
0122     ):
0123         m.take_const_tensor()
0124 
0125     with pytest.raises(
0126         RuntimeError,
0127         match="Invalid return_value_policy for Eigen Map type, must be either reference or reference_internal",
0128     ):
0129         m.take_view_tensor()
0130 
0131 
0132 @pytest.mark.parametrize("m", submodules)
0133 def test_bad_python_to_cpp_casts(m):
0134 
0135     with pytest.raises(
0136         TypeError, match=r"^round_trip_tensor\(\): incompatible function arguments"
0137     ):
0138         m.round_trip_tensor(np.zeros((2, 3)))
0139 
0140     with pytest.raises(TypeError, match=r"^Cannot cast array data from dtype"):
0141         m.round_trip_tensor(np.zeros(dtype=np.str_, shape=(2, 3, 1)))
0142 
0143     with pytest.raises(
0144         TypeError,
0145         match=r"^round_trip_tensor_noconvert\(\): incompatible function arguments",
0146     ):
0147         m.round_trip_tensor_noconvert(tensor_ref)
0148 
0149     assert_equal_tensor_ref(
0150         m.round_trip_tensor_noconvert(tensor_ref.astype(np.float64))
0151     )
0152 
0153     if m.needed_options == "F":
0154         bad_options = "C"
0155     else:
0156         bad_options = "F"
0157     # Shape, dtype and the order need to be correct for a TensorMap cast
0158     with pytest.raises(
0159         TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
0160     ):
0161         m.round_trip_view_tensor(
0162             np.zeros((3, 5, 2), dtype=np.float64, order=bad_options)
0163         )
0164 
0165     with pytest.raises(
0166         TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
0167     ):
0168         m.round_trip_view_tensor(
0169             np.zeros((3, 5, 2), dtype=np.float32, order=m.needed_options)
0170         )
0171 
0172     with pytest.raises(
0173         TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
0174     ):
0175         m.round_trip_view_tensor(
0176             np.zeros((3, 5), dtype=np.float64, order=m.needed_options)
0177         )
0178 
0179     with pytest.raises(
0180         TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
0181     ):
0182         temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
0183         m.round_trip_view_tensor(
0184             temp[:, ::-1, :],
0185         )
0186 
0187     with pytest.raises(
0188         TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
0189     ):
0190         temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
0191         temp.setflags(write=False)
0192         m.round_trip_view_tensor(temp)
0193 
0194 
0195 @pytest.mark.parametrize("m", submodules)
0196 def test_references_actually_refer(m):
0197 
0198     a = m.reference_tensor()
0199     temp = a[indices]
0200     a[indices] = 100
0201     assert_equal_tensor_ref(m.copy_const_tensor(), modified=100)
0202     a[indices] = temp
0203     assert_equal_tensor_ref(m.copy_const_tensor())
0204 
0205     a = m.reference_view_of_tensor()
0206     a[indices] = 100
0207     assert_equal_tensor_ref(m.copy_const_tensor(), modified=100)
0208     a[indices] = temp
0209     assert_equal_tensor_ref(m.copy_const_tensor())
0210 
0211 
0212 @pytest.mark.parametrize("m", submodules)
0213 def test_round_trip(m):
0214 
0215     assert_equal_tensor_ref(m.round_trip_tensor(tensor_ref))
0216 
0217     with pytest.raises(TypeError, match="^Cannot cast array data from"):
0218         assert_equal_tensor_ref(m.round_trip_tensor2(tensor_ref))
0219 
0220     assert_equal_tensor_ref(m.round_trip_tensor2(np.array(tensor_ref, dtype=np.int32)))
0221     assert_equal_tensor_ref(m.round_trip_fixed_tensor(tensor_ref))
0222     assert_equal_tensor_ref(m.round_trip_aligned_view_tensor(m.reference_tensor()))
0223 
0224     copy = np.array(tensor_ref, dtype=np.float64, order=m.needed_options)
0225     assert_equal_tensor_ref(m.round_trip_view_tensor(copy))
0226     assert_equal_tensor_ref(m.round_trip_view_tensor_ref(copy))
0227     assert_equal_tensor_ref(m.round_trip_view_tensor_ptr(copy))
0228     copy.setflags(write=False)
0229     assert_equal_tensor_ref(m.round_trip_const_view_tensor(copy))
0230 
0231     np.testing.assert_array_equal(
0232         tensor_ref[:, ::-1, :], m.round_trip_tensor(tensor_ref[:, ::-1, :])
0233     )
0234 
0235     assert m.round_trip_rank_0(np.float64(3.5)) == 3.5
0236     assert m.round_trip_rank_0(3.5) == 3.5
0237 
0238     with pytest.raises(
0239         TypeError,
0240         match=r"^round_trip_rank_0_noconvert\(\): incompatible function arguments",
0241     ):
0242         m.round_trip_rank_0_noconvert(np.float64(3.5))
0243 
0244     with pytest.raises(
0245         TypeError,
0246         match=r"^round_trip_rank_0_noconvert\(\): incompatible function arguments",
0247     ):
0248         m.round_trip_rank_0_noconvert(3.5)
0249 
0250     with pytest.raises(
0251         TypeError, match=r"^round_trip_rank_0_view\(\): incompatible function arguments"
0252     ):
0253         m.round_trip_rank_0_view(np.float64(3.5))
0254 
0255     with pytest.raises(
0256         TypeError, match=r"^round_trip_rank_0_view\(\): incompatible function arguments"
0257     ):
0258         m.round_trip_rank_0_view(3.5)
0259 
0260 
0261 @pytest.mark.parametrize("m", submodules)
0262 def test_round_trip_references_actually_refer(m):
0263 
0264     # Need to create a copy that matches the type on the C side
0265     copy = np.array(tensor_ref, dtype=np.float64, order=m.needed_options)
0266     a = m.round_trip_view_tensor(copy)
0267     temp = a[indices]
0268     a[indices] = 100
0269     assert_equal_tensor_ref(copy, modified=100)
0270     a[indices] = temp
0271     assert_equal_tensor_ref(copy)
0272 
0273 
0274 @pytest.mark.parametrize("m", submodules)
0275 def test_doc_string(m, doc):
0276     assert (
0277         doc(m.copy_tensor) == "copy_tensor() -> numpy.ndarray[numpy.float64[?, ?, ?]]"
0278     )
0279     assert (
0280         doc(m.copy_fixed_tensor)
0281         == "copy_fixed_tensor() -> numpy.ndarray[numpy.float64[3, 5, 2]]"
0282     )
0283     assert (
0284         doc(m.reference_const_tensor)
0285         == "reference_const_tensor() -> numpy.ndarray[numpy.float64[?, ?, ?]]"
0286     )
0287 
0288     order_flag = f"flags.{m.needed_options.lower()}_contiguous"
0289     assert doc(m.round_trip_view_tensor) == (
0290         f"round_trip_view_tensor(arg0: numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}])"
0291         + f" -> numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}]"
0292     )
0293     assert doc(m.round_trip_const_view_tensor) == (
0294         f"round_trip_const_view_tensor(arg0: numpy.ndarray[numpy.float64[?, ?, ?], {order_flag}])"
0295         + " -> numpy.ndarray[numpy.float64[?, ?, ?]]"
0296     )