Skip to content

Commit

Permalink
Add and test generator ctor for simdize<T>
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Kretz <kretz@kde.org>
  • Loading branch information
mattkretz committed Sep 10, 2018
1 parent 4accb4c commit c04b337
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 56 deletions.
83 changes: 53 additions & 30 deletions Vc/common/simdize.h
Expand Up @@ -863,6 +863,18 @@ template <typename Scalar, typename Base, size_t N> class Adapter : public Base
{
}

/// Generator constructor {{{
template <class F,
class = decltype(static_cast<Scalar>(std::declval<F>()(
size_t())))> // F returns objects that are convertible to S
Adapter(F &&fun)
{
for (size_t i = 0; i < N; ++i) {
assign(*this, i, fun(i));
}
}

// }}}
/// perfect forward all Base constructors
template <typename A0, typename... Args,
typename = typename std::enable_if<
Expand Down Expand Up @@ -1165,6 +1177,35 @@ inline void store_interleaved_impl(Vc::index_sequence<I...>, const Adapter<S, T,
wrapper[0] = Vc::tie(get_dispatcher<I>(a)...);
}
// }}}
template <typename A> class Interface // {{{
{
using reference = typename std::add_lvalue_reference<A>::type;
using IndexSeq =
Vc::make_index_sequence<determine_tuple_size<typename A::scalar_type>()>;

public:
Interface(reference aa) : a(aa) {}

Scalar<A> operator[](size_t i)
{
return {a, i};
}
typename A::scalar_type operator[](size_t i) const
{
return extract_impl(a, i, IndexSeq());
}

A shifted(int amount) const
{
return shifted_impl(a, amount, IndexSeq());
}

void load(const typename A::scalar_type *mem) { load_interleaved(*this, mem); }
void store(typename A::scalar_type *mem) { store_interleaved(*this, mem); }

private:
reference a;
}; // }}}
} // namespace SimdizeDetail
// assign {{{
/**
Expand Down Expand Up @@ -1248,46 +1289,28 @@ Vc_INTRINSIC void store_interleaved(const V &a, T *mem)
a.store(mem, Vc::Unaligned);
}
// }}}
namespace SimdizeDetail
{
template <typename A> class Interface // {{{
{
using reference = typename std::add_lvalue_reference<A>::type;
using IndexSeq =
Vc::make_index_sequence<determine_tuple_size<typename A::scalar_type>()>;

public:
Interface(reference aa) : a(aa) {}

Scalar<A> operator[](size_t i)
{
return {a, i};
}
typename A::scalar_type operator[](size_t i) const
{
return extract_impl(a, i, IndexSeq());
}

A shifted(int amount) const
{
return shifted_impl(a, amount, IndexSeq());
}

private:
reference a;
}; // }}}
// decorate(Adapter) {{{
template <typename S, typename T, size_t N>
Interface<Adapter<S, T, N>> decorate(Adapter<S, T, N> &a)
SimdizeDetail::Interface<SimdizeDetail::Adapter<S, T, N>> decorate(
SimdizeDetail::Adapter<S, T, N> &a)
{
return {a};
}
template <typename S, typename T, size_t N>
const Interface<const Adapter<S, T, N>> decorate(const Adapter<S, T, N> &a)
const SimdizeDetail::Interface<const SimdizeDetail::Adapter<S, T, N>> decorate(
const SimdizeDetail::Adapter<S, T, N> &a)
{
return {a};
}
template <class V, class = typename std::enable_if<
Traits::is_simd_vector<typename std::decay<V>::type>::value>>
V &&decorate(V &&v)
{
return std::forward<V>(v);
}
// }}}
namespace SimdizeDetail
{
namespace IteratorDetails // {{{
{
enum class Mutable { Yes, No };
Expand Down
71 changes: 45 additions & 26 deletions godbolt.h
Expand Up @@ -23693,6 +23693,15 @@ Adapter(U &&x_)
: Adapter(Seq(), static_cast<const Scalar &>(x_))
{
}
template <class F,
class = decltype(static_cast<Scalar>(std::declval<F>()(
size_t())))>
Adapter(F &&fun)
{
for (size_t i = 0; i < N; ++i) {
assign(*this, i, fun(i));
}
}
template <typename A0, typename... Args,
typename = typename std::enable_if<
!Traits::is_index_sequence<A0>::value &&
Expand Down Expand Up @@ -23906,6 +23915,30 @@ InterleavedMemoryWrapper<S, decltype(decay_workaround(get_dispatcher<0>(a)))> wr
mem);
wrapper[0] = Vc::tie(get_dispatcher<I>(a)...);
}
template <typename A> class Interface
{
using reference = typename std::add_lvalue_reference<A>::type;
using IndexSeq =
Vc::make_index_sequence<determine_tuple_size<typename A::scalar_type>()>;
public:
Interface(reference aa) : a(aa) {}
Scalar<A> operator[](size_t i)
{
return {a, i};
}
typename A::scalar_type operator[](size_t i) const
{
return extract_impl(a, i, IndexSeq());
}
A shifted(int amount) const
{
return shifted_impl(a, amount, IndexSeq());
}
void load(const typename A::scalar_type *mem) { load_interleaved(*this, mem); }
void store(typename A::scalar_type *mem) { store_interleaved(*this, mem); }
private:
reference a;
};
}
template <typename S, typename T, size_t N>
inline void assign(SimdizeDetail::Adapter<S, T, N> &a, size_t i, const S &x)
Expand Down Expand Up @@ -23967,40 +24000,26 @@ Vc_INTRINSIC void store_interleaved(const V &a, T *mem)
{
a.store(mem, Vc::Unaligned);
}
namespace SimdizeDetail
{
template <typename A> class Interface
{
using reference = typename std::add_lvalue_reference<A>::type;
using IndexSeq =
Vc::make_index_sequence<determine_tuple_size<typename A::scalar_type>()>;
public:
Interface(reference aa) : a(aa) {}
Scalar<A> operator[](size_t i)
{
return {a, i};
}
typename A::scalar_type operator[](size_t i) const
{
return extract_impl(a, i, IndexSeq());
}
A shifted(int amount) const
{
return shifted_impl(a, amount, IndexSeq());
}
private:
reference a;
};
template <typename S, typename T, size_t N>
Interface<Adapter<S, T, N>> decorate(Adapter<S, T, N> &a)
SimdizeDetail::Interface<SimdizeDetail::Adapter<S, T, N>> decorate(
SimdizeDetail::Adapter<S, T, N> &a)
{
return {a};
}
template <typename S, typename T, size_t N>
const Interface<const Adapter<S, T, N>> decorate(const Adapter<S, T, N> &a)
const SimdizeDetail::Interface<const SimdizeDetail::Adapter<S, T, N>> decorate(
const SimdizeDetail::Adapter<S, T, N> &a)
{
return {a};
}
template <class V, class = typename std::enable_if<
Traits::is_simd_vector<typename std::decay<V>::type>::value>>
V &&decorate(V &&v)
{
return std::forward<V>(v);
}
namespace SimdizeDetail
{
namespace IteratorDetails
{
enum class Mutable { Yes, No };
Expand Down
32 changes: 32 additions & 0 deletions tests/simdize.cpp
Expand Up @@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}}}*/

//#define UNITTEST_ONLY_XTEST 1
#include "unittest.h"
#include <list>

Expand Down Expand Up @@ -640,4 +641,35 @@ TEST(copy_simdized_objects)
COMPARE(std::get<1>(v3), V1(0));
}

template <class T> T create(int x) { return x; }
template <> std::array<float, 3> create<std::array<float, 3>>(int _x)
{
float x = _x;
return {x, x + 1, x + 2};
}
template <> std::tuple<double, int> create<std::tuple<double, int>>(int x)
{
return {x, x + 1};
}

TEST_TYPES(T, generator, float, short, std::array<float, 3>, std::tuple<double, int>)
{
using V = simdize<T>;

{
const V test([](int) { return T(); });
const auto &testv = Vc::decorate(test);
for (std::size_t i = 0; i < V::size(); ++i) {
COMPARE(testv[i], T());
}
}
{
const V test([](int n) { return create<T>(n); });
const auto &testv = Vc::decorate(test);
for (std::size_t i = 0; i < V::size(); ++i) {
COMPARE(testv[i], create<T>(i));
}
}
}

// vim: foldmethod=marker

0 comments on commit c04b337

Please sign in to comment.