#pragma once #include "base/assert.hpp" #include "std/cmath.hpp" #include "std/limits.hpp" #include "std/type_traits.hpp" #include "std/algorithm.hpp" #include namespace my { template inline T Abs(T x) { return (x < 0 ? -x : x); } // Compare floats or doubles for almost equality. // maxULPs - number of closest floating point values that are considered equal. // Infinity is treated as almost equal to the largest possible floating point values. // NaN produces undefined result. // See http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm for details. template bool AlmostEqual(FloatT x, FloatT y, unsigned int maxULPs = 256) { STATIC_ASSERT(is_floating_point::value); STATIC_ASSERT(numeric_limits::is_iec559); STATIC_ASSERT(!numeric_limits::is_exact); STATIC_ASSERT(!numeric_limits::is_integer); // Make sure maxUlps is non-negative and small enough that the // default NAN won't compare as equal to anything. ASSERT_LESS(maxULPs, 4 * 1024 * 1024, ()); int const bits = 8 * sizeof(FloatT); typedef typename boost::int_t::exact IntType; typedef typename boost::uint_t::exact UIntType; IntType xInt = *reinterpret_cast(&x); IntType yInt = *reinterpret_cast(&y); // Make xInt and yInt lexicographically ordered as a twos-complement int IntType const highestBit = IntType(1) << (bits - 1); if (xInt < 0) xInt = highestBit - xInt; if (yInt < 0) yInt = highestBit - yInt; UIntType const diff = Abs(xInt - yInt); return (diff <= maxULPs); } template inline TFloat DegToRad(TFloat deg) { return deg * TFloat(math::pi) / TFloat(180); } template inline TFloat RadToDeg(TFloat rad) { return rad * TFloat(180) / TFloat(math::pi); } template inline T id(T const & x) { return x; } template inline T sq(T const & x) { return x * x; } template inline T clamp(T x, TMin xmin, TMax xmax) { if (x > xmax) return xmax; if (x < xmin) return xmin; return x; } template inline bool between_s(T a, T b, T x) { return (a <= x && x <= b); } template inline bool between_i(T a, T b, T x) { return (a < x && x < b); } inline int rounds(double x) { return (x > 0.0 ? int(x + 0.5) : int(x - 0.5)); } inline size_t SizeAligned(size_t size, size_t align) { // static_cast . return size + (static_cast(-static_cast(size)) & (align - 1)); } template bool IsIntersect(T const & x0, T const & x1, T const & x2, T const & x3) { return !((x1 < x2) || (x3 < x0)); } // Computes x^n. template inline T PowUint(T x, uint64_t n) { T res = 1; for (T t = x; n > 0; n >>= 1, t *= t) if (n & 1) res *= t; return res; } template inline T NextModN(T x, T n) { return x + 1 == n ? 0 : x + 1; } template inline T PrevModN(T x, T n) { return x == 0 ? n - 1 : x - 1; } inline uint32_t NextPowOf2(uint32_t v) { v = v - 1; v |= (v >> 1); v |= (v >> 2); v |= (v >> 4); v |= (v >> 8); v |= (v >> 16); return v + 1; } // Greatest Common Divisor template T GCD(T a, T b) { T multiplier = 1; T gcd = 1; while (true) { if (a == 0 || b == 0) { gcd = max(a, b); break; } if (a == 1 || b == 1) { gcd = 1; break; } if ((a & 0x1) == 0 && (b & 0x1) == 0) { multiplier <<= 1; a >>= 1; b >>= 1; continue; } if ((a & 0x1) != 0 && (b & 0x1) != 0) { T const minV = min(a, b); T const maxV = max(a, b); a = (maxV - minV) >> 1; b = minV; continue; } if ((a & 0x1) != 0) swap(a, b); a >>= 1; } return multiplier * gcd; } }