ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
math.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <complex>
13 #include <limits>
14 #include <list>
15 #include <stdexcept>
16 #include <vector>
17 
18 #include "util/logging.h"
19 
20 #ifndef M_PI
21 #define M_PI 3.14159265358979323846264338327950288
22 #endif
23 
24 namespace colmap {
25 
26 // Return 1 if number is positive, -1 if negative, and 0 if the number is 0.
27 template <typename T>
28 int SignOfNumber(const T val);
29 
30 // Check if the given floating point number is a not-a-number (NaN) value.
31 inline bool IsNaN(const float x);
32 inline bool IsNaN(const double x);
33 
34 // Check if the given floating point number is a infinity.
35 inline bool IsInf(const float x);
36 inline bool IsInf(const double x);
37 
38 // Clip the given value to a low and maximum value.
39 template <typename T>
40 inline T Clip(const T& value, const T& low, const T& high);
41 
42 // Convert angle in degree to radians.
43 inline float DegToRad(const float deg);
44 inline double DegToRad(const double deg);
45 
46 // Convert angle in radians to degree.
47 inline float RadToDeg(const float rad);
48 inline double RadToDeg(const double rad);
49 
50 // Determine median value in vector. Returns NaN for empty vectors.
51 template <typename T>
52 double Median(const std::vector<T>& elems);
53 
54 // Determine mean value in a vector.
55 template <typename T>
56 double Mean(const std::vector<T>& elems);
57 
58 // Determine sample variance in a vector.
59 template <typename T>
60 double Variance(const std::vector<T>& elems);
61 
62 // Determine sample standard deviation in a vector.
63 template <typename T>
64 double StdDev(const std::vector<T>& elems);
65 
66 // Check if any of the values in the vector is less than the given threshold.
67 template <typename T>
68 bool AnyLessThan(std::vector<T> elems, T threshold);
69 
70 // Check if any of the values in the vector is greater than the given threshold.
71 template <typename T>
72 bool AnyGreaterThan(std::vector<T> elems, T threshold);
73 
74 // Generate N-choose-K combinations.
75 //
76 // Note that elements in range [first, last) must be in sorted order,
77 // according to `std::less`.
78 template <class Iterator>
79 bool NextCombination(Iterator first, Iterator middle, Iterator last);
80 
81 // Sigmoid function.
82 template <typename T>
83 T Sigmoid(const T x, const T alpha = 1);
84 
85 // Scale values according to sigmoid transform.
86 //
87 // x \in [0, 1] -> x \in [-x0, x0] -> sigmoid(x, alpha) -> x \in [0, 1]
88 //
89 // @param x Value to be scaled in the range [0, 1].
90 // @param x0 Spread that determines the range x is scaled to.
91 // @param alpha Exponential sigmoid factor.
92 //
93 // @return The scaled value in the range [0, 1].
94 template <typename T>
95 T ScaleSigmoid(T x, const T alpha = 1, const T x0 = 10);
96 
97 // Binomial coefficient or all combinations, defined as n! / ((n - k)! k!).
98 size_t NChooseK(const size_t n, const size_t k);
99 
100 // Cast value from one type to another and truncate instead of overflow, if the
101 // input value is out of range of the output data type.
102 template <typename T1, typename T2>
103 T2 TruncateCast(const T1 value);
104 
105 // Compute the n-th percentile in the given sequence.
106 template <typename T>
107 T Percentile(const std::vector<T>& elems, const double p);
108 
110 // Implementation
112 
113 namespace internal {
114 
115 template <class Iterator>
116 bool NextCombination(Iterator first1,
117  Iterator last1,
118  Iterator first2,
119  Iterator last2) {
120  if ((first1 == last1) || (first2 == last2)) {
121  return false;
122  }
123  Iterator m1 = last1;
124  Iterator m2 = last2;
125  --m2;
126  while (--m1 != first1 && *m1 >= *m2) {
127  }
128  bool result = (m1 == first1) && *first1 >= *m2;
129  if (!result) {
130  while (first2 != m2 && *m1 >= *first2) {
131  ++first2;
132  }
133  first1 = m1;
134  std::iter_swap(first1, first2);
135  ++first1;
136  ++first2;
137  }
138  if ((first1 != last1) && (first2 != last2)) {
139  m1 = last1;
140  m2 = first2;
141  while ((m1 != first1) && (m2 != last2)) {
142  std::iter_swap(--m1, m2);
143  ++m2;
144  }
145  std::reverse(first1, m1);
146  std::reverse(first1, last1);
147  std::reverse(m2, last2);
148  std::reverse(first2, last2);
149  }
150  return !result;
151 }
152 
153 } // namespace internal
154 
155 template <typename T>
156 int SignOfNumber(const T val) {
157  return (T(0) < val) - (val < T(0));
158 }
159 
160 bool IsNaN(const float x) { return x != x; }
161 bool IsNaN(const double x) { return x != x; }
162 
163 bool IsInf(const float x) { return !IsNaN(x) && IsNaN(x - x); }
164 bool IsInf(const double x) { return !IsNaN(x) && IsNaN(x - x); }
165 
166 template <typename T>
167 T Clip(const T& value, const T& low, const T& high) {
168  return std::max(low, std::min(value, high));
169 }
170 
171 float DegToRad(const float deg) {
172  return deg * 0.0174532925199432954743716805978692718781530857086181640625f;
173 }
174 
175 double DegToRad(const double deg) {
176  return deg * 0.0174532925199432954743716805978692718781530857086181640625;
177 }
178 
179 // Convert angle in radians to degree.
180 float RadToDeg(const float rad) {
181  return rad * 57.29577951308232286464772187173366546630859375f;
182 }
183 
184 double RadToDeg(const double rad) {
185  return rad * 57.29577951308232286464772187173366546630859375;
186 }
187 
188 template <typename T>
189 double Median(const std::vector<T>& elems) {
190  CHECK(!elems.empty());
191 
192  const size_t mid_idx = elems.size() / 2;
193 
194  std::vector<T> ordered_elems = elems;
195  std::nth_element(ordered_elems.begin(), ordered_elems.begin() + mid_idx,
196  ordered_elems.end());
197 
198  if (elems.size() % 2 == 0) {
199  const T mid_element1 = ordered_elems[mid_idx];
200  const T mid_element2 = *std::max_element(
201  ordered_elems.begin(), ordered_elems.begin() + mid_idx);
202  return (mid_element1 + mid_element2) / 2.0;
203  } else {
204  return ordered_elems[mid_idx];
205  }
206 }
207 
208 template <typename T>
209 T Percentile(const std::vector<T>& elems, const double p) {
210  CHECK(!elems.empty());
211  CHECK_GE(p, 0);
212  CHECK_LE(p, 100);
213 
214  const int idx = static_cast<int>(std::round(p / 100 * (elems.size() - 1)));
215  const size_t percentile_idx =
216  std::max(0, std::min(static_cast<int>(elems.size() - 1), idx));
217 
218  std::vector<T> ordered_elems = elems;
219  std::nth_element(ordered_elems.begin(),
220  ordered_elems.begin() + percentile_idx,
221  ordered_elems.end());
222 
223  return ordered_elems.at(percentile_idx);
224 }
225 
226 template <typename T>
227 double Mean(const std::vector<T>& elems) {
228  CHECK(!elems.empty());
229  double sum = 0;
230  for (const auto el : elems) {
231  sum += static_cast<double>(el);
232  }
233  return sum / elems.size();
234 }
235 
236 template <typename T>
237 double Variance(const std::vector<T>& elems) {
238  const double mean = Mean(elems);
239  double var = 0;
240  for (const auto el : elems) {
241  const double diff = el - mean;
242  var += diff * diff;
243  }
244  return var / (elems.size() - 1);
245 }
246 
247 template <typename T>
248 double StdDev(const std::vector<T>& elems) {
249  return std::sqrt(Variance(elems));
250 }
251 
252 template <typename T>
253 bool AnyLessThan(std::vector<T> elems, T threshold) {
254  for (const auto& el : elems) {
255  if (el < threshold) {
256  return true;
257  }
258  }
259  return false;
260 }
261 
262 template <typename T>
263 bool AnyGreaterThan(std::vector<T> elems, T threshold) {
264  for (const auto& el : elems) {
265  if (el > threshold) {
266  return true;
267  }
268  }
269  return false;
270 }
271 
272 template <class Iterator>
273 bool NextCombination(Iterator first, Iterator middle, Iterator last) {
274  return internal::NextCombination(first, middle, middle, last);
275 }
276 
277 template <typename T>
278 T Sigmoid(const T x, const T alpha) {
279  return T(1) / (T(1) + exp(-x * alpha));
280 }
281 
282 template <typename T>
283 T ScaleSigmoid(T x, const T alpha, const T x0) {
284  const T t0 = Sigmoid(-x0, alpha);
285  const T t1 = Sigmoid(x0, alpha);
286  x = (Sigmoid(2 * x0 * x - x0, alpha) - t0) / (t1 - t0);
287  return x;
288 }
289 
290 template <typename T1, typename T2>
291 T2 TruncateCast(const T1 value) {
292  return std::min(
293  static_cast<T1>(std::numeric_limits<T2>::max()),
294  std::max(static_cast<T1>(std::numeric_limits<T2>::min()), value));
295 }
296 
297 } // namespace colmap
core::Tensor result
Definition: VtkUtils.cpp:76
normal_z x
bool NextCombination(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
Definition: math.h:116
bool AnyGreaterThan(std::vector< T > elems, T threshold)
Definition: math.h:263
float RadToDeg(const float rad)
Definition: math.h:180
double StdDev(const std::vector< T > &elems)
Definition: math.h:248
bool AnyLessThan(std::vector< T > elems, T threshold)
Definition: math.h:253
T Sigmoid(const T x, const T alpha=1)
Definition: math.h:278
double Variance(const std::vector< T > &elems)
Definition: math.h:237
bool NextCombination(Iterator first, Iterator middle, Iterator last)
Definition: math.h:273
int SignOfNumber(const T val)
Definition: math.h:156
double Median(const std::vector< T > &elems)
Definition: math.h:189
T ScaleSigmoid(T x, const T alpha=1, const T x0=10)
Definition: math.h:283
size_t NChooseK(const size_t n, const size_t k)
Definition: math.cc:36
double Mean(const std::vector< T > &elems)
Definition: math.h:227
bool IsNaN(const float x)
Definition: math.h:160
float DegToRad(const float deg)
Definition: math.h:171
T Clip(const T &value, const T &low, const T &high)
Definition: math.h:167
T2 TruncateCast(const T1 value)
Definition: math.h:291
T Percentile(const std::vector< T > &elems, const double p)
Definition: math.h:209
bool IsInf(const float x)
Definition: math.h:163
constexpr Rgbaf middle(0.50f, 0.50f, 0.50f, 1.00f)