Embedded Template Library 1.0
Loading...
Searching...
No Matches
numeric.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2014 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_NUMERIC_INCLUDED
32#define ETL_NUMERIC_INCLUDED
33
34#include "platform.h"
35#include "iterator.h"
36#include "limits.h"
37#include "type_traits.h"
38
39#if ETL_USING_STL
40 #include <iterator>
41#endif
42
45
46namespace etl
47{
48 //***************************************************************************
56 //***************************************************************************
57 template <typename TIterator, typename T>
58 ETL_CONSTEXPR14 void iota(TIterator first, TIterator last, T value)
59 {
60 while (first != last)
61 {
62 *first++ = value++;
63 }
64 }
65
66 //***************************************************************************
69 //***************************************************************************
70 template <typename T>
71 ETL_CONSTEXPR14 typename etl::enable_if< !etl::is_pointer<T>::value && !etl::is_integral<T>::value && etl::is_floating_point<T>::value, T>::type
72 midpoint(T a, T b) ETL_NOEXCEPT
73 {
74 T lo = etl::numeric_limits<T>::min() * T(2);
75 T hi = etl::numeric_limits<T>::max() * T(2);
76
77 return ((abs(a) <= hi) && (abs(b) <= hi)) ? (a + b) / T(2)
78 : (abs(a) < lo) ? a + (b / T(2))
79 : (abs(b) < lo) ? ((a / T(2)) + b)
80 : (a / T(2)) + (b / T(2));
81 }
82
83 //***************************************************************************
86 //***************************************************************************
87 template <typename T>
88 ETL_CONSTEXPR14 typename etl::enable_if<
89 !etl::is_pointer<T>::value && etl::is_integral<T>::value && !etl::is_floating_point<T>::value && etl::is_unsigned<T>::value, T>::type
90 midpoint(T a, T b) ETL_NOEXCEPT
91 {
92 if (a > b)
93 {
94 return a - ((a - b) >> 1);
95 }
96 else
97 {
98 return a + ((b - a) >> 1);
99 }
100 }
101
102 //***************************************************************************
105 //***************************************************************************
106 template <typename T>
107 ETL_CONSTEXPR14 typename etl::enable_if<
108 !etl::is_pointer<T>::value && etl::is_integral<T>::value && !etl::is_floating_point<T>::value && etl::is_signed<T>::value, T>::type
109 midpoint(T a, T b) ETL_NOEXCEPT
110 {
111 typedef typename etl::make_unsigned<T>::type utype;
112
113 if (a > b)
114 {
115 return a - T(utype(utype(a) - utype(b)) >> 1);
116 }
117 else
118 {
119 return a + T((utype(b) - utype(a)) >> 1);
120 }
121 }
122
123 //***************************************************************************
126 //***************************************************************************
127 template <typename T>
128 ETL_CONSTEXPR14 typename etl::enable_if< etl::is_pointer<T>::value && !etl::is_integral<T>::value && !etl::is_floating_point<T>::value, T>::type
129 midpoint(T a, T b) ETL_NOEXCEPT
130 {
131 if (a > b)
132 {
133 return b + (etl::distance(b, a) / 2);
134 }
135 else
136 {
137 return a + (etl::distance(a, b) / 2);
138 }
139 }
140
141 //***************************************************************************
144 //***************************************************************************
145 template <typename T>
146 ETL_CONSTEXPR14 T midpoint(
147 T a, T b,
148 typename etl::enable_if< !etl::is_pointer<T>::value && !etl::is_integral<T>::value && !etl::is_floating_point<T>::value
149 && etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::random_access_iterator_tag>::value,
150 int>::type = 0)
151 {
152 if (a > b)
153 {
154 return b + (etl::distance(b, a) / 2);
155 }
156 else
157 {
158 return a + (etl::distance(a, b) / 2);
159 }
160 }
161
162 //***************************************************************************
166 //***************************************************************************
167 template <typename T>
168 ETL_CONSTEXPR14 T midpoint(T a, T b,
169 typename etl::enable_if<
170 (!etl::is_pointer<T>::value && !etl::is_integral<T>::value && !etl::is_floating_point<T>::value
171 && (etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::forward_iterator_tag>::value
172 || etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::bidirectional_iterator_tag>::value)),
173 int>::type = 0)
174 {
175 etl::advance(a, etl::distance(a, b) / 2);
176 return a;
177 }
178
179 //***************************************************************************
182 //***************************************************************************
183 template <typename T>
184 ETL_CONSTEXPR typename etl::enable_if<etl::is_floating_point<T>::value, T>::type lerp(T a, T b, T t) ETL_NOEXCEPT
185 {
186 return a + (t * (b - a));
187 }
188
189 //***************************************************************************
192 //***************************************************************************
193 template <typename TArithmetic1, typename TArithmetic2, typename TArithmetic3>
194 ETL_CONSTEXPR typename etl::enable_if<
195 !etl::is_floating_point<TArithmetic1>::value || !etl::is_floating_point<TArithmetic2>::value || !etl::is_floating_point<TArithmetic3>::value,
196 typename etl::conditional< etl::is_same<TArithmetic1, long double>::value || etl::is_same<TArithmetic2, long double>::value
197 || etl::is_same<TArithmetic3, long double>::value,
198 long double, double>::type>::type
199 lerp(TArithmetic1 a, TArithmetic2 b, TArithmetic3 t) ETL_NOEXCEPT
200 {
201 typedef typename etl::conditional<etl::is_integral<TArithmetic1>::value, double, TArithmetic1>::type typecast_a;
202 typedef typename etl::conditional<etl::is_integral<TArithmetic2>::value, double, TArithmetic2>::type typecast_b;
203 typedef typename etl::conditional<etl::is_integral<TArithmetic3>::value, double, TArithmetic3>::type typecast_t;
204
205 return typecast_a(a) + (typecast_t(t) * (typecast_b(b) - typecast_a(a)));
206 }
207
208 //***************************************************************************
211 //***************************************************************************
212 template <typename T>
213 ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value && etl::is_unsigned<T>::value, T>::type add_sat(T x, T y) ETL_NOEXCEPT
214 {
215 T result = static_cast<T>(x + y);
216 // Overflow occurred if result < x
217 if (result < x)
218 {
220 }
221 return result;
222 }
223
224 //***************************************************************************
227 //***************************************************************************
228 template <typename T>
229 ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value && etl::is_signed<T>::value, T>::type add_sat(T x, T y) ETL_NOEXCEPT
230 {
231 // Check for overflow: both operands have same sign and result has different sign
232 if (y > T(0))
233 {
234 // Positive overflow check
235 if (x > (etl::numeric_limits<T>::max() - y))
236 {
238 }
239 }
240 else
241 {
242 // Negative overflow check
243 if (x < (etl::numeric_limits<T>::min() - y))
244 {
246 }
247 }
248
249 return static_cast<T>(x + y);
250 }
251
252 //***************************************************************************
255 //***************************************************************************
256 template <typename T>
257 ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value && etl::is_unsigned<T>::value, T>::type sub_sat(T x, T y) ETL_NOEXCEPT
258 {
259 // Underflow occurred if y > x
260 if (y > x)
261 {
262 return T(0);
263 }
264 return static_cast<T>(x - y);
265 }
266
267 //***************************************************************************
270 //***************************************************************************
271 template <typename T>
272 ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value && etl::is_signed<T>::value, T>::type sub_sat(T x, T y) ETL_NOEXCEPT
273 {
274 // Check for overflow/underflow
275 if (y > T(0))
276 {
277 // Subtracting positive: check for underflow
278 if (x < (etl::numeric_limits<T>::min() + y))
279 {
281 }
282 }
283 else
284 {
285 // Subtracting negative (adding): check for overflow
286 if (x > (etl::numeric_limits<T>::max() + y))
287 {
289 }
290 }
291
292 return static_cast<T>(x - y);
293 }
294
295 //***************************************************************************
298 //***************************************************************************
299 template <typename T>
300 ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value && etl::is_unsigned<T>::value, T>::type mul_sat(T x, T y) ETL_NOEXCEPT
301 {
302 if ((x == T(0)) || (y == T(0)))
303 {
304 return T(0);
305 }
306
307 // Check for overflow: x * y > max => x > max / y
308 if (x > (etl::numeric_limits<T>::max() / y))
309 {
311 }
312
313 return static_cast<T>(x * y);
314 }
315
316 //***************************************************************************
319 //***************************************************************************
320 template <typename T>
321 ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value && etl::is_signed<T>::value, T>::type mul_sat(T x, T y) ETL_NOEXCEPT
322 {
323 if ((x == T(0)) || (y == T(0)))
324 {
325 return T(0);
326 }
327
328 // Both positive
329 if ((x > T(0)) && (y > T(0)))
330 {
331 if (x > (etl::numeric_limits<T>::max() / y))
332 {
334 }
335 }
336 // Both negative
337 else if ((x < T(0)) && (y < T(0)))
338 {
339 if (x < (etl::numeric_limits<T>::max() / y))
340 {
342 }
343 }
344 // Different signs (x positive, y negative)
345 else if ((x > T(0)) && (y < T(0)))
346 {
347 if (y < (etl::numeric_limits<T>::min() / x))
348 {
350 }
351 }
352 // Different signs (x negative, y positive)
353 else
354 {
355 if (x < (etl::numeric_limits<T>::min() / y))
356 {
358 }
359 }
360
361 return static_cast<T>(x * y);
362 }
363
364 //***************************************************************************
368 //***************************************************************************
369 template <typename T>
370 ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value && etl::is_unsigned<T>::value, T>::type div_sat(T x, T y) ETL_NOEXCEPT
371 {
372 return static_cast<T>(x / y);
373 }
374
375 //***************************************************************************
380 //***************************************************************************
381 template <typename T>
382 ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value && etl::is_signed<T>::value, T>::type div_sat(T x, T y) ETL_NOEXCEPT
383 {
384 // The only overflow case: min / -1 would be max + 1
385 if ((x == etl::numeric_limits<T>::min()) && (y == T(-1)))
386 {
388 }
389
390 return static_cast<T>(x / y);
391 }
392
393 //***************************************************************************
402 //***************************************************************************
403
404 // Case 1: Both unsigned.
405 template <typename R, typename T>
406 ETL_CONSTEXPR14
407 typename etl::enable_if<etl::is_integral<R>::value && etl::is_integral<T>::value && etl::is_unsigned<R>::value && etl::is_unsigned<T>::value,
408 R>::type
409 saturate_cast(T value) ETL_NOEXCEPT
410 {
411 // If sizeof(R) >= sizeof(T), all values of T fit in R.
412 // If sizeof(R) < sizeof(T), clamp to R's max. The comparison is safe
413 // because R's max fits in T when T is wider.
414 if ((sizeof(R) < sizeof(T)) && (value > static_cast<T>(etl::numeric_limits<R>::max())))
415 {
417 }
418 return static_cast<R>(value);
419 }
420
421 // Case 2: Both signed.
422 template <typename R, typename T>
423 ETL_CONSTEXPR14
424 typename etl::enable_if<etl::is_integral<R>::value && etl::is_integral<T>::value && etl::is_signed<R>::value && etl::is_signed<T>::value, R>::type
425 saturate_cast(T value) ETL_NOEXCEPT
426 {
427 // Only need to clamp when narrowing (R is smaller than T).
428 // When sizeof(R) >= sizeof(T), all values of T fit in R.
429 if (sizeof(R) < sizeof(T))
430 {
431 if (value > static_cast<T>(etl::numeric_limits<R>::max()))
432 {
434 }
435 if (value < static_cast<T>(etl::numeric_limits<R>::min()))
436 {
437 return etl::numeric_limits<R>::min();
438 }
439 }
440 return static_cast<R>(value);
441 }
442
443 // Case 3: Signed source -> Unsigned destination.
444 template <typename R, typename T>
445 ETL_CONSTEXPR14
446 typename etl::enable_if<etl::is_integral<R>::value && etl::is_integral<T>::value && etl::is_unsigned<R>::value && etl::is_signed<T>::value,
447 R>::type
448 saturate_cast(T value) ETL_NOEXCEPT
449 {
450 if (value < T(0))
451 {
452 return R(0);
453 }
454
455 typedef typename etl::make_unsigned<T>::type unsigned_t;
456 unsigned_t uvalue = static_cast<unsigned_t>(value);
457
458 // Compare in unsigned domain. R's max is always representable as unsigned_t
459 // when sizeof(T) > sizeof(R), and when sizeof(R) >= sizeof(T) all positive
460 // values of T fit in R.
461 if ((sizeof(R) < sizeof(T)) && (uvalue > static_cast<unsigned_t>(etl::numeric_limits<R>::max())))
462 {
463 return etl::numeric_limits<R>::max();
464 }
465 return static_cast<R>(value);
466 }
467
468 // Case 4: Unsigned source -> Signed destination.
469 template <typename R, typename T>
470 ETL_CONSTEXPR14
471 typename etl::enable_if<etl::is_integral<R>::value && etl::is_integral<T>::value && etl::is_signed<R>::value && etl::is_unsigned<T>::value,
472 R>::type
473 saturate_cast(T value) ETL_NOEXCEPT
474 {
475 // R's max is positive, so we can safely represent it as T (unsigned) when
476 // sizeof(T) >= sizeof(R). When sizeof(T) < sizeof(R), all values of T fit.
477 typedef typename etl::make_unsigned<R>::type unsigned_r;
478
479 if (value > static_cast<T>(static_cast<unsigned_r>(etl::numeric_limits<R>::max())))
480 {
481 return etl::numeric_limits<R>::max();
482 }
483 return static_cast<R>(value);
484 }
485} // namespace etl
486
487#endif
Definition limits.h:1714
ETL_CONSTEXPR14 void iota(TIterator first, TIterator last, T value)
Definition numeric.h:58
Definition absolute.h:40
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_unsigned< T >::value, T >::type add_sat(T x, T y) ETL_NOEXCEPT
Definition numeric.h:213
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_unsigned< T >::value, T >::type mul_sat(T x, T y) ETL_NOEXCEPT
Definition numeric.h:300
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_unsigned< T >::value, T >::type div_sat(T x, T y) ETL_NOEXCEPT
Definition numeric.h:370
ETL_CONSTEXPR14 etl::chrono::duration< TRep, TPeriod > abs(etl::chrono::duration< TRep, TPeriod > d) ETL_NOEXCEPT
Returns the absolute value of a duration.
Definition duration.h:688
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_unsigned< T >::value, T >::type sub_sat(T x, T y) ETL_NOEXCEPT
Definition numeric.h:257
ETL_CONSTEXPR etl::enable_if< etl::is_floating_point< T >::value, T >::type lerp(T a, T b, T t) ETL_NOEXCEPT
Definition numeric.h:184
ETL_CONSTEXPR14 etl::enable_if<!etl::is_pointer< T >::value &&!etl::is_integral< T >::value &&etl::is_floating_point< T >::value, T >::type midpoint(T a, T b) ETL_NOEXCEPT
Definition numeric.h:72
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< R >::value &&etl::is_integral< T >::value &&etl::is_unsigned< R >::value &&etl::is_unsigned< T >::value, R >::type saturate_cast(T value) ETL_NOEXCEPT
Definition numeric.h:409