blob: 5e505803c4829566ec9d8905ad4d99e0c3b91204 [file] [log] [blame]
// Copyright (C) 2020-2021 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
// <http://www.gnu.org/licenses/>.
// expensive: * [1-9] * *
#include "bits/verify.h"
#include "bits/metahelpers.h"
#include "bits/conversions.h"
using std::experimental::simd_cast;
using std::experimental::static_simd_cast;
template <class T, size_t N>
struct gen_cast
{
std::array<T, N> data;
template <class V>
gen_cast(const V& v)
{
for (size_t i = 0; i < V::size(); ++i)
{
data[i] = static_cast<T>(v[i]);
}
}
template <class I>
constexpr T
operator()(I)
{ return data[I::value]; }
};
template <class V, class To>
struct gen_seq_t
{
using From = typename V::value_type;
const size_t N = cvt_input_data<From, To>.size();
size_t offset = 0;
constexpr void
operator++()
{ offset += V::size(); }
explicit constexpr operator bool() const
{ return offset < N; }
template <class I>
constexpr From
operator()(I) const
{
size_t i = I::value + offset;
return i < N ? cvt_input_data<From, To>[i] : From(i);
}
};
template <class To>
struct foo
{
template <class T>
auto
operator()(const T& v) -> decltype(simd_cast<To>(v));
};
template <typename V, typename To>
void
casts()
{
using From = typename V::value_type;
constexpr auto N = V::size();
if constexpr (N <= std::experimental::simd_abi::max_fixed_size<To>)
{
using W = std::experimental::fixed_size_simd<To, N>;
if constexpr (std::is_integral_v<From>)
{
using A = typename V::abi_type;
using TU = std::make_unsigned_t<From>;
using TS = std::make_signed_t<From>;
COMPARE(typeid(static_simd_cast<TU>(V())),
typeid(std::experimental::simd<TU, A>));
COMPARE(typeid(static_simd_cast<TS>(V())),
typeid(std::experimental::simd<TS, A>));
}
using is_simd_cast_allowed
= decltype(vir::test::sfinae_is_callable_t<const V&>(foo<To>()));
COMPARE(is_simd_cast_allowed::value,
std::__digits<From>::value <= std::__digits<To>::value
&& std::__finite_max<From>::value
<= std::__finite_max<To>::value
&& !(std::is_signed<From>::value
&& std::is_unsigned<To>::value));
if constexpr (is_simd_cast_allowed::value)
{
for (gen_seq_t<V, To> gen_seq; gen_seq; ++gen_seq)
{
const V seq(gen_seq);
COMPARE(simd_cast<V>(seq), seq);
COMPARE(simd_cast<W>(seq), W(gen_cast<To, N>(seq)))
<< "seq = " << seq;
auto test = simd_cast<To>(seq);
// decltype(test) is not W if
// a) V::abi_type is not fixed_size and
// b.1) V::value_type and To are integral and of equal rank or
// b.2) V::value_type and To are equal
COMPARE(test, decltype(test)(gen_cast<To, N>(seq)));
if (std::is_same<To, From>::value)
{
COMPARE(typeid(decltype(test)), typeid(V));
}
}
}
for (gen_seq_t<V, To> gen_seq; gen_seq; ++gen_seq)
{
const V seq(gen_seq);
COMPARE(static_simd_cast<V>(seq), seq);
COMPARE(static_simd_cast<W>(seq), W(gen_cast<To, N>(seq))) << '\n'
<< seq;
auto test = static_simd_cast<To>(seq);
// decltype(test) is not W if
// a) V::abi_type is not fixed_size and
// b.1) V::value_type and To are integral and of equal rank or
// b.2) V::value_type and To are equal
COMPARE(test, decltype(test)(gen_cast<To, N>(seq)));
if (std::is_same<To, From>::value)
{
COMPARE(typeid(decltype(test)), typeid(V));
}
}
}
}
template <typename V>
void
test()
{
casts<V, long double>();
casts<V, double>();
casts<V, float>();
casts<V, long long>();
casts<V, unsigned long long>();
casts<V, unsigned long>();
casts<V, long>();
casts<V, int>();
casts<V, unsigned int>();
casts<V, short>();
casts<V, unsigned short>();
casts<V, char>();
casts<V, signed char>();
casts<V, unsigned char>();
casts<V, char32_t>();
casts<V, char16_t>();
casts<V, wchar_t>();
}