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