// 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_