1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.semianalytical.dsst.utilities;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.fraction.BigFraction;
22 import org.hipparchus.util.FastMath;
23 import org.hipparchus.util.MathArrays;
24
25 import java.util.Arrays;
26
27
28
29
30 public class FieldGammaMnsFunction <T extends CalculusFieldElement<T>> {
31
32
33 private static double[] PRECOMPUTED_RATIOS;
34
35
36 private final double[] ratios;
37
38
39 private final T[] values;
40
41
42 private final T opIg;
43
44
45 private final int I;
46
47
48
49
50
51
52
53 public FieldGammaMnsFunction(final int nMax, final T gamma, final int I, final Field<T> field) {
54 final int size = (nMax + 1) * (nMax + 2) * (4 * nMax + 3) / 6;
55 this.values = MathArrays.buildArray(field, size);
56 this.ratios = getRatios(nMax, size);
57 Arrays.fill(values, field.getZero().add(Double.NaN));
58 this.opIg = gamma.multiply(I).add(1.);
59 this.I = I;
60 }
61
62
63
64
65
66
67
68 private static int index(final int m, final int n, final int s) {
69 return n * (n + 1) * (4 * n - 1) / 6 +
70 m * (2 * n + 1) +
71 s + n;
72 }
73
74
75
76
77
78
79 private static double[] getRatios(final int nMax, final int size) {
80 synchronized (FieldGammaMnsFunction.class) {
81 if (PRECOMPUTED_RATIOS == null || PRECOMPUTED_RATIOS.length < size) {
82
83
84 final BigFraction[] bF = new BigFraction[size];
85 for (int n = 0; n <= nMax; ++n) {
86
87
88 bF[index(0, n, 0)] = BigFraction.ONE;
89 for (int m = 1; m <= n; ++m) {
90 bF[index(m, n, 0)] = bF[index(m - 1, n, 0)].multiply(n + m).divide(n - (m - 1));
91 }
92
93
94 for (int absS = 1; absS <= n; ++absS) {
95 for (int m = 0; m <= n; ++m) {
96 bF[index(m, n, +absS)] = bF[index(m, n, absS - 1)].divide(n + absS).multiply(n - (absS - 1));
97 bF[index(m, n, -absS)] = bF[index(m, n, absS)];
98 }
99 }
100
101 }
102
103
104 PRECOMPUTED_RATIOS = new double[size];
105 for (int i = 0; i < bF.length; ++i) {
106 PRECOMPUTED_RATIOS[i] = bF[i].doubleValue();
107 }
108
109 }
110 return PRECOMPUTED_RATIOS;
111 }
112 }
113
114
115
116
117
118
119
120 public T getValue(final int m, final int n, final int s) {
121 final int i = index(m, n, s);
122 if (Double.isNaN(values[i].getReal())) {
123 if (s <= -m) {
124 values[i] = FastMath.scalb(FastMath.pow(opIg, -I * m), s).multiply(((m - s) & 0x1) == 0 ? +1 : -1);
125 } else if (s <= m) {
126 values[i] = FastMath.scalb(FastMath.pow(opIg, I * s), -m).multiply(ratios[i]).multiply(((m - s) & 0x1) == 0 ? +1 : -1);
127 } else {
128 values[i] = FastMath.scalb(FastMath.pow(opIg, I * m), -s);
129 }
130 }
131 return values[i];
132 }
133
134
135
136
137
138
139
140 public T getDerivative(final int m, final int n, final int s) {
141 if (s <= -m) {
142 return getValue(m, n, s).multiply(I).multiply(-m).divide(opIg);
143 } else if (s >= m) {
144 return getValue(m, n, s).multiply(I).multiply(m).divide(opIg);
145 } else {
146 return getValue(m, n, s).multiply(I).multiply(s).divide(opIg);
147 }
148 }
149
150 }