| #pragma once |
| |
| #ifndef TCG_NUMERIC_OPS_H |
| #define TCG_NUMERIC_OPS_H |
| |
| |
| #include "traits.h" |
| #include "sfinae.h" |
| #include "macros.h" |
| |
| |
| #include <cmath> |
| #include <limits> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace tcg |
| { |
| |
| |
| |
| |
| |
| namespace numeric_ops |
| { |
| |
| template <typename Scalar> |
| |
| inline Scalar NaN() |
| { |
| return (std::numeric_limits<Scalar>::max)(); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| template <typename Scalar> |
| inline int sign(Scalar val, Scalar tol = 0) |
| { |
| return (val > tol) ? 1 : (val < -tol) ? -1 : 0; |
| } |
| |
| |
| |
| |
| template <typename Scalar> |
| Scalar trunc(Scalar val) |
| { |
| return (val < 0) ? std::ceil(val) : std::floor(val); |
| } |
| |
| |
| template <typename Scalar> |
| Scalar truncStrict(Scalar val) |
| { |
| return (val < 0) ? std::floor(val + 1) : std::ceil(val - 1); |
| } |
| |
| |
| template <typename Scalar> |
| Scalar grow(Scalar val) |
| { |
| return (val < 0) ? std::floor(val) : std::ceil(val); |
| } |
| |
| |
| template <typename Scalar> |
| Scalar growStrict(Scalar val) |
| { |
| return (val < 0) ? std::ceil(val - 1) : std::floor(val + 1); |
| } |
| |
| |
| |
| template <typename Scalar> |
| inline bool areNear(Scalar a, Scalar b, Scalar tolerance) |
| { |
| return (std::abs(b - a) < tolerance); |
| } |
| |
| |
| |
| template <typename Scalar> |
| inline typename tcg::disable_if<tcg::is_floating_point<Scalar>::value, Scalar>::type |
| mod(Scalar val, Scalar mod) |
| { |
| Scalar m = val % mod; |
| return (m >= 0) ? m : m + mod; |
| } |
| |
| template <typename Scalar> |
| inline typename tcg::enable_if<tcg::is_floating_point<Scalar>::value, Scalar>::type |
| mod(Scalar val, Scalar mod) |
| { |
| Scalar m = fmod(val, mod); |
| return (m >= 0) ? m : m + mod; |
| } |
| |
| |
| |
| template <typename Scalar> |
| inline Scalar mod(Scalar val, Scalar a, Scalar b) |
| { |
| return a + mod(val - a, b - a); |
| } |
| |
| |
| |
| |
| template <typename Scalar> |
| inline Scalar modShift(Scalar val1, Scalar val2, Scalar m) |
| { |
| Scalar shift1 = mod(val2 - val1, m), shift2 = m - shift1; |
| return (shift2 < shift1) ? -shift2 : shift1; |
| } |
| |
| |
| |
| |
| template <typename Scalar> |
| inline Scalar modShift(Scalar val1, Scalar val2, Scalar a, Scalar b) |
| { |
| return modShift(val1 - a, val2 - a, b - a); |
| } |
| |
| |
| |
| |
| |
| |
| |
| template <typename Scalar> |
| inline typename tcg::disable_if<tcg::is_floating_point<Scalar>::value, Scalar>::type |
| div(Scalar val, Scalar d) |
| { |
| TCG_STATIC_ASSERT(-3 / 5 == 0); |
| TCG_STATIC_ASSERT(3 / -5 == 0); |
| |
| return (val < 0 || d < 0) ? (val / d) - 1 : val / d; |
| } |
| |
| |
| |
| |
| |
| template <typename Scalar> |
| inline typename tcg::enable_if<tcg::is_floating_point<Scalar>::value, Scalar>::type |
| div(Scalar val, Scalar d) |
| { |
| return std::floor(val / d); |
| } |
| |
| |
| |
| |
| |
| |
| |
| template <typename Scalar> |
| inline Scalar div(Scalar val, Scalar a, Scalar b) |
| { |
| return div(val - a, b - a); |
| } |
| |
| |
| |
| |
| template <typename T, typename Scalar> |
| inline T lerp(const T &v0, const T &v1, Scalar t) |
| { |
| return (1 - t) * v0 + t * v1; |
| } |
| |
| |
| |
| |
| |
| |
| |
| template <typename T, typename Scalar> |
| inline T bezier(const T &c0, const T &c1, const T &c2, Scalar t) |
| { |
| Scalar one_t = 1 - t, t_one_t = t * one_t; |
| return (one_t * one_t) * c0 + (t_one_t + t_one_t) * c1 + (t * t) * c2; |
| |
| |
| } |
| |
| |
| |
| |
| template <typename UScalar> |
| inline UScalar GE_2Power(UScalar val) |
| { |
| if (!val) |
| return 0; |
| --val; |
| |
| UScalar i; |
| for (i = 0; val; ++i) |
| val = val >> 1; |
| |
| return 1 << i; |
| } |
| } |
| } |
| |
| #endif |