Skip to content

Commit 0bdffb1

Browse files
authored
Merge pull request #540 from JohanMabille/traits
Added xsimd_traits and other api metafunctions
2 parents cba930b + 044b8d3 commit 0bdffb1

File tree

7 files changed

+343
-0
lines changed

7 files changed

+343
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ ${XSIMD_INCLUDE_DIR}/xsimd/types/xsimd_sse3_register.hpp
6767
${XSIMD_INCLUDE_DIR}/xsimd/types/xsimd_sse4_1_register.hpp
6868
${XSIMD_INCLUDE_DIR}/xsimd/types/xsimd_sse4_2_register.hpp
6969
${XSIMD_INCLUDE_DIR}/xsimd/types/xsimd_ssse3_register.hpp
70+
${XSIMD_INCLUDE_DIR}/xsimd/types/xsimd_traits.hpp
7071
${XSIMD_INCLUDE_DIR}/xsimd/types/xsimd_utils.hpp
7172
${XSIMD_INCLUDE_DIR}/xsimd/xsimd.hpp
7273
)

include/xsimd/types/xsimd_batch.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ struct batch : types::simd_register<T, A> {
149149
batch(T const* data, detail::index_sequence<Is...>);
150150
};
151151

152+
template <class T, class A>
153+
constexpr std::size_t batch<T, A>::size;
154+
152155
/**
153156
* @brief batch of predicate over scalar or complex values.
154157
*
@@ -208,6 +211,9 @@ struct batch_bool : types::get_bool_simd_register_t<T, A> {
208211

209212
};
210213

214+
template <class T, class A>
215+
constexpr std::size_t batch_bool<T, A>::size;
216+
211217
/**
212218
* @brief batch of complex values.
213219
*
@@ -327,6 +333,9 @@ struct batch<std::complex<T>, A> {
327333
real_batch m_imag;
328334
};
329335

336+
template <class T, class A>
337+
constexpr std::size_t batch<std::complex<T>, A>::size;
338+
330339
}
331340

332341
#include "../types/xsimd_batch_constant.hpp"
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/***************************************************************************
2+
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
3+
* Martin Renou *
4+
* Copyright (c) QuantStack *
5+
* *
6+
* Distributed under the terms of the BSD 3-Clause License. *
7+
* *
8+
* The full license is in the file LICENSE, distributed with this software. *
9+
****************************************************************************/
10+
11+
#ifndef XSIMD_TRAITS_HPP
12+
#define XSIMD_TRAITS_HPP
13+
14+
#include <type_traits>
15+
16+
#include "xsimd_api.hpp"
17+
18+
namespace xsimd
19+
{
20+
namespace detail
21+
{
22+
template <class T, class = void>
23+
struct has_batch : std::false_type
24+
{
25+
};
26+
27+
template <class T>
28+
struct has_batch<T, check_size_t<sizeof(batch<T>)>> : std::true_type
29+
{
30+
};
31+
}
32+
33+
template <class T, bool = detail::has_batch<T>::value>
34+
struct simd_traits
35+
{
36+
using type = T;
37+
using bool_type = bool;
38+
static constexpr size_t size = 1;
39+
};
40+
41+
template <class T, bool B>
42+
constexpr size_t simd_traits<T, B>::size;
43+
44+
template <class T>
45+
struct revert_simd_traits
46+
{
47+
using type = T;
48+
static constexpr size_t size = simd_traits<type>::size;
49+
};
50+
51+
template <class T>
52+
constexpr size_t revert_simd_traits<T>::size;
53+
54+
template <class T>
55+
struct simd_traits<T, true>
56+
{
57+
using type = batch<T>;
58+
using bool_type = typename type::batch_bool_type;
59+
static constexpr size_t size = type::size;
60+
};
61+
62+
template <class T>
63+
constexpr size_t simd_traits<T, true>::size;
64+
65+
template <class T>
66+
struct revert_simd_traits<batch<T>>
67+
{
68+
using type = T;
69+
static constexpr size_t size = batch<T>::size;
70+
};
71+
72+
template <class T>
73+
constexpr size_t revert_simd_traits<batch<T>>::size;
74+
75+
template <class T>
76+
using simd_type = typename simd_traits<T>::type;
77+
78+
template <class T>
79+
using simd_bool_type = typename simd_traits<T>::bool_type;
80+
81+
template <class T>
82+
using revert_simd_type = typename revert_simd_traits<T>::type;
83+
84+
85+
// TODO: we have a problem here since the specialization for
86+
// batch<xtl::xcomplex<T, T, i3ec>> does not exit anymore
87+
/*#ifdef XSIMD_ENABLE_XTL_COMPLEX
88+
template <bool i3ec>
89+
struct simd_traits<xtl::xcomplex<float, float, i3ec>>
90+
{
91+
using type = batch<xtl::xcomplex<float, float, i3ec>, XSIMD_BATCH_FLOAT_SIZE>;
92+
using bool_type = typename simd_batch_traits<type>::batch_bool_type;
93+
static constexpr size_t size = type::size;
94+
};
95+
96+
template <bool i3ec>
97+
struct revert_simd_traits<batch<xtl::xcomplex<float, float, i3ec>, XSIMD_BATCH_FLOAT_SIZE>>
98+
{
99+
using type = xtl::xcomplex<float, float, i3ec>;
100+
static constexpr size_t size = simd_traits<type>::size;
101+
};
102+
#endif // XSIMD_ENABLE_XTL_COMPLEX
103+
*/
104+
/*#ifdef XSIMD_ENABLE_XTL_COMPLEX
105+
template <bool i3ec>
106+
struct simd_traits<xtl::xcomplex<double, double, i3ec>>
107+
{
108+
using type = batch<xtl::xcomplex<double, double, i3ec>, XSIMD_BATCH_DOUBLE_SIZE>;
109+
using bool_type = typename simd_batch_traits<type>::batch_bool_type;
110+
static constexpr size_t size = type::size;
111+
};
112+
113+
template <bool i3ec>
114+
struct revert_simd_traits<batch<xtl::xcomplex<double, double, i3ec>, XSIMD_BATCH_DOUBLE_SIZE>>
115+
{
116+
using type = xtl::xcomplex<double, double, i3ec>;
117+
static constexpr size_t size = simd_traits<type>::size;
118+
};
119+
#endif // XSIMD_ENABLE_XTL_COMPLEX*/
120+
121+
/********************
122+
* simd_return_type *
123+
********************/
124+
125+
namespace detail
126+
{
127+
template <class T1, class T2>
128+
struct simd_condition
129+
{
130+
static constexpr bool value =
131+
(std::is_same<T1, T2>::value && !std::is_same<T1, bool>::value) ||
132+
(std::is_same<T1, bool>::value && !std::is_same<T2, bool>::value) ||
133+
std::is_same<T1, float>::value ||
134+
std::is_same<T1, double>::value ||
135+
std::is_same<T1, int8_t>::value ||
136+
std::is_same<T1, uint8_t>::value ||
137+
std::is_same<T1, int16_t>::value ||
138+
std::is_same<T1, uint16_t>::value ||
139+
std::is_same<T1, int32_t>::value ||
140+
std::is_same<T1, uint32_t>::value ||
141+
std::is_same<T1, int64_t>::value ||
142+
std::is_same<T1, uint64_t>::value ||
143+
std::is_same<T1, char>::value ||
144+
detail::is_complex<T1>::value;
145+
};
146+
147+
template <class T1, class T2, class A>
148+
struct simd_return_type_impl
149+
: std::enable_if<simd_condition<T1, T2>::value, batch<T2, A>>
150+
{
151+
};
152+
template <class A>
153+
struct simd_return_type_impl<char, char, A>
154+
: std::conditional<std::is_signed<char>::value,
155+
simd_return_type_impl<int8_t, int8_t, A>,
156+
simd_return_type_impl<uint8_t, uint8_t, A>>::type
157+
{
158+
};
159+
160+
template <class T2, class A>
161+
struct simd_return_type_impl<bool, T2, A>
162+
: std::enable_if<simd_condition<bool, T2>::value, batch_bool<T2, A>>
163+
{
164+
};
165+
166+
template <class T1, class T2, class A>
167+
struct simd_return_type_impl<std::complex<T1>, T2, A>
168+
: std::enable_if<simd_condition<T1, T2>::value, batch<std::complex<T2>, A>>
169+
{
170+
};
171+
172+
template <class T1, class T2, class A>
173+
struct simd_return_type_impl<std::complex<T1>, std::complex<T2>, A>
174+
: std::enable_if<simd_condition<T1, T2>::value, batch<std::complex<T2>, A>>
175+
{
176+
};
177+
178+
/*#ifdef XSIMD_ENABLE_XTL_COMPLEX
179+
template <class T1, bool i3ec, class T2, std::size_t N>
180+
struct simd_return_type_impl<xtl::xcomplex<T1, T1, i3ec>, T2, N>
181+
: std::enable_if<simd_condition<T1, T2>::value, batch<xtl::xcomplex<T2, T2, i3ec>, N>>
182+
{
183+
};
184+
185+
template <class T1, class T2, bool i3ec, std::size_t N>
186+
struct simd_return_type_impl<xtl::xcomplex<T1, T1, i3ec>, xtl::xcomplex<T2, T2, i3ec>, N>
187+
: std::enable_if<simd_condition<T1, T2>::value, batch<xtl::xcomplex<T2, T2, i3ec>, N>>
188+
{
189+
};
190+
#endif // XSIMD_ENABLE_XTL_COMPLEX*/
191+
}
192+
193+
template <class T1, class T2, class A = default_arch>
194+
using simd_return_type = typename detail::simd_return_type_impl<T1, T2, A>::type;
195+
196+
/************
197+
* is_batch *
198+
************/
199+
200+
template <class V>
201+
struct is_batch : std::false_type
202+
{
203+
};
204+
205+
template <class T, class A>
206+
struct is_batch<batch<T, A>> : std::true_type
207+
{
208+
};
209+
210+
/*****************
211+
* is_batch_bool *
212+
*****************/
213+
214+
template <class V>
215+
struct is_batch_bool : std::false_type
216+
{
217+
};
218+
219+
template <class T, class A>
220+
struct is_batch_bool<batch_bool<T, A>> : std::true_type
221+
{
222+
};
223+
224+
/********************
225+
* is_batch_complex *
226+
********************/
227+
228+
template <class V>
229+
struct is_batch_complex : std::false_type
230+
{
231+
};
232+
233+
template <class T, class A>
234+
struct is_batch_complex<batch<std::complex<T>, A>> : std::true_type
235+
{
236+
};
237+
/*
238+
#ifdef XSIMD_ENABLE_XTL_COMPLEX
239+
template <class T, bool i3ec, std::size_t N>
240+
struct is_batch_complex<batch<xtl::xcomplex<T, T, i3ec>, N>> : std::true_type
241+
{
242+
};
243+
#endif //XSIMD_ENABLE_XTL_COMPLEX*/
244+
245+
}
246+
247+
#endif

include/xsimd/types/xsimd_utils.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,22 @@ namespace xsimd
318318
using void_t = typename make_void<T...>::type;
319319
}
320320

321+
/**************************************************
322+
* Equivalent of void_t but with size_t parameter *
323+
**************************************************/
324+
325+
namespace detail
326+
{
327+
template <std::size_t>
328+
struct check_size
329+
{
330+
using type = void;
331+
};
332+
333+
template <std::size_t S>
334+
using check_size_t = typename check_size<S>::type;
335+
}
336+
321337
/*****************************************
322338
* Supplementary std::array constructors *
323339
*****************************************/

include/xsimd/xsimd.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313
#include "types/xsimd_api.hpp"
1414
#include "arch/xsimd_scalar.hpp"
1515
#include "memory/xsimd_aligned_allocator.hpp"
16+
#include "types/xsimd_traits.hpp"
1617
#endif

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ set(XSIMD_TESTS
171171
test_rounding.cpp
172172
test_select.cpp
173173
test_shuffle_128.cpp
174+
test_traits.cpp
174175
test_trigonometric.cpp
175176
test_utils.hpp
176177
)

test/test_traits.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/***************************************************************************
2+
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
3+
* Martin Renou *
4+
* Copyright (c) QuantStack *
5+
* *
6+
* Distributed under the terms of the BSD 3-Clause License. *
7+
* *
8+
* The full license is in the file LICENSE, distributed with this software. *
9+
****************************************************************************/
10+
11+
#include "test_utils.hpp"
12+
13+
template <class B>
14+
class traits_test : public testing::Test
15+
{
16+
protected:
17+
18+
using batch_type = B;
19+
using value_type = typename B::value_type;
20+
21+
void test_simd_traits()
22+
{
23+
using traits_type = xsimd::simd_traits<value_type>;
24+
EXPECT_EQ(traits_type::size, batch_type::size);
25+
constexpr bool same_type = std::is_same<B, typename traits_type::type>::value;
26+
EXPECT_TRUE(same_type);
27+
using batch_bool_type = xsimd::batch_bool<value_type>;
28+
constexpr bool same_bool_type = std::is_same<batch_bool_type, typename traits_type::bool_type>::value;
29+
EXPECT_TRUE(same_bool_type);
30+
}
31+
32+
void test_revert_simd_traits()
33+
{
34+
using traits_type = xsimd::revert_simd_traits<batch_type>;
35+
EXPECT_EQ(traits_type::size, batch_type::size);
36+
constexpr bool same_type = std::is_same<value_type, typename traits_type::type>::value;
37+
EXPECT_TRUE(same_type);
38+
}
39+
40+
void test_simd_return_type()
41+
{
42+
using rtype1 = xsimd::simd_return_type<value_type, float>;
43+
constexpr bool res1 = std::is_same<rtype1, xsimd::batch<float>>::value;
44+
EXPECT_TRUE(res1);
45+
46+
using rtype2 = xsimd::simd_return_type<bool, value_type>;
47+
constexpr bool res2 = std::is_same<rtype2, xsimd::batch_bool<value_type>>::value;
48+
EXPECT_TRUE(res2);
49+
}
50+
};
51+
52+
TYPED_TEST_SUITE(traits_test, batch_types, simd_test_names);
53+
54+
TYPED_TEST(traits_test, simd_traits)
55+
{
56+
this->test_simd_traits();
57+
}
58+
59+
TYPED_TEST(traits_test, revert_simd_traits)
60+
{
61+
this->test_revert_simd_traits();
62+
}
63+
64+
TYPED_TEST(traits_test, simd_return_type)
65+
{
66+
this->test_simd_return_type();
67+
}
68+

0 commit comments

Comments
 (0)