Loading...
Searching...
No Matches
MathUtils-Impl.hpp
Go to the documentation of this file.
1// This code is based on Jet framework.
2// Copyright (c) 2018 Doyub Kim
3// CubbyFlow is voxel-based fluid simulation engine for computer games.
4// Copyright (c) 2020 CubbyFlow Team
5// Core Part: Chris Ohk, Junwoo Hwang, Jihong Sin, Seungwoo Yoo
6// AI Part: Dongheon Cho, Minseo Kim
7// We are making my contributions/submissions to this project solely in our
8// personal capacity and are not conveying any rights to any intellectual
9// property of any third parties.
10
11#ifndef CUBBYFLOW_MATH_UTILS_IMPL_HPP
12#define CUBBYFLOW_MATH_UTILS_IMPL_HPP
13
15
16#include <algorithm>
17#include <cassert>
18#include <cmath>
19
20namespace CubbyFlow
21{
22template <typename T>
23std::enable_if_t<std::is_arithmetic<T>::value, bool> Similar(T x, T y, T eps)
24{
25 return std::abs(x - y) <= eps;
26}
27
28template <typename T>
29std::enable_if_t<std::is_arithmetic<T>::value, T> Sign(T x)
30{
31 if (x >= 0)
32 {
33 return 1;
34 }
35
36 return -1;
37}
38
39template <typename T>
40std::enable_if_t<std::is_arithmetic<T>::value, T> Min3(T x, T y, T z)
41{
42 return std::min(std::min(x, y), z);
43}
44
45template <typename T>
46std::enable_if_t<std::is_arithmetic<T>::value, T> Max3(T x, T y, T z)
47{
48 return std::max(std::max(x, y), z);
49}
50
51template <typename T>
52std::enable_if_t<std::is_arithmetic<T>::value, T> MinN(const T* x, size_t n)
53{
54 T m = x[0];
55
56 for (size_t i = 1; i < n; i++)
57 {
58 m = std::min(m, x[i]);
59 }
60
61 return m;
62}
63
64template <typename T>
65std::enable_if_t<std::is_arithmetic<T>::value, T> MaxN(const T* x, size_t n)
66{
67 T m = x[0];
68
69 for (size_t i = 1; i < n; i++)
70 {
71 m = std::max(m, x[i]);
72 }
73
74 return m;
75}
76
77template <typename T>
78std::enable_if_t<std::is_arithmetic<T>::value, T> AbsMin(T x, T y)
79{
80 return (x * x < y * y) ? x : y;
81}
82
83template <typename T>
84std::enable_if_t<std::is_arithmetic<T>::value, T> AbsMax(T x, T y)
85{
86 return (x * x > y * y) ? x : y;
87}
88
89template <typename T>
90std::enable_if_t<std::is_arithmetic<T>::value, T> AbsMinN(const T* x, size_t n)
91{
92 T m = x[0];
93
94 for (size_t i = 1; i < n; i++)
95 {
96 m = AbsMin(m, x[i]);
97 }
98
99 return m;
100}
101
102template <typename T>
103std::enable_if_t<std::is_arithmetic<T>::value, T> AbsMaxN(const T* x, size_t n)
104{
105 T m = x[0];
106
107 for (size_t i = 1; i < n; i++)
108 {
109 m = AbsMax(m, x[i]);
110 }
111
112 return m;
113}
114
115template <typename T>
116std::enable_if_t<std::is_arithmetic<T>::value, size_t> ArgMin2(T x, T y)
117{
118 return (x < y) ? 0 : 1;
119}
120
121template <typename T>
122std::enable_if_t<std::is_arithmetic<T>::value, size_t> ArgMax2(T x, T y)
123{
124 return (x > y) ? 0 : 1;
125}
126
127template <typename T>
128std::enable_if_t<std::is_arithmetic<T>::value, size_t> ArgMin3(T x, T y, T z)
129{
130 if (x < y)
131 {
132 return (x < z) ? 0 : 2;
133 }
134 else
135 {
136 return (y < z) ? 1 : 2;
137 }
138}
139
140template <typename T>
141std::enable_if_t<std::is_arithmetic<T>::value, size_t> ArgMax3(T x, T y, T z)
142{
143 if (x > y)
144 {
145 return (x > z) ? 0 : 2;
146 }
147 else
148 {
149 return (y > z) ? 1 : 2;
150 }
151}
152
153template <typename T>
154std::enable_if_t<std::is_arithmetic<T>::value, T> Square(T x)
155{
156 return x * x;
157}
158
159template <typename T>
160std::enable_if_t<std::is_arithmetic<T>::value, T> Cubic(T x)
161{
162 return x * x * x;
163}
164
165template <typename T>
166std::enable_if_t<std::is_arithmetic<T>::value, T> Clamp(T val, T low, T high)
167{
168 if (val < low)
169 {
170 return low;
171 }
172
173 if (val > high)
174 {
175 return high;
176 }
177
178 return val;
179}
180
181template <typename T>
182std::enable_if_t<std::is_arithmetic<T>::value, T> DegreesToRadians(
184{
185 return angleInDegrees * PI<T>() / 180;
186}
187
188template <typename T>
189std::enable_if_t<std::is_arithmetic<T>::value, T> RadiansToDegrees(
191{
192 return angleInRadians * 180 / PI<T>();
193}
194
195template <typename T>
196std::enable_if_t<std::is_arithmetic<T>::value> GetBarycentric(T x, size_t begin,
197 size_t end,
198 size_t& i, T& t)
199{
200 assert(end > begin);
201
202 T s = std::floor(x);
203 i = static_cast<size_t>(s);
204 const size_t size = end - begin;
205
206 if (size == 1)
207 {
208 i = begin;
209 t = 0;
210 }
211 else if (i > end - 2)
212 {
213 i = end - 2;
214 t = 1;
215 }
216 else
217 {
218 t = static_cast<T>(x - s);
219 }
220}
221
222template <typename T>
223std::enable_if_t<std::is_arithmetic<T>::value> GetBarycentric(T x, size_t end,
224 size_t& i, T& t)
225{
226 assert(end > 0);
227
228 T s = std::floor(x);
229 i = static_cast<size_t>(s);
230 t = x - s;
231
232 if (end == 1)
233 {
234 i = 0;
235 t = 0;
236 }
237 else if (i > end - 2)
238 {
239 i = end - 2;
240 t = 1;
241 }
242}
243
244template <typename T>
245std::enable_if_t<std::is_arithmetic<T>::value> GetBarycentric(T x,
246 ssize_t begin,
247 ssize_t end,
248 ssize_t& i, T& t)
249{
250 assert(end > begin);
251
252 T s = std::floor(x);
253 i = static_cast<ssize_t>(s);
254 const ssize_t size = end - begin;
255
256 if (size == 1 || i < 0)
257 {
258 i = begin;
259 t = 0;
260 }
261 else if (i > end - 2)
262 {
263 i = end - 2;
264 t = 1;
265 }
266 else
267 {
268 t = static_cast<T>(x - s);
269 }
270}
271
272template <typename T>
273std::enable_if_t<std::is_arithmetic<T>::value> GetBarycentric(T x, ssize_t end,
274 ssize_t& i, T& t)
275{
276 assert(end > 0);
277
278 T s = std::floor(x);
279 i = static_cast<ssize_t>(s);
280 t = x - s;
281
282 if (end == 1 || i < 0)
283 {
284 i = 0;
285 t = 0;
286 }
287 else if (i > end - 2)
288 {
289 i = end - 2;
290 t = 1;
291 }
292}
293
294template <typename S, typename T>
295std::enable_if_t<std::is_arithmetic<T>::value, S> Lerp(const S& f0, const S& f1,
296 T t)
297{
298 return (1 - t) * f0 + t * f1;
299}
300
301template <typename S, typename T>
302std::enable_if_t<std::is_arithmetic<T>::value, S> BiLerp(
303 const S& f00, const S& f10, const S& f01, const S& f11, T tx, T ty)
304{
305 return Lerp(Lerp(f00, f10, tx), Lerp(f01, f11, tx), ty);
306}
307
308template <typename S, typename T>
309std::enable_if_t<std::is_arithmetic<T>::value, S> TriLerp(
310 const S& f000, const S& f100, const S& f010, const S& f110, const S& f001,
311 const S& f101, const S& f011, const S& f111, T tx, T ty, T tz)
312{
313 return Lerp(BiLerp(f000, f100, f010, f110, tx, ty),
314 BiLerp(f001, f101, f011, f111, tx, ty), tz);
315}
316
317template <typename S, typename T>
318std::enable_if_t<std::is_arithmetic<T>::value, S> CatmullRom(const S& f0,
319 const S& f1,
320 const S& f2,
321 const S& f3, T t)
322{
323 S d1 = (f2 - f0) / 2;
324 S d2 = (f3 - f1) / 2;
325 S D1 = f2 - f1;
326
327 S a3 = d1 + d2 - 2 * D1;
328 S a2 = 3 * D1 - 2 * d1 - d2;
329 S a1 = d1;
330 S a0 = f1;
331
332 return a3 * Cubic(t) + a2 * Square(t) + a1 * t + a0;
333}
334
335template <typename T>
336std::enable_if_t<std::is_arithmetic<T>::value, T> MonotonicCatmullRom(
337 const T& f0, const T& f1, const T& f2, const T& f3, T t)
338{
339 T d1 = (f2 - f0) / 2;
340 T d2 = (f3 - f1) / 2;
341 T D1 = f2 - f1;
342
343 if (std::fabs(D1) < std::numeric_limits<double>::epsilon())
344 {
345 d1 = d2 = 0;
346 }
347
348 if (Sign(D1) != Sign(d1))
349 {
350 d1 = 0;
351 }
352
353 if (Sign(D1) != Sign(d2))
354 {
355 d2 = 0;
356 }
357
358 T a3 = d1 + d2 - 2 * D1;
359 T a2 = 3 * D1 - 2 * d1 - d2;
360 T a1 = d1;
361 T a0 = f1;
362
363 return a3 * Cubic(t) + a2 * Square(t) + a1 * t + a0;
364}
365} // namespace CubbyFlow
366
367#endif
Definition Matrix.hpp:30
Definition pybind11Utils.hpp:21
std::enable_if_t< std::is_arithmetic< T >::value, size_t > ArgMin2(T x, T y)
Definition MathUtils-Impl.hpp:116
std::enable_if_t< std::is_arithmetic< T >::value, S > CatmullRom(const S &f0, const S &f1, const S &f2, const S &f3, T t)
Computes Catmull-Rom interpolation.
Definition MathUtils-Impl.hpp:318
std::enable_if_t< std::is_arithmetic< T >::value, size_t > ArgMax2(T x, T y)
Definition MathUtils-Impl.hpp:122
std::enable_if_t< std::is_arithmetic< T >::value, size_t > ArgMax3(T x, T y, T z)
Definition MathUtils-Impl.hpp:141
std::enable_if_t< std::is_arithmetic< T >::value, T > Min3(T x, T y, T z)
Returns the minimum value among three inputs.
Definition MathUtils-Impl.hpp:40
std::enable_if_t< std::is_arithmetic< T >::value, S > Lerp(const S &f0, const S &f1, T t)
Computes linear interpolation.
Definition MathUtils-Impl.hpp:295
std::enable_if_t< std::is_arithmetic< T >::value, T > AbsMaxN(const T *x, size_t n)
Returns absolute maximum among n-elements.
Definition MathUtils-Impl.hpp:103
std::enable_if_t< std::is_arithmetic< T >::value, T > Sign(T x)
Returns the sign of the value.
Definition MathUtils-Impl.hpp:29
std::enable_if_t< std::is_arithmetic< T >::value > GetBarycentric(T x, size_t begin, size_t end, size_t &i, T &t)
Computes the barycentric coordinate.
Definition MathUtils-Impl.hpp:196
std::enable_if_t< std::is_arithmetic< T >::value, T > MaxN(const T *x, size_t n)
Returns maximum among n-elements.
Definition MathUtils-Impl.hpp:65
std::enable_if_t< std::is_arithmetic< T >::value, T > DegreesToRadians(T angleInDegrees)
Converts degrees to radians.
Definition MathUtils-Impl.hpp:182
std::enable_if_t< std::is_arithmetic< T >::value, T > AbsMax(T x, T y)
Returns the absolute maximum value among the two inputs.
Definition MathUtils-Impl.hpp:84
std::enable_if_t< std::is_arithmetic< T >::value, T > Clamp(T val, T low, T high)
Returns the clamped value.
Definition MathUtils-Impl.hpp:166
std::enable_if_t< std::is_arithmetic< T >::value, T > RadiansToDegrees(T angleInRadians)
Converts radians to degrees.
Definition MathUtils-Impl.hpp:189
std::enable_if_t< std::is_arithmetic< T >::value, T > Cubic(T x)
Returns the cubic of x.
Definition MathUtils-Impl.hpp:160
std::enable_if_t< std::is_arithmetic< T >::value, size_t > ArgMin3(T x, T y, T z)
Definition MathUtils-Impl.hpp:128
std::enable_if_t< std::is_arithmetic< T >::value, bool > Similar(T x, T y, T eps)
Returns true if x and y are similar.
Definition MathUtils-Impl.hpp:23
std::enable_if_t< std::is_arithmetic< T >::value, T > MonotonicCatmullRom(const T &f0, const T &f1, const T &f2, const T &f3, T t)
Computes monotonic Catmull-Rom interpolation.
Definition MathUtils-Impl.hpp:336
std::enable_if_t< std::is_arithmetic< T >::value, T > Square(T x)
Returns the square of x.
Definition MathUtils-Impl.hpp:154
Matrix< T, Rows, 1 > Vector
Definition Matrix.hpp:738
std::enable_if_t< std::is_arithmetic< T >::value, T > Max3(T x, T y, T z)
Returns the maximum value among three inputs.
Definition MathUtils-Impl.hpp:46
std::enable_if_t< std::is_arithmetic< T >::value, T > AbsMinN(const T *x, size_t n)
Returns absolute minimum among n-elements.
Definition MathUtils-Impl.hpp:90
std::enable_if_t< std::is_arithmetic< T >::value, S > BiLerp(const S &f00, const S &f10, const S &f01, const S &f11, T tx, T ty)
Computes bilinear interpolation.
Definition MathUtils-Impl.hpp:302
std::enable_if_t< std::is_arithmetic< T >::value, S > TriLerp(const S &f000, const S &f100, const S &f010, const S &f110, const S &f001, const S &f101, const S &f011, const S &f111, T tx, T ty, T tz)
Computes trilinear interpolation.
Definition MathUtils-Impl.hpp:309
std::enable_if_t< std::is_arithmetic< T >::value, T > AbsMin(T x, T y)
Returns the absolute minimum value among the two inputs.
Definition MathUtils-Impl.hpp:78
std::enable_if_t< std::is_arithmetic< T >::value, T > MinN(const T *x, size_t n)
Returns minimum among n-elements.
Definition MathUtils-Impl.hpp:52