Skip to content

Commit 9fb1e59

Browse files
Apply review comments
1 parent 16e2bee commit 9fb1e59

File tree

3 files changed

+71
-55
lines changed

3 files changed

+71
-55
lines changed

dpnp/dpnp_iface_histograms.py

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,18 @@
4242

4343
import dpctl.utils as dpu
4444
import numpy
45-
from dpctl.tensor._type_utils import _can_cast
4645

4746
import dpnp
4847

4948
# pylint: disable=no-name-in-module
5049
import dpnp.backend.extensions.statistics._statistics_impl as statistics_ext
50+
from dpnp.dpnp_utils.dpnp_utils_common import (
51+
result_type_for_device,
52+
to_supported_dtypes,
53+
)
5154

5255
# pylint: disable=no-name-in-module
53-
from .dpnp_utils import get_usm_allocations, map_dtype_to_device
56+
from .dpnp_utils import get_usm_allocations
5457

5558
__all__ = [
5659
"bincount",
@@ -66,33 +69,15 @@
6669
_range = range
6770

6871

69-
def _result_type_for_device(dtypes, device):
70-
rt = dpnp.result_type(*dtypes)
71-
return map_dtype_to_device(rt, device)
72-
73-
7472
def _align_dtypes(a_dtype, bins_dtype, ntype, supported_types, device):
75-
has_fp64 = device.has_aspect_fp64
76-
has_fp16 = device.has_aspect_fp16
77-
78-
a_bin_dtype = _result_type_for_device([a_dtype, bins_dtype], device)
73+
a_bin_dtype = result_type_for_device([a_dtype, bins_dtype], device)
7974

8075
# histogram implementation doesn't support uint64 as histogram type
8176
# we can use int64 instead. Result would be correct even in case of overflow
8277
if ntype == numpy.uint64:
8378
ntype = dpnp.int64
8479

85-
if (a_bin_dtype, ntype) in supported_types:
86-
return a_bin_dtype, ntype
87-
88-
for sample_type, hist_type in supported_types:
89-
if _can_cast(
90-
a_bin_dtype, sample_type, has_fp16, has_fp64
91-
) and _can_cast(ntype, hist_type, has_fp16, has_fp64):
92-
return sample_type, hist_type
93-
94-
# should not happen
95-
return None, None
80+
return to_supported_dtypes([a_bin_dtype, ntype], supported_types, device)
9681

9782

9883
def _ravel_check_a_and_weights(a, weights):
@@ -524,6 +509,7 @@ def histogram(a, bins=10, range=None, density=None, weights=None):
524509
If `bins` is a sequence, it defines a monotonically increasing array
525510
of bin edges, including the rightmost edge, allowing for non-uniform
526511
bin widths.
512+
527513
Default: ``10``.
528514
range : {None, 2-tuple of float}, optional
529515
The lower and upper range of the bins. If not provided, range is simply
@@ -532,6 +518,7 @@ def histogram(a, bins=10, range=None, density=None, weights=None):
532518
affects the automatic bin computation as well. While bin width is
533519
computed to be optimal based on the actual data within `range`, the bin
534520
count will fill the entire range including portions containing no data.
521+
535522
Default: ``None``.
536523
density : {None, bool}, optional
537524
If ``False`` or ``None``, the result will contain the number of samples
@@ -540,6 +527,7 @@ def histogram(a, bins=10, range=None, density=None, weights=None):
540527
the range is ``1``. Note that the sum of the histogram values will not
541528
be equal to ``1`` unless bins of unity width are chosen; it is not
542529
a probability *mass* function.
530+
543531
Default: ``None``.
544532
weights : {None, dpnp.ndarray, usm_ndarray}, optional
545533
An array of weights, of the same shape as `a`. Each value in `a` only
@@ -549,6 +537,7 @@ def histogram(a, bins=10, range=None, density=None, weights=None):
549537
Please note that the ``dtype`` of `weights` will also become the
550538
``dtype`` of the returned accumulator (`hist`), so it must be large
551539
enough to hold accumulated values as well.
540+
552541
Default: ``None``.
553542
554543
Returns
@@ -782,29 +771,31 @@ def histogram2d(x, y, bins=10, range=None, density=None, weights=None):
782771
* A combination [int, array] or [array, int], where int
783772
is the number of bins and array is the bin edges.
784773
785-
Default: ``10``
774+
Default: ``10``.
786775
range : {None, dpnp.ndarray, usm_ndarray} of shape (2,2), optional
787776
The leftmost and rightmost edges of the bins along each dimension
788-
(if not specified explicitly in the `bins` parameters):
789-
``[[xmin, xmax], [ymin, ymax]]``. All values outside of this range
790-
will be considered outliers and not tallied in the histogram.
777+
If ``None`` the ranges are
778+
``[[x.min(), x.max()], [y.min(), y.max()]]``. All values outside
779+
of this range will be considered outliers and not tallied in the
780+
histogram.
791781
792-
Default: ``None``
782+
Default: ``None``.
793783
density : {None, bool}, optional
794784
If ``False`` or ``None``, the default, returns the number of
795785
samples in each bin.
796786
If ``True``, returns the probability *density* function at the bin,
797787
``bin_count / sample_count / bin_volume``.
798788
799-
Default: ``None``
789+
Default: ``None``.
800790
weights : {None, dpnp.ndarray, usm_ndarray} of shape (N,), optional
801791
An array of values ``w_i`` weighing each sample ``(x_i, y_i)``.
802792
Weights are normalized to ``1`` if `density` is ``True``.
803793
If `density` is ``False``, the values of the returned histogram
804794
are equal to the sum of the weights belonging to the samples
805795
falling into each bin.
796+
If ``None`` all samples are assigned a weight of ``1``.
806797
807-
Default: ``None``
798+
Default: ``None``.
808799
Returns
809800
-------
810801
H : dpnp.ndarray of shape (nx, ny)
@@ -836,18 +827,27 @@ def histogram2d(x, y, bins=10, range=None, density=None, weights=None):
836827
Examples
837828
--------
838829
>>> import dpnp as np
839-
>>> x = np.random.randn(20)
840-
>>> y = np.random.randn(20)
830+
>>> x = np.random.randn(20).astype("float32")
831+
>>> y = np.random.randn(20).astype("float32")
841832
>>> hist, edges_x, edges_y = np.histogram2d(x, y, bins=(4, 3))
833+
>>> hist.shape
834+
(4, 3)
842835
>>> hist
843-
[[1. 0. 0.]
844-
[0. 0. 0.]
845-
[5. 6. 4.]
846-
[1. 2. 1.]]
836+
array([[1., 2., 0.],
837+
[0., 3., 1.],
838+
[1., 4., 1.],
839+
[1., 3., 3.]], dtype=float32)
840+
>>> edges_x.shape
841+
(5,)
847842
>>> edges_x
848-
[-5.6575713 -3.5574734 -1.4573755 0.6427226 2.74282 ]
843+
array([-1.7516936 , -0.96109843, -0.17050326, 0.62009203, 1.4106871 ],
844+
dtype=float32)
845+
>>> edges_y.shape
846+
(4,)
849847
>>> edges_y
850-
[-1.1889046 -0.07263839 1.0436279 2.159894 ]
848+
array([-2.6604428 , -0.94615364, 0.76813555, 2.4824247 ], dtype=float32)
849+
850+
Please note, that resulting values of histogram and edges would be different
851851
"""
852852

853853
dpnp.check_supported_arrays_type(x, y)
@@ -869,7 +869,7 @@ def histogram2d(x, y, bins=10, range=None, density=None, weights=None):
869869
usm_type, exec_q = get_usm_allocations([x, y, bins, range, weights])
870870
device = exec_q.sycl_device
871871

872-
sample_dtype = _result_type_for_device([x.dtype, y.dtype], device)
872+
sample_dtype = result_type_for_device([x.dtype, y.dtype], device)
873873

874874
# Unlike histogramdd histogram2d accepts 1d bins and
875875
# apply it to both dimensions
@@ -883,7 +883,7 @@ def histogram2d(x, y, bins=10, range=None, density=None, weights=None):
883883
bins_dtypes = [sample_dtype]
884884
bins_dtypes += [b.dtype for b in bins if hasattr(b, "dtype")]
885885

886-
bins_dtype = _result_type_for_device(bins_dtypes, device)
886+
bins_dtype = result_type_for_device(bins_dtypes, device)
887887
hist_dtype = _histdd_hist_dtype(exec_q, weights)
888888

889889
supported_types = statistics_ext.histogramdd_dtypes()
@@ -1026,9 +1026,7 @@ def _histdd_hist_dtype(queue, weights):
10261026
# hist_dtype is either float or complex, so it is ok
10271027
# to calculate it as result type between default_float and
10281028
# weights.dtype
1029-
hist_dtype = _result_type_for_device(
1030-
[hist_dtype, weights.dtype], device
1031-
)
1029+
hist_dtype = result_type_for_device([hist_dtype, weights.dtype], device)
10321030

10331031
return hist_dtype
10341032

@@ -1039,7 +1037,7 @@ def _histdd_sample_dtype(queue, sample, bin_edges_list):
10391037
dtypes_ = [bin_edges.dtype for bin_edges in bin_edges_list]
10401038
dtypes_.append(sample.dtype)
10411039

1042-
return _result_type_for_device(dtypes_, device)
1040+
return result_type_for_device(dtypes_, device)
10431041

10441042

10451043
def _histdd_supported_dtypes(sample, bin_edges_list, weights):
@@ -1089,31 +1087,33 @@ def histogramdd(sample, bins=10, range=None, density=None, weights=None):
10891087
* The number of bins for each dimension (nx, ny, ... =bins)
10901088
* The number of bins for all dimensions (nx=ny=...=bins).
10911089
1092-
Default: ``10``
1090+
Default: ``10``.
10931091
range : {None, sequence}, optional
10941092
A sequence of length D, each an optional (lower, upper) tuple giving
10951093
the outer bin edges to be used if the edges are not given explicitly in
10961094
`bins`.
1097-
An entry of None in the sequence results in the minimum and maximum
1095+
An entry of ``None`` in the sequence results in the minimum and maximum
10981096
values being used for the corresponding dimension.
1099-
None is equivalent to passing a tuple of D None values.
1097+
``None`` is equivalent to passing a tuple of D ``None`` values.
11001098
1101-
Default: ``None``
1099+
Default: ``None``.
11021100
density : {None, bool}, optional
11031101
If ``False`` or ``None``, the default, returns the number of
11041102
samples in each bin.
11051103
If ``True``, returns the probability *density* function at the bin,
11061104
``bin_count / sample_count / bin_volume``.
11071105
1108-
Default: ``None``
1109-
weights : {dpnp.ndarray, usm_ndarray}, optional
1106+
Default: ``None``.
1107+
weights : {None, dpnp.ndarray, usm_ndarray}, optional
11101108
An (N,)-shaped array of values `w_i` weighing each sample
11111109
`(x_i, y_i, z_i, ...)`.
1112-
Weights are normalized to 1 if density is True. If density is False,
1113-
the values of the returned histogram are equal to the sum of the
1114-
weights belonging to the samples falling into each bin.
1110+
Weights are normalized to ``1`` if density is ``True``.
1111+
If density is ``False``, the values of the returned histogram
1112+
are equal to the sum of the weights belonging to the samples
1113+
falling into each bin.
1114+
If ``None`` all samples are assigned a weight of ``1``.
11151115
1116-
Default: ``None``
1116+
Default: ``None``.
11171117
11181118
Returns
11191119
-------

dpnp/dpnp_utils/dpnp_utils_common.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ def to_supported_dtypes(dtypes, supported_types, device):
5454
def is_castable(dtype, stype):
5555
return _can_cast(dtype, stype, has_fp16, has_fp64)
5656

57+
if not isinstance(supported_types, Iterable):
58+
supported_types = (supported_types,)
59+
60+
if isinstance(dtypes, Iterable):
61+
sdtypes_elem = supported_types[0]
62+
if not isinstance(sdtypes_elem, Iterable):
63+
raise ValueError(
64+
"Input and supported types must have the same length"
65+
)
66+
67+
typ = type(sdtypes_elem)
68+
dtypes = typ(dtypes)
69+
5770
if dtypes in supported_types:
5871
return dtypes
5972

@@ -78,4 +91,7 @@ def is_castable(dtype, stype):
7891
):
7992
return stypes
8093

81-
return None
94+
if not isinstance(dtypes, Iterable):
95+
return None
96+
97+
return (None,) * len(dtypes)

dpnp/tests/test_histogram.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ def test_2d(self):
930930
def test_finite_range(self, xp):
931931
x = y = xp.linspace(0.0, 1.0, num=100)
932932

933-
# normal ranges should be fine
933+
# normal ranges should be finite
934934
_, _, _ = xp.histogram2d(x, y, range=[[0.25, 0.75]] * 2)
935935
assert_raises(
936936
ValueError, xp.histogram2d, x, y, range=[[xp.nan, 0.75]] * 2

0 commit comments

Comments
 (0)