View Javadoc
1   /*
2    * Copyright (C) 2023 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.irurueta.numerical.interpolation;
17  
18  /**
19   * Estimates coefficients of a polynomial passing through provided set of x and y points.
20   * This implementation is more accurate than other implementations such as implementations of
21   * {@link com.irurueta.numerical.polynomials.estimators.PolynomialEstimator}.
22   * Those implementations are based on curve fitting a polynomial of a given degree based on a number
23   * of points that can be much larger than the number of points, which results in a polynomial that
24   * does not exactly pass through provided points, but provides a minimum square error result.
25   * On the other hand, this implementation builds a polynomial of order equal to the length of
26   * provided x and y points.
27   * Ths implementation is more accurate than {@link SimpleInterpolatingPolynomialEstimator}, at the
28   * expense of greater computational cost (N^3 of this method vs N^2 of the simple one).
29   */
30  public class AccurateInterpolatingPolynomialEstimator extends InterpolatingPolynomialEstimator {
31  
32      /**
33       * Estimates polynomial coefficients from provided x and y points.
34       *
35       * @param xa  x points the estimated polynomial passes through.
36       * @param ya  y points the estimated polynomial passes through.
37       * @param cof instance where coefficients of estimated polynomial will be stored.
38       * @throws IllegalArgumentException if any of the provided values doesn't have the same length.
39       * @throws InterpolationException   if interpolation fails for numerical reasons.
40       */
41      @Override
42      public void estimate(final double[] xa, final double[] ya, final double[] cof) throws InterpolationException {
43          int k;
44          int j;
45          int i;
46          double xmin;
47          final var n = xa.length;
48          final var x = new double[n];
49          final var y = new double[n];
50  
51          for (j = 0; j < n; j++) {
52              x[j] = xa[j];
53              y[j] = ya[j];
54          }
55          for (j = 0; j < n; j++) {
56              final var interp = new PolynomialInterpolator(x, y, n - j, false);
57              // extrapolate to x = 0
58              cof[j] = interp.rawinterp(0, 0.);
59              xmin = 1.0e99;
60              k = -1;
61              for (i = 0; i < n - j; i++) {
62                  // Find the remaining xi of smallest absolute value
63                  if (Math.abs(x[i]) < xmin) {
64                      xmin = Math.abs(x[i]);
65                      k = i;
66                  }
67                  if (x[i] != 0.0) {
68                      // (meanwhile reducing all the terms)
69                      y[i] = (y[i] - cof[j]) / x[i];
70                  }
71              }
72              // and eliminate it
73              for (i = k + 1; i < n - j; i++) {
74                  y[i - 1] = y[i];
75                  x[i - 1] = x[i];
76              }
77          }
78      }
79  }