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_FMSUB_H
9#define LIBSIMDPP_SIMDPP_DETAIL_INSN_F_FMSUB_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/detail/null/math.h>
17#include <simdpp/detail/not_implemented.h>
18
19namespace simdpp {
20namespace SIMDPP_ARCH_NAMESPACE {
21namespace detail {
22namespace insn {
23
24static SIMDPP_INL
25float32<4> i_fmsub(const float32<4>& a, const float32<4>& b,
26 const float32<4>& c)
27{
28#if SIMDPP_USE_NULL
29 return detail::null::fmsub(a, b, c);
30#elif SIMDPP_USE_FMA3
31 return _mm_fmsub_ps(a.native(), b.native(), c.native());
32#elif SIMDPP_USE_FMA4
33 return _mm_msub_ps(a.native(), b.native(), c.native());
34#elif SIMDPP_USE_NEON64
35 // FIXME: also in vfpv4
36 return vfmsq_f32(a.native(), b.native(), c.native());
37#elif SIMDPP_USE_MSA
38 return __msa_fmsub_w(c.native(), a.native(), b.native());
39#else
40 return SIMDPP_NOT_IMPLEMENTED3(a, b, c);
41#endif
42}
43
44#if SIMDPP_USE_AVX
45static SIMDPP_INL
46float32<8> i_fmsub(const float32<8>& a, const float32<8>& b,
47 const float32<8>& c)
48{
49#if SIMDPP_USE_FMA3
50 return _mm256_fmsub_ps(a.native(), b.native(), c.native());
51#elif SIMDPP_USE_FMA4
52 return _mm256_msub_ps(a.native(), b.native(), c.native());
53#else
54 return SIMDPP_NOT_IMPLEMENTED3(a, b, c);
55#endif
56}
57#endif
58
59#if SIMDPP_USE_AVX512F
60static SIMDPP_INL
61float32<16> i_fmsub(const float32<16>& a, const float32<16>& b,
62 const float32<16>& c)
63{
64 return _mm512_fmsub_ps(a.native(), b.native(), c.native());
65}
66#endif
67
68// -----------------------------------------------------------------------------
69
70static SIMDPP_INL
71float64<2> i_fmsub(const float64<2>& a, const float64<2>& b,
72 const float64<2>& c)
73{
74#if SIMDPP_USE_NULL
75 return detail::null::fmsub(a, b, c);
76#elif SIMDPP_USE_FMA3
77 return _mm_fmsub_pd(a.native(), b.native(), c.native());
78#elif SIMDPP_USE_FMA4
79 return _mm_msub_pd(a.native(), b.native(), c.native());
80#elif SIMDPP_USE_NEON64
81 // FIXME: also in vfpv4
82 return vfmsq_f64(a.native(), b.native(), c.native());
83#elif SIMDPP_USE_MSA
84 return __msa_fmsub_d(c.native(), a.native(), b.native());
85#else
86 return SIMDPP_NOT_IMPLEMENTED3(a, b, c);
87#endif
88}
89
90#if SIMDPP_USE_AVX
91static SIMDPP_INL
92float64<4> i_fmsub(const float64<4>& a, const float64<4>& b,
93 const float64<4>& c)
94{
95#if SIMDPP_USE_FMA3
96 return _mm256_fmsub_pd(a.native(), b.native(), c.native());
97#elif SIMDPP_USE_FMA4
98 return _mm256_msub_pd(a.native(), b.native(), c.native());
99#else
100 return SIMDPP_NOT_IMPLEMENTED3(a, b, c);
101#endif
102}
103#endif
104
105#if SIMDPP_USE_AVX512F
106static SIMDPP_INL
107float64<8> i_fmsub(const float64<8>& a, const float64<8>& b,
108 const float64<8>& c)
109{
110 return _mm512_fmsub_pd(a.native(), b.native(), c.native());
111}
112#endif
113
114// -----------------------------------------------------------------------------
115
116template<class V> SIMDPP_INL
117V i_fmsub(const V& a, const V& b, const V& c)
118{
119 SIMDPP_VEC_ARRAY_IMPL3(V, i_fmsub, a, b, c);
120}
121
122} // namsepace insn
123} // namespace detail
124} // namespace SIMDPP_ARCH_NAMESPACE
125} // namespace simdpp
126
127#endif
128
129