🛰️航天仿真算法库 SpaceAST 0.3.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
401template<typename T>
402struct is_arithmetic_element : std::integral_constant<bool,
403 std::is_arithmetic<T>::value
404 && !std::is_same<T, char>::value
405 && !std::is_same<T, wchar_t>::value
406 && !std::is_same<T, char16_t>::value
407 && !std::is_same<T, char32_t>::value>
408{};
409
410
411// 定义向量特征:必须要有 size() 和数值型元素的 operator[]
412template<typename T>
414private:
415 template<typename U>
416 static auto test(int) -> decltype(
417 sizeof(std::declval<U>()[0]), // 有 operator[],用 sizeof 取用返回值避免报 unused-result
418 size(std::declval<U>()), // 有 size() 函数
419 typename std::enable_if<
421 typename std::decay<decltype(std::declval<U>()[0])>::type>::value,
422 std::true_type>::type{}
423 );
424
425 template<typename>
426 static std::false_type test(...);
427
428public:
429 static constexpr bool value = decltype(test<T>(0))::value;
430};
431
432
434
435#define _AST_DEF_OP_SV(OP) \
436template<typename Scalar, typename Vector> \
437inline auto operator OP(Scalar scalar, const Vector& vec) \
438-> typename std::enable_if<std::is_arithmetic<Scalar>::value && is_vector_like<Vector>::value, Vector>::type \
439{ \
440 Vector retval{ vec }; \
441 size_t s = size(vec); \
442 for (size_t i = 0; i < s; i++) \
443 { \
444 retval[i] OP##= scalar; \
445 } \
446 return retval; \
447}
448
449
450#define _AST_DEF_OP_VS(OP) \
451template<typename Vector, typename Scalar> \
452inline auto operator OP(const Vector& vec, Scalar scalar) \
453-> typename std::enable_if<std::is_arithmetic<Scalar>::value && is_vector_like<Vector>::value, Vector>::type \
454{ \
455 Vector retval{ vec }; \
456 size_t s = size(vec); \
457 for (size_t i = 0; i < s; i++) \
458 { \
459 retval[i] OP##= scalar; \
460 } \
461 return retval; \
462}
463
464
465#define _AST_DEF_OP_VV(OP) \
466template<typename Vector1, typename Vector2> \
467inline auto operator OP(const Vector1& vec1, const Vector2& vec2)\
468-> typename std::enable_if<is_vector_like<Vector1>::value && is_vector_like<Vector2>::value, Vector1>::type \
469{ \
470 assert(size(vec1) == size(vec2)); \
471 Vector1 retval{ vec1 }; \
472 size_t s = size(vec1); \
473 for (size_t i = 0; i < s; i++) \
474 { \
475 retval[i] OP##= vec2[i]; \
476 } \
477 return retval; \
478}
479
480
481#define _AST_DEF_OP(OP) \
482_AST_DEF_OP_SV(OP) \
483_AST_DEF_OP_VS(OP) \
484_AST_DEF_OP_VV(OP) \
485
486
487
488_AST_DEF_OP(+)
489_AST_DEF_OP(-)
490
491
494
495_AST_DEF_OP_VS(*)
496_AST_DEF_OP_VS(/)
497
498// 乘除运算对于向量不应该是按元素运算,不启用以避免歧义
499// _AST_DEF_OP_VV(*)
500// _AST_DEF_OP_VV(/)
501
502
503
504
505#if 0
507template<size_t N1, size_t N2>
508inline std::array<double, N1> operator+(const double (&vec1)[N1], const double (&vec2)[N2])
509{
510 static_assert(N1 == N2, "plus operator requires vectors of the same dimension");
511 std::array<double, N1> retval{};
512 for (size_t i = 0; i < N1; i++)
513 {
514 retval[i] = vec1[i] + vec2[i];
515 }
516 return retval;
517}
518#endif
519
520
522
523
524template<typename _Scalar, size_t I, size_t J, size_t K>
525std::array<std::array<_Scalar, K>, I> mtimes(
526 const _Scalar(&left)[I][J],
527 const _Scalar(&right)[J][K]
528)
529{
530 std::array<std::array<_Scalar, K>, I> retval;
531 for (size_t i = 0; i < I; i++)
532 {
533 for (size_t k = 0; k < K ; k++) {
534 _Scalar value = 0;
535 for (size_t j = 0; j < J; j++)
536 {
537 value += left[i][j] * right[j][k];
538 }
539 retval[i][k] = value;
540 }
541 }
542 return retval;
543}
544
545}
546
547#define _ASTMATH _AST math::
548
549#ifdef AST_BUILD_LIB // 防止与其他库使用时出现冲突,默认只在编译时使用,否则需要主动开启
550using namespace math;
551#endif
552
553
554
555template<typename _Scalar, size_t I, size_t J, size_t K>
556MatrixMN<_Scalar, I, K> operator* (
557 const MatrixMN<_Scalar, I, J>& left,
558 const MatrixMN<_Scalar, J, K>& right
559)
560{
561 MatrixMN<_Scalar, I, K> retval;
562 for (size_t i = 0; i < I; i++)
563 {
564 for (size_t k = 0; k < K; k++) {
565 _Scalar value = 0;
566 for (size_t j = 0; j < J; j++)
567 {
568 value += left(i, j) * right(j, k);
569 }
570 retval(i, k) = value;
571 }
572 }
573 return retval;
574}
575
576
577template<typename _Scalar, size_t I, size_t J>
578VectorN<_Scalar, I> operator*(
579 const MatrixMN<_Scalar, I, J>& left,
580 const VectorN<_Scalar, J>& right
581)
582{
583 VectorN<_Scalar, I> result;
584 for (size_t i = 0; i < I; ++i) {
585 _Scalar sum = 0;
586 for (size_t j = 0; j < J; ++j) {
587 sum += left(i, j) * right[j];
588 }
589 result[i] = sum;
590 }
591 return result;
592}
593
594template<typename _Scalar, size_t I, size_t J>
595VectorN<_Scalar, J> operator*(
596 const VectorN<_Scalar, I>& left,
597 const MatrixMN<_Scalar, I, J>& right
598)
599{
600 VectorN<_Scalar, J> result{};
601 for(size_t i=0;i<I;++i){
602 for(size_t j=0;j<J;++j){
603 result[j] += left[i] * right(i, j);
604 }
605 }
606 return result;
607}
608
609
610
611
614AST_NAMESPACE_END
#define _AST_DEF_OP_SV(OP)
定义 MathOperator.hpp:435
向量抽象基类
定义 Vector.hpp:38
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:525
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
Unit s
秒
定义 Unit.cpp:465
Unit T
特斯拉
定义 Unit.cpp:492
Unit N
牛顿
定义 Unit.cpp:477
Unit K
开氏温度
定义 Unit.cpp:496
判断类型是否为向量运算可用的数值类型
定义 MathOperator.hpp:408
定义 MathOperator.hpp:413