1313
1414#include " xsimd_numerical_constant.hpp"
1515#include " xsimd_rounding.hpp"
16+ #include " ../types/xsimd_traits.hpp"
1617
1718namespace xsimd
1819{
@@ -63,6 +64,126 @@ namespace xsimd
6364 * Basic operations implementation *
6465 ***********************************/
6566
67+ namespace detail
68+ {
69+
70+ template <class T >
71+ struct get_batch_value_type
72+ {
73+ using type = T;
74+ };
75+
76+ template <class T , std::size_t N>
77+ struct get_batch_value_type <batch<T, N>>
78+ {
79+ using type = T;
80+ };
81+
82+ template <class B >
83+ using get_batch_value_type_t = typename get_batch_value_type<B>::type;
84+
85+ template <class B , bool is_int = std::is_integral<get_batch_value_type_t <B>>::value>
86+ struct remainder_kernel
87+ {
88+ using batch_type = B;
89+ using size_type = std::size_t ;
90+ static constexpr size_type double_size = batch_type::size;
91+
92+ static inline batch_type fmod (const batch_type& x, const batch_type& y)
93+ {
94+ return fnma (trunc (x / y), y, x);
95+ }
96+
97+ static inline batch_type remainder (const batch_type& x, const batch_type& y)
98+ {
99+ return fnma (nearbyint (x / y), y, x);
100+ }
101+
102+ template <class IB >
103+ static inline batch_type to_double (const IB& b, size_type offset)
104+ {
105+ batch_type res;
106+ for (size_type i = 0 ; i < double_size; ++i)
107+ {
108+ res[i] = b[i + offset];
109+ }
110+ return res;
111+ }
112+
113+ template <class IB >
114+ static inline void to_int (const batch_type& src, IB& dst, size_type offset)
115+ {
116+ for (size_type i = 0 ; i < double_size; ++i)
117+ {
118+ dst[i + offset] = src[i];
119+ }
120+ }
121+ };
122+
123+ template <>
124+ struct remainder_kernel <double , false >
125+ {
126+ using size_type = std::size_t ;
127+ static inline double fmod (double x, double y)
128+ {
129+ return std::fmod (x, y);
130+ }
131+
132+ static inline double remainder (double x, double y)
133+ {
134+ return std::remainder (x, y);
135+ }
136+
137+ template <class IB >
138+ static inline double to_double (const IB& b, size_type offset)
139+ {
140+ double res = b[offset];
141+ return res;
142+ }
143+
144+ template <class IB >
145+ static inline void to_int (double src, IB& dst, size_type offset)
146+ {
147+ dst[offset] = src;
148+ }
149+ };
150+
151+ template <class B >
152+ struct remainder_kernel <B, true >
153+ {
154+ using batch_type = B;
155+ using double_batch = typename simd_traits<double >::type;
156+ using double_kernel = remainder_kernel<double_batch>;
157+ using size_type = std::size_t ;
158+ static constexpr size_type int_size = B::size;
159+ static constexpr size_type double_size = simd_traits<double >::size;
160+
161+ static inline batch_type fmod (const batch_type& x, const batch_type& y)
162+ {
163+ batch_type res;
164+ for (size_type i = 0 ; i < int_size; i += double_size)
165+ {
166+ double_batch tmp = double_kernel::fmod (double_kernel::to_double (x, i),
167+ double_kernel::to_double (y, i));
168+ double_kernel::to_int (tmp, res, i);
169+ }
170+ return res;
171+ }
172+
173+ static inline batch_type remainder (const batch_type& x, const batch_type& y)
174+ {
175+ batch_type res;
176+ for (size_type i = 0 ; i < int_size; i += double_size)
177+ {
178+ double_batch tmp = double_kernel::remainder (double_kernel::to_double (x, i),
179+ double_kernel::to_double (y, i));
180+ double_kernel::to_int (tmp, res, i);
181+ }
182+ return res;
183+ }
184+ };
185+ }
186+
66187 /* *
67188 * @brief Computes the floating-point remainder of the division operation \c x/y.
68189 *
@@ -76,7 +197,7 @@ namespace xsimd
76197 template <class B >
77198 inline batch_type_t <B> fmod (const simd_base<B>& x, const simd_base<B>& y)
78199 {
79- return fnma ( trunc (x / y ), y, x );
200+ return detail::remainder_kernel<B>:: fmod ( x ( ), y () );
80201 }
81202
82203 /* *
@@ -94,7 +215,7 @@ namespace xsimd
94215 template <class B >
95216 inline batch_type_t <B> remainder (const simd_base<B>& x, const simd_base<B>& y)
96217 {
97- return fnma ( nearbyint (x / y ), y, x );
218+ return detail::remainder_kernel<B>:: remainder ( x ( ), y () );
98219 }
99220
100221 /* *
@@ -139,16 +260,12 @@ namespace xsimd
139260
140261 static inline batch_type next (const batch_type& b) noexcept
141262 {
142- return select (b != maxvalue<batch_type>(),
143- b + T (1 ),
144- b);
263+ return b;
145264 }
146265
147266 static inline batch_type prev (const batch_type& b) noexcept
148267 {
149- select (b != minvalue<batch_type>(),
150- b - T (1 ),
151- b);
268+ return b;
152269 }
153270 };
154271
@@ -216,6 +333,34 @@ namespace xsimd
216333 return (x - x) == batch_type_t <B>(0 .);
217334 }
218335
336+ namespace detail
337+ {
338+ template <class T , std::size_t N, bool is_int = std::is_integral<T>::value>
339+ struct isinf_kernel
340+ {
341+ using batch_type = batch<T, N>;
342+ using batch_bool_type = typename simd_batch_traits<batch_type>::batch_bool_type;
343+
344+ static inline batch_bool_type run (const batch_type& x)
345+ {
346+ return abs (x) == ::xsimd::infinity<batch_type_t <batch_type>>();
347+ }
348+ };
349+
350+ template <class T , std::size_t N>
351+ struct isinf_kernel <T, N, true >
352+ {
353+
354+ using batch_type = batch<T, N>;
355+ using batch_bool_type = typename simd_batch_traits<batch_type>::batch_bool_type;
356+
357+ static inline batch_bool_type run (const batch_type&)
358+ {
359+ return batch_bool_type (false );
360+ }
361+ };
362+ }
363+
219364 /* *
220365 * Determines if the scalars in the given batch \c x are positive
221366 * or negative infinity.
@@ -226,7 +371,9 @@ namespace xsimd
226371 inline typename simd_batch_traits<B>::batch_bool_type
227372 isinf (const simd_base<B>& x)
228373 {
229- return abs (x) == infinity<batch_type_t <B>>();
374+ using kernel_type = detail::isinf_kernel<typename batch_type_t <B>::value_type, batch_type_t <B>::size>;
375+ return kernel_type::run (x ());
376+ // return abs(x) == infinity<batch_type_t<B>>();
230377 }
231378
232379 template <class B >
0 commit comments