source/util/MathUtil.h (117 lines of code) (raw):

/** * Copyright 2004-present Facebook. All Rights Reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #define _USE_MATH_DEFINES #include <math.h> #include <stdint.h> #include <stdlib.h> #include <iostream> #include <limits> #include <numeric> #include <vector> namespace fb360_dep { namespace math_util { static inline float randf0to1() { return float(rand()) / float(RAND_MAX); } static inline float toRadians(const float deg) { return deg * static_cast<float>(M_PI) / 180.0f; } template <typename T> inline T square(const T x) { return x * x; } template <typename T> inline T clamp(const T& x, const T& a, const T& b) { return x < a ? a : x > b ? b : x; } template <typename T> inline T reflect(const T x, const T r) { return x < T(0) ? -x : x >= r ? 2 * r - x - 1 : x; } template <typename T> inline T wrap(const T x, const T r) { return x < T(0) ? r + x : x >= r ? x - r : x; } template <typename V, typename T> inline V lerp(const V x0, const V x1, const T alpha) { return x0 * (T(1) - alpha) + x1 * alpha; } template <typename T> inline T lerp(const T x0, const T x1, const T alpha) { return x0 * (T(1) - alpha) + x1 * alpha; } const static double LOG_E = log(M_E); template <typename T> class GaussianApproximation { protected: const T xMin, xMax, yMin, yMax; const T xRangeRecip, yRange; const T sigma, scale; const T a0, a2, a3; // a1 == 0 const T b0, b1, b2, b3; public: GaussianApproximation(const T xMin_, const T xMax_, const T yMin_, const T yMax_) : xMin(xMin_), xMax(xMax_), yMin(yMin_), yMax(yMax_), xRangeRecip(2 / (xMax_ - xMin_)), yRange(yMax_ - yMin_), sigma(sqrt(2.0) * 0.21), // 0.21 instead of 0.2 to keep b(x) > 0 scale(1 / (2 * sigma * sigma)), a0(1), a2(-(-2 * LOG_E * scale + 12 * exp(scale / 4) - 12) / exp(scale / 4)), a3((-4 * LOG_E * scale + 16 * exp(scale / 4) - 16) / exp(scale / 4)), b0((2 * LOG_E * scale - 4) / exp(scale / 4)), b1(-(8 * LOG_E * scale - 24) / exp(scale / 4)), b2((10 * LOG_E * scale - 36) / exp(scale / 4)), b3(-(4 * LOG_E * scale - 16) / exp(scale / 4)) {} T inline operator()(const T x) const { const T xr = (x - xMin) * xRangeRecip - T(1); const T xp = xr > T(0) ? xr : -xr; const T yp = // Horner's rule (xp < T(1.0)) ? ((xp < T(0.5)) ? a0 + xp * (xp * (a2 + xp * a3)) : b0 + xp * (b1 + xp * (b2 + xp * b3))) : T(0.0); return yp * yRange + yMin; } }; template <typename T, typename V> class BezierCurve { protected: std::vector<V> points_; public: BezierCurve() {} BezierCurve(std::vector<V> points) { for (auto p : points) { points_.push_back(p); } } void addPoint(const V p) { points_.push_back(p); } void clearPoints() { points_.clear(); } inline V operator()(const int i, const int j, const T t) const { return (i == j) ? points_[i] : lerp((*this)(i, j - 1, t), (*this)(i + 1, j, t), t); } inline V operator()(const T t) const { return (*this)(0, points_.size() - 1, t); } }; // Returns the (row, col)-tuple corresponding to the kth element in a (numRows x numCols) matrix static inline std::tuple<int, int> linearToMatrixIndex(int k, int numRows, int numCols, bool isRowMajor = true) { return isRowMajor ? std::make_tuple(k / numCols, k % numCols) : std::make_tuple(k % numRows, k / numRows); } // Returns the linear index corresponding to the (row, col)-tuple rowCik in a (numRows x numCols) // matrix static inline int matrixToLinearIndex(std::tuple<int, int> rowCol, int numRows, int numCols, bool isRowMajor = true) { return isRowMajor ? std::get<0>(rowCol) * numCols + std::get<1>(rowCol) : std::get<0>(rowCol) + numRows * std::get<1>(rowCol); } // Descending sort function for pairs (sort by first element) template <class T, class U> bool sortdescPair(const std::pair<T, U>& a, const std::pair<T, U>& b) { return (std::get<0>(a) > std::get<0>(b)); } } // end namespace math_util } // end namespace fb360_dep