1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.gravity;
18
19 import org.hipparchus.analysis.differentiation.DerivativeStructure;
20 import org.hipparchus.dfp.Dfp;
21 import org.hipparchus.dfp.DfpField;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28
29
30
31
32
33
34
35 class AssociatedLegendreFunction {
36
37 static final Map<Integer, List<Dfp[]>> LEGENDRE_POLYNOMIALS = new HashMap<Integer, List<Dfp[]>>();
38 final int m;
39 final Dfp[] polynomial;
40 final Dfp normalization;
41
42 private Dfp[] getLegendrePolynomial(int n, DfpField dfpField) {
43
44
45 List<Dfp[]> list = LEGENDRE_POLYNOMIALS.get(dfpField.getRadixDigits());
46 if (list == null) {
47 list = new ArrayList<Dfp[]>();
48 list.add(new Dfp[] {
49 dfpField.getOne()
50 });
51 list.add(new Dfp[] {
52 dfpField.getZero(), dfpField.getOne()
53 });
54 }
55
56 while (list.size() <= n) {
57
58
59
60 int k = list.size() - 1;
61 Dfp kDfp = dfpField.newDfp(k);
62 Dfp kP1Dfp = kDfp.add(dfpField.getOne());
63 Dfp ckDfp = kP1Dfp.add(kDfp).divide(kP1Dfp);
64 Dfp[] pk = list.get(k);
65 Dfp ckM1Dfp = kDfp.divide(kP1Dfp).negate();
66 Dfp[] pkM1 = list.get(k - 1);
67
68 Dfp[] pkP1 = new Dfp[k + 2];
69 pkP1[0] = ckM1Dfp.multiply(pkM1[0]);
70 for (int i = 0; i < k; ++i) {
71 if ((k - i) % 2 == 1) {
72 pkP1[i + 1] = dfpField.getZero();
73 } else {
74 pkP1[i + 1] = ckDfp.multiply(pk[i]).add(ckM1Dfp.multiply(pkM1[i + 1]));
75 }
76 }
77 pkP1[k + 1] = ckDfp.multiply(pk[k]);
78
79 list.add(pkP1);
80
81 }
82
83
84 return list.get(n);
85
86 }
87
88 private Dfp[] differentiateLegendrePolynomial(Dfp[] p, int m, DfpField dfpField) {
89 Dfp[] dp = new Dfp[p.length - m];
90 for (int i = 0; i < dp.length; ++i) {
91 dp[i] = p[i + m];
92 for (int j = m; j > 0; --j) {
93 dp[i] = dp[i].multiply(dfpField.newDfp(i + j));
94 }
95 }
96 return dp;
97 }
98
99 public AssociatedLegendreFunction(boolean normalized, int n, int m, DfpField dfpField) {
100
101 this.m = m;
102
103
104 polynomial = differentiateLegendrePolynomial(getLegendrePolynomial(n, dfpField), m, dfpField);
105
106 if (normalized) {
107
108 Dfp c = dfpField.newDfp(((m == 0) ? 1.0 : 2.0) * (2 * n + 1));
109 for (int k = 0; k < m; ++k) {
110 c = c.divide(dfpField.newDfp((n + 1 + k) * (n - k)));
111 }
112 this.normalization = c.sqrt();
113 } else {
114 this.normalization = dfpField.getOne();
115 }
116
117 }
118
119 public DerivativeStructure value(DerivativeStructure t) {
120 DerivativeStructure y1 = t.getField().getOne().multiply(polynomial[polynomial.length - 1].toDouble());
121 for (int j = polynomial.length - 2; j >= 0; j--) {
122 y1 = y1.multiply(t).add(polynomial[j].toDouble());
123 }
124 DerivativeStructure oneMinusT2 = t.getField().getOne().subtract(t.multiply(t));
125 DerivativeStructure y2 = oneMinusT2.pow(m).sqrt();
126 return y1.multiply(y2).multiply(normalization.toDouble());
127 }
128
129 public Dfp value(Dfp t) {
130 Dfp y1 = polynomial[polynomial.length - 1];
131 for (int j = polynomial.length - 2; j >= 0; j--) {
132 y1 = y1.multiply(t).add(polynomial[j]);
133 }
134 Dfp oneMinusT2 = t.getField().getOne().subtract(t.multiply(t));
135 Dfp y2 = t.getField().getOne();
136 for (int j = 0; j < m; ++j) {
137 y2 = y2.multiply(oneMinusT2);
138 }
139 y2 = y2.sqrt();
140 return y1.multiply(y2).multiply(normalization);
141 }
142
143 }