1   /* Copyright 2002-2015 CS Systèmes d'Information
2    * Licensed to CS Systèmes d'Information (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.Map;
20  import java.util.TreeMap;
21  
22  import org.apache.commons.math3.util.FastMath;
23  import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory.MNSKey;
24  
25  /** Compute the &Gamma;<sup>m</sup><sub>n,s</sub>(γ) function from equation 2.7.1-(13).
26   *
27   *  @author Romain Di Costanzo
28   */
29  public class GammaMnsFunction {
30  
31      /** Storage map. */
32      private final Map<MNSKey, Double> map;
33  
34      /** Factorial. */
35      private final double[] fact;
36  
37      /** 1 + I * γ. */
38      private final double opIg;
39  
40      /** I = +1 for a prograde orbit, -1 otherwise. */
41      private final int    I;
42  
43      /** Simple constructor.
44       *  @param fact factorial array
45       *  @param gamma γ
46       *  @param I retrograde factor
47       */
48      public GammaMnsFunction(final double[] fact, final double gamma, final int I) {
49          this.fact = fact.clone();
50          this.opIg = 1. + I * gamma;
51          this.I    = I;
52          this.map  = new TreeMap<MNSKey, Double>();
53      }
54  
55      /** Get &Gamma; function value.
56       *  @param m m
57       *  @param n n
58       *  @param s s
59       *  @return &Gamma;<sup>m</sup><sub>n, s</sub>(γ)
60       */
61      public double getValue(final int m, final int n, final int s) {
62          double res = 0.;
63          final MNSKey key = new MNSKey(m, n, s);
64          if (map.containsKey(key)) {
65              res = map.get(key);
66          } else {
67              if (s <= -m) {
68                  res = FastMath.pow(-1, m - s) * FastMath.pow(2, s) * FastMath.pow(opIg, -I * m);
69              } else if (s >= m) {
70                  res = FastMath.pow(2, -s) * FastMath.pow(opIg, I * m);
71              } else {
72                  res = FastMath.pow(-1, m - s) * FastMath.pow(2, -m) * FastMath.pow(opIg, I * s);
73                  res *= fact[n + m] * fact[n - m];
74                  res /= fact[n + s] * fact[n - s];
75              }
76              map.put(key, res);
77          }
78          return res;
79      }
80  
81      /** Get &Gamma; function derivative.
82       * @param m m
83       * @param n n
84       * @param s s
85       * @return d&Gamma;<sup>m</sup><sub>n,s</sub>(γ)/dγ
86       */
87      public double getDerivative(final int m, final int n, final int s) {
88          double res = 0.;
89          if (s <= -m) {
90              res = -m * I * getValue(m, n, s) / opIg;
91          } else if (s >= m) {
92              res =  m * I * getValue(m, n, s) / opIg;
93          } else {
94              res =  s * I * getValue(m, n, s) / opIg;
95          }
96          return res;
97      }
98  
99  }