/* * This file is part of libgim. * * libgim is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * libgim is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with libgim. If not, see . * * Copyright 2010-2014 Danny Robson */ #ifndef __MATHS_HPP #define __MATHS_HPP #include #include template T abs (T value) { return value > 0 ? value : -value; } template constexpr T pow2 (T value) { return value * value; } template bool is_pow2 [[gnu::pure]] (T value); template T log2 [[gnu::pure]] (T val); template T log2up [[gnu::pure]] (T val); template double rootsquare [[gnu::pure]] (T a, T b); template typename std::common_type::type align [[gnu::pure]] (T value, U size); template T round_pow2 [[gnu::pure]] (T value); template bool is_integer [[gnu::pure]] (const T& value); template unsigned digits [[gnu::pure]] (const T& value); template T divup (const T a, const U b) { return (a + b - 1) / b; } /** * Check if two floating point numbers are approximately equal. Returns true * if the difference is less than a percentage of each individual value. * * @e maximum percentage difference for equal values */ template bool almost_equal (const T &a, const T &b) { return a == b; } template <> bool almost_equal (const float &a, const float &b); template <> bool almost_equal (const double &a, const double &b); template typename std::enable_if< std::is_arithmetic::value && std::is_arithmetic::value, bool >::type almost_equal (Ta a, Tb b) { return almost_equal (static_cast(a), static_cast(b)); } template typename std::enable_if< !std::is_arithmetic::value || !std::is_arithmetic::value, bool >::type almost_equal (const Ta &a, const Tb &b) { return a == b; } // Useful for explictly ignore equality warnings #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" template bool exactly_equal (const T &a, const U &b) { return a == b; } #pragma GCC diagnostic pop template bool almost_zero (T a) { return almost_equal (a, 0); } template bool exactly_zero (T a) { return exactly_equal (a, static_cast (0)); } //----------------------------------------------------------------------------- constexpr double PI = 3.141592653589793238462643; constexpr double to_degrees (double radians) { return radians * 180 / PI; } //----------------------------------------------------------------------------- constexpr float to_radians (float degrees) { return degrees / 180 * static_cast (PI); } constexpr double to_radians (double degrees) { return degrees / 180 * PI; } //----------------------------------------------------------------------------- /// Variadic minimum template constexpr T min (const T a) { return a; } template constexpr typename std::enable_if< std::is_unsigned::type>::value == std::is_unsigned::type>::value && std::is_integral::type>::value == std::is_integral::type>::value, typename std::common_type::type >::type min (const T a, const U b, Args ...args) { return min (a < b ? a : b, std::forward (args)...); } //----------------------------------------------------------------------------- /// Variadic maximum template constexpr T max (const T a) { return a; } template constexpr typename std::enable_if< std::is_unsigned::type>::value == std::is_unsigned::type>::value && std::is_integral::type>::value == std::is_integral::type>::value, typename std::common_type::type >::type max (const T a, const U b, Args ...args) { return max (a > b ? a : b, std::forward (args)...); } //----------------------------------------------------------------------------- template int sign (T val); //----------------------------------------------------------------------------- template T limit (const T &&val, const U &&hi, const V &&lo) { return val > hi ? hi: val < lo ? lo: std::move (val); } #include "maths.ipp" #endif // __MATHS_HPP