25#ifndef _GLIBCXX_EXPERIMENTAL_SIMD_CONVERTER_H_ 
   26#define _GLIBCXX_EXPERIMENTAL_SIMD_CONVERTER_H_ 
   28#if __cplusplus >= 201703L 
   30_GLIBCXX_SIMD_BEGIN_NAMESPACE
 
   32template <
typename _From, 
typename _To>
 
   33  struct _SimdConverter<_From, simd_abi::scalar, _To, simd_abi::scalar,
 
   36    _GLIBCXX_SIMD_INTRINSIC 
constexpr _To operator()(_From __a) 
const noexcept 
   37    { 
return static_cast<_To
>(__a); }
 
   42template <
typename _From, 
typename _To, 
typename _Abi>
 
   43  struct _SimdConverter<_From, simd_abi::scalar, _To, _Abi,
 
   46    using _Ret = 
typename _Abi::template __traits<_To>::_SimdMember;
 
   48    template <
typename... _More>
 
   49      _GLIBCXX_SIMD_INTRINSIC 
constexpr _Ret
 
   50      operator()(_From __a, _More... __more) 
const noexcept 
   52        static_assert(
sizeof...(_More) + 1 == _Abi::template _S_size<_To>);
 
   53        static_assert(conjunction_v<is_same<_From, _More>...>);
 
   54        return __make_vector<_To>(__a, __more...);
 
   60template <
typename _From, 
typename _To, 
typename _AFrom, 
typename _ATo>
 
   61  struct _SimdConverter<
 
   62    _From, _AFrom, _To, _ATo,
 
   64      __is_fixed_size_abi<_AFrom>, __is_fixed_size_abi<_ATo>,
 
   65      is_same<_AFrom, simd_abi::scalar>, is_same<_ATo, simd_abi::scalar>,
 
   66      conjunction<is_same<_From, _To>, is_same<_AFrom, _ATo>>>>>
 
   68    using _Arg = 
typename _AFrom::template __traits<_From>::_SimdMember;
 
   69    using _Ret = 
typename _ATo::template __traits<_To>::_SimdMember;
 
   70    using _V = __vector_type_t<_To, simd_size_v<_To, _ATo>>;
 
   72    template <
typename... _More>
 
   73      _GLIBCXX_SIMD_INTRINSIC 
constexpr _Ret
 
   74      operator()(_Arg __a, _More... __more) 
const noexcept 
   75      { 
return __vector_convert<_V>(__a, __more...); }
 
   80template <
typename _From, 
typename _To>
 
   81  struct _SimdConverter<_From, simd_abi::scalar, _To, simd_abi::fixed_size<1>,
 
   84    _GLIBCXX_SIMD_INTRINSIC 
constexpr _SimdTuple<_To, simd_abi::scalar>
 
   85    operator()(_From __x) 
const noexcept 
   86    { 
return {
static_cast<_To
>(__x)}; }
 
   90template <
typename _From, 
typename _To>
 
   91  struct _SimdConverter<_From, simd_abi::fixed_size<1>, _To, simd_abi::scalar,
 
   94    _GLIBCXX_SIMD_INTRINSIC 
constexpr _To
 
   95    operator()(_SimdTuple<_From, simd_abi::scalar> __x) 
const noexcept 
   96    { 
return {
static_cast<_To
>(__x.first)}; }
 
  100template <
typename _From, 
typename _To, 
int _Np>
 
  101  struct _SimdConverter<_From, simd_abi::fixed_size<_Np>, _To,
 
  102                        simd_abi::fixed_size<_Np>,
 
  105    using _Ret = __fixed_size_storage_t<_To, _Np>;
 
  106    using _Arg = __fixed_size_storage_t<_From, _Np>;
 
  108    _GLIBCXX_SIMD_INTRINSIC 
constexpr _Ret
 
  109    operator()(
const _Arg& __x) 
const noexcept 
  111      if constexpr (is_same_v<_From, _To>)
 
  115      else if constexpr (
sizeof(_From) == 
sizeof(_To)
 
  116                         && is_integral_v<_From> && is_integral_v<_To>)
 
  117        return __bit_cast<_Ret>(__x);
 
  120      else if constexpr (__is_scalar_abi<typename _Ret::_FirstAbi>())
 
  122          return __call_with_subscripts(
 
  123            __x, make_index_sequence<_Np>(),
 
  124            [](
auto... __values) 
constexpr _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA -> _Ret {
 
  125              return __make_simd_tuple<_To, 
decltype((void) __values,
 
  126                                                     simd_abi::scalar())...>(
 
  127                static_cast<_To
>(__values)...);
 
  132      else if constexpr (_Arg::_S_first_size == _Ret::_S_first_size)
 
  134          _SimdConverter<_From, 
typename _Arg::_FirstAbi, _To,
 
  135                         typename _Ret::_FirstAbi>
 
  137          if constexpr (_Arg::_S_tuple_size == 1)
 
  138            return {__native_cvt(__x.first)};
 
  141              constexpr size_t _NRemain = _Np - _Arg::_S_first_size;
 
  142              _SimdConverter<_From, simd_abi::fixed_size<_NRemain>, _To,
 
  143                             simd_abi::fixed_size<_NRemain>>
 
  145              return {__native_cvt(__x.first), __remainder_cvt(__x.second)};
 
  150      else if constexpr (_Arg::_S_first_size > _Ret::_S_first_size)
 
  152          const auto __multiple_return_chunks
 
  153            = __convert_all<__vector_type_t<_To, _Ret::_S_first_size>>(
 
  155          constexpr auto __converted = __multiple_return_chunks.size()
 
  156                                       * _Ret::_FirstAbi::template _S_size<_To>;
 
  157          constexpr auto __remaining = _Np - __converted;
 
  158          if constexpr (_Arg::_S_tuple_size == 1 && __remaining == 0)
 
  159            return __to_simd_tuple<_To, _Np>(__multiple_return_chunks);
 
  160          else if constexpr (_Arg::_S_tuple_size == 1)
 
  164                = __remove_cvref_t<decltype(__simd_tuple_pop_front<__converted>(
 
  166              const auto __return_chunks2
 
  167                = __convert_all<__vector_type_t<_To, _RetRem::_S_first_size>, 0,
 
  168                                __converted>(__x.first);
 
  169              constexpr auto __converted2
 
  171                  + __return_chunks2.size() * _RetRem::_S_first_size;
 
  172              if constexpr (__converted2 == _Np)
 
  173                return __to_simd_tuple<_To, _Np>(__multiple_return_chunks,
 
  177                  using _RetRem2 = __remove_cvref_t<
 
  178                    decltype(__simd_tuple_pop_front<__return_chunks2.size()
 
  179                                                    * _RetRem::_S_first_size>(
 
  181                  const auto __return_chunks3 = __convert_all<
 
  182                    __vector_type_t<_To, _RetRem2::_S_first_size>, 0,
 
  183                    __converted2>(__x.first);
 
  184                  constexpr auto __converted3
 
  186                      + __return_chunks3.size() * _RetRem2::_S_first_size;
 
  187                  if constexpr (__converted3 == _Np)
 
  188                    return __to_simd_tuple<_To, _Np>(__multiple_return_chunks,
 
  194                        = __remove_cvref_t<
decltype(__simd_tuple_pop_front<
 
  195                                                    __return_chunks3.size()
 
  196                                                    * _RetRem2::_S_first_size>(
 
  198                      const auto __return_chunks4 = __convert_all<
 
  199                        __vector_type_t<_To, _RetRem3::_S_first_size>, 0,
 
  200                        __converted3>(__x.first);
 
  201                      constexpr auto __converted4
 
  203                          + __return_chunks4.size() * _RetRem3::_S_first_size;
 
  204                      if constexpr (__converted4 == _Np)
 
  205                        return __to_simd_tuple<_To, _Np>(
 
  206                          __multiple_return_chunks, __return_chunks2,
 
  207                          __return_chunks3, __return_chunks4);
 
  209                        __assert_unreachable<_To>();
 
  215              constexpr size_t _NRemain = _Np - _Arg::_S_first_size;
 
  216              _SimdConverter<_From, simd_abi::fixed_size<_NRemain>, _To,
 
  217                             simd_abi::fixed_size<_NRemain>>
 
  219              return __simd_tuple_concat(
 
  220                __to_simd_tuple<_To, _Arg::_S_first_size>(
 
  221                  __multiple_return_chunks),
 
  222                __remainder_cvt(__x.second));
 
  230      else if constexpr (_Ret::_S_tuple_size == 1
 
  231                         && _Np % _Arg::_S_first_size != 0)
 
  233          static_assert(_Ret::_FirstAbi::template _S_is_partial<_To>);
 
  234          return _Ret{__generate_from_n_evaluations<
 
  235            _Np, 
typename _VectorTraits<typename _Ret::_FirstType>::type>(
 
  236            [&](
auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
 
  237              return static_cast<_To
>(__x[__i]);
 
  242          static_assert(_Arg::_S_tuple_size > 1);
 
  244            = __div_roundup(_Ret::_S_first_size, _Arg::_S_first_size);
 
  245          return __call_with_n_evaluations<__n>(
 
  246            [&__x](
auto... __uncvted) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
 
  248              _SimdConverter<_From, 
typename _Arg::_FirstAbi, _To,
 
  249                             typename _Ret::_FirstAbi>
 
  251              if constexpr (_Ret::_S_tuple_size == 1)
 
  252                return _Ret{__native_cvt(__uncvted...)};
 
  255                  __native_cvt(__uncvted...),
 
  257                    _From, simd_abi::fixed_size<_Np - _Ret::_S_first_size>, _To,
 
  258                    simd_abi::fixed_size<_Np - _Ret::_S_first_size>>()(
 
  259                    __simd_tuple_pop_front<_Ret::_S_first_size>(__x))};
 
  260            }, [&__x](
auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
 
  261              return __get_tuple_at<__i>(__x);
 
  269template <
typename _From, 
typename _Ap, 
typename _To, 
int _Np>
 
  270  struct _SimdConverter<_From, _Ap, _To, simd_abi::fixed_size<_Np>,
 
  274      _Np == simd_size_v<_From, _Ap>,
 
  275      "_SimdConverter to fixed_size only works for equal element counts");
 
  277    using _Ret = __fixed_size_storage_t<_To, _Np>;
 
  279    _GLIBCXX_SIMD_INTRINSIC 
constexpr _Ret
 
  280    operator()(
typename _SimdTraits<_From, _Ap>::_SimdMember __x) 
const noexcept 
  282      if constexpr (_Ret::_S_tuple_size == 1)
 
  283        return {__vector_convert<typename _Ret::_FirstType::_BuiltinType>(__x)};
 
  286          using _FixedNp = simd_abi::fixed_size<_Np>;
 
  287          _SimdConverter<_From, _FixedNp, _To, _FixedNp> __fixed_cvt;
 
  288          using _FromFixedStorage = __fixed_size_storage_t<_From, _Np>;
 
  289          if constexpr (_FromFixedStorage::_S_tuple_size == 1)
 
  290            return __fixed_cvt(_FromFixedStorage{__x});
 
  291          else if constexpr (_FromFixedStorage::_S_tuple_size == 2)
 
  293              _FromFixedStorage __tmp;
 
  294              static_assert(
sizeof(__tmp) <= 
sizeof(__x));
 
  295              __builtin_memcpy(&__tmp.first, &__x, 
sizeof(__tmp.first));
 
  296              __builtin_memcpy(&__tmp.second.first,
 
  297                               reinterpret_cast<const char*
>(&__x)
 
  298                                 + 
sizeof(__tmp.first),
 
  299                               sizeof(__tmp.second.first));
 
  300              return __fixed_cvt(__tmp);
 
  303            __assert_unreachable<_From>();
 
  310template <
typename _From, 
int _Np, 
typename _To, 
typename _Ap>
 
  311  struct _SimdConverter<_From, simd_abi::fixed_size<_Np>, _To, _Ap,
 
  315      _Np == simd_size_v<_To, _Ap>,
 
  316      "_SimdConverter to fixed_size only works for equal element counts");
 
  318    using _Arg = __fixed_size_storage_t<_From, _Np>;
 
  320    _GLIBCXX_SIMD_INTRINSIC 
constexpr 
  321      typename _SimdTraits<_To, _Ap>::_SimdMember
 
  322      operator()(
const _Arg& __x) 
const noexcept 
  324      if constexpr (_Arg::_S_tuple_size == 1)
 
  325        return __vector_convert<__vector_type_t<_To, _Np>>(__x.first);
 
  326      else if constexpr (_Arg::_S_is_homogeneous)
 
  327        return __call_with_n_evaluations<_Arg::_S_tuple_size>(
 
  328          [](
auto... __members) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
 
  329            if constexpr ((is_convertible_v<
decltype(__members), _To> && ...))
 
  330              return __vector_type_t<_To, _Np>{
static_cast<_To
>(__members)...};
 
  332              return __vector_convert<__vector_type_t<_To, _Np>>(__members...);
 
  333          }, [&](
auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
 
  334            return __get_tuple_at<__i>(__x);
 
  336      else if constexpr (__fixed_size_storage_t<_To, _Np>::_S_tuple_size == 1)
 
  338          _SimdConverter<_From, simd_abi::fixed_size<_Np>, _To,
 
  339                         simd_abi::fixed_size<_Np>>
 
  341          return __fixed_cvt(__x).first;
 
  345          const _SimdWrapper<_From, _Np> __xv
 
  346            = __generate_from_n_evaluations<_Np, __vector_type_t<_From, _Np>>(
 
  347                [&](
auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 
return __x[__i]; });
 
  348          return __vector_convert<__vector_type_t<_To, _Np>>(__xv);
 
  354_GLIBCXX_SIMD_END_NAMESPACE
 
typename enable_if< _Cond, _Tp >::type enable_if_t
Alias template for enable_if.