Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dpnp/dpnp_algo/dpnp_algo.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ cimport dpnp.dpnp_utils as utils
cimport numpy
import numpy

import operator


__all__ = [
"dpnp_astype",
Expand Down
90 changes: 70 additions & 20 deletions dpnp/dpnp_algo/dpnp_algo_arraycreation.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -189,31 +189,81 @@ cpdef utils.dpnp_descriptor dpnp_identity(n, result_dtype):
return result


# TODO this function should work through dpnp_arange_c
cpdef tuple dpnp_linspace(start, stop, num, endpoint, retstep, dtype, axis):
cdef shape_type_c obj_shape = utils._object_to_tuple(num)
cdef utils.dpnp_descriptor result = utils_py.create_output_descriptor_py(obj_shape, dtype, None)
def dpnp_linspace(start, stop, num, dtype=None, device=None, usm_type=None, sycl_queue=None, endpoint=True, retstep=False, axis=0):
usm_type_alloc, sycl_queue_alloc = utils_py.get_usm_allocations([start, stop])

if endpoint:
steps_count = num - 1
else:
steps_count = num
# Get sycl_queue.
if sycl_queue is None and device is None:
sycl_queue = sycl_queue_alloc
sycl_queue_normalized = dpnp.get_normalized_queue_device(sycl_queue=sycl_queue, device=device)

# if there are steps, then fill values
if steps_count > 0:
step = (dpnp.float64(stop) - start) / steps_count
for i in range(1, result.size):
result.get_pyobj()[i] = start + step * i
# Get temporary usm_type for getting dtype.
if usm_type is None:
_usm_type = "device" if usm_type_alloc is None else usm_type_alloc
else:
step = dpnp.nan
_usm_type = usm_type

# Get dtype.
if not hasattr(start, "dtype") and not dpnp.isscalar(start):
start = dpnp.asarray(start, usm_type=_usm_type, sycl_queue=sycl_queue_normalized)
if not hasattr(stop, "dtype") and not dpnp.isscalar(stop):
stop = dpnp.asarray(stop, usm_type=_usm_type, sycl_queue=sycl_queue_normalized)
dt = numpy.result_type(start, stop, float(num))
dt = utils_py.map_dtype_to_device(dt, sycl_queue_normalized.sycl_device)
if dtype is None:
dtype = dt

if dpnp.isscalar(start) and dpnp.isscalar(stop):
# Call linspace() function for scalars.
res = dpnp_container.linspace(start,
stop,
num,
dtype=dt,
usm_type=_usm_type,
sycl_queue=sycl_queue_normalized,
endpoint=endpoint)
else:
num = operator.index(num)
if num < 0:
raise ValueError("Number of points must be non-negative")

# Get final usm_type and copy arrays if needed with current dtype, usm_type and sycl_queue.
# Do not need to copy usm_ndarray by usm_type if it is not explicitly stated.
if usm_type is None:
usm_type = _usm_type
if not hasattr(start, "usm_type"):
_start = dpnp.asarray(start, dtype=dt, usm_type=usm_type, sycl_queue=sycl_queue_normalized)
else:
_start = dpnp.asarray(start, dtype=dt, sycl_queue=sycl_queue_normalized)
if not hasattr(stop, "usm_type"):
_stop = dpnp.asarray(stop, dtype=dt, usm_type=usm_type, sycl_queue=sycl_queue_normalized)
else:
_stop = dpnp.asarray(stop, dtype=dt, sycl_queue=sycl_queue_normalized)
else:
_start = dpnp.asarray(start, dtype=dt, usm_type=usm_type, sycl_queue=sycl_queue_normalized)
_stop = dpnp.asarray(stop, dtype=dt, usm_type=usm_type, sycl_queue=sycl_queue_normalized)

# if result is not empty, then fiil first and last elements
if num > 0:
result.get_pyobj()[0] = start
if endpoint and result.size > 1:
result.get_pyobj()[result.size - 1] = stop
# FIXME: issue #1304. Mathematical operations with scalar don't follow data type.
_num = dpnp.asarray((num - 1) if endpoint else num, dtype=dt, usm_type=usm_type, sycl_queue=sycl_queue_normalized)

step = (_stop - _start) / _num

res = dpnp_container.arange(0,
stop=num,
step=1,
dtype=dt,
usm_type=usm_type,
sycl_queue=sycl_queue_normalized)

res = res.reshape((-1,) + (1,) * step.ndim)
res = res * step + _start

if endpoint and num > 1:
res[-1] = dpnp_container.full(step.shape, _stop)

return (result.get_pyobj(), step)
if numpy.issubdtype(dtype, dpnp.integer):
dpnp.floor(res, out=res)
return res.astype(dtype)


cpdef utils.dpnp_descriptor dpnp_logspace(start, stop, num, endpoint, base, dtype, axis):
Expand Down
68 changes: 47 additions & 21 deletions dpnp/dpnp_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"empty",
"eye",
"full",
"linspace",
"ones"
"tril",
"triu",
Expand Down Expand Up @@ -126,6 +127,33 @@ def empty(shape,
return dpnp_array(array_obj.shape, buffer=array_obj, order=order)


def eye(N,
M=None,
/,
*,
k=0,
dtype=None,
order="C",
device=None,
usm_type="device",
sycl_queue=None):
"""Validate input parameters before passing them into `dpctl.tensor` module"""
dpu.validate_usm_type(usm_type, allow_none=False)
sycl_queue_normalized = dpnp.get_normalized_queue_device(sycl_queue=sycl_queue, device=device)
if order is None:
order = 'C'

"""Creates `dpnp_array` with ones on the `k`th diagonal."""
array_obj = dpt.eye(N,
M,
k=k,
dtype=dtype,
order=order,
usm_type=usm_type,
sycl_queue=sycl_queue_normalized)
return dpnp_array(array_obj.shape, buffer=array_obj, order=order)


def full(shape,
fill_value,
*,
Expand Down Expand Up @@ -153,31 +181,29 @@ def full(shape,
return dpnp_array(array_obj.shape, buffer=array_obj, order=order)


def eye(N,
M=None,
/,
*,
k=0,
dtype=None,
order="C",
device=None,
usm_type="device",
sycl_queue=None):
def linspace(start,
stop,
/,
num,
*,
dtype=None,
device=None,
usm_type="device",
sycl_queue=None,
endpoint=True):
"""Validate input parameters before passing them into `dpctl.tensor` module"""
dpu.validate_usm_type(usm_type, allow_none=False)
sycl_queue_normalized = dpnp.get_normalized_queue_device(sycl_queue=sycl_queue, device=device)
if order is None:
order = 'C'

"""Creates `dpnp_array` with ones on the `k`th diagonal."""
array_obj = dpt.eye(N,
M,
k=k,
dtype=dtype,
order=order,
usm_type=usm_type,
sycl_queue=sycl_queue_normalized)
return dpnp_array(array_obj.shape, buffer=array_obj, order=order)
"""Creates `dpnp_array` with evenly spaced numbers of specified interval."""
array_obj = dpt.linspace(start,
stop,
num,
dtype=dtype,
usm_type=usm_type,
sycl_queue=sycl_queue_normalized,
endpoint=endpoint)
return dpnp_array(array_obj.shape, buffer=array_obj)


def meshgrid(*xi, indexing="xy"):
Expand Down
39 changes: 28 additions & 11 deletions dpnp/dpnp_iface_arraycreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

import dpnp.dpnp_container as dpnp_container
import dpctl.tensor as dpt
import dpctl


__all__ = [
Expand Down Expand Up @@ -879,7 +880,18 @@ def identity(n, dtype=None, *, like=None):
return call_origin(numpy.identity, n, dtype=dtype, like=like)


def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0):
def linspace(start,
stop,
/,
num,
*,
dtype=None,
device=None,
usm_type=None,
sycl_queue=None,
endpoint=True,
retstep=False,
axis=0):
"""
Return evenly spaced numbers over a specified interval.

Expand All @@ -888,6 +900,8 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis
Limitations
-----------
Parameter ``axis`` is supported only with default value ``0``.
Parameter ``retstep`` is supported only with default value ``False``.
Otherwise the function will be executed sequentially on CPU.

See Also
--------
Expand All @@ -913,16 +927,19 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis

"""

if not use_origin_backend():
if axis != 0:
checker_throw_value_error("linspace", "axis", axis, 0)

res = dpnp_linspace(start, stop, num, endpoint, retstep, dtype, axis)

if retstep:
return res
else:
return res[0]
if retstep is not False:
pass
elif axis != 0:
pass
else:
return dpnp_linspace(start,
stop,
num,
dtype=dtype,
device=device,
usm_type=usm_type,
sycl_queue=sycl_queue,
endpoint=endpoint)

return call_origin(numpy.linspace, start, stop, num, endpoint, retstep, dtype, axis)

Expand Down
8 changes: 3 additions & 5 deletions tests/skipped_tests.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -418,12 +418,10 @@ tests/third_party/cupy/creation_tests/test_ranges.py::TestMgrid::test_mgrid3
tests/third_party/cupy/creation_tests/test_ranges.py::TestOgrid::test_ogrid3
tests/third_party/cupy/creation_tests/test_ranges.py::TestOgrid::test_ogrid4
tests/third_party/cupy/creation_tests/test_ranges.py::TestOgrid::test_ogrid5
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_array_start_stop
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_array_start_stop_axis1
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_float_underflow
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_mixed_start_stop
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_mixed_start_stop2
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_start_stop_list
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_one_num_no_endopoint_with_retstep
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_with_retstep
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_zero_num_no_endopoint_with_retstep
tests/third_party/cupy/indexing_tests/test_generate.py::TestAxisConcatenator::test_AxisConcatenator_init1
tests/third_party/cupy/indexing_tests/test_generate.py::TestAxisConcatenator::test_len
tests/third_party/cupy/indexing_tests/test_generate.py::TestC_::test_c_1
Expand Down
14 changes: 4 additions & 10 deletions tests/skipped_tests_gpu.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -594,19 +594,13 @@ tests/third_party/cupy/creation_tests/test_ranges.py::TestMgrid::test_mgrid5
tests/third_party/cupy/creation_tests/test_ranges.py::TestOgrid::test_ogrid3
tests/third_party/cupy/creation_tests/test_ranges.py::TestOgrid::test_ogrid4
tests/third_party/cupy/creation_tests/test_ranges.py::TestOgrid::test_ogrid5

tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_array_start_stop
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_array_start_stop_axis1
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_arange_negative_size
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_arange_no_dtype_int

tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_float_underflow
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_mixed_start_stop
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_mixed_start_stop2
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_start_stop_list

tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_array_start_stop_axis1
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_one_num_no_endopoint_with_retstep
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_with_retstep
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_linspace_zero_num_no_endopoint_with_retstep
tests/third_party/cupy/creation_tests/test_ranges.py::TestRanges::test_logspace_zero_num

tests/third_party/cupy/fft_tests/test_fft.py::TestFft2_param_1_{axes=None, norm=None, s=(1, None), shape=(3, 4)}::test_fft2
tests/third_party/cupy/fft_tests/test_fft.py::TestFft2_param_7_{axes=(), norm=None, s=None, shape=(3, 4)}::test_fft2
tests/third_party/cupy/fft_tests/test_fft.py::TestFft2_param_7_{axes=(), norm=None, s=None, shape=(3, 4)}::test_ifft2
Expand Down
45 changes: 45 additions & 0 deletions tests/test_arraycreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,51 @@ def test_dpctl_tensor_input(func, args):
assert_array_equal(X, Y)


@pytest.mark.parametrize("start",
[0, -5, 10, -2.5, 9.7],
ids=['0', '-5', '10', '-2.5', '9.7'])
@pytest.mark.parametrize("stop",
[0, 10, -2, 20.5, 1000],
ids=['0', '10', '-2', '20.5', '1000'])
@pytest.mark.parametrize("num",
[5, numpy.array(10), dpnp.array(17), dpt.asarray(100)],
ids=['5', 'numpy.array(10)', 'dpnp.array(17)', 'dpt.asarray(100)'])
@pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True, no_float16=False))
def test_linspace(start, stop, num, dtype):
func = lambda xp: xp.linspace(start, stop, num, dtype=dtype)

if numpy.issubdtype(dtype, dpnp.integer):
assert_allclose(func(numpy), func(dpnp), rtol=1)
else:
assert_allclose(func(numpy), func(dpnp), atol=numpy.finfo(dtype).eps)


@pytest.mark.parametrize("start_dtype",
[numpy.float64, numpy.float32, numpy.int64, numpy.int32],
ids=['float64', 'float32', 'int64', 'int32'])
@pytest.mark.parametrize("stop_dtype",
[numpy.float64, numpy.float32, numpy.int64, numpy.int32],
ids=['float64', 'float32', 'int64', 'int32'])
def test_linspace_dtype(start_dtype, stop_dtype):
start = numpy.array([1, 2, 3], dtype=start_dtype)
stop = numpy.array([11, 7, -2], dtype=stop_dtype)
dpnp.linspace(start, stop, 10)


@pytest.mark.parametrize("start",
[dpnp.array(1), dpnp.array([2.6]), numpy.array([[-6.7, 3]]), [1, -4], (3, 5)])
@pytest.mark.parametrize("stop",
[dpnp.array([-4]), dpnp.array([[2.6], [- 4]]), numpy.array(2), [[-4.6]], (3,)])
def test_linspace_arrays(start, stop):
func = lambda xp: xp.linspace(start, stop, 10)
assert func(numpy).shape == func(dpnp).shape


def test_linspace_complex():
func = lambda xp: xp.linspace(0, 3 + 2j, num=1000)
assert_allclose(func(numpy), func(dpnp))


@pytest.mark.parametrize("arrays",
[[], [[1]], [[1, 2, 3], [4, 5, 6]], [[1, 2], [3, 4], [5, 6]]],
ids=['[]', '[[1]]', '[[1, 2, 3], [4, 5, 6]]', '[[1, 2], [3, 4], [5, 6]]'])
Expand Down
2 changes: 1 addition & 1 deletion tests/test_special.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def test_erf():
a = numpy.linspace(2.0, 3.0, num=10)
ia = dpnp.linspace(2.0, 3.0, num=10)

numpy.testing.assert_array_equal(a, ia)
numpy.testing.assert_allclose(a, ia)

expected = numpy.empty_like(a)
for idx, val in enumerate(a):
Expand Down
Loading