Eigen-Contrib  5.0.1
 
Loading...
Searching...
No Matches
SpecialFunctions.h
1// SPDX-FileCopyrightText: The Eigen Authors
2// SPDX-License-Identifier: MPL-2.0
3
4#ifndef EIGEN_NEON_SPECIALFUNCTIONS_H
5#define EIGEN_NEON_SPECIALFUNCTIONS_H
6
7namespace Eigen {
8namespace internal {
9
10#if EIGEN_ARCH_ARM
11// For x = n * 2^-149, n < 2^23, erf(x) = (2/sqrt(pi))*x to float precision.
12// round((2/sqrt(pi))*2^31) = 2423175810; the coefficient error contributes < 0.000319 ULP.
13// Integer rounding avoids ARMv7 NEON's input/output flushing. The result bits also cover the first normal binade.
14EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet2i perf_subnormal_significands(const Packet2i& n) {
15 return vreinterpret_s32_u32(vrshrn_n_u64(vmull_u32(vreinterpret_u32_s32(n), vdup_n_u32(2423175810u)), 31));
16}
17
18EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4i perf_subnormal_significands(const Packet4i& n) {
19 return vcombine_s32(perf_subnormal_significands(Packet2i(vget_low_s32(n))),
20 perf_subnormal_significands(Packet2i(vget_high_s32(n))));
21}
22
23template <typename Packet>
24EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet perf_neon(const Packet& x) {
25 using PacketI = typename unpacket_traits<Packet>::integer_packet;
26 const Packet result = generic_fast_erf<float>::run(x);
27 const PacketI bits = preinterpret<PacketI>(x);
28 const PacketI magnitude = pand(bits, pset1<PacketI>(0x7fffffff));
29 const PacketI sign = pxor(bits, magnitude);
30 const PacketI subnormal = pcmp_lt(magnitude, pset1<PacketI>(0x00800000));
31 const PacketI recovered = por(perf_subnormal_significands(magnitude), sign);
32 return pselect(preinterpret<Packet>(subnormal), preinterpret<Packet>(recovered), result);
33}
34
35template <>
36EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet2f perf<Packet2f>(const Packet2f& x) {
37 return perf_neon(x);
38}
39
40template <>
41EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4f perf<Packet4f>(const Packet4f& x) {
42 return perf_neon(x);
43}
44#endif
45
46#if EIGEN_ARCH_ARM64 && EIGEN_HAS_ARM64_FP16
47
48#define NEON_HALF_TO_FLOAT_FUNCTIONS(METHOD) \
49 template <> \
50 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet8hf METHOD<Packet8hf>(const Packet8hf& x) { \
51 const Packet4f lo = METHOD<Packet4f>(vcvt_f32_f16(vget_low_f16(x))); \
52 const Packet4f hi = METHOD<Packet4f>(vcvt_f32_f16(vget_high_f16(x))); \
53 return vcombine_f16(vcvt_f16_f32(lo), vcvt_f16_f32(hi)); \
54 } \
55 \
56 template <> \
57 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4hf METHOD<Packet4hf>(const Packet4hf& x) { \
58 return vcvt_f16_f32(METHOD<Packet4f>(vcvt_f32_f16(x))); \
59 }
60
61NEON_HALF_TO_FLOAT_FUNCTIONS(perf)
62NEON_HALF_TO_FLOAT_FUNCTIONS(pndtri)
63
64#undef NEON_HALF_TO_FLOAT_FUNCTIONS
65#endif // EIGEN_ARCH_ARM64 && EIGEN_HAS_ARM64_FP16
66
67EIGEN_INSTANTIATE_SPECIAL_FUNCS_BF16(Packet4f, Packet4bf)
68
69} // namespace internal
70} // namespace Eigen
71
72#endif // EIGEN_NEON_SPECIALFUNCTIONS_H
Namespace containing all symbols from the Eigen library.