mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Added full rounded integral division
This commit is contained in:
parent
ddfd3fa443
commit
86f76933c1
@ -9,7 +9,7 @@ https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2025 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining num copy
|
||||
Permission is hereby granted, free of charge, to any person obtaining numerator copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
@ -40,8 +40,8 @@ namespace etl
|
||||
namespace private_rounded_integral_division
|
||||
{
|
||||
//*****************************************************************************
|
||||
///\brief Checks if two values have the same sign.
|
||||
/// For signed integral types.
|
||||
// Checks if two values have the same sign.
|
||||
// For signed integral types.
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR
|
||||
@ -52,13 +52,13 @@ namespace etl
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
///\brief Checks if two values have the same sign.
|
||||
/// For unsigned integral types.
|
||||
// Checks if two values have the same sign.
|
||||
// For unsigned integral types.
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR
|
||||
typename etl::enable_if<etl::is_integral<T>::value && etl::is_unsigned<T>::value, bool>::type
|
||||
are_same_sign(T a, T b) ETL_NOEXCEPT
|
||||
are_same_sign(T /*a*/, T /*b*/) ETL_NOEXCEPT
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -68,15 +68,18 @@ namespace etl
|
||||
///\brief Integral division with rounding to ceiling.
|
||||
/// For signed integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to ceiling.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value && etl::is_signed<T>::value, T>::type
|
||||
divide_round_to_ceiling(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_to_ceiling(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T remainder = num % den;
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
T quotient = num / den;
|
||||
T quotient = numerator / denominator;
|
||||
|
||||
// If remainder is zero, already exact
|
||||
if (remainder == 0)
|
||||
@ -85,13 +88,17 @@ namespace etl
|
||||
}
|
||||
|
||||
// If signs are the same, increment quotient
|
||||
return private_rounded_integral_division::are_same_sign(num, den) ? quotient + 1 : quotient;
|
||||
return private_rounded_integral_division::are_same_sign(numerator, denominator) ? quotient + 1 : quotient;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to ceiling.
|
||||
/// For signed integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to ceiling.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -100,28 +107,31 @@ namespace etl
|
||||
etl::is_signed<T1>::value &&
|
||||
etl::is_signed<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_to_ceiling(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_to_ceiling(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_to_ceiling(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_to_ceiling(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to ceiling.
|
||||
/// For unsigned integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to ceiling.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_unsigned<T>::value,
|
||||
T>::type
|
||||
divide_round_to_ceiling(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_to_ceiling(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T remainder = num % den;
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
T quotient = num / den;
|
||||
T quotient = numerator / denominator;
|
||||
|
||||
// If remainder is zero, already exact, otherwise, increment quotient
|
||||
return remainder == 0U ? quotient : quotient + 1U;
|
||||
@ -131,6 +141,10 @@ namespace etl
|
||||
///\brief Integral division with rounding to ceiling.
|
||||
/// For unsigned integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to ceiling.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -139,28 +153,31 @@ namespace etl
|
||||
etl::is_unsigned<T1>::value &&
|
||||
etl::is_unsigned<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_to_ceiling(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_to_ceiling(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_to_ceiling(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_to_ceiling(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to floor.
|
||||
/// For signed integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to floor.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_signed<T>::value,
|
||||
T>::type
|
||||
divide_round_to_floor(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_to_floor(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T remainder = num % den;
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
T quotient = num / den;
|
||||
T quotient = numerator / denominator;
|
||||
|
||||
// If remainder is zero, already exact
|
||||
if (remainder == 0)
|
||||
@ -169,13 +186,17 @@ namespace etl
|
||||
}
|
||||
|
||||
// If signs are different, decrement quotient
|
||||
return private_rounded_integral_division::are_same_sign(num, den) ? quotient : quotient - 1;
|
||||
return private_rounded_integral_division::are_same_sign(numerator, denominator) ? quotient : quotient - 1;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to floor.
|
||||
/// For signed integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to floor.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -184,33 +205,40 @@ namespace etl
|
||||
etl::is_signed<T1>::value &&
|
||||
etl::is_signed<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_to_floor(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_to_floor(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_to_floor(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_to_floor(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to floor.
|
||||
/// For unsigned integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to floor.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_unsigned<T>::value,
|
||||
T>::type
|
||||
divide_round_to_floor(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_to_floor(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
return num / den;
|
||||
return numerator / denominator;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to floor.
|
||||
/// For unsigned integral types.
|
||||
/// For different argument types.
|
||||
//***************************************************************************
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to floor.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
/// //***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T1>::value &&
|
||||
@ -218,33 +246,36 @@ namespace etl
|
||||
etl::is_unsigned<T1>::value &&
|
||||
etl::is_unsigned<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_to_floor(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_to_floor(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
const type common_num = num;
|
||||
const type common_den = den;
|
||||
const type common_numerator = numerator;
|
||||
const type common_denominator = denominator;
|
||||
|
||||
return common_num / common_den;
|
||||
return common_numerator / common_denominator;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding towards infinity.
|
||||
/// For signed integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to infinity.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_signed<T>::value,
|
||||
T>::type
|
||||
divide_round_to_infinity(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_to_infinity(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T remainder = num % den;
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
T quotient = num / den;
|
||||
T quotient = numerator / denominator;
|
||||
|
||||
if (private_rounded_integral_division::are_same_sign(num, den))
|
||||
if (private_rounded_integral_division::are_same_sign(numerator, denominator))
|
||||
{
|
||||
// Same sign, round towards +infinity
|
||||
quotient = remainder ? quotient + 1 : quotient;
|
||||
@ -262,6 +293,10 @@ namespace etl
|
||||
///\brief Integral division with rounding towards infinity.
|
||||
/// For signed integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to infinity.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -270,28 +305,31 @@ namespace etl
|
||||
etl::is_signed<T1>::value &&
|
||||
etl::is_signed<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_to_infinity(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_to_infinity(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_to_infinity(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_to_infinity(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding towards infinity.
|
||||
/// For unsigned integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to infinity.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_unsigned<T>::value,
|
||||
T>::type
|
||||
divide_round_to_infinity(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_to_infinity(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T remainder = num % den;
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
T quotient = num / den;
|
||||
T quotient = numerator / denominator;
|
||||
|
||||
return remainder ? quotient + 1U : quotient;
|
||||
}
|
||||
@ -300,6 +338,10 @@ namespace etl
|
||||
///\brief Integral division with rounding towards infinity.
|
||||
/// For unsigned integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to infinity.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -308,77 +350,88 @@ namespace etl
|
||||
etl::is_unsigned<T1>::value &&
|
||||
etl::is_unsigned<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_to_infinity(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_to_infinity(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_to_infinity(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_to_infinity(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding towards zero.
|
||||
/// For integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to zero.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_unsigned<T>::value,
|
||||
T>::type
|
||||
divide_round_to_zero(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_to_zero(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
return num / den;
|
||||
return numerator / denominator;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding towards zero.
|
||||
/// For integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to zero.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T1>::value &&
|
||||
etl::is_integral<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_to_zero(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_to_zero(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
// Cast to common type to avoid overflow.
|
||||
const type common_num = num;
|
||||
const type common_den = den;
|
||||
const type common_numerator = numerator;
|
||||
const type common_denominator = denominator;
|
||||
|
||||
return common_num / common_den;
|
||||
return common_numerator / common_denominator;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half up.
|
||||
/// For signed integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half up.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_signed<T>::value,
|
||||
T>::type
|
||||
divide_round_half_up(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_half_up(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
// Normal division
|
||||
T quotient = num / den;
|
||||
T remainder = num % den;
|
||||
T quotient = numerator / denominator;
|
||||
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
// Work with magnitudes in unsigned form (avoids abs() overflow)
|
||||
typedef typename std::make_unsigned<T>::type utype;
|
||||
utype abs_rem = remainder < 0 ? utype(0) - utype(remainder) : utype(remainder);
|
||||
utype abs_den = den < 0 ? utype(0) - utype(den) : utype(den);
|
||||
utype abs_remainder = remainder < 0 ? utype(0) - utype(remainder) : utype(remainder);
|
||||
utype abs_denominator = denominator < 0 ? utype(0) - utype(denominator) : utype(denominator);
|
||||
|
||||
// Threshold for rounding up (half the denominator, rounded up)
|
||||
utype half_den = (abs_den + 1) / 2;
|
||||
// Threshold for rounding up (half the denominatorominator, rounded up)
|
||||
utype half_denominator = (abs_denominator + 1) / 2;
|
||||
|
||||
if (abs_rem >= half_den)
|
||||
if (abs_remainder >= half_denominator)
|
||||
{
|
||||
// Round away from zero
|
||||
if (private_rounded_integral_division::are_same_sign(num, den))
|
||||
if (private_rounded_integral_division::are_same_sign(numerator, denominator))
|
||||
{
|
||||
++quotient; // same sign ? increment
|
||||
}
|
||||
@ -395,6 +448,10 @@ namespace etl
|
||||
///\brief Integral division with rounding to half up.
|
||||
/// For signed integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half up.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -403,31 +460,34 @@ namespace etl
|
||||
etl::is_signed<T1>::value &&
|
||||
etl::is_signed<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_half_up(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_half_up(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_half_up(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_half_up(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half up.
|
||||
/// For unsigned integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half up.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_unsigned<T>::value,
|
||||
T>::type
|
||||
divide_round_half_up(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_half_up(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T remainder = num % den;
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
T quotient = num / den;
|
||||
T quotient = numerator / denominator;
|
||||
|
||||
// If remainder is at least half the divisor, round up
|
||||
if (remainder >= (den / 2U) + (den % 2U))
|
||||
if (remainder >= (denominator / 2U) + (denominator % 2U))
|
||||
{
|
||||
++quotient;
|
||||
}
|
||||
@ -439,6 +499,10 @@ namespace etl
|
||||
///\brief Integral division with rounding to half up.
|
||||
/// For unsigned integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half up.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -446,41 +510,48 @@ namespace etl
|
||||
etl::is_integral<T2>::value &&
|
||||
etl::is_unsigned<T1>::value &&
|
||||
etl::is_unsigned<T2>::value, typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_half_up(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_half_up(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_half_up(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_half_up(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half down.
|
||||
/// For signed integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half down.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_signed<T>::value,
|
||||
T>::type
|
||||
divide_round_half_down(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_half_down(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T quotient = num / den;
|
||||
const T remainder = num % den;
|
||||
const T abs_den = etl::absolute(den);
|
||||
const T abs_remainder = etl::absolute(remainder);
|
||||
const T quotient = numerator / denominator;
|
||||
const T remainder = numerator % denominator;
|
||||
const T abs_denominator = etl::absolute(denominator);
|
||||
const T abs_remainderainder = etl::absolute(remainder);
|
||||
|
||||
// Direction: +1 if result should be more positive, -1 if more negative
|
||||
const T direction = ((num >= 0) == (den >= 0)) ? 1 : -1;
|
||||
const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1;
|
||||
|
||||
// Only round away from zero if remainder is strictly greater than half the divisor
|
||||
return abs_remainder > (abs_den / 2) ? quotient + direction : quotient;
|
||||
return abs_remainderainder > (abs_denominator / 2) ? quotient + direction : quotient;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half down.
|
||||
/// For signed integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half down.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -489,31 +560,34 @@ namespace etl
|
||||
etl::is_signed<T1>::value &&
|
||||
etl::is_signed<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_half_down(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_half_down(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_half_down(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_half_down(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half down.
|
||||
/// For unsigned integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half down.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_unsigned<T>::value,
|
||||
T>::type
|
||||
divide_round_half_down(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_half_down(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T remainder = num % den;
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
T quotient = num / den;
|
||||
T quotient = numerator / denominator;
|
||||
|
||||
// If remainder is at least half the divisor, round down
|
||||
if (remainder > (den / 2U))
|
||||
if (remainder > (denominator / 2U))
|
||||
{
|
||||
++quotient;
|
||||
}
|
||||
@ -525,6 +599,10 @@ namespace etl
|
||||
///\brief Integral division with rounding to half down.
|
||||
/// For unsigned integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half down.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -532,36 +610,39 @@ namespace etl
|
||||
etl::is_integral<T2>::value &&
|
||||
etl::is_unsigned<T1>::value &&
|
||||
etl::is_unsigned<T2>::value, typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_half_down(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_half_down(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_half_down(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_half_down(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half even.
|
||||
/// For signed integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half even.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_signed<T>::value,
|
||||
T>::type
|
||||
divide_round_half_even(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_half_even(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T quotient = num / den;
|
||||
const T remainder = num % den;
|
||||
const T abs_den = etl::absolute(den);
|
||||
const T abs_remainder = etl::absolute(remainder);
|
||||
const T direction = ((num >= 0) == (den >= 0)) ? 1 : -1;
|
||||
const T quotient = numerator / denominator;
|
||||
const T remainder = numerator % denominator;
|
||||
const T abs_denominator = etl::absolute(denominator);
|
||||
const T abs_remainderainder = etl::absolute(remainder);
|
||||
const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1;
|
||||
|
||||
if ((abs_remainder * 2) < abs_den)
|
||||
if ((abs_remainderainder * 2) < abs_denominator)
|
||||
{
|
||||
return quotient;
|
||||
}
|
||||
else if ((abs_remainder * 2) > abs_den)
|
||||
else if ((abs_remainderainder * 2) > abs_denominator)
|
||||
{
|
||||
return quotient + direction;
|
||||
}
|
||||
@ -576,6 +657,10 @@ namespace etl
|
||||
///\brief Integral division with rounding to half even.
|
||||
/// For signed integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half even.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -584,34 +669,37 @@ namespace etl
|
||||
etl::is_signed<T1>::value &&
|
||||
etl::is_signed<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_half_even(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_half_even(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_half_even(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_half_even(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half even.
|
||||
/// For unsigned integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half even.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_unsigned<T>::value,
|
||||
T>::type
|
||||
divide_round_half_even(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_half_even(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T quotient = num / den;
|
||||
const T remainder = num % den;
|
||||
const T quotient = numerator / denominator;
|
||||
const T remainder = numerator % denominator;
|
||||
|
||||
if ((remainder * 2U) < den)
|
||||
if ((remainder * 2U) < denominator)
|
||||
{
|
||||
// Less than halfway, round down
|
||||
return quotient;
|
||||
}
|
||||
else if ((remainder * 2U) > den)
|
||||
else if ((remainder * 2U) > denominator)
|
||||
{
|
||||
// More than halfway, round up
|
||||
return quotient + 1U;
|
||||
@ -627,6 +715,10 @@ namespace etl
|
||||
///\brief Integral division with rounding to half even.
|
||||
/// For unsigned integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half even.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -635,36 +727,39 @@ namespace etl
|
||||
etl::is_unsigned<T1>::value &&
|
||||
etl::is_unsigned<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_half_even(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_half_even(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_half_even(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_half_even(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half odd.
|
||||
/// For signed integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half odd.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_signed<T>::value,
|
||||
T>::type
|
||||
divide_round_half_odd(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_half_odd(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T quotient = num / den;
|
||||
const T remainder = num % den;
|
||||
const T abs_den = etl::absolute(den);
|
||||
const T abs_remainder = etl::absolute(remainder);
|
||||
const T direction = ((num >= 0) == (den >= 0)) ? 1 : -1;
|
||||
const T quotient = numerator / denominator;
|
||||
const T remainder = numerator % denominator;
|
||||
const T abs_denominator = etl::absolute(denominator);
|
||||
const T abs_remainderainder = etl::absolute(remainder);
|
||||
const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1;
|
||||
|
||||
if ((abs_remainder * 2) < abs_den)
|
||||
if ((abs_remainderainder * 2) < abs_denominator)
|
||||
{
|
||||
return quotient;
|
||||
}
|
||||
else if ((abs_remainder * 2) > abs_den)
|
||||
else if ((abs_remainderainder * 2) > abs_denominator)
|
||||
{
|
||||
return quotient + direction;
|
||||
}
|
||||
@ -679,6 +774,10 @@ namespace etl
|
||||
///\brief Integral division with rounding to half odd.
|
||||
/// For signed integral types.
|
||||
/// For different parameter types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half odd.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -687,34 +786,37 @@ namespace etl
|
||||
etl::is_signed<T1>::value &&
|
||||
etl::is_signed<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_half_odd(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_half_odd(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_half_odd(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_half_odd(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
///\brief Integral division with rounding to half odd.
|
||||
/// For unsigned integral types.
|
||||
/// For identical argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half odd.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_integral<T>::value &&
|
||||
etl::is_unsigned<T>::value,
|
||||
T>::type
|
||||
divide_round_half_odd(T num, T den) ETL_NOEXCEPT
|
||||
divide_round_half_odd(T numerator, T denominator) ETL_NOEXCEPT
|
||||
{
|
||||
const T quotient = num / den;
|
||||
const T remainder = num % den;
|
||||
const T direction = ((num >= 0U) == (den >= 0U)) ? 1 : -1;
|
||||
const T quotient = numerator / denominator;
|
||||
const T remainder = numerator % denominator;
|
||||
const T direction = ((numerator >= 0U) == (denominator >= 0U)) ? 1 : -1;
|
||||
|
||||
if ((remainder * 2U) < den)
|
||||
if ((remainder * 2U) < denominator)
|
||||
{
|
||||
return quotient;
|
||||
}
|
||||
else if ((remainder * 2U) > den)
|
||||
else if ((remainder * 2U) > denominator)
|
||||
{
|
||||
return quotient + direction;
|
||||
}
|
||||
@ -729,6 +831,10 @@ namespace etl
|
||||
///\brief Integral division with rounding to half odd.
|
||||
/// For unsigned integral types.
|
||||
/// For different argument types.
|
||||
///\param numerator The numerator.
|
||||
///\param denominator The denominator.
|
||||
///\return The result of the division rounded to half odd.
|
||||
/// Return type is the etl::common_type<T1, T2>::type.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_CONSTEXPR14
|
||||
@ -737,11 +843,11 @@ namespace etl
|
||||
etl::is_unsigned<T1>::value &&
|
||||
etl::is_unsigned<T2>::value,
|
||||
typename etl::common_type<T1, T2>::type>::type
|
||||
divide_round_half_odd(T1 num, T2 den) ETL_NOEXCEPT
|
||||
divide_round_half_odd(T1 numerator, T2 denominator) ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::common_type<T1, T2>::type type;
|
||||
|
||||
return divide_round_half_odd(static_cast<type>(num), static_cast<type>(den));
|
||||
return divide_round_half_odd(static_cast<type>(numerator), static_cast<type>(denominator));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ Made invocation of delegate consrexpr for C++14
|
||||
#1132 Request: Make type_def Methods Noexcept
|
||||
#1054 Using #pragma once
|
||||
#1159 etl::fsm helper to check states id sequence at compile time
|
||||
#1160 Feature request: rounded division (similar to scaled rounding)
|
||||
|
||||
Fixes:
|
||||
Fix gamma tests (removed integral tests)
|
||||
|
||||
@ -267,6 +267,7 @@ add_executable(etl_tests
|
||||
test_rescale.cpp
|
||||
test_result.cpp
|
||||
test_rms.cpp
|
||||
test_rounded_integral_division.cpp
|
||||
test_scaled_rounding.cpp
|
||||
test_set.cpp
|
||||
test_shared_message.cpp
|
||||
|
||||
@ -3698,6 +3698,9 @@
|
||||
<ClCompile Include="..\test_delegate_observable.cpp">
|
||||
<Filter>Tests\Callbacks & Delegates</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_rounded_integral_division.cpp">
|
||||
<Filter>Tests\Maths</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\library.properties">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user