/// <summary>
        /// Approximates a 2-dimensional definite integral using an Nth order Gauss-Legendre rule over the rectangle [a,b] x [c,d].
        /// </summary>
        /// <param name="f">The 2-dimensional analytic smooth function to integrate.</param>
        /// <param name="invervalBeginA">Where the interval starts for the first (inside) integral, exclusive and finite.</param>
        /// <param name="invervalEndA">Where the interval ends for the first (inside) integral, exclusive and finite.</param>
        /// <param name="invervalBeginB">Where the interval starts for the second (outside) integral, exclusive and finite.</param>
        /// /// <param name="invervalEndB">Where the interval ends for the second (outside) integral, exclusive and finite.</param>
        /// <param name="order">Defines an Nth order Gauss-Legendre rule. The order also defines the number of abscissas and weights for the rule. Precomputed Gauss-Legendre abscissas/weights for orders 2-20, 32, 64, 96, 100, 128, 256, 512, 1024 are used, otherwise they're calculated on the fly.</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static double Integrate(Func <double, double, double> f, double invervalBeginA, double invervalEndA, double invervalBeginB, double invervalEndB, int order)
        {
            GaussPoint gaussLegendrePoint = GaussLegendrePointFactory.GetGaussPoint(order);

            double ax, cy, sum;
            int    i, j;
            int    m = (order + 1) >> 1;

            double a = 0.5 * (invervalEndA - invervalBeginA);
            double b = 0.5 * (invervalEndA + invervalBeginA);
            double c = 0.5 * (invervalEndB - invervalBeginB);
            double d = 0.5 * (invervalEndB + invervalBeginB);

            if (order.IsOdd())
            {
                sum = gaussLegendrePoint.Weights[0] * gaussLegendrePoint.Weights[0] * f(b, d);

                double t;
                for (j = 1, t = 0.0; j < m; j++)
                {
                    cy = c * gaussLegendrePoint.Abscissas[j];
                    t += gaussLegendrePoint.Weights[j] * (f(b, d + cy) + f(b, d - cy));
                }

                sum += gaussLegendrePoint.Weights[0] * t;

                for (i = 1, t = 0.0; i < m; i++)
                {
                    ax = a * gaussLegendrePoint.Abscissas[i];
                    t += gaussLegendrePoint.Weights[i] * (f(b + ax, d) + f(b - ax, d));
                }

                sum += gaussLegendrePoint.Weights[0] * t;

                for (i = 1; i < m; i++)
                {
                    ax = a * gaussLegendrePoint.Abscissas[i];
                    for (j = 1; j < m; j++)
                    {
                        cy   = c * gaussLegendrePoint.Abscissas[j];
                        sum += gaussLegendrePoint.Weights[i] * gaussLegendrePoint.Weights[j] * (f(b + ax, d + cy) + f(ax + b, d - cy) + f(b - ax, d + cy) + f(b - ax, d - cy));
                    }
                }
            }
            else
            {
                sum = 0.0;
                for (i = 0; i < m; i++)
                {
                    ax = a * gaussLegendrePoint.Abscissas[i];
                    for (j = 0; j < m; j++)
                    {
                        cy   = c * gaussLegendrePoint.Abscissas[j];
                        sum += gaussLegendrePoint.Weights[i] * gaussLegendrePoint.Weights[j] * (f(b + ax, d + cy) + f(ax + b, d - cy) + f(b - ax, d + cy) + f(b - ax, d - cy));
                    }
                }
            }

            return(c * a * sum);
        }
        /// <summary>
        /// Approximates a definite integral using an Nth order Gauss-Legendre rule.
        /// </summary>
        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>
        /// <param name="invervalBegin">Where the interval starts, exclusive and finite.</param>
        /// <param name="invervalEnd">Where the interval ends, exclusive and finite.</param>
        /// <param name="order">Defines an Nth order Gauss-Legendre rule. The order also defines the number of abscissas and weights for the rule. Precomputed Gauss-Legendre abscissas/weights for orders 2-20, 32, 64, 96, 100, 128, 256, 512, 1024 are used, otherwise they're calculated on the fly.</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static Complex ContourIntegrate(Func <double, Complex> f, double invervalBegin, double invervalEnd, int order)
        {
            GaussPoint gaussLegendrePoint = GaussLegendrePointFactory.GetGaussPoint(order);

            Complex sum;
            double  ax;
            int     i;
            int     m = (order + 1) >> 1;

            double a = 0.5 * (invervalEnd - invervalBegin);
            double b = 0.5 * (invervalEnd + invervalBegin);

            if (order.IsOdd())
            {
                sum = gaussLegendrePoint.Weights[0] * f(b);
                for (i = 1; i < m; i++)
                {
                    ax   = a * gaussLegendrePoint.Abscissas[i];
                    sum += gaussLegendrePoint.Weights[i] * (f(b + ax) + f(b - ax));
                }
            }
            else
            {
                sum = 0.0;
                for (i = 0; i < m; i++)
                {
                    ax   = a * gaussLegendrePoint.Abscissas[i];
                    sum += gaussLegendrePoint.Weights[i] * (f(b + ax) + f(b - ax));
                }
            }

            return(a * sum);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="GaussLegendreRule"/> class.
 /// </summary>
 /// <param name="intervalBegin">Where the interval starts, inclusive and finite.</param>
 /// <param name="intervalEnd">Where the interval stops, inclusive and finite.</param>
 /// <param name="order">Defines an Nth order Gauss-Legendre rule. The order also defines the number of abscissas and weights for the rule. Precomputed Gauss-Legendre abscissas/weights for orders 2-20, 32, 64, 96, 100, 128, 256, 512, 1024 are used, otherwise they're calculated on the fly.</param>
 public GaussLegendreRule(double intervalBegin, double intervalEnd, int order)
 {
     _gaussLegendrePoint = GaussLegendrePointFactory.GetGaussPoint(intervalBegin, intervalEnd, order);
 }