Line | Branch | Exec | Source |
---|---|---|---|
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 | |||
11 | namespace NAV::math | ||
12 | { | ||
13 | |||
14 | 25776 | uint64_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 | 25776 | 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 |
1/2✓ Branch 0 taken 25776 times.
✗ Branch 1 not taken.
|
25776 | if (n < factorials.size()) |
42 | { | ||
43 |
1/2✓ Branch 1 taken 25776 times.
✗ Branch 2 not taken.
|
25776 | return factorials.at(n); |
44 | } | ||
45 | ✗ | return n * factorial(n - 1); | |
46 | } | ||
47 | |||
48 | ✗ | double normalCDF(double value) | |
49 | { | ||
50 | ✗ | return 0.5 * std::erfc(-value * M_SQRT1_2); | |
51 | } | ||
52 | |||
53 | 1343753 | double calcEllipticalIntegral(double phi, double m) | |
54 | { | ||
55 | 1343753 | double origM = m; | |
56 | 1343753 | double scale = 0.0; | |
57 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1343753 times.
|
1343753 | 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 |
1/2✓ Branch 0 taken 1343753 times.
✗ Branch 1 not taken.
|
1343753 | else if (m < 0.0) |
64 | { | ||
65 | 1343753 | scale = std::sqrt(1.0 - m); | |
66 | 1343753 | phi = 0.5 * M_PI - phi; | |
67 | 1343753 | m /= m - 1.0; | |
68 | } | ||
69 | 1343753 | double a = 0.0; | |
70 | 1343753 | double eok = 0.0; | |
71 | 1343753 | double f = 0.0; | |
72 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1343753 times.
|
1343753 | 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 | 1343753 | double sgn = math::sgn(phi); | |
81 | 1343753 | phi = std::abs(phi), | |
82 | 1343753 | a = 1.0; | |
83 | 1343753 | double b = std::sqrt(1.0 - m); | |
84 | 1343753 | eok = 1.0 - 0.5 * m; | |
85 | 1343753 | double cs = 0.0; | |
86 | 1343753 | double twon = 1.0; | |
87 | 1343753 | double pi2 = 0.5 * M_PI; | |
88 | while (true) | ||
89 | { // maximum of 8 passes for 64-bit double | ||
90 | 6718765 | double c = 0.5 * (a - b); | |
91 |
2/2✓ Branch 2 taken 1343753 times.
✓ Branch 3 taken 5375012 times.
|
6718765 | if (std::abs(c) <= std::numeric_limits<double>::epsilon() * c) { break; } |
92 | 5375012 | phi += std::atan((b / a) * std::tan(phi)) + M_PI * std::floor((phi + pi2) / M_PI); | |
93 | 5375012 | cs += c * std::sin(phi); | |
94 | 5375012 | eok -= twon * c * c; | |
95 | 5375012 | twon *= 2.0; | |
96 | 5375012 | double am = a - c; | |
97 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5375012 times.
|
5375012 | if (am == a) { break; } |
98 | 5375012 | b = std::sqrt(a * b); | |
99 | 5375012 | a = am; | |
100 | 5375012 | } | |
101 | 1343753 | double f = sgn * phi / (twon * a); | |
102 | 1343753 | phi = eok * f + sgn * cs; | |
103 | } | ||
104 | |||
105 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1343753 times.
|
1343753 | if (origM > 1.0) |
106 | { | ||
107 | ✗ | phi = (phi - (1.0 - m) * f) / scale; | |
108 | } | ||
109 |
1/2✓ Branch 0 taken 1343753 times.
✗ Branch 1 not taken.
|
1343753 | else if (origM < 0.0) |
110 | { | ||
111 | 1343753 | phi = (eok * 0.5 * M_PI / a - phi) * scale; | |
112 | } | ||
113 | |||
114 | 1343753 | return phi; | |
115 | } | ||
116 | } // namespace NAV::math | ||
117 |