/*************************************************************************** * 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. *
****************************************************************************/
template <class A>
XSIMD_INLINE void store_complex_unaligned(std::complex<double>* dst, batch<std::complex<double>, A> const& src, requires_arch<neon64>) noexcept
{
store_complex_aligned(dst, src, A {});
}
/******* * neg *
*******/
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> neg(batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vreinterpretq_u64_s64(vnegq_s64(vreinterpretq_s64_u64(rhs)));
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> neg(batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vnegq_s64(rhs);
}
template <class A>
XSIMD_INLINE batch<double, A> neg(batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vnegq_f64(rhs);
}
/******* * add *
*******/
template <class A>
XSIMD_INLINE batch<double, A> add(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vaddq_f64(lhs, rhs);
}
/******** * sadd *
********/
template <class A>
XSIMD_INLINE batch<double, A> sadd(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return add(lhs, rhs, neon64 {});
}
/******* * sub *
*******/
template <class A>
XSIMD_INLINE batch<double, A> sub(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vsubq_f64(lhs, rhs);
}
/******** * ssub *
********/
template <class A>
XSIMD_INLINE batch<double, A> ssub(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return sub(lhs, rhs, neon64 {});
}
/******* * mul *
*******/
template <class A>
XSIMD_INLINE batch<double, A> mul(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vmulq_f64(lhs, rhs);
}
/******* * div *
*******/
#ifdefined(XSIMD_FAST_INTEGER_DIVISION) template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> div(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcvtq_u64_f64(vcvtq_f64_u64(lhs) / vcvtq_f64_u64(rhs));
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> div(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcvtq_s64_f64(vcvtq_f64_s64(lhs) / vcvtq_f64_s64(rhs));
} #endif template <class A>
XSIMD_INLINE batch<double, A> div(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vdivq_f64(lhs, rhs);
}
/****** * eq *
******/
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> eq(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vceqq_u64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> eq(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vceqq_s64(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch_bool<double, A> eq(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vceqq_f64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> eq(batch_bool<T, A> const& lhs, batch_bool<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vceqq_u64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> eq(batch_bool<T, A> const& lhs, batch_bool<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vceqq_u64(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch_bool<double, A> eq(batch_bool<double, A> const& lhs, batch_bool<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vceqq_u64(lhs, rhs);
}
/************* * fast_cast *
*************/ namespace detail
{ template <class A>
XSIMD_INLINE batch<double, A> fast_cast(batch<int64_t, A> const& x, batch<double, A> const&, requires_arch<neon64>) noexcept
{ return vcvtq_f64_s64(x);
}
template <class A>
XSIMD_INLINE batch<double, A> fast_cast(batch<uint64_t, A> const& x, batch<double, A> const&, requires_arch<neon64>) noexcept
{ return vcvtq_f64_u64(x);
}
template <class A>
XSIMD_INLINE batch<int64_t, A> fast_cast(batch<double, A> const& x, batch<int64_t, A> const&, requires_arch<neon64>) noexcept
{ return vcvtq_s64_f64(x);
}
template <class A>
XSIMD_INLINE batch<uint64_t, A> fast_cast(batch<double, A> const& x, batch<uint64_t, A> const&, requires_arch<neon64>) noexcept
{ return vcvtq_u64_f64(x);
}
}
/****** * lt *
******/
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> lt(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcltq_u64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> lt(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcltq_s64(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch_bool<double, A> lt(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcltq_f64(lhs, rhs);
}
/****** * le *
******/
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> le(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcleq_u64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> le(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcleq_s64(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch_bool<double, A> le(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcleq_f64(lhs, rhs);
}
/****** * gt *
******/
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> gt(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcgtq_u64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> gt(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcgtq_s64(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch_bool<double, A> gt(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcgtq_f64(lhs, rhs);
}
/****** * ge *
******/
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> ge(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcgeq_u64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch_bool<T, A> ge(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcgeq_s64(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch_bool<double, A> ge(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vcgeq_f64(lhs, rhs);
}
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<neon64>) noexcept
{ using register_type = typename batch_bool<T_out, A>::register_type; return register_type(self);
}
/*************** * bitwise_and *
***************/
template <class A>
XSIMD_INLINE batch<double, A> bitwise_and(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vreinterpretq_f64_u64(vandq_u64(vreinterpretq_u64_f64(lhs),
vreinterpretq_u64_f64(rhs)));
}
template <class A>
XSIMD_INLINE batch_bool<double, A> bitwise_and(batch_bool<double, A> const& lhs, batch_bool<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vandq_u64(lhs, rhs);
}
/************** * bitwise_or *
**************/
template <class A>
XSIMD_INLINE batch<double, A> bitwise_or(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vreinterpretq_f64_u64(vorrq_u64(vreinterpretq_u64_f64(lhs),
vreinterpretq_u64_f64(rhs)));
}
template <class A>
XSIMD_INLINE batch_bool<double, A> bitwise_or(batch_bool<double, A> const& lhs, batch_bool<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vorrq_u64(lhs, rhs);
}
/*************** * bitwise_xor *
***************/
template <class A>
XSIMD_INLINE batch<double, A> bitwise_xor(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vreinterpretq_f64_u64(veorq_u64(vreinterpretq_u64_f64(lhs),
vreinterpretq_u64_f64(rhs)));
}
template <class A>
XSIMD_INLINE batch_bool<double, A> bitwise_xor(batch_bool<double, A> const& lhs, batch_bool<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return veorq_u64(lhs, rhs);
}
/******* * neq *
*******/
template <class A>
XSIMD_INLINE batch_bool<double, A> neq(batch_bool<double, A> const& lhs, batch_bool<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return bitwise_xor(lhs, rhs, A {});
}
/*************** * bitwise_not *
***************/
template <class A>
XSIMD_INLINE batch<double, A> bitwise_not(batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vreinterpretq_f64_u32(vmvnq_u32(vreinterpretq_u32_f64(rhs)));
}
template <class A>
XSIMD_INLINE batch_bool<double, A> bitwise_not(batch_bool<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return detail::bitwise_not_u64(rhs);
}
#ifdef __ARM_FEATURE_FMA template <class A>
XSIMD_INLINE batch<double, A> fma(batch<double, A> const& x, batch<double, A> const& y, batch<double, A> const& z, requires_arch<neon64>) noexcept
{ return vfmaq_f64(z, x, y);
}
template <class A>
XSIMD_INLINE batch<double, A> fms(batch<double, A> const& x, batch<double, A> const& y, batch<double, A> const& z, requires_arch<neon64>) noexcept
{ return vfmaq_f64(-z, x, y);
} #endif
/********* * haddp *
*********/
template <class A>
XSIMD_INLINE batch<double, A> haddp(const batch<double, A>* row, requires_arch<neon64>) noexcept
{ return vpaddq_f64(row[0], row[1]);
}
/********** * insert *
**********/
template <class A, size_t I>
XSIMD_INLINE batch<double, A> insert(batch<double, A> const& self, double val, index<I>, requires_arch<neon64>) noexcept
{ return vsetq_lane_f64(val, self, I);
}
template <class A>
XSIMD_INLINE batch<double, A> select(batch_bool<double, A> const& cond, batch<double, A> const& a, batch<double, A> const& b, requires_arch<neon64>) noexcept
{ return vbslq_f64(cond, a, b);
}
template <class A, bool... b>
XSIMD_INLINE batch<double, A> select(batch_bool_constant<double, A, b...> const&,
batch<double, A> const& true_br,
batch<double, A> const& false_br,
requires_arch<neon64>) noexcept
{ return select(batch_bool<double, A> { b... }, true_br, false_br, neon64 {});
}
/********** * zip_lo *
**********/ template <class A, class T, detail::enable_sized_unsigned_t<T, 1> = 0>
XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_u8(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 1> = 0>
XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_s8(lhs, rhs);
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 2> = 0>
XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_u16(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 2> = 0>
XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_s16(lhs, rhs);
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 4> = 0>
XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_u32(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 4> = 0>
XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_s32(lhs, rhs);
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_u64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_s64(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch<float, A> zip_lo(batch<float, A> const& lhs, batch<float, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_f32(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch<double, A> zip_lo(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip1q_f64(lhs, rhs);
}
/********** * zip_hi *
**********/
template <class A, class T, detail::enable_sized_unsigned_t<T, 1> = 0>
XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_u8(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 1> = 0>
XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_s8(lhs, rhs);
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 2> = 0>
XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_u16(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 2> = 0>
XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_s16(lhs, rhs);
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 4> = 0>
XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_u32(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 4> = 0>
XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_s32(lhs, rhs);
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_u64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_s64(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch<float, A> zip_hi(batch<float, A> const& lhs, batch<float, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_f32(lhs, rhs);
}
template <class A>
XSIMD_INLINE batch<double, A> zip_hi(batch<double, A> const& lhs, batch<double, A> const& rhs, requires_arch<neon64>) noexcept
{ return vzip2q_f64(lhs, rhs);
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> bitwise_rshift(batch<T, A> const& lhs, int n, requires_arch<neon64>) noexcept
{ return bitwise_rshift<A>(lhs, n, neon {});
}
template <class A, class T, detail::enable_sized_unsigned_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> bitwise_rshift(batch<T, A> const& lhs, batch<as_signed_integer_t<T>, A> const& rhs, requires_arch<neon64>) noexcept
{ return vshlq_u64(lhs, vnegq_s64(rhs));
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> bitwise_rshift(batch<T, A> const& lhs, int n, requires_arch<neon64>) noexcept
{ return bitwise_rshift<A>(lhs, n, neon {});
}
template <class A, class T, detail::enable_sized_signed_t<T, 8> = 0>
XSIMD_INLINE batch<T, A> bitwise_rshift(batch<T, A> const& lhs, batch<T, A> const& rhs, requires_arch<neon64>) noexcept
{ return vshlq_s64(lhs, vnegq_s64(rhs));
}
template <class V>
V apply(float64x2_t rhs) const
{ using func_type = V (*)(float64x2_t); auto func = xsimd::detail::get<func_type>(m_func); return func(rhs);
}
};
}
template <class A, class R>
XSIMD_INLINE batch<R, A> bitwise_cast(batch<double, A> const& arg, batch<R, A> const&, requires_arch<neon64>) noexcept
{ using caster_type = detail::bitwise_caster_neon64<float64x2_t,
uint8x16_t, int8x16_t,
uint16x8_t, int16x8_t,
uint32x4_t, int32x4_t,
uint64x2_t, int64x2_t,
float32x4_t>; const caster_type caster = {
std::make_tuple(wrap::vreinterpretq_u8_f64, wrap::vreinterpretq_s8_f64, wrap::vreinterpretq_u16_f64, wrap::vreinterpretq_s16_f64,
wrap::vreinterpretq_u32_f64, wrap::vreinterpretq_s32_f64, wrap::vreinterpretq_u64_f64, wrap::vreinterpretq_s64_f64,
wrap::vreinterpretq_f32_f64)
}; using src_register_type = typename batch<double, A>::register_type; using dst_register_type = typename batch<R, A>::register_type; return caster.apply<dst_register_type>(src_register_type(arg));
}
template <class A>
XSIMD_INLINE batch<double, A> bitwise_cast(batch<double, A> const& arg, batch<double, A> const&, requires_arch<neon64>) noexcept
{ return arg;
}
/********* * isnan *
*********/
template <class A>
XSIMD_INLINE batch_bool<double, A> isnan(batch<double, A> const& arg, requires_arch<neon64>) noexcept
{ return !(arg == arg);
}
/**************** * rotate_left *
****************/ template <size_t N, class A>
XSIMD_INLINE batch<double, A> rotate_left(batch<double, A> const& a, requires_arch<neon64>) noexcept
{ return vextq_f64(a, a, N);
}
}
template <typename T, class A, T... Values> struct batch_constant;
namespace kernel
{ /********************* * swizzle (dynamic) *
*********************/ template <class A>
XSIMD_INLINE batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch<uint8_t, A> idx,
requires_arch<neon64>) noexcept
{ return vqtbl1q_u8(self, idx);
}
template <class A>
XSIMD_INLINE batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch<uint8_t, A> idx,
requires_arch<neon64>) noexcept
{ return vqtbl1q_s8(self, idx);
}
template <class A>
XSIMD_INLINE batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self,
batch<uint16_t, A> idx,
requires_arch<neon64>) noexcept
{ using batch_type = batch<uint8_t, A>; using index_type = batch<uint8_t, A>; return vreinterpretq_u16_u8(swizzle(batch_type(vreinterpretq_u8_u16(self)),
index_type(vreinterpretq_u8_u16(idx * 0x0202 + 0x0100)),
neon64 {}));
}
template <class A>
XSIMD_INLINE batch<int16_t, A> swizzle(batch<int16_t, A> const& self,
batch<uint16_t, A> idx,
requires_arch<neon64>) noexcept
{ return bitwise_cast<int16_t>(swizzle(bitwise_cast<uint16_t>(self), idx, neon64 {}));
}
template <class A>
XSIMD_INLINE batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self,
batch<uint32_t, A> idx,
requires_arch<neon64>) noexcept
{ using batch_type = batch<uint8_t, A>; using index_type = batch<uint8_t, A>; return vreinterpretq_u32_u8(swizzle(batch_type(vreinterpretq_u8_u32(self)),
index_type(vreinterpretq_u8_u32(idx * 0x04040404 + 0x03020100)),
neon64 {}));
}
template <class A>
XSIMD_INLINE batch<int32_t, A> swizzle(batch<int32_t, A> const& self,
batch<uint32_t, A> idx,
requires_arch<neon64>) noexcept
{ return bitwise_cast<int32_t>(swizzle(bitwise_cast<uint32_t>(self), idx, neon64 {}));
}
template <class A>
XSIMD_INLINE batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self,
batch<uint64_t, A> idx,
requires_arch<neon64>) noexcept
{ using batch_type = batch<uint8_t, A>; using index_type = batch<uint8_t, A>; return vreinterpretq_u64_u8(swizzle(batch_type(vreinterpretq_u8_u64(self)),
index_type(vreinterpretq_u8_u64(idx * 0x0808080808080808ull + 0x0706050403020100ull)),
neon64 {}));
}
template <class A>
XSIMD_INLINE batch<int64_t, A> swizzle(batch<int64_t, A> const& self,
batch<uint64_t, A> idx,
requires_arch<neon64>) noexcept
{ return bitwise_cast<int64_t>(swizzle(bitwise_cast<uint64_t>(self), idx, neon64 {}));
}
template <class A>
XSIMD_INLINE batch<float, A> swizzle(batch<float, A> const& self,
batch<uint32_t, A> idx,
requires_arch<neon64>) noexcept
{ return bitwise_cast<float>(swizzle(bitwise_cast<uint32_t>(self), idx, neon64 {}));
}
template <class A>
XSIMD_INLINE batch<double, A> swizzle(batch<double, A> const& self,
batch<uint64_t, A> idx,
requires_arch<neon64>) noexcept
{ return bitwise_cast<double>(swizzle(bitwise_cast<uint64_t>(self), idx, neon64 {}));
}
namespace detail
{ using ::xsimd::batch_constant; using ::xsimd::detail::integer_sequence; using ::xsimd::detail::make_integer_sequence;
template <class CB1, class CB2, class IS> struct index_burst_impl;
template <typename T1, class A, typename T2, T2... V,
T2... incr> struct index_burst_impl<batch_constant<T1, A>, batch_constant<T2, A, V...>,
integer_sequence<T2, incr...>>
{ using type = batch_constant<T2, A, V...>;
};
template <typename T1, class A, T1 V0, T1... V1, typename T2, T2... V2, T2... incr> struct index_burst_impl<batch_constant<T1, A, V0, V1...>, batch_constant<T2, A, V2...>,
integer_sequence<T2, incr...>>
{ using next_input = batch_constant<T1, A, V1...>; using next_output = batch_constant<T2, A, V2..., (V0 + incr)...>; using type = typename index_burst_impl<next_input, next_output, integer_sequence<T2, incr...>>::type;
};
template <class B, class T> struct index_burst;
template <typename Tp, class A, Tp... V, typename T> struct index_burst<batch_constant<Tp, A, V...>, T>
{ static constexpr size_t mul = sizeof(Tp) / sizeof(T); using input = batch_constant<Tp, A, (mul * V)...>; using output = batch_constant<T, A>; using type = typename index_burst_impl<input, output, make_integer_sequence<T, mul>>::type;
};
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.