0.3.0
Loading...
Searching...
No Matches
Math.cpp
Go to the documentation of this file.
1// This file is part of INSTINCT, the INS Toolkit for Integrated
2// Navigation Concepts and Training by the Institute of Navigation of
3// the University of Stuttgart, Germany.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#include "Math.hpp"
10
11namespace NAV::math
12{
13
14uint64_t factorial(uint64_t n)
15{
16 // uint64_t is required to calculate factorials of n > 12 (Limit of uint32_t). The limit of uint64_t is at n = 20
17 constexpr std::array factorials = {
18 uint64_t(1), // 0
19 uint64_t(1), // 1
20 uint64_t(2), // 2
21 uint64_t(6), // 3
22 uint64_t(24), // 4
23 uint64_t(120), // 5
24 uint64_t(720), // 6
25 uint64_t(5040), // 7
26 uint64_t(40320), // 8
27 uint64_t(362880), // 9
28 uint64_t(3628800), // 10
29 uint64_t(39916800), // 11
30 uint64_t(479001600), // 12
31 uint64_t(6227020800), // 13
32 uint64_t(87178291200), // 14
33 uint64_t(1307674368000), // 15
34 uint64_t(20922789888000), // 16
35 uint64_t(355687428096000), // 17
36 uint64_t(6402373705728000), // 18
37 uint64_t(121645100408832000), // 19
38 uint64_t(2432902008176640000), // 20
39 };
40
41 if (n < factorials.size())
42 {
43 return factorials.at(n);
44 }
45 return n * factorial(n - 1);
46}
47
48double normalCDF(double value)
49{
50 return 0.5 * std::erfc(-value * M_SQRT1_2);
51}
52
53double calcEllipticalIntegral(double phi, double m)
54{
55 double origM = m;
56 double scale = 0.0;
57 if (m > 1.0)
58 {
59 scale = std::sqrt(m);
60 phi = std::asin(scale * std::sin(phi));
61 m = 1.0 / m;
62 }
63 else if (m < 0.0)
64 {
65 scale = std::sqrt(1.0 - m);
66 phi = 0.5 * M_PI - phi;
67 m /= m - 1.0;
68 }
69 double a = 0.0;
70 double eok = 0.0;
71 double f = 0.0;
72 if (m == 1.0)
73 {
74 double per = std::floor((phi + 0.5 * M_PI) / M_PI);
75 phi = std::sin(phi) * math::sgn(0.5 - std::abs(std::fmod(per, 2.0))) + 2 * per;
76 a = 0.0;
77 }
78 else
79 { // compute using arithmetic-geometric mean
80 double sgn = math::sgn(phi);
81 phi = std::abs(phi),
82 a = 1.0;
83 double b = std::sqrt(1.0 - m);
84 eok = 1.0 - 0.5 * m;
85 double cs = 0.0;
86 double twon = 1.0;
87 double pi2 = 0.5 * M_PI;
88 while (true)
89 { // maximum of 8 passes for 64-bit double
90 double c = 0.5 * (a - b);
91 if (std::abs(c) <= std::numeric_limits<double>::epsilon() * c) { break; }
92 phi += std::atan((b / a) * std::tan(phi)) + M_PI * std::floor((phi + pi2) / M_PI);
93 cs += c * std::sin(phi);
94 eok -= twon * c * c;
95 twon *= 2.0;
96 double am = a - c;
97 if (am == a) { break; }
98 b = std::sqrt(a * b);
99 a = am;
100 }
101 double f = sgn * phi / (twon * a);
102 phi = eok * f + sgn * cs;
103 }
104
105 if (origM > 1.0)
106 {
107 phi = (phi - (1.0 - m) * f) / scale;
108 }
109 else if (origM < 0.0)
110 {
111 phi = (eok * 0.5 * M_PI / a - phi) * scale;
112 }
113
114 return phi;
115}
116} // namespace NAV::math
Simple Math functions.
int sgn(const T &val)
Returns the sign of the given value.
Definition Math.hpp:139
double calcEllipticalIntegral(double phi, double m)
Calculates the incomplete elliptical integral of the second kind.
Definition Math.cpp:53
uint64_t factorial(uint64_t n)
Calculates the factorial of an unsigned integer.
Definition Math.cpp:14
double normalCDF(double value)
Calculates the cumulative distribution function (CDF) of the standard normal distribution.
Definition Math.cpp:48