• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IntelPython / dpnp / 24687578389

20 Apr 2026 08:03PM UTC coverage: 78.429% (-3.6%) from 82.034%
24687578389

push

github

web-flow
Migrate `dpctl.tensor` into `dpnp.tensor` (#2856)

This PR migrates the tensor implementation from `dpctl.tensor` into
`dpnp.tensor` making dpnp the primary owner of the Array API-compliant
tensor layer

Major changes:

- Move compiled C++/SYCL extensions (`_tensor_impl,
_tensor_elementwise_impl, _tensor_reductions_impl, _tensor_sorting_impl,
_tensor_accumulation_impl, tensor linalg`) into `dpnp.tensor`
- Move `usm_ndarray`, `compute-follows-data utilities` and tensor
`tests` from dpctl
- Replace all `dpctl.tensor` references with `dpnp.tensor` in
docstrings, error messages and comments
- Remove redundant dpctl.tensor C-API  interface
- Add `tensor.rst` documentation page describing the module, its
relationship to `dpnp.ndarray` and `dpctl` and linking to the `dpctl
0.21.1 API` reference

This simplifies maintenance, reduces cross-project dependencies and
enables independent development and release cycles

1573 of 2908 branches covered (54.09%)

Branch coverage included in aggregate %.

6973 of 9803 new or added lines in 203 files covered. (71.13%)

1 existing line in 1 file now uncovered.

26259 of 32579 relevant lines covered (80.6%)

7622.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.0
/dpnp/tensor/libtensor/include/utils/type_utils.hpp
1
//*****************************************************************************
2
// Copyright (c) 2026, 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
// - Neither the name of the copyright holder nor the names of its contributors
13
//   may be used to endorse or promote products derived from this software
14
//   without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26
// THE POSSIBILITY OF SUCH DAMAGE.
27
//*****************************************************************************
28
///
29
/// \file
30
/// This file defines functions for value casting.
31
//===----------------------------------------------------------------------===//
32

33
#pragma once
34

35
#include <complex>
36
#include <cstddef>
37
#include <cstdint>
38
#include <stdexcept>
39
#include <type_traits>
40
#include <utility>
41

42
#include <sycl/sycl.hpp>
43

44
namespace dpnp::tensor::type_utils
45
{
46
template <typename T, typename = void>
47
struct is_complex : public std::false_type
48
{
49
};
50

51
template <typename T>
52
struct is_complex<
53
    T,
54
    std::enable_if_t<std::is_same_v<std::remove_cv_t<T>, std::complex<float>> ||
55
                     std::is_same_v<std::remove_cv_t<T>, std::complex<double>>>>
56
    : public std::true_type
57
{
58
};
59

60
template <typename T>
61
inline constexpr bool is_complex_v = is_complex<T>::value;
62

63
template <typename dstTy, typename srcTy>
64
dstTy convert_impl(const srcTy &v)
65
{
66
    if constexpr (std::is_same_v<dstTy, srcTy>) {
67
        return v;
68
    }
69
    else if constexpr (std::is_same_v<dstTy, bool>) {
70
        if constexpr (is_complex_v<srcTy>) {
71
            // bool(complex_v) ==
72
            //     (complex_v.real() != 0) && (complex_v.imag() !=0)
73
            return (convert_impl<bool, typename srcTy::value_type>(v.real()) ||
74
                    convert_impl<bool, typename srcTy::value_type>(v.imag()));
75
        }
76
        else {
77
            return static_cast<dstTy>(v != srcTy{0});
78
        }
79
    }
80
    else if constexpr (std::is_same_v<srcTy, bool>) {
81
        // C++ interprets a byte of storage behind bool by only
82
        // testing is least significant bit, leading to both
83
        // 0x00 and 0x02 interpreted as False, while 0x01 and 0xFF
84
        // interpreted as True. NumPy's interpretation of underlying
85
        // storage is different: any bit set is interpreted as True,
86
        // no bits set as False, see gh-2121
87
        const std::uint8_t &u = sycl::bit_cast<std::uint8_t>(v);
88
        if constexpr (is_complex_v<dstTy>) {
89
            return (u == 0) ? dstTy{} : dstTy{1, 0};
90
        }
91
        else {
92
            return (u == 0) ? dstTy{} : dstTy{1};
93
        }
94
    }
95
    else if constexpr (is_complex_v<srcTy> && !is_complex_v<dstTy>) {
96
        // real_t(complex_v) == real_t(complex_v.real())
97
        return convert_impl<dstTy, typename srcTy::value_type>(v.real());
98
    }
99
    else if constexpr (!std::is_integral_v<srcTy> &&
100
                       !std::is_same_v<dstTy, bool> &&
101
                       std::is_integral_v<dstTy> && std::is_unsigned_v<dstTy>) {
102
        // first cast to signed variant, the cast to unsigned one
103
        using signedT = typename std::make_signed_t<dstTy>;
104
        return static_cast<dstTy>(convert_impl<signedT, srcTy>(v));
105
    }
106
    else {
107
        return static_cast<dstTy>(v);
108
    }
109
}
110

111
template <typename T>
112
void validate_type_for_device(const sycl::device &d)
113
{
82,236✔
114
    if constexpr (std::is_same_v<T, double>) {
82,236✔
115
        if (!d.has(sycl::aspect::fp64)) {
45,051!
NEW
116
            throw std::runtime_error("Device " +
×
NEW
117
                                     d.get_info<sycl::info::device::name>() +
×
NEW
118
                                     " does not support type 'float64'");
×
NEW
119
        }
×
120
    }
121
    else if constexpr (std::is_same_v<T, std::complex<double>>) {
10,646✔
122
        if (!d.has(sycl::aspect::fp64)) {
10,646!
NEW
123
            throw std::runtime_error("Device " +
×
NEW
124
                                     d.get_info<sycl::info::device::name>() +
×
NEW
125
                                     " does not support type 'complex128'");
×
NEW
126
        }
×
127
    }
128
    else if constexpr (std::is_same_v<T, sycl::half>) {
43✔
129
        if (!d.has(sycl::aspect::fp16)) {
43!
NEW
130
            throw std::runtime_error("Device " +
×
NEW
131
                                     d.get_info<sycl::info::device::name>() +
×
NEW
132
                                     " does not support type 'float16'");
×
NEW
133
        }
×
134
    }
43✔
135
}
82,236✔
136

137
template <typename T>
138
void validate_type_for_device(const sycl::queue &q)
139
{
82,236✔
140
    validate_type_for_device<T>(q.get_device());
82,236✔
141
}
82,236✔
142

143
template <typename Op, typename Vec, std::size_t... I>
144
auto vec_cast_impl(const Vec &v, std::index_sequence<I...>)
145
{
146
    return Op{v[I]...};
147
}
148

149
template <typename dstT,
150
          typename srcT,
151
          std::size_t N,
152
          typename Indices = std::make_index_sequence<N>>
153
auto vec_cast(const sycl::vec<srcT, N> &s)
154
{
155
    if constexpr (std::is_same_v<srcT, dstT>) {
156
        return s;
157
    }
158
    else {
159
        return vec_cast_impl<sycl::vec<dstT, N>, sycl::vec<srcT, N>>(s,
160
                                                                     Indices{});
161
    }
162
}
163
} // namespace dpnp::tensor::type_utils
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc