diff options
author | B Stack <bgstack15@gmail.com> | 2021-02-02 21:49:34 +0000 |
---|---|---|
committer | B Stack <bgstack15@gmail.com> | 2021-02-02 21:49:34 +0000 |
commit | 26b8bd6eb07b78adad36049e03494a2931b231af (patch) | |
tree | 4d7c950512836f473a6a8cbb521c61e800db6584 /zen/basic_math.h | |
parent | Merge branch '11.5' into 'master' (diff) | |
parent | add upstream 11.6 (diff) | |
download | FreeFileSync-26b8bd6eb07b78adad36049e03494a2931b231af.tar.gz FreeFileSync-26b8bd6eb07b78adad36049e03494a2931b231af.tar.bz2 FreeFileSync-26b8bd6eb07b78adad36049e03494a2931b231af.zip |
Merge branch '11.6' into 'master'11.6
add upstream 11.6
See merge request opensource-tracking/FreeFileSync!30
Diffstat (limited to 'zen/basic_math.h')
-rw-r--r-- | zen/basic_math.h | 74 |
1 files changed, 49 insertions, 25 deletions
diff --git a/zen/basic_math.h b/zen/basic_math.h index 2171ee24..a4feb83e 100644 --- a/zen/basic_math.h +++ b/zen/basic_math.h @@ -16,7 +16,6 @@ namespace numeric { -template <class T> T abs(T value); template <class T> auto dist(T a, T b); template <class T> int sign(T value); //returns one of {-1, 0, 1} template <class T> bool isNull(T value); //...definitively fishy... @@ -24,10 +23,9 @@ template <class T> bool isNull(T value); //...definitively fishy... template <class T, class InputIterator> //precondition: range must be sorted! auto nearMatch(const T& val, InputIterator first, InputIterator last); -int64_t round(double d); //"little rounding function" - -template <class N, class D> -auto integerDivideRoundUp(N numerator, D denominator); +template <class N, class D> auto intDivRound(N numerator, D denominator); +template <class N, class D> auto intDivCeil (N numerator, D denominator); +template <class N, class D> auto intDivFloor(N numerator, D denominator); template <size_t N, class T> T power(T value); @@ -67,16 +65,6 @@ double norm2(InputIterator first, InputIterator last); //################# inline implementation ######################### template <class T> inline -T abs(T value) -{ - //static_assert(std::is_signed_v<T>); - if (value < 0) - return -value; //operator "?:" caveat: may be different type than "value" - else - return value; -} - -template <class T> inline auto dist(T a, T b) //return type might be different than T, e.g. std::chrono::duration instead of std::chrono::time_point { return a > b ? a - b : b - a; @@ -160,23 +148,59 @@ bool isNull(T value) } -inline -int64_t round(double d) +template <class N, class D> inline +auto intDivRound(N num, D den) { - assert(d - 0.5 >= std::numeric_limits<int64_t>::min() && //if double is larger than what int can represent: - d + 0.5 <= std::numeric_limits<int64_t>::max()); //=> undefined behavior! + using namespace zen; + static_assert(IsInteger<N>::value && IsInteger<D>::value); + static_assert(IsSignedInt<N>::value == IsSignedInt<D>::value); //until further + assert(den != 0); + if constexpr (IsSignedInt<N>::value) + { + if ((num < 0) != (den < 0)) + return (num - den / 2) / den; + } + return (num + den / 2) / den; +} + - return static_cast<int64_t>(d < 0 ? d - 0.5 : d + 0.5); +template <class N, class D> inline +auto intDivCeil(N num, D den) +{ + using namespace zen; + static_assert(IsInteger<N>::value && IsInteger<D>::value); + static_assert(IsSignedInt<N>::value == IsSignedInt<D>::value); //until further + assert(den != 0); + if constexpr (IsSignedInt<N>::value) + { + if ((num < 0) != (den < 0)) + return num / den; + + if (num < 0 && den < 0) + num += 2; //return (num + den + 1) / den + } + return (num + den - 1) / den; } template <class N, class D> inline -auto integerDivideRoundUp(N numerator, D denominator) +auto intDivFloor(N num, D den) { - static_assert(zen::IsInteger<N>::value); - static_assert(zen::IsInteger<D>::value); - assert(numerator >= 0 && denominator > 0); - return (numerator + denominator - 1) / denominator; + using namespace zen; + static_assert(IsInteger<N>::value && IsInteger<D>::value); + static_assert(IsSignedInt<N>::value == IsSignedInt<D>::value); //until further + assert(den != 0); + if constexpr (IsSignedInt<N>::value) + { + if ((num < 0) != (den < 0)) + { + if (num < 0) + num += 2; //return (num - den + 1) / den + + return (num - den - 1) / den; + } + } + return num / den; } |