diff --git a/documentation/library_guide/api_for_dpcpp_kernels/tested_standard_cpp_api.rst b/documentation/library_guide/api_for_dpcpp_kernels/tested_standard_cpp_api.rst index b5cae0c324c..b5f87cc4952 100644 --- a/documentation/library_guide/api_for_dpcpp_kernels/tested_standard_cpp_api.rst +++ b/documentation/library_guide/api_for_dpcpp_kernels/tested_standard_cpp_api.rst @@ -358,6 +358,10 @@ C++ Standard API libstdc++ libc++ MSVC ``std::move`` Tested Tested Tested ------------------------------------ ---------- ---------- ---------- ``std::move_backward`` Tested Tested Tested +------------------------------------ ---------- ---------- ---------- +``std::rotate`` Tested Tested Tested +------------------------------------ ---------- ---------- ---------- +``std::rotate_copy`` Tested Tested Tested ==================================== ========== ========== ========== These tests were done for the following versions of the standard C++ library: diff --git a/include/oneapi/dpl/algorithm b/include/oneapi/dpl/algorithm index ccb2c6e03ad..9e17bda600b 100644 --- a/include/oneapi/dpl/algorithm +++ b/include/oneapi/dpl/algorithm @@ -64,6 +64,8 @@ using ::std::lower_bound; using ::std::move; using ::std::move_backward; using ::std::none_of; +using ::std::rotate; +using ::std::rotate_copy; using ::std::upper_bound; } // namespace dpl diff --git a/test/support/math_utils.h b/test/support/math_utils.h new file mode 100644 index 00000000000..fb761c7f030 --- /dev/null +++ b/test/support/math_utils.h @@ -0,0 +1,48 @@ +// -*- C++ -*- +//===-- math_utils.h ------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef MATH_UTILS +#include +#include +// _USE_MATH_DEFINES must be defined in order to use math constants in MSVC +#ifdef _WIN32 +#define _USE_MATH_DEFINES 1 +#include +#endif + +// Since it is not proper to compare float point using operator ==, this +// function measures whether the result of function from kernel is close +// to the reference and machine epsilon is used as threshold in this +// function. T must be float-point type. +template bool approx_equal_fp(T x, T y) { + + // At least one input is nan + if (std::isnan(x) || std::isnan(y)) + return std::isnan(x) && std::isnan(y); + + // At least one input is inf + if (std::isinf(x) || std::isinf(y)) + return (x == y); + + // two finite + T threshold = std::numeric_limits::epsilon() * 100; + if (x != 0 && y != 0) { + T max_v = std::fmax(std::abs(x), std::abs(y)); + return std::abs(x - y) < threshold * max_v; + } + return x != 0 ? std::abs(x) < threshold : std::abs(y) < threshold; +} + +#endif diff --git a/test/xpu_api/algorithms/alg.modifying.operations/alg.rotate/xpu_rotate.pass.cpp b/test/xpu_api/algorithms/alg.modifying.operations/alg.rotate/xpu_rotate.pass.cpp new file mode 100644 index 00000000000..5b5da62ea1d --- /dev/null +++ b/test/xpu_api/algorithms/alg.modifying.operations/alg.rotate/xpu_rotate.pass.cpp @@ -0,0 +1,84 @@ +//===-- xpu_rotate.pass.cpp -----------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include + +#include "support/math_utils.h" +#include "support/test_iterators.h" + +#include +#include + +template +void +test(sycl::queue& deviceQueue) +{ + bool ret = true; + using T = typename std::iterator_traits::value_type; + T ia[] = {0, 1, 2, 3, 4}; + const unsigned sa = sizeof(ia) / sizeof(ia[0]); + sycl::range<1> item1{1}; + sycl::range<1> itemN{sa}; + { + sycl::buffer buffer1(&ret, item1); + sycl::buffer buffer2(ia, itemN); + deviceQueue.submit([&](sycl::handler& cgh) { + auto ret_acc = buffer1.template get_access(cgh); + auto acc_arr1 = buffer2.template get_access(cgh); + cgh.single_task([=]() { + auto r = dpl::rotate(Iter(&acc_arr1[0]), Iter(&acc_arr1[0] + 1), Iter(&acc_arr1[0] + sa)); + ret_acc[0] &= (base(r) == &acc_arr1[0] + 4); + }); + }); + } + assert(ret); + if (std::is_floating_point::value) + { + assert(approx_equal_fp(ia[0], T(1))); + assert(approx_equal_fp(ia[1], T(2))); + assert(approx_equal_fp(ia[2], T(3))); + assert(approx_equal_fp(ia[3], T(4))); + assert(approx_equal_fp(ia[4], T(0))); + } + else + { + assert(ia[0] == 1); + assert(ia[1] == 2); + assert(ia[2] == 3); + assert(ia[3] == 4); + assert(ia[4] == 0); + } +} + +int +main() +{ + sycl::queue deviceQueue; + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test(deviceQueue); + if (deviceQueue.get_device().has(sycl::aspect::fp64)) + { + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test(deviceQueue); + } + return 0; +} diff --git a/test/xpu_api/algorithms/alg.modifying.operations/alg.rotate/xpu_rotate_copy.pass.cpp b/test/xpu_api/algorithms/alg.modifying.operations/alg.rotate/xpu_rotate_copy.pass.cpp new file mode 100644 index 00000000000..b8bddf5d2e1 --- /dev/null +++ b/test/xpu_api/algorithms/alg.modifying.operations/alg.rotate/xpu_rotate_copy.pass.cpp @@ -0,0 +1,130 @@ +//===-- xpu_rotate_copy.pass.cpp ------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include + +#include "support/math_utils.h" +#include "support/test_iterators.h" + +#include +#include + +template +class KernelTest; + +template +void +test(sycl::queue& deviceQueue) +{ + bool ret = true; + using T = typename std::iterator_traits::value_type; + T ia[] = {0, 1, 2, 3, 4}; + const unsigned sa = sizeof(ia) / sizeof(ia[0]); + T ib[sa] = {0}; + sycl::range<1> item1{1}; + sycl::range<1> itemN{sa}; + { + sycl::buffer buffer1(&ret, item1); + sycl::buffer buffer2(ia, itemN); + sycl::buffer buffer3(ib, itemN); + deviceQueue.submit([&](sycl::handler& cgh) { + auto ret_acc = buffer1.template get_access(cgh); + auto acc_arr1 = buffer2.template get_access(cgh); + auto acc_arr2 = buffer3.template get_access(cgh); + cgh.single_task>([=]() { + OutIter r = dpl::rotate_copy(InIter(&acc_arr1[0]), InIter(&acc_arr1[0] + 2), InIter(&acc_arr1[0] + sa), + OutIter(&acc_arr2[0])); + ret_acc[0] = (base(r) == &acc_arr2[0] + sa); + }); + }); + } + assert(ret); + if (std::is_floating_point::value) + { + assert(approx_equal_fp(ib[0], T(2))); + assert(approx_equal_fp(ib[1], T(3))); + assert(approx_equal_fp(ib[2], T(4))); + assert(approx_equal_fp(ib[3], T(0))); + assert(approx_equal_fp(ib[4], T(1))); + } + else + { + assert(ib[0] == 2); + assert(ib[1] == 3); + assert(ib[2] == 4); + assert(ib[3] == 0); + assert(ib[4] == 1); + } +} + +int +main() +{ + sycl::queue deviceQueue; + test, output_iterator>(deviceQueue); + test, forward_iterator>(deviceQueue); + test, bidirectional_iterator>(deviceQueue); + test, random_access_iterator>(deviceQueue); + test, int*>(deviceQueue); + + test, output_iterator>(deviceQueue); + test, forward_iterator>(deviceQueue); + test, bidirectional_iterator>(deviceQueue); + test, random_access_iterator>(deviceQueue); + test, int*>(deviceQueue); + + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test(deviceQueue); + + test, output_iterator>(deviceQueue); + test, forward_iterator>(deviceQueue); + test, bidirectional_iterator>(deviceQueue); + test, random_access_iterator>(deviceQueue); + test, float*>(deviceQueue); + + test, output_iterator>(deviceQueue); + test, forward_iterator>(deviceQueue); + test, bidirectional_iterator>(deviceQueue); + test, random_access_iterator>(deviceQueue); + test, float*>(deviceQueue); + + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test(deviceQueue); + + test, output_iterator>(deviceQueue); + test, forward_iterator>(deviceQueue); + test, bidirectional_iterator>(deviceQueue); + test, random_access_iterator>(deviceQueue); + test, double*>(deviceQueue); + + test, output_iterator>(deviceQueue); + test, forward_iterator>(deviceQueue); + test, bidirectional_iterator>(deviceQueue); + test, random_access_iterator>(deviceQueue); + test, double*>(deviceQueue); + + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test>(deviceQueue); + test(deviceQueue); + + return 0; +}