MeVisLab Toolbox Reference
mlRangeCasts.h
Go to the documentation of this file.
1/*************************************************************************************
2**
3** Copyright 2011, MeVis Medical Solutions AG
4**
5** The user may use this file in accordance with the license agreement provided with
6** the Software or, alternatively, in accordance with the terms contained in a
7** written agreement between the user and MeVis Medical Solutions AG.
8**
9** For further information use the contact form at https://www.mevislab.de/contact
10**
11**************************************************************************************/
12
13#ifndef ML_RANGE_CASTS_H
14#define ML_RANGE_CASTS_H
15
17
18#include "mlTypeDefs.h"
19#include "mlErrorMacros.h"
20#include "mlErrorOutput.h"
21
22#include <ThirdPartyWarningsDisable.h>
23#include <climits>
24#include <ThirdPartyWarningsRestore.h>
25
27 //#define _ML_COMPILE_RANGE_CASTS_ONLY_AS_CASTS
28
30 #define _ML_COMPILE_RANGE_CASTS_WITH_CHECKS
31
33 #define _ML_RANGE_ERROR_TYPE ML_PRINT_FATAL_ERROR
34
36 #define _ML_OUTPUT_RANGE_ERROR \
37 _ML_RANGE_ERROR_TYPE("_MLRangeCheck::checked_cast", ML_OUT_OF_RANGE, "Invalid numeric cast (range check failed).");
38
39//= _ml_numeric_limits ==========================================================================
40
42 // The minimums are always returned with the equivalent signed type, while the
43 // maximums are returned with the equivalent unsigned type. This is needed so
44 // that comparisons of minimums or maximums of types with the same size but different
45 // signed-ness do not fail (the compiler would cast to one of the types).
46 template <typename T>
48
49 template<>
50 struct _ml_numeric_limits<unsigned char>
51 {
52 static const signed char MinValue = 0;
53 static const unsigned char MaxValue = UCHAR_MAX;
54 static const bool isFloat = false;
55 };
56
57 template<>
58 struct _ml_numeric_limits<signed char>
59 {
60 static const signed char MinValue = SCHAR_MIN;
61 static const unsigned char MaxValue = SCHAR_MAX;
62 static const bool isFloat = false;
63 };
64
65 template<>
66 struct _ml_numeric_limits<char>
67 {
68 static const signed char MinValue = CHAR_MIN;
69 static const unsigned char MaxValue = CHAR_MAX;
70 static const bool isFloat = false;
71 };
72
73 template<>
74 struct _ml_numeric_limits<unsigned short>
75 {
76 static const signed short MinValue = 0;
77 static const unsigned short MaxValue = USHRT_MAX;
78 static const bool isFloat = false;
79 };
80
81 template<>
82 struct _ml_numeric_limits<short>
83 {
84 static const short MinValue = SHRT_MIN;
85 static const unsigned short MaxValue = SHRT_MAX;
86 static const bool isFloat = false;
87 };
88
89 template<>
90 struct _ml_numeric_limits<unsigned int>
91 {
92 static const int MinValue = 0;
93 static const unsigned int MaxValue = UINT_MAX;
94 static const bool isFloat = false;
95 };
96
97 template<>
99 {
100 static const int MinValue = INT_MIN;
101 static const unsigned int MaxValue = INT_MAX;
102 static const bool isFloat = false;
103 };
104
105 template<>
106 struct _ml_numeric_limits<unsigned long>
107 {
108 static const long MinValue = 0;
109 static const unsigned long MaxValue = ULONG_MAX;
110 static const bool isFloat = false;
111 };
112
113 template<>
115 {
116 static const long MinValue = LONG_MIN;
117 static const unsigned long MaxValue = LONG_MAX;
118 static const bool isFloat = false;
119 };
120
121 template<>
122 struct _ml_numeric_limits<unsigned long long>
123 {
124 static const long long MinValue = 0;
125 static const unsigned long long MaxValue = ULLONG_MAX;
126 static const bool isFloat = false;
127 };
128
129 template<>
130 struct _ml_numeric_limits<long long>
131 {
132 static const long long MinValue = LLONG_MIN;
133 static const unsigned long long MaxValue = LLONG_MAX;
134 static const bool isFloat = false;
135 };
136
137 template<>
138 struct _ml_numeric_limits<float>
139 {
140 // float values cannot be compile-time constants:
141 // static const double MinValue = -FLT_MAX;
142 // static const double MaxValue = FLT_MAX;
143 static const bool isFloat = true;
144 };
145
146 template<>
147 struct _ml_numeric_limits<double>
148 {
149 // float values cannot be compile-time constants:
150 // static const double MinValue = -DBL_MAX;
151 // static const double MaxValue = DBL_MAX;
152 static const bool isFloat = true;
153 };
154
155
157 #if defined(_ML_COMPILE_RANGE_CASTS_WITH_CHECKS)
158
159//= _MLIntegerRangeCheck ========================================================================
160
163 template <bool CheckLowerBounds, bool CheckUpperBounds, typename Target, typename Source>
165
166 template <typename Target, typename Source>
167 struct _MLIntegerRangeCheck<true, true, Target, Source>
168 {
169 static inline Target checked_cast(Source srcVal)
170 {
171 if ((srcVal < static_cast<Source>(_ml_numeric_limits<Target>::MinValue)) ||
172 (srcVal > static_cast<Source>(_ml_numeric_limits<Target>::MaxValue)))
173 {
175 }
176 return static_cast<Target>(srcVal);
177 }
178 };
179
180 template <typename Target, typename Source>
181 struct _MLIntegerRangeCheck<false, true, Target, Source>
182 {
183 static inline Target checked_cast(Source srcVal)
184 {
185 if (srcVal > static_cast<Source>(_ml_numeric_limits<Target>::MaxValue))
186 {
188 }
189 return static_cast<Target>(srcVal);
190 }
191 };
192
193 template <typename Target, typename Source>
194 struct _MLIntegerRangeCheck<true, false, Target, Source>
195 {
196 static inline Target checked_cast(Source srcVal)
197 {
198 if (srcVal < static_cast<Source>(_ml_numeric_limits<Target>::MinValue))
199 {
201 }
202 return static_cast<Target>(srcVal);
203 }
204 };
205
206 template <typename Target, typename Source>
207 struct _MLIntegerRangeCheck<false, false, Target, Source>
208 {
209 static inline Target checked_cast(Source srcVal)
210 {
211 return static_cast<Target>(srcVal);
212 }
213 };
214
215//= _MLFloatRangeCheck ==========================================================================
216
217 // The default float range check does nothing.
218 template <typename Target, typename Source>
220 {
221 static inline Target checked_cast(Source arg)
222 {
223 return static_cast<Target>(arg);
224 }
225 };
226
227 // Only if casting from double to float, a range check is applied.
228 template<>
229 struct _MLFloatRangeCheck<float, double>
230 {
231 static inline float checked_cast(double arg)
232 {
233 if ((arg < static_cast<double>(-FLT_MAX)) ||
234 (arg > static_cast<double>(FLT_MAX)))
235 {
237 }
238 return static_cast<float>(arg);
239 }
240 };
241
242//= _MLRangeCheck ===============================================================================
243
246 template <bool isTargetFloat, bool isSourceFloat, typename Target, typename Source>
248
249 // Casting integer to integer performs (only the necessary) range checks.
250 template <typename Target, typename Source>
251 struct _MLRangeCheck<false, false, Target, Source>
252 {
260 };
261
262 // Casting integer to float performs no range checks.
263 template <typename Target, typename Source>
264 struct _MLRangeCheck<true, false, Target, Source>
265 {
266 static inline Target checked_cast(Source arg)
267 {
268 return static_cast<Target>(arg);
269 }
270 };
271
272 // Casting float to integer performs range checks.
273 template <typename Target, typename Source>
274 struct _MLRangeCheck<false, true, Target, Source>
275 {
276 static inline Target checked_cast(Source arg)
277 {
278 arg = floor(arg + 0.5f);
279 if ((arg < static_cast<Source>(_ml_numeric_limits<Target>::MinValue)) ||
280 (arg > static_cast<Source>(_ml_numeric_limits<Target>::MaxValue)))
281 {
283 }
284 return static_cast<Target>(arg);
285 }
286 };
287
288 template <typename Target, typename Source>
289 struct _MLRangeCheck<true, true, Target, Source>
290 {
291 static inline Target checked_cast(Source arg)
292 {
294 }
295 };
296
297 #endif
298
299//===============================================================================================
300
301 //----------------------------------------------
303 //----------------------------------------------
304 #if defined(_ML_COMPILE_RANGE_CASTS_ONLY_AS_CASTS) && defined(_ML_COMPILE_RANGE_CASTS_WITH_CHECKS)
305 #error "_ML_COMPILE_RANGE_CASTS_ONLY_AS_CASTS and _ML_COMPILE_RANGE_CAST_FUNCTIONS_WITH_CHECKS must not be set both."
306 #else
307 #if !defined(_ML_COMPILE_RANGE_CASTS_ONLY_AS_CASTS) && !defined(_ML_COMPILE_RANGE_CASTS_WITH_CHECKS)
308 // Compilation is disabled - so just insert original statements instead of function calls.
309
310 template<Target, Source>
311 inline Target mlrange_cast(Source arg) { return arg; }
312
313 #else
314
315 #if defined(_ML_COMPILE_RANGE_CASTS_ONLY_AS_CASTS)
316 // Compilation is enabled, but checks are disabled for maximum performance. Just insert casts then.
317
318 template<Target, Source>
319 inline Target mlrange_cast(Source arg) { return static_cast<Target>(arg); }
320
321 #else
322 // Compilation is enabled with checks. Insert check function calls.
323
331 template<typename Target, typename Source>
332 inline Target mlrange_cast(Source arg)
333 {
336 Target, Source>
337 ::checked_cast(arg);
338 }
339
340 #endif
341 #endif
342 #endif
343#endif
344
#define _ML_OUTPUT_RANGE_ERROR
To avoid duplication...
Target mlrange_cast(Source arg)
Generic version of checked ML casts.
double floor(T value)
static float checked_cast(double arg)
static Target checked_cast(Source arg)
Compile-check functions only if needed.
static const unsigned char MaxValue
static const signed char MinValue
static const bool isFloat
static const bool isFloat
static const int MinValue
static const bool isFloat
static const unsigned int MaxValue
static const long MinValue
static const bool isFloat
static const unsigned long MaxValue
static const long long MinValue
static const unsigned long long MaxValue
static const short MinValue
static const bool isFloat
static const unsigned short MaxValue
static const signed char MinValue
static const unsigned char MaxValue
static const unsigned char MaxValue
static const signed char MinValue
static const unsigned int MaxValue
static const unsigned long MaxValue
static const unsigned long long MaxValue
static const unsigned short MaxValue
static const signed short MinValue
Defines a template to get the minimum and maximum values for each basic integer type.