177 lines
6.1 KiB
C++
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_
|