🛰️航天仿真算法库 SpaceAST 0.0.1
载入中...
搜索中...
未找到
MathOperator.hpp
浏览该文件的文档.
1
19
20#pragma once
21
22#include "AstGlobal.h"
23#include <cmath> // for sqrt
24#include <assert.h> // for assert
25#include <type_traits> // for std::is_pointer
26#include <array> // for std::array
27#include <iterator> // for std::size in C++17
28#include <cassert> // for assert
29
30AST_NAMESPACE_BEGIN
31
32#ifndef A_LIKELY
33# define A_LIKELY(expr) (expr)
34#endif
35
36
37typedef std::array<double, 3> array3d;
38typedef std::array<double, 6> array6d;
39
40
46template<typename _Scalar, size_t Row, size_t Col>
47class MatrixMN;
48
57namespace math{
58
59
60inline std::pair<double, double> twoSum(double a, double b) {
61 double s = a + b;
62 double t = s - a;
63 double e = (a - (s - t)) + (b - t);
64 return {s, e};
65}
66
67inline double eps(double t)
68{
69 if (t == 0)
70 //return pow(2.0, -1074.0);
71 return pow(2.0, -1075.0);
72 else
73 //return pow(2.0, -52.0 + floor(log(fabs(t)) / log(2.0)));
74 return pow(2.0, -53.0 + floor(log(fabs(t)) / log(2.0)));
75}
76
77// msvc has std::size for vc2015+
78#if defined _MSC_VER || __cplusplus >= 201703L
79
80using std::size; // use std::size in stdlib
81
82#else
83
84template <typename Container>
85auto size(const Container& vec) noexcept
86 -> decltype(vec.size())
87{
88 return vec.size();
89}
90
91template <class _Scalar, size_t N>
92constexpr size_t size(const _Scalar (&)[N]) noexcept
93{
94 return N;
95}
96#endif
97
98
100
101template<typename _Scalar>
102int sign(_Scalar val)
103{
104 if(val > 0)
105 return 1;
106 else if(val < 0)
107 return -1;
108 return 0;
109}
110
111template<typename T>
112inline
113typename std::enable_if<std::is_arithmetic<T>::value, T>::type
114rem(T x, T y)
115{
116 return x - int(x / y) * y;
117}
118
119
120template<typename T>
121inline typename std::enable_if<std::is_floating_point<T>::value, T>::type
122mod(T x, T y)
123{
124 if (y == 0) return x;
125 return x - floor(x / y) * y;
126}
127
128
129template<typename T>
130inline
131typename std::enable_if<std::is_arithmetic<T>::value, T>::type
132fix(T x)
133{
134 return (int)x;
135}
136
137
139
140inline double cot(double a)
141{
142 return cos(a) / sin(a);
143};
144
145inline double acot(double a)
146{
147 return atan(1 / a);
148}
149
151
152template<typename Container1, typename Container2>
153inline double dot(const Container1& vec1, const Container2& vec2)
154{
155 assert (size(vec1) == size(vec2));
156 double retval = 0;
157 size_t s = size(vec2);
158 for (size_t i = 0; i < s; i++)
159 {
160 retval += vec1[i] * vec2[i];
161 }
162 return retval;
163}
164
165
166template<size_t N1, size_t N2>
167inline double dot(const double(&vec1)[N1], const double(&vec2)[N2])
168{
169 static_assert(N1 == N2, "dot product requires two vectors of the same size");
170 double retval = 0;
171 for (size_t i = 0; i < N1; i++)
172 {
173 retval += vec1[i] * vec2[i];
174 }
175 return retval;
176}
177
178
179inline double dot(const double* vec1, const double* vec2, size_t N)
180{
181 double retval = 0;
182 for (size_t i = 0; i < N; i++)
183 {
184 retval += vec1[i] * vec2[i];
185 }
186 return retval;
187}
188
189inline double dot3(const double* vec1, const double* vec2)
190{
191 return dot(vec1, vec2, 3);
192}
193
194
196
197template<typename Vector3D1, typename Vector3D2>
198inline auto cross(const Vector3D1& vec1, const Vector3D2& vec2)
199 -> typename std::enable_if<!std::is_pointer<Vector3D1>::value && !std::is_pointer<Vector3D2>::value, Vector3D1>::type
200{
201 assert (size(vec1) >= 3 && size(vec2) >= 3);
202
203 return Vector3D1{
204 vec1[1] * vec2[2] - vec1[2] * vec2[1],
205 vec1[2] * vec2[0] - vec1[0] * vec2[2],
206 vec1[0] * vec2[1] - vec1[1] * vec2[0]
207 };
208}
209
210inline void cross(double* res, const double* vec1, const double* vec2)
211{
212 res[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
213 res[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
214 res[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
215}
216
217
218
219
220template<size_t N1, size_t N2>
221inline std::array<double, 3> cross(const double (&vec1)[N1], const double (&vec2)[N2])
222{
223 static_assert(N1 >= 3, "cross product requires vectors of at least size 3");
224 static_assert(N2 >= 3, "cross product requires vectors of at least size 3");
225
226 return std::array<double, 3>{
227 vec1[1] * vec2[2] - vec1[2] * vec2[1],
228 vec1[2] * vec2[0] - vec1[0] * vec2[2],
229 vec1[0] * vec2[1] - vec1[1] * vec2[0]
230 };
231}
232
233
234inline std::array<double, 3> cross3(const double* vec1, const double* vec2)
235{
236 return std::array<double, 3>{
237 vec1[1] * vec2[2] - vec1[2] * vec2[1],
238 vec1[2] * vec2[0] - vec1[0] * vec2[2],
239 vec1[0] * vec2[1] - vec1[1] * vec2[0]
240 };
241}
242
244
245inline double squaredNorm(const double* vec, size_t N)
246{
247 double sumsq = 0;
248 for (size_t i = 0; i < N; i++)
249 {
250 sumsq += vec[i] * vec[i];
251 }
252 return sumsq;
253}
254
255
256template<typename Vector>
257inline auto squaredNorm(const Vector& vec)
258 -> typename std::enable_if<!std::is_pointer<Vector>::value, double>::type
259{
260 double sumsq = 0.0;
261 for (const auto& val : vec) {
262 sumsq += val * val;
263 }
264 return sumsq;
265}
266
267template <size_t N>
268inline double squaredNorm(const double (&vec)[N])
269{
270 double sumsq = 0;
271 for (size_t i = 0; i < N; i++)
272 {
273 sumsq += vec[i] * vec[i];
274 }
275 return sumsq;
276}
277
278
280
281inline double norm(const double* vec, size_t N)
282{
283 return sqrt(squaredNorm(vec, N));
284}
285
286
287template<typename Vector>
288inline auto norm(const Vector& vec)
289 -> typename std::enable_if<!std::is_pointer<Vector>::value, double>::type
290{
291 return sqrt(squaredNorm(vec));
292}
293
294
295
296template <size_t N>
297inline double norm(const double (&vec)[N])
298{
299 return sqrt(squaredNorm(vec));
300}
301
302
304
305
306inline double normalize(double* vec, size_t N)
307{
308 double mag = norm(vec, N);
309 if (A_LIKELY(mag != 0)){
310 for (size_t i = 0; i < N; i++)
311 {
312 vec[i] /= mag;
313 }
314 }
315 return mag;
316}
317
318
319template<typename Vector>
320inline auto normalize(Vector& vec)
321-> typename std::enable_if<!std::is_pointer<Vector>::value, double>::type
322{
323 double mag = norm(vec);
324 if (A_LIKELY(mag != 0)){
325 for (auto& val : vec) {
326 val /= mag;
327 }
328 }
329 return mag;
330}
331
332
333
334template <size_t N>
335inline double normalize(double (&vec)[N])
336{
337 double mag = norm(vec);
338 if (A_LIKELY(mag != 0)){
339 for (size_t i = 0; i < N; i++)
340 {
341 vec[i] /= mag;
342 }
343 }
344 return mag;
345}
346
347
349
350
351template<typename Vector>
352inline auto normalized(const Vector& vec)
353-> typename std::enable_if<!std::is_pointer<Vector>::value, Vector>::type
354{
355 Vector retval{ vec };
356 normalize(retval);
357 return retval;
358}
359
360
361
362template <size_t N>
363inline std::array<double, N> normalized(double (&vec)[N])
364{
365 std::array<double, N> retval;
366 double mag = norm(vec);
367 if (A_LIKELY(mag != 0)){
368 for (size_t i = 0; i < N; i++)
369 {
370 retval[i] = vec[i] / mag;
371 }
372 }
373 else {
374 for (size_t i = 0; i < N; i++) {
375 retval[i] = vec[i];
376 }
377 }
378 return retval;
379}
380
381template <size_t N>
382inline std::array<double, N> normalized(const double* vec)
383{
384 std::array<double, N> retval;
385 double mag = norm(vec, N);
386 if (A_LIKELY(mag != 0)){
387 for (size_t i = 0; i < N; i++)
388 {
389 retval[i] = vec[i] / mag;
390 }
391 }
392 else {
393 for (size_t i = 0; i < N; i++) {
394 retval[i] = vec[i];
395 }
396 }
397 return retval;
398}
399
400// 定义向量特征:必须要有 size() 和 operator[]
401template<typename T>
403private:
404 template<typename U>
405 static auto test(int) -> decltype(
406 std::declval<U>()[0], // 有 operator[]
407 size(std::declval<U>()), // 有 size() 函数
408 std::true_type{}
409 );
410
411 template<typename>
412 static std::false_type test(...);
413
414public:
415 static constexpr bool value = decltype(test<T>(0))::value;
416};
417
418
420
421#define _AST_DEF_OP_SV(OP) \
422template<typename Scalar, typename Vector> \
423inline auto operator OP(Scalar scalar, const Vector& vec) \
424-> typename std::enable_if<std::is_arithmetic<Scalar>::value && is_vector_like<Vector>::value, Vector>::type \
425{ \
426 Vector retval{ vec }; \
427 size_t s = size(vec); \
428 for (size_t i = 0; i < s; i++) \
429 { \
430 retval[i] OP##= scalar; \
431 } \
432 return retval; \
433}
434
435
436#define _AST_DEF_OP_VS(OP) \
437template<typename Vector, typename Scalar> \
438inline auto operator OP(const Vector& vec, Scalar scalar) \
439-> typename std::enable_if<std::is_arithmetic<Scalar>::value && is_vector_like<Vector>::value, Vector>::type \
440{ \
441 Vector retval{ vec }; \
442 size_t s = size(vec); \
443 for (size_t i = 0; i < s; i++) \
444 { \
445 retval[i] OP##= scalar; \
446 } \
447 return retval; \
448}
449
450
451#define _AST_DEF_OP_VV(OP) \
452template<typename Vector1, typename Vector2> \
453inline auto operator OP(const Vector1& vec1, const Vector2& vec2)\
454-> typename std::enable_if<is_vector_like<Vector1>::value && is_vector_like<Vector2>::value, Vector1>::type \
455{ \
456 assert(size(vec1) == size(vec2)); \
457 Vector1 retval{ vec1 }; \
458 size_t s = size(vec1); \
459 for (size_t i = 0; i < s; i++) \
460 { \
461 retval[i] OP##= vec2[i]; \
462 } \
463 return retval; \
464}
465
466
467#define _AST_DEF_OP(OP) \
468_AST_DEF_OP_SV(OP) \
469_AST_DEF_OP_VS(OP) \
470_AST_DEF_OP_VV(OP) \
471
472
473
474_AST_DEF_OP(+)
475_AST_DEF_OP(-)
476
477
480
481_AST_DEF_OP_VS(*)
482_AST_DEF_OP_VS(/)
483
484// 乘除运算对于向量不应该是按元素运算,不启用以避免歧义
485// _AST_DEF_OP_VV(*)
486// _AST_DEF_OP_VV(/)
487
488
489
490
491#if 0
493template<size_t N1, size_t N2>
494inline std::array<double, N1> operator+(const double (&vec1)[N1], const double (&vec2)[N2])
495{
496 static_assert(N1 == N2, "plus operator requires vectors of the same dimension");
497 std::array<double, N1> retval{};
498 for (size_t i = 0; i < N1; i++)
499 {
500 retval[i] = vec1[i] + vec2[i];
501 }
502 return retval;
503}
504#endif
505
506
508
509
510template<typename _Scalar, size_t I, size_t J, size_t K>
511std::array<std::array<_Scalar, K>, I> mtimes(
512 const _Scalar(&left)[I][J],
513 const _Scalar(&right)[J][K]
514)
515{
516 std::array<std::array<_Scalar, K>, I> retval;
517 for (size_t i = 0; i < I; i++)
518 {
519 for (size_t k = 0; k < K ; k++) {
520 _Scalar value = 0;
521 for (size_t j = 0; j < J; j++)
522 {
523 value += left[i][j] * right[j][k];
524 }
525 retval[i][k] = value;
526 }
527 }
528 return retval;
529}
530
531}
532
533#define _ASTMATH _AST math::
534
535#ifdef AST_BUILD_LIB // 防止与其他库使用时出现冲突,默认只在编译时使用,否则需要主动开启
536using namespace math;
537#endif
538
539
540
541template<typename _Scalar, size_t I, size_t J, size_t K>
542MatrixMN<_Scalar, I, K> operator* (
543 const MatrixMN<_Scalar, I, J>& left,
544 const MatrixMN<_Scalar, J, K>& right
545)
546{
547 MatrixMN<_Scalar, I, K> retval;
548 for (size_t i = 0; i < I; i++)
549 {
550 for (size_t k = 0; k < K; k++) {
551 _Scalar value = 0;
552 for (size_t j = 0; j < J; j++)
553 {
554 value += left(i, j) * right(j, k);
555 }
556 retval(i, k) = value;
557 }
558 }
559 return retval;
560}
561
562
563template<typename _Scalar, size_t I, size_t J>
564VectorN<_Scalar, I> operator*(
565 const MatrixMN<_Scalar, I, J>& left,
566 const VectorN<_Scalar, J>& right
567)
568{
569 VectorN<_Scalar, I> result;
570 for (size_t i = 0; i < I; ++i) {
571 _Scalar sum = 0;
572 for (size_t j = 0; j < J; ++j) {
573 sum += left(i, j) * right[j];
574 }
575 result[i] = sum;
576 }
577 return result;
578}
579
580template<typename _Scalar, size_t I, size_t J>
581VectorN<_Scalar, J> operator*(
582 const VectorN<_Scalar, I>& left,
583 const MatrixMN<_Scalar, I, J>& right
584)
585{
586 VectorN<_Scalar, J> result{};
587 for(size_t i=0;i<I;++i){
588 for(size_t j=0;j<J;++j){
589 result[j] += left[i] * right(i, j);
590 }
591 }
592 return result;
593}
594
595
596
597template<typename T>
598A_CONSTEXPR_CXX14 const T& clamp(const T& val, const T& low, const T& high)
599{
600 #ifdef A_CXX14
601 assert(low <= high && "low must be less than or equal to high");
602 if(val < low){
603 return low;
604 }
605 if(val > high){
606 return high;
607 }
608 return val;
609 #else
610 return (val < low) ? low : ((val > high) ? high : val);
611 #endif
612}
613
616AST_NAMESPACE_END
#define _AST_DEF_OP_SV(OP)
定义 MathOperator.hpp:421
Unit s
定义 Unit.cpp:425
Unit N
牛顿
定义 Unit.cpp:437
int sign(_Scalar val)
sign
定义 MathOperator.hpp:102
double cot(double a)
cot acot
定义 MathOperator.hpp:140
double norm(const double *vec, size_t N)
norm
定义 MathOperator.hpp:281
double dot(const Container1 &vec1, const Container2 &vec2)
dot
定义 MathOperator.hpp:153
std::array< std::array< _Scalar, K >, I > mtimes(const _Scalar(&left)[I][J], const _Scalar(&right)[J][K])
矩阵乘法
定义 MathOperator.hpp:511
auto normalized(const Vector &vec) -> typename std::enable_if<!std::is_pointer< Vector >::value, Vector >::type
normalized
定义 MathOperator.hpp:352
double normalize(double *vec, size_t N)
normalize
定义 MathOperator.hpp:306
double squaredNorm(const double *vec, size_t N)
squaredNorm
定义 MathOperator.hpp:245
定义 MathOperator.hpp:402