Skip to content

Commit e22975b

Browse files
committed
implement dpnp.bartlett
1 parent 25fb39b commit e22975b

File tree

7 files changed

+183
-5
lines changed

7 files changed

+183
-5
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//*****************************************************************************
2+
// Copyright (c) 2025, Intel Corporation
3+
// All rights reserved.
4+
//
5+
// Redistribution and use in source and binary forms, with or without
6+
// modification, are permitted provided that the following conditions are met:
7+
// - Redistributions of source code must retain the above copyright notice,
8+
// this list of conditions and the following disclaimer.
9+
// - Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
//
13+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
// THE POSSIBILITY OF SUCH DAMAGE.
24+
//*****************************************************************************
25+
26+
#pragma once
27+
28+
#include "common.hpp"
29+
#include <sycl/sycl.hpp>
30+
31+
namespace dpnp::extensions::window::kernels
32+
{
33+
34+
template <typename T>
35+
class BartlettFunctor
36+
{
37+
private:
38+
T *data = nullptr;
39+
const std::size_t N;
40+
41+
public:
42+
BartlettFunctor(T *data, const std::size_t N) : data(data), N(N) {}
43+
44+
void operator()(sycl::id<1> id) const
45+
{
46+
const auto i = id.get(0);
47+
48+
data[i] =
49+
T(2) / (N - 1) * ((N - 1) / T(2) - sycl::fabs(i - (N - 1) / T(2)));
50+
}
51+
};
52+
53+
template <typename fnT, typename T>
54+
struct BartlettFactory
55+
{
56+
fnT get()
57+
{
58+
if constexpr (std::is_floating_point_v<T>) {
59+
return window_impl<T, BartlettFunctor>;
60+
}
61+
else {
62+
return nullptr;
63+
}
64+
}
65+
};
66+
67+
} // namespace dpnp::extensions::window::kernels

dpnp/backend/extensions/window/window_py.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <pybind11/pybind11.h>
3131
#include <pybind11/stl.h>
3232

33+
#include "bartlett.hpp"
3334
#include "blackman.hpp"
3435
#include "common.hpp"
3536
#include "hamming.hpp"
@@ -41,6 +42,7 @@ using window_ns::window_fn_ptr_t;
4142

4243
namespace dpctl_td_ns = dpctl::tensor::type_dispatch;
4344

45+
static window_fn_ptr_t bartlett_dispatch_vector[dpctl_td_ns::num_types];
4446
static window_fn_ptr_t blackman_dispatch_vector[dpctl_td_ns::num_types];
4547
static window_fn_ptr_t hamming_dispatch_vector[dpctl_td_ns::num_types];
4648
static window_fn_ptr_t hanning_dispatch_vector[dpctl_td_ns::num_types];
@@ -50,6 +52,21 @@ PYBIND11_MODULE(_window_impl, m)
5052
using arrayT = dpctl::tensor::usm_ndarray;
5153
using event_vecT = std::vector<sycl::event>;
5254

55+
{
56+
window_ns::init_window_dispatch_vectors<
57+
window_ns::kernels::BartlettFactory>(bartlett_dispatch_vector);
58+
59+
auto bartlett_pyapi = [&](sycl::queue &exec_q, const arrayT &result,
60+
const event_vecT &depends = {}) {
61+
return window_ns::py_window(exec_q, result, depends,
62+
bartlett_dispatch_vector);
63+
};
64+
65+
m.def("_bartlett", bartlett_pyapi, "Call Bartlett kernel",
66+
py::arg("sycl_queue"), py::arg("result"),
67+
py::arg("depends") = py::list());
68+
}
69+
5370
{
5471
window_ns::init_window_dispatch_vectors<
5572
window_ns::kernels::BlackmanFactory>(blackman_dispatch_vector);

dpnp/dpnp_iface_window.py

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import dpnp
4646
import dpnp.backend.extensions.window._window_impl as wi
4747

48-
__all__ = ["blackman", "hamming", "hanning"]
48+
__all__ = ["bartlett", "blackman", "hamming", "hanning"]
4949

5050

5151
def _call_window_kernel(
@@ -174,6 +174,99 @@ def blackman(M, device=None, usm_type=None, sycl_queue=None):
174174
)
175175

176176

177+
def bartlett(M, device=None, usm_type=None, sycl_queue=None):
178+
r"""
179+
Return the Bartlett window.
180+
181+
The Bartlett window is very similar to a triangular window, except that the
182+
end points are at zero. It is often used in signal processing for tapering
183+
a signal, without generating too much ripple in the frequency domain.
184+
185+
For full documentation refer to :obj:`numpy.bartlett`.
186+
187+
Parameters
188+
----------
189+
M : int
190+
Number of points in the output window. If zero or less, an empty array
191+
is returned.
192+
device : {None, string, SyclDevice, SyclQueue, Device}, optional
193+
An array API concept of device where the output array is created.
194+
`device` can be ``None``, a oneAPI filter selector string, an instance
195+
of :class:`dpctl.SyclDevice` corresponding to a non-partitioned SYCL
196+
device, an instance of :class:`dpctl.SyclQueue`, or a
197+
:class:`dpctl.tensor.Device` object returned by
198+
:attr:`dpnp.ndarray.device`.
199+
200+
Default: ``None``.
201+
usm_type : {None, "device", "shared", "host"}, optional
202+
The type of SYCL USM allocation for the output array.
203+
204+
Default: ``None``.
205+
sycl_queue : {None, SyclQueue}, optional
206+
A SYCL queue to use for output array allocation and copying. The
207+
`sycl_queue` can be passed as ``None`` (the default), which means
208+
to get the SYCL queue from `device` keyword if present or to use
209+
a default queue.
210+
211+
Default: ``None``.
212+
213+
Returns
214+
-------
215+
out : dpnp.ndarray of shape (M,)
216+
The triangular window, with the maximum value normalized to one
217+
(the value one appears only if the number of samples is odd), with the
218+
first and last samples equal to zero.
219+
220+
See Also
221+
--------
222+
:obj:`dpnp.blackman` : Return the Blackman window.
223+
:obj:`dpnp.hamming` : Return the Hamming window.
224+
:obj:`dpnp.hanning` : Return the Hanning window.
225+
:obj:`dpnp.kaiser` : Return the Kaiser window.
226+
227+
Notes
228+
-----
229+
The Bartlett window is defined as
230+
231+
.. math:: w(n) = \frac{2}{M-1} \left(\frac{M-1}{2} -
232+
\left|n - \frac{M-1}{2}\right|\right)
233+
234+
Examples
235+
--------
236+
>>> import dpnp as np
237+
>>> np.bartlett(12)
238+
array([0. , 0.18181818, 0.36363636, 0.54545455, 0.72727273,
239+
0.90909091, 0.90909091, 0.72727273, 0.54545455, 0.36363636,
240+
0.18181818, 0. ])
241+
242+
Creating the output array on a different device or with a
243+
specified usm_type:
244+
245+
>>> x = np.bartlett(4) # default case
246+
>>> x, x.device, x.usm_type
247+
(array([0. , 0.66666667, 0.66666667, 0. ]),
248+
Device(level_zero:gpu:0),
249+
'device')
250+
251+
>>> y = np.bartlett(4, device="cpu")
252+
>>> y, y.device, y.usm_type
253+
(array([0. , 0.66666667, 0.66666667, 0. ]),
254+
Device(opencl:cpu:0),
255+
'device')
256+
257+
>>> z = np.bartlett(4, usm_type="host")
258+
>>> z, z.device, z.usm_type
259+
(array([0. , 0.66666667, 0.66666667, 0. ]),
260+
Device(level_zero:gpu:0),
261+
'host')
262+
263+
"""
264+
265+
return _call_window_kernel(
266+
M, wi._bartlett, device=device, usm_type=usm_type, sycl_queue=sycl_queue
267+
)
268+
269+
177270
def hamming(M, device=None, usm_type=None, sycl_queue=None):
178271
r"""
179272
Return the Hamming window.

dpnp/tests/test_sycl_queue.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def assert_sycl_queue_equal(result, expected):
5353
"func, arg, kwargs",
5454
[
5555
pytest.param("arange", [-25.7], {"stop": 10**8, "step": 15}),
56+
pytest.param("bartlett", [10], {}),
5657
pytest.param("blackman", [10], {}),
5758
pytest.param("eye", [4, 2], {}),
5859
pytest.param("empty", [(2, 2)], {}),

dpnp/tests/test_usm_type.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ def test_array_creation_from_array(func, args, usm_type_x, usm_type_y):
177177
"func, arg, kwargs",
178178
[
179179
pytest.param("arange", [-25.7], {"stop": 10**8, "step": 15}),
180+
pytest.param("bartlett", [10], {}),
180181
pytest.param("blackman", [10], {}),
181182
pytest.param("eye", [4, 2], {}),
182183
pytest.param("empty", [(3, 4)], {}),

dpnp/tests/test_window.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from .helper import assert_dtype_allclose
88

99

10-
@pytest.mark.parametrize("func", ["blackman", "hamming", "hanning"])
10+
@pytest.mark.parametrize("func", ["bartlett", "blackman", "hamming", "hanning"])
1111
@pytest.mark.parametrize(
1212
"M",
1313
[
@@ -32,7 +32,7 @@ def test_window(func, M):
3232
assert_dtype_allclose(result, expected)
3333

3434

35-
@pytest.mark.parametrize("func", ["blackman", "hamming", "hanning"])
35+
@pytest.mark.parametrize("func", ["bartlett", "blackman", "hamming", "hanning"])
3636
@pytest.mark.parametrize(
3737
"M",
3838
[

dpnp/tests/third_party/cupy/math_tests/test_window.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
*testing.product(
1111
{
1212
"m": [0, 1, -1, 1024],
13-
# TODO: add ["bartlett"] when supported
14-
"name": ["blackman", "hamming", "hanning"],
13+
"name": ["bartlett", "blackman", "hamming", "hanning"],
1514
}
1615
)
1716
)

0 commit comments

Comments
 (0)