// 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
// .
#ifndef SIMD_TESTS_BITS_CONVERSIONS_H_
#define SIMD_TESTS_BITS_CONVERSIONS_H_
#include
// 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
constexpr bool
is_conversion_undefined_impl(From x, std::true_type)
{
return x > static_cast(std::__finite_max_v)
|| x < static_cast(std::__finite_min_v);
}
template
constexpr bool
is_conversion_undefined_impl(From, std::false_type)
{ return false; }
template
constexpr bool
is_conversion_undefined(From x)
{
static_assert(std::is_arithmetic::value,
"this overload is only meant for builtin arithmetic types");
return is_conversion_undefined_impl(
x, std::integral_constant<
bool, std::is_floating_point::value
&& (std::is_integral::value
|| (std::is_floating_point::value
&& sizeof(From) > sizeof(To)))>());
}
static_assert(is_conversion_undefined(float(0x100000000LL)),
"testing my expectations of is_conversion_undefined");
static_assert(!is_conversion_undefined(0x100000000LL),
"testing my expectations of is_conversion_undefined");
template
inline std::experimental::simd_mask
is_conversion_undefined(const std::experimental::simd& x)
{
std::experimental::simd_mask k = false;
for (std::size_t i = 0; i < x.size(); ++i)
k[i] = is_conversion_undefined(x[i]);
return k;
}
template
constexpr T
genHalfBits()
{
if constexpr (std::is_floating_point_v)
return 0;
else
return std::__finite_max_v >> (std::__digits_v / 2);
}
template
constexpr U
avoid_ub(UU x)
{ return is_conversion_undefined(U(x)) ? U(0) : U(x); }
template
constexpr U
avoid_ub2(UU x)
{ return is_conversion_undefined(x) ? U(0) : avoid_ub(x); }
// conversion test input data
template
static const std::array cvt_input_data = {{
avoid_ub(0xc0000080U),
avoid_ub(0xc0000081U),
avoid_ub(0xc0000082U),
avoid_ub(0xc0000084U),
avoid_ub(0xc0000088U),
avoid_ub(0xc0000090U),
avoid_ub(0xc00000A0U),
avoid_ub(0xc00000C0U),
avoid_ub(0xc000017fU),
avoid_ub(0xc0000180U),
avoid_ub(0x100000001LL),
avoid_ub(0x100000011LL),
avoid_ub(0x100000111LL),
avoid_ub(0x100001111LL),
avoid_ub(0x100011111LL),
avoid_ub(0x100111111LL),
avoid_ub(0x101111111LL),
avoid_ub(-0x100000001LL),
avoid_ub(-0x100000011LL),
avoid_ub(-0x100000111LL),
avoid_ub(-0x100001111LL),
avoid_ub(-0x100011111LL),
avoid_ub(-0x100111111LL),
avoid_ub(-0x101111111LL),
avoid_ub(std::__norm_min_v),
avoid_ub(std::__norm_min_v + 1),
avoid_ub(std::__finite_min_v),
avoid_ub(std::__finite_min_v + 1),
avoid_ub(-1),
avoid_ub(-10),
avoid_ub(-100),
avoid_ub(-1000),
avoid_ub(-10000),
avoid_ub(0),
avoid_ub(1),
avoid_ub(genHalfBits() - 1),
avoid_ub(genHalfBits()),
avoid_ub(genHalfBits() + 1),
avoid_ub(std::__finite_max_v - 1),
avoid_ub(std::__finite_max_v),
avoid_ub(std::__finite_max_v - 0xff),
avoid_ub(std::__finite_max_v - 0xff),
avoid_ub(std::__finite_max_v - 0x55),
avoid_ub(-(std::__finite_min_v + 1)),
avoid_ub(-std::__finite_max_v),
avoid_ub(std::__finite_max_v / std::pow(2., sizeof(T) * 6 - 1)),
avoid_ub2(-std::__finite_max_v / std::pow(2., sizeof(T) * 6 - 1)),
avoid_ub(std::__finite_max_v / std::pow(2., sizeof(T) * 4 - 1)),
avoid_ub2(-std::__finite_max_v / std::pow(2., sizeof(T) * 4 - 1)),
avoid_ub(std::__finite_max_v / std::pow(2., sizeof(T) * 2 - 1)),
avoid_ub2(-std::__finite_max_v / std::pow(2., sizeof(T) * 2 - 1)),
avoid_ub(std::__finite_max_v - 1),
avoid_ub(std::__finite_max_v * 0.75),
}};
template
struct cvt_inputs
{
static constexpr size_t
size()
{ return cvt_input_data.size(); }
U
operator[](size_t i) const
{ return cvt_input_data[i]; }
};
#endif // SIMD_TESTS_BITS_CONVERSIONS_H_