/* SPDX-License-Identifier: GPL-2.0-or-later * Copyright 2022 Blender Foundation. */ #pragma once /** \file * \ingroup bli */ #include #include #include #include "BLI_math_base_safe.h" #include "BLI_utildefines.h" namespace blender::math { template inline constexpr bool is_math_float_type = std::is_floating_point_v; template inline constexpr bool is_math_integral_type = std::is_integral_v; template inline bool is_zero(const T &a) { return a == T(0); } template inline bool is_any_zero(const T &a) { return is_zero(a); } template inline T abs(const T &a) { return std::abs(a); } template inline T sign(const T &a) { return (T(0) < a) - (a < T(0)); } template inline T min(const T &a, const T &b) { return std::min(a, b); } template inline T max(const T &a, const T &b) { return std::max(a, b); } template inline void max_inplace(T &a, const T &b) { a = math::max(a, b); } template inline void min_inplace(T &a, const T &b) { a = math::min(a, b); } template inline T clamp(const T &a, const T &min, const T &max) { return std::clamp(a, min, max); } template inline T mod(const T &a, const T &b) { return std::fmod(a, b); } template inline T safe_mod(const T &a, const T &b) { return (b != 0) ? std::fmod(a, b) : 0; } template inline void min_max(const T &value, T &min, T &max) { min = math::min(value, min); max = math::max(value, max); } template inline T safe_divide(const T &a, const T &b) { return (b != 0) ? a / b : T(0.0f); } template inline T floor(const T &a) { return std::floor(a); } /** * Repeats the saw-tooth pattern even on negative numbers. * ex: `mod_periodic(-3, 4) = 1`, `mod(-3, 4)= -3` */ template inline T mod_periodic(const T &a, const T &b) { return a - (b * math::floor(a / b)); } template<> inline int64_t mod_periodic(const int64_t &a, const int64_t &b) { int64_t c = (a >= 0) ? a : (-1 - a); int64_t tmp = c - (b * (c / b)); /* Negative integers have different rounding that do not match floor(). */ return (a >= 0) ? tmp : (b - 1 - tmp); } template inline T ceil(const T &a) { return std::ceil(a); } template inline T distance(const T &a, const T &b) { return std::abs(a - b); } template inline T fract(const T &a) { return a - std::floor(a); } template inline T sqrt(const T &a) { return std::sqrt(a); } template inline T cos(const T &a) { return std::cos(a); } template inline T sin(const T &a) { return std::sin(a); } template inline T tan(const T &a) { return std::tan(a); } template inline T acos(const T &a) { return std::acos(a); } template inline T pow(const T &x, const T &power) { return std::pow(x, power); } template inline T safe_acos(const T &a) { if (UNLIKELY(a <= T(-1))) { return T(M_PI); } else if (UNLIKELY(a >= T(1))) { return T(0); } return math::acos((a)); } template inline T asin(const T &a) { return std::asin(a); } template inline T atan(const T &a) { return std::atan(a); } template inline T atan2(const T &y, const T &x) { return std::atan2(y, x); } template inline T hypot(const T &y, const T &x) { return std::hypot(y, x); } template inline T interpolate(const T &a, const T &b, const FactorT &t) { auto result = a * (1 - t) + b * t; if constexpr (std::is_integral_v && std::is_floating_point_v) { result = std::round(result); } return result; } template inline T midpoint(const T &a, const T &b) { auto result = (a + b) * T(0.5); if constexpr (std::is_integral_v) { result = std::round(result); } return result; } } // namespace blender::math