Skip to content

Ranges: Stories sketch

Denis Yaroshevskiy edited this page May 5, 2021 · 5 revisions

This is what I see for stories we'd need to do. The list is incomplete and we will see how are we with updating it.

allow customisation for eve::load/eve::store outside of EVE.

@jfalcou says there is already a good way to do it in which case this is a noop.

eve::iterator<T, N> class

Has just one pointer (ptr) to T or const T inside.

Supports eve::load[ignore](eve::iterator<T, N>) -> eve::load[ignore](ptr, N{}); eve::store[ignore]

operators: + - <=>

has a static constexpr N cardinality;

eve::aligned_iterator<T, N>

Has one aligned_ptr<T, N> member. Can be converted to iterator at the same position via eve::remove_alignment that should be customisable outside of eve namespace.

Is comparable against iterator. You can do pointer arithmetic between iterator and aligned_iterator.

cardinality_cast<eve::fixed> customisation point.

Should allow customisation.

cardinality_cast<N>(eve::iterator<T, M>) -> eve::iterator<T, N>

cardinality_cast<M>(eve::aligned_iterator<T, N>) requires(M::value <= N::value) -> eve::aligned_iterator<T, M>

Not sure if we need M::value > N::value or what should it do. We should probably skip it at the moment.

eve::wide_value_type

Basically a typedef for return type of load, or a parameter of store. Maybe needs to be exposed for iterators via some machinery, since you can't reflect it for store easily.

bring kumi tuple into the project https://github.com/jfalcou/ofw

We need a decent tuple implementation

write a simplistic eve::ranges::any that works only on pointers.

This is kind of putting some of the things together. No aligning, no zips. No constraints on templates. Put whatever instead of traits.

We need:

This is the version I had for my talk: https://github.com/DenisYaroshevskiy/unsq_eve/blob/977794c06f504ee03c027e9415f4a451b2ceb5d9/src/unsq_eve/all_any_none.h#L94

This would be my sketch:

namespace eve::ranges {
namespace detail {

// steps return true if the iteration should break

template <typename Traits, typename P>
struct any_of_impl {
  Traits traits;
  P p;
  
  template <typename I, eve::relative_conditional_expression C>
  bool small_step(I it, C c)
  {
     auto loaded = eve::load[c](it);
     return eve::any[ignore](p(loaded));
  }
  
  template <typename I>
  bool big_step(I it) {
    eve::logical<decltype(eve::load(it)> res = false;

    // This is not an ideal way to aggregate any across the array.
    // However @jfalcou thinks it's important to allow for arbitrary unrolls
    // (and not just powers of 2)
    // So we cannot just reuse the `any(wide<aggregated>)` logic.
    for (int i = 0; i != Traits::unrolling(); ++i) {
      res = res || p(eve::load(it));
      it += I::cardinality();
    }

    return eve::any(res);
  }
  
};

}  // namespace detail

template <typename I, typename S, typename P>
bool any_of(I _f, S _l, P p) {
  // We'd need this empty check in the future
  // because otherwise doing &*std::vector<int>::iterator is not legal.
  if (_f == _l) return false;

  auto [f, l] = make_range(_f, _l);
  detail::any_impl impl{any_traits, p};

  return iteration::for_each(f, l, impl).action == Action::Break;
}

}  // namespace eve::ranges