1 /* Copyright 2002-2021 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.propagation.semianalytical.dsst.utilities;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.hipparchus.CalculusFieldElement;
25 import org.hipparchus.analysis.differentiation.FieldGradient;
26 import org.hipparchus.analysis.differentiation.Gradient;
27 import org.hipparchus.analysis.polynomials.PolynomialFunction;
28 import org.hipparchus.analysis.polynomials.PolynomialsUtils;
29
30 /** Provider of the Jacobi polynomials P<sub>l</sub><sup>v,w</sup>.
31 * <p>
32 * This class is used for {@link
33 * org.orekit.propagation.semianalytical.dsst.forces.DSSTTesseral
34 * tesseral contribution} computation.
35 * </p>
36 *
37 * @author Nicolas Bernard
38 * @since 6.1
39 */
40 public class JacobiPolynomials {
41
42 /** Storage map. */
43 private static final Map<JacobiKey, List<PolynomialFunction>> MAP =
44 new HashMap<JacobiPolynomials.JacobiKey, List<PolynomialFunction>>();
45
46 /** Private constructor as class is a utility. */
47 private JacobiPolynomials() {
48 }
49
50 /** Returns the value and derivatives of the Jacobi polynomial P<sub>l</sub><sup>v,w</sup> evaluated at γ.
51 * <p>
52 * This method is guaranteed to be thread-safe
53 * </p>
54 * @param l degree of the polynomial
55 * @param v v value
56 * @param w w value
57 * @param gamma γ value
58 * @return value and derivatives of the Jacobi polynomial P<sub>l</sub><sup>v,w</sup>(γ)
59 * @since 10.2
60 */
61 public static Gradient getValue(final int l, final int v, final int w, final Gradient gamma) {
62
63 final List<PolynomialFunction> polyList;
64 synchronized (MAP) {
65
66 final JacobiKey key = new JacobiKey(v, w);
67
68 // Check the existence of the corresponding key in the map.
69 if (!MAP.containsKey(key)) {
70 MAP.put(key, new ArrayList<PolynomialFunction>());
71 }
72
73 polyList = MAP.get(key);
74
75 }
76
77 final PolynomialFunction polynomial;
78 synchronized (polyList) {
79 // If the l-th degree polynomial has not been computed yet, the polynomials
80 // up to this degree are computed.
81 for (int degree = polyList.size(); degree <= l; degree++) {
82 polyList.add(degree, PolynomialsUtils.createJacobiPolynomial(degree, v, w));
83 }
84 polynomial = polyList.get(l);
85 }
86
87 // compute value and derivative
88 return polynomial.value(gamma);
89
90 }
91
92 /** Returns the value and derivatives of the Jacobi polynomial P<sub>l</sub><sup>v,w</sup> evaluated at γ.
93 * <p>
94 * This method is guaranteed to be thread-safe
95 * </p>
96 * @param <T> the type of the field elements
97 * @param l degree of the polynomial
98 * @param v v value
99 * @param w w value
100 * @param gamma γ value
101 * @return value and derivatives of the Jacobi polynomial P<sub>l</sub><sup>v,w</sup>(γ)
102 * @since 10.2
103 */
104 public static <T extends CalculusFieldElement<T>> FieldGradient<T> getValue(final int l, final int v, final int w,
105 final FieldGradient<T> gamma) {
106
107 final List<PolynomialFunction> polyList;
108 synchronized (MAP) {
109
110 final JacobiKey key = new JacobiKey(v, w);
111
112 // Check the existence of the corresponding key in the map.
113 if (!MAP.containsKey(key)) {
114 MAP.put(key, new ArrayList<PolynomialFunction>());
115 }
116
117 polyList = MAP.get(key);
118
119 }
120
121 final PolynomialFunction polynomial;
122 synchronized (polyList) {
123 // If the l-th degree polynomial has not been computed yet, the polynomials
124 // up to this degree are computed.
125 for (int degree = polyList.size(); degree <= l; degree++) {
126 polyList.add(degree, PolynomialsUtils.createJacobiPolynomial(degree, v, w));
127 }
128 polynomial = polyList.get(l);
129 }
130
131 // compute value and derivative
132 return polynomial.value(gamma);
133
134 }
135
136 /** Inner class for Jacobi polynomials keys.
137 * <p>
138 * Please note that this class is not original content but is a copy from the
139 * Hipparchus library. This library is published under the
140 * Apache License, version 2.0.
141 * </p>
142 *
143 * @see org.hipparchus.analysis.polynomials.PolynomialsUtils
144 */
145 private static class JacobiKey {
146
147 /** First exponent. */
148 private final int v;
149
150 /** Second exponent. */
151 private final int w;
152
153 /** Simple constructor.
154 * @param v first exponent
155 * @param w second exponent
156 */
157 JacobiKey(final int v, final int w) {
158 this.v = v;
159 this.w = w;
160 }
161
162 /** Get hash code.
163 * @return hash code
164 */
165 @Override
166 public int hashCode() {
167 return (v << 16) ^ w;
168 }
169
170 /** Check if the instance represent the same key as another instance.
171 * @param key other key
172 * @return true if the instance and the other key refer to the same polynomial
173 */
174 @Override
175 public boolean equals(final Object key) {
176
177 if (!(key instanceof JacobiKey)) {
178 return false;
179 }
180
181 final JacobiKey otherK = (JacobiKey) key;
182 return v == otherK.v && w == otherK.w;
183
184 }
185 }
186
187 }