ArmNN
 25.11
Loading...
Searching...
No Matches
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
13namespace 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// Unsigned to Unsigned
29
30template<typename Dest, typename Source>
31typename std::enable_if_t<
32 std::is_unsigned<Source>::value &&
33 std::is_unsigned<Dest>::value,
34 Dest>
35numeric_cast(Source source)
36{
37#if ENABLE_NUMERIC_CAST_CHECKS
38 if (source > std::numeric_limits<Dest>::max())
39 {
40 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting unsigned type to "
41 "narrower unsigned type. Overflow detected.");
42 }
43#endif // ENABLE_NUMERIC_CAST_CHECKS
44
45 return static_cast<Dest>(source);
46}
47
48// Signed to Signed
49
50// numeric cast from signed integral to signed integral types, checked for narrowing overflows
51template<typename Dest, typename Source>
52typename std::enable_if_t<
53 std::is_signed<Source>::value &&
54 std::is_integral<Source>::value &&
55 std::is_signed<Dest>::value &&
56 std::is_integral<Dest>::value,
57 Dest>
58numeric_cast(Source source)
59{
60#if ENABLE_NUMERIC_CAST_CHECKS
61 if (source > std::numeric_limits<Dest>::max())
62 {
63 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed integral type to narrower signed type. "
64 "Overflow detected.");
65 }
66
67 if (source < std::numeric_limits<Dest>::lowest())
68 {
69 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed integral type to narrower signed type. "
70 "Underflow detected.");
71 }
72#endif // ENABLE_NUMERIC_CAST_CHECKS
73
74 return static_cast<Dest>(source);
75}
76
77// numeric cast from floating point to floating point types, checked for narrowing overflows
78template<typename Dest, typename Source>
79typename std::enable_if_t<
80 std::is_floating_point<Source>::value &&
81 std::is_floating_point<Dest>::value,
82 Dest>
83numeric_cast(Source source)
84{
85#if ENABLE_NUMERIC_CAST_CHECKS
86 if (source > std::numeric_limits<Dest>::max())
87 {
88 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting floating point type to narrower signed type. "
89 "Overflow detected.");
90 }
91
92 if (source < std::numeric_limits<Dest>::lowest())
93 {
94 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting floating point type to narrower signed type. "
95 "Underflow detected.");
96 }
97#endif // ENABLE_NUMERIC_CAST_CHECKS
98
99 return static_cast<Dest>(source);
100}
101
102// numeric cast from floating point types (signed) to signed integral types, checked for narrowing overflows
103template<typename Dest, typename Source>
104typename std::enable_if_t<
105 std::is_floating_point<Source>::value &&
106 std::is_signed<Dest>::value &&
107 std::is_integral<Dest>::value,
108 Dest>
109numeric_cast(Source source)
110{
111#if ENABLE_NUMERIC_CAST_CHECKS
112 if (source > static_cast<Source>(std::numeric_limits<Dest>::max()))
113 {
114 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting floating point type to narrower signed type. "
115 "Overflow detected.");
116 }
117
118 if (source < static_cast<Source>(std::numeric_limits<Dest>::lowest()))
119 {
120 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting floating point type to narrower signed type. "
121 "Underflow detected.");
122 }
123#endif // ENABLE_NUMERIC_CAST_CHECKS
124
125 return static_cast<Dest>(source);
126}
127
128// numeric cast from signed integral types to floating point types (signed), checked for narrowing overflows
129template<typename Dest, typename Source>
130typename std::enable_if_t<
131 std::is_signed<Source>::value &&
132 std::is_integral<Source>::value &&
133 std::is_floating_point<Dest>::value,
134 Dest>
135numeric_cast(Source source)
136{
137#if ENABLE_NUMERIC_CAST_CHECKS
138 Dest sourceConverted = static_cast<Dest>(source);
139
140 if (sourceConverted > std::numeric_limits<Dest>::max())
141 {
142 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to narrower floating point type. "
143 "Overflow detected.");
144 }
145
146 if (sourceConverted < std::numeric_limits<Dest>::lowest())
147 {
148 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to narrower floating point type. "
149 "Underflow detected.");
150 }
151#endif // ENABLE_NUMERIC_CAST_CHECKS
152
153 return static_cast<Dest>(source);
154}
155
156// Unsigned to Signed
157
158// numeric cast from unsigned integral type to signed integral type, checked for narrowing overflows
159template<typename Dest, typename Source>
160typename std::enable_if_t<
161 std::is_signed<Dest>::value &&
162 std::is_integral<Dest>::value &&
163 std::is_unsigned<Source>::value,
164 Dest>
165numeric_cast(Source sValue)
166{
167#if ENABLE_NUMERIC_CAST_CHECKS
168 if (sValue > static_cast< typename std::make_unsigned<Dest>::type >(std::numeric_limits<Dest>::max()))
169 {
170 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting unsigned type to signed type. "
171 "Overflow detected.");
172 }
173#endif // ENABLE_NUMERIC_CAST_CHECKS
174
175 return static_cast<Dest>(sValue);
176}
177
178// numeric cast from unsigned integral type to floating point (signed), checked for narrowing overflows
179template<typename Dest, typename Source>
180typename std::enable_if_t<
181 std::is_floating_point<Dest>::value &&
182 std::is_unsigned<Source>::value,
183 Dest>
184numeric_cast(Source sValue)
185{
186#if ENABLE_NUMERIC_CAST_CHECKS
187 if (static_cast<Dest>(sValue) > std::numeric_limits<Dest>::max())
188 {
189 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting unsigned type to floating point type. "
190 "Overflow detected.");
191 }
192#endif // ENABLE_NUMERIC_CAST_CHECKS
193
194 return static_cast<Dest>(sValue);
195}
196
197// Signed to Unsigned
198
199// numeric cast from signed integral types to unsigned integral type, checked for underflows and narrowing overflows
200template<typename Dest, typename Source>
201typename std::enable_if_t<
202 std::is_unsigned<Dest>::value &&
203 std::is_signed<Source>::value &&
204 std::is_integral<Source>::value,
205 Dest>
206numeric_cast(Source sValue)
207{
208#if ENABLE_NUMERIC_CAST_CHECKS
209 if (sValue < 0)
210 {
211 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting negative value to unsigned type. "
212 "Underflow detected.");
213 }
214
215 if (static_cast< typename std::make_unsigned<Source>::type >(sValue) > std::numeric_limits<Dest>::max())
216 {
217 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to unsigned type. "
218 "Overflow detected.");
219 }
220#endif // ENABLE_NUMERIC_CAST_CHECKS
221 return static_cast<Dest>(sValue);
222}
223
224// numeric cast from floating point (signed) to unsigned integral type, checked for underflows and narrowing overflows
225template<typename Dest, typename Source>
226typename std::enable_if_t<
227 std::is_unsigned<Dest>::value &&
228 std::is_floating_point<Source>::value,
229 Dest>
230numeric_cast(Source sValue)
231{
232#if ENABLE_NUMERIC_CAST_CHECKS
233 if (sValue < 0)
234 {
235 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting negative value to unsigned type. "
236 "Underflow detected.");
237 }
238
239 if (sValue > static_cast<Source>(std::numeric_limits<Dest>::max()))
240 {
241 ARMNN_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting floating point type to unsigned type. "
242 "Overflow detected.");
243 }
244#endif // ENABLE_NUMERIC_CAST_CHECKS
245 return static_cast<Dest>(sValue);
246}
247
248#undef ENABLE_NUMERIC_CAST_CHECKS
249
250} //namespace armnn
#define ARMNN_NUMERIC_CAST_CHECK(cond, msg)
Copyright (c) 2021 ARM Limited and Contributors.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)