namespace xsimd
{ namespace kernel
{ usingnamespace types; using v1ti = __int128 __attribute__((vector_size(16))); using v4sf = float __attribute__((vector_size(16))); using v2df = double __attribute__((vector_size(16))); using uv2di = unsignedlonglongint __attribute__((vector_size(16))); using v2di = longlongint __attribute__((vector_size(16))); using uv4si = unsignedint __attribute__((vector_size(16))); using v4si = int __attribute__((vector_size(16))); using uv8hi = unsignedshortint __attribute__((vector_size(16))); using v8hi = shortint __attribute__((vector_size(16))); using uv16qi = unsignedchar __attribute__((vector_size(16))); using v16qi = signedchar __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<unsignedlong>
{ using type = unsignedlonglong;
};
template <> struct builtin_scalar<long>
{ using type = longlong;
};
template <> struct builtin_scalar<char>
{ using type = typename std::conditional<std::is_signed<char>::value, signedchar, unsignedchar>::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&, 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) { 0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27 };
uv16qi perm_imag = (uv16qi) { 4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31 };
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) };
}
// 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"); returntypename 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"); returntypename 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> const& other, 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& 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& z, requires_arch<vxe>) noexcept
{ return vec_msub(x.data, y.data, z.data);
}
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 {});
}
// 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 #ifdefined __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, 4, 1);
} #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
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-08-25)
¤
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.