// Copyright (C) 2020-2022 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// .
// expensive: * [1-9] * *
#include "bits/verify.h"
#include "bits/make_vec.h"
#include "bits/metahelpers.h"
template
struct Convertible
{
operator V() const { return V(4); }
};
template
constexpr bool
where_is_ill_formed_impl(M, const T&, float)
{
return true;
}
template
constexpr auto
where_is_ill_formed_impl(M m, const T& v, int)
-> std::conditional_t
{
return false;
}
template
constexpr bool
where_is_ill_formed(M m, const T& v)
{
return where_is_ill_formed_impl(m, v, int());
}
template
void
where_fundamental()
{
using std::experimental::where;
T x = T();
where(true, x) = x + 1;
COMPARE(x, T(1));
where(false, x) = x - 1;
COMPARE(x, T(1));
where(true, x) += T(1);
COMPARE(x, T(2));
}
template
void
test()
{
using M = typename V::mask_type;
using T = typename V::value_type;
where_fundamental();
VERIFY(!(sfinae_is_callable(
[](auto x) -> decltype(where(true, x))* { return nullptr; })));
const V indexes([](int i) { return i + 1; });
const M alternating_mask = make_mask({true, false});
V x = 0;
where(alternating_mask, x) = indexes;
COMPARE(alternating_mask, x == indexes);
where(!alternating_mask, x) = T(2);
COMPARE(!alternating_mask, x == T(2)) << x;
where(!alternating_mask, x) = Convertible();
COMPARE(!alternating_mask, x == T(4));
x = 0;
COMPARE(x, T(0));
where(alternating_mask, x) += indexes;
COMPARE(alternating_mask, x == indexes);
x = 10;
COMPARE(x, T(10));
where(!alternating_mask, x) += T(1);
COMPARE(!alternating_mask, x == T(11));
where(alternating_mask, x) -= Convertible();
COMPARE(alternating_mask, x == T(6));
constexpr bool fast_math =
#ifdef __FAST_MATH__
true;
#else
false;
#endif
if constexpr (fast_math && std::is_floating_point_v)
where(alternating_mask, x) *= T(.5);
else
where(alternating_mask, x) /= T(2);
COMPARE(alternating_mask, x == T(3)) << "\nx = " << x;
where(alternating_mask, x) *= T(3);
COMPARE(alternating_mask, x == T(9));
COMPARE(!alternating_mask, x == T(11));
x = 10;
where(alternating_mask, x)++;
COMPARE(alternating_mask, x == T(11));
++where(alternating_mask, x);
COMPARE(alternating_mask, x == T(12));
where(alternating_mask, x)--;
COMPARE(alternating_mask, x == T(11));
--where(alternating_mask, x);
--where(alternating_mask, x);
COMPARE(alternating_mask, x == T(9));
COMPARE(alternating_mask, -where(alternating_mask, x) == T(-T(9)));
const auto y = x;
VERIFY(where_is_ill_formed(true, y));
VERIFY(where_is_ill_formed(true, x));
VERIFY(where_is_ill_formed(true, V(x)));
M test = alternating_mask;
where(alternating_mask, test) = M(true);
COMPARE(test, alternating_mask);
where(alternating_mask, test) = M(false);
COMPARE(test, M(false));
where(alternating_mask, test) = M(true);
COMPARE(test, alternating_mask);
}