ArmNN
 20.08
NumericCast.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include "Assert.hpp"
9 
10 #include <type_traits>
11 #include <limits>
12 
13 namespace armnn
14 {
15 
16 #if !defined(NDEBUG) || defined(ARMNN_NUMERIC_CAST_TESTABLE)
17 #define ENABLE_NUMERIC_CAST_CHECKS 1
18 #else
19 #define ENABLE_NUMERIC_CAST_CHECKS 0
20 #endif
21 
22 #if defined(ARMNN_NUMERIC_CAST_TESTABLE)
23 # define ARMNN_NUMERIC_CAST_CHECK(cond, msg) ConditionalThrow<std::bad_cast>(cond)
24 #else
25 # define ARMNN_NUMERIC_CAST_CHECK(cond, msg) ARMNN_ASSERT_MSG(cond, msg)
26 #endif
27 
28 template<typename Dest, typename Source>
29 typename std::enable_if_t<
30  std::is_unsigned<Source>::value &&
31  std::is_unsigned<Dest>::value
32  , Dest>
33 numeric_cast(Source source)
34 {
35 #if ENABLE_NUMERIC_CAST_CHECKS
36  if (source > std::numeric_limits<Dest>::max())
37  {
38  ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting unsigned type to "
39  "narrower unsigned type. Overflow detected.");
40  }
41 #endif // ENABLE_NUMERIC_CAST_CHECKS
42 
43  return static_cast<Dest>(source);
44 }
45 
46 template<typename Dest, typename Source>
47 typename std::enable_if_t<
48  std::is_signed<Source>::value &&
49  std::is_signed<Dest>::value
50  , Dest>
51 numeric_cast(Source source)
52 {
53  static_assert(!std::is_floating_point<Source>::value && !std::is_floating_point<Dest>::value,
54  "numeric_cast doesn't cast float.");
55 
56 #if ENABLE_NUMERIC_CAST_CHECKS
57  if (source > std::numeric_limits<Dest>::max())
58  {
59  ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to narrower signed type. "
60  "Overflow detected.");
61  }
62 
63  if (source < std::numeric_limits<Dest>::lowest())
64  {
65  ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to narrower signed type. "
66  "Underflow detected.");
67  }
68 #endif // ENABLE_NUMERIC_CAST_CHECKS
69 
70  return static_cast<Dest>(source);
71 }
72 
73 // numeric cast from unsigned to signed checked for narrowing overflows
74 template<typename Dest, typename Source>
75 typename std::enable_if_t<
76  std::is_signed<Dest>::value &&
77  std::is_unsigned<Source>::value
78  , Dest>
79 numeric_cast(Source sValue)
80 {
81  static_assert(!std::is_floating_point<Dest>::value, "numeric_cast doesn't cast to float.");
82 
83 #if ENABLE_NUMERIC_CAST_CHECKS
84  if (sValue > static_cast< typename std::make_unsigned<Dest>::type >(std::numeric_limits<Dest>::max()))
85  {
86  ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting unsigned type to signed type. "
87  "Overflow detected.");
88  }
89 #endif // ENABLE_NUMERIC_CAST_CHECKS
90 
91  return static_cast<Dest>(sValue);
92 }
93 
94 // numeric cast from signed to unsigned checked for underflows and narrowing overflows
95 template<typename Dest, typename Source>
96 typename std::enable_if_t<
97  std::is_unsigned<Dest>::value &&
98  std::is_signed<Source>::value
99  , Dest>
100 numeric_cast(Source sValue)
101 {
102  static_assert(!std::is_floating_point<Source>::value && !std::is_floating_point<Dest>::value,
103  "numeric_cast doesn't cast floats.");
104 
105 #if ENABLE_NUMERIC_CAST_CHECKS
106  if (sValue < 0)
107  {
108  ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting negative value to unsigned type. "
109  "Underflow detected.");
110  }
111 
112  if (static_cast< typename std::make_unsigned<Source>::type >(sValue) > std::numeric_limits<Dest>::max())
113  {
114  ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to unsigned type. "
115  "Overflow detected.");
116  }
117 
118 #endif // ENABLE_NUMERIC_CAST_CHECKS
119  return static_cast<Dest>(sValue);
120 }
121 
122 #undef ENABLE_NUMERIC_CAST_CHECKS
123 
124 } //namespace armnn
Copyright (c) 2020 ARM Limited.
#define ARMNN_NUMERIC_CAST_CHECK(cond, msg)
Definition: NumericCast.hpp:25
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:33