| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #ifndef COLMAP_SRC_UTIL_MATH_H_ |
| #define COLMAP_SRC_UTIL_MATH_H_ |
|
|
| #include <algorithm> |
| #include <cmath> |
| #include <complex> |
| #include <limits> |
| #include <list> |
| #include <stdexcept> |
| #include <vector> |
|
|
| #include "util/logging.h" |
|
|
| #ifndef M_PI |
| #define M_PI 3.14159265358979323846264338327950288 |
| #endif |
|
|
| namespace colmap { |
|
|
| |
| template <typename T> |
| int SignOfNumber(const T val); |
|
|
| |
| inline bool IsNaN(const float x); |
| inline bool IsNaN(const double x); |
|
|
| |
| inline bool IsInf(const float x); |
| inline bool IsInf(const double x); |
|
|
| |
| template <typename T> |
| inline T Clip(const T& value, const T& low, const T& high); |
|
|
| |
| inline float DegToRad(const float deg); |
| inline double DegToRad(const double deg); |
|
|
| |
| inline float RadToDeg(const float rad); |
| inline double RadToDeg(const double rad); |
|
|
| |
| template <typename T> |
| double Median(const std::vector<T>& elems); |
|
|
| |
| template <typename T> |
| double Mean(const std::vector<T>& elems); |
|
|
| |
| template <typename T> |
| double Variance(const std::vector<T>& elems); |
|
|
| |
| template <typename T> |
| double StdDev(const std::vector<T>& elems); |
|
|
| |
| template <typename T> |
| bool AnyLessThan(std::vector<T> elems, T threshold); |
|
|
| |
| template <typename T> |
| bool AnyGreaterThan(std::vector<T> elems, T threshold); |
|
|
| |
| |
| |
| |
| template <class Iterator> |
| bool NextCombination(Iterator first, Iterator middle, Iterator last); |
|
|
| |
| template <typename T> |
| T Sigmoid(const T x, const T alpha = 1); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| template <typename T> |
| T ScaleSigmoid(T x, const T alpha = 1, const T x0 = 10); |
|
|
| |
| size_t NChooseK(const size_t n, const size_t k); |
|
|
| |
| |
| template <typename T1, typename T2> |
| T2 TruncateCast(const T1 value); |
|
|
| |
| template <typename T> |
| T Percentile(const std::vector<T>& elems, const double p); |
|
|
| |
| |
| |
|
|
| namespace internal { |
|
|
| template <class Iterator> |
| bool NextCombination(Iterator first1, Iterator last1, Iterator first2, |
| Iterator last2) { |
| if ((first1 == last1) || (first2 == last2)) { |
| return false; |
| } |
| Iterator m1 = last1; |
| Iterator m2 = last2; |
| --m2; |
| while (--m1 != first1 && *m1 >= *m2) { |
| } |
| bool result = (m1 == first1) && *first1 >= *m2; |
| if (!result) { |
| while (first2 != m2 && *m1 >= *first2) { |
| ++first2; |
| } |
| first1 = m1; |
| std::iter_swap(first1, first2); |
| ++first1; |
| ++first2; |
| } |
| if ((first1 != last1) && (first2 != last2)) { |
| m1 = last1; |
| m2 = first2; |
| while ((m1 != first1) && (m2 != last2)) { |
| std::iter_swap(--m1, m2); |
| ++m2; |
| } |
| std::reverse(first1, m1); |
| std::reverse(first1, last1); |
| std::reverse(m2, last2); |
| std::reverse(first2, last2); |
| } |
| return !result; |
| } |
|
|
| } |
|
|
| template <typename T> |
| int SignOfNumber(const T val) { |
| return (T(0) < val) - (val < T(0)); |
| } |
|
|
| bool IsNaN(const float x) { return x != x; } |
| bool IsNaN(const double x) { return x != x; } |
|
|
| bool IsInf(const float x) { return !IsNaN(x) && IsNaN(x - x); } |
| bool IsInf(const double x) { return !IsNaN(x) && IsNaN(x - x); } |
|
|
| template <typename T> |
| T Clip(const T& value, const T& low, const T& high) { |
| return std::max(low, std::min(value, high)); |
| } |
|
|
| float DegToRad(const float deg) { |
| return deg * 0.0174532925199432954743716805978692718781530857086181640625f; |
| } |
|
|
| double DegToRad(const double deg) { |
| return deg * 0.0174532925199432954743716805978692718781530857086181640625; |
| } |
|
|
| |
| float RadToDeg(const float rad) { |
| return rad * 57.29577951308232286464772187173366546630859375f; |
| } |
|
|
| double RadToDeg(const double rad) { |
| return rad * 57.29577951308232286464772187173366546630859375; |
| } |
|
|
| template <typename T> |
| double Median(const std::vector<T>& elems) { |
| CHECK(!elems.empty()); |
|
|
| const size_t mid_idx = elems.size() / 2; |
|
|
| std::vector<T> ordered_elems = elems; |
| std::nth_element(ordered_elems.begin(), ordered_elems.begin() + mid_idx, |
| ordered_elems.end()); |
|
|
| if (elems.size() % 2 == 0) { |
| const T mid_element1 = ordered_elems[mid_idx]; |
| const T mid_element2 = *std::max_element(ordered_elems.begin(), |
| ordered_elems.begin() + mid_idx); |
| return (mid_element1 + mid_element2) / 2.0; |
| } else { |
| return ordered_elems[mid_idx]; |
| } |
| } |
|
|
| template <typename T> |
| T Percentile(const std::vector<T>& elems, const double p) { |
| CHECK(!elems.empty()); |
| CHECK_GE(p, 0); |
| CHECK_LE(p, 100); |
|
|
| const int idx = static_cast<int>(std::round(p / 100 * (elems.size() - 1))); |
| const size_t percentile_idx = |
| std::max(0, std::min(static_cast<int>(elems.size() - 1), idx)); |
|
|
| std::vector<T> ordered_elems = elems; |
| std::nth_element(ordered_elems.begin(), |
| ordered_elems.begin() + percentile_idx, ordered_elems.end()); |
|
|
| return ordered_elems.at(percentile_idx); |
| } |
|
|
| template <typename T> |
| double Mean(const std::vector<T>& elems) { |
| CHECK(!elems.empty()); |
| double sum = 0; |
| for (const auto el : elems) { |
| sum += static_cast<double>(el); |
| } |
| return sum / elems.size(); |
| } |
|
|
| template <typename T> |
| double Variance(const std::vector<T>& elems) { |
| const double mean = Mean(elems); |
| double var = 0; |
| for (const auto el : elems) { |
| const double diff = el - mean; |
| var += diff * diff; |
| } |
| return var / (elems.size() - 1); |
| } |
|
|
| template <typename T> |
| double StdDev(const std::vector<T>& elems) { |
| return std::sqrt(Variance(elems)); |
| } |
|
|
| template <typename T> |
| bool AnyLessThan(std::vector<T> elems, T threshold) { |
| for (const auto& el : elems) { |
| if (el < threshold) { |
| return true; |
| } |
| } |
| return false; |
| } |
|
|
| template <typename T> |
| bool AnyGreaterThan(std::vector<T> elems, T threshold) { |
| for (const auto& el : elems) { |
| if (el > threshold) { |
| return true; |
| } |
| } |
| return false; |
| } |
|
|
| template <class Iterator> |
| bool NextCombination(Iterator first, Iterator middle, Iterator last) { |
| return internal::NextCombination(first, middle, middle, last); |
| } |
|
|
| template <typename T> |
| T Sigmoid(const T x, const T alpha) { |
| return T(1) / (T(1) + exp(-x * alpha)); |
| } |
|
|
| template <typename T> |
| T ScaleSigmoid(T x, const T alpha, const T x0) { |
| const T t0 = Sigmoid(-x0, alpha); |
| const T t1 = Sigmoid(x0, alpha); |
| x = (Sigmoid(2 * x0 * x - x0, alpha) - t0) / (t1 - t0); |
| return x; |
| } |
|
|
| template <typename T1, typename T2> |
| T2 TruncateCast(const T1 value) { |
| return std::min( |
| static_cast<T1>(std::numeric_limits<T2>::max()), |
| std::max(static_cast<T1>(std::numeric_limits<T2>::min()), value)); |
| } |
|
|
| } |
|
|
| #endif |
|
|