LCOV - code coverage report
Current view: top level - home/runner/.local/lib/python3.11/site-packages/torch/include/c10/util - overflows.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 0 17 0.0 %
Date: 2026-11-05 10:19:04 Functions: 0 45 0.0 %

          Line data    Source code
       1             : #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
       2             : #pragma once
       3             : 
       4             : #include <c10/macros/Macros.h>
       5             : #include <c10/util/TypeSafeSignMath.h>
       6             : #include <c10/util/complex.h>
       7             : 
       8             : #include <cmath>
       9             : #include <limits>
      10             : #include <type_traits>
      11             : 
      12             : namespace c10 {
      13             : // In some versions of MSVC, there will be a compiler error when building.
      14             : // C4146: unary minus operator applied to unsigned type, result still unsigned
      15             : // C4804: unsafe use of type 'bool' in operation
      16             : // It can be addressed by disabling the following warning.
      17             : #ifdef _MSC_VER
      18             : #pragma warning(push)
      19             : #pragma warning(disable : 4146)
      20             : #pragma warning(disable : 4804)
      21             : #pragma warning(disable : 4018)
      22             : #endif
      23             : 
      24             : // The overflow checks may involve float to int conversion which may
      25             : // trigger precision loss warning. Re-enable the warning once the code
      26             : // is fixed. See T58053069.
      27             : C10_CLANG_DIAGNOSTIC_PUSH()
      28             : #if C10_CLANG_HAS_WARNING("-Wimplicit-float-conversion")
      29             : C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-float-conversion")
      30             : #endif
      31             : 
      32             : // bool can be converted to any type.
      33             : // Without specializing on bool, in pytorch_linux_trusty_py2_7_9_build:
      34             : // `error: comparison of constant '255' with boolean expression is always false`
      35             : // for `f > limit::max()` below
      36             : template <typename To, typename From>
      37           0 : std::enable_if_t<std::is_same_v<From, bool>, bool> overflows(
      38             :     From /*f*/,
      39             :     bool strict_unsigned [[maybe_unused]] = false) {
      40           0 :   return false;
      41             : }
      42             : 
      43             : // skip isnan and isinf check for integral types
      44             : template <typename To, typename From>
      45             : std::enable_if_t<std::is_integral_v<From> && !std::is_same_v<From, bool>, bool>
      46           0 : overflows(From f, bool strict_unsigned = false) {
      47             :   using limit = std::numeric_limits<typename scalar_value_type<To>::type>;
      48             :   if constexpr (!limit::is_signed && std::numeric_limits<From>::is_signed) {
      49             :     // allow for negative numbers to wrap using two's complement arithmetic.
      50             :     // For example, with uint8, this allows for `a - b` to be treated as
      51             :     // `a + 255 * b`.
      52           0 :     if (!strict_unsigned) {
      53           0 :       return greater_than_max<To>(f) ||
      54           0 :           (c10::is_negative(f) &&
      55           0 :            -static_cast<uint64_t>(f) > static_cast<uint64_t>(limit::max()));
      56             :     }
      57             :   }
      58           0 :   return c10::less_than_lowest<To>(f) || greater_than_max<To>(f);
      59             : }
      60             : 
      61             : template <typename To, typename From>
      62           0 : std::enable_if_t<std::is_floating_point_v<From>, bool> overflows(
      63             :     From f,
      64             :     bool strict_unsigned [[maybe_unused]] = false) {
      65             :   using ToScalar = typename scalar_value_type<To>::type;
      66             :   using limit = std::numeric_limits<ToScalar>;
      67           0 :   if (limit::has_infinity && std::isinf(static_cast<double>(f))) {
      68             :     return false;
      69             :   }
      70           0 :   if (!limit::has_quiet_NaN && (f != f)) {
      71             :     return true;
      72             :   }
      73             :   if constexpr (std::is_integral_v<ToScalar>) {
      74             :     // limit::max() for wide integer types is NOT exactly representable in
      75             :     // floating point (e.g. int64 max = 2^63-1 rounds up to 2^63), so `f >
      76             :     // limit::max()` lets a just-out-of-range value like 2^63 slip through and
      77             :     // then become INT64_MIN via static_cast. Compare against the
      78             :     // exactly-representable upper bound max()+1 == 2^digits instead. lowest()
      79             :     // is 0 or a negated power of two, so it stays exact. (digits-1 keeps the
      80             :     // shift < 64 for the uint64 case; the *2 recovers 2^digits without a 1<<64
      81             :     // overflow.)
      82             :     constexpr int digits = limit::digits;
      83             :     constexpr From upper =
      84             :         static_cast<From>(uint64_t{1} << (digits - 1)) * From{2};
      85           0 :     return f < static_cast<From>(limit::lowest()) || f >= upper;
      86             :   }
      87           0 :   return f < limit::lowest() || f > limit::max();
      88             : }
      89             : 
      90             : C10_CLANG_DIAGNOSTIC_POP()
      91             : 
      92             : #ifdef _MSC_VER
      93             : #pragma warning(pop)
      94             : #endif
      95             : 
      96             : template <typename To, typename From>
      97           0 : std::enable_if_t<is_complex<From>::value, bool> overflows(
      98             :     From f,
      99             :     bool strict_unsigned = false) {
     100             :   // casts from complex to real are considered to overflow if the
     101             :   // imaginary component is non-zero
     102           0 :   if (!is_complex<To>::value && f.imag() != 0) {
     103             :     return true;
     104             :   }
     105             :   // Check for overflow componentwise
     106             :   // (Technically, the imag overflow check is guaranteed to be false
     107             :   // when !is_complex<To>, but any optimizer worth its salt will be
     108             :   // able to figure it out.)
     109             :   return overflows<
     110             :              typename scalar_value_type<To>::type,
     111           0 :              typename From::value_type>(f.real(), strict_unsigned) ||
     112             :       overflows<
     113             :              typename scalar_value_type<To>::type,
     114           0 :              typename From::value_type>(f.imag(), strict_unsigned);
     115             : }
     116             : } // namespace c10
     117             : 
     118             : #else
     119             : #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
     120             : #endif  // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)

Generated by: LCOV version 1.16