Skip to content

Commit 75c81ab

Browse files
committed
Add batch_traits and some missing functions
- Add `batch_traits` that unifies traits for scalar, `batch`, and `batch_bool`. - Treat `batch_bool` as its own mask type. - `batch_cast` can now be used on `batch_bool` (because why not?) - Add casts for scalar types - Simplify `abs` implementation.
1 parent 37e5d9f commit 75c81ab

File tree

4 files changed

+129
-71
lines changed

4 files changed

+129
-71
lines changed

docs/source/api/type_traits.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@ Type Traits
3232
===========
3333

3434
`xsimd` provides a few type traits to interact with scalar and batch types in an
35-
uniformeous manner.
35+
uniform manner.
3636

3737

38+
Combined traits:
39+
40+
+---------------------------------------+----------------------------------------------------+
41+
| :cpp:class:`batch_traits` | batch types and proprties |
42+
+---------------------------------------+----------------------------------------------------+
43+
3844
Type check:
3945

4046
+---------------------------------------+----------------------------------------------------+

include/xsimd/arch/xsimd_scalar.hpp

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -83,53 +83,16 @@ namespace xsimd
8383
using std::tgamma;
8484
using std::trunc;
8585

86-
XSIMD_INLINE signed char abs(signed char v)
86+
template <typename T>
87+
XSIMD_INLINE constexpr typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type
88+
abs(T v) noexcept
8789
{
8890
return v < 0 ? -v : v;
8991
}
9092

91-
namespace detail
92-
{
93-
// Use templated type here to prevent automatic instantiation that may
94-
// ends up in a warning
95-
template <typename char_type>
96-
XSIMD_INLINE char abs(char_type v, std::true_type)
97-
{
98-
return v;
99-
}
100-
template <typename char_type>
101-
XSIMD_INLINE char abs(char_type v, std::false_type)
102-
{
103-
return v < 0 ? -v : v;
104-
}
105-
}
106-
107-
XSIMD_INLINE char abs(char v)
108-
{
109-
return detail::abs(v, std::is_unsigned<char>::type {});
110-
}
111-
112-
XSIMD_INLINE short abs(short v)
113-
{
114-
return v < 0 ? -v : v;
115-
}
116-
XSIMD_INLINE unsigned char abs(unsigned char v)
117-
{
118-
return v;
119-
}
120-
XSIMD_INLINE unsigned short abs(unsigned short v)
121-
{
122-
return v;
123-
}
124-
XSIMD_INLINE unsigned int abs(unsigned int v)
125-
{
126-
return v;
127-
}
128-
XSIMD_INLINE unsigned long abs(unsigned long v)
129-
{
130-
return v;
131-
}
132-
XSIMD_INLINE unsigned long long abs(unsigned long long v)
93+
template <typename T>
94+
XSIMD_INLINE constexpr typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, T>::type
95+
abs(T v) noexcept
13396
{
13497
return v;
13598
}
@@ -251,7 +214,7 @@ namespace xsimd
251214
}
252215

253216
template <class T>
254-
XSIMD_INLINE typename std::enable_if<std::is_integral<T>::value, T>::type
217+
XSIMD_INLINE constexpr typename std::enable_if<std::is_integral<T>::value, T>::type
255218
bitwise_and(T x, T y) noexcept
256219
{
257220
return x & y;
@@ -1235,6 +1198,19 @@ namespace xsimd
12351198
{
12361199
return cond ? true_br : false_br;
12371200
}
1201+
1202+
template <class T>
1203+
XSIMD_INLINE constexpr bool batch_bool_cast(bool b) noexcept
1204+
{
1205+
return b;
1206+
}
1207+
1208+
template <class T_out, class T_in>
1209+
XSIMD_INLINE constexpr T_out batch_cast(T_in const& val) noexcept
1210+
{
1211+
static_assert(std::is_same<T_in, bool>::value ^ std::is_same<T_in, bool>::value, "cannot convert to/from bool; use !x or x != 0");
1212+
return static_cast<T_out>(val);
1213+
}
12381214
}
12391215

12401216
#endif

include/xsimd/types/xsimd_api.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,19 @@ namespace xsimd
264264
return kernel::batch_cast<A>(x, batch<T_out, A> {}, A {});
265265
}
266266

267+
/**
268+
* @ingroup batch_conversion
269+
*
270+
* Perform a static_cast from \c T_in to \c T_out on \c x.
271+
* @param x batch of \c T_in
272+
* @return \c x cast to \c T_out
273+
*/
274+
template <class T_out, class T_in, class A>
275+
XSIMD_INLINE batch_bool<T_out, A> batch_cast(batch_bool<T_in, A> const& x) noexcept
276+
{
277+
return batch_bool_cast<T_out>(x);
278+
}
279+
267280
/**
268281
* @ingroup batch_miscellaneous
269282
*

include/xsimd/types/xsimd_traits.hpp

Lines changed: 89 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -233,59 +233,133 @@ namespace xsimd
233233
/**
234234
* @ingroup batch_traits
235235
*
236-
* type traits that inherits from @c std::true_type for @c batch<...> types and from
237-
* @c std::false_type otherwise.
236+
* type traits that provide information about a batch or scalar type.
238237
*
239238
* @tparam T type to analyze.
240239
*/
240+
241241
template <class T>
242-
struct is_batch;
242+
struct batch_traits
243+
{
244+
using scalar_type = T; ///< T if scalar, or type of the scalar element for the batch T.
245+
using mask_type = bool; ///< Mask type for T: bool for scalars, or batch_bool for batch types.
243246

247+
static constexpr bool is_batch = false; ///< True if T is @c batch<...>.
248+
static constexpr bool is_batch_bool = false; ///< True if T is @c batch_bool<...>.
249+
static constexpr bool is_any_batch = false; ///< True if T is @c batch<...> or @c batch_bool<...>.
250+
static constexpr bool is_complex = detail::is_complex<T>::value; ///< True if T is complex or a batch of complex values.
251+
};
252+
253+
#if __cplusplus < 201703L
254+
template <class T>
255+
constexpr bool batch_traits<T>::is_batch;
244256
template <class T>
245-
struct is_batch : std::false_type
257+
constexpr bool batch_traits<T>::is_batch_bool;
258+
template <class T>
259+
constexpr bool batch_traits<T>::is_any_batch;
260+
template <class T>
261+
constexpr bool batch_traits<T>::is_complex;
262+
#endif
263+
264+
template <class T, class A>
265+
struct batch_traits<batch<T, A>>
246266
{
267+
using scalar_type = T;
268+
using mask_type = typename batch<T, A>::batch_bool_type;
269+
270+
static constexpr bool is_batch = true;
271+
static constexpr bool is_batch_bool = false;
272+
static constexpr bool is_any_batch = true;
273+
static constexpr bool is_complex = detail::is_complex<T>::value;
247274
};
248275

276+
#if __cplusplus < 201703L
277+
template <class T, class A>
278+
constexpr bool batch_traits<batch<T, A>>::is_batch;
279+
template <class T, class A>
280+
constexpr bool batch_traits<batch<T, A>>::is_batch_bool;
281+
template <class T, class A>
282+
constexpr bool batch_traits<batch<T, A>>::is_any_batch;
283+
template <class T, class A>
284+
constexpr bool batch_traits<batch<T, A>>::is_complex;
285+
#endif
286+
249287
template <class T, class A>
250-
struct is_batch<batch<T, A>> : std::true_type
288+
struct batch_traits<batch_bool<T, A>>
251289
{
290+
using scalar_type = bool;
291+
using mask_type = batch_bool<T, A>;
292+
293+
static constexpr bool is_batch = false;
294+
static constexpr bool is_batch_bool = true;
295+
static constexpr bool is_any_batch = true;
296+
static constexpr bool is_complex = false;
252297
};
253298

299+
#if __cplusplus < 201703L
300+
template <class T, class A>
301+
constexpr bool batch_traits<batch_bool<T, A>>::is_batch;
302+
template <class T, class A>
303+
constexpr bool batch_traits<batch_bool<T, A>>::is_batch_bool;
304+
template <class T, class A>
305+
constexpr bool batch_traits<batch_bool<T, A>>::is_any_batch;
306+
template <class T, class A>
307+
constexpr bool batch_traits<batch_bool<T, A>>::is_complex;
308+
#endif
309+
254310
/**
255311
* @ingroup batch_traits
256312
*
257-
* type traits that inherits from @c std::true_type for @c batch_bool<...> types and from
313+
* type traits that inherits from @c std::true_type for @c batch<...> types and from
258314
* @c std::false_type otherwise.
259315
*
260316
* @tparam T type to analyze.
261317
*/
262318

263319
template <class T>
264-
struct is_batch_bool : std::false_type
320+
struct is_batch : std::integral_constant<bool, batch_traits<T>::is_batch>
265321
{
266322
};
267323

268-
template <class T, class A>
269-
struct is_batch_bool<batch_bool<T, A>> : std::true_type
324+
/**
325+
* @ingroup batch_traits
326+
*
327+
* type traits that inherits from @c std::true_type for @c batch_bool<...> types and from
328+
* @c std::false_type otherwise.
329+
*
330+
* @tparam T type to analyze.
331+
*/
332+
333+
template <class T>
334+
struct is_batch_bool : std::integral_constant<bool, batch_traits<T>::is_batch_bool>
270335
{
271336
};
272337

273338
/**
274339
* @ingroup batch_traits
275340
*
276-
* type traits that inherits from @c std::true_type for @c batch<std::complex<...>>
341+
* type traits that inherits from @c std::true_type for @c batch<...> or batch_bool<...>
277342
* types and from @c std::false_type otherwise.
278343
*
279344
* @tparam T type to analyze.
280345
*/
281346

282347
template <class T>
283-
struct is_batch_complex : std::false_type
348+
struct is_any_batch : std::integral_constant<bool, batch_traits<T>::is_any_batch>
284349
{
285350
};
286351

287-
template <class T, class A>
288-
struct is_batch_complex<batch<std::complex<T>, A>> : std::true_type
352+
/**
353+
* @ingroup batch_traits
354+
*
355+
* type traits that inherits from @c std::true_type for @c batch<std::complex<...>>
356+
* types and from @c std::false_type otherwise.
357+
*
358+
* @tparam T type to analyze.
359+
*/
360+
361+
template <class T>
362+
struct is_batch_complex : std::integral_constant<bool, batch_traits<T>::is_batch && batch_traits<T>::is_complex>
289363
{
290364
};
291365

@@ -300,12 +374,7 @@ namespace xsimd
300374
template <class T>
301375
struct scalar_type
302376
{
303-
using type = T;
304-
};
305-
template <class T, class A>
306-
struct scalar_type<batch<T, A>>
307-
{
308-
using type = T;
377+
using type = typename batch_traits<T>::scalar_type;
309378
};
310379

311380
template <class T>
@@ -322,12 +391,7 @@ namespace xsimd
322391
template <class T>
323392
struct mask_type
324393
{
325-
using type = bool;
326-
};
327-
template <class T, class A>
328-
struct mask_type<batch<T, A>>
329-
{
330-
using type = typename batch<T, A>::batch_bool_type;
394+
using type = typename batch_traits<T>::mask_type;
331395
};
332396

333397
template <class T>
@@ -364,7 +428,6 @@ namespace xsimd
364428
}
365429
template <typename T>
366430
using widen_t = typename detail::widen<T>::type;
367-
368431
}
369432

370433
#endif

0 commit comments

Comments
 (0)