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_LOGICAL_HPP 13 #define XSIMD_GENERIC_LOGICAL_HPP 14 15 #include "./xsimd_generic_details.hpp" 16 17 namespace xsimd 18 { 19 20 namespace kernel 21 { 22 23 using namespace types; 24 25 // ge 26 template <class A, class T> ge(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)27 inline batch_bool<T, A> ge(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept 28 { 29 return other <= self; 30 } 31 32 // gt 33 template <class A, class T> gt(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)34 inline batch_bool<T, A> gt(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept 35 { 36 return other < self; 37 } 38 39 // is_even 40 template <class A, class T> is_even(batch<T,A> const & self,requires_arch<generic>)41 inline batch_bool<T, A> is_even(batch<T, A> const& self, requires_arch<generic>) noexcept 42 { 43 return is_flint(self * T(0.5)); 44 } 45 46 // is_flint 47 template <class A, class T> is_flint(batch<T,A> const & self,requires_arch<generic>)48 inline batch_bool<T, A> is_flint(batch<T, A> const& self, requires_arch<generic>) noexcept 49 { 50 auto frac = select(isnan(self - self), constants::nan<batch<T, A>>(), self - trunc(self)); 51 return frac == T(0.); 52 } 53 54 // is_odd 55 template <class A, class T> is_odd(batch<T,A> const & self,requires_arch<generic>)56 inline batch_bool<T, A> is_odd(batch<T, A> const& self, requires_arch<generic>) noexcept 57 { 58 return is_even(self - T(1.)); 59 } 60 61 // isinf 62 template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type> isinf(batch<T,A> const &,requires_arch<generic>)63 inline batch_bool<T, A> isinf(batch<T, A> const&, requires_arch<generic>) noexcept 64 { 65 return batch_bool<T, A>(false); 66 } 67 template <class A> isinf(batch<float,A> const & self,requires_arch<generic>)68 inline batch_bool<float, A> isinf(batch<float, A> const& self, requires_arch<generic>) noexcept 69 { 70 return abs(self) == std::numeric_limits<float>::infinity(); 71 } 72 template <class A> isinf(batch<double,A> const & self,requires_arch<generic>)73 inline batch_bool<double, A> isinf(batch<double, A> const& self, requires_arch<generic>) noexcept 74 { 75 return abs(self) == std::numeric_limits<double>::infinity(); 76 } 77 78 // isfinite 79 template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type> isfinite(batch<T,A> const &,requires_arch<generic>)80 inline batch_bool<T, A> isfinite(batch<T, A> const&, requires_arch<generic>) noexcept 81 { 82 return batch_bool<T, A>(true); 83 } 84 template <class A> isfinite(batch<float,A> const & self,requires_arch<generic>)85 inline batch_bool<float, A> isfinite(batch<float, A> const& self, requires_arch<generic>) noexcept 86 { 87 return (self - self) == 0; 88 } 89 template <class A> isfinite(batch<double,A> const & self,requires_arch<generic>)90 inline batch_bool<double, A> isfinite(batch<double, A> const& self, requires_arch<generic>) noexcept 91 { 92 return (self - self) == 0; 93 } 94 95 // isnan 96 template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type> isnan(batch<T,A> const &,requires_arch<generic>)97 inline batch_bool<T, A> isnan(batch<T, A> const&, requires_arch<generic>) noexcept 98 { 99 return batch_bool<T, A>(false); 100 } 101 102 // le 103 template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type> le(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)104 inline batch_bool<T, A> le(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept 105 { 106 return (self < other) || (self == other); 107 } 108 109 // neq 110 template <class A, class T> neq(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)111 inline batch_bool<T, A> neq(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept 112 { 113 return !(other == self); 114 } 115 116 // logical_and 117 template <class A, class T> logical_and(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)118 inline batch<T, A> logical_and(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept 119 { 120 return detail::apply([](T x, T y) noexcept 121 { return x && y; }, 122 self, other); 123 } 124 125 // logical_or 126 template <class A, class T> logical_or(batch<T,A> const & self,batch<T,A> const & other,requires_arch<generic>)127 inline batch<T, A> logical_or(batch<T, A> const& self, batch<T, A> const& other, requires_arch<generic>) noexcept 128 { 129 return detail::apply([](T x, T y) noexcept 130 { return x || y; }, 131 self, other); 132 } 133 } 134 } 135 136 #endif 137