| // { dg-additional-options -std=c++20 } |
| // { dg-output-file target-std__valarray-1.output } |
| |
| #include <valarray> |
| #include <ostream> |
| #include <sstream> |
| |
| |
| /*TODO Work around PR118484 "ICE during IPA pass: cp, segfault in determine_versionability ipa-cp.cc:467". |
| |
| We can't: |
| |
| #pragma omp declare target(std::basic_streambuf<char, std::char_traits<char>>::basic_streambuf) |
| |
| ... because: |
| |
| error: overloaded function name ‘std::basic_streambuf<char>::__ct ’ in clause ‘enter’ |
| |
| Therefore, use dummy classes in '#pragma omp declare target': |
| */ |
| |
| #pragma omp declare target |
| |
| // For 'std::basic_streambuf<char, std::char_traits<char> >::basic_streambuf': |
| |
| class dummy_basic_streambuf__char |
| : public std::basic_streambuf<char> |
| { |
| public: |
| dummy_basic_streambuf__char() {} |
| }; |
| |
| // For 'std::basic_ios<char, std::char_traits<char> >::basic_ios()': |
| |
| class dummy_basic_ios__char |
| : public std::basic_ios<char> |
| { |
| public: |
| dummy_basic_ios__char() {} |
| }; |
| |
| #pragma omp end declare target |
| |
| |
| int main() |
| { |
| // Due to PR120021 "Offloading vs. C++ 'std::initializer_list'", we can't construct these on the device. |
| std::initializer_list<int> v1_i = {10, 20, 30, 40, 50}; |
| const int *v1_i_data = std::data(v1_i); |
| size_t v1_i_size = v1_i.size(); |
| std::initializer_list<int> v2_i = {5, 4, 3, 2, 1}; |
| const int *v2_i_data = std::data(v2_i); |
| size_t v2_i_size = v2_i.size(); |
| std::initializer_list<int> shiftData_i = {1, 2, 3, 4, 5}; |
| const int *shiftData_i_data = std::data(shiftData_i); |
| size_t shiftData_i_size = shiftData_i.size(); |
| #pragma omp target \ |
| defaultmap(none) \ |
| map(to: v1_i_data[:v1_i_size], v1_i_size, \ |
| v2_i_data[:v2_i_size], v2_i_size, \ |
| shiftData_i_data[:shiftData_i_size], shiftData_i_size) |
| { |
| /* Manually set up a buffer we can stream into, similar to 'cout << [...]', and print it at the end of region. */ |
| std::stringbuf out_b; |
| std::ostream out(&out_b); |
| |
| std::valarray<int> v1(v1_i_data, v1_i_size); |
| out << "\nv1:"; |
| for (auto val : v1) |
| out << " " << val; |
| |
| std::valarray<int> v2(v2_i_data, v2_i_size); |
| out << "\nv2:"; |
| for (auto val : v2) |
| out << " " << val; |
| |
| std::valarray<int> sum = v1 + v2; |
| out << "\nv1 + v2:"; |
| for (auto val : sum) |
| out << " " << val; |
| |
| std::valarray<int> diff = v1 - v2; |
| out << "\nv1 - v2:"; |
| for (auto val : diff) |
| out << " " << val; |
| |
| std::valarray<int> product = v1 * v2; |
| out << "\nv1 * v2:"; |
| for (auto val : product) |
| out << " " << val; |
| |
| std::valarray<int> quotient = v1 / v2; |
| out << "\nv1 / v2:"; |
| for (auto val : quotient) |
| out << " " << val; |
| |
| std::valarray<int> squares = pow(v1, 2); |
| out << "\npow(v1, 2):"; |
| for (auto val : squares) |
| out << " " << val; |
| |
| std::valarray<int> sinhs = sinh(v2); |
| out << "\nsinh(v2):"; |
| for (auto val : sinhs) |
| out << " " << val; |
| |
| std::valarray<int> logs = log(v1 * v2); |
| out << "\nlog(v1 * v2):"; |
| for (auto val : logs) |
| out << " " << val; |
| |
| std::valarray<int> data(12); |
| for (size_t i = 0; i < data.size(); ++i) |
| data[i] = i; |
| out << "\nOriginal array:"; |
| for (auto val : data) |
| out << " " << val; |
| |
| std::slice slice1(2, 5, 1); |
| std::valarray<int> sliced1 = data[slice1]; |
| out << "\nSlice(2, 5, 1):"; |
| for (auto val : sliced1) |
| out << " " << val; |
| |
| std::slice slice2(1, 4, 3); |
| std::valarray<int> sliced2 = data[slice2]; |
| out << "\nSlice(1, 4, 3):"; |
| for (auto val : sliced2) |
| out << " " << val; |
| |
| data[slice1] = 99; |
| out << "\nArray after slice modification:"; |
| for (auto val : data) |
| out << " " << val; |
| |
| std::valarray<bool> mask = (v1 > 20); |
| out << "\nElements of v1 > 20:"; |
| for (size_t i = 0; i < v1.size(); ++i) |
| { |
| if (mask[i]) |
| out << " " << v1[i]; |
| } |
| |
| std::valarray<int> masked = v1[mask]; |
| out << "\nMasked array:"; |
| for (auto val : masked) |
| out << " " << val; |
| |
| std::valarray<int> shiftData(shiftData_i_data, shiftData_i_size); |
| out << "\nOriginal shiftData:"; |
| for (auto val : shiftData) |
| out << " " << val; |
| |
| std::valarray<int> shifted = shiftData.shift(2); |
| out << "\nshift(2):"; |
| for (auto val : shifted) |
| out << " " << val; |
| |
| std::valarray<int> cshifted = shiftData.cshift(-1); |
| out << "\ncshift(-1):"; |
| for (auto val : cshifted) |
| out << " " << val; |
| |
| out << "\nSum(v1): " << v1.sum(); |
| out << "\nMin(v1): " << v1.min(); |
| out << "\nMax(v1): " << v1.max(); |
| |
| out << "\n"; |
| |
| /* Terminate with a NUL. Otherwise, we'd have to use: |
| __builtin_printf("%.*s", (int) out_b_sv.size(), out_b_sv.data()); |
| ... which nvptx 'printf', as implemented via PTX 'vprintf', doesn't support (TODO). */ |
| out << '\0'; |
| std::string_view out_b_sv = out_b.view(); |
| __builtin_printf("%s", out_b_sv.data()); |
| } |
| |
| return 0; |
| } |