168 lines
4.5 KiB
C++
168 lines
4.5 KiB
C++
// Copyright (C) 2020-2024 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/main.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>();
|
|
}
|