diff --git a/doc/reference/ufunc.rst b/doc/reference/ufunc.rst index a5b64852bd4..bd1219117e0 100644 --- a/doc/reference/ufunc.rst +++ b/doc/reference/ufunc.rst @@ -54,6 +54,8 @@ Math operations Trigonometric functions ~~~~~~~~~~~~~~~~~~~~~~~ +All trigonometric functions use radians when an angle is called for. +The ratio of degrees to radians is :math:`180^{\circ}/\pi.` .. autosummary:: :toctree: generated/ @@ -73,6 +75,8 @@ Trigonometric functions dpnp.arcsinh dpnp.arccosh dpnp.arctanh + dpnp.degrees + dpnp.radians dpnp.deg2rad dpnp.rad2deg diff --git a/dpnp/backend/extensions/ufunc/CMakeLists.txt b/dpnp/backend/extensions/ufunc/CMakeLists.txt index 077710cb55c..bc926257822 100644 --- a/dpnp/backend/extensions/ufunc/CMakeLists.txt +++ b/dpnp/backend/extensions/ufunc/CMakeLists.txt @@ -29,6 +29,7 @@ set(_elementwise_sources ${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fmax.cpp ${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fmin.cpp ${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fmod.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/radians.cpp ) set(python_module_name _ufunc_impl) diff --git a/dpnp/backend/extensions/ufunc/elementwise_functions/common.cpp b/dpnp/backend/extensions/ufunc/elementwise_functions/common.cpp index e4af134f46d..bd59c2b6118 100644 --- a/dpnp/backend/extensions/ufunc/elementwise_functions/common.cpp +++ b/dpnp/backend/extensions/ufunc/elementwise_functions/common.cpp @@ -29,6 +29,7 @@ #include "fmax.hpp" #include "fmin.hpp" #include "fmod.hpp" +#include "radians.hpp" namespace py = pybind11; @@ -43,5 +44,6 @@ void init_elementwise_functions(py::module_ m) init_fmax(m); init_fmin(m); init_fmod(m); + init_radians(m); } } // namespace dpnp::extensions::ufunc diff --git a/dpnp/backend/extensions/ufunc/elementwise_functions/fabs.cpp b/dpnp/backend/extensions/ufunc/elementwise_functions/fabs.cpp index 7588e133473..69807c0ca71 100644 --- a/dpnp/backend/extensions/ufunc/elementwise_functions/fabs.cpp +++ b/dpnp/backend/extensions/ufunc/elementwise_functions/fabs.cpp @@ -40,19 +40,16 @@ #include "kernels/elementwise_functions/common.hpp" #include "utils/type_dispatch.hpp" -namespace py = pybind11; - namespace dpnp::extensions::ufunc { -namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; +namespace py = pybind11; namespace py_int = dpnp::extensions::py_internal; -namespace td_ns = dpctl::tensor::type_dispatch; - -using ew_cmn_ns::unary_contig_impl_fn_ptr_t; -using ew_cmn_ns::unary_strided_impl_fn_ptr_t; namespace impl { +namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; +namespace td_ns = dpctl::tensor::type_dispatch; + /** * @brief A factory to define pairs of supported types for which * sycl::fabs function is available. diff --git a/dpnp/backend/extensions/ufunc/elementwise_functions/fmax.cpp b/dpnp/backend/extensions/ufunc/elementwise_functions/fmax.cpp index 64f68d146be..9e39cc678f8 100644 --- a/dpnp/backend/extensions/ufunc/elementwise_functions/fmax.cpp +++ b/dpnp/backend/extensions/ufunc/elementwise_functions/fmax.cpp @@ -41,20 +41,17 @@ #include "kernels/elementwise_functions/maximum.hpp" #include "utils/type_dispatch.hpp" -namespace py = pybind11; - namespace dpnp::extensions::ufunc { -namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; -namespace max_ns = dpctl::tensor::kernels::maximum; +namespace py = pybind11; namespace py_int = dpnp::extensions::py_internal; namespace td_ns = dpctl::tensor::type_dispatch; -using ew_cmn_ns::unary_contig_impl_fn_ptr_t; -using ew_cmn_ns::unary_strided_impl_fn_ptr_t; - namespace impl { +namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; +namespace max_ns = dpctl::tensor::kernels::maximum; + // Supports the same types table as for maximum function in dpctl template using OutputType = max_ns::MaximumOutputType; diff --git a/dpnp/backend/extensions/ufunc/elementwise_functions/fmin.cpp b/dpnp/backend/extensions/ufunc/elementwise_functions/fmin.cpp index 0972ffde922..5b2ae0727b8 100644 --- a/dpnp/backend/extensions/ufunc/elementwise_functions/fmin.cpp +++ b/dpnp/backend/extensions/ufunc/elementwise_functions/fmin.cpp @@ -41,20 +41,17 @@ #include "kernels/elementwise_functions/minimum.hpp" #include "utils/type_dispatch.hpp" -namespace py = pybind11; - namespace dpnp::extensions::ufunc { -namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; -namespace min_ns = dpctl::tensor::kernels::minimum; +namespace py = pybind11; namespace py_int = dpnp::extensions::py_internal; namespace td_ns = dpctl::tensor::type_dispatch; -using ew_cmn_ns::unary_contig_impl_fn_ptr_t; -using ew_cmn_ns::unary_strided_impl_fn_ptr_t; - namespace impl { +namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; +namespace min_ns = dpctl::tensor::kernels::minimum; + // Supports the same types table as for minimum function in dpctl template using OutputType = min_ns::MinimumOutputType; diff --git a/dpnp/backend/extensions/ufunc/elementwise_functions/fmod.cpp b/dpnp/backend/extensions/ufunc/elementwise_functions/fmod.cpp index dbc215ec1f4..ff504548c9d 100644 --- a/dpnp/backend/extensions/ufunc/elementwise_functions/fmod.cpp +++ b/dpnp/backend/extensions/ufunc/elementwise_functions/fmod.cpp @@ -40,19 +40,16 @@ #include "kernels/elementwise_functions/common.hpp" #include "utils/type_dispatch.hpp" -namespace py = pybind11; - namespace dpnp::extensions::ufunc { -namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; +namespace py = pybind11; namespace py_int = dpnp::extensions::py_internal; -namespace td_ns = dpctl::tensor::type_dispatch; - -using ew_cmn_ns::unary_contig_impl_fn_ptr_t; -using ew_cmn_ns::unary_strided_impl_fn_ptr_t; namespace impl { +namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; +namespace td_ns = dpctl::tensor::type_dispatch; + /** * @brief A factory to define pairs of supported types for which * sycl::fmod function is available. diff --git a/dpnp/backend/extensions/ufunc/elementwise_functions/radians.cpp b/dpnp/backend/extensions/ufunc/elementwise_functions/radians.cpp new file mode 100644 index 00000000000..c856f14b7de --- /dev/null +++ b/dpnp/backend/extensions/ufunc/elementwise_functions/radians.cpp @@ -0,0 +1,127 @@ +//***************************************************************************** +// 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. +//***************************************************************************** + +#include + +#include "dpctl4pybind11.hpp" + +#include "kernels/elementwise_functions/radians.hpp" +#include "populate.hpp" +#include "radians.hpp" + +// include a local copy of elementwise common header from dpctl tensor: +// dpctl/tensor/libtensor/source/elementwise_functions/elementwise_functions.hpp +// TODO: replace by including dpctl header once available +#include "../../elementwise_functions/elementwise_functions.hpp" + +// dpctl tensor headers +#include "kernels/elementwise_functions/common.hpp" +#include "utils/type_dispatch.hpp" + +namespace dpnp::extensions::ufunc +{ +namespace py = pybind11; +namespace py_int = dpnp::extensions::py_internal; + +namespace impl +{ +namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common; +namespace td_ns = dpctl::tensor::type_dispatch; + +/** + * @brief A factory to define pairs of supported types for which + * sycl::radians function is available. + * + * @tparam T Type of input vector `a` and of result vector `y`. + */ +template +struct OutputType +{ + using value_type = + typename std::disjunction, + td_ns::TypeMapResultEntry, + td_ns::TypeMapResultEntry, + td_ns::DefaultResultEntry>::result_type; +}; + +using dpnp::kernels::radians::RadiansFunctor; + +template +using ContigFunctor = ew_cmn_ns::UnaryContigFunctor, + vec_sz, + n_vecs, + enable_sg_loadstore>; + +template +using StridedFunctor = ew_cmn_ns:: + UnaryStridedFunctor>; + +using ew_cmn_ns::unary_contig_impl_fn_ptr_t; +using ew_cmn_ns::unary_strided_impl_fn_ptr_t; + +static unary_contig_impl_fn_ptr_t + radians_contig_dispatch_vector[td_ns::num_types]; +static int radians_output_typeid_vector[td_ns::num_types]; +static unary_strided_impl_fn_ptr_t + radians_strided_dispatch_vector[td_ns::num_types]; + +MACRO_POPULATE_DISPATCH_VECTORS(radians); +} // namespace impl + +void init_radians(py::module_ m) +{ + using arrayT = dpctl::tensor::usm_ndarray; + using event_vecT = std::vector; + { + impl::populate_radians_dispatch_vectors(); + using impl::radians_contig_dispatch_vector; + using impl::radians_output_typeid_vector; + using impl::radians_strided_dispatch_vector; + + auto radians_pyapi = [&](const arrayT &src, const arrayT &dst, + sycl::queue &exec_q, + const event_vecT &depends = {}) { + return py_int::py_unary_ufunc(src, dst, exec_q, depends, + radians_output_typeid_vector, + radians_contig_dispatch_vector, + radians_strided_dispatch_vector); + }; + m.def("_radians", radians_pyapi, "", py::arg("src"), py::arg("dst"), + py::arg("sycl_queue"), py::arg("depends") = py::list()); + + auto radians_result_type_pyapi = [&](const py::dtype &dtype) { + return py_int::py_unary_ufunc_result_type( + dtype, radians_output_typeid_vector); + }; + m.def("_radians_result_type", radians_result_type_pyapi); + } +} +} // namespace dpnp::extensions::ufunc diff --git a/dpnp/backend/extensions/ufunc/elementwise_functions/radians.hpp b/dpnp/backend/extensions/ufunc/elementwise_functions/radians.hpp new file mode 100644 index 00000000000..b0236a4786e --- /dev/null +++ b/dpnp/backend/extensions/ufunc/elementwise_functions/radians.hpp @@ -0,0 +1,35 @@ +//***************************************************************************** +// 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. +//***************************************************************************** + +#pragma once + +#include + +namespace py = pybind11; + +namespace dpnp::extensions::ufunc +{ +void init_radians(py::module_ m); +} // namespace dpnp::extensions::ufunc diff --git a/dpnp/backend/include/dpnp_gen_1arg_2type_tbl.hpp b/dpnp/backend/include/dpnp_gen_1arg_2type_tbl.hpp index a27353866d2..a0d2b456f78 100644 --- a/dpnp/backend/include/dpnp_gen_1arg_2type_tbl.hpp +++ b/dpnp/backend/include/dpnp_gen_1arg_2type_tbl.hpp @@ -89,9 +89,6 @@ MACRO_1ARG_2TYPES_OP(dpnp_copyto_c, input_elem, q.submit(kernel_func)) MACRO_1ARG_2TYPES_OP(dpnp_degrees_c, sycl::degrees(input_elem), q.submit(kernel_func)) -MACRO_1ARG_2TYPES_OP(dpnp_radians_c, - sycl::radians(input_elem), - q.submit(kernel_func)) MACRO_1ARG_2TYPES_OP(dpnp_sqrt_c, sycl::sqrt(input_elem), oneapi::mkl::vm::sqrt(q, input1_size, input1_data, result)) diff --git a/dpnp/backend/include/dpnp_iface_fptr.hpp b/dpnp/backend/include/dpnp_iface_fptr.hpp index 9f9b7a89143..9e5cc2b7b9b 100644 --- a/dpnp/backend/include/dpnp_iface_fptr.hpp +++ b/dpnp/backend/include/dpnp_iface_fptr.hpp @@ -116,9 +116,6 @@ enum class DPNPFuncName : size_t DPNP_FN_PARTITION_EXT, /**< Used in numpy.partition() impl, requires extra parameters */ DPNP_FN_PROD, /**< Used in numpy.prod() impl */ - DPNP_FN_RADIANS, /**< Used in numpy.radians() impl */ - DPNP_FN_RADIANS_EXT, /**< Used in numpy.radians() impl, requires extra - parameters */ DPNP_FN_RNG_BETA, /**< Used in numpy.random.beta() impl */ DPNP_FN_RNG_BETA_EXT, /**< Used in numpy.random.beta() impl, requires extra parameters */ diff --git a/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp b/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp index 75413cc5e60..a1b6dbed3c4 100644 --- a/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp +++ b/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp @@ -337,36 +337,6 @@ static void func_map_init_elemwise_1arg_2type(func_map_t &fmap) fmap[DPNPFuncName::DPNP_FN_DEGREES_EXT][eft_DBL][eft_DBL] = { eft_DBL, (void *)dpnp_degrees_c_ext}; - fmap[DPNPFuncName::DPNP_FN_RADIANS][eft_INT][eft_INT] = { - eft_DBL, (void *)dpnp_radians_c_default}; - fmap[DPNPFuncName::DPNP_FN_RADIANS][eft_LNG][eft_LNG] = { - eft_DBL, (void *)dpnp_radians_c_default}; - fmap[DPNPFuncName::DPNP_FN_RADIANS][eft_FLT][eft_FLT] = { - eft_FLT, (void *)dpnp_radians_c_default}; - fmap[DPNPFuncName::DPNP_FN_RADIANS][eft_DBL][eft_DBL] = { - eft_DBL, (void *)dpnp_radians_c_default}; - - fmap[DPNPFuncName::DPNP_FN_RADIANS_EXT][eft_INT][eft_INT] = { - get_default_floating_type(), - (void *)dpnp_radians_c_ext< - int32_t, func_type_map_t::find_type>, - get_default_floating_type(), - (void *)dpnp_radians_c_ext< - int32_t, func_type_map_t::find_type< - get_default_floating_type()>>}; - fmap[DPNPFuncName::DPNP_FN_RADIANS_EXT][eft_LNG][eft_LNG] = { - get_default_floating_type(), - (void *)dpnp_radians_c_ext< - int64_t, func_type_map_t::find_type>, - get_default_floating_type(), - (void *)dpnp_radians_c_ext< - int64_t, func_type_map_t::find_type< - get_default_floating_type()>>}; - fmap[DPNPFuncName::DPNP_FN_RADIANS_EXT][eft_FLT][eft_FLT] = { - eft_FLT, (void *)dpnp_radians_c_ext}; - fmap[DPNPFuncName::DPNP_FN_RADIANS_EXT][eft_DBL][eft_DBL] = { - eft_DBL, (void *)dpnp_radians_c_ext}; - fmap[DPNPFuncName::DPNP_FN_SQRT][eft_INT][eft_INT] = { eft_DBL, (void *)dpnp_sqrt_c_default}; fmap[DPNPFuncName::DPNP_FN_SQRT][eft_LNG][eft_LNG] = { diff --git a/dpnp/backend/kernels/elementwise_functions/fabs.hpp b/dpnp/backend/kernels/elementwise_functions/fabs.hpp index 525cfc5bfe6..4fde9d329f9 100644 --- a/dpnp/backend/kernels/elementwise_functions/fabs.hpp +++ b/dpnp/backend/kernels/elementwise_functions/fabs.hpp @@ -38,7 +38,7 @@ struct FabsFunctor // constexpr resT constant_value = resT{}; // is function defined for sycl::vec using supports_vec = typename std::false_type; - // do both argT and resT support sugroup store/load operation + // do both argT and resT support subgroup store/load operation using supports_sg_loadstore = typename std::true_type; resT operator()(const argT &x) const diff --git a/dpnp/backend/kernels/elementwise_functions/radians.hpp b/dpnp/backend/kernels/elementwise_functions/radians.hpp new file mode 100644 index 00000000000..8eab2a9e4cf --- /dev/null +++ b/dpnp/backend/kernels/elementwise_functions/radians.hpp @@ -0,0 +1,55 @@ +//***************************************************************************** +// 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. +//***************************************************************************** + +#pragma once + +#include + +namespace dpnp::kernels::radians +{ +template +struct RadiansFunctor +{ + // is function constant for given argT + using is_constant = typename std::false_type; + // constant value, if constant + // constexpr resT constant_value = resT{}; + // is function defined for sycl::vec + using supports_vec = typename std::true_type; + // do both argT and resT support subgroup store/load operation + using supports_sg_loadstore = typename std::true_type; + + resT operator()(const argT &x) const + { + return sycl::radians(x); + } + + template + sycl::vec operator()(const sycl::vec &x) const + { + return sycl::radians(x); + } +}; +} // namespace dpnp::kernels::radians diff --git a/dpnp/dpnp_algo/dpnp_algo.pxd b/dpnp/dpnp_algo/dpnp_algo.pxd index 3b5b2383226..39487e6cb9e 100644 --- a/dpnp/dpnp_algo/dpnp_algo.pxd +++ b/dpnp/dpnp_algo/dpnp_algo.pxd @@ -44,7 +44,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na DPNP_FN_MEDIAN_EXT DPNP_FN_MODF_EXT DPNP_FN_PARTITION_EXT - DPNP_FN_RADIANS_EXT DPNP_FN_RNG_BETA_EXT DPNP_FN_RNG_BINOMIAL_EXT DPNP_FN_RNG_CHISQUARE_EXT @@ -172,4 +171,3 @@ cpdef dpnp_descriptor dpnp_isclose(dpnp_descriptor input1, dpnp_descriptor input Trigonometric functions """ cpdef dpnp_descriptor dpnp_degrees(dpnp_descriptor array1) -cpdef dpnp_descriptor dpnp_radians(dpnp_descriptor array1) diff --git a/dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi b/dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi index 14348d852dc..69586644937 100644 --- a/dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi +++ b/dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi @@ -37,7 +37,6 @@ and the rest of the library __all__ += [ 'dpnp_degrees', - 'dpnp_radians', 'dpnp_unwrap' ] @@ -46,10 +45,6 @@ cpdef utils.dpnp_descriptor dpnp_degrees(utils.dpnp_descriptor x1): return call_fptr_1in_1out_strides(DPNP_FN_DEGREES_EXT, x1) -cpdef utils.dpnp_descriptor dpnp_radians(utils.dpnp_descriptor x1): - return call_fptr_1in_1out_strides(DPNP_FN_RADIANS_EXT, x1) - - cpdef utils.dpnp_descriptor dpnp_unwrap(utils.dpnp_descriptor array1): result_type = dpnp.float64 diff --git a/dpnp/dpnp_iface_trigonometric.py b/dpnp/dpnp_iface_trigonometric.py index 4d5703cfc6c..b9c14770746 100644 --- a/dpnp/dpnp_iface_trigonometric.py +++ b/dpnp/dpnp_iface_trigonometric.py @@ -49,11 +49,11 @@ import numpy import dpnp +import dpnp.backend.extensions.ufunc._ufunc_impl as ufi import dpnp.backend.extensions.vm._vm_impl as vmi from .dpnp_algo import ( dpnp_degrees, - dpnp_radians, dpnp_unwrap, ) from .dpnp_algo.dpnp_elementwise_common import DPNPBinaryFunc, DPNPUnaryFunc @@ -766,24 +766,59 @@ def cumlogsumexp( ) -def deg2rad(x1): - """ - Convert angles from degrees to radians. +_DEG2RAD_DOCSTRING = """ +Convert angles from degrees to radians. - For full documentation refer to :obj:`numpy.deg2rad`. +For full documentation refer to :obj:`numpy.deg2rad`. - See Also - -------- - :obj:`dpnp.rad2deg` : Convert angles from radians to degrees. - :obj:`dpnp.unwrap` : Remove large jumps in angle by wrapping. +Parameters +---------- +x : {dpnp.ndarray, usm_ndarray} + Angles in degrees. +out : {None, dpnp.ndarray, usm_ndarray}, optional + Output array to populate. + Array must have the correct shape and the expected data type. + Default: ``None``. +order : {"C", "F", "A", "K"}, optional + Memory layout of the newly output array, if parameter `out` is ``None``. + Default: ``"K"``. - Notes - ----- - This function works exactly the same as :obj:`dpnp.radians`. +Returns +------- +out : dpnp.ndarray + The corresponding angle in radians. The data type of the returned array is + determined by the Type Promotion Rules. - """ +Limitations +----------- +Parameters `where` and `subok` are supported with their default values. +Keyword argument `kwargs` is currently unsupported. +Otherwise ``NotImplementedError`` exception will be raised. - return radians(x1) +See Also +-------- +:obj:`dpnp.rad2deg` : Convert angles from radians to degrees. +:obj:`dpnp.unwrap` : Remove large jumps in angle by wrapping. +:obj:`dpnp.radians` : Equivalent function. + +Notes +----- +:obj:`dpnp.deg2rad(x)` is ``x * pi / 180``. + +Examples +-------- +>>> import dpnp as np +>>> x = np.array(180) +>>> np.deg2rad(x) +array(3.14159265) +""" + +deg2rad = DPNPUnaryFunc( + "deg2rad", + ufi._radians_result_type, + ufi._radians, + _DEG2RAD_DOCSTRING, +) def degrees(x1, **kwargs): @@ -1641,38 +1676,63 @@ def rad2deg(x1): return degrees(x1) -def radians(x1, **kwargs): - """ - Convert angles from degrees to radians. +_RADIANS_DOCSTRING = """ +Convert angles from degrees to radians. - For full documentation refer to :obj:`numpy.radians`. +For full documentation refer to :obj:`numpy.radians`. - Limitations - ----------- - Input array is supported as :obj:`dpnp.ndarray`. - Input array data types are limited by supported DPNP :ref:`Data types`. +Parameters +---------- +x : {dpnp.ndarray, usm_ndarray} + Input array in degrees. +out : {None, dpnp.ndarray, usm_ndarray}, optional + Output array to populate. + Array must have the correct shape and the expected data type. + Default: ``None``. +order : {"C", "F", "A", "K"}, optional + Memory layout of the newly output array, if parameter `out` is ``None``. + Default: ``"K"``. - .. seealso:: :obj:`dpnp.deg2rad` equivalent function. +Returns +------- +out : dpnp.ndarray + The corresponding radian values. The data type of the returned array is + determined by the Type Promotion Rules. - Examples - -------- - >>> import dpnp as np - >>> deg = np.arange(6.) * 30. - >>> out = np.radians(deg) - >>> [i for i in out] - [0.0, 0.52359878, 1.04719755, 1.57079633, 2.0943951, 2.61799388] +Limitations +----------- +Parameters `where` and `subok` are supported with their default values. +Keyword argument `kwargs` is currently unsupported. +Otherwise ``NotImplementedError`` exception will be raised. - """ +See Also +-------- +:obj:`dpnp.deg2rad` : Equivalent function. - x1_desc = dpnp.get_dpnp_descriptor( - x1, copy_when_strides=False, copy_when_nondefault_queue=False - ) - if kwargs: - pass - elif x1_desc: - return dpnp_radians(x1_desc).get_pyobj() +Examples +-------- +>>> import dpnp as np +>>> deg = np.arange(12.) * 30. + +Convert a degree array to radians: - return call_origin(numpy.radians, x1, **kwargs) +>>> np.radians(deg) +array([0. , 0.52359878, 1.04719755, 1.57079633, 2.0943951 , + 2.61799388, 3.14159265, 3.66519143, 4.1887902 , 4.71238898, + 5.23598776, 5.75958653]) + +>>> out = np.zeros_like(deg) +>>> ret = np.radians(deg, out) +>>> ret is out +True +""" + +radians = DPNPUnaryFunc( + "radians", + ufi._radians_result_type, + ufi._radians, + _RADIANS_DOCSTRING, +) _SIN_DOCSTRING = """ diff --git a/tests/skipped_tests.tbl b/tests/skipped_tests.tbl index ec4ebe8fe4e..976a1f34c74 100644 --- a/tests/skipped_tests.tbl +++ b/tests/skipped_tests.tbl @@ -36,7 +36,6 @@ tests/third_party/cupy/fft_tests/test_fft.py::TestFftn_param_23_{axes=None, norm tests/third_party/intel/test_zero_copy_test1.py::test_dpnp_interaction_with_dpctl_memory tests/test_strides.py::test_strides_1arg[(10,)-None-degrees] -tests/test_strides.py::test_strides_1arg[(10,)-None-radians] tests/test_umath.py::test_umaths[('divmod', 'ii')] tests/test_umath.py::test_umaths[('divmod', 'll')] diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index 0449ac39812..418b51bacc8 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -451,6 +451,7 @@ def test_meshgrid(device): pytest.param("positive", [1.0, 0.0, -1.0]), pytest.param("prod", [1.0, 2.0]), pytest.param("ptp", [1.0, 2.0, 4.0, 7.0]), + pytest.param("radians", [180, 90, 45, 0]), pytest.param( "real", [complex(1.0, 2.0), complex(3.0, 4.0), complex(5.0, 6.0)] ), diff --git a/tests/test_umath.py b/tests/test_umath.py index c302cbba3a0..d396fc9ae54 100644 --- a/tests/test_umath.py +++ b/tests/test_umath.py @@ -169,103 +169,41 @@ def _get_output_data_type(dtype): return out_dtype -class TestUmath: - @pytest.fixture( - params=[ - {"func_name": "arccos", "input_values": [-1, 1, 10]}, - {"func_name": "arccosh", "input_values": [1, 10, 10]}, - {"func_name": "arcsin", "input_values": [-1, 1, 10]}, - {"func_name": "arcsinh", "input_values": [-5, 5, 10]}, - {"func_name": "arctan", "input_values": [-5, 5, 10]}, - {"func_name": "arctanh", "input_values": [-1, 1, 10]}, - {"func_name": "cos", "input_values": [-5, 5, 10]}, - {"func_name": "cosh", "input_values": [-5, 5, 10]}, - {"func_name": "exp", "input_values": [-3, 8, 10]}, - {"func_name": "exp2", "input_values": [-5, 5, 10]}, - {"func_name": "expm1", "input_values": [-5, 5, 10]}, - {"func_name": "log", "input_values": [0, 10, 10]}, - {"func_name": "log10", "input_values": [0, 10, 10]}, - {"func_name": "log2", "input_values": [0, 10, 10]}, - {"func_name": "log1p", "input_values": [0, 10, 10]}, - {"func_name": "sin", "input_values": [-5, 5, 10]}, - {"func_name": "sinh", "input_values": [-5, 5, 10]}, - {"func_name": "sqrt", "input_values": [0, 10, 10]}, - {"func_name": "tan", "input_values": [-1.5, 1.5, 10]}, - {"func_name": "tanh", "input_values": [-5, 5, 10]}, - ], - ids=[ - "arccos", - "arccosh", - "arcsin", - "arcsinh", - "arctan", - "arctanh", - "cos", - "cosh", - "exp", - "exp2", - "expm1", - "log", - "log10", - "log2", - "log1p", - "sin", - "sinh", - "sqrt", - "tan", - "tanh", - ], - ) - def func_params(self, request): - return request.param - - @pytest.mark.usefixtures("suppress_divide_invalid_numpy_warnings") - @pytest.mark.parametrize("dtype", get_all_dtypes()) - def test_out(self, func_params, dtype): - func_name = func_params["func_name"] - input_values = func_params["input_values"] - np_array, expected = _get_numpy_arrays_1in_1out( - func_name, dtype, input_values +class TestArctan2: + @pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) + def test_arctan2(self, dtype): + np_array1, np_array2, expected = _get_numpy_arrays_2in_1out( + "arctan2", dtype, [0, 10, 10] ) - dp_array = dpnp.array(np_array) + dp_array1 = dpnp.array(np_array1) + dp_array2 = dpnp.array(np_array2) out_dtype = _get_output_data_type(dtype) dp_out = dpnp.empty(expected.shape, dtype=out_dtype) - result = getattr(dpnp, func_name)(dp_array, out=dp_out) + result = dpnp.arctan2(dp_array1, dp_array2, out=dp_out) assert result is dp_out assert_dtype_allclose(result, expected) - @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)[:-1]) - def test_invalid_dtype(self, func_params, dtype): - func_name = func_params["func_name"] - dpnp_dtype = get_all_dtypes(no_none=True)[-1] + @pytest.mark.parametrize( + "dtype", get_all_dtypes(no_complex=True, no_none=True)[:-1] + ) + def test_invalid_dtype(self, dtype): + dpnp_dtype = get_all_dtypes(no_complex=True, no_none=True)[-1] dp_array = dpnp.arange(10, dtype=dpnp_dtype) dp_out = dpnp.empty(10, dtype=dtype) with pytest.raises(ValueError): - getattr(dpnp, func_name)(dp_array, out=dp_out) + dpnp.arctan2(dp_array, dp_array, out=dp_out) @pytest.mark.parametrize( "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] ) - def test_invalid_shape(self, func_params, shape): - func_name = func_params["func_name"] + def test_invalid_shape(self, shape): dp_array = dpnp.arange(10) dp_out = dpnp.empty(shape) with pytest.raises(ValueError): - getattr(dpnp, func_name)(dp_array, out=dp_out) - - @pytest.mark.parametrize( - "out", - [4, (), [], (3, 7), [2, 4]], - ids=["4", "()", "[]", "(3, 7)", "[2, 4]"], - ) - def test_invalid_out(self, func_params, out): - func_name = func_params["func_name"] - a = dpnp.arange(10) - assert_raises(TypeError, getattr(dpnp, func_name), a, out) - assert_raises(TypeError, getattr(numpy, func_name), a.asnumpy(), out) + dpnp.arctan2(dp_array, dp_array, out=dp_out) class TestCbrt: @@ -305,19 +243,18 @@ def test_invalid_shape(self, shape): dpnp.cbrt(dp_array, out=dp_out) -class TestRsqrt: - @pytest.mark.usefixtures("suppress_divide_numpy_warnings") +class TestCopySign: @pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) - def test_rsqrt(self, dtype): - np_array, expected = _get_numpy_arrays_1in_1out( - "sqrt", dtype, [0, 10, 10] + def test_copysign(self, dtype): + np_array1, np_array2, expected = _get_numpy_arrays_2in_1out( + "copysign", dtype, [0, 10, 10] ) - expected = numpy.reciprocal(expected) - dp_array = dpnp.array(np_array) + dp_array1 = dpnp.array(np_array1) + dp_array2 = dpnp.array(np_array2) out_dtype = _get_output_data_type(dtype) dp_out = dpnp.empty(expected.shape, dtype=out_dtype) - result = dpnp.rsqrt(dp_array, out=dp_out) + result = dpnp.copysign(dp_array1, dp_array2, out=dp_out) assert result is dp_out assert_dtype_allclose(result, expected) @@ -329,9 +266,8 @@ def test_invalid_dtype(self, dtype): dpnp_dtype = get_all_dtypes(no_complex=True, no_none=True)[-1] dp_array = dpnp.arange(10, dtype=dpnp_dtype) dp_out = dpnp.empty(10, dtype=dtype) - with pytest.raises(ValueError): - dpnp.rsqrt(dp_array, out=dp_out) + dpnp.copysign(dp_array, dp_array, out=dp_out) @pytest.mark.parametrize( "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] @@ -340,41 +276,34 @@ def test_invalid_shape(self, shape): dp_array = dpnp.arange(10) dp_out = dpnp.empty(shape) with pytest.raises(ValueError): - dpnp.rsqrt(dp_array, out=dp_out) - - @pytest.mark.parametrize( - "out", - [4, (), [], (3, 7), [2, 4]], - ids=["4", "()", "[]", "(3, 7)", "[2, 4]"], - ) - def test_invalid_out(self, out): - a = dpnp.arange(10) - assert_raises(TypeError, dpnp.rsqrt, a, out) + dpnp.copysign(dp_array, dp_array, out=dp_out) -class TestSquare: - @pytest.mark.parametrize("dtype", get_all_dtypes()) - def test_square(self, dtype): - np_array, expected = _get_numpy_arrays_1in_1out( - "square", dtype, [-5, 5, 10] +class TestLogaddexp: + @pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) + def test_logaddexp(self, dtype): + np_array1, np_array2, expected = _get_numpy_arrays_2in_1out( + "logaddexp", dtype, [0, 10, 10] ) - dp_array = dpnp.array(np_array) - out_dtype = numpy.int8 if dtype == numpy.bool_ else dtype + dp_array1 = dpnp.array(np_array1) + dp_array2 = dpnp.array(np_array2) + out_dtype = _get_output_data_type(dtype) dp_out = dpnp.empty(expected.shape, dtype=out_dtype) - result = dpnp.square(dp_array, out=dp_out) + result = dpnp.logaddexp(dp_array1, dp_array2, out=dp_out) assert result is dp_out assert_dtype_allclose(result, expected) - @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)[:-1]) + @pytest.mark.parametrize( + "dtype", get_all_dtypes(no_complex=True, no_none=True)[:-1] + ) def test_invalid_dtype(self, dtype): - dpnp_dtype = get_all_dtypes(no_none=True)[-1] + dpnp_dtype = get_all_dtypes(no_complex=True, no_none=True)[-1] dp_array = dpnp.arange(10, dtype=dpnp_dtype) dp_out = dpnp.empty(10, dtype=dtype) - with pytest.raises(ValueError): - dpnp.square(dp_array, out=dp_out) + dpnp.logaddexp(dp_array, dp_array, out=dp_out) @pytest.mark.parametrize( "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] @@ -383,18 +312,20 @@ def test_invalid_shape(self, shape): dp_array = dpnp.arange(10) dp_out = dpnp.empty(shape) with pytest.raises(ValueError): - dpnp.square(dp_array, out=dp_out) + dpnp.logaddexp(dp_array, dp_array, out=dp_out) + +class TestRadians: @pytest.mark.parametrize( - "out", - [4, (), [], (3, 7), [2, 4]], - ids=["4", "()", "[]", "(3, 7)", "[2, 4]"], + "dtype", get_all_dtypes(no_none=True, no_complex=True) ) - def test_invalid_out(self, out): - a = dpnp.arange(10) + def test_radians(self, dtype): + a = numpy.array([180.0, -90.0], dtype=dtype) + ia = dpnp.array(a) - assert_raises(TypeError, dpnp.square, a, out) - assert_raises(TypeError, numpy.square, a.asnumpy(), out) + result = dpnp.radians(ia) + expected = numpy.radians(a) + assert_dtype_allclose(result, expected) class TestReciprocal: @@ -433,18 +364,19 @@ def test_invalid_shape(self, shape): dpnp.reciprocal(dp_array, out=dp_out) -class TestArctan2: +class TestRsqrt: + @pytest.mark.usefixtures("suppress_divide_numpy_warnings") @pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) - def test_arctan2(self, dtype): - np_array1, np_array2, expected = _get_numpy_arrays_2in_1out( - "arctan2", dtype, [0, 10, 10] + def test_rsqrt(self, dtype): + np_array, expected = _get_numpy_arrays_1in_1out( + "sqrt", dtype, [0, 10, 10] ) + expected = numpy.reciprocal(expected) - dp_array1 = dpnp.array(np_array1) - dp_array2 = dpnp.array(np_array2) + dp_array = dpnp.array(np_array) out_dtype = _get_output_data_type(dtype) dp_out = dpnp.empty(expected.shape, dtype=out_dtype) - result = dpnp.arctan2(dp_array1, dp_array2, out=dp_out) + result = dpnp.rsqrt(dp_array, out=dp_out) assert result is dp_out assert_dtype_allclose(result, expected) @@ -458,7 +390,7 @@ def test_invalid_dtype(self, dtype): dp_out = dpnp.empty(10, dtype=dtype) with pytest.raises(ValueError): - dpnp.arctan2(dp_array, dp_array, out=dp_out) + dpnp.rsqrt(dp_array, out=dp_out) @pytest.mark.parametrize( "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] @@ -467,34 +399,41 @@ def test_invalid_shape(self, shape): dp_array = dpnp.arange(10) dp_out = dpnp.empty(shape) with pytest.raises(ValueError): - dpnp.arctan2(dp_array, dp_array, out=dp_out) + dpnp.rsqrt(dp_array, out=dp_out) + @pytest.mark.parametrize( + "out", + [4, (), [], (3, 7), [2, 4]], + ids=["4", "()", "[]", "(3, 7)", "[2, 4]"], + ) + def test_invalid_out(self, out): + a = dpnp.arange(10) + assert_raises(TypeError, dpnp.rsqrt, a, out) -class TestCopySign: - @pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) - def test_copysign(self, dtype): - np_array1, np_array2, expected = _get_numpy_arrays_2in_1out( - "copysign", dtype, [0, 10, 10] + +class TestSquare: + @pytest.mark.parametrize("dtype", get_all_dtypes()) + def test_square(self, dtype): + np_array, expected = _get_numpy_arrays_1in_1out( + "square", dtype, [-5, 5, 10] ) - dp_array1 = dpnp.array(np_array1) - dp_array2 = dpnp.array(np_array2) - out_dtype = _get_output_data_type(dtype) + dp_array = dpnp.array(np_array) + out_dtype = numpy.int8 if dtype == numpy.bool_ else dtype dp_out = dpnp.empty(expected.shape, dtype=out_dtype) - result = dpnp.copysign(dp_array1, dp_array2, out=dp_out) + result = dpnp.square(dp_array, out=dp_out) assert result is dp_out assert_dtype_allclose(result, expected) - @pytest.mark.parametrize( - "dtype", get_all_dtypes(no_complex=True, no_none=True)[:-1] - ) + @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)[:-1]) def test_invalid_dtype(self, dtype): - dpnp_dtype = get_all_dtypes(no_complex=True, no_none=True)[-1] + dpnp_dtype = get_all_dtypes(no_none=True)[-1] dp_array = dpnp.arange(10, dtype=dpnp_dtype) dp_out = dpnp.empty(10, dtype=dtype) + with pytest.raises(ValueError): - dpnp.copysign(dp_array, dp_array, out=dp_out) + dpnp.square(dp_array, out=dp_out) @pytest.mark.parametrize( "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] @@ -503,40 +442,114 @@ def test_invalid_shape(self, shape): dp_array = dpnp.arange(10) dp_out = dpnp.empty(shape) with pytest.raises(ValueError): - dpnp.copysign(dp_array, dp_array, out=dp_out) + dpnp.square(dp_array, out=dp_out) + + @pytest.mark.parametrize( + "out", + [4, (), [], (3, 7), [2, 4]], + ids=["4", "()", "[]", "(3, 7)", "[2, 4]"], + ) + def test_invalid_out(self, out): + a = dpnp.arange(10) + assert_raises(TypeError, dpnp.square, a, out) + assert_raises(TypeError, numpy.square, a.asnumpy(), out) -class TestLogaddexp: - @pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) - def test_logaddexp(self, dtype): - np_array1, np_array2, expected = _get_numpy_arrays_2in_1out( - "logaddexp", dtype, [0, 10, 10] + +class TestUmath: + @pytest.fixture( + params=[ + {"func_name": "arccos", "input_values": [-1, 1, 10]}, + {"func_name": "arccosh", "input_values": [1, 10, 10]}, + {"func_name": "arcsin", "input_values": [-1, 1, 10]}, + {"func_name": "arcsinh", "input_values": [-5, 5, 10]}, + {"func_name": "arctan", "input_values": [-5, 5, 10]}, + {"func_name": "arctanh", "input_values": [-1, 1, 10]}, + {"func_name": "cos", "input_values": [-5, 5, 10]}, + {"func_name": "cosh", "input_values": [-5, 5, 10]}, + {"func_name": "exp", "input_values": [-3, 8, 10]}, + {"func_name": "exp2", "input_values": [-5, 5, 10]}, + {"func_name": "expm1", "input_values": [-5, 5, 10]}, + {"func_name": "log", "input_values": [0, 10, 10]}, + {"func_name": "log10", "input_values": [0, 10, 10]}, + {"func_name": "log2", "input_values": [0, 10, 10]}, + {"func_name": "log1p", "input_values": [0, 10, 10]}, + {"func_name": "sin", "input_values": [-5, 5, 10]}, + {"func_name": "sinh", "input_values": [-5, 5, 10]}, + {"func_name": "sqrt", "input_values": [0, 10, 10]}, + {"func_name": "tan", "input_values": [-1.5, 1.5, 10]}, + {"func_name": "tanh", "input_values": [-5, 5, 10]}, + ], + ids=[ + "arccos", + "arccosh", + "arcsin", + "arcsinh", + "arctan", + "arctanh", + "cos", + "cosh", + "exp", + "exp2", + "expm1", + "log", + "log10", + "log2", + "log1p", + "sin", + "sinh", + "sqrt", + "tan", + "tanh", + ], + ) + def func_params(self, request): + return request.param + + @pytest.mark.usefixtures("suppress_divide_invalid_numpy_warnings") + @pytest.mark.parametrize("dtype", get_all_dtypes()) + def test_out(self, func_params, dtype): + func_name = func_params["func_name"] + input_values = func_params["input_values"] + np_array, expected = _get_numpy_arrays_1in_1out( + func_name, dtype, input_values ) - dp_array1 = dpnp.array(np_array1) - dp_array2 = dpnp.array(np_array2) + dp_array = dpnp.array(np_array) out_dtype = _get_output_data_type(dtype) dp_out = dpnp.empty(expected.shape, dtype=out_dtype) - result = dpnp.logaddexp(dp_array1, dp_array2, out=dp_out) + result = getattr(dpnp, func_name)(dp_array, out=dp_out) assert result is dp_out assert_dtype_allclose(result, expected) - @pytest.mark.parametrize( - "dtype", get_all_dtypes(no_complex=True, no_none=True)[:-1] - ) - def test_invalid_dtype(self, dtype): - dpnp_dtype = get_all_dtypes(no_complex=True, no_none=True)[-1] + @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)[:-1]) + def test_invalid_dtype(self, func_params, dtype): + func_name = func_params["func_name"] + dpnp_dtype = get_all_dtypes(no_none=True)[-1] dp_array = dpnp.arange(10, dtype=dpnp_dtype) dp_out = dpnp.empty(10, dtype=dtype) + with pytest.raises(ValueError): - dpnp.logaddexp(dp_array, dp_array, out=dp_out) + getattr(dpnp, func_name)(dp_array, out=dp_out) @pytest.mark.parametrize( "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] ) - def test_invalid_shape(self, shape): + def test_invalid_shape(self, func_params, shape): + func_name = func_params["func_name"] dp_array = dpnp.arange(10) dp_out = dpnp.empty(shape) with pytest.raises(ValueError): - dpnp.logaddexp(dp_array, dp_array, out=dp_out) + getattr(dpnp, func_name)(dp_array, out=dp_out) + + @pytest.mark.parametrize( + "out", + [4, (), [], (3, 7), [2, 4]], + ids=["4", "()", "[]", "(3, 7)", "[2, 4]"], + ) + def test_invalid_out(self, func_params, out): + func_name = func_params["func_name"] + a = dpnp.arange(10) + assert_raises(TypeError, getattr(dpnp, func_name), a, out) + assert_raises(TypeError, getattr(numpy, func_name), a.asnumpy(), out) diff --git a/tests/test_usm_type.py b/tests/test_usm_type.py index 3071ffa638e..d53377b307f 100644 --- a/tests/test_usm_type.py +++ b/tests/test_usm_type.py @@ -585,6 +585,7 @@ def test_norm(usm_type, ord, axis): pytest.param("prod", [1.0, 2.0]), pytest.param("proj", [complex(1.0, 2.0), complex(dp.inf, -1.0)]), pytest.param("ptp", [1.0, 2.0, 4.0, 7.0]), + pytest.param("radians", [180, 90, 45, 0]), pytest.param( "real", [complex(1.0, 2.0), complex(3.0, 4.0), complex(5.0, 6.0)] ),