Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  xsimd_vxe.hpp

  Sprache: C
 

/***************************************************************************
 * Copyright (c) Andreas Krebbel                                            *
 * Based on xsimd_vsx.hpp                                                   *
 * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
 * Martin Renou                                                             *
 * Copyright (c) QuantStack                                                 *
 * Copyright (c) Serge Guelton                                              *
 *                                                                          *
 * Distributed under the terms of the BSD 3-Clause License.                 *
 *                                                                          *
 * The full license is in the file LICENSE, distributed with this software. *
 ****************************************************************************/


#ifndef XSIMD_VXE_HPP
#define XSIMD_VXE_HPP

#include "../types/xsimd_vxe_register.hpp"

#include <type_traits>

namespace xsimd
{
    namespace kernel
    {
        using namespace types;
        using v1ti = __int128 __attribute__((vector_size(16)));
        using v4sf = float __attribute__((vector_size(16)));
        using v2df = double __attribute__((vector_size(16)));
        using uv2di = unsigned long long int __attribute__((vector_size(16)));
        using v2di = long long int __attribute__((vector_size(16)));
        using uv4si = unsigned int __attribute__((vector_size(16)));
        using v4si = int __attribute__((vector_size(16)));
        using uv8hi = unsigned short int __attribute__((vector_size(16)));
        using v8hi = short int __attribute__((vector_size(16)));
        using uv16qi = unsigned char __attribute__((vector_size(16)));
        using v16qi = signed char __attribute__((vector_size(16)));

        // builtin_t<T> - the scalar type as it would be used for a vector intrinsic
        // VXE vector intrinsics do not support long, unsigned long, and char
        // The builtin<T> definition can be used to map the incoming
        // type to the right one to be used with the intrinsics.
        template <typename T>
        struct builtin_scalar
        {
            using type = T;
        };

        template <>
        struct builtin_scalar<unsigned long>
        {
            using type = unsigned long long;
        };

        template <>
        struct builtin_scalar<long>
        {
            using type = long long;
        };

        template <>
        struct builtin_scalar<char>
        {
            using type = typename std::conditional<std::is_signed<char>::value, signed charunsigned char>::type;
        };

        template <typename T>
        using builtin_t = typename builtin_scalar<T>::type;

        // bitwise_cast
        template <class A, class T_in, class T_out>
        XSIMD_INLINE batch<T_out, A> bitwise_cast(batch<T_in, A> const& self, batch<T_out, A> const&,&nbsp;requires_arch<vxe>) noexcept
        {
            return (typename batch<T_out, A>::register_type)(self.data);
        }

        // batch_bool_cast
        template <class A, class T_out, class T_in>
        XSIMD_INLINE batch_bool<T_out, A> batch_bool_cast(batch_bool<T_in, A> const& self, batch_bool<T_out, A> const&, requires_arch<vxe>) noexcept
        {
            return (typename batch_bool<T_out, A>::register_type)self.data;
        }

        // load

        // load_unaligned
        template <class A, class T, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE batch<T, A> load_unaligned(T const* mem, convert<T>, requires_arch<vxe>) noexcept
        {
            return (typename batch<T, A>::register_type)vec_xl(0, (builtin_t<T>*)mem);
        }

        // load_aligned
        template <class A, class T, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE batch<T, A> load_aligned(T const* mem, convert<T>, requires_arch<vxe>) noexcept
        {
            return load_unaligned<A>(mem, kernel::convert<T> {}, vxe {});
        }

        // load_complex
        namespace detail
        {
            template <class A>
            XSIMD_INLINE batch<std::complex<float>, A> load_complex(batch<float, A> const& hi, batch<float, A> const& lo, requires_arch<vxe>) noexcept
            {
                // Interleave real and imaginary parts
                // hi = [r0, i0, r1, i1], lo = [r2, i2, r3, i3]
                // We need: real = [r0, r1, r2, r3], imag = [i0, i1, i2, i3]
                using v4sf = float __attribute__((vector_size(16)));
                uv16qi perm_real = (uv16qi) { 01238910111617181924252627 };
                uv16qi perm_imag = (uv16qi) { 4567121314152021222328293031 };
                v4sf real = vec_perm((v4sf)hi.data, (v4sf)lo.data, perm_real);
                v4sf imag = vec_perm((v4sf)hi.data, (v4sf)lo.data, perm_imag);
                return { batch<float, A>(real), batch<float, A>(imag) };
            }

            template <class A>
            XSIMD_INLINE batch<std::complex<double>, A> load_complex(batch<double, A> const& hi, batch<double, A> const& lo, requires_arch<vxe>) noexcept
            {
                // hi = [r0, i0], lo = [r1, i1]
                // We need: real = [r0, r1], imag = [i0, i1]
                using v2df = double __attribute__((vector_size(16)));
                uv16qi perm_real = (uv16qi) { 012345671617181920212223 };
                uv16qi perm_imag = (uv16qi) { 891011121314152425262728293031 };
                v2df real = vec_perm((v2df)hi.data, (v2df)lo.data, perm_real);
                v2df imag = vec_perm((v2df)hi.data, (v2df)lo.data, perm_imag);
                return { batch<double, A>(real), batch<double, A>(imag) };
            }

            template <class A>
            XSIMD_INLINE batch<float, A> complex_low(batch<std::complex<float>, A> const& self, requires_arch<vxe>) noexcept
            {
                uv16qi perm = (uv16qi) { 012316171819456720212223 };
                return batch<float, A>(vec_perm((v4sf)self.real().data, (v4sf)self.imag().data, perm));
            }

            template <class A>
            XSIMD_INLINE batch<float, A> complex_high(batch<std::complex<float>, A> const& self, requires_arch<vxe>) noexcept
            {
                uv16qi perm = (uv16qi) { 891011242526271213141528293031 };
                return batch<float, A>(vec_perm((v4sf)self.real().data, (v4sf)self.imag().data, perm));
            }

            template <class A>
            XSIMD_INLINE batch<double, A> complex_low(batch<std::complex<double>, A> const& self, requires_arch<vxe>) noexcept
            {
                uv16qi perm = (uv16qi) { 012345671617181920212223 };
                return batch<double, A>(vec_perm((v2df)self.real().data, (v2df)self.imag().data, perm));
            }

            template <class A>
            XSIMD_INLINE batch<double, A> complex_high(batch<std::complex<double>, A> const& self, requires_arch<vxe>) noexcept
            {
                uv16qi perm = (uv16qi) { 891011121314152425262728293031 };
                return batch<double, A>(vec_perm((v2df)self.real().data, (v2df)self.imag().data, perm));
            }
        }

        // store
        template <class A, class T>
        XSIMD_INLINE void store_aligned(T* dst, batch<T, A> const& src, requires_arch<vxe>) noexcept
        {
            vec_xst(src.data, 0, (builtin_t<T>*)dst);
        }

        template <class A, class T>
        XSIMD_INLINE void store_unaligned(T* dst, batch<T, A> const& src, requires_arch<vxe>) noexcept
        {
            store_aligned<A>(dst, src, vxe {});
        }

        // set
        template <class A, class T, class... Values>
        XSIMD_INLINE batch<T, A> set(batch<T, A> const&, requires_arch<vxe>, Values... values) noexcept
        {
            static_assert(sizeof...(Values) == batch<T, A>::size, "consistent init");
            return typename batch<T, A>::register_type { values... };
        }

        template <class A, class T, class... Values, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE batch_bool<T, A> set(batch_bool<T, A> const&, requires_arch<vxe>, Values... values) noexcept
        {
            static_assert(sizeof...(Values) == batch_bool<T, A>::size, "consistent init");
            return typename batch_bool<T, A>::register_type { static_cast<decltype(std::declval<typename batch_bool<T, A>::register_type>()[0])>(values ? -1LL : 0LL)... };
        }
        // first
        template <class A, class T, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE T first(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return self.data[0];
        }
        // insert
        template <class A, class T, size_t I, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE batch<T, A> insert(batch<T, A> const& self, T val, index<I>, requires_arch<vxe>) noexcept
        {
            // vec_insert on float is broken with clang
            batch<T, A> out(self);
            out.data[I] = val;
            return out;
        }

        // eq
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> eq(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data == other.data;
        }
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> eq(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data == other.data;
        }

        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> lt(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data < other.data;
        }
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> le(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data <= other.data;
        }

        // neq
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> neq(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return ~(self.data == other.data);
        }

        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> neq(batch_bool<T, A> const& self, batch_bool<T, A> constother, requires_arch<vxe>) noexcept
        {
            return bitwise_xor(self, other);
        }

        // sub
        template <class A, class T>
        XSIMD_INLINE batch<T, A> sub(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data - other.data;
        }

        // broadcast
        template <class A, class T, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE batch<T, A> broadcast(T val, requires_arch<vxe>) noexcept
        {
            return vec_splats(static_cast<builtin_t<T>>(val));
        }

        // abs
        template <class A, class T, class = typename std::enable_if<std::is_signed<T>::value, void>::type>
        XSIMD_INLINE batch<T, A> abs(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return vec_abs(self.data);
        }
        // bitwise_and
        template <class A, class T>
        XSIMD_INLINE batch<T, A> bitwise_and(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return (typename batch<T, A>::register_type)((v4si)self.data & (v4si)other.data);
        }
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> bitwise_and(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data & other.data;
        }

        // bitwise_or
        template <class A, class T>
        XSIMD_INLINE batch<T, A> bitwise_or(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return (typename batch<T, A>::register_type)((v4si)self.data | (v4si)other.data);
        }
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> bitwise_or(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data | other.data;
        }

        // bitwise_xor
        template <class A, class T>
        XSIMD_INLINE batch<T, A> bitwise_xor(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return (typename batch<T, A>::register_type)((v4si)self.data ^ (v4si)other.data);
        }
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> bitwise_xor(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data ^ other.data;
        }

        // bitwise_not
        template <class A, class T>
        XSIMD_INLINE batch<T, A> bitwise_not(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            // ~ operator does not work on floating point vectors
            return (typename batch<T, A>::register_type)(~(v4si)self.data);
        }
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> bitwise_not(batch_bool<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return ~self.data;
        }

        // bitwise_andnot
        template <class A, class T>
        XSIMD_INLINE batch<T, A> bitwise_andnot(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return (typename batch<T, A>::register_type)((v4si)self.data & ~(v4si)other.data);
        }
        template <class A, class T>
        XSIMD_INLINE batch_bool<T, A> bitwise_andnot(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data & ~other.data;
        }

        // div
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> div(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data / other.data;
        }

        // neg
        template <class A, class T>
        XSIMD_INLINE batch<T, A> neg(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return (typename batch<T, A>::register_type) { 0 } - self.data;
        }

        // add
        template <class A, class T>
        XSIMD_INLINE batch<T, A> add(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data + other.data;
        }

        // all
        template <class A, class T>
        XSIMD_INLINE bool all(batch_bool<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return ((v1ti)self.data)[0] == -1;
        }

        // any
        template <class A, class T>
        XSIMD_INLINE bool any(batch_bool<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return ((v1ti)self.data)[0] != 0;
        }
        // avgr
        template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
        XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return vec_avg(self.data, other.data);
        }

        // max
        template <class A, class T>
        XSIMD_INLINE batch<T, A> max(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return vec_max(self.data, other.data);
        }
        // min
        template <class A, class T>
        XSIMD_INLINE batch<T, A> min(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return vec_min(self.data, other.data);
        }
        // fma
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> fma(batch<T, A> const& x, batch<T, A> const& y, batch<T, A> const&&nbsp;z, requires_arch<vxe>) noexcept
        {
            return vec_madd(x.data, y.data, z.data);
        }
        // fms
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> fms(batch<T, A> const& x, batch<T, A> const& y, batch<T, A> const&&nbsp;z, requires_arch<vxe>) noexcept
        {
            return vec_msub(x.data, y.data, z.data);
        }

        // mul
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> mul(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return self.data * other.data;
        }
        // haddp
        template <class A>
        XSIMD_INLINE batch<float, A> haddp(batch<float, A> const* r, requires_arch<vxe>) noexcept
        {
            v4sf lo01, hi01, lo23, hi23, sum01, sum23, sumeven, sumodd;
            lo01 = vec_mergel(r[0].data, r[1].data); // { r[0][2], r[1][2], r[0][3], r[1][3] }
            hi01 = vec_mergeh(r[0].data, r[1].data); // { r[0][0], r[1][0], r[0][1], r[1][1] }
            lo23 = vec_mergel(r[2].data, r[3].data); // { r[2][2], r[2][2], r[3][3], r[3][3] }
            hi23 = vec_mergeh(r[2].data, r[3].data); // { r[2][0], r[2][0], r[3][1], r[3][1] }
            sum01 = lo01 + hi01; // { r[0][0] + r[0][2], r[1][0] + r[1][2], r[0][1] + r[0][3], r[1][1] + r[1][3] }
            sum23 = lo23 + hi23; // { r[2][0] + r[2][2], r[3][0] + r[3][2], r[2][1] + r[2][3], r[3][1] + r[3][3] }
            sumeven = (v4sf)vec_mergeh((v2di)sum01, (v2di)sum23); // { r[0][0] + r[0][2], r[1][0] + r[1][2], r[2][0] + r[2][2], r[3][0] + r[3][2] }
            sumodd = (v4sf)vec_mergel((v2di)sum01, (v2di)sum23); // { r[0][1] + r[0][3], r[1][1] + r[1][3], r[2][1] + r[2][3], r[3][1] + r[3][3] }
            return sumeven + sumodd;
        }
        template <class A>
        XSIMD_INLINE batch<double, A> haddp(batch<double, A> const* row, requires_arch<vxe>) noexcept
        {
            return vec_mergeh(row[0].data, row[1].data) + vec_mergel(row[0].data, row[1].data);
        }

        // reduce_add
        template <class A>
        XSIMD_INLINE float reduce_add(batch<float, A> const& self, requires_arch<vxe>) noexcept
        {
            v4sf shifted_64 = vec_sld(self.data, self.data, 8);
            v4sf added_1 = self.data + shifted_64;
            v4sf shifted_32 = vec_sld(added_1, added_1, 4);
            return (added_1 + shifted_32)[0];
        }

        template <class A>
        XSIMD_INLINE double reduce_add(batch<double, A> const& self, requires_arch<vxe>) noexcept
        {
            return (self.data + vec_sld(self.data, self.data, 8))[0];
        }

        template <class A>
        XSIMD_INLINE uint64_t reduce_add(batch<uint64_t, A> const& self, requires_arch<vxe>) noexcept
        {
            uv2di shifted = vec_sld((uv2di)self.data, (uv2di)self.data, 8);
            uv2di sum = (uv2di)self.data + shifted;
            return (uint64_t)sum[0];
        }
        template <class A>
        XSIMD_INLINE int64_t reduce_add(batch<int64_t, A> const& self, requires_arch<vxe>) noexcept
        {
            v2di shifted = vec_sld((v2di)self.data, (v2di)self.data, 8);
            v2di sum = (v2di)self.data + shifted;
            return (int64_t)sum[0];
        }
        template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
        XSIMD_INLINE T reduce_add(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
            {
                using t = typename batch<T, A>::register_type;
                t shifted_64 = vec_sld(self.data, self.data, 8);
                t added_1 = self.data + shifted_64;
                t shifted_32 = vec_sld(added_1, added_1, 4);
                return (added_1 + shifted_32)[0];
            }
            else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
            {
                using t = typename batch<T, A>::register_type;
                t shifted_64 = vec_sld(self.data, self.data, 8);
                t added_1 = self.data + shifted_64;
                t shifted_32 = vec_sld(added_1, added_1, 4);
                t added_2 = added_1 + shifted_32;
                t shifted_16 = vec_sld(added_2, added_2, 2);
                return (added_2 + shifted_16)[0];
            }
            else
            {
                using t = typename batch<T, A>::register_type;
                t shifted_64 = vec_sld(self.data, self.data, 8);
                t added_1 = self.data + shifted_64;
                t shifted_32 = vec_sld(added_1, added_1, 4);
                t added_2 = added_1 + shifted_32;
                t shifted_16 = vec_sld(added_2, added_2, 2);
                t added_3 = added_2 + shifted_16;
                t shifted_8 = vec_sld(added_3, added_3, 1);
                return (added_3 + shifted_8)[0];
            }
        }

        // select
        template <class A, class T>
        XSIMD_INLINE batch<T, A> select(batch_bool<T, A> const& cond, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<vxe>) noexcept
        {
            return vec_sel(false_br.data, true_br.data, cond.data);
        }
        template <class A, class T, bool... Values, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE batch<T, A> select(batch_bool_constant<T, A, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<vxe>) noexcept
        {
            return select(batch_bool<T, A> { Values... }, true_br, false_br, vxe {});
        }

        // slide_left
        template <size_t N, class A, class T>
        XSIMD_INLINE batch<T, A> slide_left(batch<T, A> const& x, requires_arch<vxe>) noexcept
        {
            XSIMD_IF_CONSTEXPR(N == batch<T, A>::size * sizeof(T))
            {
                return batch<T, A>(0);
            }
            else
            {
                auto shift_count = vec_splats((uint8_t)(8 * N));
                return vec_sll(x.data, shift_count);
            }
        }

        // slide_right
        template <size_t N, class A, class T>
        XSIMD_INLINE batch<T, A> slide_right(batch<T, A> const& x, requires_arch<vxe>) noexcept
        {
            XSIMD_IF_CONSTEXPR(N == batch<T, A>::size * sizeof(T))
            {
                return batch<T, A>(0);
            }
            else
            {
                auto shift_count = vec_splats((uint8_t)(8 * N));
                return vec_srl(x.data, shift_count);
            }
        }

        // sqrt
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> sqrt(batch<T, A> const& val, requires_arch<vxe>) noexcept
        {
            return vec_sqrt(val.data);
        }

        // rsqrt
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> rsqrt(batch<T, A> const& val, requires_arch<vxe>) noexcept
        {
            return batch<T, A>(T(1)) / sqrt(val, vxe {});
        }

        // shuffle
        template <class A, class ITy, ITy I0, ITy I1, ITy I2, ITy I3>
        XSIMD_INLINE batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y, batch_constant<ITy, A, I0, I1, I2, I3>, requires_arch<vxe>) noexcept
        {
            return vec_perm(x.data, y.data,
                            (__vector unsigned char) {
                                4 * I0 + 04 * I0 + 14 * I0 + 24 * I0 + 3,
                                4 * I1 + 04 * I1 + 14 * I1 + 24 * I1 + 3,
                                4 * I2 + 04 * I2 + 14 * I2 + 24 * I2 + 3,
                                4 * I3 + 04 * I3 + 14 * I3 + 24 * I3 + 3 });
        }

        template <class A, class ITy, ITy I0, ITy I1>
        XSIMD_INLINE batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const;y, batch_constant<ITy, A, I0, I1>, requires_arch<vxe>) noexcept
        {
            return vec_perm(x.data, y.data,
                            (__vector unsigned char) {
                                8 * I0 + 0,
                                8 * I0 + 1,
                                8 * I0 + 2,
                                8 * I0 + 3,
                                8 * I0 + 4,
                                8 * I0 + 5,
                                8 * I0 + 6,
                                8 * I0 + 7,
                                8 * I1 + 0,
                                8 * I1 + 1,
                                8 * I1 + 2,
                                8 * I1 + 3,
                                8 * I1 + 4,
                                8 * I1 + 5,
                                8 * I1 + 6,
                                8 * I1 + 7,
                            });
        }

        // swizzle
        // 16 x 8bit
        template <class A, uint8_t... Values>
        XSIMD_INLINE batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<uint8_t, A, Values...>, requires_arch<vxe>) noexcept
        {
            static_assert(sizeof...(Values) == batch<uint8_t, A>::size, "consistent init");
            uv16qi perm = (uv16qi) { Values... };
            return vec_perm(self.data, self.data, perm);
        }
        template <class A, uint8_t... Values>
        XSIMD_INLINE batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<uint8_t, A, Values...>, requires_arch<vxe>) noexcept
        {
            static_assert(sizeof...(Values) == batch<int8_t, A>::size, "consistent init");
            uv16qi perm = (uv16qi) { Values... };
            return vec_perm(self.data, self.data, perm);
        }

        // 8 x 16 bit
        template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
        XSIMD_INLINE batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<vxe>) noexcept
        {
            uv16qi perm = (uv16qi) {
                2 * V0, 2 * V0 + 1,
                2 * V1, 2 * V1 + 1,
                2 * V2, 2 * V2 + 1,
                2 * V3, 2 * V3 + 1,
                2 * V4, 2 * V4 + 1,
                2 * V5, 2 * V5 + 1,
                2 * V6, 2 * V6 + 1,
                2 * V7, 2 * V7 + 1
            };
            return vec_perm(self.data, self.data, perm);
        }
        template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
        XSIMD_INLINE batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<vxe>) noexcept
        {
            uv16qi perm = (uv16qi) {
                2 * V0, 2 * V0 + 1,
                2 * V1, 2 * V1 + 1,
                2 * V2, 2 * V2 + 1,
                2 * V3, 2 * V3 + 1,
                2 * V4, 2 * V4 + 1,
                2 * V5, 2 * V5 + 1,
                2 * V6, 2 * V6 + 1,
                2 * V7, 2 * V7 + 1
            };
            return vec_perm(self.data, self.data, perm);
        }

        // 4 x 32 bit
        template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
        XSIMD_INLINE batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<vxe>) noexcept
        {
            uv16qi perm = (uv16qi) {
                4 * V0, 4 * V0 + 14 * V0 + 24 * V0 + 3,
                4 * V1, 4 * V1 + 14 * V1 + 24 * V1 + 3,
                4 * V2, 4 * V2 + 14 * V2 + 24 * V2 + 3,
                4 * V3, 4 * V3 + 14 * V3 + 24 * V3 + 3
            };
            return vec_perm(self.data, self.data, perm);
        }
        template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
        XSIMD_INLINE batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<vxe>) noexcept
        {
            uv16qi perm = (uv16qi) {
                4 * V0, 4 * V0 + 14 * V0 + 24 * V0 + 3,
                4 * V1, 4 * V1 + 14 * V1 + 24 * V1 + 3,
                4 * V2, 4 * V2 + 14 * V2 + 24 * V2 + 3,
                4 * V3, 4 * V3 + 14 * V3 + 24 * V3 + 3
            };
            return vec_perm(self.data, self.data, perm);
        }
        template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
        XSIMD_INLINE batch<float, A> swizzle(batch<float, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<vxe>) noexcept
        {
            uv16qi perm = (uv16qi) {
                4 * V0, 4 * V0 + 14 * V0 + 24 * V0 + 3,
                4 * V1, 4 * V1 + 14 * V1 + 24 * V1 + 3,
                4 * V2, 4 * V2 + 14 * V2 + 24 * V2 + 3,
                4 * V3, 4 * V3 + 14 * V3 + 24 * V3 + 3
            };
            return vec_perm(self.data, self.data, perm);
        }

        // 2 x 64 bit
        template <class A, uint64_t V0, uint64_t V1>
        XSIMD_INLINE batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<vxe>) noexcept
        {
            using out = typename batch<uint64_t, A>::register_type;
            uv16qi perm = (uv16qi) {
                8 * V0 + 0,
                8 * V0 + 1,
                8 * V0 + 2,
                8 * V0 + 3,
                8 * V0 + 4,
                8 * V0 + 5,
                8 * V0 + 6,
                8 * V0 + 7,
                8 * V1 + 0,
                8 * V1 + 1,
                8 * V1 + 2,
                8 * V1 + 3,
                8 * V1 + 4,
                8 * V1 + 5,
                8 * V1 + 6,
                8 * V1 + 7,
            };
            return (out)vec_perm((uv2di)self.data, (uv2di)self.data, perm);
        }
        template <class A, uint64_t V0, uint64_t V1>
        XSIMD_INLINE batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<vxe>) noexcept
        {
            using out = typename batch<int64_t, A>::register_type;
            uv16qi perm = (uv16qi) {
                8 * V0 + 0,
                8 * V0 + 1,
                8 * V0 + 2,
                8 * V0 + 3,
                8 * V0 + 4,
                8 * V0 + 5,
                8 * V0 + 6,
                8 * V0 + 7,
                8 * V1 + 0,
                8 * V1 + 1,
                8 * V1 + 2,
                8 * V1 + 3,
                8 * V1 + 4,
                8 * V1 + 5,
                8 * V1 + 6,
                8 * V1 + 7,
            };
            return (out)vec_perm((v2di)self.data, (v2di)self.data, perm);
        }
        template <class A, uint64_t V0, uint64_t V1>
        XSIMD_INLINE batch<double, A> swizzle(batch<double, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<vxe>) noexcept
        {
            uv16qi perm = (uv16qi) {
                8 * V0 + 0,
                8 * V0 + 1,
                8 * V0 + 2,
                8 * V0 + 3,
                8 * V0 + 4,
                8 * V0 + 5,
                8 * V0 + 6,
                8 * V0 + 7,
                8 * V1 + 0,
                8 * V1 + 1,
                8 * V1 + 2,
                8 * V1 + 3,
                8 * V1 + 4,
                8 * V1 + 5,
                8 * V1 + 6,
                8 * V1 + 7,
            };
            return vec_perm(self.data, self.data, perm);
        }
        // zip_hi
        template <class A, class T, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return vec_mergel(self.data, other.data);
        }

        // zip_lo
        template <class A, class T, class = std::enable_if_t<std::is_scalar<T>::value>>
        XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& self, batch<T, A> const& other, requires_arch<vxe>) noexcept
        {
            return vec_mergeh(self.data, other.data);
        }
        // bitwise_rshift
        template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
        XSIMD_INLINE batch<T, A> bitwise_rshift(batch<T, A> const& self, int32_t other, requires_arch<vxe>) noexcept
        {
            return self.data >> other;
        }
        // bitwise_lshift
        template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
        XSIMD_INLINE batch<T, A> bitwise_lshift(batch<T, A> const& self, int32_t other, requires_arch<vxe>) noexcept
        {
            return self.data << other;
        }

        // isnan
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch_bool<T, A> isnan(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return ~vec_cmpeq(self.data, self.data);
        }

        // ceil
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> ceil(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return vec_ceil(self.data);
        }

        // floor
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> floor(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return vec_floor(self.data);
        }
        // round
        // vec_round rounds ties to even instead of zero
#if defined __has_builtin && __has_builtin(__builtin_s390_vfi)
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> round(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return __builtin_s390_vfi(self.data, 41);
        }
#endif
        // trunc
        template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
        XSIMD_INLINE batch<T, A> trunc(batch<T, A> const& self, requires_arch<vxe>) noexcept
        {
            return vec_trunc(self.data);
        }
    }
}
#endif

Messung V0.5 in Prozent
C=91 H=100 G=95

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=476070
#Domains=661743