A C++ template library for embedded applications
MIT licensed
Designed and
maintained by
John Wellbelove

Scaled Rounding

Rounding algorithms for scaled integral values.

From 20.40.1 all scaling functions are ETL_NODISCARD and ETL_CONSTEXPR14.

It is often advantageous to use scaled integral values rather than floating point for performance reasons.
These functions will round the supplied values according to various popular rounding algorithms.
See http://www.clivemaxfield.com/diycalculator/sp-round.shtml

The results may be scaled or unscaled.
Scaled : The result has the same scaling as the input value.
Unscaled : The result has the scaling factor removed from the input value. 'Unscaled' is a little faster than 'scaled'.

Assume a scaling factor of 10 for all of the examples below (simulated one decimal place).
i.e. 5.1 => 51
____________________________________________________________________________________________________

Round Ceiling


Values are rounded to the next more positive integral value.

Scaling = 10
Therefore 54 represents 5.4

template <size_t Scaling, typename T>
T round_ceiling_scaled(T value)

-54 => -50    -5.4 => -5.0
-55 => -50    -5.5 => -5.0
-56 => -50    -5.6 => -5.0

54 => 60      5.4 => 6.0
55 => 60      5.5 => 6.0
56 => 60      5.5 => 6.0

template <size_t Scaling, typename T>
T round_ceiling_unscaled(T value)

-54 => -5    -5.4 => -5
-55 => -5    -5.5 => -5
-56 => -5    -5.6 => -5
54 => 6      5.4 => 6
55 => 6      5.5 => 6
56 => 6      5.6 => 6
____________________________________________________________________________________________________

Round Floor


Values are rounded to the next more negative integral value.

Scaling = 10
Therefore 54 represents 5.4

template <size_t Scaling, typename T>
T round_floor_scaled(T value)

-54 => -60     -5.4 => -6.0
-55 => -60     -5.5 => -6.0
-56 => -60     -5.6 => -6.0

54 => 50       5.4 => 5.0
55 => 50       5.5 => 5.0
56 => 50       5.6 => 5.0

template <size_t Scaling, typename T>
T round_floor_unscaled(T value)

-54 => -6      -5.4 => -6
-55 => -6      -5.5 => -6
-56 => -6      -5.6 => -6

54 => 5        5.4 => 5
55 => 5        5.5 => 5
56 => 5        5.6 => 5
____________________________________________________________________________________________________

Round Half Up


Values are rounded to the nearest integral value. 'Half' values are rounded up (towards infinity).

template <size_t Scaling, typename T>
T round_half_up_scaled(T value)

-54 => -50     -5.4 => -5.0
-55 => -60     -5.5 => -5.0
-56 => -60     -5.6 => -5.0

54 => 50
55 => 60
56 => 60

template <size_t Scaling, typename T>
T round_half_up_unscaled(T value)

-54 => -5
-55 => -6
-56 => -6

54 => 5
55 => 6
56 => 6
____________________________________________________________________________________________________

Round Half Down


Values are rounded to the nearest integral value. 'Half' values are rounded down (towards zero).

template <size_t Scaling, typename T>
T round_half_down_scaled(T value)

-54 => -50
-55 => -50
-56 => -60

54 => 50
55 => 50
56 => 60

template <size_t Scaling, typename T>
T round_half_down_unscaled(T value)

-54 => -5
-55 => -5
-56 => -6

54 =>  5
55 =>  5
56 =>  6
____________________________________________________________________________________________________

Round To Zero


Values are rounded towards zero.

template <size_t Scaling, typename T>
T round_zero_scaled(T value)

-54 => -50
-55 => -50
-56 => -50

54 => 50
55 => 50
56 => 50

template <size_t Scaling, typename T>
T round_zero_unscaled(T value)

-54 => -5
-55 => -5
-56 => -5

54 => 5
55 => 5
56 => 5

____________________________________________________________________________________________________

Round To Infinity


Values are rounded towards infinity.

template <size_t Scaling, typename T>
T round_infinity_scaled(T value)

-54 => -60
-55 => -60
-56 => -60

54 => 60
55 => 60
56 => 60

template <size_t Scaling, typename T>
T round_infinity_unscaled(T value)

-54 => -6
-55 => -6
-56 => -6

54 => 6
55 => 6
56 => 6

____________________________________________________________________________________________________

Round Half Even (Banker's Rounding)


Values are rounded to the nearest integral value. 'Half' values are rounded to the nearest even value.

template <size_t Scaling, typename T>
T round_half_even_scaled(T value)

-54 => -50
-55 => -60
-56 => -60
-64 => -60
-65 => -60
-66 => -70

54 => 50
55 => 60
56 => 60
64 => 60
65 => 60
66 => 70

template <size_t Scaling, typename T>
T round_half_even_unscaled(T value)

-54 => -5
-55 => -6
-56 => -6
-64 => -6
-65 => -6
-66 => -7

54 => 5
55 => 6
56 => 6
64 => 6
65 => 6
66 => 7

____________________________________________________________________________________________________

Round Half Odd


Values are rounded to the nearest integral value. 'Half' values are rounded to the nearest odd value.

template <size_t Scaling, typename T>
T round_half_even_scaled(T value)

-54 => -50
-55 => -50
-56 => -60
-64 => -60
-65 => -70
-66 => -70

54 => 50
55 => 50
56 => 60
64 => 60
65 => 70
66 => 70

template <size_t Scaling, typename T>
T round_half_even_unscaled(T value)

-54 => -5
-55 => -5
-56 => -6
-64 => -6
-65 => -7
-66 => -7

54 => 5
55 => 5
56 => 6
64 => 6
65 => 7
66 => 7
scaled_rounding.h