mattkretz / wg21-papers

my papers to WG21 — the C++ committee
5 stars 7 forks source link

scoped masked execution - extends where #43

Open mattkretz opened 7 years ago

mattkretz commented 7 years ago
template <class T, class A, class... Vs, class OnTrue, class OnFalse>
// require mask<T, A> to be convertible to Vs::mask_type forall Vs
void where(mask<T, A> k, Vs &&... vs, OnTrue &&on_true, OnFalse &&on_false) {
  std::forward<OnTrue >(on_true )(masked_datapar( k, std::forward<Vs>(vs))...);
  std::forward<OnFalse>(on_false)(masked_datapar(!k, std::forward<Vs>(vs))...);
}
template <class T, class A, class... Vs, class OnTrue>
// require mask<T, A> to be convertible to Vs::mask_type forall Vs
void where(mask<T, A> k, Vs &&... vs, OnTrue &&on_true) {
  std::forward<OnTrue>(on_true)(masked_datapar(k, std::forward<Vs>(vs))...);
}

// usage:
where(v1 > 0, v1, v2, [&](auto &&v1masked, auto &&v2masked) {
  v1masked = 1 / v1masked;  // division is guaranteed to be masked
  v1 = 1 / v1masked;        // ill-formed: if you want masked assignment, mask the LHS
}, [&](auto &&v1masked, auto &&v2masked) {
  v2masked += 1;
});
mattkretz commented 7 years ago

The above has a problem with deduction of Vs... since the pack is not at the end of the function parameter list. After moving it, a call would look like:

where(v1 > 0, [&](auto &&v1masked, auto &&v2masked) {
  v1masked = 1 / v1masked;  // division is guaranteed to be masked
  v1 = 1 / v1masked;        // ill-formed: if you want masked assignment, mask the LHS
}, [&](auto &&v1masked, auto &&v2masked) {
  v2masked += 1;
}, v1, v2);

In addition I believe the implicit meaning of the two callables is suboptimal.

new variant

where(v1 > 0, v1, v2)
  .apply([&](auto &&v1masked, auto &&v2masked) {
    v1masked = 1 / v1masked;  // division is guaranteed to be masked
    v1 = 1 / v1masked;        // ill-formed: if you want masked assignment, mask the LHS
  })
  .apply_inv([&](auto &&v1masked, auto &&v2masked) {
    v2masked += 1;
  });
mattkretz commented 7 years ago

@phalpern What do you think of https://github.com/VcDevel/Vc/blob/4a333e9b856e4b26b7498530c89edd1e902d254e/tests/experimental.cpp#L47-L49? If you like it I'll look into a small extension paper to LEWG. Your suggestion had the problem that the parameter pack isn't deducible. Also the meaning of the two lambdas as last and second to last argument was not obvious enough, IMHO.