!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.1.30 

uname -a: Linux server1.tuhinhossain.com 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC
2025 x86_64
 

uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root)  

Safe-mode: OFF (not secure)

/usr/include/c++/11/experimental/bits/   drwxr-xr-x
Free 26.58 GB of 117.98 GB (22.53%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     simd_x86_conversions.h (80.53 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
// x86 specific conversion optimizations -*- C++ -*-

// Copyright (C) 2020-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

#ifndef _GLIBCXX_EXPERIMENTAL_SIMD_X86_CONVERSIONS_H
#define _GLIBCXX_EXPERIMENTAL_SIMD_X86_CONVERSIONS_H

#if __cplusplus >= 201703L

// work around PR85827
// 1-arg __convert_x86 {{{1
template <typename _To, typename _V, typename _Traits>
  _GLIBCXX_SIMD_INTRINSIC _To
  __convert_x86(_V __v)
  {
    static_assert(__is_vector_type_v<_V>);
    using _Tp = typename _Traits::value_type;
    constexpr size_t _Np = _Traits::_S_full_size;
    [[maybe_unused]] const auto __intrin = __to_intrin(__v);
    using _Up = typename _VectorTraits<_To>::value_type;
    constexpr size_t _M = _VectorTraits<_To>::_S_full_size;

    // [xyz]_to_[xyz] {{{2
    [[maybe_unused]] constexpr bool __x_to_x
      = sizeof(__v) <= 16 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __x_to_y
      = sizeof(__v) <= 16 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __x_to_z
      = sizeof(__v) <= 16 && sizeof(_To) == 64;
    [[maybe_unused]] constexpr bool __y_to_x
      = sizeof(__v) == 32 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __y_to_y
      = sizeof(__v) == 32 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __y_to_z
      = sizeof(__v) == 32 && sizeof(_To) == 64;
    [[maybe_unused]] constexpr bool __z_to_x
      = sizeof(__v) == 64 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __z_to_y
      = sizeof(__v) == 64 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __z_to_z
      = sizeof(__v) == 64 && sizeof(_To) == 64;

    // iX_to_iX {{{2
    [[maybe_unused]] constexpr bool __i_to_i
      = is_integral_v<_Up> && is_integral_v<_Tp>;
    [[maybe_unused]] constexpr bool __i8_to_i16
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i8_to_i32
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __i8_to_i64
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i16_to_i8
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i16_to_i32
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __i16_to_i64
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i32_to_i8
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i32_to_i16
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i32_to_i64
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i64_to_i8
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i64_to_i16
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i64_to_i32
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 4;

    // [fsu]X_to_[fsu]X {{{2
    // ibw = integral && byte or word, i.e. char and short with any signedness
    [[maybe_unused]] constexpr bool __s64_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s32_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s16_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s8_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u64_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u32_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u16_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u8_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s64_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __s32_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u64_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u32_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __f32_to_s64
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_s32
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_u64
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_u32
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f64_to_s64
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_s32
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_u64
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_u32
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __ibw_to_f32
      = is_integral_v<_Tp> && sizeof(_Tp) <= 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __ibw_to_f64
      = is_integral_v<_Tp> && sizeof(_Tp) <= 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __f32_to_ibw
      = is_integral_v<_Up> && sizeof(_Up) <= 2
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f64_to_ibw
      = is_integral_v<_Up> && sizeof(_Up) <= 2
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f32_to_f64
      = is_floating_point_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __f64_to_f32
      = is_floating_point_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;

    if constexpr (__i_to_i && __y_to_x && !__have_avx2) //{{{2
      return __convert_x86<_To>(__lo128(__v), __hi128(__v));
    else if constexpr (__i_to_i && __x_to_y && !__have_avx2) //{{{2
      return __concat(__convert_x86<__vector_type_t<_Up, _M / 2>>(__v),
              __convert_x86<__vector_type_t<_Up, _M / 2>>(
            __extract_part<1, _Np / _M * 2>(__v)));
    else if constexpr (__i_to_i) //{{{2
      {
    static_assert(__x_to_x || __have_avx2,
              "integral conversions with ymm registers require AVX2");
    static_assert(__have_avx512bw
            || ((sizeof(_Tp) >= 4 || sizeof(__v) < 64)
                && (sizeof(_Up) >= 4 || sizeof(_To) < 64)),
              "8/16-bit integers in zmm registers require AVX512BW");
    static_assert((sizeof(__v) < 64 && sizeof(_To) < 64) || __have_avx512f,
              "integral conversions with ymm registers require AVX2");
      }
    if constexpr (is_floating_point_v<_Tp> == is_floating_point_v<_Up> && //{{{2
          sizeof(_Tp) == sizeof(_Up))
      {
    // conversion uses simple bit reinterpretation (or no conversion at all)
    if constexpr (_Np >= _M)
      return __intrin_bitcast<_To>(__v);
    else
      return __zero_extend(__vector_bitcast<_Up>(__v));
      }
    else if constexpr (_Np < _M && sizeof(_To) > 16) //{{{2
      // zero extend (eg. xmm -> ymm)
      return __zero_extend(
    __convert_x86<__vector_type_t<
      _Up, (16 / sizeof(_Up) > _Np) ? 16 / sizeof(_Up) : _Np>>(__v));
    else if constexpr (_Np > _M && sizeof(__v) > 16) //{{{2
      // partial input (eg. ymm -> xmm)
      return __convert_x86<_To>(__extract_part<0, _Np / _M>(__v));
    else if constexpr (__i64_to_i32) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm_cvtepi64_epi32(__intrin));
    else if constexpr (__x_to_x)
      return __auto_bitcast(
        _mm_shuffle_ps(__vector_bitcast<float>(__v), __m128(), 8));
    else if constexpr (__y_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm256_cvtepi64_epi32(__intrin));
    else if constexpr (__y_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepi64_epi32(__auto_bitcast(__v))));
    else if constexpr (__y_to_x)
      return __intrin_bitcast<_To>(
        __lo128(_mm256_permute4x64_epi64(_mm256_shuffle_epi32(__intrin, 8),
                         0 + 4 * 2)));
    else if constexpr (__z_to_y)
      return __intrin_bitcast<_To>(_mm512_cvtepi64_epi32(__intrin));
      }
    else if constexpr (__i64_to_i16) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm_cvtepi64_epi16(__intrin));
    else if constexpr (__x_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepi64_epi16(__auto_bitcast(__v))));
    else if constexpr (__x_to_x && __have_ssse3)
      {
        return __intrin_bitcast<_To>(
          _mm_shuffle_epi8(__intrin,
                   _mm_setr_epi8(0, 1, 8, 9, -0x80, -0x80, -0x80,
                         -0x80, -0x80, -0x80, -0x80, -0x80,
                         -0x80, -0x80, -0x80, -0x80)));
        // fallback without SSSE3
      }
    else if constexpr (__y_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm256_cvtepi64_epi16(__intrin));
    else if constexpr (__y_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepi64_epi16(__auto_bitcast(__v))));
    else if constexpr (__y_to_x)
      {
        const auto __a = _mm256_shuffle_epi8(
          __intrin,
          _mm256_setr_epi8(0, 1, 8, 9, -0x80, -0x80, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80, -0x80, 0, 1, 8, 9, -0x80,
                   -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
                   -0x80));
        return __intrin_bitcast<_To>(__lo128(__a) | __hi128(__a));
      }
    else if constexpr (__z_to_x)
      return __intrin_bitcast<_To>(_mm512_cvtepi64_epi16(__intrin));
      }
    else if constexpr (__i64_to_i8) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm_cvtepi64_epi8(__intrin));
    else if constexpr (__x_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepi64_epi8(__zero_extend(__intrin))));
    else if constexpr (__y_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm256_cvtepi64_epi8(__intrin));
    else if constexpr (__y_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        _mm512_cvtepi64_epi8(__zero_extend(__intrin)));
    else if constexpr (__z_to_x)
      return __intrin_bitcast<_To>(_mm512_cvtepi64_epi8(__intrin));
      }
    else if constexpr (__i32_to_i64) //{{{2
      {
    if constexpr (__have_sse4_1 && __x_to_x)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm_cvtepi32_epi64(__intrin)
                     : _mm_cvtepu32_epi64(__intrin));
    else if constexpr (__x_to_x)
      {
        return __intrin_bitcast<_To>(
          _mm_unpacklo_epi32(__intrin, is_signed_v<_Tp>
                         ? _mm_srai_epi32(__intrin, 31)
                         : __m128i()));
      }
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm256_cvtepi32_epi64(__intrin)
                     : _mm256_cvtepu32_epi64(__intrin));
    else if constexpr (__y_to_z)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm512_cvtepi32_epi64(__intrin)
                     : _mm512_cvtepu32_epi64(__intrin));
      }
    else if constexpr (__i32_to_i16) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm_cvtepi32_epi16(__intrin));
    else if constexpr (__x_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepi32_epi16(__auto_bitcast(__v))));
    else if constexpr (__x_to_x && __have_ssse3)
      return __intrin_bitcast<_To>(_mm_shuffle_epi8(
        __intrin, _mm_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, -0x80, -0x80,
                    -0x80, -0x80, -0x80, -0x80, -0x80, -0x80)));
    else if constexpr (__x_to_x)
      {
        auto __a = _mm_unpacklo_epi16(__intrin, __m128i()); // 0o.o 1o.o
        auto __b = _mm_unpackhi_epi16(__intrin, __m128i()); // 2o.o 3o.o
        auto __c = _mm_unpacklo_epi16(__a, __b);            // 02oo ..oo
        auto __d = _mm_unpackhi_epi16(__a, __b);            // 13oo ..oo
        return __intrin_bitcast<_To>(
          _mm_unpacklo_epi16(__c, __d)); // 0123 oooo
      }
    else if constexpr (__y_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm256_cvtepi32_epi16(__intrin));
    else if constexpr (__y_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepi32_epi16(__auto_bitcast(__v))));
    else if constexpr (__y_to_x)
      {
        auto __a = _mm256_shuffle_epi8(
          __intrin,
          _mm256_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80, -0x80, -0x80, 0, 1, 4, 5, 8,
                   9, 12, 13, -0x80, -0x80, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80));
        return __intrin_bitcast<_To>(__lo128(
          _mm256_permute4x64_epi64(__a,
                       0xf8))); // __a[0] __a[2] | __a[3] __a[3]
      }
    else if constexpr (__z_to_y)
      return __intrin_bitcast<_To>(_mm512_cvtepi32_epi16(__intrin));
      }
    else if constexpr (__i32_to_i8) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm_cvtepi32_epi8(__intrin));
    else if constexpr (__x_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepi32_epi8(__zero_extend(__intrin))));
    else if constexpr (__x_to_x && __have_ssse3)
      {
        return __intrin_bitcast<_To>(
          _mm_shuffle_epi8(__intrin,
                   _mm_setr_epi8(0, 4, 8, 12, -0x80, -0x80, -0x80,
                         -0x80, -0x80, -0x80, -0x80, -0x80,
                         -0x80, -0x80, -0x80, -0x80)));
      }
    else if constexpr (__x_to_x)
      {
        const auto __a
          = _mm_unpacklo_epi8(__intrin, __intrin); // 0... .... 1... ....
        const auto __b
          = _mm_unpackhi_epi8(__intrin, __intrin);    // 2... .... 3... ....
        const auto __c = _mm_unpacklo_epi8(__a, __b); // 02.. .... .... ....
        const auto __d = _mm_unpackhi_epi8(__a, __b); // 13.. .... .... ....
        const auto __e = _mm_unpacklo_epi8(__c, __d); // 0123 .... .... ....
        return __intrin_bitcast<_To>(__e & _mm_cvtsi32_si128(-1));
      }
    else if constexpr (__y_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm256_cvtepi32_epi8(__intrin));
    else if constexpr (__y_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        _mm512_cvtepi32_epi8(__zero_extend(__intrin)));
    else if constexpr (__z_to_x)
      return __intrin_bitcast<_To>(_mm512_cvtepi32_epi8(__intrin));
      }
    else if constexpr (__i16_to_i64) //{{{2
      {
    if constexpr (__x_to_x && __have_sse4_1)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm_cvtepi16_epi64(__intrin)
                     : _mm_cvtepu16_epi64(__intrin));
    else if constexpr (__x_to_x && is_signed_v<_Tp>)
      {
        auto __x = _mm_srai_epi16(__intrin, 15);
        auto __y = _mm_unpacklo_epi16(__intrin, __x);
        __x = _mm_unpacklo_epi16(__x, __x);
        return __intrin_bitcast<_To>(_mm_unpacklo_epi32(__y, __x));
      }
    else if constexpr (__x_to_x)
      return __intrin_bitcast<_To>(
        _mm_unpacklo_epi32(_mm_unpacklo_epi16(__intrin, __m128i()),
                   __m128i()));
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm256_cvtepi16_epi64(__intrin)
                     : _mm256_cvtepu16_epi64(__intrin));
    else if constexpr (__x_to_z)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm512_cvtepi16_epi64(__intrin)
                     : _mm512_cvtepu16_epi64(__intrin));
      }
    else if constexpr (__i16_to_i32) //{{{2
      {
    if constexpr (__x_to_x && __have_sse4_1)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm_cvtepi16_epi32(__intrin)
                     : _mm_cvtepu16_epi32(__intrin));
    else if constexpr (__x_to_x && is_signed_v<_Tp>)
      return __intrin_bitcast<_To>(
        _mm_srai_epi32(_mm_unpacklo_epi16(__intrin, __intrin), 16));
    else if constexpr (__x_to_x && is_unsigned_v<_Tp>)
      return __intrin_bitcast<_To>(_mm_unpacklo_epi16(__intrin, __m128i()));
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm256_cvtepi16_epi32(__intrin)
                     : _mm256_cvtepu16_epi32(__intrin));
    else if constexpr (__y_to_z)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm512_cvtepi16_epi32(__intrin)
                     : _mm512_cvtepu16_epi32(__intrin));
      }
    else if constexpr (__i16_to_i8) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512bw_vl)
      return __intrin_bitcast<_To>(_mm_cvtepi16_epi8(__intrin));
    else if constexpr (__x_to_x && __have_avx512bw)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepi16_epi8(__zero_extend(__intrin))));
    else if constexpr (__x_to_x && __have_ssse3)
      return __intrin_bitcast<_To>(_mm_shuffle_epi8(
        __intrin, _mm_setr_epi8(0, 2, 4, 6, 8, 10, 12, 14, -0x80, -0x80,
                    -0x80, -0x80, -0x80, -0x80, -0x80, -0x80)));
    else if constexpr (__x_to_x)
      {
        auto __a
          = _mm_unpacklo_epi8(__intrin, __intrin); // 00.. 11.. 22.. 33..
        auto __b
          = _mm_unpackhi_epi8(__intrin, __intrin); // 44.. 55.. 66.. 77..
        auto __c = _mm_unpacklo_epi8(__a, __b);    // 0404 .... 1515 ....
        auto __d = _mm_unpackhi_epi8(__a, __b);    // 2626 .... 3737 ....
        auto __e = _mm_unpacklo_epi8(__c, __d);    // 0246 0246 .... ....
        auto __f = _mm_unpackhi_epi8(__c, __d);    // 1357 1357 .... ....
        return __intrin_bitcast<_To>(_mm_unpacklo_epi8(__e, __f));
      }
    else if constexpr (__y_to_x && __have_avx512bw_vl)
      return __intrin_bitcast<_To>(_mm256_cvtepi16_epi8(__intrin));
    else if constexpr (__y_to_x && __have_avx512bw)
      return __intrin_bitcast<_To>(
        __lo256(_mm512_cvtepi16_epi8(__zero_extend(__intrin))));
    else if constexpr (__y_to_x)
      {
        auto __a = _mm256_shuffle_epi8(
          __intrin,
          _mm256_setr_epi8(0, 2, 4, 6, 8, 10, 12, 14, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, 0, 2,
                   4, 6, 8, 10, 12, 14));
        return __intrin_bitcast<_To>(__lo128(__a) | __hi128(__a));
      }
    else if constexpr (__z_to_y && __have_avx512bw)
      return __intrin_bitcast<_To>(_mm512_cvtepi16_epi8(__intrin));
    else if constexpr (__z_to_y)
      __assert_unreachable<_Tp>();
      }
    else if constexpr (__i8_to_i64) //{{{2
      {
    if constexpr (__x_to_x && __have_sse4_1)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm_cvtepi8_epi64(__intrin)
                     : _mm_cvtepu8_epi64(__intrin));
    else if constexpr (__x_to_x && is_signed_v<_Tp>)
      {
        if constexpr (__have_ssse3)
          {
        auto __dup = _mm_unpacklo_epi8(__intrin, __intrin);
        auto __epi16 = _mm_srai_epi16(__dup, 8);
        _mm_shuffle_epi8(__epi16,
                 _mm_setr_epi8(0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3,
                           3, 3, 3, 3, 3));
          }
        else
          {
        auto __x = _mm_unpacklo_epi8(__intrin, __intrin);
        __x = _mm_unpacklo_epi16(__x, __x);
        return __intrin_bitcast<_To>(
          _mm_unpacklo_epi32(_mm_srai_epi32(__x, 24),
                     _mm_srai_epi32(__x, 31)));
          }
      }
    else if constexpr (__x_to_x)
      {
        return __intrin_bitcast<_To>(_mm_unpacklo_epi32(
          _mm_unpacklo_epi16(_mm_unpacklo_epi8(__intrin, __m128i()),
                 __m128i()),
          __m128i()));
      }
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm256_cvtepi8_epi64(__intrin)
                     : _mm256_cvtepu8_epi64(__intrin));
    else if constexpr (__x_to_z)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm512_cvtepi8_epi64(__intrin)
                     : _mm512_cvtepu8_epi64(__intrin));
      }
    else if constexpr (__i8_to_i32) //{{{2
      {
    if constexpr (__x_to_x && __have_sse4_1)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm_cvtepi8_epi32(__intrin)
                     : _mm_cvtepu8_epi32(__intrin));
    else if constexpr (__x_to_x && is_signed_v<_Tp>)
      {
        const auto __x = _mm_unpacklo_epi8(__intrin, __intrin);
        return __intrin_bitcast<_To>(
          _mm_srai_epi32(_mm_unpacklo_epi16(__x, __x), 24));
      }
    else if constexpr (__x_to_x && is_unsigned_v<_Tp>)
      return __intrin_bitcast<_To>(
        _mm_unpacklo_epi16(_mm_unpacklo_epi8(__intrin, __m128i()),
                   __m128i()));
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm256_cvtepi8_epi32(__intrin)
                     : _mm256_cvtepu8_epi32(__intrin));
    else if constexpr (__x_to_z)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm512_cvtepi8_epi32(__intrin)
                     : _mm512_cvtepu8_epi32(__intrin));
      }
    else if constexpr (__i8_to_i16) //{{{2
      {
    if constexpr (__x_to_x && __have_sse4_1)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm_cvtepi8_epi16(__intrin)
                     : _mm_cvtepu8_epi16(__intrin));
    else if constexpr (__x_to_x && is_signed_v<_Tp>)
      return __intrin_bitcast<_To>(
        _mm_srai_epi16(_mm_unpacklo_epi8(__intrin, __intrin), 8));
    else if constexpr (__x_to_x && is_unsigned_v<_Tp>)
      return __intrin_bitcast<_To>(_mm_unpacklo_epi8(__intrin, __m128i()));
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm256_cvtepi8_epi16(__intrin)
                     : _mm256_cvtepu8_epi16(__intrin));
    else if constexpr (__y_to_z && __have_avx512bw)
      return __intrin_bitcast<_To>(is_signed_v<_Tp>
                     ? _mm512_cvtepi8_epi16(__intrin)
                     : _mm512_cvtepu8_epi16(__intrin));
    else if constexpr (__y_to_z)
      __assert_unreachable<_Tp>();
      }
    else if constexpr (__f32_to_s64) //{{{2
      {
    if constexpr (__have_avx512dq_vl && __x_to_x)
      return __intrin_bitcast<_To>(_mm_cvttps_epi64(__intrin));
    else if constexpr (__have_avx512dq_vl && __x_to_y)
      return __intrin_bitcast<_To>(_mm256_cvttps_epi64(__intrin));
    else if constexpr (__have_avx512dq && __y_to_z)
      return __intrin_bitcast<_To>(_mm512_cvttps_epi64(__intrin));
    // else use scalar fallback
      }
    else if constexpr (__f32_to_u64) //{{{2
      {
    if constexpr (__have_avx512dq_vl && __x_to_x)
      return __intrin_bitcast<_To>(_mm_cvttps_epu64(__intrin));
    else if constexpr (__have_avx512dq_vl && __x_to_y)
      return __intrin_bitcast<_To>(_mm256_cvttps_epu64(__intrin));
    else if constexpr (__have_avx512dq && __y_to_z)
      return __intrin_bitcast<_To>(_mm512_cvttps_epu64(__intrin));
    // else use scalar fallback
      }
    else if constexpr (__f32_to_s32) //{{{2
      {
    if constexpr (__x_to_x || __y_to_y || __z_to_z)
      {
        // go to fallback, it does the right thing
      }
    else
      __assert_unreachable<_Tp>();
      }
    else if constexpr (__f32_to_u32) //{{{2
      {
    if constexpr (__have_avx512vl && __x_to_x)
      return __auto_bitcast(_mm_cvttps_epu32(__intrin));
    else if constexpr (__have_avx512f && __x_to_x)
      return __auto_bitcast(
        __lo128(_mm512_cvttps_epu32(__auto_bitcast(__v))));
    else if constexpr (__have_avx512vl && __y_to_y)
      return __vector_bitcast<_Up>(_mm256_cvttps_epu32(__intrin));
    else if constexpr (__have_avx512f && __y_to_y)
      return __vector_bitcast<_Up>(
        __lo256(_mm512_cvttps_epu32(__auto_bitcast(__v))));
    else if constexpr (__x_to_x || __y_to_y || __z_to_z)
      {
        // go to fallback, it does the right thing. We can't use the
        // _mm_floor_ps - 0x8000'0000 trick for f32->u32 because it would
        // discard small input values (only 24 mantissa bits)
      }
    else
      __assert_unreachable<_Tp>();
      }
    else if constexpr (__f32_to_ibw) //{{{2
      return __convert_x86<_To>(__convert_x86<__vector_type_t<int, _Np>>(__v));
    else if constexpr (__f64_to_s64) //{{{2
      {
    if constexpr (__have_avx512dq_vl && __x_to_x)
      return __intrin_bitcast<_To>(_mm_cvttpd_epi64(__intrin));
    else if constexpr (__have_avx512dq_vl && __y_to_y)
      return __intrin_bitcast<_To>(_mm256_cvttpd_epi64(__intrin));
    else if constexpr (__have_avx512dq && __z_to_z)
      return __intrin_bitcast<_To>(_mm512_cvttpd_epi64(__intrin));
    // else use scalar fallback
      }
    else if constexpr (__f64_to_u64) //{{{2
      {
    if constexpr (__have_avx512dq_vl && __x_to_x)
      return __intrin_bitcast<_To>(_mm_cvttpd_epu64(__intrin));
    else if constexpr (__have_avx512dq_vl && __y_to_y)
      return __intrin_bitcast<_To>(_mm256_cvttpd_epu64(__intrin));
    else if constexpr (__have_avx512dq && __z_to_z)
      return __intrin_bitcast<_To>(_mm512_cvttpd_epu64(__intrin));
    // else use scalar fallback
      }
    else if constexpr (__f64_to_s32) //{{{2
      {
    if constexpr (__x_to_x)
      return __intrin_bitcast<_To>(_mm_cvttpd_epi32(__intrin));
    else if constexpr (__y_to_x)
      return __intrin_bitcast<_To>(_mm256_cvttpd_epi32(__intrin));
    else if constexpr (__z_to_y)
      return __intrin_bitcast<_To>(_mm512_cvttpd_epi32(__intrin));
      }
    else if constexpr (__f64_to_u32) //{{{2
      {
    if constexpr (__have_avx512vl && __x_to_x)
      return __intrin_bitcast<_To>(_mm_cvttpd_epu32(__intrin));
    else if constexpr (__have_sse4_1 && __x_to_x)
      return __vector_bitcast<_Up, _M>(
           _mm_cvttpd_epi32(_mm_floor_pd(__intrin) - 0x8000'0000u))
         ^ 0x8000'0000u;
    else if constexpr (__x_to_x)
      {
        // use scalar fallback: it's only 2 values to convert, can't get
        // much better than scalar decomposition
      }
    else if constexpr (__have_avx512vl && __y_to_x)
      return __intrin_bitcast<_To>(_mm256_cvttpd_epu32(__intrin));
    else if constexpr (__y_to_x)
      {
        return __intrin_bitcast<_To>(
          __vector_bitcast<_Up>(
        _mm256_cvttpd_epi32(_mm256_floor_pd(__intrin) - 0x8000'0000u))
          ^ 0x8000'0000u);
      }
    else if constexpr (__z_to_y)
      return __intrin_bitcast<_To>(_mm512_cvttpd_epu32(__intrin));
      }
    else if constexpr (__f64_to_ibw) //{{{2
      {
    return __convert_x86<_To>(
      __convert_x86<__vector_type_t<int, (_Np < 4 ? 4 : _Np)>>(__v));
      }
    else if constexpr (__s64_to_f32) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512dq_vl)
      return __intrin_bitcast<_To>(_mm_cvtepi64_ps(__intrin));
    else if constexpr (__y_to_x && __have_avx512dq_vl)
      return __intrin_bitcast<_To>(_mm256_cvtepi64_ps(__intrin));
    else if constexpr (__z_to_y && __have_avx512dq)
      return __intrin_bitcast<_To>(_mm512_cvtepi64_ps(__intrin));
    else if constexpr (__z_to_y)
      return __intrin_bitcast<_To>(
        _mm512_cvtpd_ps(__convert_x86<__vector_type_t<double, 8>>(__v)));
      }
    else if constexpr (__u64_to_f32) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512dq_vl)
      return __intrin_bitcast<_To>(_mm_cvtepu64_ps(__intrin));
    else if constexpr (__y_to_x && __have_avx512dq_vl)
      return __intrin_bitcast<_To>(_mm256_cvtepu64_ps(__intrin));
    else if constexpr (__z_to_y && __have_avx512dq)
      return __intrin_bitcast<_To>(_mm512_cvtepu64_ps(__intrin));
    else if constexpr (__z_to_y)
      {
        return __intrin_bitcast<_To>(
          __lo256(_mm512_cvtepu32_ps(__auto_bitcast(
        _mm512_cvtepi64_epi32(_mm512_srai_epi64(__intrin, 32)))))
        * 0x100000000LL
          + __lo256(_mm512_cvtepu32_ps(
        __auto_bitcast(_mm512_cvtepi64_epi32(__intrin)))));
      }
      }
    else if constexpr (__s32_to_f32) //{{{2
      {
    // use fallback (builtin conversion)
      }
    else if constexpr (__u32_to_f32) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512vl)
      {
        // use fallback
      }
    else if constexpr (__x_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepu32_ps(__auto_bitcast(__v))));
    else if constexpr (__x_to_x && (__have_fma || __have_fma4))
      // work around PR85819
      return __auto_bitcast(0x10000
                  * _mm_cvtepi32_ps(__to_intrin(__v >> 16))
                + _mm_cvtepi32_ps(__to_intrin(__v & 0xffff)));
    else if constexpr (__y_to_y && __have_avx512vl)
      {
        // use fallback
      }
    else if constexpr (__y_to_y && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo256(_mm512_cvtepu32_ps(__auto_bitcast(__v))));
    else if constexpr (__y_to_y)
      // work around PR85819
      return 0x10000 * _mm256_cvtepi32_ps(__to_intrin(__v >> 16))
         + _mm256_cvtepi32_ps(__to_intrin(__v & 0xffff));
    // else use fallback (builtin conversion)
      }
    else if constexpr (__ibw_to_f32) //{{{2
      {
    if constexpr (_M <= 4 || __have_avx2)
      return __convert_x86<_To>(
        __convert_x86<__vector_type_t<int, _M>>(__v));
    else
      {
        static_assert(__x_to_y);
        __m128i __a, __b;
        if constexpr (__have_sse4_1)
          {
        __a = sizeof(_Tp) == 2
            ? (is_signed_v<_Tp> ? _mm_cvtepi16_epi32(__intrin)
                        : _mm_cvtepu16_epi32(__intrin))
            : (is_signed_v<_Tp> ? _mm_cvtepi8_epi32(__intrin)
                        : _mm_cvtepu8_epi32(__intrin));
        const auto __w
          = _mm_shuffle_epi32(__intrin, sizeof(_Tp) == 2 ? 0xee : 0xe9);
        __b = sizeof(_Tp) == 2
            ? (is_signed_v<_Tp> ? _mm_cvtepi16_epi32(__w)
                        : _mm_cvtepu16_epi32(__w))
            : (is_signed_v<_Tp> ? _mm_cvtepi8_epi32(__w)
                        : _mm_cvtepu8_epi32(__w));
          }
        else
          {
        __m128i __tmp;
        if constexpr (sizeof(_Tp) == 1)
          {
            __tmp = is_signed_v<_Tp>
                  ? _mm_srai_epi16(_mm_unpacklo_epi8(__intrin,
                                 __intrin),
                           8)
                  : _mm_unpacklo_epi8(__intrin, __m128i());
          }
        else
          {
            static_assert(sizeof(_Tp) == 2);
            __tmp = __intrin;
          }
        __a = is_signed_v<_Tp>
            ? _mm_srai_epi32(_mm_unpacklo_epi16(__tmp, __tmp), 16)
            : _mm_unpacklo_epi16(__tmp, __m128i());
        __b = is_signed_v<_Tp>
            ? _mm_srai_epi32(_mm_unpackhi_epi16(__tmp, __tmp), 16)
            : _mm_unpackhi_epi16(__tmp, __m128i());
          }
        return __convert_x86<_To>(__vector_bitcast<int>(__a),
                      __vector_bitcast<int>(__b));
      }
      }
    else if constexpr (__s64_to_f64) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512dq_vl)
      return __intrin_bitcast<_To>(_mm_cvtepi64_pd(__intrin));
    else if constexpr (__y_to_y && __have_avx512dq_vl)
      return __intrin_bitcast<_To>(_mm256_cvtepi64_pd(__intrin));
    else if constexpr (__z_to_z && __have_avx512dq)
      return __intrin_bitcast<_To>(_mm512_cvtepi64_pd(__intrin));
    else if constexpr (__z_to_z)
      {
        return __intrin_bitcast<_To>(
          _mm512_cvtepi32_pd(_mm512_cvtepi64_epi32(__to_intrin(__v >> 32)))
        * 0x100000000LL
          + _mm512_cvtepu32_pd(_mm512_cvtepi64_epi32(__intrin)));
      }
      }
    else if constexpr (__u64_to_f64) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512dq_vl)
      return __intrin_bitcast<_To>(_mm_cvtepu64_pd(__intrin));
    else if constexpr (__y_to_y && __have_avx512dq_vl)
      return __intrin_bitcast<_To>(_mm256_cvtepu64_pd(__intrin));
    else if constexpr (__z_to_z && __have_avx512dq)
      return __intrin_bitcast<_To>(_mm512_cvtepu64_pd(__intrin));
    else if constexpr (__z_to_z)
      {
        return __intrin_bitcast<_To>(
          _mm512_cvtepu32_pd(_mm512_cvtepi64_epi32(__to_intrin(__v >> 32)))
        * 0x100000000LL
          + _mm512_cvtepu32_pd(_mm512_cvtepi64_epi32(__intrin)));
      }
      }
    else if constexpr (__s32_to_f64) //{{{2
      {
    if constexpr (__x_to_x)
      return __intrin_bitcast<_To>(_mm_cvtepi32_pd(__intrin));
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(_mm256_cvtepi32_pd(__intrin));
    else if constexpr (__y_to_z)
      return __intrin_bitcast<_To>(_mm512_cvtepi32_pd(__intrin));
      }
    else if constexpr (__u32_to_f64) //{{{2
      {
    if constexpr (__x_to_x && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm_cvtepu32_pd(__intrin));
    else if constexpr (__x_to_x && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo128(_mm512_cvtepu32_pd(__auto_bitcast(__v))));
    else if constexpr (__x_to_x)
      return __intrin_bitcast<_To>(
        _mm_cvtepi32_pd(__to_intrin(__v ^ 0x8000'0000u)) + 0x8000'0000u);
    else if constexpr (__x_to_y && __have_avx512vl)
      return __intrin_bitcast<_To>(_mm256_cvtepu32_pd(__intrin));
    else if constexpr (__x_to_y && __have_avx512f)
      return __intrin_bitcast<_To>(
        __lo256(_mm512_cvtepu32_pd(__auto_bitcast(__v))));
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(
        _mm256_cvtepi32_pd(__to_intrin(__v ^ 0x8000'0000u)) + 0x8000'0000u);
    else if constexpr (__y_to_z)
      return __intrin_bitcast<_To>(_mm512_cvtepu32_pd(__intrin));
      }
    else if constexpr (__ibw_to_f64) //{{{2
      {
    return __convert_x86<_To>(
      __convert_x86<__vector_type_t<int, std::max(size_t(4), _M)>>(__v));
      }
    else if constexpr (__f32_to_f64) //{{{2
      {
    if constexpr (__x_to_x)
      return __intrin_bitcast<_To>(_mm_cvtps_pd(__intrin));
    else if constexpr (__x_to_y)
      return __intrin_bitcast<_To>(_mm256_cvtps_pd(__intrin));
    else if constexpr (__y_to_z)
      return __intrin_bitcast<_To>(_mm512_cvtps_pd(__intrin));
      }
    else if constexpr (__f64_to_f32) //{{{2
      {
    if constexpr (__x_to_x)
      return __intrin_bitcast<_To>(_mm_cvtpd_ps(__intrin));
    else if constexpr (__y_to_x)
      return __intrin_bitcast<_To>(_mm256_cvtpd_ps(__intrin));
    else if constexpr (__z_to_y)
      return __intrin_bitcast<_To>(_mm512_cvtpd_ps(__intrin));
      }
    else //{{{2
      __assert_unreachable<_Tp>();

    // fallback:{{{2
    return __vector_convert<_To>(__v, make_index_sequence<std::min(_M, _Np)>());
    //}}}
  }

// }}}
// 2-arg __convert_x86 {{{1
template <typename _To, typename _V, typename _Traits>
  _GLIBCXX_SIMD_INTRINSIC _To
  __convert_x86(_V __v0, _V __v1)
  {
    static_assert(__is_vector_type_v<_V>);
    using _Tp = typename _Traits::value_type;
    constexpr size_t _Np = _Traits::_S_full_size;
    [[maybe_unused]] const auto __i0 = __to_intrin(__v0);
    [[maybe_unused]] const auto __i1 = __to_intrin(__v1);
    using _Up = typename _VectorTraits<_To>::value_type;
    constexpr size_t _M = _VectorTraits<_To>::_S_full_size;

    static_assert(2 * _Np <= _M,
          "__v1 would be discarded; use the one-argument "
          "__convert_x86 overload instead");

    // [xyz]_to_[xyz] {{{2
    [[maybe_unused]] constexpr bool __x_to_x
      = sizeof(__v0) <= 16 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __x_to_y
      = sizeof(__v0) <= 16 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __x_to_z
      = sizeof(__v0) <= 16 && sizeof(_To) == 64;
    [[maybe_unused]] constexpr bool __y_to_x
      = sizeof(__v0) == 32 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __y_to_y
      = sizeof(__v0) == 32 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __y_to_z
      = sizeof(__v0) == 32 && sizeof(_To) == 64;
    [[maybe_unused]] constexpr bool __z_to_x
      = sizeof(__v0) == 64 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __z_to_y
      = sizeof(__v0) == 64 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __z_to_z
      = sizeof(__v0) == 64 && sizeof(_To) == 64;

    // iX_to_iX {{{2
    [[maybe_unused]] constexpr bool __i_to_i
      = is_integral_v<_Up> && is_integral_v<_Tp>;
    [[maybe_unused]] constexpr bool __i8_to_i16
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i8_to_i32
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __i8_to_i64
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i16_to_i8
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i16_to_i32
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __i16_to_i64
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i32_to_i8
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i32_to_i16
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i32_to_i64
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i64_to_i8
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i64_to_i16
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i64_to_i32
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 4;

    // [fsu]X_to_[fsu]X {{{2
    // ibw = integral && byte or word, i.e. char and short with any signedness
    [[maybe_unused]] constexpr bool __i64_to_f32
      = is_integral_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s32_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s16_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s8_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u32_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u16_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u8_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s64_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __s32_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __s16_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __s8_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u64_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u32_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u16_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u8_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __f32_to_s64
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_s32
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_u64
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_u32
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f64_to_s64
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_s32
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_u64
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_u32
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f32_to_ibw
      = is_integral_v<_Up> && sizeof(_Up) <= 2
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f64_to_ibw
      = is_integral_v<_Up> && sizeof(_Up) <= 2
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f32_to_f64
      = is_floating_point_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __f64_to_f32
      = is_floating_point_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;

    if constexpr (__i_to_i && __y_to_x && !__have_avx2) //{{{2
      // <double, 4>, <double, 4> => <short, 8>
      return __convert_x86<_To>(__lo128(__v0), __hi128(__v0), __lo128(__v1),
                __hi128(__v1));
    else if constexpr (__i_to_i) // assert ISA {{{2
      {
    static_assert(__x_to_x || __have_avx2,
              "integral conversions with ymm registers require AVX2");
    static_assert(__have_avx512bw
            || ((sizeof(_Tp) >= 4 || sizeof(__v0) < 64)
                && (sizeof(_Up) >= 4 || sizeof(_To) < 64)),
              "8/16-bit integers in zmm registers require AVX512BW");
    static_assert((sizeof(__v0) < 64 && sizeof(_To) < 64) || __have_avx512f,
              "integral conversions with ymm registers require AVX2");
      }
    // concat => use 1-arg __convert_x86 {{{2
    if constexpr (sizeof(__v0) < 16 || (sizeof(__v0) == 16 && __have_avx2)
          || (sizeof(__v0) == 16 && __have_avx
              && is_floating_point_v<_Tp>)
          || (sizeof(__v0) == 32 && __have_avx512f
              && (sizeof(_Tp) >= 4 || __have_avx512bw)))
      {
    // The ISA can handle wider input registers, so concat and use one-arg
    // implementation. This reduces code duplication considerably.
    return __convert_x86<_To>(__concat(__v0, __v1));
      }
    else //{{{2
      {
    // conversion using bit reinterpretation (or no conversion at all)
    // should all go through the concat branch above:
    static_assert(
      !(is_floating_point_v<
          _Tp> == is_floating_point_v<_Up> && sizeof(_Tp) == sizeof(_Up)));
    // handle all zero extension{{{2
    if constexpr (2 * _Np < _M && sizeof(_To) > 16)
      {
        constexpr size_t Min = 16 / sizeof(_Up);
        return __zero_extend(
          __convert_x86<
        __vector_type_t<_Up, (Min > 2 * _Np) ? Min : 2 * _Np>>(__v0,
                                       __v1));
      }
    else if constexpr (__i64_to_i32) //{{{2
      {
        if constexpr (__x_to_x)
          return __auto_bitcast(_mm_shuffle_ps(__auto_bitcast(__v0),
                           __auto_bitcast(__v1), 0x88));
        else if constexpr (__y_to_y)
          {
        // AVX512F is not available (would concat otherwise)
        return __auto_bitcast(
          __xzyw(_mm256_shuffle_ps(__auto_bitcast(__v0),
                       __auto_bitcast(__v1), 0x88)));
        // alternative:
        // const auto v0_abxxcdxx = _mm256_shuffle_epi32(__v0, 8);
        // const auto v1_efxxghxx = _mm256_shuffle_epi32(__v1, 8);
        // const auto v_abefcdgh = _mm256_unpacklo_epi64(v0_abxxcdxx,
        // v1_efxxghxx); return _mm256_permute4x64_epi64(v_abefcdgh,
        // 0x01 * 0 + 0x04 * 2 + 0x10 * 1 + 0x40 * 3);  // abcdefgh
          }
        else if constexpr (__z_to_z)
          return __intrin_bitcast<_To>(
        __concat(_mm512_cvtepi64_epi32(__i0),
             _mm512_cvtepi64_epi32(__i1)));
      }
    else if constexpr (__i64_to_i16) //{{{2
      {
        if constexpr (__x_to_x)
          {
        // AVX2 is not available (would concat otherwise)
        if constexpr (__have_sse4_1)
          {
            return __intrin_bitcast<_To>(_mm_shuffle_epi8(
              _mm_blend_epi16(__i0, _mm_slli_si128(__i1, 4), 0x44),
              _mm_setr_epi8(0, 1, 8, 9, 4, 5, 12, 13, -0x80, -0x80,
                    -0x80, -0x80, -0x80, -0x80, -0x80, -0x80)));
          }
        else
          {
            return __vector_type_t<_Up, _M>{_Up(__v0[0]), _Up(__v0[1]),
                            _Up(__v1[0]), _Up(__v1[1])};
          }
          }
        else if constexpr (__y_to_x)
          {
        auto __a
          = _mm256_unpacklo_epi16(__i0, __i1); // 04.. .... 26.. ....
        auto __b
          = _mm256_unpackhi_epi16(__i0, __i1); // 15.. .... 37.. ....
        auto __c
          = _mm256_unpacklo_epi16(__a, __b); // 0145 .... 2367 ....
        return __intrin_bitcast<_To>(
          _mm_unpacklo_epi32(__lo128(__c), __hi128(__c))); // 0123 4567
          }
        else if constexpr (__z_to_y)
          return __intrin_bitcast<_To>(
        __concat(_mm512_cvtepi64_epi16(__i0),
             _mm512_cvtepi64_epi16(__i1)));
      }
    else if constexpr (__i64_to_i8) //{{{2
      {
        if constexpr (__x_to_x && __have_sse4_1)
          {
        return __intrin_bitcast<_To>(_mm_shuffle_epi8(
          _mm_blend_epi16(__i0, _mm_slli_si128(__i1, 4), 0x44),
          _mm_setr_epi8(0, 8, 4, 12, -0x80, -0x80, -0x80, -0x80, -0x80,
                -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
                -0x80)));
          }
        else if constexpr (__x_to_x && __have_ssse3)
          {
        return __intrin_bitcast<_To>(_mm_unpacklo_epi16(
          _mm_shuffle_epi8(
            __i0, _mm_setr_epi8(0, 8, -0x80, -0x80, -0x80, -0x80, -0x80,
                    -0x80, -0x80, -0x80, -0x80, -0x80,
                    -0x80, -0x80, -0x80, -0x80)),
          _mm_shuffle_epi8(
            __i1, _mm_setr_epi8(0, 8, -0x80, -0x80, -0x80, -0x80, -0x80,
                    -0x80, -0x80, -0x80, -0x80, -0x80,
                    -0x80, -0x80, -0x80, -0x80))));
          }
        else if constexpr (__x_to_x)
          {
        return __vector_type_t<_Up, _M>{_Up(__v0[0]), _Up(__v0[1]),
                        _Up(__v1[0]), _Up(__v1[1])};
          }
        else if constexpr (__y_to_x)
          {
        const auto __a = _mm256_shuffle_epi8(
          _mm256_blend_epi32(__i0, _mm256_slli_epi64(__i1, 32), 0xAA),
          _mm256_setr_epi8(0, 8, -0x80, -0x80, 4, 12, -0x80, -0x80,
                   -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80, -0x80, 0, 8, -0x80,
                   -0x80, 4, 12, -0x80, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80, -0x80));
        return __intrin_bitcast<_To>(__lo128(__a) | __hi128(__a));
          } // __z_to_x uses concat fallback
      }
    else if constexpr (__i32_to_i16) //{{{2
      {
        if constexpr (__x_to_x)
          {
        // AVX2 is not available (would concat otherwise)
        if constexpr (__have_sse4_1)
          {
            return __intrin_bitcast<_To>(_mm_shuffle_epi8(
              _mm_blend_epi16(__i0, _mm_slli_si128(__i1, 2), 0xaa),
              _mm_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10,
                    11, 14, 15)));
          }
        else if constexpr (__have_ssse3)
          {
            return __intrin_bitcast<_To>(
              _mm_hadd_epi16(__to_intrin(__v0 << 16),
                     __to_intrin(__v1 << 16)));
            /*
            return _mm_unpacklo_epi64(
            _mm_shuffle_epi8(__i0, _mm_setr_epi8(0, 1, 4, 5, 8, 9,
            12, 13, 8, 9, 12, 13, 12, 13, 14, 15)),
            _mm_shuffle_epi8(__i1, _mm_setr_epi8(0, 1, 4, 5, 8, 9, 12,
            13, 8, 9, 12, 13, 12, 13, 14, 15)));
                               */
          }
        else
          {
            auto __a = _mm_unpacklo_epi16(__i0, __i1); // 04.. 15..
            auto __b = _mm_unpackhi_epi16(__i0, __i1); // 26.. 37..
            auto __c = _mm_unpacklo_epi16(__a, __b);   // 0246 ....
            auto __d = _mm_unpackhi_epi16(__a, __b);   // 1357 ....
            return __intrin_bitcast<_To>(
              _mm_unpacklo_epi16(__c, __d)); // 0123 4567
          }
          }
        else if constexpr (__y_to_y)
          {
        const auto __shuf
          = _mm256_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, -0x80, -0x80,
                     -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
                     0, 1, 4, 5, 8, 9, 12, 13, -0x80, -0x80,
                     -0x80, -0x80, -0x80, -0x80, -0x80, -0x80);
        auto __a = _mm256_shuffle_epi8(__i0, __shuf);
        auto __b = _mm256_shuffle_epi8(__i1, __shuf);
        return __intrin_bitcast<_To>(
          __xzyw(_mm256_unpacklo_epi64(__a, __b)));
          } // __z_to_z uses concat fallback
      }
    else if constexpr (__i32_to_i8) //{{{2
      {
        if constexpr (__x_to_x && __have_ssse3)
          {
        const auto shufmask
          = _mm_setr_epi8(0, 4, 8, 12, -0x80, -0x80, -0x80, -0x80,
                  -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
                  -0x80, -0x80);
        return __intrin_bitcast<_To>(
          _mm_unpacklo_epi32(_mm_shuffle_epi8(__i0, shufmask),
                     _mm_shuffle_epi8(__i1, shufmask)));
          }
        else if constexpr (__x_to_x)
          {
        auto __a = _mm_unpacklo_epi8(__i0, __i1); // 04.. .... 15.. ....
        auto __b = _mm_unpackhi_epi8(__i0, __i1); // 26.. .... 37.. ....
        auto __c = _mm_unpacklo_epi8(__a, __b);   // 0246 .... .... ....
        auto __d = _mm_unpackhi_epi8(__a, __b);   // 1357 .... .... ....
        auto __e = _mm_unpacklo_epi8(__c, __d);   // 0123 4567 .... ....
        return __intrin_bitcast<_To>(__e & __m128i{-1, 0});
          }
        else if constexpr (__y_to_x)
          {
        const auto __a = _mm256_shuffle_epi8(
          _mm256_blend_epi16(__i0, _mm256_slli_epi32(__i1, 16), 0xAA),
          _mm256_setr_epi8(0, 4, 8, 12, -0x80, -0x80, -0x80, -0x80, 2,
                   6, 10, 14, -0x80, -0x80, -0x80, -0x80, -0x80,
                   -0x80, -0x80, -0x80, 0, 4, 8, 12, -0x80,
                   -0x80, -0x80, -0x80, 2, 6, 10, 14));
        return __intrin_bitcast<_To>(__lo128(__a) | __hi128(__a));
          } // __z_to_y uses concat fallback
      }
    else if constexpr (__i16_to_i8) //{{{2
      {
        if constexpr (__x_to_x && __have_ssse3)
          {
        const auto __shuf = reinterpret_cast<__m128i>(
          __vector_type_t<_UChar, 16>{0, 2, 4, 6, 8, 10, 12, 14, 0x80,
                          0x80, 0x80, 0x80, 0x80, 0x80,
                          0x80, 0x80});
        return __intrin_bitcast<_To>(
          _mm_unpacklo_epi64(_mm_shuffle_epi8(__i0, __shuf),
                     _mm_shuffle_epi8(__i1, __shuf)));
          }
        else if constexpr (__x_to_x)
          {
        auto __a = _mm_unpacklo_epi8(__i0, __i1); // 08.. 19.. 2A.. 3B..
        auto __b = _mm_unpackhi_epi8(__i0, __i1); // 4C.. 5D.. 6E.. 7F..
        auto __c = _mm_unpacklo_epi8(__a, __b);   // 048C .... 159D ....
        auto __d = _mm_unpackhi_epi8(__a, __b);   // 26AE .... 37BF ....
        auto __e = _mm_unpacklo_epi8(__c, __d);   // 0246 8ACE .... ....
        auto __f = _mm_unpackhi_epi8(__c, __d);   // 1357 9BDF .... ....
        return __intrin_bitcast<_To>(_mm_unpacklo_epi8(__e, __f));
          }
        else if constexpr (__y_to_y)
          {
        return __intrin_bitcast<_To>(__xzyw(_mm256_shuffle_epi8(
          (__to_intrin(__v0) & _mm256_set1_epi32(0x00ff00ff))
            | _mm256_slli_epi16(__i1, 8),
          _mm256_setr_epi8(0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11,
                   13, 15, 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5,
                   7, 9, 11, 13, 15))));
          } // __z_to_z uses concat fallback
      }
    else if constexpr (__i64_to_f32) //{{{2
      {
        if constexpr (__x_to_x)
          return __make_wrapper<float>(__v0[0], __v0[1], __v1[0], __v1[1]);
        else if constexpr (__y_to_y)
          {
        static_assert(__y_to_y && __have_avx2);
        const auto __a = _mm256_unpacklo_epi32(__i0, __i1); // aeAE cgCG
        const auto __b = _mm256_unpackhi_epi32(__i0, __i1); // bfBF dhDH
        const auto __lo32
          = _mm256_unpacklo_epi32(__a, __b); // abef cdgh
        const auto __hi32 = __vector_bitcast<
          conditional_t<is_signed_v<_Tp>, int, _UInt>>(
          _mm256_unpackhi_epi32(__a, __b)); // ABEF CDGH
        const auto __hi
          = 0x100000000LL
            * __convert_x86<__vector_type_t<float, 8>>(__hi32);
        const auto __mid
          = 0x10000 * _mm256_cvtepi32_ps(_mm256_srli_epi32(__lo32, 16));
        const auto __lo
          = _mm256_cvtepi32_ps(_mm256_set1_epi32(0x0000ffffu) & __lo32);
        return __xzyw((__hi + __mid) + __lo);
          }
        else if constexpr (__z_to_z && __have_avx512dq)
          {
        return is_signed_v<_Tp> ? __concat(_mm512_cvtepi64_ps(__i0),
                           _mm512_cvtepi64_ps(__i1))
                    : __concat(_mm512_cvtepu64_ps(__i0),
                           _mm512_cvtepu64_ps(__i1));
          }
        else if constexpr (__z_to_z && is_signed_v<_Tp>)
          {
        const __m512 __hi32 = _mm512_cvtepi32_ps(
          __concat(_mm512_cvtepi64_epi32(__to_intrin(__v0 >> 32)),
               _mm512_cvtepi64_epi32(__to_intrin(__v1 >> 32))));
        const __m512i __lo32 = __concat(_mm512_cvtepi64_epi32(__i0),
                        _mm512_cvtepi64_epi32(__i1));
        // split low 32-bits, because if __hi32 is a small negative
        // number, the 24-bit mantissa may lose important information if
        // any of the high 8 bits of __lo32 is set, leading to
        // catastrophic cancelation in the FMA
        const __m512 __hi16
          = _mm512_cvtepu32_ps(_mm512_set1_epi32(0xffff0000u) & __lo32);
        const __m512 __lo16
          = _mm512_cvtepi32_ps(_mm512_set1_epi32(0x0000ffffu) & __lo32);
        return (__hi32 * 0x100000000LL + __hi16) + __lo16;
          }
        else if constexpr (__z_to_z && is_unsigned_v<_Tp>)
          {
        return __intrin_bitcast<_To>(
          _mm512_cvtepu32_ps(__concat(
            _mm512_cvtepi64_epi32(_mm512_srai_epi64(__i0, 32)),
            _mm512_cvtepi64_epi32(_mm512_srai_epi64(__i1, 32))))
            * 0x100000000LL
          + _mm512_cvtepu32_ps(__concat(_mm512_cvtepi64_epi32(__i0),
                        _mm512_cvtepi64_epi32(__i1))));
          }
      }
    else if constexpr (__f64_to_s32) //{{{2
      {
        // use concat fallback
      }
    else if constexpr (__f64_to_u32) //{{{2
      {
        if constexpr (__x_to_x && __have_sse4_1)
          {
        return __vector_bitcast<_Up, _M>(_mm_unpacklo_epi64(
             _mm_cvttpd_epi32(_mm_floor_pd(__i0) - 0x8000'0000u),
             _mm_cvttpd_epi32(_mm_floor_pd(__i1) - 0x8000'0000u)))
               ^ 0x8000'0000u;
        // without SSE4.1 just use the scalar fallback, it's only four
        // values
          }
        else if constexpr (__y_to_y)
          {
        return __vector_bitcast<_Up>(
             __concat(_mm256_cvttpd_epi32(_mm256_floor_pd(__i0)
                              - 0x8000'0000u),
                  _mm256_cvttpd_epi32(_mm256_floor_pd(__i1)
                              - 0x8000'0000u)))
               ^ 0x8000'0000u;
          } // __z_to_z uses fallback
      }
    else if constexpr (__f64_to_ibw) //{{{2
      {
        // one-arg __f64_to_ibw goes via _SimdWrapper<int, ?>. The fallback
        // would go via two independet conversions to _SimdWrapper<_To> and
        // subsequent interleaving. This is better, because f64->__i32
        // allows to combine __v0 and __v1 into one register: if constexpr
        // (__z_to_x || __y_to_x) {
        return __convert_x86<_To>(
          __convert_x86<__vector_type_t<int, _Np * 2>>(__v0, __v1));
        //}
      }
    else if constexpr (__f32_to_ibw) //{{{2
      {
        return __convert_x86<_To>(
          __convert_x86<__vector_type_t<int, _Np>>(__v0),
          __convert_x86<__vector_type_t<int, _Np>>(__v1));
      } //}}}

    // fallback: {{{2
    if constexpr (sizeof(_To) >= 32)
      // if _To is ymm or zmm, then _SimdWrapper<_Up, _M / 2> is xmm or ymm
      return __concat(__convert_x86<__vector_type_t<_Up, _M / 2>>(__v0),
              __convert_x86<__vector_type_t<_Up, _M / 2>>(__v1));
    else if constexpr (sizeof(_To) == 16)
      {
        const auto __lo = __to_intrin(__convert_x86<_To>(__v0));
        const auto __hi = __to_intrin(__convert_x86<_To>(__v1));
        if constexpr (sizeof(_Up) * _Np == 8)
          {
        if constexpr (is_floating_point_v<_Up>)
          return __auto_bitcast(
            _mm_unpacklo_pd(__vector_bitcast<double>(__lo),
                    __vector_bitcast<double>(__hi)));
        else
          return __intrin_bitcast<_To>(_mm_unpacklo_epi64(__lo, __hi));
          }
        else if constexpr (sizeof(_Up) * _Np == 4)
          {
        if constexpr (is_floating_point_v<_Up>)
          return __auto_bitcast(
            _mm_unpacklo_ps(__vector_bitcast<float>(__lo),
                    __vector_bitcast<float>(__hi)));
        else
          return __intrin_bitcast<_To>(_mm_unpacklo_epi32(__lo, __hi));
          }
        else if constexpr (sizeof(_Up) * _Np == 2)
          return __intrin_bitcast<_To>(_mm_unpacklo_epi16(__lo, __hi));
        else
          __assert_unreachable<_Tp>();
      }
    else
      return __vector_convert<_To>(__v0, __v1, make_index_sequence<_Np>());
    //}}}
      }
  }

//}}}1
// 4-arg __convert_x86 {{{1
template <typename _To, typename _V, typename _Traits>
  _GLIBCXX_SIMD_INTRINSIC _To
  __convert_x86(_V __v0, _V __v1, _V __v2, _V __v3)
  {
    static_assert(__is_vector_type_v<_V>);
    using _Tp = typename _Traits::value_type;
    constexpr size_t _Np = _Traits::_S_full_size;
    [[maybe_unused]] const auto __i0 = __to_intrin(__v0);
    [[maybe_unused]] const auto __i1 = __to_intrin(__v1);
    [[maybe_unused]] const auto __i2 = __to_intrin(__v2);
    [[maybe_unused]] const auto __i3 = __to_intrin(__v3);
    using _Up = typename _VectorTraits<_To>::value_type;
    constexpr size_t _M = _VectorTraits<_To>::_S_full_size;

    static_assert(4 * _Np <= _M,
          "__v2/__v3 would be discarded; use the two/one-argument "
          "__convert_x86 overload instead");

    // [xyz]_to_[xyz] {{{2
    [[maybe_unused]] constexpr bool __x_to_x
      = sizeof(__v0) <= 16 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __x_to_y
      = sizeof(__v0) <= 16 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __x_to_z
      = sizeof(__v0) <= 16 && sizeof(_To) == 64;
    [[maybe_unused]] constexpr bool __y_to_x
      = sizeof(__v0) == 32 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __y_to_y
      = sizeof(__v0) == 32 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __y_to_z
      = sizeof(__v0) == 32 && sizeof(_To) == 64;
    [[maybe_unused]] constexpr bool __z_to_x
      = sizeof(__v0) == 64 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __z_to_y
      = sizeof(__v0) == 64 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __z_to_z
      = sizeof(__v0) == 64 && sizeof(_To) == 64;

    // iX_to_iX {{{2
    [[maybe_unused]] constexpr bool __i_to_i
      = is_integral_v<_Up> && is_integral_v<_Tp>;
    [[maybe_unused]] constexpr bool __i8_to_i16
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i8_to_i32
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __i8_to_i64
      = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i16_to_i8
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i16_to_i32
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __i16_to_i64
      = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i32_to_i8
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i32_to_i16
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i32_to_i64
      = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __i64_to_i8
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __i64_to_i16
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 2;
    [[maybe_unused]] constexpr bool __i64_to_i32
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 4;

    // [fsu]X_to_[fsu]X {{{2
    // ibw = integral && byte or word, i.e. char and short with any signedness
    [[maybe_unused]] constexpr bool __i64_to_f32
      = is_integral_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s32_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s16_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s8_to_f32
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u32_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u16_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __u8_to_f32
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;
    [[maybe_unused]] constexpr bool __s64_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __s32_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __s16_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __s8_to_f64
      = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u64_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u32_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u16_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __u8_to_f64
      = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __f32_to_s64
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_s32
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_u64
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f32_to_u32
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f64_to_s64
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_s32
      = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_u64
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f64_to_u32
      = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f32_to_ibw
      = is_integral_v<_Up> && sizeof(_Up) <= 2
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
    [[maybe_unused]] constexpr bool __f64_to_ibw
      = is_integral_v<_Up> && sizeof(_Up) <= 2
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
    [[maybe_unused]] constexpr bool __f32_to_f64
      = is_floating_point_v<_Tp> && sizeof(_Tp) == 4
    && is_floating_point_v<_Up> && sizeof(_Up) == 8;
    [[maybe_unused]] constexpr bool __f64_to_f32
      = is_floating_point_v<_Tp> && sizeof(_Tp) == 8
    && is_floating_point_v<_Up> && sizeof(_Up) == 4;

    if constexpr (__i_to_i && __y_to_x && !__have_avx2) //{{{2
      {
    // <double, 4>, <double, 4>, <double, 4>, <double, 4> => <char, 16>
    return __convert_x86<_To>(__lo128(__v0), __hi128(__v0), __lo128(__v1),
                  __hi128(__v1), __lo128(__v2), __hi128(__v2),
                  __lo128(__v3), __hi128(__v3));
      }
    else if constexpr (__i_to_i) // assert ISA {{{2
      {
    static_assert(__x_to_x || __have_avx2,
              "integral conversions with ymm registers require AVX2");
    static_assert(__have_avx512bw
            || ((sizeof(_Tp) >= 4 || sizeof(__v0) < 64)
                && (sizeof(_Up) >= 4 || sizeof(_To) < 64)),
              "8/16-bit integers in zmm registers require AVX512BW");
    static_assert((sizeof(__v0) < 64 && sizeof(_To) < 64) || __have_avx512f,
              "integral conversions with ymm registers require AVX2");
      }
    // concat => use 2-arg __convert_x86 {{{2
    if constexpr (sizeof(__v0) < 16 || (sizeof(__v0) == 16 && __have_avx2)
          || (sizeof(__v0) == 16 && __have_avx
              && is_floating_point_v<_Tp>)
          || (sizeof(__v0) == 32 && __have_avx512f))
      {
    // The ISA can handle wider input registers, so concat and use two-arg
    // implementation. This reduces code duplication considerably.
    return __convert_x86<_To>(__concat(__v0, __v1), __concat(__v2, __v3));
      }
    else //{{{2
      {
    // conversion using bit reinterpretation (or no conversion at all)
    // should all go through the concat branch above:
    static_assert(
      !(is_floating_point_v<
          _Tp> == is_floating_point_v<_Up> && sizeof(_Tp) == sizeof(_Up)));
    // handle all zero extension{{{2
    if constexpr (4 * _Np < _M && sizeof(_To) > 16)
      {
        constexpr size_t Min = 16 / sizeof(_Up);
        return __zero_extend(
          __convert_x86<
        __vector_type_t<_Up, (Min > 4 * _Np) ? Min : 4 * _Np>>(
        __v0, __v1, __v2, __v3));
      }
    else if constexpr (__i64_to_i16) //{{{2
      {
        if constexpr (__x_to_x && __have_sse4_1)
          {
        return __intrin_bitcast<_To>(_mm_shuffle_epi8(
          _mm_blend_epi16(
            _mm_blend_epi16(__i0, _mm_slli_si128(__i1, 2), 0x22),
            _mm_blend_epi16(_mm_slli_si128(__i2, 4),
                    _mm_slli_si128(__i3, 6), 0x88),
            0xcc),
          _mm_setr_epi8(0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7,
                14, 15)));
          }
        else if constexpr (__y_to_y && __have_avx2)
          {
        return __intrin_bitcast<_To>(_mm256_shuffle_epi8(
          __xzyw(_mm256_blend_epi16(
            __auto_bitcast(
              _mm256_shuffle_ps(__vector_bitcast<float>(__v0),
                    __vector_bitcast<float>(__v2),
                    0x88)), // 0.1. 8.9. 2.3. A.B.
            __to_intrin(__vector_bitcast<int>(_mm256_shuffle_ps(
                  __vector_bitcast<float>(__v1),
                  __vector_bitcast<float>(__v3), 0x88))
                << 16), // .4.5 .C.D .6.7 .E.F
            0xaa)               // 0415 8C9D 2637 AEBF
             ),             // 0415 2637 8C9D AEBF
          _mm256_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11,
                   14, 15, 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7,
                   10, 11, 14, 15)));
        /*
        auto __a = _mm256_unpacklo_epi16(__v0, __v1);  // 04.. .... 26..
        .... auto __b = _mm256_unpackhi_epi16(__v0, __v1);  // 15..
        .... 37.. .... auto __c = _mm256_unpacklo_epi16(__v2, __v3);  //
        8C.. .... AE.. .... auto __d = _mm256_unpackhi_epi16(__v2,
        __v3);
        // 9D.. .... BF.. .... auto __e = _mm256_unpacklo_epi16(__a,
        __b);
        // 0145 .... 2367 .... auto __f = _mm256_unpacklo_epi16(__c,
        __d);
        // 89CD .... ABEF .... auto __g = _mm256_unpacklo_epi64(__e,
        __f);
        // 0145 89CD 2367 ABEF return __concat(
            _mm_unpacklo_epi32(__lo128(__g), __hi128(__g)),
            _mm_unpackhi_epi32(__lo128(__g), __hi128(__g)));  // 0123
        4567 89AB CDEF
            */
          } // else use fallback
      }
    else if constexpr (__i64_to_i8) //{{{2
      {
        if constexpr (__x_to_x)
          {
        // TODO: use fallback for now
          }
        else if constexpr (__y_to_x)
          {
        auto __a
          = _mm256_srli_epi32(_mm256_slli_epi32(__i0, 24), 24)
            | _mm256_srli_epi32(_mm256_slli_epi32(__i1, 24), 16)
            | _mm256_srli_epi32(_mm256_slli_epi32(__i2, 24), 8)
            | _mm256_slli_epi32(
              __i3, 24); // 048C .... 159D .... 26AE .... 37BF ....
        /*return _mm_shuffle_epi8(
            _mm_blend_epi32(__lo128(__a) << 32, __hi128(__a), 0x5),
            _mm_setr_epi8(4, 12, 0, 8, 5, 13, 1, 9, 6, 14, 2, 10, 7, 15,
           3, 11));*/
        auto __b = _mm256_unpackhi_epi64(
          __a, __a); // 159D .... 159D .... 37BF .... 37BF ....
        auto __c = _mm256_unpacklo_epi8(
          __a, __b); // 0145 89CD .... .... 2367 ABEF .... ....
        return __intrin_bitcast<_To>(
          _mm_unpacklo_epi16(__lo128(__c),
                     __hi128(__c))); // 0123 4567 89AB CDEF
          }
      }
    else if constexpr (__i32_to_i8) //{{{2
      {
        if constexpr (__x_to_x)
          {
        if constexpr (__have_ssse3)
          {
            const auto __x0 = __vector_bitcast<_UInt>(__v0) & 0xff;
            const auto __x1 = (__vector_bitcast<_UInt>(__v1) & 0xff)
                      << 8;
            const auto __x2 = (__vector_bitcast<_UInt>(__v2) & 0xff)
                      << 16;
            const auto __x3 = __vector_bitcast<_UInt>(__v3) << 24;
            return __intrin_bitcast<_To>(
              _mm_shuffle_epi8(__to_intrin(__x0 | __x1 | __x2 | __x3),
                       _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13,
                             2, 6, 10, 14, 3, 7, 11,
                             15)));
          }
        else
          {
            auto __a
              = _mm_unpacklo_epi8(__i0, __i2); // 08.. .... 19.. ....
            auto __b
              = _mm_unpackhi_epi8(__i0, __i2); // 2A.. .... 3B.. ....
            auto __c
              = _mm_unpacklo_epi8(__i1, __i3); // 4C.. .... 5D.. ....
            auto __d
              = _mm_unpackhi_epi8(__i1, __i3); // 6E.. .... 7F.. ....
            auto __e
              = _mm_unpacklo_epi8(__a, __c); // 048C .... .... ....
            auto __f
              = _mm_unpackhi_epi8(__a, __c); // 159D .... .... ....
            auto __g
              = _mm_unpacklo_epi8(__b, __d); // 26AE .... .... ....
            auto __h
              = _mm_unpackhi_epi8(__b, __d); // 37BF .... .... ....
            return __intrin_bitcast<_To>(_mm_unpacklo_epi8(
              _mm_unpacklo_epi8(__e, __g), // 0246 8ACE .... ....
              _mm_unpacklo_epi8(__f, __h)  // 1357 9BDF .... ....
              ));                          // 0123 4567 89AB CDEF
          }
          }
        else if constexpr (__y_to_y)
          {
        const auto __a = _mm256_shuffle_epi8(
          __to_intrin((__vector_bitcast<_UShort>(_mm256_blend_epi16(
                 __i0, _mm256_slli_epi32(__i1, 16), 0xAA))
                   & 0xff)
                  | (__vector_bitcast<_UShort>(_mm256_blend_epi16(
                   __i2, _mm256_slli_epi32(__i3, 16), 0xAA))
                 << 8)),
          _mm256_setr_epi8(0, 4, 8, 12, 2, 6, 10, 14, 1, 5, 9, 13, 3, 7,
                   11, 15, 0, 4, 8, 12, 2, 6, 10, 14, 1, 5, 9,
                   13, 3, 7, 11, 15));
        return __intrin_bitcast<_To>(_mm256_permutevar8x32_epi32(
          __a, _mm256_setr_epi32(0, 4, 1, 5, 2, 6, 3, 7)));
          }
      }
    else if constexpr (__i64_to_f32) //{{{2
      {
        // this branch is only relevant with AVX and w/o AVX2 (i.e. no ymm
        // integers)
        if constexpr (__x_to_y)
          {
        return __make_wrapper<float>(__v0[0], __v0[1], __v1[0], __v1[1],
                         __v2[0], __v2[1], __v3[0],
                         __v3[1]);

        const auto __a = _mm_unpacklo_epi32(__i0, __i1);   // acAC
        const auto __b = _mm_unpackhi_epi32(__i0, __i1);   // bdBD
        const auto __c = _mm_unpacklo_epi32(__i2, __i3);   // egEG
        const auto __d = _mm_unpackhi_epi32(__i2, __i3);   // fhFH
        const auto __lo32a = _mm_unpacklo_epi32(__a, __b); // abcd
        const auto __lo32b = _mm_unpacklo_epi32(__c, __d); // efgh
        const auto __hi32 = __vector_bitcast<
          conditional_t<is_signed_v<_Tp>, int, _UInt>>(
          __concat(_mm_unpackhi_epi32(__a, __b),
               _mm_unpackhi_epi32(__c, __d))); // ABCD EFGH
        const auto __hi
          = 0x100000000LL
            * __convert_x86<__vector_type_t<float, 8>>(__hi32);
        const auto __mid
          = 0x10000
            * _mm256_cvtepi32_ps(__concat(_mm_srli_epi32(__lo32a, 16),
                          _mm_srli_epi32(__lo32b, 16)));
        const auto __lo = _mm256_cvtepi32_ps(
          __concat(_mm_set1_epi32(0x0000ffffu) & __lo32a,
               _mm_set1_epi32(0x0000ffffu) & __lo32b));
        return (__hi + __mid) + __lo;
          }
      }
    else if constexpr (__f64_to_ibw) //{{{2
      {
        return __convert_x86<_To>(
          __convert_x86<__vector_type_t<int, _Np * 2>>(__v0, __v1),
          __convert_x86<__vector_type_t<int, _Np * 2>>(__v2, __v3));
      }
    else if constexpr (__f32_to_ibw) //{{{2
      {
        return __convert_x86<_To>(
          __convert_x86<__vector_type_t<int, _Np>>(__v0),
          __convert_x86<__vector_type_t<int, _Np>>(__v1),
          __convert_x86<__vector_type_t<int, _Np>>(__v2),
          __convert_x86<__vector_type_t<int, _Np>>(__v3));
      } //}}}

    // fallback: {{{2
    if constexpr (sizeof(_To) >= 32)
      // if _To is ymm or zmm, then _SimdWrapper<_Up, _M / 2> is xmm or ymm
      return __concat(__convert_x86<__vector_type_t<_Up, _M / 2>>(__v0,
                                      __v1),
              __convert_x86<__vector_type_t<_Up, _M / 2>>(__v2,
                                      __v3));
    else if constexpr (sizeof(_To) == 16)
      {
        const auto __lo = __to_intrin(__convert_x86<_To>(__v0, __v1));
        const auto __hi = __to_intrin(__convert_x86<_To>(__v2, __v3));
        if constexpr (sizeof(_Up) * _Np * 2 == 8)
          {
        if constexpr (is_floating_point_v<_Up>)
          return __auto_bitcast(_mm_unpacklo_pd(__lo, __hi));
        else
          return __intrin_bitcast<_To>(_mm_unpacklo_epi64(__lo, __hi));
          }
        else if constexpr (sizeof(_Up) * _Np * 2 == 4)
          {
        if constexpr (is_floating_point_v<_Up>)
          return __auto_bitcast(_mm_unpacklo_ps(__lo, __hi));
        else
          return __intrin_bitcast<_To>(_mm_unpacklo_epi32(__lo, __hi));
          }
        else
          __assert_unreachable<_Tp>();
      }
    else
      return __vector_convert<_To>(__v0, __v1, __v2, __v3,
                       make_index_sequence<_Np>());
    //}}}2
      }
  }

//}}}
// 8-arg __convert_x86 {{{1
template <typename _To, typename _V, typename _Traits>
  _GLIBCXX_SIMD_INTRINSIC _To
  __convert_x86(_V __v0, _V __v1, _V __v2, _V __v3, _V __v4, _V __v5, _V __v6,
        _V __v7)
  {
    static_assert(__is_vector_type_v<_V>);
    using _Tp = typename _Traits::value_type;
    constexpr size_t _Np = _Traits::_S_full_size;
    [[maybe_unused]] const auto __i0 = __to_intrin(__v0);
    [[maybe_unused]] const auto __i1 = __to_intrin(__v1);
    [[maybe_unused]] const auto __i2 = __to_intrin(__v2);
    [[maybe_unused]] const auto __i3 = __to_intrin(__v3);
    [[maybe_unused]] const auto __i4 = __to_intrin(__v4);
    [[maybe_unused]] const auto __i5 = __to_intrin(__v5);
    [[maybe_unused]] const auto __i6 = __to_intrin(__v6);
    [[maybe_unused]] const auto __i7 = __to_intrin(__v7);
    using _Up = typename _VectorTraits<_To>::value_type;
    constexpr size_t _M = _VectorTraits<_To>::_S_full_size;

    static_assert(8 * _Np <= _M,
          "__v4-__v7 would be discarded; use the four/two/one-argument "
          "__convert_x86 overload instead");

    // [xyz]_to_[xyz] {{{2
    [[maybe_unused]] constexpr bool __x_to_x
      = sizeof(__v0) <= 16 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __x_to_y
      = sizeof(__v0) <= 16 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __x_to_z
      = sizeof(__v0) <= 16 && sizeof(_To) == 64;
    [[maybe_unused]] constexpr bool __y_to_x
      = sizeof(__v0) == 32 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __y_to_y
      = sizeof(__v0) == 32 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __y_to_z
      = sizeof(__v0) == 32 && sizeof(_To) == 64;
    [[maybe_unused]] constexpr bool __z_to_x
      = sizeof(__v0) == 64 && sizeof(_To) <= 16;
    [[maybe_unused]] constexpr bool __z_to_y
      = sizeof(__v0) == 64 && sizeof(_To) == 32;
    [[maybe_unused]] constexpr bool __z_to_z
      = sizeof(__v0) == 64 && sizeof(_To) == 64;

    // [if]X_to_i8 {{{2
    [[maybe_unused]] constexpr bool __i_to_i
      = is_integral_v<_Up> && is_integral_v<_Tp>;
    [[maybe_unused]] constexpr bool __i64_to_i8
      = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 1;
    [[maybe_unused]] constexpr bool __f64_to_i8
      = is_integral_v<_Up> && sizeof(_Up) == 1
    && is_floating_point_v<_Tp> && sizeof(_Tp) == 8;

    if constexpr (__i_to_i) // assert ISA {{{2
      {
    static_assert(__x_to_x || __have_avx2,
              "integral conversions with ymm registers require AVX2");
    static_assert(__have_avx512bw
            || ((sizeof(_Tp) >= 4 || sizeof(__v0) < 64)
                && (sizeof(_Up) >= 4 || sizeof(_To) < 64)),
              "8/16-bit integers in zmm registers require AVX512BW");
    static_assert((sizeof(__v0) < 64 && sizeof(_To) < 64) || __have_avx512f,
              "integral conversions with ymm registers require AVX2");
      }
    // concat => use 4-arg __convert_x86 {{{2
    if constexpr (sizeof(__v0) < 16 || (sizeof(__v0) == 16 && __have_avx2)
          || (sizeof(__v0) == 16 && __have_avx
              && is_floating_point_v<_Tp>)
          || (sizeof(__v0) == 32 && __have_avx512f))
      {
    // The ISA can handle wider input registers, so concat and use two-arg
    // implementation. This reduces code duplication considerably.
    return __convert_x86<_To>(__concat(__v0, __v1), __concat(__v2, __v3),
                  __concat(__v4, __v5), __concat(__v6, __v7));
      }
    else //{{{2
      {
    // conversion using bit reinterpretation (or no conversion at all)
    // should all go through the concat branch above:
    static_assert(
      !(is_floating_point_v<
          _Tp> == is_floating_point_v<_Up> && sizeof(_Tp) == sizeof(_Up)));
    static_assert(!(8 * _Np < _M && sizeof(_To) > 16),
              "zero extension should be impossible");
    if constexpr (__i64_to_i8) //{{{2
      {
        if constexpr (__x_to_x && __have_ssse3)
          {
        // unsure whether this is better than the variant below
        return __intrin_bitcast<_To>(_mm_shuffle_epi8(
          __to_intrin(
            (((__v0 & 0xff) | ((__v1 & 0xff) << 8))
             | (((__v2 & 0xff) << 16) | ((__v3 & 0xff) << 24)))
            | ((((__v4 & 0xff) << 32) | ((__v5 & 0xff) << 40))
               | (((__v6 & 0xff) << 48) | (__v7 << 56)))),
          _mm_setr_epi8(0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14,
                7, 15)));
          }
        else if constexpr (__x_to_x)
          {
        const auto __a = _mm_unpacklo_epi8(__i0, __i1); // ac
        const auto __b = _mm_unpackhi_epi8(__i0, __i1); // bd
        const auto __c = _mm_unpacklo_epi8(__i2, __i3); // eg
        const auto __d = _mm_unpackhi_epi8(__i2, __i3); // fh
        const auto __e = _mm_unpacklo_epi8(__i4, __i5); // ik
        const auto __f = _mm_unpackhi_epi8(__i4, __i5); // jl
        const auto __g = _mm_unpacklo_epi8(__i6, __i7); // mo
        const auto __h = _mm_unpackhi_epi8(__i6, __i7); // np
        return __intrin_bitcast<_To>(_mm_unpacklo_epi64(
          _mm_unpacklo_epi32(_mm_unpacklo_epi8(__a, __b),  // abcd
                     _mm_unpacklo_epi8(__c, __d)), // efgh
          _mm_unpacklo_epi32(_mm_unpacklo_epi8(__e, __f),  // ijkl
                     _mm_unpacklo_epi8(__g, __h))  // mnop
          ));
          }
        else if constexpr (__y_to_y)
          {
        auto __a = // 048C GKOS 159D HLPT 26AE IMQU 37BF JNRV
          __to_intrin(
            (((__v0 & 0xff) | ((__v1 & 0xff) << 8))
             | (((__v2 & 0xff) << 16) | ((__v3 & 0xff) << 24)))
            | ((((__v4 & 0xff) << 32) | ((__v5 & 0xff) << 40))
               | (((__v6 & 0xff) << 48) | ((__v7 << 56)))));
        /*
        auto __b = _mm256_unpackhi_epi64(__a, __a);  // 159D HLPT 159D
        HLPT 37BF JNRV 37BF JNRV auto __c = _mm256_unpacklo_epi8(__a,
        __b);  // 0145 89CD GHKL OPST 2367 ABEF IJMN QRUV auto __d =
        __xzyw(__c); // 0145 89CD 2367 ABEF GHKL OPST IJMN QRUV return
        _mm256_shuffle_epi8(
            __d, _mm256_setr_epi8(0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12,
        13, 6, 7, 14, 15, 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7,
        14, 15));
                    */
        auto __b = _mm256_shuffle_epi8( // 0145 89CD GHKL OPST 2367 ABEF
                        // IJMN QRUV
          __a, _mm256_setr_epi8(0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13,
                    6, 14, 7, 15, 0, 8, 1, 9, 2, 10, 3, 11,
                    4, 12, 5, 13, 6, 14, 7, 15));
        auto __c
          = __xzyw(__b); // 0145 89CD 2367 ABEF GHKL OPST IJMN QRUV
        return __intrin_bitcast<_To>(_mm256_shuffle_epi8(
          __c, _mm256_setr_epi8(0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13,
                    6, 7, 14, 15, 0, 1, 8, 9, 2, 3, 10, 11,
                    4, 5, 12, 13, 6, 7, 14, 15)));
          }
        else if constexpr (__z_to_z)
          {
        return __concat(
          __convert_x86<__vector_type_t<_Up, _M / 2>>(__v0, __v1, __v2,
                                  __v3),
          __convert_x86<__vector_type_t<_Up, _M / 2>>(__v4, __v5, __v6,
                                  __v7));
          }
      }
    else if constexpr (__f64_to_i8) //{{{2
      {
        return __convert_x86<_To>(
          __convert_x86<__vector_type_t<int, _Np * 2>>(__v0, __v1),
          __convert_x86<__vector_type_t<int, _Np * 2>>(__v2, __v3),
          __convert_x86<__vector_type_t<int, _Np * 2>>(__v4, __v5),
          __convert_x86<__vector_type_t<int, _Np * 2>>(__v6, __v7));
      }
    else // unreachable {{{2
      __assert_unreachable<_Tp>();
    //}}}

    // fallback: {{{2
    if constexpr (sizeof(_To) >= 32)
      // if _To is ymm or zmm, then _SimdWrapper<_Up, _M / 2> is xmm or ymm
      return __concat(
        __convert_x86<__vector_type_t<_Up, _M / 2>>(__v0, __v1, __v2, __v3),
        __convert_x86<__vector_type_t<_Up, _M / 2>>(__v4, __v5, __v6,
                            __v7));
    else if constexpr (sizeof(_To) == 16)
      {
        const auto __lo
          = __to_intrin(__convert_x86<_To>(__v0, __v1, __v2, __v3));
        const auto __hi
          = __to_intrin(__convert_x86<_To>(__v4, __v5, __v6, __v7));
        static_assert(sizeof(_Up) == 1 && _Np == 2);
        return __intrin_bitcast<_To>(_mm_unpacklo_epi64(__lo, __hi));
      }
    else
      {
        __assert_unreachable<_Tp>();
        // return __vector_convert<_To>(__v0, __v1, __v2, __v3, __v4, __v5,
        // __v6, __v7,
        //                             make_index_sequence<_Np>());
      } //}}}2
      }
  }

//}}}
// 16-arg __convert_x86 {{{1
template <typename _To, typename _V, typename _Traits>
  _GLIBCXX_SIMD_INTRINSIC _To
  __convert_x86(_V __v0, _V __v1, _V __v2, _V __v3, _V __v4, _V __v5, _V __v6,
        _V __v7, _V __v8, _V __v9, _V __v10, _V __v11, _V __v12,
        _V __v13, _V __v14, _V __v15)
  {
    // concat => use 8-arg __convert_x86
    return __convert_x86<_To>(__concat(__v0, __v1), __concat(__v2, __v3),
                  __concat(__v4, __v5), __concat(__v6, __v7),
                  __concat(__v8, __v9), __concat(__v10, __v11),
                  __concat(__v12, __v13), __concat(__v14, __v15));
  }

//}}}

#endif // __cplusplus >= 201703L
#endif // _GLIBCXX_EXPERIMENTAL_SIMD_X86_CONVERSIONS_H

// vim: foldmethod=marker

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0087 ]--