public static void jacobi_compute(int order, double alpha, double beta, ref double[] x,
                                      ref double[] w)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    JACOBI_COMPUTE computes a Jacobi quadrature rule.
    //
    //  Discussion:
    //
    //    The integration interval is [ -1, 1 ].
    //
    //    The weight function is w(x) = (1-X)^ALPHA * (1+X)^BETA.
    //
    //    The integral to approximate:
    //
    //      Integral ( -1 <= X <= 1 ) (1-X)^ALPHA * (1+X)^BETA * F(X) dX
    //
    //    The quadrature rule:
    //
    //      Sum ( 1 <= I <= ORDER ) W(I) * F ( X(I) )
    //
    //    Thanks to Xu Xiang of Fudan University for pointing out that
    //    an earlier implementation of this routine was incorrect!
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    18 February 2008
    //
    //  Author:
    //
    //    Original FORTRAN77 version by Arthur Stroud, Don Secrest.
    //    C++ version by John Burkardt.
    //
    //  Reference:
    //
    //    Arthur Stroud, Don Secrest,
    //    Gaussian Quadrature Formulas,
    //    Prentice Hall, 1966,
    //    LC: QA299.4G3S7.
    //
    //  Parameters:
    //
    //    Input, int ORDER, the order of the rule.
    //    1 <= ORDER.
    //
    //    Input, double ALPHA, BETA, the exponents of (1-X) and
    //    (1+X) in the quadrature rule.  For simple Legendre quadrature,
    //    set ALPHA = BETA = 0.0.  -1.0 < ALPHA and -1.0 < BETA are required.
    //
    //    Output, double X[ORDER], the abscissas.
    //
    //    Output, double W[ORDER], the weights.
    //
    {
        double dp2 = 0;
        int    i;
        double p1 = 0;
        double temp;
        double x0 = 0;

        switch (order)
        {
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("JACOBI_COMPUTE - Fatal error!");
            Console.WriteLine("  Illegal value of ORDER = " + order + "");
            return;
        }

        double[] b = new double[order];
        double[] c = new double[order];
        switch (alpha)
        {
        //
        //  Check ALPHA and BETA.
        //
        case <= -1.0:
            Console.WriteLine("");
            Console.WriteLine("JACOBI_COMPUTE - Fatal error!");
            Console.WriteLine("  -1.0 < ALPHA is required.");
            return;
        }

        switch (beta)
        {
        case <= -1.0:
            Console.WriteLine("");
            Console.WriteLine("JACOBI_COMPUTE - Fatal error!");
            Console.WriteLine("  -1.0 < BETA is required.");
            return;
        }

        //
        //  Set the recursion coefficients.
        //
        for (i = 1; i <= order; i++)
        {
            if (alpha + beta == 0.0 || beta - alpha == 0.0)
            {
                b[i - 1] = 0.0;
            }
            else
            {
                b[i - 1] = (alpha + beta) * (beta - alpha) /
                           ((alpha + beta + 2 * i)
                            * (alpha + beta + (2 * i - 2)));
            }

            c[i - 1] = i switch
            {
                1 => 0.0,
                _ => 4.0 * (i - 1) * (alpha + (i - 1)) * (beta + (i - 1)) * (alpha + beta + (i - 1)) /
                ((alpha + beta + (2 * i - 1)) * Math.Pow(alpha + beta + (2 * i - 2), 2) *
                 (alpha + beta + (2 * i - 3)))
            };
        }

        double delta = typeMethods.r8_gamma(alpha + 1.0)
                       * typeMethods.r8_gamma(beta + 1.0)
                       / typeMethods.r8_gamma(alpha + beta + 2.0);

        double prod = 1.0;

        for (i = 2; i <= order; i++)
        {
            prod *= c[i - 1];
        }

        double cc = delta * Math.Pow(2.0, alpha + beta + 1.0) * prod;

        for (i = 1; i <= order; i++)
        {
            double r2;
            double r3;
            double r1;
            switch (i)
            {
            case 1:
                double an = alpha / order;
                double bn = beta / order;

                r1 = (1.0 + alpha)
                     * (2.78 / (4.0 + order * order)
                        + 0.768 * an / order);

                r2 = 1.0 + 1.48 * an + 0.96 * bn
                     + 0.452 * an * an + 0.83 * an * bn;

                x0 = (r2 - r1) / r2;
                break;

            case 2:
                r1 = (4.1 + alpha) /
                     ((1.0 + alpha) * (1.0 + 0.156 * alpha));

                r2 = 1.0 + 0.06 * (order - 8.0) *
                     (1.0 + 0.12 * alpha) / order;

                r3 = 1.0 + 0.012 * beta *
                     (1.0 + 0.25 * Math.Abs(alpha)) / order;

                x0 -= r1 * r2 * r3 * (1.0 - x0);
                break;

            case 3:
                r1 = (1.67 + 0.28 * alpha) / (1.0 + 0.37 * alpha);

                r2 = 1.0 + 0.22 * (order - 8.0)
                     / order;

                r3 = 1.0 + 8.0 * beta /
                     ((6.28 + beta) * (order * order));

                x0 -= r1 * r2 * r3 * (x[0] - x0);
                break;

            default:
            {
                if (i < order - 1)
                {
                    x0 = 3.0 * x[i - 2] - 3.0 * x[i - 3] + x[i - 4];
                }
                else if (i == order - 1)
                {
                    r1 = (1.0 + 0.235 * beta) / (0.766 + 0.119 * beta);

                    r2 = 1.0 / (1.0 + 0.639
                                * (order - 4.0)
                                / (1.0 + 0.71 * (order - 4.0)));

                    r3 = 1.0 / (1.0 + 20.0 * alpha / ((7.5 + alpha) *
                                                      (order * order)));

                    x0 += r1 * r2 * r3 * (x0 - x[i - 3]);
                }
                else if (i == order)
                {
                    r1 = (1.0 + 0.37 * beta) / (1.67 + 0.28 * beta);

                    r2 = 1.0 /
                         (1.0 + 0.22 * (order - 8.0)
                          / order);

                    r3 = 1.0 / (1.0 + 8.0 * alpha /
                                ((6.28 + alpha) * (order * order)));

                    x0 += r1 * r2 * r3 * (x0 - x[i - 3]);
                }

                break;
            }
            }

            Jacobi.jacobi_root(ref x0, order, alpha, beta, ref dp2, ref p1, b, c);

            x[i - 1] = x0;
            w[i - 1] = cc / (dp2 * p1);
        }

        //
        //  Reverse the order of the values.
        //
        for (i = 1; i <= order / 2; i++)
        {
            temp         = x[i - 1];
            x[i - 1]     = x[order - i];
            x[order - i] = temp;
        }

        for (i = 1; i <= order / 2; i++)
        {
            temp         = w[i - 1];
            w[i - 1]     = w[order - i];
            w[order - i] = temp;
        }
    }
}