1 /***************************************************************************
2  * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
3  * Martin Renou                                                             *
4  * Copyright (c) QuantStack                                                 *
5  * Copyright (c) Serge Guelton                                              *
6  *                                                                          *
7  * Distributed under the terms of the BSD 3-Clause License.                 *
8  *                                                                          *
9  * The full license is in the file LICENSE, distributed with this software. *
10  ****************************************************************************/
11 
12 #ifndef XSIMD_GENERIC_ARITHMETIC_HPP
13 #define XSIMD_GENERIC_ARITHMETIC_HPP
14 
15 #include <complex>
16 #include <type_traits>
17 
18 #include "./xsimd_generic_details.hpp"
19 
20 namespace xsimd
21 {
22 
23     namespace kernel
24     {
25 
26         using namespace types;
27 
28         // bitwise_lshift
29         template <class A, class T, class /*=typename std::enable_if<std::is_integral<T>::value, void>::type*/>
bitwise_lshift(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)30         inline batch<T, A> bitwise_lshift(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept
31         {
32             return detail::apply([](T x, T y) noexcept
33                                  { return x << y; },
34                                  self, other);
35         }
36 
37         // bitwise_rshift
38         template <class A, class T, class /*=typename std::enable_if<std::is_integral<T>::value, void>::type*/>
bitwise_rshift(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)39         inline batch<T, A> bitwise_rshift(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept
40         {
41             return detail::apply([](T x, T y) noexcept
42                                  { return x >> y; },
43                                  self, other);
44         }
45 
46         // div
47         template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
div(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)48         inline batch<T, A> div(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept
49         {
50             return detail::apply([](T x, T y) noexcept -> T
51                                  { return x / y; },
52                                  self, other);
53         }
54 
55         // fma
56         template <class A, class T>
fma(batch<T,A> const & x,batch<T,A> const & y,batch<T,A> const & z,requires_arch<generic>)57         inline batch<T, A> fma(batch<T, A> const& x, batch<T, A> const& y, batch<T, A> const& z, requires_arch<generic>) noexcept
58         {
59             return x * y + z;
60         }
61 
62         template <class A, class T>
fma(batch<std::complex<T>,A> const & x,batch<std::complex<T>,A> const & y,batch<std::complex<T>,A> const & z,requires_arch<generic>)63         inline batch<std::complex<T>, A> fma(batch<std::complex<T>, A> const& x, batch<std::complex<T>, A> const& y, batch<std::complex<T>, A> const& z, requires_arch<generic>) noexcept
64         {
65             auto res_r = fms(x.real(), y.real(), fms(x.imag(), y.imag(), z.real()));
66             auto res_i = fma(x.real(), y.imag(), fma(x.imag(), y.real(), z.imag()));
67             return { res_r, res_i };
68         }
69 
70         // fms
71         template <class A, class T>
fms(batch<T,A> const & x,batch<T,A> const & y,batch<T,A> const & z,requires_arch<generic>)72         inline batch<T, A> fms(batch<T, A> const& x, batch<T, A> const& y, batch<T, A> const& z, requires_arch<generic>) noexcept
73         {
74             return x * y - z;
75         }
76 
77         template <class A, class T>
fms(batch<std::complex<T>,A> const & x,batch<std::complex<T>,A> const & y,batch<std::complex<T>,A> const & z,requires_arch<generic>)78         inline batch<std::complex<T>, A> fms(batch<std::complex<T>, A> const& x, batch<std::complex<T>, A> const& y, batch<std::complex<T>, A> const& z, requires_arch<generic>) noexcept
79         {
80             auto res_r = fms(x.real(), y.real(), fma(x.imag(), y.imag(), z.real()));
81             auto res_i = fma(x.real(), y.imag(), fms(x.imag(), y.real(), z.imag()));
82             return { res_r, res_i };
83         }
84 
85         // fnma
86         template <class A, class T>
fnma(batch<T,A> const & x,batch<T,A> const & y,batch<T,A> const & z,requires_arch<generic>)87         inline batch<T, A> fnma(batch<T, A> const& x, batch<T, A> const& y, batch<T, A> const& z, requires_arch<generic>) noexcept
88         {
89             return -x * y + z;
90         }
91 
92         template <class A, class T>
fnma(batch<std::complex<T>,A> const & x,batch<std::complex<T>,A> const & y,batch<std::complex<T>,A> const & z,requires_arch<generic>)93         inline batch<std::complex<T>, A> fnma(batch<std::complex<T>, A> const& x, batch<std::complex<T>, A> const& y, batch<std::complex<T>, A> const& z, requires_arch<generic>) noexcept
94         {
95             auto res_r = -fms(x.real(), y.real(), fma(x.imag(), y.imag(), z.real()));
96             auto res_i = -fma(x.real(), y.imag(), fms(x.imag(), y.real(), z.imag()));
97             return { res_r, res_i };
98         }
99 
100         // fnms
101         template <class A, class T>
fnms(batch<T,A> const & x,batch<T,A> const & y,batch<T,A> const & z,requires_arch<generic>)102         inline batch<T, A> fnms(batch<T, A> const& x, batch<T, A> const& y, batch<T, A> const& z, requires_arch<generic>) noexcept
103         {
104             return -x * y - z;
105         }
106 
107         template <class A, class T>
fnms(batch<std::complex<T>,A> const & x,batch<std::complex<T>,A> const & y,batch<std::complex<T>,A> const & z,requires_arch<generic>)108         inline batch<std::complex<T>, A> fnms(batch<std::complex<T>, A> const& x, batch<std::complex<T>, A> const& y, batch<std::complex<T>, A> const& z, requires_arch<generic>) noexcept
109         {
110             auto res_r = -fms(x.real(), y.real(), fms(x.imag(), y.imag(), z.real()));
111             auto res_i = -fma(x.real(), y.imag(), fma(x.imag(), y.real(), z.imag()));
112             return { res_r, res_i };
113         }
114 
115         // mul
116         template <class A, class T, class /*=typename std::enable_if<std::is_integral<T>::value, void>::type*/>
mul(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)117         inline batch<T, A> mul(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept
118         {
119             return detail::apply([](T x, T y) noexcept -> T
120                                  { return x * y; },
121                                  self, other);
122         }
123 
124     }
125 
126 }
127 
128 #endif
129