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