LaguerreRuleFactory.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF 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.  *      https://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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.analysis.integration.gauss;

  22. import org.hipparchus.util.Pair;

  23. /**
  24.  * Factory that creates Gauss-type quadrature rule using Laguerre polynomials.
  25.  *
  26.  * @see <a href="http://en.wikipedia.org/wiki/Gauss%E2%80%93Laguerre_quadrature">Gauss-Laguerre quadrature (Wikipedia)</a>
  27.  */
  28. public class LaguerreRuleFactory extends AbstractRuleFactory {

  29.     /** Empty constructor.
  30.      * <p>
  31.      * This constructor is not strictly necessary, but it prevents spurious
  32.      * javadoc warnings with JDK 18 and later.
  33.      * </p>
  34.      * @since 3.0
  35.      */
  36.     public LaguerreRuleFactory() { // NOPMD - unnecessary constructor added intentionally to make javadoc happy
  37.         // nothing to do
  38.     }

  39.     /** {@inheritDoc} */
  40.     @Override
  41.     protected Pair<double[], double[]> computeRule(int numberOfPoints) {

  42.         // find nodes as roots of Laguerre polynomial
  43.         final double[] points  = findRoots(numberOfPoints, new Laguerre(numberOfPoints)::ratio);

  44.         // compute weights
  45.         final double[] weights    = new double[numberOfPoints];
  46.         final int      n1         = numberOfPoints + 1;
  47.         final long     n1Squared  = n1 * (long) n1;
  48.         final Laguerre laguerreN1 = new Laguerre(n1);
  49.         for (int i = 0; i < numberOfPoints; i++) {
  50.             final double val = laguerreN1.value(points[i]);
  51.             weights[i] = points[i] / (n1Squared * val * val);
  52.         }

  53.         return new Pair<>(points, weights);

  54.     }

  55.     /** Laguerre polynomial. */
  56.     private static class Laguerre {

  57.         /** Degree. */
  58.         private int degree;

  59.         /** Simple constructor.
  60.          * @param degree polynomial degree
  61.          */
  62.         Laguerre(int degree) {
  63.             this.degree = degree;
  64.         }

  65.         /** Evaluate polynomial.
  66.          * @param x point at which polynomial must be evaluated
  67.          * @return value of the polynomial
  68.          */
  69.         public double value(final double x) {
  70.             return lNlNm1(x)[0];
  71.         }

  72.         /** Compute ratio L(x)/L'(x).
  73.          * @param x point at which ratio must be computed
  74.          * @return ratio L(x)/L'(x)
  75.          */
  76.         public double ratio(double x) {
  77.             double[] l = lNlNm1(x);
  78.             return x * l[0] / (degree * (l[0] - l[1]));
  79.         }

  80.         /** Compute Lₙ(x) and Lₙ₋₁(x).
  81.          * @param x point at which polynomials are evaluated
  82.          * @return array containing Lₙ(x) at index 0 and Lₙ₋₁(x) at index 1
  83.          */
  84.         private double[] lNlNm1(final double x) {
  85.             double[] l = { 1 - x, 1 };
  86.             for (int n = 1; n < degree; n++) {
  87.                 // apply recurrence relation (n+1) Lₙ₊₁(x) = (2n + 1 - x) Lₙ(x) - n Lₙ₋₁(x)
  88.                 final double lp = (l[0] * (2 * n + 1 - x) - l[1] * n) / (n + 1);
  89.                 l[1] = l[0];
  90.                 l[0] = lp;
  91.             }
  92.             return l;
  93.         }

  94.     }

  95. }