(root)/
gcc-13.2.0/
libstdc++-v3/
testsuite/
experimental/
simd/
tests/
bits/
conversions.h
       1  // Copyright (C) 2020-2023 Free Software Foundation, Inc.
       2  //
       3  // This file is part of the GNU ISO C++ Library.  This library is free
       4  // software; you can redistribute it and/or modify it under the
       5  // terms of the GNU General Public License as published by the
       6  // Free Software Foundation; either version 3, or (at your option)
       7  // any later version.
       8  //
       9  // This library is distributed in the hope that it will be useful,
      10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12  // GNU General Public License for more details.
      13  //
      14  // You should have received a copy of the GNU General Public License along
      15  // with this library; see the file COPYING3.  If not see
      16  // <http://www.gnu.org/licenses/>.
      17  
      18  #ifndef SIMD_TESTS_BITS_CONVERSIONS_H_
      19  #define SIMD_TESTS_BITS_CONVERSIONS_H_
      20  #include <array>
      21  
      22  // is_conversion_undefined
      23  /* implementation-defined
      24   * ======================
      25   * §4.7 p3 (integral conversions)
      26   *  If the destination type is signed, the value is unchanged if it can be
      27   *  represented in the destination type (and bit-field width); otherwise, the
      28   *  value is implementation-defined.
      29   *
      30   * undefined
      31   * =========
      32   * §4.9/1  (floating-point conversions)
      33   *  If the source value is neither exactly represented in the destination type
      34   *  nor between two adjacent destination values the result is undefined.
      35   *
      36   * §4.10/1 (floating-integral conversions)
      37   *  floating point type can be converted to integer type.
      38   *  The behavior is undefined if the truncated value cannot be
      39   *  represented in the destination type.
      40   *
      41   * §4.10/2
      42   *  integer can be converted to floating point type.
      43   *  If the value being converted is outside the range of values that can be
      44   *  represented, the behavior is undefined.
      45   */
      46  template <typename To, typename From>
      47    constexpr bool
      48    is_conversion_undefined_impl(From x, std::true_type)
      49    {
      50      return x > static_cast<long double>(std::__finite_max_v<To>)
      51  	     || x < static_cast<long double>(std::__finite_min_v<To>);
      52    }
      53  
      54  template <typename To, typename From>
      55    constexpr bool
      56    is_conversion_undefined_impl(From, std::false_type)
      57    { return false; }
      58  
      59  template <typename To, typename From>
      60    constexpr bool
      61    is_conversion_undefined(From x)
      62    {
      63      static_assert(std::is_arithmetic<From>::value,
      64  		  "this overload is only meant for builtin arithmetic types");
      65      return is_conversion_undefined_impl<To, From>(
      66  	     x, std::integral_constant<
      67  		  bool, std::is_floating_point<From>::value
      68  			  && (std::is_integral<To>::value
      69  				|| (std::is_floating_point<To>::value
      70  				      && sizeof(From) > sizeof(To)))>());
      71    }
      72  
      73  static_assert(is_conversion_undefined<uint>(float(0x100000000LL)),
      74  	      "testing my expectations of is_conversion_undefined");
      75  static_assert(!is_conversion_undefined<float>(0x100000000LL),
      76  	      "testing my expectations of is_conversion_undefined");
      77  
      78  template <typename To, typename T, typename A>
      79    inline std::experimental::simd_mask<T, A>
      80    is_conversion_undefined(const std::experimental::simd<T, A>& x)
      81    {
      82      std::experimental::simd_mask<T, A> k = false;
      83      for (std::size_t i = 0; i < x.size(); ++i)
      84        k[i] = is_conversion_undefined(x[i]);
      85      return k;
      86    }
      87  
      88  template <class T>
      89    constexpr T
      90    genHalfBits()
      91    {
      92      if constexpr (std::is_floating_point_v<T>)
      93        return 0;
      94      else
      95        return std::__finite_max_v<T> >> (std::__digits_v<T> / 2);
      96    }
      97  
      98  template <class U, class T, class UU>
      99    constexpr U
     100    avoid_ub(UU x)
     101    { return is_conversion_undefined<T>(U(x)) ? U(0) : U(x); }
     102  
     103  template <class U, class T, class UU>
     104    constexpr U
     105    avoid_ub2(UU x)
     106    { return is_conversion_undefined<U>(x) ? U(0) : avoid_ub<U, T>(x); }
     107  
     108  // conversion test input data
     109  template <class U, class T>
     110    static const std::array<U, 53> cvt_input_data = {{
     111      avoid_ub<U, T>(0xc0000080U),
     112      avoid_ub<U, T>(0xc0000081U),
     113      avoid_ub<U, T>(0xc0000082U),
     114      avoid_ub<U, T>(0xc0000084U),
     115      avoid_ub<U, T>(0xc0000088U),
     116      avoid_ub<U, T>(0xc0000090U),
     117      avoid_ub<U, T>(0xc00000A0U),
     118      avoid_ub<U, T>(0xc00000C0U),
     119      avoid_ub<U, T>(0xc000017fU),
     120      avoid_ub<U, T>(0xc0000180U),
     121      avoid_ub<U, T>(0x100000001LL),
     122      avoid_ub<U, T>(0x100000011LL),
     123      avoid_ub<U, T>(0x100000111LL),
     124      avoid_ub<U, T>(0x100001111LL),
     125      avoid_ub<U, T>(0x100011111LL),
     126      avoid_ub<U, T>(0x100111111LL),
     127      avoid_ub<U, T>(0x101111111LL),
     128      avoid_ub<U, T>(-0x100000001LL),
     129      avoid_ub<U, T>(-0x100000011LL),
     130      avoid_ub<U, T>(-0x100000111LL),
     131      avoid_ub<U, T>(-0x100001111LL),
     132      avoid_ub<U, T>(-0x100011111LL),
     133      avoid_ub<U, T>(-0x100111111LL),
     134      avoid_ub<U, T>(-0x101111111LL),
     135      avoid_ub<U, T>(std::__norm_min_v<U>),
     136      avoid_ub<U, T>(std::__norm_min_v<U> + 1),
     137      avoid_ub<U, T>(std::__finite_min_v<U>),
     138      avoid_ub<U, T>(std::__finite_min_v<U> + 1),
     139      avoid_ub<U, T>(-1),
     140      avoid_ub<U, T>(-10),
     141      avoid_ub<U, T>(-100),
     142      avoid_ub<U, T>(-1000),
     143      avoid_ub<U, T>(-10000),
     144      avoid_ub<U, T>(0),
     145      avoid_ub<U, T>(1),
     146      avoid_ub<U, T>(genHalfBits<U>() - 1),
     147      avoid_ub<U, T>(genHalfBits<U>()),
     148      avoid_ub<U, T>(genHalfBits<U>() + 1),
     149      avoid_ub<U, T>(std::__finite_max_v<U> - 1),
     150      avoid_ub<U, T>(std::__finite_max_v<U>),
     151      avoid_ub<U, T>(std::__finite_max_v<U> - 0xff),
     152      avoid_ub<U, T>(std::__finite_max_v<U> - 0xff),
     153      avoid_ub<U, T>(std::__finite_max_v<U> - 0x55),
     154      avoid_ub<U, T>(-(std::__finite_min_v<U> + 1)),
     155      avoid_ub<U, T>(-std::__finite_max_v<U>),
     156      avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 6 - 1)),
     157      avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 6 - 1)),
     158      avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 4 - 1)),
     159      avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 4 - 1)),
     160      avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 2 - 1)),
     161      avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 2 - 1)),
     162      avoid_ub<U, T>(std::__finite_max_v<T> - 1),
     163      avoid_ub<U, T>(std::__finite_max_v<T> * 0.75),
     164    }};
     165  
     166  template <class T, class U>
     167    struct cvt_inputs
     168    {
     169      static constexpr size_t
     170      size()
     171      { return cvt_input_data<U, T>.size(); }
     172  
     173      U
     174      operator[](size_t i) const
     175      { return cvt_input_data<U, T>[i]; }
     176    };
     177  #endif  // SIMD_TESTS_BITS_CONVERSIONS_H_