// Copyright 2019-2024, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto.  Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.

#ifndef _NVCOMPILER_ALGORITHM_EXECUTION_HEADER_
#define _NVCOMPILER_ALGORITHM_EXECUTION_HEADER_

#if !defined(_NVCOMPILER_ALGORITHM_HEADER_) || \
    !defined(_NVCOMPILER_EXECUTION_HEADER_)
  #error <nvhpc/algorithm_execution.hpp> should not be included directly. Include <algorithm> and <execution> instead.
#endif

#include <nvhpc/stdpar_config.hpp>

#if _NVHPC_INCLUDE_THRUST
#define __NVCOMPILER_PROCESSING_THRUST_INCLUDES
#include <thrust/copy.h>
#include <thrust/count.h>
#include <thrust/equal.h>
#include <thrust/extrema.h>
#include <thrust/fill.h>
#include <thrust/find.h>
#include <thrust/generate.h>
#include <thrust/for_each.h>
#include <thrust/logical.h>
#include <thrust/merge.h>
#include <thrust/mismatch.h>
#include <thrust/partition.h>
#include <thrust/remove.h>
#include <thrust/replace.h>
#include <thrust/reverse.h>
#include <thrust/set_operations.h>
#include <thrust/sort.h>
#include <thrust/swap.h>
#include <thrust/transform.h>
#include <thrust/unique.h>
#undef __NVCOMPILER_PROCESSING_THRUST_INCLUDES
#endif

#if __NVCOMPILER_STDPAR_OPENACC_GPU || _NVHPC_STDPAR_GPU
#include <nvhpc/algorithm_openacc.hpp>
#endif

namespace std {

namespace __stdpar {

// _EP = execution policy
// _FIt = forward iterator
// _BDIt = bidirectional iterator
// _RIt = random access iterator
// _UF = unary operator/function
// _BF = binary operator/function

template <__back_end _BE> struct __algorithm_impl;

// The sequential back end.  Run the algorithm sequentially.

template <> struct __algorithm_impl<__back_end::__seq> {

  //========== adjacent_find ==========

  template <class _FIt>
  static _FIt adjacent_find(__no_policy, _FIt __first, _FIt __last) {
    return std::adjacent_find(__first, __last);
  }

  template <class _FIt, class _BF>
  static _FIt adjacent_find(__no_policy, _FIt __first, _FIt __last, _BF __f) {
    return std::adjacent_find(__first, __last, __f);
  }

  //========== all_of ==========

  template <class _FIt, class _UF>
  static bool all_of(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::all_of(__first, __last, __f);
  }

  //========== any_of ==========

  template <class _FIt, class _UF>
  static bool any_of(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::any_of(__first, __last, __f);
  }

  //========== copy ==========

  template <class _FIt1, class _FIt2>
  static _FIt2 copy(__no_policy, _FIt1 __first, _FIt1 __last, _FIt2 __d_first) {
    return std::copy(__first, __last, __d_first);
  }

  //========== copy_if ==========

  template <class _FIt1, class _FIt2, class _UF>
  static _FIt2 copy_if(__no_policy, _FIt1 __first, _FIt1 __last,
                       _FIt2 __d_first, _UF __f) {
    return std::copy_if(__first, __last, __d_first, __f);
  }

  //========== copy_n ==========

  template <class _FIt1, class _Size, class _FIt2>
  static _FIt2 copy_n(__no_policy, _FIt1 __first, _Size __count,
                      _FIt2 __d_first) {
    return std::copy_n(__first, __count, __d_first);
  }

  //========== count ==========

  template <class _FIt, class _T>
  static typename std::iterator_traits<_FIt>::difference_type
  count(__no_policy, _FIt __first, _FIt __last, _T const& __value) {
    return std::count(__first, __last, __value);
  }

  //========== count_if ==========
  
  template <class _FIt, class _UF>
  static typename std::iterator_traits<_FIt>::difference_type
  count_if(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::count_if(__first, __last, __f);
  }

  //========== equal ==========

  template <class _FIt1, class _FIt2>
  static bool equal(__no_policy, _FIt1 __first1, _FIt1 __last1,
                    _FIt2 __first2) {
    return std::equal(__first1, __last1, __first2);
  }

  template <class _FIt1, class _FIt2, class _BF>
  static bool equal(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _BF __f) {
    return std::equal(__first1, __last1, __first2, __f);
  }

  template <class _FIt1, class _FIt2>
  static bool equal(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _FIt2 __last2) {
#if __cplusplus >= 201402L
    return std::equal(__first1, __last1, __first2, __last2);
#else
    return std::distance(__first1, __last1) ==
             std::distance(__first2, __last2) &&
           std::equal(__first1, __last1, __first2);
#endif
  }

  template <class _FIt1, class _FIt2, class _BF>
  static bool equal(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _FIt2 __last2, _BF __f) {
#if __cplusplus >= 201402L
    return std::equal(__first1, __last1, __first2, __last2, __f);
#else
    return std::distance(__first1, __last1) ==
             std::distance(__first2, __last2) &&
           std::equal(__first1, __last1, __first2, __f);
#endif
  }
  
  //========== fill ==========

  template <class _FIt, class _T>
  static void fill(__no_policy, _FIt __first, _FIt __last, _T const& __value) {
    std::fill(__first, __last, __value);
  }

  //========== fill_n ==========

  template <class _FIt, class _Size, class _T>
  static _FIt fill_n(__no_policy, _FIt __first, _Size __count,
                     _T const& __value) {
    return std::fill_n(__first, __count, __value);
  }

  //========== find ==========

  template <class _FIt, class _T>
  static _FIt find(__no_policy, _FIt __first, _FIt __last, _T const& __value) {
    return std::find(__first, __last, __value);
  }

  //========== find_end ==========

  template <class _FIt1, class _FIt2>
  static _FIt1 find_end(__no_policy, _FIt1 __first, _FIt1 __last,
                        _FIt2 __s_first, _FIt2 __s_last) {
    return std::find_end(__first, __last, __s_first, __s_last);
  }

  template <class _FIt1, class _FIt2, class _BF>
  static _FIt1 find_end(__no_policy, _FIt1 __first, _FIt1 __last,
                        _FIt2 __s_first, _FIt2 __s_last, _BF __f) {
    return std::find_end(__first, __last, __s_first, __s_last, __f);
  }
  
  //========== find_first_of ==========

  template <class _FIt1, class _FIt2>
  static _FIt1 find_first_of(__no_policy, _FIt1 __first, _FIt1 __last,
                             _FIt2 __s_first, _FIt2 __s_last) {
    return std::find_first_of(__first, __last, __s_first, __s_last);
  }

  template <class _FIt1, class _FIt2, class _BF>
  static _FIt1 find_first_of(__no_policy, _FIt1 __first, _FIt1 __last,
                             _FIt2 __s_first, _FIt2 __s_last, _BF __f) {
    return std::find_first_of(__first, __last, __s_first, __s_last, __f);
  }

  //========== find_if ==========

  template <class _FIt, class _UF>
  static _FIt find_if(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::find_if(__first, __last, __f);
  }

  //========== find_if_not ==========

  template <class _FIt, class _UF>
  static _FIt find_if_not(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::find_if_not(__first, __last, __f);
  }
  
  //========== for_each ==========

  template <class _FIt, class _UF>
  static void for_each(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    (void)std::for_each(__first, __last, __f);
  }

  //========== for_each_n ==========

  template <class _FIt, class _Size, class _UF>
  static _FIt for_each_n(__no_policy, _FIt __first, _Size __n, _UF __f) {
    // C++11 doesn't have a sequential version of for_each_n()
    for (_Size __i = 0; __i < __n; ++__first, ++__i) {
      __f(*__first);
    }
    return __first;
  }

  //========== generate ==========

  template <class _FIt, class _Generator>
  static void generate(__no_policy, _FIt __first, _FIt __last, _Generator __g) {
    std::generate(__first, __last, __g);
  }

  //========== generate_n ==========

  template <class _FIt, class _Size, class _Generator>
  static _FIt generate_n(__no_policy, _FIt __first, _Size __count,
                         _Generator __g) {
    return std::generate_n(__first, __count, __g);
  }

  //========== includes ==========

  template <class _FIt1, class _FIt2>
  static bool includes(__no_policy, _FIt1 __first1, _FIt1 __last1,
                       _FIt2 __first2, _FIt2 __last2) {
    return std::includes(__first1, __last1, __first2, __last2);
  }

  template <class _FIt1, class _FIt2, class _BF>
  static bool includes(__no_policy, _FIt1 __first1, _FIt1 __last1,
                       _FIt2 __first2, _FIt2 __last2, _BF __cmp) {
    return std::includes(__first1, __last1, __first2, __last2, __cmp);
  }

  //========== inplace_merge ==========

  template <class _BDIt>
  static void inplace_merge(__no_policy, _BDIt __first, _BDIt __middle,
                            _BDIt __last) {
    std::inplace_merge(__first, __middle, __last);
  }

  template <class _BDIt, class _BF>
  static void inplace_merge(__no_policy, _BDIt __first, _BDIt __middle,
                            _BDIt __last, _BF __cmp) {
    std::inplace_merge(__first, __middle, __last, __cmp);
  }
  
  //========== is_heap ==========

  template <class _RIt>
  static bool is_heap(__no_policy, _RIt __first, _RIt __last) {
    return std::is_heap(__first, __last);
  }

  template <class _RIt, class _BF>
  static bool is_heap(__no_policy, _RIt __first, _RIt __last, _BF __cmp) {
    return std::is_heap(__first, __last, __cmp);
  }

  //========== is_heap_until ==========

  template <class _RIt>
  static _RIt is_heap_until(__no_policy, _RIt __first, _RIt __last) {
    return std::is_heap_until(__first, __last);
  }

  template <class _RIt, class _BF>
  static _RIt is_heap_until(__no_policy, _RIt __first, _RIt __last, _BF __cmp) {
    return std::is_heap_until(__first, __last, __cmp);
  }

  //========== is_partitioned ==========

  template <class _FIt, class _UF>
  static bool is_partitioned(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::is_partitioned(__first, __last, __f);
  }

  //========== is_sorted ==========

  template <class _FIt>
  static bool is_sorted(__no_policy, _FIt __first, _FIt __last) {
    return std::is_sorted(__first, __last);
  }

  template <class _FIt, class _BF>
  static bool is_sorted(__no_policy, _FIt __first, _FIt __last, _BF __cmp) {
    return std::is_sorted(__first, __last, __cmp);
  }

  //========== is_sorted_until ==========

  template <class _FIt>
  static _FIt is_sorted_until(__no_policy, _FIt __first, _FIt __last) {
    return std::is_sorted_until(__first, __last);
  }

  template <class _FIt, class _BF>
  static _FIt is_sorted_until(__no_policy, _FIt __first, _FIt __last,
                              _BF __cmp) {
    return std::is_sorted_until(__first, __last, __cmp);
  }

  //========== lexicographical_compare ==========

  template <class _FIt1, class _FIt2>
  static bool lexicographical_compare(__no_policy, _FIt1 __first1,
                                      _FIt1 __last1, _FIt2 __first2,
                                      _FIt2 __last2) {
    return std::lexicographical_compare(__first1, __last1, __first2, __last2);
  }

  template <class _FIt1, class _FIt2, class _BF>
  static bool lexicographical_compare(__no_policy, _FIt1 __first1,
                                      _FIt1 __last1, _FIt2 __first2,
                                      _FIt2 __last2, _BF __cmp) {
    return std::lexicographical_compare(__first1, __last1, __first2, __last2,
                                        __cmp);
  }

  //========== max_element ==========

  template <class _FIt>
  static _FIt max_element(__no_policy, _FIt __first, _FIt __last) {
    return std::max_element(__first, __last);
  }

  template <class _FIt, class _BF>
  static _FIt max_element(__no_policy, _FIt __first, _FIt __last, _BF __cmp) {
    return std::max_element(__first, __last, __cmp);
  }

  //========== merge ==========

  template <class _FIt1, class _FIt2, class _FIt3>
  static _FIt3 merge(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                     _FIt2 __last2, _FIt3 __d_first) {
    return std::merge(__first1, __last1, __first2, __last2, __d_first);
  }

  template <class _FIt1, class _FIt2, class _FIt3, class _BF>
  static _FIt3 merge(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                     _FIt2 __last2, _FIt3 __d_first, _BF __cmp) {
    return std::merge(__first1, __last1, __first2, __last2, __d_first, __cmp);
  }
  
  //========== min_element ==========

  template <class _FIt>
  static _FIt min_element(__no_policy, _FIt __first, _FIt __last) {
    return std::min_element(__first, __last);
  }

  template <class _FIt, class _BF>
  static _FIt min_element(__no_policy, _FIt __first, _FIt __last, _BF __cmp) {
    return std::min_element(__first, __last, __cmp);
  }

  //========== minmax_element ==========

  template <class _FIt>
  static std::pair<_FIt, _FIt> minmax_element(__no_policy, _FIt __first,
                                              _FIt __last) {
    return std::minmax_element(__first, __last);
  }

  template <class _FIt, class _BF>
  static std::pair<_FIt, _FIt> minmax_element(__no_policy, _FIt __first,
                                              _FIt __last, _BF __cmp) {
    return std::minmax_element(__first, __last, __cmp);
  }

  //========== mismatch ==========

  template <class _FIt1, class _FIt2>
  static std::pair<_FIt1, _FIt2> mismatch(__no_policy, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2) {
    return std::mismatch(__first1, __last1, __first2);
  }

  template <class _FIt1, class _FIt2, class _BF>
  static std::pair<_FIt1, _FIt2> mismatch(__no_policy, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _BF __f) {
    return std::mismatch(__first1, __last1, __first2, __f);
  }

  template <class _FIt1, class _FIt2>
  static std::pair<_FIt1, _FIt2> mismatch(__no_policy, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _FIt2 __last2) {
#if __cplusplus >= 201402L
    return std::mismatch(__first1, __last1, __first2, __last2);
#else
    auto __size1 = std::distance(__first1, __last1);
    auto __size2 = std::distance(__first2, __last2);
    _FIt1 __end = std::next(__first1, __size2 < __size1 ? __size2 : __size1);
    return std::mismatch(__first1, __end, __first2);
#endif
  }

  template <class _FIt1, class _FIt2, class _BF>
  static std::pair<_FIt1, _FIt2> mismatch(__no_policy, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _FIt2 __last2, _BF __f) {
#if __cplusplus >= 201402L
    return std::mismatch(__first1, __last1, __first2, __last2, __f);
#else
    auto __size1 = std::distance(__first1, __last1);
    auto __size2 = std::distance(__first2, __last2);
    _FIt1 __end = std::next(__first1, __size2 < __size1 ? __size2 : __size1);
    return std::mismatch(__first1, __end, __first2, __f);
#endif
  }

  //========== move ==========

  template <class _FIt1, class _FIt2>
  static _FIt2 move(__no_policy, _FIt1 __first, _FIt1 __last, _FIt2 __d_first) {
    return std::move(__first, __last, __d_first);
  }

  //========== none_of ==========

  template <class _FIt, class _UF>
  static bool none_of(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::none_of(__first, __last, __f);
  }
  
  //========== nth_element ==========

  template <class _RIt>
  static void nth_element(__no_policy, _RIt __first, _RIt __nth, _RIt __last) {
    std::nth_element(__first, __nth, __last);
  }

  template <class _RIt, class _BF>
  static void nth_element(__no_policy, _RIt __first, _RIt __nth, _RIt __last,
                          _BF __cmp) {
    std::nth_element(__first, __nth, __last, __cmp);
  }

  //========== partial_sort ==========

  template <class _RIt>
  static void partial_sort(__no_policy, _RIt __first, _RIt __middle,
                           _RIt __last) {
    std::partial_sort(__first, __middle, __last);
  }

  template <class _RIt, class _BF>
  static void partial_sort(__no_policy, _RIt __first, _RIt __middle,
                           _RIt __last, _BF __cmp) {
    std::partial_sort(__first, __middle, __last, __cmp);
  }

  //========== partial_sort_copy ==========

  template <class _FIt, class _RIt>
  static _RIt partial_sort_copy(__no_policy, _FIt __first, _FIt __last,
                                _RIt __d_first, _RIt __d_last) {
    return std::partial_sort_copy(__first, __last, __d_first, __d_last);
  }

  template <class _FIt, class _RIt, class _BF>
  static _RIt partial_sort_copy(__no_policy, _FIt __first, _FIt __last,
                                _RIt __d_first, _RIt __d_last, _BF __cmp) {
    return std::partial_sort_copy(__first, __last, __d_first, __d_last, __cmp);
  }

  //========== partition ==========

  template <class _FIt, class _UF>
  static _FIt partition(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::partition(__first, __last, __f);
  }

  //========== partition_copy ==========

  template <class _FIt1, class _FIt2, class _FIt3, class _UF>
  static std::pair<_FIt2, _FIt3> partition_copy(__no_policy, _FIt1 __first,
                                                _FIt1  __last, _FIt2 __d_true,
                                                _FIt3 __d_false, _UF __f) {
    return std::partition_copy(__first, __last, __d_true, __d_false, __f);
  }

  //========== remove ==========

  template <class _FIt, class _T>
  static _FIt remove(__no_policy, _FIt __first, _FIt __last,
                     _T const& __value) {
    return std::remove(__first, __last, __value);
  }

  //========== remove_copy ==========

  template <class _FIt1, class _FIt2, class _T>
  static _FIt2 remove_copy(__no_policy, _FIt1 __first, _FIt1 __last,
                           _FIt2 __d_first, _T const& __value) {
    return std::remove_copy(__first, __last, __d_first, __value);
  }

  //========== remove_copy_if ==========

  template <class _FIt1, class _FIt2, class _UF>
  static _FIt2 remove_copy_if(__no_policy, _FIt1 __first, _FIt1 __last,
                              _FIt2 __d_first, _UF __f) {
    return std::remove_copy_if(__first, __last, __d_first, __f);
  }

  //========== remove_if ==========

  template <class _FIt, class _UF>
  static _FIt remove_if(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    return std::remove_if(__first, __last, __f);
  }

  //========== replace ==========

  template <class _FIt, class _T>
  static void replace(__no_policy, _FIt __first, _FIt __last,
                      _T const& __old_value, _T const& __new_value) {
    std::replace(__first, __last, __old_value, __new_value);
  }

  //========== replace_copy ==========

  template <class _FIt1, class _FIt2, class _T>
  static _FIt2 replace_copy(__no_policy, _FIt1 __first, _FIt1 __last,
                            _FIt2 __d_first, _T const& __old_value,
                            _T const& __new_value) {
    return std::replace_copy(__first, __last, __d_first, __old_value,
                             __new_value);
  }

  //========== replace_copy_if ==========

  template <class _FIt1, class _FIt2, class _UF, class _T>
  static _FIt2 replace_copy_if(__no_policy, _FIt1 __first, _FIt1 __last,
                               _FIt2 __d_first, _UF __f,
                               _T const& __new_value) {
    return std::replace_copy_if(__first, __last, __d_first, __f, __new_value);
  }

  //========== replace_if ==========

  template <class _FIt, class _UF, class _T>
  static void replace_if(__no_policy, _FIt __first, _FIt __last, _UF __f,
                         _T const& __new_value) {
    std::replace_if(__first, __last, __f, __new_value);
  }

  //========== reverse ==========

  template <class _BDIt>
  static void reverse(__no_policy, _BDIt __first, _BDIt __last) {
    std::reverse(__first, __last);
  }

  //========== reverse_copy ==========

  template <class _BDIt, class _FIt>
  static _FIt reverse_copy(__no_policy, _BDIt __first, _BDIt __last,
                           _FIt __d_first) {
    return std::reverse_copy(__first, __last, __d_first);
  }

  //========== rotate ==========

  template <class _FIt>
  static _FIt rotate(__no_policy, _FIt __first, _FIt __n_first, _FIt __last) {
    return std::rotate(__first, __n_first, __last);
  }

  //========== rotate_copy ==========

  template <class _FIt1, class _FIt2>
  static _FIt2 rotate_copy(__no_policy, _FIt1 __first, _FIt1 __n_first,
                           _FIt1 __last, _FIt2 __d_first) {
    return std::rotate_copy(__first, __n_first, __last, __d_first);
  }

  //========== search ==========

  template <class _FIt1, class _FIt2>
  static _FIt1 search(__no_policy, _FIt1 __first, _FIt1 __last, _FIt2 __s_first,
                      _FIt2 __s_last) {
    return std::search(__first, __last, __s_first, __s_last);
  }

  template <class _FIt1, class _FIt2, class _BF>
  static _FIt1 search(__no_policy, _FIt1 __first, _FIt1 __last, _FIt2 __s_first,
                      _FIt2 __s_last, _BF __f) {
    return std::search(__first, __last, __s_first, __s_last, __f);
  }

  //========== search_n ==========

  template <class _FIt, class _Size, class _T>
  static _FIt search_n(__no_policy, _FIt __first, _FIt __last, _Size __count,
                       _T const& __value) {
    return std::search_n(__first, __last, __count, __value);
  }

  template <class _FIt, class _Size, class _T, class _BF>
  static _FIt search_n(__no_policy, _FIt __first, _FIt __last, _Size __count,
                       _T const& __value, _BF __f) {
    return std::search_n(__first, __last, __count, __value, __f);
  }
  
  //========== set_difference ==========

  template <class _FIt1, class _FIt2, class _FIt3>
  static _FIt3 set_difference(__no_policy, _FIt1 __first1, _FIt1 __last1,
                              _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first) {
    return std::set_difference(__first1, __last1, __first2, __last2, __d_first);
  }

  template <class _FIt1, class _FIt2, class _FIt3, class _BF>
  static _FIt3 set_difference(__no_policy, _FIt1 __first1, _FIt1 __last1,
                              _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first,
                              _BF __cmp) {
    return std::set_difference(__first1, __last1, __first2, __last2, __d_first,
                               __cmp);
  }

  //========== set_intersection ==========

  template <class _FIt1, class _FIt2, class _FIt3>
  static _FIt3 set_intersection(__no_policy, _FIt1 __first1, _FIt1 __last1,
                                _FIt2 __first2, _FIt2 __last2,
                                _FIt3 __d_first) {
    return std::set_intersection(__first1, __last1, __first2, __last2,
                                 __d_first);
  }

  template <class _FIt1, class _FIt2, class _FIt3, class _BF>
  static _FIt3 set_intersection(__no_policy, _FIt1 __first1, _FIt1 __last1,
                                _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first,
                                _BF __cmp) {
    return std::set_intersection(__first1, __last1, __first2, __last2,
                                 __d_first, __cmp);
  }

  //========== set_symmetric_difference ==========

  template <class _FIt1, class _FIt2, class _FIt3>
  static _FIt3 set_symmetric_difference(__no_policy, _FIt1 __first1,
                                        _FIt1 __last1, _FIt2 __first2,
                                        _FIt2 __last2, _FIt3 __d_first) {
    return std::set_symmetric_difference(__first1, __last1, __first2, __last2,
                                         __d_first);
  }

  template <class _FIt1, class _FIt2, class _FIt3, class _BF>
  static _FIt3 set_symmetric_difference(__no_policy, _FIt1 __first1,
                                        _FIt1 __last1, _FIt2 __first2,
                                        _FIt2 __last2, _FIt3 __d_first,
                                        _BF __cmp) {
    return std::set_symmetric_difference(__first1, __last1, __first2, __last2,
                                         __d_first, __cmp);
  }

  //========== set_union ==========

  template <class _FIt1, class _FIt2, class _FIt3>
  static _FIt3 set_union(__no_policy, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first) {
    return std::set_union(__first1, __last1, __first2, __last2, __d_first);
  }

  template <class _FIt1, class _FIt2, class _FIt3, class _BF>
  static _FIt3 set_union(__no_policy, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first,
                         _BF __cmp) {
    return std::set_union(__first1, __last1, __first2, __last2, __d_first,
                          __cmp);
  }

  //========== shift_left ==========

  template <class _FIt>
  static _FIt
  shift_left(__no_policy, _FIt __first, _FIt __last,
             typename std::iterator_traits<_FIt>::difference_type __n) {
    if (__n <= 0) {
      return __last;
    }
    if (std::distance(__first, __last) <= __n) {
      return __first;
    }
    return std::move(std::next(__first, __n), __last, __first);
  }

  //========== shift_right ==========

  template <class _FIt>
  static _FIt
  shift_right(__no_policy, _FIt __first, _FIt __last,
              typename std::iterator_traits<_FIt>::difference_type __n) {
    using _Index = typename std::iterator_traits<_FIt>::difference_type;
    if (__n <= 0) {
      return __first;
    }
    _Index __input_size = std::distance(__first, __last);
    if (__input_size <= __n) {
      return __last;
    }
    _Index __shifted_size = __input_size - __n;
    if constexpr (std::is_base_of<std::random_access_iterator_tag,
                                  typename std::iterator_traits<
                                      _FIt>::iterator_category>::value) {
      _FIt __last_elem = __last - 1;
      for (_Index __i = 0; __i < __shifted_size; ++__i) {
        __last_elem[-__i] = std::move(__last_elem[-(__i + __n)]);
      }
    } else {
      // An efficient implementation with forward iterators is difficult.
      // Use rotate even though it does extra work.
      std::rotate(__first, std::next(__first, __shifted_size), __last);
    }
    return std::next(__first, __n);
  }

  //========== sort ==========

  template <class _RIt>
  static void sort(__no_policy, _RIt __first, _RIt __last) {
    std::sort(__first, __last);
  }

  template <class _RIt, class _BF>
  static void sort(__no_policy, _RIt __first, _RIt __last, _BF __cmp) {
    std::sort(__first, __last, __cmp);
  }

  //========== stable_partition ==========

  template <class _BDIt, class _UF>
  static _BDIt stable_partition(__no_policy, _BDIt __first, _BDIt __last,
                                _UF __f) {
    return std::stable_partition(__first, __last, __f);
  }

  //========== stable_sort ==========

  template <class _RIt>
  static void stable_sort(__no_policy, _RIt __first, _RIt __last) {
    std::stable_sort(__first, __last);
  }

  template <class _RIt, class _BF>
  static void stable_sort(__no_policy, _RIt __first, _RIt __last, _BF __cmp) {
    std::stable_sort(__first, __last, __cmp);
  }

  //========== swap_ranges ==========

  template <class _FIt1, class _FIt2>
  static _FIt2 swap_ranges(__no_policy, _FIt1 __first1, _FIt1 __last1,
                           _FIt2 __first2) {
    return std::swap_ranges(__first1, __last1, __first2);
  }

  //========== transform ==========

  template <class _FIt1, class _FIt2, class _UF>
  static _FIt2 transform(__no_policy, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __d_first, _UF __f) {
    return std::transform(__first1, __last1, __d_first, __f);
  }

  template <class _FIt1, class _FIt2, class _FIt3, class _BF>
  static _FIt3 transform(__no_policy, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __first2, _FIt3 __d_first, _BF __f) {
    return std::transform(__first1, __last1, __first2, __d_first, __f);
  }

  //========== unique ==========

  template <class _FIt>
  static _FIt unique(__no_policy, _FIt __first, _FIt __last) {
    return std::unique(__first, __last);
  }

  template <class _FIt, class _BF>
  static _FIt unique(__no_policy, _FIt __first, _FIt __last, _BF __f) {
    return std::unique(__first, __last, __f);
  }

  //========== unique_copy ==========

  template <class _FIt1, class _FIt2>
  static _FIt2 unique_copy(__no_policy, _FIt1 __first, _FIt1 __last,
                           _FIt2 __d_first) {
    return std::unique_copy(__first, __last, __d_first);
  }

  template <class _FIt1, class _FIt2, class _BF>
  static _FIt2 unique_copy(__no_policy, _FIt1 __first, _FIt1 __last,
                           _FIt2 __d_first, _BF __f) {
    return std::unique_copy(__first, __last, __d_first, __f);
  }
};

// The Thrust parallel back end.  This is used for both CPU and GPU.  The
// correct Thrust execution policy to use to choose between CPU and GPU is a
// template parameter.

template <> struct __algorithm_impl<__back_end::__thrust_multicore> {

#if _NVHPC_INCLUDE_THRUST

  //========== adjacent_find ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt adjacent_find(_EP&& __ep, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    // There isn't a parallel implement of adjacent_find(). Use mismatch()
    // instead. (Thanks to Conor Hoekstra for the idea.)
    if (__first == __last) {
      return __last;
    }
    _FIt __second = std::next(__first, 1);
    _FIt __next_to_last = std::prev(__last, 1);
    auto __result = thrust::mismatch(
      (_EP&&)__ep, __first, __next_to_last, __second,
      [](typename std::iterator_traits<_FIt>::value_type const& __a,
         typename std::iterator_traits<_FIt>::value_type const& __b) {
        return !(__a == __b);
      });
    return __result.first == __next_to_last ? __last : __result.first;
  }
  
  template <class _EP, class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt adjacent_find(_EP&& __ep, _FIt __first, _FIt __last, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // There isn't a parallel implement of adjacent_find(). Use mismatch()
    // instead. (Thanks to Conor Hoekstra for the idea.)
    if (__first == __last) {
      return __last;
    }
    _FIt __second = std::next(__first, 1);
    _FIt __next_to_last = std::prev(__last, 1);
    auto __result = thrust::mismatch(
      (_EP&&)__ep, __first, __next_to_last, __second,
      [=](typename std::iterator_traits<_FIt>::value_type const& __a,
          typename std::iterator_traits<_FIt>::value_type const& __b) mutable {
        return !__f(__a, __b);
      });
    return __result.first == __next_to_last ? __last : __result.first;
  }

  //========== all_of ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool all_of(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::all_of((_EP&&)__ep, __first, __last, __f);
  }

  //========== any_of ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool any_of(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::any_of((_EP&&)__ep, __first, __last, __f);
  }

  //========== count ==========

  template <class _EP, class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static typename std::iterator_traits<_FIt>::difference_type
  count(_EP&& __ep, _FIt __first, _FIt __last, _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::count((_EP&&)__ep, __first, __last, __value);
  }

  //========== copy ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 copy(_EP&& __ep, _FIt1 __first, _FIt1 __last, _FIt2 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return thrust::copy((_EP&&)__ep, __first, __last, __d_first);
  }
  
  //========== copy_if ==========

  template <class _EP, class _FIt1, class _FIt2, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 copy_if(_EP&& __ep, _FIt1 __first, _FIt1 __last, _FIt2 __d_first,
                       _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::copy_if((_EP&&)__ep, __first, __last, __d_first, __f);
  }

  //========== copy_n ==========

  template <class _EP, class _FIt1, class _Size, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 copy_n(_EP&& __ep, _FIt1 __first, _Size __count,
                      _FIt2 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return thrust::copy_n((_EP&&)__ep, __first, __count, __d_first);
  }
  
  //========== count_if ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static typename std::iterator_traits<_FIt>::difference_type
  count_if(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::count_if((_EP&&)__ep, __first, __last, __f);
  }

  //========== equal ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool equal(_EP&& __ep, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return thrust::equal((_EP&&)__ep, __first1, __last1, __first2);
  }
  
  template <class _EP, class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool equal(_EP&& __ep, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::equal((_EP&&)__ep, __first1, __last1, __first2, __f);
  }
  
  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool equal(_EP&& __ep, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _FIt2 __last2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    // Thrust does not implement this overload of equal().
    return std::distance(__first1, __last1) ==
             std::distance(__first2, __last2) &&
           thrust::equal((_EP&&)__ep, __first1, __last1, __first2);
  }
  
  template <class _EP, class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool equal(_EP&& __ep, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _FIt2 __last2, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // Thrust does not implement this overload of equal().
    return std::distance(__first1, __last1) ==
             std::distance(__first2, __last2) &&
           thrust::equal((_EP&&)__ep, __first1, __last1, __first2, __f);
  }

  //========== fill ==========

  template <class _EP, class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void fill(_EP&& __ep, _FIt __first, _FIt __last, _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    thrust::fill((_EP&&)__ep, __first, __last, __value);
  }

  //========== fill_n ==========
  
  template <class _EP, class _FIt, class _Size, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt fill_n(_EP&& __ep, _FIt __first, _Size __count,
                     _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    // std::fill_n is a no-op when __count < 0, but thrust::fill_n doesn't
    // handle that correctly.  Make sure the count is non-negative.
    return thrust::fill_n((_EP&&)__ep, __first, std::max<_Size>(__count, 0),
                          __value);
  }

  //========== find ==========

  template <class _EP, class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt find(_EP&& __ep, _FIt __first, _FIt __last, _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::find((_EP&&)__ep, __first, __last, __value);
  }  

  //========== find_end ==========

  // No parallel implementation available
  
  //========== find_first_of ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt1 find_first_of(_EP&& __ep, _FIt1 __first, _FIt1 __last,
                             _FIt2 __s_first, _FIt2 __s_last) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    // Thrust does not implement find_first_of().
    return thrust::find_if(
      (_EP&&)__ep, __first, __last,
      [=](typename std::iterator_traits<_FIt1>::value_type const& __x) {
        return std::find(__s_first, __s_last, __x) != __s_last;
      });
  }

  template <class _EP, class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt1 find_first_of(_EP&& __ep, _FIt1 __first, _FIt1 __last,
                             _FIt2 __s_first, _FIt2 __s_last, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // Thrust does not implement find_first_of().
    return thrust::find_if(
      (_EP&&)__ep, __first, __last,
      [=](typename std::iterator_traits<_FIt1>::value_type const& __x) mutable {
        return std::find_if(
                 __s_first, __s_last,
                 [=](typename std::iterator_traits<_FIt2>::value_type const
                       &__y) mutable {
                   return __f(__x, __y); }) != __s_last;
        });
  }

  //========== find_if ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt find_if(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::find_if((_EP&&)__ep, __first, __last, __f);
  }
  
  //========== find_if_not ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt find_if_not(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::find_if_not((_EP&&)__ep, __first, __last, __f);
  }

  //========== for_each ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void for_each(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    thrust::for_each((_EP&&)__ep, __first, __last, __f);
  }

  //========== for_each_n ==========

  template <class _EP, class _FIt, class _Size, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt for_each_n(_EP&& __ep, _FIt __first, _Size __n, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::for_each_n((_EP&&)__ep, __first, __n, __f);
  }

  //========== generate ==========

  template <class _EP, class _FIt, class _Generator>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void generate(_EP&& __ep, _FIt __first, _FIt __last, _Generator __g) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_Generator);
    thrust::generate((_EP&&)__ep, __first, __last, __g);
  }

  //========== generate_n ==========

  template <class _EP, class _FIt, class _Size, class _Generator>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt generate_n(_EP&& __ep, _FIt __first, _Size __count,
                         _Generator __g) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_Generator);
    return thrust::generate_n((_EP&&)__ep, __first, __count, __g);
  }

  //========== includes ==========

  // No parallel implementation available

  //========== inplace_merge ==========

  // No parallel implementation available

  //========== is_heap ==========

  template <class _EP, class _RIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool is_heap(_EP&& __ep, _RIt __first, _RIt __last) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    // Thrust does not implement is_heap().
    return thrust::none_of(
      (_EP&&)__ep, ::cuda::counting_iterator<_RIt>(__first),
      ::cuda::counting_iterator<_RIt>(__last),
      [=](_RIt __it) { return __first[(__it - __first - 1) / 2] < *__it; });
  }
  
  template <class _EP, class _RIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool is_heap(_EP&& __ep, _RIt __first, _RIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // Thrust does not implement is_heap().
    return thrust::none_of(
      (_EP&&)__ep, ::cuda::counting_iterator<_RIt>(__first),
      ::cuda::counting_iterator<_RIt>(__last),
      [=](_RIt __it) mutable {
        return __cmp(__first[(__it - __first - 1) / 2], *__it);
      });
  }

  //========== is_heap_until ==========

  template <class _EP, class _RIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _RIt is_heap_until(_EP&& __ep, _RIt __first, _RIt __last) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    // Thrust does not implement is_heap_until().
    return *thrust::find_if(
      (_EP&&)__ep, ::cuda::counting_iterator<_RIt>(__first),
      ::cuda::counting_iterator<_RIt>(__last),
      [=](_RIt __it) { return __first[(__it - __first - 1) / 2] < *__it; });
  }

  template <class _EP, class _RIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _RIt is_heap_until(_EP&& __ep, _RIt __first, _RIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // Thrust does not implement is_heap_until().
    return *thrust::find_if(
      (_EP&&)__ep, ::cuda::counting_iterator<_RIt>(__first),
      ::cuda::counting_iterator<_RIt>(__last),
      [=](_RIt __it) mutable {
        return __cmp(__first[(__it - __first - 1) / 2], *__it);
      });
  }

  //========== is_partitioned ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool is_partitioned(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::is_partitioned((_EP&&)__ep, __first, __last, __f);
  }

  //========== is_sorted ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool is_sorted(_EP&& __ep, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::is_sorted((_EP&&)__ep, __first, __last);
  }

  template <class _EP, class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool is_sorted(_EP&& __ep, _FIt __first, _FIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::is_sorted((_EP&&)__ep, __first, __last, __cmp);
  }
  
  //========== is_sorted_until ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt is_sorted_until(_EP&& __ep, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::is_sorted_until((_EP&&)__ep, __first, __last);
  }

  template <class _EP, class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt is_sorted_until(_EP&& __ep, _FIt __first, _FIt __last,
                              _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::is_sorted_until((_EP&&)__ep, __first, __last, __cmp);
  }

  //========== lexicographical_compare ==========

  // No parallel implementation available

  //========== max_element ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt max_element(_EP&& __ep, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::max_element((_EP&&)__ep, __first, __last);
  }

  template <class _EP, class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt max_element(_EP&& __ep, _FIt __first, _FIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::max_element((_EP&&)__ep, __first, __last, __cmp);
  }

  //========== merge ==========

  template <class _EP, class _FIt1, class _FIt2, class _FIt3>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 merge(_EP&& __ep, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, 
                     _FIt2 __last2, _FIt3 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    return thrust::merge((_EP&&)__ep, __first1, __last1, __first2, __last2,
                         __d_first);
  }
  
  template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 merge(_EP&& __ep, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                     _FIt2 __last2, _FIt3 __d_first, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::merge((_EP&&)__ep, __first1, __last1, __first2, __last2,
                         __d_first, __cmp);
  }

  //========== min_element ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt min_element(_EP&& __ep, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::min_element((_EP&&)__ep, __first, __last);
  }

  template <class _EP, class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt min_element(_EP&& __ep, _FIt __first, _FIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::min_element((_EP&&)__ep, __first, __last, __cmp);
  }

  //========== minmax_element ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static std::pair<_FIt, _FIt> minmax_element(_EP&& __ep, _FIt __first,
                                              _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    auto __result = thrust::minmax_element((_EP&&)__ep, __first, __last);
    return std::pair<_FIt, _FIt>(__result.first, __result.second);
  }

  template <class _EP, class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static std::pair<_FIt, _FIt> minmax_element(_EP&& __ep, _FIt __first,
                                              _FIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    auto __result = thrust::minmax_element((_EP&&)__ep, __first, __last, __cmp);
    return std::pair<_FIt, _FIt>(__result.first, __result.second);
  }

  //========== mismatch ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static std::pair<_FIt1, _FIt2> mismatch(_EP&& __ep, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    auto __result = thrust::mismatch((_EP&&)__ep, __first1, __last1, __first2);
    return std::pair<_FIt1, _FIt2>(__result.first, __result.second);
  }

  template <class _EP, class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static std::pair<_FIt1, _FIt2> mismatch(_EP&& __ep, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    auto __result =
      thrust::mismatch((_EP&&)__ep, __first1, __last1, __first2, __f);
    return std::pair<_FIt1, _FIt2>(__result.first, __result.second);
  }

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static std::pair<_FIt1, _FIt2> mismatch(_EP&& __ep, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _FIt2 __last2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    // Thrust does not have a version of mismatch() with two separate end
    // iterators.
    auto __size1 = std::distance(__first1, __last1);
    auto __size2 = std::distance(__first2, __last2);
    _FIt1 __end = std::next(__first1, __size2 < __size1 ? __size2 : __size1);
    auto __result = thrust::mismatch((_EP&&)__ep, __first1, __end, __first2);
    return std::pair<_FIt1, _FIt2>(__result.first, __result.second);
  }

  template <class _EP, class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static std::pair<_FIt1, _FIt2> mismatch(_EP&& __ep, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _FIt2 __last2, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // Thrust does not have a version of mismatch with two separate end
    // iterators.
    auto __size1 = std::distance(__first1, __last1);
    auto __size2 = std::distance(__first2, __last2);
    _FIt1 __end = std::next(__first1, __size2 < __size1 ? __size2 : __size1);
    auto __result =
      thrust::mismatch((_EP&&)__ep, __first1, __end, __first2, __f);
    return std::pair<_FIt1, _FIt2>(__result.first, __result.second);
  }

  //========== move ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 move(_EP&& __ep, _FIt1 __first, _FIt1 __last, _FIt2 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    // Thrust does not implement move().  Wrap the input range in a
    // counting_iterator to maintain control over how the input iterators are
    // dereferenced.
    return thrust::transform(
      (_EP&&)__ep, ::cuda::counting_iterator<_FIt1>(__first),
      ::cuda::counting_iterator<_FIt1>(__last), __d_first,
      [](_FIt1 __it) -> typename std::iterator_traits<_FIt1>::value_type && {
        return std::move(*__it);
      });
  }

  //========== none_of ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static bool none_of(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::none_of((_EP&&)__ep, __first, __last, __f);
  }

  //========== nth_element ==========

  // No parallel implementation available

  //========== partial_sort ==========

  template <class _EP, class _RIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void partial_sort(_EP&& __ep, _RIt __first, _RIt __middle,
                           _RIt __last) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    // Thrust does not implement partial_sort().  Sort everything instead.
    thrust::sort((_EP&&)__ep, __first, __last);
  }

  template <class _EP, class _RIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void partial_sort(_EP&& __ep, _RIt __first, _RIt __middle, _RIt __last,
                           _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // Thrust does not implement partial_sort().  Sort everything instead.
    thrust::sort((_EP&&)__ep, __first, __last, __cmp);
  }

  //========== partial_sort_copy ==========

  // No parallel implementation available

  //========== partition ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt partition(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::partition((_EP&&)__ep, __first, __last, __f);
  }

  //========== partition_copy ==========

  template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static std::pair<_FIt2, _FIt3> partition_copy(_EP&& __ep, _FIt1 __first,
                                                _FIt1  __last, _FIt2 __d_true,
                                                _FIt3 __d_false, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_UF);
    auto __result = thrust::partition_copy((_EP&&)__ep, __first, __last,
                                           __d_true, __d_false, __f);
    return std::pair<_FIt2, _FIt3>(__result.first, __result.second);
  }
  
  //========== remove ==========

  template <class _EP, class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt remove(_EP&& __ep, _FIt __first, _FIt __last, _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::remove((_EP&&)__ep, __first, __last, __value);
  }
  
  //========== remove_copy ==========

  template <class _EP, class _FIt1, class _FIt2, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 remove_copy(_EP&& __ep, _FIt1 __first, _FIt1 __last,
                           _FIt2 __d_first, _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return thrust::remove_copy((_EP&&)__ep, __first, __last, __d_first,
                               __value);
  }
  
  //========== remove_copy_if ==========

  template <class _EP, class _FIt1, class _FIt2, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 remove_copy_if(_EP&& __ep, _FIt1 __first, _FIt1 __last,
                              _FIt2 __d_first, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::remove_copy_if((_EP&&)__ep, __first, __last, __d_first, __f);
  }
  
  //========== remove_if ==========

  template <class _EP, class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt remove_if(_EP&& __ep, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::remove_if((_EP&&)__ep, __first, __last, __f);
  }

  //========== replace ==========

  template <class _EP, class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void replace(_EP&& __ep, _FIt __first, _FIt __last,
                      _T const& __old_value, _T const& __new_value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    thrust::replace((_EP&&)__ep, __first, __last, __old_value, __new_value);
  }

  //========== replace_copy ==========

  template <class _EP, class _FIt1, class _FIt2, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 replace_copy(_EP&& __ep, _FIt1 __first, _FIt1 __last,
                            _FIt2 __d_first, _T const& __old_value,
                            _T const& __new_value) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return thrust::replace_copy((_EP&&)__ep, __first, __last, __d_first,
                                __old_value, __new_value);
  }

  //========== replace_copy_if ==========

  template <class _EP, class _FIt1, class _FIt2, class _UF, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 replace_copy_if(_EP&& __ep, _FIt1 __first, _FIt1 __last,
                               _FIt2 __d_first, _UF __f,
                               _T const& __new_value) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::replace_copy_if((_EP&&)__ep, __first, __last, __d_first, __f,
                                   __new_value);
  }

  //========== replace_if ==========

  template <class _EP, class _FIt, class _UF, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void replace_if(_EP&& __ep, _FIt __first, _FIt __last, _UF __f, 
                         _T const& __new_value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    thrust::replace_if((_EP&&)__ep, __first, __last, __f, __new_value);
  }

  //========== reverse ==========

  template <class _EP, class _BDIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void reverse(_EP&& __ep, _BDIt __first, _BDIt __last) {
    _ASSERT_RANDOM_ACCESS(_BDIt);
    thrust::reverse((_EP&&)__ep, __first, __last);
  }

  //========== reverse_copy ==========

  template <class _EP, class _BDIt, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt reverse_copy(_EP&& __ep, _BDIt __first, _BDIt __last,
                           _FIt __d_first) {
    _ASSERT_RANDOM_ACCESS(_BDIt);
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::reverse_copy((_EP&&)__ep, __first, __last, __d_first);
  }

  //========== rotate ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt rotate(_EP&& __ep, _FIt __first, _FIt __n_first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    if (__first == __n_first) {
      return __last;
    }
    if (__n_first == __last) {
      return __first;
    }
    thrust::reverse((_EP&&)__ep, __first, __n_first);
    thrust::reverse((_EP&&)__ep, __n_first, __last);
    thrust::reverse((_EP&&)__ep, __first, __last);
    return __first + std::distance(__n_first, __last);
  }

  //========== rotate_copy ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 rotate_copy(_EP&& __ep, _FIt1 __first, _FIt1 __n_first,
                           _FIt1 __last, _FIt2 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    // Thrust does not implement rotate_copy().
    return thrust::copy(
      (_EP&&)__ep, __first, __n_first,
      thrust::copy((_EP&&)__ep, __n_first, __last, __d_first));
  }

  //========== search ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt1 search(_EP&& __ep, _FIt1 __first, _FIt1 __last, _FIt2 __s_first,
                      _FIt2 __s_last) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    // Thrust does not implement search().
    if (__s_first == __s_last) {
      return __first;
    }
    auto __input_size = std::distance(__first, __last);
    auto __search_size = std::distance(__s_first, __s_last);
    if (__search_size > __input_size) {
      return __last;
    }
    _FIt1 __tail = std::next(__first, __input_size - __search_size + 1);
    _FIt1 __result = *thrust::find_if(
      (_EP&&)__ep, ::cuda::counting_iterator<_FIt1>(__first),
      ::cuda::counting_iterator<_FIt1>(__tail),
      [=](_FIt1 __it) {
        // Calling std::equal might result in calling memcmp from device
        // code, which is not supported.
        for (_FIt2 __sit = __s_first; __sit != __s_last; ++__it, ++__sit) {
          if (!(*__it == *__sit)) return false;
        }
        return true;
      });
    if (__result == __tail) {
      return __last;
    }
    return __result;
  }

  template <class _EP, class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt1 search(_EP&& __ep, _FIt1 __first, _FIt1 __last, _FIt2 __s_first,
                      _FIt2 __s_last, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // Thrust does not implement search().
    if (__s_first == __s_last) {
      return __first;
    }
    auto __input_size = std::distance(__first, __last);
    auto __search_size = std::distance(__s_first, __s_last);
    if (__search_size > __input_size) {
      return __last;
    }
    _FIt1 __tail = std::next(__first, __input_size - __search_size + 1);
    _FIt1 __result = *thrust::find_if(
      (_EP&&)__ep, ::cuda::counting_iterator<_FIt1>(__first),
      ::cuda::counting_iterator<_FIt1>(__tail),
      [=](_FIt1 __it) mutable {
        // Calling std::equal might result in calling memcmp from device
        // code, which is not supported.
        for (_FIt2 __sit = __s_first; __sit != __s_last; ++__it, ++__sit) {
          if (!__f(*__it, *__sit)) return false;
        }
        return true;
      });
    if (__result == __tail) {
      return __last;
    }
    return __result;
  }

  //========== search_n ==========

  template <class _EP, class _FIt, class _Size, class _T>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt search_n(_EP&& __ep, _FIt __first, _FIt __last, _Size __count,
                       _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    // Thrust does not implement search_n().
    if (__count <= 0) {
      return __first;
    }
    auto __input_size = std::distance(__first, __last);
    if (__count > __input_size) {
      return __last;
    }
    _FIt __tail = std::next(__first, __input_size - __count + 1);
    _FIt __result = *thrust::find_if(
      (_EP&&)__ep, ::cuda::counting_iterator<_FIt>(__first),
      ::cuda::counting_iterator<_FIt>(__tail),
      [=](_FIt __it) {
        return std::all_of(
          __it, std::next(__it, __count),
          [=](typename std::iterator_traits<_FIt>::value_type const& __x) {
            return __x == __value;
          });
      });
    if (__result == __tail) {
      return __last;
    }
    return __result;
  }
  
  template <class _EP, class _FIt, class _Size, class _T, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt search_n(_EP&& __ep, _FIt __first, _FIt __last, _Size __count,
                       _T const& __value, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    // Thrust does not implement search_n().
    if (__count <= 0) {
      return __first;
    }
    auto __input_size = std::distance(__first, __last);
    if (__count > __input_size) {
      return __last;
    }
    _FIt __tail = std::next(__first, __input_size - __count + 1);
    _FIt __result = *thrust::find_if(
      (_EP&&)__ep, ::cuda::counting_iterator<_FIt>(__first),
      ::cuda::counting_iterator<_FIt>(__tail),
      [=](_FIt __it) {
        return std::all_of(
          __it, std::next(__it, __count),
          [=](typename std::iterator_traits<_FIt>::value_type const
                &__x) mutable {
            return __f(__x, __value);
          });
      });
    if (__result == __tail) {
      return __last;
    }
    return __result;
  }

  //========== set_difference ==========

  template <class _EP, class _FIt1, class _FIt2, class _FIt3>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 set_difference(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                              _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    return thrust::set_difference((_EP&&)__ep, __first1, __last1, __first2,
                                  __last2, __d_first);
  }

  template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 set_difference(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                              _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first,
                              _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::set_difference((_EP&&)__ep, __first1, __last1, __first2,
                                  __last2, __d_first, __cmp);
  }

  //========== set_intersection ==========

  template <class _EP, class _FIt1, class _FIt2, class _FIt3>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 set_intersection(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                                _FIt2 __first2, _FIt2 __last2,
                                _FIt3 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    return thrust::set_intersection((_EP&&)__ep, __first1, __last1, __first2,
                                    __last2, __d_first);
  }

  template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 set_intersection(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                                _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first,
                                _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::set_intersection((_EP&&)__ep, __first1, __last1, __first2,
                                    __last2, __d_first, __cmp);
  }

  //========== set_symmetric_difference ==========

  template <class _EP, class _FIt1, class _FIt2, class _FIt3>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 set_symmetric_difference(_EP&& __ep, _FIt1 __first1,
                                        _FIt1 __last1, _FIt2 __first2,
                                        _FIt2 __last2, _FIt3 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    return thrust::set_symmetric_difference((_EP&&)__ep, __first1, __last1,
                                            __first2, __last2, __d_first);
  }

  template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 set_symmetric_difference(_EP&& __ep, _FIt1 __first1,
                                        _FIt1 __last1, _FIt2 __first2,
                                        _FIt2 __last2, _FIt3 __d_first,
                                        _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::set_symmetric_difference((_EP&&)__ep, __first1, __last1,
                                            __first2, __last2, __d_first,
                                            __cmp);
  }

  //========== set_union ==========

  template <class _EP, class _FIt1, class _FIt2, class _FIt3>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 set_union(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    return thrust::set_union((_EP&&)__ep, __first1, __last1, __first2, __last2,
                             __d_first);
  }

  template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 set_union(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __first2, _FIt2 __last2, _FIt3 __d_first,
                         _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::set_union((_EP&&)__ep, __first1, __last1, __first2, __last2,
                             __d_first, __cmp);
  }

  //========== shift_left ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST static _FIt
  shift_left(_EP&& __ep, _FIt __first, _FIt __last,
             typename std::iterator_traits<_FIt>::difference_type __n) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    using _Index = typename std::iterator_traits<_FIt>::difference_type;
    if (__n <= 0) {
      return __last;
    }
    _Index __input_size = std::distance(__first, __last);
    if (__n >= __input_size) {
      return __first;
    }
    if (__n < 50'000 && __n < __input_size / 128) {
      thrust::reverse((_EP&&)__ep, __first + __n, __last);
      thrust::reverse((_EP&&)__ep, __first, __last);
    } else {
      _Index __shifted_size = __input_size - __n;
      _Index __threads = __detail::min(__n, __shifted_size);
      thrust::for_each(
          (_EP&&)__ep, ::cuda::counting_iterator<_Index>(0),
          ::cuda::counting_iterator<_Index>(__threads),
          [=](_Index __i) {
            for (_Index __j = __i; __j < __shifted_size; __j += __n) {
              __first[__j] = std::move(__first[__j + __n]);
            }
          });
    }
    return __last - __n;
  }

  //========== shift_right ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST static _FIt
  shift_right(_EP&& __ep, _FIt __first, _FIt __last,
              typename std::iterator_traits<_FIt>::difference_type __n) {
    using _Index = typename std::iterator_traits<_FIt>::difference_type;
    _ASSERT_RANDOM_ACCESS(_FIt);
    if (__n <= 0) {
      return __first;
    }
    _Index __input_size = std::distance(__first, __last);
    if (__n >= __input_size) {
      return __last;
    }
    if (__n < 50'000 && __n < __input_size / 128) {
      thrust::reverse((_EP&&)__ep, __first, __last - __n);
      thrust::reverse((_EP&&)__ep, __first, __last);
    } else {
      _Index __shifted_size = __input_size - __n;
      _Index __threads = __detail::min(__n, __shifted_size);
      _FIt __last_elem = __last - 1;
      thrust::for_each(
          (_EP&&)__ep, ::cuda::counting_iterator<_Index>(0),
          ::cuda::counting_iterator<_Index>(__threads),
          [=](_Index __i) {
            for (_Index __j = __i; __j < __shifted_size; __j += __n) {
              __last_elem[-__j] = std::move(__last_elem[-(__j + __n)]);
            }
          });
    }
    return __first + __n;
  }

  //========== sort ==========

  template <class _EP, class _RIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void sort(_EP&& __ep, _RIt __first, _RIt __last) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    thrust::sort((_EP&&)__ep, __first, __last);
  }

  template <class _EP, class _RIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void sort(_EP&& __ep, _RIt __first, _RIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    thrust::sort((_EP&&)__ep, __first, __last, __cmp);
  }

  //========== stable_partition ==========

  template <class _EP, class _BDIt, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _BDIt stable_partition(_EP&& __ep, _BDIt __first, _BDIt __last,
                                _UF __f) {
    _ASSERT_RANDOM_ACCESS(_BDIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::stable_partition((_EP&&)__ep, __first, __last, __f);
  }

  //========== stable_sort ==========

  template <class _EP, class _RIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void stable_sort(_EP&& __ep, _RIt __first, _RIt __last) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    thrust::stable_sort((_EP&&)__ep, __first, __last);
  }

  template <class _EP, class _RIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static void stable_sort(_EP&& __ep, _RIt __first, _RIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    thrust::stable_sort((_EP&&)__ep, __first, __last, __cmp);
  }

  //========== swap_ranges ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 swap_ranges(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                           _FIt2 __first2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return thrust::swap_ranges((_EP&&)__ep, __first1, __last1, __first2);
  }

  //========== transform ==========

  template <class _EP, class _FIt1, class _FIt2, class _UF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 transform(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __d_first, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return thrust::transform((_EP&&)__ep, __first1, __last1, __d_first, __f);
  }

  template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt3 transform(_EP&& __ep, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __first2, _FIt3 __d_first, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::transform((_EP&&)__ep, __first1, __last1, __first2,
                             __d_first, __f);
  }

  //========== unique ==========

  template <class _EP, class _FIt>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt unique(_EP&& __ep, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return thrust::unique((_EP&&)__ep, __first, __last);
  }
  
  template <class _EP, class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt unique(_EP&& __ep, _FIt __first, _FIt __last, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::unique((_EP&&)__ep, __first, __last, __f);
  }

  //========== unique_copy ==========

  template <class _EP, class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 unique_copy(_EP&& __ep, _FIt1 __first, _FIt1 __last,
                           _FIt2 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return thrust::unique_copy((_EP&&)__ep, __first, __last, __d_first);
  }
  
  template <class _EP, class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_THRUST
  static _FIt2 unique_copy(_EP&& __ep, _FIt1 __first, _FIt1 __last,
                           _FIt2 __d_first, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return thrust::unique_copy((_EP&&)__ep, __first, __last, __d_first, __f);
  }
  
#endif // _NVHPC_INCLUDE_THRUST
};

template <>
struct __algorithm_impl<__back_end::__thrust_gpu>
    : __algorithm_impl<__back_end::__thrust_multicore> { };

// The __gpu_multicore back end is empty because it is treated specially by the
// dispatch framework.
template <> struct __algorithm_impl<__back_end::__gpu_multicore> { };

// The OpenACC back end.  Only some algorithms are implemented.

template <> struct __algorithm_impl<__back_end::__openacc> {

#if __NVCOMPILER_STDPAR_OPENACC_GPU || _NVHPC_STDPAR_GPU

  //========== adjacent_find ==========

  template <class _FIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt adjacent_find(__no_policy, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::adjacent_find(__first, __last, std::equal_to<void>());
  }

  template <class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt adjacent_find(__no_policy, _FIt __first, _FIt __last, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::adjacent_find(__first, __last, __f);
  }

  //========== all_of ==========

  template <class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static bool all_of(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::all_of(__first, __last, __f);
  }

  //========== any_of ==========

  template <class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static bool any_of(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::any_of(__first, __last, __f);
  }

  //========== copy ==========

  template <class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt2 copy(__no_policy, _FIt1 __first, _FIt1 __last, _FIt2 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return __openacc::copy(__first, __last, __d_first);
  }

  //========== copy_if ==========

  template <class _FIt1, class _FIt2, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt2 copy_if(__no_policy, _FIt1 __first, _FIt1 __last,
                       _FIt2 __d_first, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::copy_if(__first, __last, __d_first, __f);
  }

  //========== copy_n ==========

  template <class _FIt1, class _Size, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt2 copy_n(__no_policy, _FIt1 __first, _Size __count,
                      _FIt2 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return __openacc::copy_n(__first, __count, __d_first);
  }

  //========== count ==========

  template <class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static typename std::iterator_traits<_FIt>::difference_type
  count(__no_policy, _FIt __first, _FIt __last, _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::count(__first, __last, __value);
  }

  //========== count_if ==========

  template <class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static typename std::iterator_traits<_FIt>::difference_type
  count_if(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::count_if(__first, __last, __f);
  }

  //========== equal ==========

  template <class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static bool equal(__no_policy, _FIt1 __first1, _FIt1 __last1,
                    _FIt2 __first2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return __openacc::mismatch(__first1, __last1, __first2,
                               std::equal_to<void>{})
               .first == __last1;
  }

  template <class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static bool equal(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::mismatch(__first1, __last1, __first2, __f).first ==
        __last1;
  }

  template <class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static bool equal(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _FIt2 __last2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    auto __input_size1 = std::distance(__first1, __last1);
    auto __input_size2 = std::distance(__first2, __last2);
    if (__input_size1 != __input_size2) {
      return false;
    }
    return __openacc::mismatch(__first1, __last1, __first2,
                               std::equal_to<void>{})
               .first == __last1;
  }

  template <class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static bool equal(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                    _FIt2 __last2, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    auto __input_size1 = std::distance(__first1, __last1);
    auto __input_size2 = std::distance(__first2, __last2);
    if (__input_size1 != __input_size2) {
      return false;
    }
    return __openacc::mismatch(__first1, __last1, __first2, __f).first ==
        __last1;
  }

  //========== fill ==========

  template <class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void fill(__no_policy, _FIt __first, _FIt __last, _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::fill(__first, __last, __value);
  }

  //========== fill_n ==========

  template <class _FIt, class _Size, class _T>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt fill_n(__no_policy, _FIt __first, _Size __count,
                     _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::fill_n(__first, __count, __value);
  }

  //========== find ==========

  template <class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt find(__no_policy, _FIt __first, _FIt __last, _T const& __value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::find_if(
        __first, __last,
        [=](typename std::iterator_traits<_FIt>::value_type const& __elem) {
          return __elem == __value;
        });
  }

  //========== find_if ==========

  template <class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt find_if(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::find_if(__first, __last, __f);
  }

  //========== find_if_not ==========

  template <class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt find_if_not(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::find_if(__first, __last, std::not_fn(__f));
  }

  //========== for_each ==========

  template <class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void for_each(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::for_each(__first, __last, __f);
  }

  //========== for_each_n ==========

  template <class _FIt, class _Size, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt for_each_n(__no_policy, _FIt __first, _Size __n, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::for_each_n(__first, __n, __f);
  }

  //========== max_element ==========

  template <class _FIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt max_element(__no_policy, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::max_element(__first, __last, std::less<void>{});
  }

  template <class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt max_element(__no_policy, _FIt __first, _FIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::max_element(__first, __last, __cmp);
  }

  //========== merge ==========

  template <class _FIt1, class _FIt2, class _FIt3>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt3 merge(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                     _FIt2 __last2, _FIt3 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    return __openacc::merge(__first1, __last1, __first2, __last2, __d_first,
                            std::less<void>{});
  }

  template <class _FIt1, class _FIt2, class _FIt3, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt3 merge(__no_policy, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                     _FIt2 __last2, _FIt3 __d_first, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::merge(__first1, __last1, __first2, __last2, __d_first,
                            __cmp);
  }

  //========== min_element ==========

  template <class _FIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt min_element(__no_policy, _FIt __first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::min_element(__first, __last, std::less<void>{});
  }

  template <class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt min_element(__no_policy, _FIt __first, _FIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::min_element(__first, __last, __cmp);
  }

  //========== minmax_element ==========

  template <class _FIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static std::pair<_FIt, _FIt> minmax_element(__no_policy, _FIt __first,
                                              _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::minmax_element(__first, __last, std::less<void>{});
  }

  template <class _FIt, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static std::pair<_FIt, _FIt> minmax_element(__no_policy, _FIt __first,
                                              _FIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::minmax_element(__first, __last, __cmp);
  }

  //========== mismatch ==========

  template <class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static std::pair<_FIt1, _FIt2> mismatch(__no_policy, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return __openacc::mismatch(__first1, __last1, __first2,
                               std::equal_to<void>{});
  }

  template <class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static std::pair<_FIt1, _FIt2> mismatch(__no_policy, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::mismatch(__first1, __last1, __first2, __f);
  }

  template <class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static std::pair<_FIt1, _FIt2> mismatch(__no_policy, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _FIt2 __last2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    auto __input_size1 = std::distance(__first1, __last1);
    auto __input_size2 = std::distance(__first2, __last2);
    auto __input_size = __detail::min(__input_size1, __input_size2);
    return __openacc::mismatch(__first1, __first1 + __input_size, __first2,
                               std::equal_to<void>{});
  }

  template <class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static std::pair<_FIt1, _FIt2> mismatch(__no_policy, _FIt1 __first1,
                                          _FIt1 __last1, _FIt2 __first2,
                                          _FIt2 __last2, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    auto __input_size1 = std::distance(__first1, __last1);
    auto __input_size2 = std::distance(__first2, __last2);
    auto __input_size = __detail::min(__input_size1, __input_size2);
    return __openacc::mismatch(__first1, __first1 + __input_size, __first2,
                               __f);
  }

  //========== none_of ==========

  template <class _FIt, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static bool none_of(__no_policy, _FIt __first, _FIt __last, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return !__openacc::any_of(__first, __last, __f);
  }

  //========== replace ==========

  template <class _FIt, class _T>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void replace(__no_policy, _FIt __first, _FIt __last,
                      _T const& __old_value, _T const& __new_value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::replace(__first, __last, __old_value, __new_value);
  }

  //========== replace_copy ==========

  template <class _FIt1, class _FIt2, class _T>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt2 replace_copy(__no_policy, _FIt1 __first, _FIt1 __last,
                            _FIt2 __d_first, _T const& __old_value,
                            _T const& __new_value) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return __openacc::replace_copy(__first, __last, __d_first, __old_value,
                                   __new_value);
  }

  //========== replace_copy_if ==========

  template <class _FIt1, class _FIt2, class _UF, class _T>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt2 replace_copy_if(__no_policy, _FIt1 __first, _FIt1 __last,
                               _FIt2 __d_first, _UF __f,
                               _T const& __new_value) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::replace_copy_if(__first, __last, __d_first, __f,
                                      __new_value);
  }

  //========== replace_if ==========

  template <class _FIt, class _UF, class _T>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void replace_if(__no_policy, _FIt __first, _FIt __last, _UF __f,
                         _T const& __new_value) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::replace_if(__first, __last, __f, __new_value);
  }

  //========== reverse ==========

  template <class _BDIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void reverse(__no_policy, _BDIt __first, _BDIt __last) {
    _ASSERT_RANDOM_ACCESS(_BDIt);
    return __openacc::reverse(__first, __last);
  }

  //========== reverse_copy ==========

  template <class _BDIt, class _FIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt reverse_copy(__no_policy, _BDIt __first, _BDIt __last,
                           _FIt __d_first) {
    _ASSERT_RANDOM_ACCESS(_BDIt);
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::reverse_copy(__first, __last, __d_first);
  }

  //========== rotate ==========

  template <class _FIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt rotate(__no_policy, _FIt __first, _FIt __n_first, _FIt __last) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::rotate(__first, __n_first, __last);
  }

  //========== rotate_copy ==========

  template <class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt2 rotate_copy(__no_policy, _FIt1 __first, _FIt1 __n_first,
                           _FIt1 __last, _FIt2 __d_first) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return __openacc::rotate_copy(__first, __n_first, __last, __d_first);
  }

  //========== search ==========

  template <class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt1 search(__no_policy, _FIt1 __first, _FIt1 __last, _FIt2 __s_first,
                      _FIt2 __s_last) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return __openacc::search(__first, __last, __s_first, __s_last,
                             std::equal_to<void>());
  }

  template <class _FIt1, class _FIt2, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt1 search(__no_policy, _FIt1 __first, _FIt1 __last, _FIt2 __s_first,
                      _FIt2 __s_last, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::search(__first, __last, __s_first, __s_last, __f);
  }

  //========== shift_left ==========

  template <class _FIt>
  _NVHPC_PARALLEL_IMPL_OPENACC static _FIt
  shift_left(__no_policy, _FIt __first, _FIt __last,
             typename std::iterator_traits<_FIt>::difference_type __n) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::shift_left(__first, __last, __n);
  }

  //========== shift_right ==========

  template <class _FIt>
  _NVHPC_PARALLEL_IMPL_OPENACC static _FIt
  shift_right(__no_policy, _FIt __first, _FIt __last,
              typename std::iterator_traits<_FIt>::difference_type __n) {
    _ASSERT_RANDOM_ACCESS(_FIt);
    return __openacc::shift_right(__first, __last, __n);
  }

  //========== sort ==========

#if _NVHPC_STDPAR_ACC_EXPERIMENTAL
  template <class _RIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void sort(__no_policy, _RIt __first, _RIt __last) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    return __openacc::stable_sort(__first, __last, std::less<void>{});
  }

  template <class _RIt, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void sort(__no_policy, _RIt __first, _RIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::stable_sort(__first, __last, __cmp);
  }
#endif

  //========== stable_sort ==========

#if _NVHPC_STDPAR_ACC_EXPERIMENTAL
  template <class _RIt>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void stable_sort(__no_policy, _RIt __first, _RIt __last) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    return __openacc::stable_sort(__first, __last, std::less<void>{});
  }

  template <class _RIt, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static void stable_sort(__no_policy, _RIt __first, _RIt __last, _BF __cmp) {
    _ASSERT_RANDOM_ACCESS(_RIt);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::stable_sort(__first, __last, __cmp);
  }
#endif

  //========== swap_ranges ==========

  template <class _FIt1, class _FIt2>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt2 swap_ranges(__no_policy, _FIt1 __first1, _FIt1 __last1,
                           _FIt2 __first2) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    return __openacc::swap_ranges(__first1, __last1, __first2);
  }

  //========== transform ==========

  template <class _FIt1, class _FIt2, class _UF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt2 transform(__no_policy, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __d_first, _UF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_NOT_FUNC_PTR(_UF);
    return __openacc::transform(__first1, __last1, __d_first, __f);
  }

  template <class _FIt1, class _FIt2, class _FIt3, class _BF>
  _NVHPC_PARALLEL_IMPL_OPENACC
  static _FIt3 transform(__no_policy, _FIt1 __first1, _FIt1 __last1,
                         _FIt2 __first2, _FIt3 __d_first, _BF __f) {
    _ASSERT_RANDOM_ACCESS(_FIt1);
    _ASSERT_RANDOM_ACCESS(_FIt2);
    _ASSERT_RANDOM_ACCESS(_FIt3);
    _ASSERT_NOT_FUNC_PTR(_BF);
    return __openacc::transform(__first1, __last1, __first2, __d_first, __f);
  }

#endif // __NVCOMPILER_STDPAR_OPENACC_GPU || _NVHPC_STDPAR_GPU
};

// Each overload of each parallel algorithm has a helper class that packages up
// the argument so they can be passed around within the dispatch framework.

#define _NVHPC_ALGORITHM_CALL_IS_VALID(call) \
  _NVHPC_CALL_IS_VALID(__algorithm_impl, call)

//========== adjacent_find ==========

template <class _FIt>
struct __call_adjacent_find {
  _FIt __first;
  _FIt __last;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::adjacent_find(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      adjacent_find(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                    std::declval<_FIt>()));
};

template <class _FIt, class _BF>
struct __call_adjacent_find_pred {
  _FIt __first;
  _FIt __last;
  _BF __f;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::adjacent_find(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      adjacent_find(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                    std::declval<_FIt>(), std::declval<_BF>()));
};

//========== all_of ==========

template <class _FIt, class _UF>
struct __call_all_of {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::all_of(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      all_of(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
             std::declval<_FIt>(), std::declval<_UF>()));
};

//========== any_of ==========

template <class _FIt, class _UF>
struct __call_any_of {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::any_of(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      any_of(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
             std::declval<_FIt>(), std::declval<_UF>()));
};

//========== copy ==========

template <class _FIt1, class _FIt2>
struct __call_copy {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      copy(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
           std::declval<_FIt1>(), std::declval<_FIt2>()));
};

//========== copy_if ==========

template <class _FIt1, class _FIt2, class _UF>
struct __call_copy_if {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  _UF __f;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::copy_if(
        __policy_for<_BE>::__policy(), __first, __last, __d_first, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      copy_if(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
              std::declval<_FIt1>(), std::declval<_FIt2>(),
              std::declval<_UF>()));
};

//========== copy_n ==========

template <class _FIt1, class _Size, class _FIt2>
struct __call_copy_n {
  _FIt1 __first;
  _Size __count;
  _FIt2 __d_first;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::copy_n(
        __policy_for<_BE>::__policy(), __first, __count, __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      copy_n(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
             std::declval<_Size>(), std::declval<_FIt2>()));
};

//========== count ==========

template <class _FIt, class _T>
struct __call_count {
  _FIt __first;
  _FIt __last;
  _T const& __value;
  using __return_type = typename std::iterator_traits<_FIt>::difference_type;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::count(
        __policy_for<_BE>::__policy(), __first, __last, __value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      count(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
            std::declval<_FIt>(), std::declval<_T const&>()));
};

//========== count_if ==========

template <class _FIt, class _UF>
struct __call_count_if {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = typename std::iterator_traits<_FIt>::difference_type;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::count_if(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      count_if(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
               std::declval<_FIt>(), std::declval<_UF>()));
};

//========== equal ==========

template <class _FIt1, class _FIt2>
struct __call_equal {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::equal(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      equal(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
            std::declval<_FIt1>(), std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_equal_pred {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _BF __f;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::equal(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      equal(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
            std::declval<_FIt1>(), std::declval<_FIt2>(),
            std::declval<_BF>()));
};

template <class _FIt1, class _FIt2>
struct __call_equal_2ends {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::equal(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      equal(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
            std::declval<_FIt1>(), std::declval<_FIt2>(),
            std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_equal_2ends_pred {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _BF __f;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::equal(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      equal(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
            std::declval<_FIt1>(), std::declval<_FIt2>(),
            std::declval<_FIt2>(), std::declval<_BF>()));
};

//========== fill ==========

template <class _FIt, class _T>
struct __call_fill {
  _FIt __first;
  _FIt __last;
  _T const& __value;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::fill(
        __policy_for<_BE>::__policy(), __first, __last, __value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      fill(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
           std::declval<_FIt>(), std::declval<_T const&>()));
};

//========== fill_n ==========

template <class _FIt, class _Size, class _T>
struct __call_fill_n {
  _FIt __first;
  _Size __count;
  _T const& __value;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::fill_n(
        __policy_for<_BE>::__policy(), __first, __count, __value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      fill_n(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
             std::declval<_Size>(), std::declval<_T const&>()));
};

//========== find ==========

template <class _FIt, class _T>
struct __call_find {
  _FIt __first;
  _FIt __last;
  _T const& __value;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::find(
        __policy_for<_BE>::__policy(), __first, __last, __value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      find(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
           std::declval<_FIt>(), std::declval<_T const&>()));
};

//========== find_end ==========

template <class _FIt1, class _FIt2>
struct __call_find_end {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __s_first;
  _FIt2 __s_last;
  using __return_type = _FIt1;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::find_end(
        __policy_for<_BE>::__policy(), __first, __last, __s_first, __s_last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      find_end(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
               std::declval<_FIt1>(), std::declval<_FIt2>(),
               std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_find_end_pred {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __s_first;
  _FIt2 __s_last;
  _BF __f;
  using __return_type = _FIt1;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::find_end(
        __policy_for<_BE>::__policy(), __first, __last, __s_first, __s_last,
        __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      find_end(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
               std::declval<_FIt1>(), std::declval<_FIt2>(),
               std::declval<_FIt2>(), std::declval<_BF>()));
};

//========== find_first_of ==========

template <class _FIt1, class _FIt2>
struct __call_find_first_of {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __s_first;
  _FIt2 __s_last;
  using __return_type = _FIt1;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::find_first_of(
        __policy_for<_BE>::__policy(), __first, __last, __s_first, __s_last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      find_first_of(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                    std::declval<_FIt1>(), std::declval<_FIt2>(),
                    std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_find_first_of_pred {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __s_first;
  _FIt2 __s_last;
  _BF __f;
  using __return_type = _FIt1;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::find_first_of(
        __policy_for<_BE>::__policy(), __first, __last, __s_first, __s_last,
        __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      find_first_of(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                    std::declval<_FIt1>(), std::declval<_FIt2>(),
                    std::declval<_FIt2>(), std::declval<_BF>()));
};

//========== find_if ==========

template <class _FIt, class _UF>
struct __call_find_if {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::find_if(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      find_if(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
              std::declval<_FIt>(), std::declval<_UF>()));
};

//========== find_if_not ==========

template <class _FIt, class _UF>
struct __call_find_if_not {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::find_if_not(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      find_if_not(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                  std::declval<_FIt>(), std::declval<_UF>()));
};

//========== for_each ==========

template <class _FIt, class _UF>
struct __call_for_each {
  _FIt __first;
  _FIt __last;                                                                  
  _UF __f;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::for_each(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      for_each(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
               std::declval<_FIt>(), std::declval<_UF>()));
};

//========== for_each_n ==========

template <class _FIt, class _Size, class _UF>
struct __call_for_each_n {
  _FIt __first;
  _Size __n;
  _UF __f;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::for_each_n(
        __policy_for<_BE>::__policy(), __first, __n, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      for_each_n(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                 std::declval<_Size>(), std::declval<_UF>()));
};

//========== generate ==========

template <class _FIt, class _Generator>
struct __call_generate {
  _FIt __first;
  _FIt __last;
  _Generator __g;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::generate(
        __policy_for<_BE>::__policy(), __first, __last, __g);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      generate(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
               declval<_FIt>(), std::declval<_Generator>()));
};

//========== generate_n ==========

template <class _FIt, class _Size, class _Generator>
struct __call_generate_n {
  _FIt __first;
  _Size __count;
  _Generator __g;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::generate_n(
        __policy_for<_BE>::__policy(), __first, __count, __g);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      generate_n(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                 declval<_Size>(), std::declval<_Generator>()));
};

//========== includes ==========

template <class _FIt1, class _FIt2>
struct __call_includes {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::includes(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      includes(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
               std::declval<_FIt1>(), std::declval<_FIt2>(),
               std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_includes_cmp {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _BF __cmp;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::includes(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      includes(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
               std::declval<_FIt1>(), std::declval<_FIt2>(),
               std::declval<_FIt2>(), std::declval<_BF>()));
};

//========== inplace_merge ==========

template <class _BDIt>
struct __call_inplace_merge {
  _BDIt __first;
  _BDIt __middle;
  _BDIt __last;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::inplace_merge(
        __policy_for<_BE>::__policy(), __first, __middle, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      inplace_merge(__policy_for<_BE>::__policy(), std::declval<_BDIt>(),
                    std::declval<_BDIt>(), std::declval<_BDIt>()));
};

template <class _BDIt, class _BF>
struct __call_inplace_merge_cmp {
  _BDIt __first;
  _BDIt __middle;
  _BDIt __last;
  _BF __cmp;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::inplace_merge(
        __policy_for<_BE>::__policy(), __first, __middle, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      inplace_merge(__policy_for<_BE>::__policy(), std::declval<_BDIt>(),
                    std::declval<_BDIt>(), std::declval<_BDIt>(),
                    std::declval<_BF>()));
};

//========== is_heap ==========

template <class _RIt>
struct __call_is_heap {
  _RIt __first;
  _RIt __last;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_heap(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_heap(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
              std::declval<_RIt>()));
};

template <class _RIt, class _BF>
struct __call_is_heap_cmp {
  _RIt __first;
  _RIt __last;
  _BF __cmp;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_heap(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_heap(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
              std::declval<_RIt>(), std::declval<_BF>()));
};

//========== is_heap_until ==========

template <class _RIt>
struct __call_is_heap_until {
  _RIt __first;
  _RIt __last;
  using __return_type = _RIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_heap_until(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_heap_until(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
                    std::declval<_RIt>()));
};

template <class _RIt, class _BF>
struct __call_is_heap_until_cmp {
  _RIt __first;
  _RIt __last;
  _BF __cmp;
  using __return_type = _RIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_heap_until(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_heap_until(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
                    std::declval<_RIt>(), std::declval<_BF>()));
};

//========== is_partitioned ==========

template <class _FIt, class _UF>
struct __call_is_partitioned {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_partitioned(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_partitioned(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                     std::declval<_FIt>(), std::declval<_UF>()));
};

//========== is_sorted ==========

template <class _FIt>
struct __call_is_sorted {
  _FIt __first;
  _FIt __last;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_sorted(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_sorted(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                std::declval<_FIt>()));
};

template <class _FIt, class _BF>
struct __call_is_sorted_cmp {
  _FIt __first;
  _FIt __last;
  _BF __cmp;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_sorted(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_sorted(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                std::declval<_FIt>(), std::declval<_BF>()));
};

//========== is_sorted_until ==========

template <class _FIt>
struct __call_is_sorted_until {
  _FIt __first;
  _FIt __last;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_sorted_until(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_sorted_until(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                      std::declval<_FIt>()));
};

template <class _FIt, class _BF>
struct __call_is_sorted_until_cmp {
  _FIt __first;
  _FIt __last;
  _BF __cmp;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::is_sorted_until(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      is_sorted_until(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                      std::declval<_FIt>(), std::declval<_BF>()));
};

//========== lexicographical_compare ==========

template <class _FIt1, class _FIt2>
struct __call_lexicographical_compare {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::lexicographical_compare(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      lexicographical_compare(__policy_for<_BE>::__policy(),
                              std::declval<_FIt1>(), std::declval<_FIt1>(),
                              std::declval<_FIt2>(), std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_lexicographical_compare_cmp {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _BF __cmp;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::lexicographical_compare(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      lexicographical_compare(__policy_for<_BE>::__policy(),
                              std::declval<_FIt1>(), std::declval<_FIt1>(),
                              std::declval<_FIt2>(), std::declval<_FIt2>(), 
                              std::declval<_BF>()));
};

//========== max_element ==========

template <class _FIt>
struct __call_max_element {
  _FIt __first;
  _FIt __last;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::max_element(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      max_element(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                  std::declval<_FIt>()));
};

template <class _FIt, class _BF>
struct __call_max_element_cmp {
  _FIt __first;
  _FIt __last;
  _BF __cmp;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::max_element(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      max_element(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                  std::declval<_FIt>(), std::declval<_BF>()));
};

//========== merge ==========

template <class _FIt1, class _FIt2, class _FIt3>
struct __call_merge {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::merge(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      merge(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
            std::declval<_FIt1>(), std::declval<_FIt2>(),
            std::declval<_FIt2>(), std::declval<_FIt3>()));
};

template <class _FIt1, class _FIt2, class _FIt3, class _BF>
struct __call_merge_cmp {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  _BF __cmp;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::merge(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      merge(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
            std::declval<_FIt1>(), std::declval<_FIt2>(),
            std::declval<_FIt2>(), std::declval<_FIt3>(),
            std::declval<_BF>()));
};

//========== min_element ==========

template <class _FIt>
struct __call_min_element {
  _FIt __first;
  _FIt __last;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::min_element(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      min_element(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                  std::declval<_FIt>()));
};

template <class _FIt, class _BF>
struct __call_min_element_cmp {
  _FIt __first;
  _FIt __last;
  _BF __cmp;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::min_element(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      min_element(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                  std::declval<_FIt>(), std::declval<_BF>()));
};

//========== minmax_element ==========

template <class _FIt>
struct __call_minmax_element {
  _FIt __first;
  _FIt __last;
  using __return_type = std::pair<_FIt, _FIt>;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::minmax_element(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      minmax_element(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                     std::declval<_FIt>()));
};

template <class _FIt, class _BF>
struct __call_minmax_element_cmp {
  _FIt __first;
  _FIt __last;
  _BF __cmp;
  using __return_type = std::pair<_FIt, _FIt>;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::minmax_element(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      minmax_element(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                     std::declval<_FIt>(), std::declval<_BF>()));
};

//========== mismatch ==========

template <class _FIt1, class _FIt2>
struct __call_mismatch {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  using __return_type = std::pair<_FIt1, _FIt2>;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::mismatch(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      mismatch(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
               std::declval<_FIt1>(), std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_mismatch_pred {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _BF __f;
  using __return_type = std::pair<_FIt1, _FIt2>;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::mismatch(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      mismatch(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
               std::declval<_FIt1>(), std::declval<_FIt2>(),
               std::declval<_BF>()));
};

template <class _FIt1, class _FIt2>
struct __call_mismatch_2ends {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  using __return_type = std::pair<_FIt1, _FIt2>;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::mismatch(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      mismatch(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
               std::declval<_FIt1>(), std::declval<_FIt2>(),
               std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_mismatch_2ends_pred {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _BF __f;
  using __return_type = std::pair<_FIt1, _FIt2>;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::mismatch(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      mismatch(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
               std::declval<_FIt1>(), std::declval<_FIt2>(),
               std::declval<_FIt2>(), std::declval<_BF>()));
};

//========== move ==========

template <class _FIt1, class _FIt2>
struct __call_move {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::move(
        __policy_for<_BE>::__policy(), __first, __last, __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      move(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
           std::declval<_FIt1>(), std::declval<_FIt2>()));
};

//========== none_of ==========

template <class _FIt, class _UF>
struct __call_none_of {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = bool;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::none_of(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      none_of(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
              std::declval<_FIt>(), std::declval<_UF>()));
};

//========== nth_element ==========

template <class _RIt>
struct __call_nth_element {
  _RIt __first;
  _RIt __nth;
  _RIt __last;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::nth_element(
        __policy_for<_BE>::__policy(), __first, __nth, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      nth_element(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
                  std::declval<_RIt>(), std::declval<_RIt>()));
};

template <class _RIt, class _BF>
struct __call_nth_element_cmp {
  _RIt __first;
  _RIt __nth;
  _RIt __last;
  _BF __cmp;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::nth_element(
        __policy_for<_BE>::__policy(), __first, __nth, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      nth_element(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
                  std::declval<_RIt>(), std::declval<_RIt>(),
                  std::declval<_BF>()));
};

//========== partial_sort ==========

template <class _RIt>
struct __call_partial_sort {
  _RIt __first;
  _RIt __middle;
  _RIt __last;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::partial_sort(
        __policy_for<_BE>::__policy(), __first, __middle, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      partial_sort(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
                   std::declval<_RIt>(), std::declval<_RIt>()));
};

template <class _RIt, class _BF>
struct __call_partial_sort_cmp {
  _RIt __first;
  _RIt __middle;
  _RIt __last;
  _BF __cmp;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::partial_sort(
        __policy_for<_BE>::__policy(), __first, __middle, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      partial_sort(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
                   std::declval<_RIt>(), std::declval<_RIt>(),
                   std::declval<_BF>()));
};

//========== partial_sort_copy ==========

template <class _FIt, class _RIt>
struct __call_partial_sort_copy {
  _FIt __first;
  _FIt __last;
  _RIt __d_first;
  _RIt __d_last;
  using __return_type = _RIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::partial_sort_copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_first, __d_last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      partial_sort_copy(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                        std::declval<_FIt>(), std::declval<_RIt>(),
                        std::declval<_RIt>()));
};

template <class _FIt, class _RIt, class _BF>
struct __call_partial_sort_copy_cmp {
  _FIt __first;
  _FIt __last;
  _RIt __d_first;
  _RIt __d_last;
  _BF __cmp;
  using __return_type = _RIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::partial_sort_copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_first, __d_last,
        __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      partial_sort_copy(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                        std::declval<_FIt>(), std::declval<_RIt>(),
                        std::declval<_RIt>(), std::declval<_BF>()));
};

//========== partition ==========

template <class _FIt, class _UF>
struct __call_partition {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::partition(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      partition(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                std::declval<_FIt>(), std::declval<_UF>()));
};

//========== partition_copy ==========

template <class _FIt1, class _FIt2, class _FIt3, class _UF>
struct __call_partition_copy {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_true;
  _FIt3 __d_false;
  _UF __f;
  using __return_type = std::pair<_FIt2, _FIt3>;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::partition_copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_true, __d_false,
        __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      partition_copy(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                     std::declval<_FIt1>(), std::declval<_FIt2>(),
                     std::declval<_FIt3>(), std::declval<_UF>()));
};

//========== remove ==========

template <class _FIt, class _T>
struct __call_remove {
  _FIt __first;
  _FIt __last;
  _T const& __value;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::remove(
        __policy_for<_BE>::__policy(), __first, __last, __value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      remove(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
             std::declval<_FIt>(), std::declval<_T const&>()));
};

//========== remove_copy ==========

template <class _FIt1, class _FIt2, class _T>
struct __call_remove_copy {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  _T const& __value;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::remove_copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_first, __value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      remove_copy(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                  std::declval<_FIt1>(), std::declval<_FIt2>(),
                  std::declval<_T const&>()));
};

//========== remove_copy_if =========

template <class _FIt1, class _FIt2, class _UF>
struct __call_remove_copy_if {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  _UF __f;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::remove_copy_if(
        __policy_for<_BE>::__policy(), __first, __last, __d_first, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      remove_copy_if(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                     std::declval<_FIt1>(), std::declval<_FIt2>(),
                     std::declval<_UF>()));
};

//========== remove_if ==========

template <class _FIt, class _UF>
struct __call_remove_if {
  _FIt __first;
  _FIt __last;
  _UF __f;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::remove_if(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      remove_if(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                std::declval<_FIt>(), std::declval<_UF>()));
};

//========== replace ==========

template <class _FIt, class _T>
struct __call_replace {
  _FIt __first;
  _FIt __last;
  _T const& __old_value;
  _T const& __new_value;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::replace(
        __policy_for<_BE>::__policy(), __first, __last, __old_value,
        __new_value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      replace(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
              std::declval<_FIt>(), std::declval<_T const&>(),
              std::declval<_T const&>()));
};

//========== replace_copy ==========

template <class _FIt1, class _FIt2, class _T>
struct __call_replace_copy {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  _T const& __old_value;
  _T const& __new_value;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::replace_copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_first, __old_value,
        __new_value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      replace_copy(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                   std::declval<_FIt1>(), std::declval<_FIt2>(),
                   std::declval<_T const&>(), std::declval<_T const&>()));
};

//========== replace_copy_if ==========

template <class _FIt1, class _FIt2, class _UF, class _T>
struct __call_replace_copy_if {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  _UF __f;
  _T const& __new_value;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::replace_copy_if(
        __policy_for<_BE>::__policy(), __first, __last, __d_first, __f,
        __new_value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      replace_copy_if(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                      std::declval<_FIt1>(), std::declval<_FIt2>(),
                      std::declval<_UF>(), std::declval<_T const&>()));
};

//========== replace_if ==========

template <class _FIt, class _UF, class _T>
struct __call_replace_if {
  _FIt __first;
  _FIt __last;
  _UF __f;
  _T const& __new_value;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::replace_if(
        __policy_for<_BE>::__policy(), __first, __last, __f, __new_value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      replace_if(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
                 std::declval<_FIt>(), std::declval<_UF>(),
                 std::declval<_T const&>()));
};

//========== reverse ==========

template <class _BDIt>
struct __call_reverse {
  _BDIt __first;
  _BDIt __last;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::reverse(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      reverse(__policy_for<_BE>::__policy(), std::declval<_BDIt>(),
              std::declval<_BDIt>()));
};

//========== reverse_copy ==========

template <class _BDIt, class _FIt>
struct __call_reverse_copy {
  _BDIt __first;
  _BDIt __last;
  _FIt __d_first;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::reverse_copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      reverse_copy(__policy_for<_BE>::__policy(), std::declval<_BDIt>(),
                   std::declval<_BDIt>(), std::declval<_FIt>()));
};

//========== rotate ==========

template <class _FIt>
struct __call_rotate {
  _FIt __first;
  _FIt __n_first;
  _FIt __last;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::rotate(
        __policy_for<_BE>::__policy(), __first, __n_first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      rotate(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
             std::declval<_FIt>(), std::declval<_FIt>()));
};

//========== rotate_copy ==========

template <class _FIt1, class _FIt2>
struct __call_rotate_copy {
  _FIt1 __first;
  _FIt1 __n_first;
  _FIt1 __last;
  _FIt2 __d_first;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::rotate_copy(
        __policy_for<_BE>::__policy(), __first, __n_first, __last, __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      rotate_copy(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                  std::declval<_FIt1>(), std::declval<_FIt1>(),
                  std::declval<_FIt2>()));
};

//========== search ==========

template <class _FIt1, class _FIt2>
struct __call_search {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __s_first;
  _FIt2 __s_last;
  using __return_type = _FIt1;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::search(
        __policy_for<_BE>::__policy(), __first, __last, __s_first, __s_last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      search(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
             std::declval<_FIt1>(), std::declval<_FIt2>(),
             std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_search_pred {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __s_first;
  _FIt2 __s_last;
  _BF __f;
  using __return_type = _FIt1;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::search(
        __policy_for<_BE>::__policy(), __first, __last, __s_first, __s_last,
        __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      search(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
             std::declval<_FIt1>(), std::declval<_FIt2>(),
             std::declval<_FIt2>(), std::declval<_BF>()));
};

//========== search_n ==========

template <class _FIt, class _Size, class _T>
struct __call_search_n {
  _FIt __first;
  _FIt __last;
  _Size __count;
  _T const& __value;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::search_n(
        __policy_for<_BE>::__policy(), __first, __last, __count, __value);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      search_n(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
               std::declval<_FIt>(), std::declval<_Size>(),
               std::declval<_T const&>()));
};

template <class _FIt, class _Size, class _T, class _BF>
struct __call_search_n_pred {
  _FIt __first;
  _FIt __last;
  _Size __count;
  _T const& __value;
  _BF __f;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::search_n(
        __policy_for<_BE>::__policy(), __first, __last, __count, __value, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      search_n(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
               std::declval<_FIt>(), std::declval<_Size>(),
               std::declval<_T const&>(), std::declval<_BF>()));
};

//========== set_difference ==========

template <class _FIt1, class _FIt2, class _FIt3>
struct __call_set_difference {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::set_difference(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      set_difference(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                     std::declval<_FIt1>(), std::declval<_FIt2>(),
                     std::declval<_FIt2>(), std::declval<_FIt3>()));
};

template <class _FIt1, class _FIt2, class _FIt3, class _BF>
struct __call_set_difference_cmp {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  _BF __cmp;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::set_difference(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      set_difference(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                     std::declval<_FIt1>(), std::declval<_FIt2>(),
                     std::declval<_FIt2>(), std::declval<_FIt3>(),
                     std::declval<_BF>()));
};

//========== set_intersection ==========

template <class _FIt1, class _FIt2, class _FIt3>
struct __call_set_intersection {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::set_intersection(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      set_intersection(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                       std::declval<_FIt1>(), std::declval<_FIt2>(),
                       std::declval<_FIt2>(), std::declval<_FIt3>()));
};

template <class _FIt1, class _FIt2, class _FIt3, class _BF>
struct __call_set_intersection_cmp {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  _BF __cmp;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::set_intersection(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      set_intersection(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                       std::declval<_FIt1>(), std::declval<_FIt2>(),
                       std::declval<_FIt2>(), std::declval<_FIt3>(),
                       std::declval<_BF>()));
};

//========== set_symmetric_difference ==========

template <class _FIt1, class _FIt2, class _FIt3>
struct __call_set_symmetric_difference {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::set_symmetric_difference(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      set_symmetric_difference(__policy_for<_BE>::__policy(),
                               std::declval<_FIt1>(), std::declval<_FIt1>(),
                               std::declval<_FIt2>(), std::declval<_FIt2>(),
                               std::declval<_FIt3>()));
};

template <class _FIt1, class _FIt2, class _FIt3, class _BF>
struct __call_set_symmetric_difference_cmp {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  _BF __cmp;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::set_symmetric_difference(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      set_symmetric_difference(__policy_for<_BE>::__policy(),
                               std::declval<_FIt1>(), std::declval<_FIt1>(),
                               std::declval<_FIt2>(), std::declval<_FIt2>(),
                               std::declval<_FIt3>(), std::declval<_BF>()));
};

//========== set_union ==========

template <class _FIt1, class _FIt2, class _FIt3>
struct __call_set_union {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::set_union(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      set_union(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                std::declval<_FIt1>(), std::declval<_FIt2>(),
                std::declval<_FIt2>(), std::declval<_FIt3>()));
};

template <class _FIt1, class _FIt2, class _FIt3, class _BF>
struct __call_set_union_cmp {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt2 __last2;
  _FIt3 __d_first;
  _BF __cmp;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::set_union(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __last2,
        __d_first, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      set_union(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                std::declval<_FIt1>(), std::declval<_FIt2>(),
                std::declval<_FIt2>(), std::declval<_FIt3>(),
                std::declval<_BF>()));
};

//========== shift_left ==========

template <class _FIt>
struct __call_shift_left {
  _FIt __first;
  _FIt __last;
  typename std::iterator_traits<_FIt>::difference_type __n;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::shift_left(
        __policy_for<_BE>::__policy(), __first, __last, __n);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      shift_left(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
        std::declval<_FIt>(),
        std::declval<typename std::iterator_traits<_FIt>::difference_type>()));
};

//========== shift_right ==========

template <class _FIt>
struct __call_shift_right {
  _FIt __first;
  _FIt __last;
  typename std::iterator_traits<_FIt>::difference_type __n;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::shift_right(
        __policy_for<_BE>::__policy(), __first, __last, __n);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      shift_right(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
        std::declval<_FIt>(),
        std::declval<typename std::iterator_traits<_FIt>::difference_type>()));
};

//========== sort ==========

template <class _RIt>
struct __call_sort {
  _RIt __first;
  _RIt __last;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::sort(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      sort(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
           std::declval<_RIt>()));
};

template <class _RIt, class _BF>
struct __call_sort_cmp {
  _RIt __first;
  _RIt __last;
  _BF __cmp;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::sort(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      sort(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
           std::declval<_RIt>(), std::declval<_BF>()));
};

//========== stable_partition ==========

template <class _BDIt, class _UF>
struct __call_stable_partition {
  _BDIt __first;
  _BDIt __last;
  _UF __f;
  using __return_type = _BDIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::stable_partition(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      stable_partition(__policy_for<_BE>::__policy(), std::declval<_BDIt>(),
                       std::declval<_BDIt>(), std::declval<_UF>()));
};

//========== stable_sort ==========

template <class _RIt>
struct __call_stable_sort {
  _RIt __first;
  _RIt __last;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::stable_sort(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      stable_sort(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
                  std::declval<_RIt>()));
};

template <class _RIt, class _BF>
struct __call_stable_sort_cmp {
  _RIt __first;
  _RIt __last;
  _BF __cmp;
  using __return_type = void;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::stable_sort(
        __policy_for<_BE>::__policy(), __first, __last, __cmp);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      stable_sort(__policy_for<_BE>::__policy(), std::declval<_RIt>(),
                  std::declval<_RIt>(), std::declval<_BF>()));
};

//========== swap_ranges ==========

template <class _FIt1, class _FIt2>
struct __call_swap_ranges {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::swap_ranges(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      swap_ranges(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                  std::declval<_FIt1>(), std::declval<_FIt2>()));
};

//========== transform ==========

template <class _FIt1, class _FIt2, class _UF>
struct __call_transform {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __d_first;
  _UF __f;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::transform(
        __policy_for<_BE>::__policy(), __first1, __last1, __d_first, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      transform(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                std::declval<_FIt1>(), std::declval<_FIt2>(),
                std::declval<_UF>()));
};

template <class _FIt1, class _FIt2, class _FIt3, class _BF>
struct __call_transform_merge {
  _FIt1 __first1;
  _FIt1 __last1;
  _FIt2 __first2;
  _FIt3 __d_first;
  _BF __f;
  using __return_type = _FIt3;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::transform(
        __policy_for<_BE>::__policy(), __first1, __last1, __first2, __d_first,
        __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      transform(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                std::declval<_FIt1>(), std::declval<_FIt2>(),
                std::declval<_FIt3>(), std::declval<_BF>()));
};

//========== unique ==========

template <class _FIt>
struct __call_unique {
  _FIt __first;
  _FIt __last;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::unique(
        __policy_for<_BE>::__policy(), __first, __last);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      unique(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
             std::declval<_FIt>()));
};

template <class _FIt, class _BF>
struct __call_unique_pred {
  _FIt __first;
  _FIt __last;
  _BF __f;
  using __return_type = _FIt;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::unique(
        __policy_for<_BE>::__policy(), __first, __last, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      unique(__policy_for<_BE>::__policy(), std::declval<_FIt>(),
             std::declval<_FIt>(), std::declval<_BF>()));
};

//========== unique_copy ==========

template <class _FIt1, class _FIt2>
struct __call_unique_copy {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::unique_copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_first);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      unique_copy(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                  std::declval<_FIt1>(), std::declval<_FIt2>()));
};

template <class _FIt1, class _FIt2, class _BF>
struct __call_unique_copy_pred {
  _FIt1 __first;
  _FIt1 __last;
  _FIt2 __d_first;
  _BF __f;
  using __return_type = _FIt2;
  template <__back_end _BE>
  _NVHPC_PARALLEL_FRAMEWORK_IMPL __return_type __call() const {
    return __algorithm_impl<_BE>::unique_copy(
        __policy_for<_BE>::__policy(), __first, __last, __d_first, __f);
  }
  _NVHPC_ALGORITHM_CALL_IS_VALID(
      unique_copy(__policy_for<_BE>::__policy(), std::declval<_FIt1>(),
                  std::declval<_FIt1>(), std::declval<_FIt2>(),
                  std::declval<_BF>()));
};

} // namespace __stdpar

// The definitions of the standard parallel algorithms.

//========== adjacent_find ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
adjacent_find(_EP&&, _FIt __first, _FIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_adjacent_find<_FIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
adjacent_find(_EP&&, _FIt __first, _FIt __last, _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_adjacent_find_pred<_FIt, _BF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
} 

//========== all_of ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
all_of(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_all_of<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== any_of ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
any_of(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_any_of<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== copy ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
copy(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_copy<_FIt1, _FIt2>{__first, __last, __d_first});
  } catch (...) { std::terminate(); }
}

//========== copy_if ==========

template <class _EP, class _FIt1, class _FIt2, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
copy_if(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_copy_if<_FIt1, _FIt2, _UF>{
            __first, __last, __d_first, __f});
  } catch (...) { std::terminate(); }
}

//========== copy_n ==========

template <class _EP, class _FIt1, class _Size, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
copy_n(_EP&&, _FIt1 __first, _Size __count, _FIt2 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_copy_n<_FIt1, _Size, _FIt2>{
            __first, __count, __d_first});
  } catch (...) { std::terminate(); }
}

//========== count ==========

template <class _EP, class _FIt, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP,
    typename std::iterator_traits<_FIt>::difference_type>
count(_EP&&, _FIt __first, _FIt __last, _T const& __value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_count<_FIt, _T>{__first, __last, __value});
  } catch (...) { std::terminate(); }
}

//========== count_if ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP,
    typename std::iterator_traits<_FIt>::difference_type>
count_if(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_count_if<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== equal ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
equal(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_equal<_FIt1, _FIt2>{__first1, __last1, __first2});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
equal(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_equal_pred<_FIt1, _FIt2, _BF>{
            __first1, __last1, __first2, __f});
  } catch (...) { std::terminate(); }
} 

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
equal(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_equal_2ends<_FIt1, _FIt2>{
            __first1, __last1, __first2, __last2});
  } catch (...) { std::terminate(); }
} 

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
equal(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2,
      _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_equal_2ends_pred<_FIt1, _FIt2, _BF>{
             __first1, __last1, __first2, __last2, __f});
  } catch (...) { std::terminate(); }
}

//========== fill ==========

template <class _EP, class _FIt, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
fill(_EP&&, _FIt __first, _FIt __last, _T const& __value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_fill<_FIt, _T>{__first, __last, __value});
  } catch (...) { std::terminate(); }
}

//========== fill_n ==========

template <class _EP, class _FIt, class _Size, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
fill_n(_EP&&, _FIt __first, _Size __count, _T const& __value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_fill_n<_FIt, _Size, _T>{__first, __count, __value});
  } catch (...) { std::terminate(); }
}

//========== find ==========

template <class _EP, class _FIt, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
find(_EP&&, _FIt __first, _FIt __last, _T const& __value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
         __stdpar::__call_find<_FIt, _T>{__first, __last, __value});
  } catch (...) { std::terminate(); }
}

//========== find_end ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt1>
find_end(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __s_first, _FIt2 __s_last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_find_end<_FIt1, _FIt2>{
            __first, __last, __s_first, __s_last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt1>
find_end(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __s_first, _FIt2 __s_last,
         _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_find_end_pred<_FIt1, _FIt2, _BF>{
            __first, __last, __s_first, __s_last, __f});
  } catch (...) { std::terminate(); }
}

//========== find_first_of ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt1>
find_first_of(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __s_first,
              _FIt2 __s_last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_find_first_of<_FIt1, _FIt2>{
            __first, __last, __s_first, __s_last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt1>
find_first_of(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __s_first,
              _FIt2 __s_last, _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_find_first_of_pred<_FIt1, _FIt2, _BF>{
             __first, __last, __s_first, __s_last, __f});
  } catch (...) { std::terminate(); }
}

//========== find_if ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
find_if(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_find_if<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== find_if_not ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
find_if_not(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_find_if_not<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== for_each ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
for_each(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_for_each<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== for_each_n ==========

template <class _EP, class _FIt, class _Size, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
for_each_n(_EP&&, _FIt __first, _Size __n, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_for_each_n<_FIt, _Size, _UF>{__first, __n, __f});
  } catch (...) { std::terminate(); }
}

//========== generate ==========

template <class _EP, class _FIt, class _Generator>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
generate(_EP&&, _FIt __first, _FIt __last, _Generator __g) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_generate<_FIt, _Generator>{__first, __last, __g});
  } catch (...) { std::terminate(); }
}

//========== generate_n ==========

template <class _EP, class _FIt, class _Size, class _Generator>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
generate_n(_EP&&, _FIt __first, _Size __count, _Generator __g) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_generate_n<_FIt, _Size, _Generator>{
            __first, __count, __g});
  } catch (...) { std::terminate(); }
}

//========== includes ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
includes(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_includes<_FIt1, _FIt2>{
            __first1, __last1, __first2, __last2});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
includes(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2,
         _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_includes_cmp<_FIt1, _FIt2, _BF>{
            __first1, __last1, __first2, __last2, __cmp});
  } catch (...) { std::terminate(); }
} 

//========== inplace_merge ==========

template <class _EP, class _BDIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
inplace_merge(_EP&&, _BDIt __first, _BDIt __middle, _BDIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_inplace_merge<_BDIt>{__first, __middle, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _BDIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
inplace_merge(_EP&&, _BDIt __first, _BDIt __middle, _BDIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_inplace_merge_cmp<_BDIt, _BF>{
            __first, __middle, __last, __cmp});
  } catch (...) { std::terminate(); }
} 

//========== is_heap ==========

template <class _EP, class _RIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
is_heap(_EP&&, _RIt __first, _RIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_heap<_RIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _RIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
is_heap(_EP&&, _RIt __first, _RIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_heap_cmp<_RIt, _BF>{__first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== is_heap_until ==========

template <class _EP, class _RIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _RIt>
is_heap_until(_EP&&, _RIt __first, _RIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_heap_until<_RIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _RIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _RIt>
is_heap_until(_EP&&, _RIt __first, _RIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_heap_until_cmp<_RIt, _BF>{__first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== is_partitioned ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
is_partitioned(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_partitioned<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== is_sorted ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
is_sorted(_EP&&, _FIt __first, _FIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_sorted<_FIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
is_sorted(_EP&&, _FIt __first, _FIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_sorted_cmp<_FIt, _BF>{__first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== is_sorted_until ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
is_sorted_until(_EP&&, _FIt __first, _FIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_sorted_until<_FIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
is_sorted_until(_EP&&, _FIt __first, _FIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_is_sorted_until_cmp<_FIt, _BF>{
            __first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== lexicographical_compare ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
lexicographical_compare(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                        _FIt2 __last2) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_lexicographical_compare<_FIt1, _FIt2>{
            __first1, __last1, __first2, __last2});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
lexicographical_compare(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                        _FIt2 __last2, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_lexicographical_compare_cmp<_FIt1, _FIt2, _BF>{
            __first1, __last1, __first2, __last2, __cmp});
  } catch (...) { std::terminate(); }
}

//========== max_element ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
max_element(_EP&&, _FIt __first, _FIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_max_element<_FIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
max_element(_EP&&, _FIt __first, _FIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_max_element_cmp<_FIt, _BF>{__first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== merge ==========

template <class _EP, class _FIt1, class _FIt2, class _FIt3>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
merge(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2,
      _FIt3 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_merge<_FIt1, _FIt2, _FIt3>{
            __first1, __last1, __first2, __last2, __d_first});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
merge(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2,
      _FIt3 __d_first, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_merge_cmp<_FIt1, _FIt2, _FIt3, _BF>{
            __first1, __last1, __first2, __last2, __d_first, __cmp});
  } catch (...) { std::terminate(); }
}

//========== min_element ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
min_element(_EP&&, _FIt __first, _FIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_min_element<_FIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
min_element(_EP&&, _FIt __first, _FIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_min_element_cmp<_FIt, _BF>{__first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== minmax_element ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, std::pair<_FIt, _FIt>>
minmax_element(_EP&&, _FIt __first, _FIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_minmax_element<_FIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, std::pair<_FIt, _FIt>>
minmax_element(_EP&&, _FIt __first, _FIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_minmax_element_cmp<_FIt, _BF>{__first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== mismatch ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, std::pair<_FIt1, _FIt2>>
mismatch(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_mismatch<_FIt1, _FIt2>{__first1, __last1, __first2});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, std::pair<_FIt1, _FIt2>>
mismatch(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_mismatch_pred<_FIt1, _FIt2, _BF>{
            __first1, __last1, __first2, __f});
  } catch (...) { std::terminate(); }
} 

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, std::pair<_FIt1, _FIt2>>
mismatch(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_mismatch_2ends<_FIt1, _FIt2>{
            __first1, __last1, __first2, __last2});
  } catch (...) { std::terminate(); }
} 

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, std::pair<_FIt1, _FIt2>>
mismatch(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2,
         _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_mismatch_2ends_pred<_FIt1, _FIt2, _BF>{
            __first1, __last1, __first2, __last2, __f});
  } catch (...) { std::terminate(); }
} 

//========== move ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
move(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_move<_FIt1, _FIt2>{__first, __last, __d_first});
  } catch (...) { std::terminate(); }
}

//========== none_of ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, bool>
none_of(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_none_of<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== nth_element ==========

template <class _EP, class _RIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
nth_element(_EP&&, _RIt __first, _RIt __nth, _RIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_nth_element<_RIt>{__first, __nth, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _RIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
nth_element(_EP&&, _RIt __first, _RIt __nth, _RIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_nth_element_cmp<_RIt, _BF>{
            __first, __nth, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== partial_sort ==========

template <class _EP, class _RIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
partial_sort(_EP&&, _RIt __first, _RIt __middle, _RIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_partial_sort<_RIt>{__first, __middle, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _RIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
partial_sort(_EP&&, _RIt __first, _RIt __middle, _RIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_partial_sort_cmp<_RIt, _BF>{
            __first, __middle, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== partial_sort_copy ==========

template <class _EP, class _FIt, class _RIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _RIt>
partial_sort_copy(_EP&&, _FIt __first, _FIt __last, _RIt __d_first,
                  _RIt __d_last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_partial_sort_copy<_FIt, _RIt>{
            __first, __last, __d_first, __d_last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _RIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _RIt>
partial_sort_copy(_EP&&, _FIt __first, _FIt __last, _RIt __d_first,
                  _RIt __d_last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_partial_sort_copy_cmp<_FIt, _RIt, _BF>{
            __first, __last, __d_first, __d_last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== partition ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
partition(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_partition<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== partition_copy ==========

template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, std::pair<_FIt2, _FIt3>>
partition_copy(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_true,
               _FIt3 __d_false, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_partition_copy<_FIt1, _FIt2, _FIt3, _UF>{
            __first, __last, __d_true, __d_false, __f});
  } catch (...) { std::terminate(); }
}

//========== remove ==========

template <class _EP, class _FIt, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
remove(_EP&&, _FIt __first, _FIt __last, _T const& __value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_remove<_FIt, _T>{__first, __last, __value});
  } catch (...) { std::terminate(); }
}

//========== remove_copy ==========

template <class _EP, class _FIt1, class _FIt2, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
remove_copy(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first,
            _T const& __value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_remove_copy<_FIt1, _FIt2, _T>{
            __first, __last, __d_first, __value});
  } catch (...) { std::terminate(); }
}

//========== remove_copy_if ==========

template <class _EP, class _FIt1, class _FIt2, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
remove_copy_if(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_remove_copy_if<_FIt1, _FIt2, _UF>{
            __first, __last, __d_first, __f});
  } catch (...) { std::terminate(); }
} 

//========== remove_if ==========

template <class _EP, class _FIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
remove_if(_EP&&, _FIt __first, _FIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_remove_if<_FIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== replace ==========

template <class _EP, class _FIt, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
replace(_EP&&, _FIt __first, _FIt __last, _T const& __old_value,
        _T const& __new_value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_replace<_FIt, _T>{
            __first, __last, __old_value, __new_value});
  } catch (...) { std::terminate(); }
}

//========== replace_copy ==========

template <class _EP, class _FIt1, class _FIt2, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
replace_copy(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first,
            _T const& __old_value, _T const& __new_value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_replace_copy<_FIt1, _FIt2, _T>{
            __first, __last, __d_first, __old_value, __new_value});
  } catch (...) { std::terminate(); }
}

//========== replace_copy_if ==========

template <class _EP, class _FIt1, class _FIt2, class _UF, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
replace_copy_if(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first, _UF __f,
                _T const& __new_value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_replace_copy_if<_FIt1, _FIt2, _UF, _T>{
            __first, __last, __d_first, __f, __new_value});
  } catch (...) { std::terminate(); }
}

//========== replace_if ==========

template <class _EP, class _FIt, class _UF, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
replace_if(_EP&&, _FIt __first, _FIt __last, _UF __f, _T const& __new_value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_replace_if<_FIt, _UF, _T>{
            __first, __last, __f, __new_value});
  } catch (...) { std::terminate(); }
}

//========== reverse ==========

template <class _EP, class _BDIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
reverse(_EP&&, _BDIt __first, _BDIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_reverse<_BDIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

//========== reverse_copy ==========

template <class _EP, class _BDIt, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
reverse_copy(_EP&&, _BDIt __first, _BDIt __last, _FIt __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_reverse_copy<_BDIt, _FIt>{__first, __last, __d_first});
  } catch (...) { std::terminate(); }
}

//========== rotate ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
rotate(_EP&&, _FIt __first, _FIt __n_first, _FIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_rotate<_FIt>{__first, __n_first, __last});
  } catch (...) { std::terminate(); }
}

//========== rotate_copy ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
rotate_copy(_EP&&, _FIt1 __first, _FIt1 __n_first, _FIt1 __last,
            _FIt2 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_rotate_copy<_FIt1, _FIt2>{
            __first, __n_first, __last, __d_first});
  } catch (...) { std::terminate(); }
}

//========== search ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt1>
search(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __s_first, _FIt2 __s_last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_search<_FIt1, _FIt2>{
            __first, __last, __s_first, __s_last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt1>
search(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __s_first, _FIt2 __s_last,
       _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_search_pred<_FIt1, _FIt2, _BF>{
            __first, __last, __s_first, __s_last, __f});
  } catch (...) { std::terminate(); }
}

//========== search_n ==========

template <class _EP, class _FIt, class _Size, class _T>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
search_n(_EP&&, _FIt __first, _FIt __last, _Size __count, _T const& __value) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_search_n<_FIt, _Size, _T>{
            __first, __last, __count, __value});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _Size, class _T, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
search_n(_EP&&, _FIt __first, _FIt __last, _Size __count, _T const& __value,
         _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_search_n_pred<_FIt, _Size, _T, _BF>{
            __first, __last, __count, __value, __f});
  } catch (...) { std::terminate(); }
} 

//========== set_difference ==========

template <class _EP, class _FIt1, class _FIt2, class _FIt3>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
set_difference(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
               _FIt2 __last2, _FIt3 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_set_difference<_FIt1, _FIt2, _FIt3>{
            __first1, __last1, __first2, __last2, __d_first});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
set_difference(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
               _FIt2 __last2, _FIt3 __d_first, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_set_difference_cmp<_FIt1, _FIt2, _FIt3, _BF>{
            __first1, __last1, __first2, __last2, __d_first, __cmp});
  } catch (...) { std::terminate(); }
}

//========== set_intersection ==========

template <class _EP, class _FIt1, class _FIt2, class _FIt3>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
set_intersection(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                 _FIt2 __last2, _FIt3 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_set_intersection<_FIt1, _FIt2, _FIt3>{
            __first1, __last1, __first2, __last2, __d_first});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
set_intersection(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                 _FIt2 __last2, _FIt3 __d_first, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_set_intersection_cmp<_FIt1, _FIt2, _FIt3, _BF>{
            __first1, __last1, __first2, __last2, __d_first, __cmp});
  } catch (...) { std::terminate(); }
}

//========== set_symmetric_difference ==========

template <class _EP, class _FIt1, class _FIt2, class _FIt3>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
set_symmetric_difference(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                         _FIt2 __last2, _FIt3 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_set_symmetric_difference<_FIt1, _FIt2, _FIt3>{
            __first1, __last1, __first2, __last2, __d_first});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
set_symmetric_difference(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
                         _FIt2 __last2, _FIt3 __d_first, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_set_symmetric_difference_cmp<_FIt1, _FIt2, _FIt3, _BF>{
            __first1, __last1, __first2, __last2, __d_first, __cmp});
  } catch (...) { std::terminate(); }
}

//========== set_union ==========

template <class _EP, class _FIt1, class _FIt2, class _FIt3>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
set_union(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2,
          _FIt3 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_set_union<_FIt1, _FIt2, _FIt3>{
            __first1, __last1, __first2, __last2, __d_first});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
set_union(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2, _FIt2 __last2,
          _FIt3 __d_first, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_set_union_cmp<_FIt1, _FIt2, _FIt3, _BF>{
            __first1, __last1, __first2, __last2, __d_first, __cmp});
  } catch (...) { std::terminate(); }
}

//========== shift_left ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
shift_left(_EP&&, _FIt __first, _FIt __last,
           typename std::iterator_traits<_FIt>::difference_type __n) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_shift_left<_FIt>{__first, __last, __n});
  } catch (...) { std::terminate(); }
}

//========== shift_right ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
shift_right(_EP&&, _FIt __first, _FIt __last,
            typename std::iterator_traits<_FIt>::difference_type __n) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_shift_right<_FIt>{__first, __last, __n});
  } catch (...) { std::terminate(); }
}

//========== sort ==========

template <class _EP, class _RIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
sort(_EP&&, _RIt __first, _RIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_sort<_RIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _RIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
sort(_EP&&, _RIt __first, _RIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_sort_cmp<_RIt, _BF>{__first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== stable_partition ==========

template <class _EP, class _BDIt, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _BDIt>
stable_partition(_EP&&, _BDIt __first, _BDIt __last, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_stable_partition<_BDIt, _UF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== stable_sort ==========

template <class _EP, class _RIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
stable_sort(_EP&&, _RIt __first, _RIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_stable_sort<_RIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _RIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, void>
stable_sort(_EP&&, _RIt __first, _RIt __last, _BF __cmp) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_stable_sort_cmp<_RIt, _BF>{__first, __last, __cmp});
  } catch (...) { std::terminate(); }
}

//========== swap_ranges ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
swap_ranges(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_swap_ranges<_FIt1, _FIt2>{
            __first1, __last1, __first2});
  } catch (...) { std::terminate(); }
}

//========== transform ==========

template <class _EP, class _FIt1, class _FIt2, class _UF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
transform(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __d_first, _UF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_transform<_FIt1, _FIt2, _UF>{
            __first1, __last1, __d_first, __f});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _FIt3, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt3>
transform(_EP&&, _FIt1 __first1, _FIt1 __last1, _FIt2 __first2,
          _FIt3 __d_first, _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_transform_merge<_FIt1, _FIt2, _FIt3, _BF>{
            __first1, __last1, __first2, __d_first, __f});
  } catch (...) { std::terminate(); }
}

//========== unique ==========

template <class _EP, class _FIt>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
unique(_EP&&, _FIt __first, _FIt __last) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
         __stdpar::__call_unique<_FIt>{__first, __last});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt>
unique(_EP&&, _FIt __first, _FIt __last, _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_unique_pred<_FIt, _BF>{__first, __last, __f});
  } catch (...) { std::terminate(); }
}

//========== unique_copy ==========

template <class _EP, class _FIt1, class _FIt2>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
unique_copy(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_unique_copy<_FIt1, _FIt2>{__first, __last, __d_first});
  } catch (...) { std::terminate(); }
}

template <class _EP, class _FIt1, class _FIt2, class _BF>
_NVHPC_PARALLEL_ALGORITHM
__stdpar::__enable_if_EP<_EP, _FIt2>
unique_copy(_EP&&, _FIt1 __first, _FIt1 __last, _FIt2 __d_first, _BF __f) {
  try {
    _NVHPC_STDPAR_NVTX_RANGE
    return __stdpar::__dispatch<_EP>(
        __stdpar::__call_unique_copy_pred<_FIt1, _FIt2, _BF>{
            __first, __last, __d_first, __f});
  } catch (...) { std::terminate(); }
} 

} // namespace std

#endif
