summaryrefslogtreecommitdiff
path: root/zen/basic_math.h
diff options
context:
space:
mode:
Diffstat (limited to 'zen/basic_math.h')
-rw-r--r--zen/basic_math.h74
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;
}
bgstack15