Embedded Template Library 1.0
Loading...
Searching...
No Matches
rounded_integral_division.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) 2025 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining numerator 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_ROUNDED_INTEGRAL_DIVISION_INCLUDED
32#define ETL_ROUNDED_INTEGRAL_DIVISION_INCLUDED
33
34#include "platform.h"
35#include "type_traits.h"
36#include "absolute.h"
37#include "utility.h"
38
39namespace etl
40{
41 namespace private_rounded_integral_division
42 {
43 //*****************************************************************************
44 // Checks if two values have the same sign.
45 // For signed integral types.
46 //*****************************************************************************
47 template <typename T>
48 ETL_CONSTEXPR
50 are_same_sign(T a, T b) ETL_NOEXCEPT
51 {
52 return ((a ^ b) >= 0);
53 }
54
55 //*****************************************************************************
56 // Checks if two values have the same sign.
57 // For unsigned integral types.
58 //*****************************************************************************
59 template <typename T>
60 ETL_CONSTEXPR
62 are_same_sign(T /*a*/, T /*b*/) ETL_NOEXCEPT
63 {
64 return true;
65 }
66 }
67
68 //***************************************************************************
75 //***************************************************************************
76 template <typename T>
77 ETL_CONSTEXPR14
80 {
83
84 // If remainder is zero, already exact
85 if (remainder == 0)
86 {
87 return quotient;
88 }
89
90 // If signs are the same, increment quotient
91 return private_rounded_integral_division::are_same_sign(numerator, denominator) ? quotient + 1 : quotient;
92 }
93
94 //***************************************************************************
102 //***************************************************************************
103 template <typename T1, typename T2>
104 ETL_CONSTEXPR14
109 typename etl::common_type<T1, T2>::type>::type
111 {
112 typedef typename etl::common_type<T1, T2>::type type;
113
114 return divide_round_to_ceiling(static_cast<type>(numerator), static_cast<type>(denominator));
115 }
116
117 //***************************************************************************
124 //***************************************************************************
125 template <typename T>
126 ETL_CONSTEXPR14
129 T>::type
131 {
134
135 // If remainder is zero, already exact, otherwise, increment quotient
136 return remainder == 0U ? quotient : quotient + 1U;
137 }
138
139 //***************************************************************************
147 //***************************************************************************
148 template <typename T1, typename T2>
149 ETL_CONSTEXPR14
154 typename etl::common_type<T1, T2>::type>::type
156 {
157 typedef typename etl::common_type<T1, T2>::type type;
158
159 return divide_round_to_ceiling(static_cast<type>(numerator), static_cast<type>(denominator));
160 }
161
162 //***************************************************************************
169 //***************************************************************************
170 template <typename T>
171 ETL_CONSTEXPR14
174 T>::type
176 {
179
180 // If remainder is zero, already exact
181 if (remainder == 0)
182 {
183 return quotient;
184 }
185
186 // If signs are different, decrement quotient
187 return private_rounded_integral_division::are_same_sign(numerator, denominator) ? quotient : quotient - 1;
188 }
189
190 //***************************************************************************
198 //***************************************************************************
199 template <typename T1, typename T2>
200 ETL_CONSTEXPR14
205 typename etl::common_type<T1, T2>::type>::type
207 {
208 typedef typename etl::common_type<T1, T2>::type type;
209
210 return divide_round_to_floor(static_cast<type>(numerator), static_cast<type>(denominator));
211 }
212
213 //***************************************************************************
220 //***************************************************************************
221 template <typename T>
222 ETL_CONSTEXPR14
225 T>::type
227 {
228 return numerator / denominator;
229 }
230
231 //***************************************************************************
240 template <typename T1, typename T2>
241 ETL_CONSTEXPR14
246 typename etl::common_type<T1, T2>::type>::type
248 {
249 typedef typename etl::common_type<T1, T2>::type type;
250
251 const type common_numerator = numerator;
252 const type common_denominator = denominator;
253
255 }
256
257 //***************************************************************************
264 //***************************************************************************
265 template <typename T>
266 ETL_CONSTEXPR14
269 T>::type
271 {
274
275 if (private_rounded_integral_division::are_same_sign(numerator, denominator))
276 {
277 // Same sign, round towards +infinity
278 return (remainder != 0) ? quotient + 1 : quotient;
279 }
280 else
281 {
282 // Different signs, round towards -infinity
283 return (remainder != 0) ? quotient - 1 : quotient;
284 }
285 }
286
287 //***************************************************************************
295 //***************************************************************************
296 template <typename T1, typename T2>
297 ETL_CONSTEXPR14
302 typename etl::common_type<T1, T2>::type>::type
304 {
305 typedef typename etl::common_type<T1, T2>::type type;
306
307 return divide_round_to_infinity(static_cast<type>(numerator), static_cast<type>(denominator));
308 }
309
310 //***************************************************************************
317 //***************************************************************************
318 template <typename T>
319 ETL_CONSTEXPR14
322 T>::type
324 {
327
328 return remainder ? quotient + 1U : quotient;
329 }
330
331 //***************************************************************************
339 //***************************************************************************
340 template <typename T1, typename T2>
341 ETL_CONSTEXPR14
346 typename etl::common_type<T1, T2>::type>::type
348 {
349 typedef typename etl::common_type<T1, T2>::type type;
350
351 return divide_round_to_infinity(static_cast<type>(numerator), static_cast<type>(denominator));
352 }
353
354 //***************************************************************************
361 //***************************************************************************
362 template <typename T>
363 ETL_CONSTEXPR14
366 T>::type
368 {
369 return numerator / denominator;
370 }
371
372 //***************************************************************************
380 //***************************************************************************
381 template <typename T1, typename T2>
382 ETL_CONSTEXPR14
385 typename etl::common_type<T1, T2>::type>::type
387 {
388 typedef typename etl::common_type<T1, T2>::type type;
389
390 // Cast to common type to avoid overflow.
391 const type common_numerator = numerator;
392 const type common_denominator = denominator;
393
395 }
396
397 //***************************************************************************
404 //***************************************************************************
405 template <typename T>
406 ETL_CONSTEXPR14
409 T>::type
411 {
412 // Normal division
415
416 // Work with magnitudes in unsigned form (avoids abs() overflow)
417 typedef typename std::make_unsigned<T>::type utype;
420
421 // Threshold for rounding up (half the denominatorominator, rounded up)
423
425 {
426 // Round away from zero
427 if (private_rounded_integral_division::are_same_sign(numerator, denominator))
428 {
429 return quotient + 1; // same sign ? increment
430 }
431 else
432 {
433 return quotient - 1; // different sign ? decrement
434 }
435 }
436
437 return quotient;
438 }
439
440 //***************************************************************************
448 //***************************************************************************
449 template <typename T1, typename T2>
450 ETL_CONSTEXPR14
455 typename etl::common_type<T1, T2>::type>::type
457 {
458 typedef typename etl::common_type<T1, T2>::type type;
459
460 return divide_round_half_up(static_cast<type>(numerator), static_cast<type>(denominator));
461 }
462
463 //***************************************************************************
470 //***************************************************************************
471 template <typename T>
472 ETL_CONSTEXPR14
475 T>::type
477 {
480
481 // If remainder is at least half the divisor, round up
482 return (remainder >= (denominator / 2U) + (denominator % 2U)) ? quotient + 1U : quotient;
483 }
484
485 //***************************************************************************
493 //***************************************************************************
494 template <typename T1, typename T2>
495 ETL_CONSTEXPR14
499 etl::is_unsigned<T2>::value, typename etl::common_type<T1, T2>::type>::type
501 {
502 typedef typename etl::common_type<T1, T2>::type type;
503
504 return divide_round_half_up(static_cast<type>(numerator), static_cast<type>(denominator));
505 }
506
507 //***************************************************************************
514 //***************************************************************************
515 template <typename T>
516 ETL_CONSTEXPR14
519 T>::type
521 {
524 const T abs_denominator = etl::absolute(denominator);
525 const T abs_remainderainder = etl::absolute(remainder);
526
527 // Direction: +1 if result should be more positive, -1 if more negative
528 const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1;
529
530 // Only round away from zero if remainder is strictly greater than half the divisor
532 }
533
534 //***************************************************************************
542 //***************************************************************************
543 template <typename T1, typename T2>
544 ETL_CONSTEXPR14
549 typename etl::common_type<T1, T2>::type>::type
551 {
552 typedef typename etl::common_type<T1, T2>::type type;
553
554 return divide_round_half_down(static_cast<type>(numerator), static_cast<type>(denominator));
555 }
556
557 //***************************************************************************
564 //***************************************************************************
565 template <typename T>
566 ETL_CONSTEXPR14
569 T>::type
571 {
574
575 // If remainder is at least half the divisor, round down
576 return (remainder > (denominator / 2U)) ? quotient + 1U : quotient;
577 }
578
579 //***************************************************************************
587 //***************************************************************************
588 template <typename T1, typename T2>
589 ETL_CONSTEXPR14
593 etl::is_unsigned<T2>::value, typename etl::common_type<T1, T2>::type>::type
595 {
596 typedef typename etl::common_type<T1, T2>::type type;
597
598 return divide_round_half_down(static_cast<type>(numerator), static_cast<type>(denominator));
599 }
600
601 //***************************************************************************
608 //***************************************************************************
609 template <typename T>
610 ETL_CONSTEXPR14
613 T>::type
615 {
618 const T abs_denominator = etl::absolute(denominator);
619 const T abs_remainderainder = etl::absolute(remainder);
620 const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1;
621
623 {
624 return quotient;
625 }
626 else if ((abs_remainderainder * 2) > abs_denominator)
627 {
628 return quotient + direction;
629 }
630 else
631 {
632 // Exactly halfway, round to even
633 return (quotient & 1) == 0 ? quotient : quotient + direction;
634 }
635 }
636
637 //***************************************************************************
645 //***************************************************************************
646 template <typename T1, typename T2>
647 ETL_CONSTEXPR14
652 typename etl::common_type<T1, T2>::type>::type
654 {
655 typedef typename etl::common_type<T1, T2>::type type;
656
657 return divide_round_half_even(static_cast<type>(numerator), static_cast<type>(denominator));
658 }
659
660 //***************************************************************************
667 //***************************************************************************
668 template <typename T>
669 ETL_CONSTEXPR14
672 T>::type
674 {
677
678 if ((remainder * 2U) < denominator)
679 {
680 // Less than halfway, round down
681 return quotient;
682 }
683 else if ((remainder * 2U) > denominator)
684 {
685 // More than halfway, round up
686 return quotient + 1U;
687 }
688 else
689 {
690 // Exactly halfway, round to even
691 return (quotient & 1U) == 0U ? quotient : quotient + 1;
692 }
693 }
694
695 //***************************************************************************
703 //***************************************************************************
704 template <typename T1, typename T2>
705 ETL_CONSTEXPR14
710 typename etl::common_type<T1, T2>::type>::type
712 {
713 typedef typename etl::common_type<T1, T2>::type type;
714
715 return divide_round_half_even(static_cast<type>(numerator), static_cast<type>(denominator));
716 }
717
718 //***************************************************************************
725 //***************************************************************************
726 template <typename T>
727 ETL_CONSTEXPR14
730 T>::type
732 {
735 const T abs_denominator = etl::absolute(denominator);
736 const T abs_remainderainder = etl::absolute(remainder);
737 const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1;
738
740 {
741 return quotient;
742 }
743 else if ((abs_remainderainder * 2) > abs_denominator)
744 {
745 return quotient + direction;
746 }
747 else
748 {
749 // Exactly halfway, round to odd
750 return (quotient & 1) != 0 ? quotient : quotient + direction;
751 }
752 }
753
754 //***************************************************************************
762 //***************************************************************************
763 template <typename T1, typename T2>
764 ETL_CONSTEXPR14
769 typename etl::common_type<T1, T2>::type>::type
771 {
772 typedef typename etl::common_type<T1, T2>::type type;
773
774 return divide_round_half_odd(static_cast<type>(numerator), static_cast<type>(denominator));
775 }
776
777 //***************************************************************************
784 //***************************************************************************
785 template <typename T>
786 ETL_CONSTEXPR14
789 T>::type
791 {
794 const T direction = ((numerator >= 0U) == (denominator >= 0U)) ? 1 : -1;
795
796 if ((remainder * 2U) < denominator)
797 {
798 return quotient;
799 }
800 else if ((remainder * 2U) > denominator)
801 {
802 return quotient + direction;
803 }
804 else
805 {
806 // Exactly halfway, round to odd
807 return (quotient & 1U) != 0U ? quotient : quotient + direction;
808 }
809 }
810
811 //***************************************************************************
819 //***************************************************************************
820 template <typename T1, typename T2>
821 ETL_CONSTEXPR14
826 typename etl::common_type<T1, T2>::type>::type
828 {
829 typedef typename etl::common_type<T1, T2>::type type;
830
831 return divide_round_half_odd(static_cast<type>(numerator), static_cast<type>(denominator));
832 }
833}
834
835#endif
enable_if
Definition type_traits_generator.h:1254
is_integral
Definition type_traits_generator.h:1064
is_signed
Definition type_traits_generator.h:1074
is_unsigned
Definition type_traits_generator.h:1084
bitset_ext
Definition absolute.h:39
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_signed< T >::value, T >::type divide_round_half_odd(T numerator, T denominator) ETL_NOEXCEPT
Integral division with rounding to half odd. For signed integral types. For identical argument types.
Definition rounded_integral_division.h:731
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_signed< T >::value, T >::type divide_round_to_infinity(T numerator, T denominator) ETL_NOEXCEPT
Integral division with rounding towards infinity. For signed integral types. For identical argument t...
Definition rounded_integral_division.h:270
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_unsigned< T >::value, T >::type divide_round_to_zero(T numerator, T denominator) ETL_NOEXCEPT
Integral division with rounding towards zero. For integral types. For identical argument types.
Definition rounded_integral_division.h:367
ETL_NODISCARD ETL_CONSTEXPR14 T round_half_even_unscaled(T value) ETL_NOEXCEPT
Definition scaled_rounding.h:315
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_signed< T >::value, T >::type divide_round_half_down(T numerator, T denominator) ETL_NOEXCEPT
Integral division with rounding to half down. For signed integral types. For identical argument types...
Definition rounded_integral_division.h:520
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_signed< T >::value, T >::type divide_round_half_up(T numerator, T denominator) ETL_NOEXCEPT
Integral division with rounding to half up. For signed integral types. For identical argument types.
Definition rounded_integral_division.h:410
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_signed< T >::value, T >::type divide_round_half_even(T numerator, T denominator) ETL_NOEXCEPT
Integral division with rounding to half even. For signed integral types. For identical argument types...
Definition rounded_integral_division.h:614
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_signed< T >::value, T >::type divide_round_to_floor(T numerator, T denominator) ETL_NOEXCEPT
Integral division with rounding to floor. For signed integral types. For identical argument types.
Definition rounded_integral_division.h:175
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_signed< T >::value, T >::type divide_round_to_ceiling(T numerator, T denominator) ETL_NOEXCEPT
Integral division with rounding to ceiling. For signed integral types. For identical argument types.
Definition rounded_integral_division.h:79