Skip to content

Commit b140981

Browse files
committed
Fixed basic math functions for integral batches
1 parent 547f7e4 commit b140981

File tree

4 files changed

+514
-285
lines changed

4 files changed

+514
-285
lines changed

include/xsimd/math/xsimd_basic_math.hpp

Lines changed: 125 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "xsimd_numerical_constant.hpp"
1515
#include "xsimd_rounding.hpp"
16+
#include "../types/xsimd_traits.hpp"
1617

1718
namespace 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

include/xsimd/math/xsimd_numerical_constant.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,32 @@ namespace xsimd
297297
}
298298
};
299299

300+
template <class T>
301+
struct minvalue_common
302+
{
303+
static constexpr T get_value() noexcept
304+
{
305+
return std::numeric_limits<T>::min();
306+
}
307+
};
308+
309+
template <>
310+
struct minvalue_impl<int8_t> : minvalue_common<int8_t> {};
311+
template <>
312+
struct minvalue_impl<uint8_t> : minvalue_common<uint8_t> {};
313+
template <>
314+
struct minvalue_impl<int16_t> : minvalue_common<int16_t> {};
315+
template <>
316+
struct minvalue_impl<uint16_t> : minvalue_common<uint16_t> {};
317+
template <>
318+
struct minvalue_impl<int32_t> : minvalue_common<int32_t> {};
319+
template <>
320+
struct minvalue_impl<uint32_t> : minvalue_common<uint32_t> {};
321+
template <>
322+
struct minvalue_impl<int64_t> : minvalue_common<int64_t> {};
323+
template <>
324+
struct minvalue_impl<uint64_t> : minvalue_common<uint64_t> {};
325+
300326
template <>
301327
struct minvalue_impl<float>
302328
{

0 commit comments

Comments
 (0)