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