1 | /* Copyright (C) 2013-2014 Povilas Kanapickas <povilas@radix.lt> |
2 | |
3 | Distributed under the Boost Software License, Version 1.0. |
4 | (See accompanying file LICENSE_1_0.txt or copy at |
5 | http://www.boost.org/LICENSE_1_0.txt) |
6 | */ |
7 | |
8 | #ifndef LIBSIMDPP_SIMDPP_DETAIL_INSN_F_ABS_H |
9 | #define LIBSIMDPP_SIMDPP_DETAIL_INSN_F_ABS_H |
10 | |
11 | #ifndef LIBSIMDPP_SIMD_H |
12 | #error "This file must be included through simd.h" |
13 | #endif |
14 | |
15 | #include <simdpp/types.h> |
16 | #include <simdpp/core/bit_and.h> |
17 | #include <simdpp/detail/null/math.h> |
18 | #include <simdpp/detail/vector_array_macros.h> |
19 | |
20 | namespace simdpp { |
21 | namespace SIMDPP_ARCH_NAMESPACE { |
22 | namespace detail { |
23 | namespace insn { |
24 | |
25 | static SIMDPP_INL |
26 | float32<4> i_fabs(const float32<4>& a) |
27 | { |
28 | #if SIMDPP_USE_NULL || SIMDPP_USE_NEON_NO_FLT_SP |
29 | return detail::null::abs(a); |
30 | #elif SIMDPP_USE_SSE2 || SIMDPP_USE_MSA |
31 | return bit_and(a, 0x7fffffff); |
32 | #elif SIMDPP_USE_NEON_FLT_SP |
33 | return vabsq_f32(a.native()); |
34 | #elif SIMDPP_USE_ALTIVEC |
35 | return vec_abs(a.native()); |
36 | #endif |
37 | } |
38 | |
39 | #if SIMDPP_USE_AVX |
40 | static SIMDPP_INL |
41 | float32<8> i_fabs(const float32<8>& a) |
42 | { |
43 | return bit_and(a, 0x7fffffff); |
44 | } |
45 | #endif |
46 | |
47 | #if SIMDPP_USE_AVX512F |
48 | static SIMDPP_INL |
49 | float32<16> i_fabs(const float32<16>& a) |
50 | { |
51 | // TODO: maybe cmp_lt is better, but what to do with negative zero? |
52 | return bit_and(a, 0x7fffffff); |
53 | } |
54 | #endif |
55 | |
56 | // ----------------------------------------------------------------------------- |
57 | |
58 | static SIMDPP_INL |
59 | float64x2 i_fabs(const float64<2>& a) |
60 | { |
61 | #if SIMDPP_USE_SSE2 || SIMDPP_USE_MSA |
62 | return bit_and(a, 0x7fffffffffffffff); |
63 | #elif SIMDPP_USE_NEON64 |
64 | return vabsq_f64(a.native()); |
65 | #elif SIMDPP_USE_VSX_206 |
66 | return vec_abs(a.native()); |
67 | #elif SIMDPP_USE_NULL || SIMDPP_USE_NEON32 || SIMDPP_USE_ALTIVEC |
68 | return detail::null::abs(a); |
69 | #endif |
70 | } |
71 | |
72 | #if SIMDPP_USE_AVX |
73 | static SIMDPP_INL |
74 | float64x4 i_fabs(const float64<4>& a) |
75 | { |
76 | return bit_and(a, 0x7fffffffffffffff); |
77 | } |
78 | #endif |
79 | |
80 | #if SIMDPP_USE_AVX512F |
81 | static SIMDPP_INL |
82 | float64<8> i_fabs(const float64<8>& a) |
83 | { |
84 | // TODO: maybe cmp_lt is better, but what to do with negative zero? |
85 | return bit_and(a, 0x7fffffffffffffff); |
86 | } |
87 | #endif |
88 | |
89 | // ----------------------------------------------------------------------------- |
90 | |
91 | template<class V> SIMDPP_INL |
92 | V i_fabs(const V& a) |
93 | { |
94 | SIMDPP_VEC_ARRAY_IMPL1(V, i_fabs, a) |
95 | } |
96 | |
97 | } // namespace insn |
98 | } // namespace detail |
99 | } // namespace SIMDPP_ARCH_NAMESPACE |
100 | } // namespace simdpp |
101 | |
102 | #endif |
103 | |
104 | |