Skip to content

Commit 47f51e3

Browse files
authored
Merge branch 'master' into tests_cuda
2 parents 1461e81 + e236ad9 commit 47f51e3

File tree

9 files changed

+147
-48
lines changed

9 files changed

+147
-48
lines changed

.github/workflows/conda-package.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ env:
6363
third_party/cupy/statistics_tests/test_histogram.py
6464
third_party/cupy/statistics_tests/test_meanvar.py
6565
third_party/cupy/test_ndim.py
66+
third_party/cupy/test_type_routines.py
6667
VER_JSON_NAME: 'version.json'
6768
VER_SCRIPT1: "import json; f = open('version.json', 'r'); j = json.load(f); f.close(); "
6869
VER_SCRIPT2: "d = j['dpnp'][0]; print('='.join((d[s] for s in ('version', 'build'))))"

dpnp/dpnp_iface_logic.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"iscomplex",
6565
"iscomplexobj",
6666
"isfinite",
67+
"isfortran",
6768
"isinf",
6869
"isnan",
6970
"isneginf",
@@ -991,6 +992,76 @@ def iscomplexobj(x):
991992
)
992993

993994

995+
def isfortran(a):
996+
"""
997+
Check if the array is Fortran contiguous but *not* C contiguous.
998+
999+
This function is obsolete. If you only want to check if an array is Fortran
1000+
contiguous use ``a.flags.f_contiguous`` instead.
1001+
1002+
For full documentation refer to :obj:`numpy.isfortran`.
1003+
1004+
Parameters
1005+
----------
1006+
a : {dpnp.ndarray, usm_ndarray}
1007+
Input array.
1008+
1009+
Returns
1010+
-------
1011+
isfortran : bool
1012+
Returns ``True`` if the array is Fortran contiguous
1013+
but *not* C contiguous.
1014+
1015+
Examples
1016+
--------
1017+
:obj:`dpnp.array` allows to specify whether the array is written in
1018+
C-contiguous order (last index varies the fastest), or FORTRAN-contiguous
1019+
order in memory (first index varies the fastest).
1020+
1021+
>>> import dpnp as np
1022+
>>> a = np.array([[1, 2, 3], [4, 5, 6]], order='C')
1023+
>>> a
1024+
array([[1, 2, 3],
1025+
[4, 5, 6]])
1026+
>>> np.isfortran(a)
1027+
False
1028+
1029+
>>> b = np.array([[1, 2, 3], [4, 5, 6]], order='F')
1030+
>>> b
1031+
array([[1, 2, 3],
1032+
[4, 5, 6]])
1033+
>>> np.isfortran(b)
1034+
True
1035+
1036+
The transpose of a C-ordered array is a FORTRAN-ordered array.
1037+
1038+
>>> a = np.array([[1, 2, 3], [4, 5, 6]], order='C')
1039+
>>> a
1040+
array([[1, 2, 3],
1041+
[4, 5, 6]])
1042+
>>> np.isfortran(a)
1043+
False
1044+
>>> b = a.T
1045+
>>> b
1046+
array([[1, 4],
1047+
[2, 5],
1048+
[3, 6]])
1049+
>>> np.isfortran(b)
1050+
True
1051+
1052+
C-ordered arrays evaluate as ``False`` even if they are also
1053+
FORTRAN-ordered.
1054+
1055+
>>> np.isfortran(np.array([1, 2], order='F'))
1056+
False
1057+
1058+
"""
1059+
1060+
dpnp.check_supported_arrays_type(a)
1061+
1062+
return a.flags.fnc
1063+
1064+
9941065
_ISINF_DOCSTRING = """
9951066
Test if each element of input array is an infinity.
9961067

dpnp/dpnp_iface_statistics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ def correlate(x1, x2, mode="valid"):
370370
-----------
371371
Input arrays are supported as :obj:`dpnp.ndarray`.
372372
Size and shape of input arrays are supported to be equal.
373-
Parameter `mode` is supported only with default value ``"valid``.
373+
Parameter `mode` is supported only with default value ``"valid"``.
374374
Otherwise the function will be executed sequentially on CPU.
375375
Input array data types are limited by supported DPNP :ref:`Data types`.
376376

dpnp/dpnp_utils/dpnp_utils_einsum.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@
3333
from dpctl.utils import ExecutionPlacementError
3434

3535
import dpnp
36-
from dpnp.dpnp_utils import get_usm_allocations
37-
38-
from ..dpnp_array import dpnp_array
36+
from dpnp.dpnp_array import dpnp_array
37+
from dpnp.dpnp_utils import get_usm_allocations, map_dtype_to_device
3938

4039
_einsum_symbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
4140

@@ -1027,17 +1026,16 @@ def dpnp_einsum(
10271026
"Input and output allocation queues are not compatible"
10281027
)
10291028

1030-
result_dtype = dpnp.result_type(*arrays) if dtype is None else dtype
10311029
for id, a in enumerate(operands):
10321030
if dpnp.isscalar(a):
1031+
scalar_dtype = map_dtype_to_device(type(a), exec_q.sycl_device)
10331032
operands[id] = dpnp.array(
1034-
a, dtype=result_dtype, usm_type=res_usm_type, sycl_queue=exec_q
1033+
a, dtype=scalar_dtype, usm_type=res_usm_type, sycl_queue=exec_q
10351034
)
1035+
arrays.append(operands[id])
10361036
result_dtype = dpnp.result_type(*arrays) if dtype is None else dtype
1037-
if order in ["a", "A"]:
1038-
order = (
1039-
"F" if not any(arr.flags.c_contiguous for arr in arrays) else "C"
1040-
)
1037+
if order in "aA":
1038+
order = "F" if all(arr.flags.fnc for arr in arrays) else "C"
10411039

10421040
input_subscripts = [
10431041
_parse_ellipsis_subscript(sub, idx, ndim=arr.ndim)

tests/test_linalg.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,14 +1139,12 @@ def check_einsum_sums(self, dtype, do_opt=False):
11391139
result = inp.einsum(*args, dtype="?", casting="unsafe", optimize=do_opt)
11401140
assert_dtype_allclose(result, expected)
11411141

1142-
# with an scalar, NumPy < 2.0.0 uses the other input arrays to
1143-
# determine the output type while for NumPy > 2.0.0 the scalar
1144-
# with default machine dtype is used to determine the output
1145-
# data type
1142+
# NumPy >= 2.0 follows NEP-50 to determine the output dtype when one of
1143+
# the inputs is a scalar while NumPy < 2.0 does not
11461144
if numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0":
1147-
check_type = True
1148-
else:
11491145
check_type = False
1146+
else:
1147+
check_type = True
11501148
a = numpy.arange(9, dtype=dtype)
11511149
a_dp = inp.array(a)
11521150
expected = numpy.einsum(",i->", 3, a)
@@ -1712,7 +1710,7 @@ def test_broadcasting_dot_cases(self):
17121710

17131711
def test_output_order(self):
17141712
# Ensure output order is respected for optimize cases, the below
1715-
# conraction should yield a reshaped tensor view
1713+
# contraction should yield a reshaped tensor view
17161714
a = inp.ones((2, 3, 5), order="F")
17171715
b = inp.ones((4, 3), order="F")
17181716

tests/test_logic.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,34 @@ def test_finite(op, data, dtype):
434434
assert_equal(dpnp_res, np_res)
435435

436436

437+
class TestIsFortran:
438+
@pytest.mark.parametrize(
439+
"array, expected",
440+
[
441+
(dpnp.ones((2, 4), order="C"), True),
442+
(dpnp.ones((2, 4), order="F"), False),
443+
],
444+
)
445+
def test_isfortran_transpose(self, array, expected):
446+
assert dpnp.isfortran(array.T) == expected
447+
448+
@pytest.mark.parametrize(
449+
"array, expected",
450+
[
451+
(dpnp.ones((2, 4), order="C"), False),
452+
(dpnp.ones((2, 4), order="F"), True),
453+
],
454+
)
455+
def test_isfortran_usm_ndarray(self, array, expected):
456+
assert dpnp.isfortran(array.get_array()) == expected
457+
458+
def test_isfortran_errors(self):
459+
# unsupported type
460+
a_np = numpy.ones((2, 3))
461+
assert_raises(TypeError, dpnp.isfortran, a_np)
462+
assert_raises(TypeError, dpnp.isfortran, [1, 2, 3])
463+
464+
437465
@pytest.mark.parametrize("func", ["isneginf", "isposinf"])
438466
@pytest.mark.parametrize(
439467
"data",

tests/third_party/cupy/linalg_tests/test_einsum.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -475,13 +475,12 @@ def test_einsum_binary(self, xp, dtype_a, dtype_b):
475475

476476

477477
class TestEinSumBinaryOperationWithScalar:
478-
# with an scalar, NumPy < 2.0.0 uses the other input arrays to determine
479-
# the output type while for NumPy > 2.0.0 the scalar with default machine
480-
# dtype is used to determine the output type
478+
# NumPy >= 2.0 follows NEP-50 to determine the output dtype when one of
479+
# the inputs is a scalar while NumPy < 2.0 does not
481480
if numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0":
482-
type_check = has_support_aspect64()
483-
else:
484481
type_check = False
482+
else:
483+
type_check = has_support_aspect64()
485484

486485
@testing.for_all_dtypes()
487486
@testing.numpy_cupy_allclose(contiguous_check=False, type_check=type_check)

tests/third_party/cupy/logic_tests/test_type_test.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ def setUp(self):
7272
)
7373
class TestIsFortran(unittest.TestCase):
7474

75-
@pytest.mark.skip("isfortran not implemented")
7675
@testing.numpy_cupy_equal()
7776
def test(self, xp):
7877
return xp.isfortran(xp.asarray(self.value))

tests/third_party/cupy/test_type_routines.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ class TestCanCast(unittest.TestCase):
3434
@testing.for_all_dtypes_combination(names=("from_dtype", "to_dtype"))
3535
@testing.numpy_cupy_equal()
3636
def test_can_cast(self, xp, from_dtype, to_dtype):
37-
if self.obj_type == "scalar":
37+
if (
38+
self.obj_type == "scalar"
39+
and numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0"
40+
):
3841
pytest.skip("to be aligned with NEP-50")
3942

4043
from_obj = _generate_type_routines_input(xp, from_dtype, self.obj_type)
41-
4244
ret = xp.can_cast(from_obj, to_dtype)
4345
assert isinstance(ret, bool)
4446
return ret
@@ -92,37 +94,40 @@ class TestResultType(unittest.TestCase):
9294
@testing.for_all_dtypes_combination(names=("dtype1", "dtype2"))
9395
@testing.numpy_cupy_equal()
9496
def test_result_type(self, xp, dtype1, dtype2):
95-
if "scalar" in {self.obj_type1, self.obj_type2}:
97+
if (
98+
"scalar" in {self.obj_type1, self.obj_type2}
99+
and numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0"
100+
):
96101
pytest.skip("to be aligned with NEP-50")
97102

98103
input1 = _generate_type_routines_input(xp, dtype1, self.obj_type1)
99-
100104
input2 = _generate_type_routines_input(xp, dtype2, self.obj_type2)
101105

102-
flag1 = isinstance(input1, (numpy.ndarray, cupy.ndarray))
103-
flag2 = isinstance(input2, (numpy.ndarray, cupy.ndarray))
104-
dt1 = cupy.dtype(input1) if not flag1 else None
105-
dt2 = cupy.dtype(input2) if not flag2 else None
106-
# dpnp takes into account device capabilities only if one of the
107-
# inputs is an array, for such a case, if the other dtype is not
108-
# supported by device, dpnp raise ValueError. So, we skip the test.
109-
if flag1 or flag2:
110-
if (
111-
dt1 in [cupy.float64, cupy.complex128]
112-
or dt2 in [cupy.float64, cupy.complex128]
113-
) and not has_support_aspect64():
114-
pytest.skip("No fp64 support by device.")
106+
# dpnp.result_type takes into account device capabilities, when one of
107+
# the inputs is an array. If dtype is `float32` and the object is
108+
# primitive, the final dtype is `float` which needs a device with
109+
# double precision support. So we have to skip the test for such a case
110+
# on a device that does not support fp64
111+
flag1 = self.obj_type1 == "array" or self.obj_type2 == "array"
112+
flag2 = (self.obj_type1 == "primitive" and input1 == float) or (
113+
self.obj_type2 == "primitive" and input2 == float
114+
)
115+
if flag1 and flag2 and not has_support_aspect64():
116+
pytest.skip("No fp64 support by device.")
115117

116118
ret = xp.result_type(input1, input2)
117119

118-
# dpnp takes into account device capabilities if one of the inputs
119-
# is an array, for such a case, we have to modify the results for
120-
# NumPy to align it with device capabilities.
121-
if (flag1 or flag2) and xp == numpy and not has_support_aspect64():
122-
ret = numpy.dtype(numpy.float32) if ret == numpy.float64 else ret
123-
ret = (
124-
numpy.dtype(numpy.complex64) if ret == numpy.complex128 else ret
125-
)
120+
# dpnp.result_type takes into account device capabilities, when one of the inputs
121+
# is an array.
122+
# So, we have to modify the results for NumPy to align it with
123+
# device capabilities.
124+
flag1 = isinstance(input1, numpy.ndarray)
125+
flag2 = isinstance(input2, numpy.ndarray)
126+
if (flag1 or flag2) and not has_support_aspect64():
127+
if ret == numpy.float64:
128+
ret = numpy.dtype(numpy.float32)
129+
elif ret == numpy.complex128:
130+
ret = numpy.dtype(numpy.complex64)
126131

127132
assert isinstance(ret, numpy.dtype)
128133
return ret

0 commit comments

Comments
 (0)