gcc/libstdc++-v3/testsuite/experimental/simd/tests/bits/conversions.h
2024-01-03 12:19:35 +01:00

177 lines
6.1 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/>.
#ifndef SIMD_TESTS_BITS_CONVERSIONS_H_
#define SIMD_TESTS_BITS_CONVERSIONS_H_
#include <array>
// is_conversion_undefined
/* implementation-defined
* ======================
* §4.7 p3 (integral conversions)
* If the destination type is signed, the value is unchanged if it can be
* represented in the destination type (and bit-field width); otherwise, the
* value is implementation-defined.
*
* undefined
* =========
* §4.9/1 (floating-point conversions)
* If the source value is neither exactly represented in the destination type
* nor between two adjacent destination values the result is undefined.
*
* §4.10/1 (floating-integral conversions)
* floating point type can be converted to integer type.
* The behavior is undefined if the truncated value cannot be
* represented in the destination type.
*
* §4.10/2
* integer can be converted to floating point type.
* If the value being converted is outside the range of values that can be
* represented, the behavior is undefined.
*/
template <typename To, typename From>
constexpr bool
is_conversion_undefined_impl(From x, std::true_type)
{
return x > static_cast<long double>(std::__finite_max_v<To>)
|| x < static_cast<long double>(std::__finite_min_v<To>);
}
template <typename To, typename From>
constexpr bool
is_conversion_undefined_impl(From, std::false_type)
{ return false; }
template <typename To, typename From>
constexpr bool
is_conversion_undefined(From x)
{
static_assert(std::is_arithmetic<From>::value,
"this overload is only meant for builtin arithmetic types");
return is_conversion_undefined_impl<To, From>(
x, std::integral_constant<
bool, std::is_floating_point<From>::value
&& (std::is_integral<To>::value
|| (std::is_floating_point<To>::value
&& sizeof(From) > sizeof(To)))>());
}
static_assert(is_conversion_undefined<uint>(float(0x100000000LL)),
"testing my expectations of is_conversion_undefined");
static_assert(!is_conversion_undefined<float>(0x100000000LL),
"testing my expectations of is_conversion_undefined");
template <typename To, typename T, typename A>
inline std::experimental::simd_mask<T, A>
is_conversion_undefined(const std::experimental::simd<T, A>& x)
{
std::experimental::simd_mask<T, A> k = false;
for (std::size_t i = 0; i < x.size(); ++i)
k[i] = is_conversion_undefined(x[i]);
return k;
}
template <class T>
constexpr T
genHalfBits()
{
if constexpr (std::is_floating_point_v<T>)
return 0;
else
return std::__finite_max_v<T> >> (std::__digits_v<T> / 2);
}
template <class U, class T, class UU>
constexpr U
avoid_ub(UU x)
{ return is_conversion_undefined<T>(U(x)) ? U(0) : U(x); }
template <class U, class T, class UU>
constexpr U
avoid_ub2(UU x)
{ return is_conversion_undefined<U>(x) ? U(0) : avoid_ub<U, T>(x); }
// conversion test input data
template <class U, class T>
static const std::array<U, 53> cvt_input_data = {{
avoid_ub<U, T>(0xc0000080U),
avoid_ub<U, T>(0xc0000081U),
avoid_ub<U, T>(0xc0000082U),
avoid_ub<U, T>(0xc0000084U),
avoid_ub<U, T>(0xc0000088U),
avoid_ub<U, T>(0xc0000090U),
avoid_ub<U, T>(0xc00000A0U),
avoid_ub<U, T>(0xc00000C0U),
avoid_ub<U, T>(0xc000017fU),
avoid_ub<U, T>(0xc0000180U),
avoid_ub<U, T>(0x100000001LL),
avoid_ub<U, T>(0x100000011LL),
avoid_ub<U, T>(0x100000111LL),
avoid_ub<U, T>(0x100001111LL),
avoid_ub<U, T>(0x100011111LL),
avoid_ub<U, T>(0x100111111LL),
avoid_ub<U, T>(0x101111111LL),
avoid_ub<U, T>(-0x100000001LL),
avoid_ub<U, T>(-0x100000011LL),
avoid_ub<U, T>(-0x100000111LL),
avoid_ub<U, T>(-0x100001111LL),
avoid_ub<U, T>(-0x100011111LL),
avoid_ub<U, T>(-0x100111111LL),
avoid_ub<U, T>(-0x101111111LL),
avoid_ub<U, T>(std::__norm_min_v<U>),
avoid_ub<U, T>(std::__norm_min_v<U> + 1),
avoid_ub<U, T>(std::__finite_min_v<U>),
avoid_ub<U, T>(std::__finite_min_v<U> + 1),
avoid_ub<U, T>(-1),
avoid_ub<U, T>(-10),
avoid_ub<U, T>(-100),
avoid_ub<U, T>(-1000),
avoid_ub<U, T>(-10000),
avoid_ub<U, T>(0),
avoid_ub<U, T>(1),
avoid_ub<U, T>(genHalfBits<U>() - 1),
avoid_ub<U, T>(genHalfBits<U>()),
avoid_ub<U, T>(genHalfBits<U>() + 1),
avoid_ub<U, T>(std::__finite_max_v<U> - 1),
avoid_ub<U, T>(std::__finite_max_v<U>),
avoid_ub<U, T>(std::__finite_max_v<U> - 0xff),
avoid_ub<U, T>(std::__finite_max_v<U> - 0xff),
avoid_ub<U, T>(std::__finite_max_v<U> - 0x55),
avoid_ub<U, T>(-(std::__finite_min_v<U> + 1)),
avoid_ub<U, T>(-std::__finite_max_v<U>),
avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 6 - 1)),
avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 6 - 1)),
avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 4 - 1)),
avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 4 - 1)),
avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 2 - 1)),
avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 2 - 1)),
avoid_ub<U, T>(std::__finite_max_v<T> - 1),
avoid_ub<U, T>(std::__finite_max_v<T> * 0.75),
}};
template <class T, class U>
struct cvt_inputs
{
static constexpr size_t
size()
{ return cvt_input_data<U, T>.size(); }
U
operator[](size_t i) const
{ return cvt_input_data<U, T>[i]; }
};
#endif // SIMD_TESTS_BITS_CONVERSIONS_H_