Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
3 changes: 2 additions & 1 deletion doc/reference/misc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Utility
:toctree: generated/
:nosignatures:

dpnp.broadcast_shapes
dpnp.byte_bounds
dpnp.get_include
dpnp.show_config
dpnp.show_runtime
dpnp.broadcast_shapes
4 changes: 4 additions & 0 deletions dpnp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,13 @@
from dpnp.dpnp_iface_types import *
from dpnp.dpnp_iface import *
from dpnp.dpnp_iface import __all__ as _iface__all__
from dpnp.dpnp_iface_utils import *
from dpnp.dpnp_iface_utils import __all__ as _ifaceutils__all__
from dpnp._version import get_versions

__all__ = _iface__all__
__all__ += _ifaceutils__all__


__version__ = get_versions()["version"]
del get_versions
75 changes: 75 additions & 0 deletions dpnp/dpnp_iface_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
# *****************************************************************************
# Copyright (c) 2024, Intel Corporation
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
# *****************************************************************************

"""
Interface of the utils function of the DPNP

Notes
-----
This module is a face or public interface file for the library

"""

import dpnp

__all__ = ["byte_bounds"]


def byte_bounds(a):
"""
Returns a 2-tuple with pointers to the end-points of the array.

For full documentation refer to
:obj:`numpy.lib.array_utils.byte_bounds`.

Parameters
----------
a : {dpnp.ndarray, usm_ndarray}
Input array

Returns
-------
(low, high) : tuple of 2 integers
The first integer is the first byte of the array, the second integer is
just past the last byte of the array. If `a` is not contiguous it will
not use every byte between the (`low`, `high`) values.

Examples
--------
>>> import dpnp as np
>>> I = np.eye(2, dtype=np.complex64);
>>> low, high = np.byte_bounds(I)
>>> high - low == I.size*I.itemsize
True
>>> I = np.eye(2);
>>> low, high = np.byte_bounds(I)
>>> high - low == I.size*I.itemsize
True

"""

# pylint: disable=protected-access
return dpnp.get_usm_ndarray(a)._byte_bounds
39 changes: 39 additions & 0 deletions tests/test_array_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import dpnp


def test_byte_bounds():
a = dpnp.zeros((3, 4), dtype=dpnp.int64, usm_type="shared")
values = dpnp.arange(12, dtype="int64")
for i in range(3):
a[i, :] = values[i * 4 : (i + 1) * 4]
low, high = dpnp.byte_bounds(a)
assert (high - low) == (a.size * a.itemsize)


def test_unusual_order_positive_stride():
a = dpnp.zeros((3, 4), dtype=dpnp.int64, usm_type="shared")
values = dpnp.arange(12, dtype="int64")
for i in range(3):
a[i, :] = values[i * 4 : (i + 1) * 4]
b = a.T
low, high = dpnp.byte_bounds(b)
assert (high - low) == (b.size * b.itemsize)


def test_unusual_order_negative_stride():
a = dpnp.zeros((3, 4), dtype=dpnp.int64, usm_type="shared")
values = dpnp.arange(12, dtype="int64")
for i in range(3):
a[i, :] = values[i * 4 : (i + 1) * 4]
b = a.T[::-1]
low, high = dpnp.byte_bounds(b)
assert (high - low) == (b.size * b.itemsize)


def test_strided():
a = dpnp.zeros(12, dtype=dpnp.int64, usm_type="shared")
a[:] = dpnp.arange(12, dtype="int64")
b = a[::2]
low, high = dpnp.byte_bounds(b)
expected_byte_diff = b.size * 2 * b.itemsize - b.itemsize
assert (high - low) == expected_byte_diff
Empty file.
75 changes: 75 additions & 0 deletions tests/third_party/cupy/misc_tests/test_byte_bounds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import dpnp as cupy


def test_1d_contiguous():
a = cupy.zeros(12, dtype=cupy.int64)
itemsize = a.itemsize
a_low = a.get_array()._pointer
a_high = a.get_array()._pointer + 12 * itemsize
assert cupy.byte_bounds(a) == (a_low, a_high)


def test_2d_contiguous():
a = cupy.zeros((4, 7), dtype=cupy.int64)
itemsize = a.itemsize
a_low = a.get_array()._pointer
a_high = a.get_array()._pointer + 4 * 7 * itemsize
assert cupy.byte_bounds(a) == (a_low, a_high)


def test_1d_noncontiguous_pos_stride():
a = cupy.zeros(12, dtype=cupy.int64)
itemsize = a.itemsize
b = a[::2]
b_low = b.get_array()._pointer
b_high = b.get_array()._pointer + 11 * itemsize # a[10]
assert cupy.byte_bounds(b) == (b_low, b_high)


def test_2d_noncontiguous_pos_stride():
a = cupy.zeros((4, 7), dtype=cupy.int64)
b = a[::2, ::2]
itemsize = b.itemsize
b_low = a.get_array()._pointer
b_high = b.get_array()._pointer + 3 * 7 * itemsize # a[2][6]
assert cupy.byte_bounds(b) == (b_low, b_high)


def test_1d_contiguous_neg_stride():
a = cupy.zeros(12, dtype=cupy.int64)
b = a[::-1]
itemsize = b.itemsize
b_low = b.get_array()._pointer - 11 * itemsize
b_high = b.get_array()._pointer + 1 * itemsize
assert cupy.byte_bounds(b) == (b_low, b_high)


def test_2d_noncontiguous_neg_stride():
a = cupy.zeros((4, 7), dtype=cupy.int64)
b = a[::-2, ::-2] # strides = (-56, -8), shape = (2, 4)
itemsize = b.itemsize
b_low = (
b.get_array()._pointer
- 2 * 7 * itemsize * (2 - 1)
- 2 * itemsize * (4 - 1)
)
b_high = b.get_array()._pointer + 1 * itemsize
assert cupy.byte_bounds(b) == (b_low, b_high)


def test_2d_noncontiguous_posneg_stride_1():
a = cupy.zeros((4, 7), dtype=cupy.int64)
b = a[::1, ::-1] # strides = (28, -4), shape=(4, 7)
itemsize = b.itemsize
b_low = b.get_array()._pointer - itemsize * (7 - 1)
b_high = b.get_array()._pointer + 1 * itemsize + 7 * itemsize * (4 - 1)
assert cupy.byte_bounds(b) == (b_low, b_high)


def test_2d_noncontiguous_posneg_stride_2():
a = cupy.zeros((4, 7), dtype=cupy.int64)
b = a[::2, ::-2] # strides = (56, -8), shape=(2, 4)
itemsize = b.itemsize
b_low = b.get_array()._pointer - 2 * itemsize * (4 - 1)
b_high = b.get_array()._pointer + 1 * itemsize + 2 * 7 * itemsize * (2 - 1)
assert cupy.byte_bounds(b) == (b_low, b_high)
Loading