27#ifndef BACKEND_UTILS_H
28#define BACKEND_UTILS_H
37#include <sycl/sycl.hpp>
39#include <dpnp_iface_fptr.hpp>
41#define LIBSYCL_VERSION_GREATER(major, minor, patch) \
42 (__LIBSYCL_MAJOR_VERSION > major) || \
43 (__LIBSYCL_MAJOR_VERSION == major and \
44 __LIBSYCL_MINOR_VERSION > minor) || \
45 (__LIBSYCL_MAJOR_VERSION == major and \
46 __LIBSYCL_MINOR_VERSION == minor and \
47 __LIBSYCL_PATCH_VERSION >= patch)
53#ifndef __SYCL_COMPILER_VECTOR_ABS_CHANGED
54#define __SYCL_COMPILER_VECTOR_ABS_CHANGED 20230503L
60#ifndef __INTEL_MKL_2023_0_0_VERSION_REQUIRED
61#define __INTEL_MKL_2023_0_0_VERSION_REQUIRED 20230000
70#ifndef __INTEL_MKL_2023_2_0_VERSION_REQUIRED
71#define __INTEL_MKL_2023_2_0_VERSION_REQUIRED 20230002L
94template <
typename _DataType>
99 size_t dim_prod_input = 1;
100 for (
size_t i = 0; i < shape_size; ++i) {
101 long i_reverse = shape_size - 1 - i;
102 offsets[i_reverse] = dim_prod_input;
103 dim_prod_input *= shape[i_reverse];
125template <
typename _DataType>
127 const _DataType *offsets,
134 assert(axis < offsets_size);
136 _DataType xyz_id = 0;
137 long reminder = global_id;
138 for (
size_t i = 0; i < axis + 1; ++i) {
139 const _DataType axis_val = offsets[i];
140 xyz_id = reminder / axis_val;
141 reminder = reminder % axis_val;
158 broadcastable(
const std::vector<shape_elem_type> &input_shape,
159 const std::vector<shape_elem_type> &output_shape)
161 if (input_shape.size() > output_shape.size()) {
165 std::vector<shape_elem_type>::const_reverse_iterator irit =
166 input_shape.rbegin();
167 std::vector<shape_elem_type>::const_reverse_iterator orit =
168 output_shape.rbegin();
169 for (; irit != input_shape.rend(); ++irit, ++orit) {
170 if (*irit != 1 && *irit != *orit) {
179 broadcastable(
const shape_elem_type *input_shape,
180 const size_t input_shape_size,
181 const std::vector<shape_elem_type> &output_shape)
183 const std::vector<shape_elem_type> input_shape_vec(
184 input_shape, input_shape + input_shape_size);
185 return broadcastable(input_shape_vec, output_shape);
199template <
typename _DataType>
200static inline bool array_equal(
const _DataType *input1,
201 const size_t input1_size,
202 const _DataType *input2,
203 const size_t input2_size)
205 if (input1_size != input2_size)
208 const std::vector<_DataType> input1_vec(input1, input1 + input1_size);
209 const std::vector<_DataType> input2_vec(input2, input2 + input2_size);
211 return std::equal(std::begin(input1_vec), std::end(input1_vec),
212 std::begin(input2_vec));
234static inline std::vector<shape_elem_type>
235 get_validated_axes(
const std::vector<shape_elem_type> &__axes,
236 const size_t __shape_size,
237 const bool __allow_duplicate =
false)
239 std::vector<shape_elem_type> result;
241 if (__axes.empty()) {
245 if (__axes.size() > __shape_size) {
249 result.reserve(__axes.size());
250 for (std::vector<shape_elem_type>::const_iterator it = __axes.cbegin();
251 it != __axes.cend(); ++it)
253 const shape_elem_type _axis = *it;
254 const shape_elem_type input_shape_size_signed =
255 static_cast<shape_elem_type
>(__shape_size);
256 if (_axis >= input_shape_size_signed) {
260 if (_axis < -input_shape_size_signed) {
264 const shape_elem_type positive_axis =
265 _axis < 0 ? (_axis + input_shape_size_signed) : _axis;
267 if (!__allow_duplicate) {
268 if (std::find(result.begin(), result.end(), positive_axis) !=
274 result.push_back(positive_axis);
283 throw std::range_error(
284 "DPNP Error: validate_axes() failed with axis check");
298static inline void validate_type_for_device(
const sycl::device &d)
300 if constexpr (std::is_same_v<T, double>) {
301 if (!d.has(sycl::aspect::fp64)) {
302 throw std::runtime_error(
"Device " +
303 d.get_info<sycl::info::device::name>() +
304 " does not support type 'double'");
307 else if constexpr (std::is_same_v<T, std::complex<double>>) {
308 if (!d.has(sycl::aspect::fp64)) {
309 throw std::runtime_error(
310 "Device " + d.get_info<sycl::info::device::name>() +
311 " does not support type 'complex<double>'");
314 else if constexpr (std::is_same_v<T, sycl::half>) {
315 if (!d.has(sycl::aspect::fp16)) {
316 throw std::runtime_error(
"Device " +
317 d.get_info<sycl::info::device::name>() +
318 " does not support type 'half'");
334static inline void validate_type_for_device(
const sycl::queue &q)
336 validate_type_for_device<T>(q.get_device());
348std::ostream &
operator<<(std::ostream &out,
const std::vector<T> &vec)
350 std::string delimiter;
355 for (
auto &elem : vec) {
356 out << delimiter << elem;
357 if (delimiter.empty()) {
358 delimiter.assign(
", ");
378 out << static_cast<size_t>(elem);
DPNPFuncType
Template types which are used in this interface.
std::ostream & operator<<(std::ostream &out, const std::vector< T > &vec)
print std::vector to std::ostream.
void get_shape_offsets_inkernel(const _DataType *shape, size_t shape_size, _DataType *offsets)
Shape offset calculation used in kernels.
_DataType get_xyz_id_by_id_inkernel(size_t global_id, const _DataType *offsets, size_t offsets_size, size_t axis)
Calculate xyz id for given axis from linear index.