<NME> Integrate.cs
<BEF> ﻿// <copyright file="Integrate.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2016 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>

using System;
using System.Numerics;
using MathNet.Numerics.Integration;

namespace MathNet.Numerics
{
    /// <summary>
    /// Numerical Integration (Quadrature).
    /// </summary>
    public static class Integrate
    {
        /// <summary>
        /// Approximation of the definite integral of an analytic smooth function on a closed interval.
        /// </summary>
        /// <param name="f">The analytic smooth function to integrate.</param>
        /// <param name="intervalBegin">Where the interval starts, inclusive and finite.</param>
        /// <param name="intervalEnd">Where the interval stops, inclusive and finite.</param>
        /// <param name="targetAbsoluteError">The expected relative accuracy of the approximation.</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static double OnClosedInterval(Func<double, double> f, double intervalBegin, double intervalEnd, double targetAbsoluteError)
        {
            return DoubleExponentialTransformation.Integrate(f, intervalBegin, intervalEnd, targetAbsoluteError);
        }

        /// <summary>
        /// Approximation of the definite integral of an analytic smooth function on a closed interval.
        /// </summary>
        /// <param name="f">The analytic smooth function to integrate.</param>
        /// <param name="intervalBegin">Where the interval starts, inclusive and finite.</param>
        /// <param name="intervalEnd">Where the interval stops, inclusive and finite.</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static double OnClosedInterval(Func<double, double> f, double intervalBegin, double intervalEnd)
        {
            return DoubleExponentialTransformation.Integrate(f, intervalBegin, intervalEnd, 1e-8);
        }

        /// <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 OnRectangle(Func<double, double, double> f, double invervalBeginA, double invervalEndA, double invervalBeginB, double invervalEndB, int order)
        {
            return GaussLegendreRule.Integrate(f, invervalBeginA, invervalEndA, invervalBeginB, invervalEndB, order);
        }

        /// <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>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static double OnRectangle(Func<double, double, double> f, double invervalBeginA, double invervalEndA, double invervalBeginB, double invervalEndB)
        {
            return GaussLegendreRule.Integrate(f, invervalBeginA, invervalEndA, invervalBeginB, invervalEndB, 32);
        }

        /// <summary>
        /// Approximation of the definite integral of an analytic smooth function by double-exponential quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.
        /// </summary>
        /// <param name="f">The analytic smooth function to integrate.</param>
        /// <param name="intervalBegin">Where the interval starts.</param>
        /// <param name="intervalEnd">Where the interval stops.</param>
        /// <param name="targetAbsoluteError">The expected relative accuracy of the approximation.</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static double DoubleExponential(Func<double, double> f, double intervalBegin, double intervalEnd, double targetAbsoluteError = 1E-8)
        {
            // Reference:
            // Formula used for variable subsitution from
            // 1. Shampine, L. F. (2008). Vectorized adaptive quadrature in MATLAB. Journal of Computational and Applied Mathematics, 211(2), 131-140.
            // 2. quadgk.m, GNU Octave

            if (intervalBegin > intervalEnd)
            {
                return -DoubleExponential(f, intervalEnd, intervalBegin, targetAbsoluteError);
            }

            // (-oo, oo) => [-1, 1]
            //
            // integral_(-oo)^(oo) f(x) dx = integral_(-1)^(1) f(g(t)) g'(t) dt
            // g(t) = t / (1 - t^2)
            // g'(t) = (1 + t^2) / (1 - t^2)^2
            if (double.IsInfinity(intervalBegin) && double.IsInfinity(intervalEnd))
            {
                Func<double, double> u = (t) =>
                {
                    return f(t / (1 - t * t)) * (1 + t * t) / ((1 - t * t) * (1 - t * t));
                };
                return DoubleExponentialTransformation.Integrate(u, -1, 1, targetAbsoluteError);
            }
            // [a, oo) => [0, 1]
            //
            // integral_(a)^(oo) f(x) dx = integral_(0)^(oo) f(a + t^2) 2 t dt
            //                           = integral_(0)^(1) f(a + g(s)^2) 2 g(s) g'(s) ds
            // g(s) = s / (1 - s)
            // g'(s) = 1 / (1 - s)^2
            else if (double.IsInfinity(intervalEnd))
            {
                Func<double, double> u = (s) =>
                {
                    return 2 * s * f(intervalBegin + (s / (1 - s)) * (s / (1 - s))) / ((1 - s) * (1 - s) * (1 - s));
                };
                return DoubleExponentialTransformation.Integrate(u, 0, 1, targetAbsoluteError);
            }
            // (-oo, b] => [-1, 0]
            //
            // integral_(-oo)^(b) f(x) dx = -integral_(-oo)^(0) f(b - t^2) 2 t dt
            //                            = -integral_(-1)^(0) f(b - g(s)^2) 2 g(s) g'(s) ds
            // g(s) = s / (1 + s)
            // g'(s) = 1 / (1 + s)^2
            else if (double.IsInfinity(intervalBegin))
            {
                Func<double, double> u = (s) =>
                {
                    return -2 * s * f(intervalEnd - s / (1 + s) * (s / (1 + s))) / ((1 + s) * (1 + s) * (1 + s));
                };
                return DoubleExponentialTransformation.Integrate(u, -1, 0, targetAbsoluteError);
            }
            else
            {
                return DoubleExponentialTransformation.Integrate(f, intervalBegin, intervalEnd, targetAbsoluteError);
            }
        }

        /// <summary>
        /// Approximation of the definite integral of an analytic smooth function by Gauss-Legendre quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.
        /// <param name="intervalEnd">Where the interval stops.</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 GausLegendre(Func<double, double> f, double intervalBegin, double intervalEnd, int order = 128)
        {
            // Reference:
            // Formula used for variable subsitution from 
        {
            // Reference:
            // Formula used for variable subsitution from
            // 1. Shampine, L. F. (2008). Vectorized adaptive quadrature in MATLAB. Journal of Computational and Applied Mathematics, 211(2), 131-140.
            // 2. quadgk.m, GNU Octave

            if (intervalBegin > intervalEnd)
            {
                return -GaussLegendre(f, intervalEnd, intervalBegin, order);
            }

            // (-oo, oo) => [-1, 1]
            //
            // integral_(-oo)^(oo) f(x) dx = integral_(-1)^(1) f(g(t)) g'(t) dt
            // g(t) = t / (1 - t^2)
            // g'(t) = (1 + t^2) / (1 - t^2)^2
            if (double.IsInfinity(intervalBegin) && double.IsInfinity(intervalEnd))
            {
                Func<double, double> u = (t) =>
                {
                    return f(t / (1 - t * t)) * (1 + t * t) / ((1 - t * t) * (1 - t * t));
                };
                return GaussLegendreRule.Integrate(u, -1, 1, order);
            }
            // [a, oo) => [0, 1]
            //
            // integral_(a)^(oo) f(x) dx = integral_(0)^(oo) f(a + t^2) 2 t dt
            //                           = integral_(0)^(1) f(a + g(s)^2) 2 g(s) g'(s) ds
            // g(s) = s / (1 - s)
            // g'(s) = 1 / (1 - s)^2
            else if (double.IsInfinity(intervalEnd))
            {
                Func<double, double> u = (s) =>
                {
                    return 2 * s * f(intervalBegin + (s / (1 - s)) * (s / (1 - s))) / ((1 - s) * (1 - s) * (1 - s));
                };
                return GaussLegendreRule.Integrate(u, 0, 1, order);
            }
            // (-oo, b] => [-1, 0]
            //
            // integral_(-oo)^(b) f(x) dx = -integral_(-oo)^(0) f(b - t^2) 2 t dt
            //                            = -integral_(-1)^(0) f(b - g(s)^2) 2 g(s) g'(s) ds
            // g(s) = s / (1 + s)
            // g'(s) = 1 / (1 + s)^2
            else if (double.IsInfinity(intervalBegin))
            {
                Func<double, double> u = (s) =>
                {
                    return -2 * s * f(intervalEnd - s / (1 + s) * (s / (1 + s))) / ((1 + s) * (1 + s) * (1 + s));
                };
                return GaussLegendreRule.Integrate(u, -1, 0, order);
            }
            // [a, b] => [-1, 1]
            //
            // integral_(a)^(b) f(x) dx = integral_(-1)^(1) f(g(t)) g'(t) dt
            // g(t) = (b - a) * t * (3 - t^2) / 4 + (b + a) / 2
            // g'(t) = 3 / 4 * (b - a) * (1 - t^2)
            else
            {
                Func<double, double> u = (t) =>
                {
                    return f((intervalEnd - intervalBegin) / 4 * t * (3 - t * t) + (intervalEnd + intervalBegin) / 2) * 3 * (intervalEnd - intervalBegin) / 4 * (1 - t * t);
                };
                return GaussLegendreRule.Integrate(u, -1, 1, order);
            }
        }

        /// <summary>
        /// Approximation of the definite integral of an analytic smooth function by Gauss-Kronrod quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.
        /// </summary>
        /// <param name="f">The analytic smooth function to integrate.</param>
        /// <param name="intervalBegin">Where the interval starts.</param>
        /// <param name="intervalEnd">Where the interval stops.</param>
        /// <param name="targetRelativeError">The expected relative accuracy of the approximation.</param>
        /// <param name="maximumDepth">The maximum number of interval splittings permitted before stopping.</param>
        /// <param name="order">The number of Gauss-Kronrod points. Pre-computed for 15, 21, 31, 41, 51 and 61 points.</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static double GaussKronrod(Func<double, double> f, double intervalBegin, double intervalEnd, double targetRelativeError = 1E-8, int maximumDepth = 15, int order = 15)
        {
            return GaussKronrodRule.Integrate(f, intervalBegin, intervalEnd, out _, out _, targetRelativeError: targetRelativeError, maximumDepth: maximumDepth, order: order);
        }

        /// <summary>
        /// Approximation of the definite integral of an analytic smooth function by Gauss-Kronrod quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.
        /// </summary>
        /// <param name="f">The analytic smooth function to integrate.</param>
        /// <param name="intervalBegin">Where the interval starts.</param>
        /// <param name="intervalEnd">Where the interval stops.</param>
        /// <param name="error">The difference between the (N-1)/2 point Gauss approximation and the N-point Gauss-Kronrod approximation</param>
        /// <param name="L1Norm">The L1 norm of the result, if there is a significant difference between this and the returned value, then the result is likely to be ill-conditioned.</param>
        /// <param name="targetRelativeError">The expected relative accuracy of the approximation.</param>
        /// <param name="maximumDepth">The maximum number of interval splittings permitted before stopping</param>
        /// <param name="order">The number of Gauss-Kronrod points. Pre-computed for 15, 21, 31, 41, 51 and 61 points</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static double GaussKronrod(Func<double, double> f, double intervalBegin, double intervalEnd, out double error, out double L1Norm, double targetRelativeError = 1E-8, int maximumDepth = 15, int order = 15)
        {
            return GaussKronrodRule.Integrate(f, intervalBegin, intervalEnd, out error, out L1Norm, targetRelativeError: targetRelativeError, maximumDepth: maximumDepth, order: order);
        }
    }

    /// <summary>
    /// Numerical Contour Integration of a complex-valued function over a real variable,.
    /// </summary>
    public static class ContourIntegrate
    {
        /// <summary>
        /// Approximation of the definite integral of an analytic smooth complex function by double-exponential quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.
        /// </summary>
        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>
        /// <param name="intervalBegin">Where the interval starts.</param>
        /// <param name="intervalEnd">Where the interval stops.</param>
        /// <param name="targetAbsoluteError">The expected relative accuracy of the approximation.</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static Complex DoubleExponential(Func<double, Complex> f, double intervalBegin, double intervalEnd, double targetAbsoluteError = 1E-8)
        {
            // Reference:
            // Formula used for variable subsitution from
            // 1. Shampine, L. F. (2008). Vectorized adaptive quadrature in MATLAB. Journal of Computational and Applied Mathematics, 211(2), 131-140.
            // 2. quadgk.m, GNU Octave

            if (intervalBegin > intervalEnd)
            {
                return -DoubleExponential(f, intervalEnd, intervalBegin, targetAbsoluteError);
            }

            // (-oo, oo) => [-1, 1]
            //
            // integral_(-oo)^(oo) f(x) dx = integral_(-1)^(1) f(g(t)) g'(t) dt
            // g(t) = t / (1 - t^2)
            // g'(t) = (1 + t^2) / (1 - t^2)^2
            if (double.IsInfinity(intervalBegin) && double.IsInfinity(intervalEnd))
            {
                Func<double, Complex> u = (t) =>
                {
                    return f(t / (1 - t * t)) * (1 + t * t) / ((1 - t * t) * (1 - t * t));
                };
                return DoubleExponentialTransformation.ContourIntegrate(u, -1, 1, targetAbsoluteError);
            }
            // [a, oo) => [0, 1]
            //
            // integral_(a)^(oo) f(x) dx = integral_(0)^(oo) f(a + t^2) 2 t dt
            //                           = integral_(0)^(1) f(a + g(s)^2) 2 g(s) g'(s) ds
            // g(s) = s / (1 - s)
            // g'(s) = 1 / (1 - s)^2
            else if (double.IsInfinity(intervalEnd))
            {
                Func<double, Complex> u = (s) =>
                {
                    return 2 * s * f(intervalBegin + (s / (1 - s)) * (s / (1 - s))) / ((1 - s) * (1 - s) * (1 - s));
                };
                return DoubleExponentialTransformation.ContourIntegrate(u, 0, 1, targetAbsoluteError);
            }
            // (-oo, b] => [-1, 0]
            //
            // integral_(-oo)^(b) f(x) dx = -integral_(-oo)^(0) f(b - t^2) 2 t dt
            //                            = -integral_(-1)^(0) f(b - g(s)^2) 2 g(s) g'(s) ds
            // g(s) = s / (1 + s)
            // g'(s) = 1 / (1 + s)^2
            else if (double.IsInfinity(intervalBegin))
            {
                Func<double, Complex> u = (s) =>
                {
                    return -2 * s * f(intervalEnd - s / (1 + s) * (s / (1 + s))) / ((1 + s) * (1 + s) * (1 + s));
                };
                return DoubleExponentialTransformation.ContourIntegrate(u, -1, 0, targetAbsoluteError);
            }
            else
            {
                return DoubleExponentialTransformation.ContourIntegrate(f, intervalBegin, intervalEnd, targetAbsoluteError);
            }
        }

        /// <summary>
        /// Approximation of the definite integral of an analytic smooth complex function by double-exponential quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.
        /// </summary>
        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>
        /// <param name="intervalBegin">Where the interval starts.</param>
        /// <param name="intervalEnd">Where the interval stops.</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 GaussLegendre(Func<double, Complex> f, double intervalBegin, double intervalEnd, int order = 128)
        {
            // Reference:
            // Formula used for variable subsitution from
            // 1. Shampine, L. F. (2008). Vectorized adaptive quadrature in MATLAB. Journal of Computational and Applied Mathematics, 211(2), 131-140.
            // 2. quadgk.m, GNU Octave

            if (intervalBegin > intervalEnd)
            {
                return -GaussLegendre(f, intervalEnd, intervalBegin, order);
            }

            // (-oo, oo) => [-1, 1]
            //
            // integral_(-oo)^(oo) f(x) dx = integral_(-1)^(1) f(g(t)) g'(t) dt
            // g(t) = t / (1 - t^2)
            // g'(t) = (1 + t^2) / (1 - t^2)^2
            if (double.IsInfinity(intervalBegin) && double.IsInfinity(intervalEnd))
            {
                Func<double, Complex> u = (t) =>
                {
                    return f(t / (1 - t * t)) * (1 + t * t) / ((1 - t * t) * (1 - t * t));
                };
                return GaussLegendreRule.ContourIntegrate(u, -1, 1, order);
            }
            // [a, oo) => [0, 1]
            //
            // integral_(a)^(oo) f(x) dx = integral_(0)^(oo) f(a + t^2) 2 t dt
            //                           = integral_(0)^(1) f(a + g(s)^2) 2 g(s) g'(s) ds
            // g(s) = s / (1 - s)
            // g'(s) = 1 / (1 - s)^2
            else if (double.IsInfinity(intervalEnd))
            {
                Func<double, Complex> u = (s) =>
                {
                    return 2 * s * f(intervalBegin + (s / (1 - s)) * (s / (1 - s))) / ((1 - s) * (1 - s) * (1 - s));
                };
                return GaussLegendreRule.ContourIntegrate(u, 0, 1, order);
            }
            // (-oo, b] => [-1, 0]
            //
            // integral_(-oo)^(b) f(x) dx = -integral_(-oo)^(0) f(b - t^2) 2 t dt
            //                            = -integral_(-1)^(0) f(b - g(s)^2) 2 g(s) g'(s) ds
            // g(s) = s / (1 + s)
            // g'(s) = 1 / (1 + s)^2
            else if (double.IsInfinity(intervalBegin))
            {
                Func<double, Complex> u = (s) =>
                {
                    return -2 * s * f(intervalEnd - s / (1 + s) * (s / (1 + s))) / ((1 + s) * (1 + s) * (1 + s));
                };
                return GaussLegendreRule.ContourIntegrate(u, -1, 0, order);
            }
            // [a, b] => [-1, 1]
            //
            // integral_(a)^(b) f(x) dx = integral_(-1)^(1) f(g(t)) g'(t) dt
            // g(t) = (b - a) * t * (3 - t^2) / 4 + (b + a) / 2
            // g'(t) = 3 / 4 * (b - a) * (1 - t^2)
            else
            {
                Func<double, Complex> u = (t) =>
                {
                    return f((intervalEnd - intervalBegin) / 4 * t * (3 - t * t) + (intervalEnd + intervalBegin) / 2) * 3 * (intervalEnd - intervalBegin) / 4 * (1 - t * t);
                };
                return GaussLegendreRule.ContourIntegrate(u, -1, 1, order);
            }
        }

        /// <summary>
        /// Approximation of the definite integral of an analytic smooth function by Gauss-Kronrod quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.
        /// </summary>
        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>
        /// <param name="intervalBegin">Where the interval starts.</param>
        /// <param name="intervalEnd">Where the interval stops.</param>
        /// <param name="targetRelativeError">The expected relative accuracy of the approximation.</param>
        /// <param name="maximumDepth">The maximum number of interval splittings permitted before stopping</param>
        /// <param name="order">The number of Gauss-Kronrod points. Pre-computed for 15, 21, 31, 41, 51 and 61 points</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static Complex GaussKronrod(Func<double, Complex> f, double intervalBegin, double intervalEnd, double targetRelativeError = 1E-8, int maximumDepth = 15, int order = 15)
        {
            return GaussKronrodRule.ContourIntegrate(f, intervalBegin, intervalEnd, out _, out _, targetRelativeError: targetRelativeError, maximumDepth: maximumDepth, order: order);
        }

        /// <summary>
        /// Approximation of the definite integral of an analytic smooth function by Gauss-Kronrod quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.
        /// </summary>
        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>
        /// <param name="intervalBegin">Where the interval starts.</param>
        /// <param name="intervalEnd">Where the interval stops.</param>
        /// <param name="error">The difference between the (N-1)/2 point Gauss approximation and the N-point Gauss-Kronrod approximation</param>
        /// <param name="L1Norm">The L1 norm of the result, if there is a significant difference between this and the returned value, then the result is likely to be ill-conditioned.</param>
        /// <param name="targetRelativeError">The expected relative accuracy of the approximation.</param>
        /// <param name="maximumDepth">The maximum number of interval splittings permitted before stopping</param>
        /// <param name="order">The number of Gauss-Kronrod points. Pre-computed for 15, 21, 31, 41, 51 and 61 points</param>
        /// <returns>Approximation of the finite integral in the given interval.</returns>
        public static Complex GaussKronrod(Func<double, Complex> f, double intervalBegin, double intervalEnd, out double error, out double L1Norm, double targetRelativeError = 1E-8, int maximumDepth = 15, int order = 15)
        {
            return GaussKronrodRule.ContourIntegrate(f, intervalBegin, intervalEnd, out error, out L1Norm, targetRelativeError: targetRelativeError, maximumDepth: maximumDepth, order: order);
        }
    }
}

<MSG> Fix typos

<DFF> @@ -164,7 +164,7 @@ public static double DoubleExponential(Func<double, double> f, double intervalBe
         /// <param name="intervalEnd">Where the interval stops.</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 GausLegendre(Func<double, double> f, double intervalBegin, double intervalEnd, int order = 128)
+        public static double GaussLegendre(Func<double, double> f, double intervalBegin, double intervalEnd, int order = 128)
         {
             // Reference:
             // Formula used for variable subsitution from 

{'commit': 'diff --git a/src/Numerics.Tests/IntegrationTests/IntegrationTest.cs b/src/Numerics.Tests/IntegrationTests/IntegrationTest.cs\nindex c8422144..dd988098 100644\n--- a/src/Numerics.Tests/IntegrationTests/IntegrationTest.cs\n+++ b/src/Numerics.Tests/IntegrationTests/IntegrationTest.cs\n@@ -62,7 +62,7 @@ private static double TargetFunctionB(double x, double y)\n         }\n \n         /// <summary>\n-        /// Test Function: f(x,y) = 1 / (1 + x^2)\n+        /// Test Function: f(x) = 1 / (1 + x^2)\n         /// </summary>\n         /// <param name="x">First input value.</param>\n         /// <returns>Function result.</returns>\n@@ -72,7 +72,7 @@ private static double TargetFunctionC(double x)\n         }\n \n         /// <summary>\n-        /// Test Function: f(x,y) = log(x)\n+        /// Test Function: f(x) = log(x)\n         /// </summary>\n         /// <param name="x">First input value.</param>\n         /// <returns>Function result.</returns>\n@@ -120,7 +120,7 @@ private static double TargetFunctionD(double x)\n         /// Test Function Stop point.\n         /// </summary>\n         private const double StopD = 1;\n-        \n+\n         /// <summary>\n         /// Target area square.\n         /// </summary>\n@@ -140,7 +140,7 @@ private static double TargetFunctionD(double x)\n         /// Target area.\n         /// </summary>\n         private const double TargetAreaD = -1;\n-        \n+\n         /// <summary>\n         /// Test Integrate facade for simple use cases.\n         /// </summary>\n@@ -183,6 +183,21 @@ public void TestIntegrateFacade()\n                 1e-10,\n                 "DoubleExponential, Target 1e-10");\n \n+            // integrate_(0)^(1) log(x) dx = -1\n+            // Note that DoubleExponential returns -oo.\n+\n+            Assert.AreEqual(\n+                TargetAreaD,\n+                Integrate.OnClosedInterval(TargetFunctionD, StartD, StopD),\n+                1e-10,\n+                "Interval");\n+\n+            Assert.AreEqual(\n+                TargetAreaD,\n+                Integrate.GaussLegendre(TargetFunctionD, StartD, StopD, order: 1024),\n+                1e-10,\n+                "GaussLegendre, order 128");\n+\n             Assert.AreEqual(\n                 TargetAreaD,\n                 Integrate.GaussKronrod(TargetFunctionD, StartD, StopD, 1e-10, order: 15),\n@@ -440,7 +455,7 @@ public void TestIntegralOfGaussian(double a, double b, double expected)\n \n             Assert.AreEqual(\n                 expected,\n-                Integrate.GausLegendre((x) => Math.Exp(-x * x / 2), a, b, order: 128),\n+                Integrate.GaussLegendre((x) => Math.Exp(-x * x / 2), a, b, order: 128),\n                 1e-10,\n                 "GL Integral of e^(-x^2 /2) from {0} to {1}", a, b);\n         }\n@@ -469,7 +484,7 @@ public void TestIntegralOfSinc(double a, double b, double expected, double facto\n \n             Assert.AreEqual(\n                 expected,\n-                factor * Integrate.GausLegendre((x) => 1 / (1 + x * x), a, b, order: 128),\n+                factor * Integrate.GaussLegendre((x) => 1 / (1 + x * x), a, b, order: 128),\n                 1e-10,\n                 "GL Integral of sin(pi*x)/(pi*x) from -oo to oo");\n         }\ndiff --git a/src/Numerics/Integrate.cs b/src/Numerics/Integrate.cs\nindex 6057ed6a..9c7e0370 100644\n--- a/src/Numerics/Integrate.cs\n+++ b/src/Numerics/Integrate.cs\n@@ -164,7 +164,7 @@ public static double DoubleExponential(Func<double, double> f, double intervalBe\n         /// <param name="intervalEnd">Where the interval stops.</param>\n         /// <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>\n         /// <returns>Approximation of the finite integral in the given interval.</returns>\n-        public static double GausLegendre(Func<double, double> f, double intervalBegin, double intervalEnd, int order = 128)\n+        public static double GaussLegendre(Func<double, double> f, double intervalBegin, double intervalEnd, int order = 128)\n         {\n             // Reference:\n             // Formula used for variable subsitution from \n', 'commit_subject': 'Fix typos', 'repo_name': 'mathnet/mathnet-numerics', 'committer': {'name': 'diluculo', 'email': '4e98adf6374c56e91f2f6863b64f29ca081b66b6@gmail.com', 'time_sec': '1568601840', 'tz_offset': '540', 'date': {'seconds': '1568601840'}}, 'commit_tree': 'd84c95494abd007718c5549ed80b498fff02e629', 'commit_message': 'Fix typos\n', 'language_name': 'C', 'license': 'mit', 'hunks': '@@ -164,7 +164,7 @@ public static double DoubleExponential(Func<double, double> f, double intervalBe\n         /// <param name="intervalEnd">Where the interval stops.</param>\n         /// <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>\n         /// <returns>Approximation of the finite integral in the given interval.</returns>\n-        public static double GausLegendre(Func<double, double> f, double intervalBegin, double intervalEnd, int order = 128)\n+        public static double GaussLegendre(Func<double, double> f, double intervalBegin, double intervalEnd, int order = 128)\n         {\n             // Reference:\n             // Formula used for variable subsitution from \n', 'addition_count': 1, 'deletion_count': 1, 'src_file': 'a/src/Numerics/Integrate.cs', 'tgt_file': 'b/src/Numerics/Integrate.cs', 'file_extension': '.cs', 'before_file': '\ufeff// <copyright file="Integrate.cs" company="Math.NET">\n// Math.NET Numerics, part of the Math.NET Project\n// http://numerics.mathdotnet.com\n// http://github.com/mathnet/mathnet-numerics\n//\n// Copyright (c) 2009-2016 Math.NET\n//\n// Permission is hereby granted, free of charge, to any person\n// obtaining a copy of this software and associated documentation\n// files (the "Software"), to deal in the Software without\n// restriction, including without limitation the rights to use,\n// copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following\n// conditions:\n//\n// The above copyright notice and this permission notice shall be\n// included in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\n// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n// OTHER DEALINGS IN THE SOFTWARE.\n// </copyright>\n\nusing System;\nusing System.Numerics;\nusing MathNet.Numerics.Integration;\n\nnamespace MathNet.Numerics\n{\n    /// <summary>\n    /// Numerical Integration (Quadrature).\n    /// </summary>\n    public static class Integrate\n    {\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth function on a closed interval.\n        /// </summary>\n        /// <param name="f">The analytic smooth function to integrate.</param>\n        /// <param name="intervalBegin">Where the interval starts, inclusive and finite.</param>\n        /// <param name="intervalEnd">Where the interval stops, inclusive and finite.</param>\n        /// <param name="targetAbsoluteError">The expected relative accuracy of the approximation.</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static double OnClosedInterval(Func<double, double> f, double intervalBegin, double intervalEnd, double targetAbsoluteError)\n        {\n            return DoubleExponentialTransformation.Integrate(f, intervalBegin, intervalEnd, targetAbsoluteError);\n        }\n\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth function on a closed interval.\n        /// </summary>\n        /// <param name="f">The analytic smooth function to integrate.</param>\n        /// <param name="intervalBegin">Where the interval starts, inclusive and finite.</param>\n        /// <param name="intervalEnd">Where the interval stops, inclusive and finite.</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static double OnClosedInterval(Func<double, double> f, double intervalBegin, double intervalEnd)\n        {\n            return DoubleExponentialTransformation.Integrate(f, intervalBegin, intervalEnd, 1e-8);\n        }\n\n        /// <summary>\n        /// Approximates a 2-dimensional definite integral using an Nth order Gauss-Legendre rule over the rectangle [a,b] x [c,d].\n        /// </summary>\n        /// <param name="f">The 2-dimensional analytic smooth function to integrate.</param>\n        /// <param name="invervalBeginA">Where the interval starts for the first (inside) integral, exclusive and finite.</param>\n        /// <param name="invervalEndA">Where the interval ends for the first (inside) integral, exclusive and finite.</param>\n        /// <param name="invervalBeginB">Where the interval starts for the second (outside) integral, exclusive and finite.</param>\n        /// /// <param name="invervalEndB">Where the interval ends for the second (outside) integral, exclusive and finite.</param>\n        /// <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>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static double OnRectangle(Func<double, double, double> f, double invervalBeginA, double invervalEndA, double invervalBeginB, double invervalEndB, int order)\n        {\n            return GaussLegendreRule.Integrate(f, invervalBeginA, invervalEndA, invervalBeginB, invervalEndB, order);\n        }\n\n        /// <summary>\n        /// Approximates a 2-dimensional definite integral using an Nth order Gauss-Legendre rule over the rectangle [a,b] x [c,d].\n        /// </summary>\n        /// <param name="f">The 2-dimensional analytic smooth function to integrate.</param>\n        /// <param name="invervalBeginA">Where the interval starts for the first (inside) integral, exclusive and finite.</param>\n        /// <param name="invervalEndA">Where the interval ends for the first (inside) integral, exclusive and finite.</param>\n        /// <param name="invervalBeginB">Where the interval starts for the second (outside) integral, exclusive and finite.</param>\n        /// /// <param name="invervalEndB">Where the interval ends for the second (outside) integral, exclusive and finite.</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static double OnRectangle(Func<double, double, double> f, double invervalBeginA, double invervalEndA, double invervalBeginB, double invervalEndB)\n        {\n            return GaussLegendreRule.Integrate(f, invervalBeginA, invervalEndA, invervalBeginB, invervalEndB, 32);\n        }\n\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth function by double-exponential quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.\n        /// </summary>\n        /// <param name="f">The analytic smooth function to integrate.</param>\n        /// <param name="intervalBegin">Where the interval starts.</param>\n        /// <param name="intervalEnd">Where the interval stops.</param>\n        /// <param name="targetAbsoluteError">The expected relative accuracy of the approximation.</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static double DoubleExponential(Func<double, double> f, double intervalBegin, double intervalEnd, double targetAbsoluteError = 1E-8)\n        {\n            // Reference:\n            // Formula used for variable subsitution from\n            // 1. Shampine, L. F. (2008). Vectorized adaptive quadrature in MATLAB. Journal of Computational and Applied Mathematics, 211(2), 131-140.\n            // 2. quadgk.m, GNU Octave\n\n            if (intervalBegin > intervalEnd)\n            {\n                return -DoubleExponential(f, intervalEnd, intervalBegin, targetAbsoluteError);\n            }\n\n            // (-oo, oo) => [-1, 1]\n            //\n            // integral_(-oo)^(oo) f(x) dx = integral_(-1)^(1) f(g(t)) g\'(t) dt\n            // g(t) = t / (1 - t^2)\n            // g\'(t) = (1 + t^2) / (1 - t^2)^2\n            if (double.IsInfinity(intervalBegin) && double.IsInfinity(intervalEnd))\n            {\n                Func<double, double> u = (t) =>\n                {\n                    return f(t / (1 - t * t)) * (1 + t * t) / ((1 - t * t) * (1 - t * t));\n                };\n                return DoubleExponentialTransformation.Integrate(u, -1, 1, targetAbsoluteError);\n            }\n            // [a, oo) => [0, 1]\n            //\n            // integral_(a)^(oo) f(x) dx = integral_(0)^(oo) f(a + t^2) 2 t dt\n            //                           = integral_(0)^(1) f(a + g(s)^2) 2 g(s) g\'(s) ds\n            // g(s) = s / (1 - s)\n            // g\'(s) = 1 / (1 - s)^2\n            else if (double.IsInfinity(intervalEnd))\n            {\n                Func<double, double> u = (s) =>\n                {\n                    return 2 * s * f(intervalBegin + (s / (1 - s)) * (s / (1 - s))) / ((1 - s) * (1 - s) * (1 - s));\n                };\n                return DoubleExponentialTransformation.Integrate(u, 0, 1, targetAbsoluteError);\n            }\n            // (-oo, b] => [-1, 0]\n            //\n            // integral_(-oo)^(b) f(x) dx = -integral_(-oo)^(0) f(b - t^2) 2 t dt\n            //                            = -integral_(-1)^(0) f(b - g(s)^2) 2 g(s) g\'(s) ds\n            // g(s) = s / (1 + s)\n            // g\'(s) = 1 / (1 + s)^2\n            else if (double.IsInfinity(intervalBegin))\n            {\n                Func<double, double> u = (s) =>\n                {\n                    return -2 * s * f(intervalEnd - s / (1 + s) * (s / (1 + s))) / ((1 + s) * (1 + s) * (1 + s));\n                };\n                return DoubleExponentialTransformation.Integrate(u, -1, 0, targetAbsoluteError);\n            }\n            else\n            {\n                return DoubleExponentialTransformation.Integrate(f, intervalBegin, intervalEnd, targetAbsoluteError);\n            }\n        }\n\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth function by Gauss-Legendre quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.\n        /// <param name="intervalEnd">Where the interval stops.</param>\n        /// <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>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static double GausLegendre(Func<double, double> f, double intervalBegin, double intervalEnd, int order = 128)\n        {\n            // Reference:\n            // Formula used for variable subsitution from \n        {\n            // Reference:\n            // Formula used for variable subsitution from\n            // 1. Shampine, L. F. (2008). Vectorized adaptive quadrature in MATLAB. Journal of Computational and Applied Mathematics, 211(2), 131-140.\n            // 2. quadgk.m, GNU Octave\n\n            if (intervalBegin > intervalEnd)\n            {\n                return -GaussLegendre(f, intervalEnd, intervalBegin, order);\n            }\n\n            // (-oo, oo) => [-1, 1]\n            //\n            // integral_(-oo)^(oo) f(x) dx = integral_(-1)^(1) f(g(t)) g\'(t) dt\n            // g(t) = t / (1 - t^2)\n            // g\'(t) = (1 + t^2) / (1 - t^2)^2\n            if (double.IsInfinity(intervalBegin) && double.IsInfinity(intervalEnd))\n            {\n                Func<double, double> u = (t) =>\n                {\n                    return f(t / (1 - t * t)) * (1 + t * t) / ((1 - t * t) * (1 - t * t));\n                };\n                return GaussLegendreRule.Integrate(u, -1, 1, order);\n            }\n            // [a, oo) => [0, 1]\n            //\n            // integral_(a)^(oo) f(x) dx = integral_(0)^(oo) f(a + t^2) 2 t dt\n            //                           = integral_(0)^(1) f(a + g(s)^2) 2 g(s) g\'(s) ds\n            // g(s) = s / (1 - s)\n            // g\'(s) = 1 / (1 - s)^2\n            else if (double.IsInfinity(intervalEnd))\n            {\n                Func<double, double> u = (s) =>\n                {\n                    return 2 * s * f(intervalBegin + (s / (1 - s)) * (s / (1 - s))) / ((1 - s) * (1 - s) * (1 - s));\n                };\n                return GaussLegendreRule.Integrate(u, 0, 1, order);\n            }\n            // (-oo, b] => [-1, 0]\n            //\n            // integral_(-oo)^(b) f(x) dx = -integral_(-oo)^(0) f(b - t^2) 2 t dt\n            //                            = -integral_(-1)^(0) f(b - g(s)^2) 2 g(s) g\'(s) ds\n            // g(s) = s / (1 + s)\n            // g\'(s) = 1 / (1 + s)^2\n            else if (double.IsInfinity(intervalBegin))\n            {\n                Func<double, double> u = (s) =>\n                {\n                    return -2 * s * f(intervalEnd - s / (1 + s) * (s / (1 + s))) / ((1 + s) * (1 + s) * (1 + s));\n                };\n                return GaussLegendreRule.Integrate(u, -1, 0, order);\n            }\n            // [a, b] => [-1, 1]\n            //\n            // integral_(a)^(b) f(x) dx = integral_(-1)^(1) f(g(t)) g\'(t) dt\n            // g(t) = (b - a) * t * (3 - t^2) / 4 + (b + a) / 2\n            // g\'(t) = 3 / 4 * (b - a) * (1 - t^2)\n            else\n            {\n                Func<double, double> u = (t) =>\n                {\n                    return f((intervalEnd - intervalBegin) / 4 * t * (3 - t * t) + (intervalEnd + intervalBegin) / 2) * 3 * (intervalEnd - intervalBegin) / 4 * (1 - t * t);\n                };\n                return GaussLegendreRule.Integrate(u, -1, 1, order);\n            }\n        }\n\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth function by Gauss-Kronrod quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.\n        /// </summary>\n        /// <param name="f">The analytic smooth function to integrate.</param>\n        /// <param name="intervalBegin">Where the interval starts.</param>\n        /// <param name="intervalEnd">Where the interval stops.</param>\n        /// <param name="targetRelativeError">The expected relative accuracy of the approximation.</param>\n        /// <param name="maximumDepth">The maximum number of interval splittings permitted before stopping.</param>\n        /// <param name="order">The number of Gauss-Kronrod points. Pre-computed for 15, 21, 31, 41, 51 and 61 points.</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static double GaussKronrod(Func<double, double> f, double intervalBegin, double intervalEnd, double targetRelativeError = 1E-8, int maximumDepth = 15, int order = 15)\n        {\n            return GaussKronrodRule.Integrate(f, intervalBegin, intervalEnd, out _, out _, targetRelativeError: targetRelativeError, maximumDepth: maximumDepth, order: order);\n        }\n\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth function by Gauss-Kronrod quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.\n        /// </summary>\n        /// <param name="f">The analytic smooth function to integrate.</param>\n        /// <param name="intervalBegin">Where the interval starts.</param>\n        /// <param name="intervalEnd">Where the interval stops.</param>\n        /// <param name="error">The difference between the (N-1)/2 point Gauss approximation and the N-point Gauss-Kronrod approximation</param>\n        /// <param name="L1Norm">The L1 norm of the result, if there is a significant difference between this and the returned value, then the result is likely to be ill-conditioned.</param>\n        /// <param name="targetRelativeError">The expected relative accuracy of the approximation.</param>\n        /// <param name="maximumDepth">The maximum number of interval splittings permitted before stopping</param>\n        /// <param name="order">The number of Gauss-Kronrod points. Pre-computed for 15, 21, 31, 41, 51 and 61 points</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static double GaussKronrod(Func<double, double> f, double intervalBegin, double intervalEnd, out double error, out double L1Norm, double targetRelativeError = 1E-8, int maximumDepth = 15, int order = 15)\n        {\n            return GaussKronrodRule.Integrate(f, intervalBegin, intervalEnd, out error, out L1Norm, targetRelativeError: targetRelativeError, maximumDepth: maximumDepth, order: order);\n        }\n    }\n\n    /// <summary>\n    /// Numerical Contour Integration of a complex-valued function over a real variable,.\n    /// </summary>\n    public static class ContourIntegrate\n    {\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth complex function by double-exponential quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.\n        /// </summary>\n        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>\n        /// <param name="intervalBegin">Where the interval starts.</param>\n        /// <param name="intervalEnd">Where the interval stops.</param>\n        /// <param name="targetAbsoluteError">The expected relative accuracy of the approximation.</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static Complex DoubleExponential(Func<double, Complex> f, double intervalBegin, double intervalEnd, double targetAbsoluteError = 1E-8)\n        {\n            // Reference:\n            // Formula used for variable subsitution from\n            // 1. Shampine, L. F. (2008). Vectorized adaptive quadrature in MATLAB. Journal of Computational and Applied Mathematics, 211(2), 131-140.\n            // 2. quadgk.m, GNU Octave\n\n            if (intervalBegin > intervalEnd)\n            {\n                return -DoubleExponential(f, intervalEnd, intervalBegin, targetAbsoluteError);\n            }\n\n            // (-oo, oo) => [-1, 1]\n            //\n            // integral_(-oo)^(oo) f(x) dx = integral_(-1)^(1) f(g(t)) g\'(t) dt\n            // g(t) = t / (1 - t^2)\n            // g\'(t) = (1 + t^2) / (1 - t^2)^2\n            if (double.IsInfinity(intervalBegin) && double.IsInfinity(intervalEnd))\n            {\n                Func<double, Complex> u = (t) =>\n                {\n                    return f(t / (1 - t * t)) * (1 + t * t) / ((1 - t * t) * (1 - t * t));\n                };\n                return DoubleExponentialTransformation.ContourIntegrate(u, -1, 1, targetAbsoluteError);\n            }\n            // [a, oo) => [0, 1]\n            //\n            // integral_(a)^(oo) f(x) dx = integral_(0)^(oo) f(a + t^2) 2 t dt\n            //                           = integral_(0)^(1) f(a + g(s)^2) 2 g(s) g\'(s) ds\n            // g(s) = s / (1 - s)\n            // g\'(s) = 1 / (1 - s)^2\n            else if (double.IsInfinity(intervalEnd))\n            {\n                Func<double, Complex> u = (s) =>\n                {\n                    return 2 * s * f(intervalBegin + (s / (1 - s)) * (s / (1 - s))) / ((1 - s) * (1 - s) * (1 - s));\n                };\n                return DoubleExponentialTransformation.ContourIntegrate(u, 0, 1, targetAbsoluteError);\n            }\n            // (-oo, b] => [-1, 0]\n            //\n            // integral_(-oo)^(b) f(x) dx = -integral_(-oo)^(0) f(b - t^2) 2 t dt\n            //                            = -integral_(-1)^(0) f(b - g(s)^2) 2 g(s) g\'(s) ds\n            // g(s) = s / (1 + s)\n            // g\'(s) = 1 / (1 + s)^2\n            else if (double.IsInfinity(intervalBegin))\n            {\n                Func<double, Complex> u = (s) =>\n                {\n                    return -2 * s * f(intervalEnd - s / (1 + s) * (s / (1 + s))) / ((1 + s) * (1 + s) * (1 + s));\n                };\n                return DoubleExponentialTransformation.ContourIntegrate(u, -1, 0, targetAbsoluteError);\n            }\n            else\n            {\n                return DoubleExponentialTransformation.ContourIntegrate(f, intervalBegin, intervalEnd, targetAbsoluteError);\n            }\n        }\n\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth complex function by double-exponential quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.\n        /// </summary>\n        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>\n        /// <param name="intervalBegin">Where the interval starts.</param>\n        /// <param name="intervalEnd">Where the interval stops.</param>\n        /// <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>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static Complex GaussLegendre(Func<double, Complex> f, double intervalBegin, double intervalEnd, int order = 128)\n        {\n            // Reference:\n            // Formula used for variable subsitution from\n            // 1. Shampine, L. F. (2008). Vectorized adaptive quadrature in MATLAB. Journal of Computational and Applied Mathematics, 211(2), 131-140.\n            // 2. quadgk.m, GNU Octave\n\n            if (intervalBegin > intervalEnd)\n            {\n                return -GaussLegendre(f, intervalEnd, intervalBegin, order);\n            }\n\n            // (-oo, oo) => [-1, 1]\n            //\n            // integral_(-oo)^(oo) f(x) dx = integral_(-1)^(1) f(g(t)) g\'(t) dt\n            // g(t) = t / (1 - t^2)\n            // g\'(t) = (1 + t^2) / (1 - t^2)^2\n            if (double.IsInfinity(intervalBegin) && double.IsInfinity(intervalEnd))\n            {\n                Func<double, Complex> u = (t) =>\n                {\n                    return f(t / (1 - t * t)) * (1 + t * t) / ((1 - t * t) * (1 - t * t));\n                };\n                return GaussLegendreRule.ContourIntegrate(u, -1, 1, order);\n            }\n            // [a, oo) => [0, 1]\n            //\n            // integral_(a)^(oo) f(x) dx = integral_(0)^(oo) f(a + t^2) 2 t dt\n            //                           = integral_(0)^(1) f(a + g(s)^2) 2 g(s) g\'(s) ds\n            // g(s) = s / (1 - s)\n            // g\'(s) = 1 / (1 - s)^2\n            else if (double.IsInfinity(intervalEnd))\n            {\n                Func<double, Complex> u = (s) =>\n                {\n                    return 2 * s * f(intervalBegin + (s / (1 - s)) * (s / (1 - s))) / ((1 - s) * (1 - s) * (1 - s));\n                };\n                return GaussLegendreRule.ContourIntegrate(u, 0, 1, order);\n            }\n            // (-oo, b] => [-1, 0]\n            //\n            // integral_(-oo)^(b) f(x) dx = -integral_(-oo)^(0) f(b - t^2) 2 t dt\n            //                            = -integral_(-1)^(0) f(b - g(s)^2) 2 g(s) g\'(s) ds\n            // g(s) = s / (1 + s)\n            // g\'(s) = 1 / (1 + s)^2\n            else if (double.IsInfinity(intervalBegin))\n            {\n                Func<double, Complex> u = (s) =>\n                {\n                    return -2 * s * f(intervalEnd - s / (1 + s) * (s / (1 + s))) / ((1 + s) * (1 + s) * (1 + s));\n                };\n                return GaussLegendreRule.ContourIntegrate(u, -1, 0, order);\n            }\n            // [a, b] => [-1, 1]\n            //\n            // integral_(a)^(b) f(x) dx = integral_(-1)^(1) f(g(t)) g\'(t) dt\n            // g(t) = (b - a) * t * (3 - t^2) / 4 + (b + a) / 2\n            // g\'(t) = 3 / 4 * (b - a) * (1 - t^2)\n            else\n            {\n                Func<double, Complex> u = (t) =>\n                {\n                    return f((intervalEnd - intervalBegin) / 4 * t * (3 - t * t) + (intervalEnd + intervalBegin) / 2) * 3 * (intervalEnd - intervalBegin) / 4 * (1 - t * t);\n                };\n                return GaussLegendreRule.ContourIntegrate(u, -1, 1, order);\n            }\n        }\n\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth function by Gauss-Kronrod quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.\n        /// </summary>\n        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>\n        /// <param name="intervalBegin">Where the interval starts.</param>\n        /// <param name="intervalEnd">Where the interval stops.</param>\n        /// <param name="targetRelativeError">The expected relative accuracy of the approximation.</param>\n        /// <param name="maximumDepth">The maximum number of interval splittings permitted before stopping</param>\n        /// <param name="order">The number of Gauss-Kronrod points. Pre-computed for 15, 21, 31, 41, 51 and 61 points</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static Complex GaussKronrod(Func<double, Complex> f, double intervalBegin, double intervalEnd, double targetRelativeError = 1E-8, int maximumDepth = 15, int order = 15)\n        {\n            return GaussKronrodRule.ContourIntegrate(f, intervalBegin, intervalEnd, out _, out _, targetRelativeError: targetRelativeError, maximumDepth: maximumDepth, order: order);\n        }\n\n        /// <summary>\n        /// Approximation of the definite integral of an analytic smooth function by Gauss-Kronrod quadrature. When either or both limits are infinite, the integrand is assumed rapidly decayed to zero as x -> infinity.\n        /// </summary>\n        /// <param name="f">The analytic smooth complex function to integrate, defined on the real domain.</param>\n        /// <param name="intervalBegin">Where the interval starts.</param>\n        /// <param name="intervalEnd">Where the interval stops.</param>\n        /// <param name="error">The difference between the (N-1)/2 point Gauss approximation and the N-point Gauss-Kronrod approximation</param>\n        /// <param name="L1Norm">The L1 norm of the result, if there is a significant difference between this and the returned value, then the result is likely to be ill-conditioned.</param>\n        /// <param name="targetRelativeError">The expected relative accuracy of the approximation.</param>\n        /// <param name="maximumDepth">The maximum number of interval splittings permitted before stopping</param>\n        /// <param name="order">The number of Gauss-Kronrod points. Pre-computed for 15, 21, 31, 41, 51 and 61 points</param>\n        /// <returns>Approximation of the finite integral in the given interval.</returns>\n        public static Complex GaussKronrod(Func<double, Complex> f, double intervalBegin, double intervalEnd, out double error, out double L1Norm, double targetRelativeError = 1E-8, int maximumDepth = 15, int order = 15)\n        {\n            return GaussKronrodRule.ContourIntegrate(f, intervalBegin, intervalEnd, out error, out L1Norm, targetRelativeError: targetRelativeError, maximumDepth: maximumDepth, order: order);\n        }\n    }\n}\n', 'message': 'Fix typos\n', 'author_name': 'diluculo', 'lang': 'cs'}