1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14 10 11 // <experimental/simd> 12 // 13 // [simd.reference] 14 // template<class U> reference+=(U&& x) && noexcept; 15 // template<class U> reference-=(U&& x) && noexcept; 16 // template<class U> reference*=(U&& x) && noexcept; 17 // template<class U> reference/=(U&& x) && noexcept; 18 // template<class U> reference%=(U&& x) && noexcept; 19 20 #include <experimental/simd> 21 #include <functional> 22 23 #include "../test_utils.h" 24 25 namespace ex = std::experimental::parallelism_v2; 26 27 struct PlusAssign { 28 template <typename T, typename U> 29 void operator()(T&& lhs, const U& rhs) const noexcept { 30 std::forward<T>(lhs) += rhs; 31 } 32 }; 33 34 struct MinusAssign { 35 template <typename T, typename U> 36 void operator()(T&& lhs, const U& rhs) const noexcept { 37 std::forward<T>(lhs) -= rhs; 38 } 39 }; 40 41 struct MultipliesAssign { 42 template <typename T, typename U> 43 void operator()(T&& lhs, const U& rhs) const noexcept { 44 std::forward<T>(lhs) *= rhs; 45 } 46 }; 47 48 struct DividesAssign { 49 template <typename T, typename U> 50 void operator()(T&& lhs, const U& rhs) const noexcept { 51 std::forward<T>(lhs) /= rhs; 52 } 53 }; 54 55 struct ModulusAssign { 56 template <typename T, typename U> 57 void operator()(T&& lhs, const U& rhs) const noexcept { 58 std::forward<T>(lhs) %= rhs; 59 } 60 }; 61 62 template <typename T, typename SimdAbi, typename Op, typename OpAssign> 63 struct SimdReferenceOperatorHelper { 64 template <class U> 65 void operator()() const { 66 ex::simd<T, SimdAbi> origin_simd(static_cast<T>(3)); 67 static_assert(noexcept(OpAssign{}(origin_simd[0], static_cast<U>(2)))); 68 OpAssign{}(origin_simd[0], static_cast<U>(2)); 69 assert((T)origin_simd[0] == (T)Op{}(static_cast<T>(3), static_cast<T>(std::forward<U>(2)))); 70 } 71 }; 72 73 template <class T, std::size_t> 74 struct CheckReferenceArithOperators { 75 template <class SimdAbi> 76 void operator()() { 77 types::for_each(simd_test_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::plus<>, PlusAssign>()); 78 types::for_each(simd_test_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::minus<>, MinusAssign>()); 79 types::for_each(simd_test_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::multiplies<>, MultipliesAssign>()); 80 types::for_each(simd_test_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::divides<>, DividesAssign>()); 81 } 82 }; 83 84 template <class T, std::size_t> 85 struct CheckReferenceModOperators { 86 template <class SimdAbi> 87 void operator()() { 88 types::for_each( 89 simd_test_integer_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::modulus<>, ModulusAssign>()); 90 } 91 }; 92 93 int main(int, char**) { 94 test_all_simd_abi<CheckReferenceArithOperators>(); 95 types::for_each(types::integer_types(), TestAllSimdAbiFunctor<CheckReferenceModOperators>()); 96 return 0; 97 } 98