-
Notifications
You must be signed in to change notification settings - Fork 61
Ranges: bundles, objects and zips
The fundamental problem was outlined in: Ranges: tuple<wide,...> is not that simple
This is what I think we could actually do.
What we want - fundamentally - is to do objects. However vector<object>
is not really a thing in SIMD world - we need to do struct of arrays in order to be remotely efficient.
Let's say that tuple_vector<object>
is a std::tuple<std::vector<tuple_element_t<i, object>....>>
with some special begin/end.
What I propose is at least embrace objects and wider objects on the interface level.
struct pixel {
int x, y, r, g, b;
};
eve::bundle<pixel>;
auto collect_broken_pixels(tuple_vector<pixel> pixels) {
tuple_vector<pixel> res(pixels.size());
constexpr int treshold = 300;
auto l = eve::algo::copy_if(pixels, res, [](auto p) {
auto [x, y, r, g, b] = p;
return (r + g + b) > treshold;
});
res.erase(l, res.end());
return res;
}
Where eve::bundle
is a layer on top of kumi::tuple<wide>
with a wide
for every field. (Joel didn't feel like reusing wide
here).
*NOTE: Let's for now assume that pixel
provides a tuple_like
interface. I'm going to mention how we can make it better. *
I think eve::bundle
should be declared smth like:
template <tuple_like Obj, typename N> bundle
And we should be able to use it in most places where we can use wide
.
- NOTE: I am not sure about
math
functions and things like that. Not sure that automatically enabling them makes sense. *.
There are 2 important consequences of thinking in terms of objects
:
- comparisons and such on two
bundle
should returneve::logical
where it's one register,and
across all wides. pixel == pixel returns 1 bool. pixel < pixel -> lexycographical compare and we can do a tag_dispatch to not do that. - we have a really nice place to customise
eve
operations: we can justtag_dispatch
for our object.
Actually for aggregates there is a trick to do reflections: you first figure out the number of elements starting with sizeof(T)
in the aggregate, and then you do something like:
template <typename T>
auto get_tuple_like_interface(T&& x) {
constexpr std::ptrdiff_t elements_number;
if constexpr (elements_number == 1) {
auto [e1] = x;
return kumi::tuple(e1);
} else if constexpr (elements_number == 2) {
auto [e1] = x;
return kumi::tuple(e1);
}
}
This is limited but we can do it.
Can we maybe get these to work by some clever conversions in a related place?