Numerical integration/Gauss-Legendre Quadrature: Difference between revisions

Added FreeBASIC
m (→‎version 1: corrected time 'E' to time 'R' (reset))
(Added FreeBASIC)
 
(107 intermediate revisions by 37 users not shown)
Line 1:
{{Task|Arithmetic operations}}[[Category:Arithmetic]][[Category:Mathematics]]
[[Category:Arithmetic]]
[[Category:Mathematics]]
 
{|border=1 cellspacing=0 cellpadding=3
Line 11 ⟶ 13:
|<math>\int_{-1}^1 f(x)\,dx \approx \sum_{i=1}^n w_i f(x_i)</math>
|}
 
 
For this, we first need to calculate the nodes and the weights, but after we have them, we can reuse them for numerious integral evaluations, which greatly speeds up the calculation compared to more [[Numerical Integration|simple numerical integration methods]].
Line 35 ⟶ 38:
|<math>\int_a^b f(x)\,dx \approx \frac{b-a}{2} \sum_{i=1}^n w_i f\left(\frac{b-a}{2}x_i + \frac{a+b}{2}\right)</math>
|}
 
 
'''Task description'''
Line 40 ⟶ 44:
Similar to the task [[Numerical Integration]], the task here is to calculate the definite integral of a function <math>f(x)</math>, but by applying an n-point Gauss-Legendre quadrature rule, as described [[wp:Gaussian Quadrature|here]], for example. The input values should be an function f to integrate, the bounds of the integration interval a and b, and the number of gaussian evaluation points n. An reference implementation in Common Lisp is provided for comparison.
 
To demonstrate the calculation, compute the weights and nodes for an 5-point quadrature rule and then use them to compute:
<big><big><math>\int_{-3}^{3} \exp(x) \, dx \approx \sum_{i=1}^5 w_i \; \exp(x_i) \approx 20.036</math></big></big>
<br><br>
 
=={{header|11l}}==
::<math>\int_{-3}^{3} \exp(x) \, dx \approx \sum_{i=1}^5 w_i \; \exp(x_i) \approx 20.036</math>
{{trans|Nim}}
 
<syntaxhighlight lang="11l">F legendreIn(x, n)
F prev1(idx, pn1)
R (2 * idx - 1) * @x * pn1
F prev2(idx, pn2)
R (idx - 1) * pn2
 
I n == 0
R 1.0
E I n == 1
R x
E
V result = 0.0
V p1 = x
V p2 = 1.0
L(i) 2 .. n
result = (prev1(i, p1) - prev2(i, p2)) / i
p2 = p1
p1 = result
R result
 
F deriveLegendreIn(x, n)
F calcresult(curr, prev)
R Float(@n) / (@x ^ 2 - 1) * (@x * curr - prev)
R calcresult(legendreIn(x, n), legendreIn(x, n - 1))
 
F guess(n, i)
R cos(math:pi * (i - 0.25) / (n + 0.5))
 
F nodes(n)
V result = [(0.0, 0.0)] * n
F calc(x)
R legendreIn(x, @n) / deriveLegendreIn(x, @n)
 
L(i) 0 .< n
V x = guess(n, i + 1)
V x0 = x
x -= calc(x)
L abs(x - x0) > 1e-12
x0 = x
x -= calc(x)
 
result[i] = (x, 2 / ((1.0 - x ^ 2) * (deriveLegendreIn(x, n)) ^ 2))
 
R result
 
F integ(f, ns, p1, p2)
F dist()
R (@p2 - @p1) / 2
F avg()
R (@p1 + @p2) / 2
V result = dist()
V sum = 0.0
V thenodes = [0.0] * ns
V weights = [0.0] * ns
L(nw) nodes(ns)
sum += nw[1] * f(dist() * nw[0] + avg())
thenodes[L.index] = nw[0]
weights[L.index] = nw[1]
 
print(‘ nodes:’, end' ‘’)
L(n) thenodes
print(‘ #.5’.format(n), end' ‘’)
print()
print(‘ weights:’, end' ‘’)
L(w) weights
print(‘ #.5’.format(w), end' ‘’)
print()
R result * sum
 
print(‘integral: ’integ(x -> exp(x), 5, -3, 3))</syntaxhighlight>
 
{{out}}
<pre>
nodes: 0.90618 0.53847 0.00000 -0.53847 -0.90618
weights: 0.23693 0.47863 0.56889 0.47863 0.23693
integral: 20.035577718
</pre>
 
=={{header|ATS}}==
{{trans|Common Lisp}}
 
This is a very close translation of the Common Lisp.
 
(A lot of the "ATS-ism" is completely optional. For instance, you can use <code>arrszref</code> instead of <code>arrayref</code>, if you want bounds checking at runtime instead of compile-time. But then debugging and regression-prevention become harder, and in that particular case the code will almost surely be slower.
 
And, if I may grumble a bit: ''Some'' of us ''do not'' think "turning off bounds checking for production" is acceptable. It is at best something to tolerate grudgingly.)
 
<syntaxhighlight lang="ats">
#include "share/atspre_staload.hats"
 
%{^
#include <float.h>
#include <math.h>
%}
 
extern fn {tk : tkind} g0float_pi : () -<> g0float tk
extern fn {tk : tkind} g0float_cos : g0float tk -<> g0float tk
extern fn {tk : tkind} g0float_exp : g0float tk -<> g0float tk
implement g0float_pi<dblknd> () = $extval (double, "M_PI")
implement g0float_cos<dblknd> x = $extfcall (double, "cos", x)
implement g0float_exp<dblknd> x = $extfcall (double, "exp", x)
 
macdef PI = g0float_pi ()
overload cos with g0float_cos
overload exp with g0float_exp
 
macdef NAN = g0f2f ($extval (float, "NAN"))
macdef Zero = g0i2f 0
macdef One = g0i2f 1
macdef Two = g0i2f 2
 
(* Computes the initial guess for the root i of a n-order Legendre
polynomial. *)
fn {tk : tkind}
guess {n, i : int | 1 <= i; i <= n}
(n : int n, i : int i) :<> g0float tk =
cos (PI * ((g0i2f i - g0f2f 0.25) / (g0i2f n + g0f2f 0.5)))
 
(* Computes and evaluates the degree-n Legendre polynomial at the
point x. *)
fn {tk : tkind}
legpoly {n : pos}
(n : int n, x : g0float tk) :<> g0float tk =
let
fun
loop {i : int | 2 <= i; i <= n + 1} .<n + 1 - i>.
(i : int i, pa : g0float tk, pb : g0float tk)
:<> g0float tk =
if i = succ n then
pb
else
let
val iflt = (g0i2f i) : g0float tk
val pn = (((iflt + iflt - One) / iflt) * x * pb)
- (((iflt - One) / iflt) * pa)
in
loop (succ i, pb, pn)
end
in
if n = 0 then
One
else if n = 1 then
x
else
loop (2, One, x)
end
 
(* Computes and evaluates the derivative of an n-order Legendre
polynomial at point x. *)
fn {tk : tkind}
legdiff {n : int | 2 <= n}
(n : int n, x : g0float tk) :<> g0float tk =
(g0i2f n / ((x * x) - One))
* ((x * legpoly<tk> (n, x)) - legpoly<tk> (pred n, x))
 
(* Computes the n nodes for an n-point quadrature rule (the n roots of
a degree-n polynomial). *)
fn {tk : tkind}
nodes {n : int | 2 <= n}
(n : int n) :<!refwrt> arrayref (g0float tk, n) =
let
val x = arrayref_make_elt<g0float tk> (i2sz n, Zero)
fn
v_update (v : g0float tk) :<> g0float tk =
v - (legpoly<tk> (n, v) / legdiff<tk> (n, v))
var i : Int
in
for* {i : nat | i <= n} .<n - i>.
(i : int i) =>
(i := 0; i <> n; i := succ i)
let
val v = guess<tk> (n, succ i)
val v = v_update v
val v = v_update v
val v = v_update v
val v = v_update v
val v = v_update v
in
x[i] := v
end;
x
end
 
(* Computes the weight for an degree-n polynomial at the node x. *)
fn {tk : tkind}
legwts {n : int | 2 <= n}
(n : int n, x : g0float tk) :<> g0float tk =
(* Here I am having slightly excessive fun with notation: *)
Two / ((One - (x * x)) * (y * y where {val y = legdiff<tk> (n, x)}))
(* Normally I would not write code in such fashion. :) Nevertheless,
it is interesting that this works. *)
 
(* Takes an array of nodes x and computes an array of corresponding
weights w. Note that x is an arrayref, not an arrszref, and so
(unlike in the Common Lisp) we have to tell the function the size
of the new array w. That information is not otherwise stored AT
RUNTIME. The ATS compiler, however, will force us AT COMPILE TIME
to pass the correct size. *)
fn {tk : tkind}
weights {n : int | 2 <= n}
(n : int n, x : arrayref (g0float tk, n))
:<!refwrt> arrayref (g0float tk, n) =
let
val w = arrayref_make_elt<g0float tk> (i2sz n, Zero)
var i : Int
in
for* {i : nat | i <= n} .<n - i>.
(i : int i) =>
(i := 0; i <> n; i := succ i)
w[i] := legwts (n, x[i]);
w
end
 
(* Estimates the definite integral of a function on [a,b], using an
n-point Gauss-Legendre quadrature rule. *)
fn {tk : tkind}
quad {n : int | 2 <= n}
(f : g0float tk -<> g0float tk,
n : int n,
a : g0float tk,
b : g0float tk) :<> g0float tk =
let
val x = $effmask_ref ($effmask_wrt (nodes<tk> n))
val w = $effmask_ref ($effmask_wrt (weights<tk> (n, x)))
 
val ahalf = g0f2f 0.5 * a and bhalf = g0f2f 0.5 * b
val C1 = bhalf - ahalf and C2 = ahalf + bhalf
 
fun
loop {i : nat | i <= n} .<n - i>.
(i : int i, sum : g0float tk) :<> g0float tk =
if i = n then
sum
else
let
val y = $effmask_ref (w[i] * f ((C1 * x[i]) + C2))
in
loop (succ i, sum + y)
end
in
C1 * loop (0, Zero)
end
 
implement
main () =
let
val outf = stdout_ref
in
fprintln! (outf, "nodes<dblknd> 5");
fprint_arrayref_sep<double> (outf, nodes<dblknd> (5),
i2sz 5, " ");
fprintln! (outf); fprintln! (outf);
fprintln! (outf, "weights (nodes<dblknd> 5)");
fprint_arrayref_sep<double> (outf, weights (5, nodes<dblknd> (5)),
i2sz 5, " ");
fprintln! (outf); fprintln! (outf);
fprintln! (outf, "quad (lam x => exp x, 5, ~3.0, 3.0) = ",
quad (lam x => exp x, 5, ~3.0, 3.0));
fprintln! (outf);
fprintln! (outf, "More examples, borrowed from the Common Lisp:");
fprintln! (outf, "quad (lam x => x ** 3, 5, 0.0, 1.0) = ",
quad (lam x => x ** 3, 5, 0.0, 1.0));
fprintln! (outf, "quad (lam x => 1.0 / x, 5, 1.0, 100.0) = ",
quad (lam x => 1.0 / x, 5, 1.0, 100.0));
fprintln! (outf, "quad (lam x => x, 5, 0.0, 5000.0) = ",
quad (lam x => x, 5, 0.0, 5000.0));
fprintln! (outf, "quad (lam x => x, 5, 0.0, 6000.0) = ",
quad (lam x => x, 5, 0.0, 6000.0));
0
end
</syntaxhighlight>
 
{{out}}
<pre>$ patscc -std=gnu2x -g -O2 -DATS_MEMALLOC_GCBDW gauss_legendre_task.dats -lgc -lm && ./a.out
nodes<dblknd> 5
0.906180 0.538469 0.000000 -0.538469 -0.906180
 
weights (nodes<dblknd> 5)
0.236927 0.478629 0.568889 0.478629 0.236927
 
quad (lam x => exp x, 5, ~3.0, 3.0) = 20.035578
 
More examples, borrowed from the Common Lisp:
quad (lam x => x ** 3, 5, 0.0, 1.0) = 0.250000
quad (lam x => 1.0 / x, 5, 1.0, 100.0) = 4.059148
quad (lam x => x, 5, 0.0, 5000.0) = 12500000.000000
quad (lam x => x, 5, 0.0, 6000.0) = 18000000.000000</pre>
 
=={{header|Axiom}}==
{{trans|Maxima}}
Axiom provides Legendre polynomials and related solvers.<syntaxhighlight lang="axiom">NNI ==> NonNegativeInteger
RECORD ==> Record(x : List Fraction Integer, w : List Fraction Integer)
 
gaussCoefficients(n : NNI, eps : Fraction Integer) : RECORD ==
p := legendreP(n,z)
q := n/2*D(p, z)*legendreP(subtractIfCan(n,1)::NNI, z)
x := map(rhs,solve(p,eps))
w := [subst(1/q, z=xi) for xi in x]
[x,w]
 
gaussIntegrate(e : Expression Float, segbind : SegmentBinding(Float), n : NNI) : Float ==
eps := 1/10^100
u := gaussCoefficients(n,eps)
interval := segment segbind
var := variable segbind
a := lo interval
b := hi interval
c := (a+b)/2
h := (b-a)/2
h*reduce(+,[wi*subst(e,var=c+xi*h) for xi in u.x for wi in u.w])</syntaxhighlight>Example:<syntaxhighlight lang="axiom">digits(50)
gaussIntegrate(4/(1+x^2), x=0..1, 20)
 
(1) 3.1415926535_8979323846_2643379815_9534002592_872901276
Type: Float
% - %pi
 
(2) - 0.3463549483_9378821092_475 E -26</syntaxhighlight>
 
=={{header|C}}==
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <math.h>
 
Line 89 ⟶ 414:
x1 = x;
x -= lege_eval(N, x) / lege_diff(N, x);
} while (x !=fdim( x, x1) > 2e-16 );
/* fdim( ) was introduced in C99, if it isn't available
/* x != x1 is normally a no-no, but this task happens to be
* wellon behaved.your system, try fabs( ) */
lroots[i - 1] = x;
 
Line 128 ⟶ 453:
lege_inte(exp, -3, 3), exp(3) - exp(-3));
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>Roots: 0.90618 0.538469 0 -0.538469 -0.90618
Line 136 ⟶ 461:
compred to actual
20.03574985</pre>
 
=={{header|C++}}==
Derived from various sources already here.
 
Does not quite perform the task quite as specified since the node count, N, is set at compile time (to avoid heap allocation) so cannot be passed as a parameter.
<syntaxhighlight lang="cpp">#include <iostream>
#include <iomanip>
#include <cmath>
 
namespace Rosetta {
 
/*! Implementation of Gauss-Legendre quadrature
* http://en.wikipedia.org/wiki/Gaussian_quadrature
* http://rosettacode.org/wiki/Numerical_integration/Gauss-Legendre_Quadrature
*
*/
template <int N>
class GaussLegendreQuadrature {
public:
enum {eDEGREE = N};
 
/*! Compute the integral of a functor
*
* @param a lower limit of integration
* @param b upper limit of integration
* @param f the function to integrate
* @param err callback in case of problems
*/
template <typename Function>
double integrate(double a, double b, Function f) {
double p = (b - a) / 2;
double q = (b + a) / 2;
const LegendrePolynomial& legpoly = s_LegendrePolynomial;
 
double sum = 0;
for (int i = 1; i <= eDEGREE; ++i) {
sum += legpoly.weight(i) * f(p * legpoly.root(i) + q);
}
return p * sum;
}
 
/*! Print out roots and weights for information
*/
void print_roots_and_weights(std::ostream& out) const {
const LegendrePolynomial& legpoly = s_LegendrePolynomial;
out << "Roots: ";
for (int i = 0; i <= eDEGREE; ++i) {
out << ' ' << legpoly.root(i);
}
out << std::endl;
out << "Weights:";
for (int i = 0; i <= eDEGREE; ++i) {
out << ' ' << legpoly.weight(i);
}
out << std::endl;
}
private:
/*! Implementation of the Legendre polynomials that form
* the basis of this quadrature
*/
class LegendrePolynomial {
public:
LegendrePolynomial () {
// Solve roots and weights
for (int i = 0; i <= eDEGREE; ++i) {
double dr = 1;
 
// Find zero
Evaluation eval(cos(M_PI * (i - 0.25) / (eDEGREE + 0.5)));
do {
dr = eval.v() / eval.d();
eval.evaluate(eval.x() - dr);
} while (fabs (dr) > 2e-16);
 
this->_r[i] = eval.x();
this->_w[i] = 2 / ((1 - eval.x() * eval.x()) * eval.d() * eval.d());
}
}
 
double root(int i) const { return this->_r[i]; }
double weight(int i) const { return this->_w[i]; }
private:
double _r[eDEGREE + 1];
double _w[eDEGREE + 1];
 
/*! Evaluate the value *and* derivative of the
* Legendre polynomial
*/
class Evaluation {
public:
explicit Evaluation (double x) : _x(x), _v(1), _d(0) {
this->evaluate(x);
}
 
void evaluate(double x) {
this->_x = x;
 
double vsub1 = x;
double vsub2 = 1;
double f = 1 / (x * x - 1);
for (int i = 2; i <= eDEGREE; ++i) {
this->_v = ((2 * i - 1) * x * vsub1 - (i - 1) * vsub2) / i;
this->_d = i * f * (x * this->_v - vsub1);
 
vsub2 = vsub1;
vsub1 = this->_v;
}
}
 
double v() const { return this->_v; }
double d() const { return this->_d; }
double x() const { return this->_x; }
 
private:
double _x;
double _v;
double _d;
};
};
 
/*! Pre-compute the weights and abscissae of the Legendre polynomials
*/
static LegendrePolynomial s_LegendrePolynomial;
};
 
template <int N>
typename GaussLegendreQuadrature<N>::LegendrePolynomial GaussLegendreQuadrature<N>::s_LegendrePolynomial;
}
 
// This to avoid issues with exp being a templated function
double RosettaExp(double x) {
return exp(x);
}
 
int main() {
Rosetta::GaussLegendreQuadrature<5> gl5;
std::cout << std::setprecision(10);
 
gl5.print_roots_and_weights(std::cout);
std::cout << "Integrating Exp(X) over [-3, 3]: " << gl5.integrate(-3., 3., RosettaExp) << std::endl;
std::cout << "Actual value: " << RosettaExp(3) - RosettaExp(-3) << std::endl;
}</syntaxhighlight>
 
{{out}}
<pre>
Roots: 0.9061798459 0.9061798459 0.5384693101 0 -0.5384693101 -0.9061798459
Weights: 0.2369268851 0.2369268851 0.4786286705 0.5688888889 0.4786286705 0.2369268851
Integrating Exp(X) over [-3, 3]: 20.03557772
Actual value: 20.03574985
</pre>
 
=={{header|C sharp|C#}}==
Derived from the C++ and Java versions here.
 
<syntaxhighlight lang="csharp">
using System;
//Works in .NET 6+
//Tested using https://dotnetfiddle.net because im lazy
public class Program {
 
public static double[][] legeCoef(int N) {
//Initialising Jagged Array
double[][] lcoef = new double[N+1][];
for (int i=0; i < lcoef.Length; ++i)
lcoef[i] = new double[N+1];
 
 
lcoef[0][0] = lcoef[1][1] = 1;
for (int n = 2; n <= N; n++) {
lcoef[n][0] = -(n - 1) * lcoef[n - 2][0] / n;
for (int i = 1; i <= n; i++)
lcoef[n][i] = ((2*n - 1) * lcoef[n-1][i-1]
- (n-1) * lcoef[n-2][i] ) / n;
}
return lcoef;
}
 
 
static double legeEval(double[][] lcoef, int N, double x) {
double s = lcoef[N][N];
for (int i = N; i > 0; --i)
s = s * x + lcoef[N][i-1];
return s;
}
 
static double legeDiff(double[][] lcoef, int N, double x) {
return N * (x * legeEval(lcoef, N, x) - legeEval(lcoef, N-1, x)) / (x*x - 1);
}
 
static void legeRoots(double[][] lcoef, int N, out double[] lroots, out double[] weight) {
lroots = new double[N];
weight = new double[N];
 
double x, x1;
for (int i = 1; i <= N; i++) {
x = Math.Cos(Math.PI * (i - 0.25) / (N + 0.5));
do {
x1 = x;
x -= legeEval(lcoef, N, x) / legeDiff(lcoef, N, x);
}
while (x != x1);
lroots[i-1] = x;
 
x1 = legeDiff(lcoef, N, x);
weight[i-1] = 2 / ((1 - x*x) * x1*x1);
}
}
 
static double legeInte(Func<Double, Double> f, int N, double[] weights, double[] lroots, double a, double b) {
double c1 = (b - a) / 2, c2 = (b + a) / 2, sum = 0;
for (int i = 0; i < N; i++)
sum += weights[i] * f.Invoke(c1 * lroots[i] + c2);
return c1 * sum;
}
//..................Main...............................
public static string Combine(double[] arrayD) {
return string.Join(", ", arrayD);
}
 
public static void Main() {
int N = 5;
var lcoeff = legeCoef(N);
double[] roots;
double[] weights;
legeRoots(lcoeff, N, out roots, out weights);
var integrateResult = legeInte(x=>Math.Exp(x), N, weights, roots, -3, 3);
Console.WriteLine("Roots: " + Combine(roots));
Console.WriteLine("Weights: " + Combine(weights)+ "\n" );
Console.WriteLine("integral: " + integrateResult );
Console.WriteLine("actual: " + (Math.Exp(3)-Math.Exp(-3)) );
}
 
 
}</syntaxhighlight>
 
{{out}}
<pre>
Roots: 0.906179845938664, 0.538469310105683, 0, -0.538469310105683, -0.906179845938664
Weights: 0.236926885056189, 0.478628670499367, 0.568888888888889, 0.478628670499367, 0.236926885056189
 
integral: 20.0355777183856
actual: 20.0357498548198
</pre>
 
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">;; Computes the initial guess for the root i of a n-order Legendre polynomial.
(defun guess (n i)
(cos (* pi
Line 200 ⟶ 780:
(funcall f (+ (* (/ (- b a) 2.0d0)
(aref x i))
(/ (+ a b) 2.0d0))))))))</langsyntaxhighlight>
{{out|Example}}
<langsyntaxhighlight lang="lisp">(nodes 5)
#(0.906179845938664d0 0.5384693101056831d0 2.996272867003007d-95 -0.5384693101056831d0 -0.906179845938664d0)
 
Line 209 ⟶ 789:
 
(int #'exp 5 -3 3)
20.035577718385568d0</langsyntaxhighlight>
Comparison of the 5-point rule with simpler, but more costly methods from the task [[Numerical Integration]]:
<langsyntaxhighlight lang="lisp">(int #'(lambda (x) (expt x 3)) 5 0 1)
0.24999999999999997d0
 
Line 221 ⟶ 801:
 
(int #'(lambda (x) x) 5 0 6000)
1.8000000000000004d7</langsyntaxhighlight>
 
=={{header|D}}==
{{trans|C}}
<langsyntaxhighlight lang="d">import std.stdio, std.math;
 
immutable struct GaussLegendreQuadrature(size_t N, FP=double,
Line 232 ⟶ 812:
alias FP[N + 1][N + 1] CoefMat;
 
pure nothrow @safe @nogc static this() {
static FP legendreEval(in ref FP[N + 1][N + 1] lcoef,
in int n, in FP x) pure nothrow {
Line 242 ⟶ 822:
 
static FP legendreDiff(in ref CoefMat lcoef,
in int n, in FP x) pure nothrow {
pure nothrow @safe @nogc {
return n * (x * legendreEval(lcoef, n, x) -
legendreEval(lcoef, n - 1, x)) /
(x ^^ 2 - 1);
}
 
static void legendreRoots(in ref CoefMat lcoef) pure nothrow {
foreach (immutable i; 1 .. N + 1) {
FP x = cos(PI * (i - 0.25) / (N + 0.5));
FP x1;
do {
x1 = x;
x -= legendreEval(lcoef, N, x) /
legendreDiff(lcoef, N, x);
} while (feqrel(x, x1) < NBITS);
lroots[i - 1] = x;
x1 = legendreDiff(lcoef, N, x);
weight[i - 1] = 2 / ((1 - x ^^ 2) * (x1 ^^ 2));
}
}
 
CoefMat lcoef = 0.0;
legendreCoefInit(/*ref*/ lcoef);
 
legendreRoots(lcoef);
// Legendre roots:
foreach (immutable i; 1 .. N + 1) {
FP x = cos(PI * (i - 0.25) / (N + 0.5));
FP x1;
do {
x1 = x;
x -= legendreEval(lcoef, N, x) /
legendreDiff(lcoef, N, x);
} while (feqrel(x, x1) < NBITS);
lroots[i - 1] = x;
x1 = legendreDiff(lcoef, N, x);
weight[i - 1] = 2 / ((1 - x ^^ 2) * (x1 ^^ 2));
}
}
 
static private void legendreCoefInit(ref CoefMat lcoef)
pure nothrow @safe @nogc {
lcoef[0][0] = lcoef[1][1] = 1;
foreach (immutable int n; 2 .. N + 1) { // n must be signed.
Line 279 ⟶ 858:
}
 
static public FP integrate(in FP function(/*in*/ FP x) pure nothrow @safe @nogc f,
in FP a, in FP b) {
pure nothrow @safe @nogc {
immutable FP c1 = (b - a) / 2;
immutable FP c2 = (b + a) / 2;
Line 297 ⟶ 877:
glq.integrate(&exp, -3, 3));
writefln("Compred to actual: %10.12f",
3.0.exp - exp(-3.0.exp));
}</langsyntaxhighlight>
{{out}}
<pre>Roots: [0.90618, 0.538469, 0, -0.538469, -0.90618]
Line 304 ⟶ 884:
Integrating exp(x) over [-3, 3]: 20.035577718386
Compred to actual: 20.035749854820</pre>
 
=={{header|Delphi}}==
 
<syntaxhighlight lang="delphi">program Legendre;
 
{$APPTYPE CONSOLE}
 
const Order = 5;
Epsilon = 1E-12;
 
var Roots : array[0..Order-1] of double;
Weight : array[0..Order-1] of double;
LegCoef : array [0..Order,0..Order] of double;
 
function F(X:double) : double;
begin
Result := Exp(X);
end;
 
procedure PrepCoef;
var I, N : integer;
begin
for I:=0 to Order do
for N := 0 to Order do
LegCoef[I,N] := 0;
LegCoef[0,0] := 1;
LegCoef[1,1] := 1;
For N:=2 to Order do
begin
LegCoef[N,0] := -(N-1) * LegCoef[N-2,0] / N;
For I := 1 to Order do
LegCoef[N,I] := ((2*N-1) * LegCoef[N-1,I-1] - (N-1)*LegCoef[N-2,I]) / N;
end;
end;
 
function LegEval(N:integer; X:double) : double;
var I : integer;
begin
Result := LegCoef[n][n];
for I := N-1 downto 0 do
Result := Result * X + LegCoef[N][I];
end;
 
function LegDiff(N:integer; X:double) : double;
begin
Result := N * (X * LegEval(N,X) - LegEval(N-1,X)) / (X*X-1);
end;
 
procedure LegRoots;
var I : integer;
X, X1 : double;
begin
for I := 1 to Order do
begin
X := Cos(Pi * (I-0.25) / (Order+0.5));
repeat
X1 := X;
X := X - LegEval(Order,X) / LegDiff(Order, X);
until Abs (X-X1) < Epsilon;
Roots[I-1] := X;
X1 := LegDiff(Order,X);
Weight[I-1] := 2 / ((1-X*X) * X1*X1);
end;
end;
 
function LegInt(A,B:double) : double;
var I : integer;
C1, C2 : double;
begin
C1 := (B-A)/2;
C2 := (B+A)/2;
Result := 0;
For I := 0 to Order-1 do
Result := Result + Weight[I] * F(C1*Roots[I] + C2);
Result := C1 * Result;
end;
 
var I : integer;
 
begin
PrepCoef;
LegRoots;
 
Write('Roots: ');
for I := 0 to Order-1 do
Write (' ',Roots[I]:13:10);
Writeln;
 
Write('Weight: ');
for I := 0 to Order-1 do
Write (' ', Weight[I]:13:10);
writeln;
 
Writeln('Integrating Exp(x) over [-3, 3]: ',LegInt(-3,3):13:10);
Writeln('Actual value: ',Exp(3)-Exp(-3):13:10);
Readln;
end.</syntaxhighlight>
 
<pre>
Roots: 0.9061798459 0.5384693101 0.0000000000 -0.5384693101 -0.9061798459
Weight: 0.2369268851 0.4786286705 0.5688888889 0.4786286705 0.2369268851
Integrating Exp(X) over [-3, 3]: 20.0355777184
Actual value: 20.0357498548
</pre>
 
=={{header|Fortran}}==
<langsyntaxhighlight Fortranlang="fortran">! Works with gfortran but needs the option
! -assume realloc_lhs
! when compiled with Intel Fortran.
Line 357 ⟶ 1,041:
end function
end program
</syntaxhighlight>
</lang>
 
<pre>
Line 383 ⟶ 1,067:
20 20.0357498548198037979491872388495 -.82E-28
</pre>
 
=={{header|FreeBASIC}}==
{{trans|Wren}}
<syntaxhighlight lang="vbnet">#define PI 4 * Atn(1)
Const As Double LIM = 5
 
Dim Shared As Double lroots(LIM - 1)
Dim Shared As Double weight(LIM - 1)
 
Dim Shared As Double lcoef(LIM, LIM)
For i As Integer = 0 To LIM
For j As Integer = 0 To LIM
lcoef(i, j) = 0
Next j
Next i
 
Sub legeCoef()
lcoef(0, 0) = 1
lcoef(1, 1) = 1
For n As Integer = 2 To LIM
lcoef(n, 0) = -(n - 1) * lcoef(n - 2, 0) / n
For i As Integer = 1 To n
lcoef(n, i) = ((2 * n - 1) * lcoef(n - 1, i - 1) - (n - 1) * lcoef(n - 2, i)) / n
Next i
Next n
End Sub
 
Function legeEval(n As Integer, x As Double) As Double
Dim As Double s = lcoef(n, n)
For i As Integer = n To 1 Step -1
s = s * x + lcoef(n, i - 1)
Next i
Return s
End Function
 
Function legeDiff(n As Integer, x As Double) As Double
Return n * (x * legeEval(n, x) - legeEval(n - 1, x)) / (x * x - 1)
End Function
 
Sub legeRoots()
Dim As Double x = 0
Dim As Double x1 = 0
For i As Integer = 1 To LIM
x = Cos(PI * (i - 0.25) / (LIM + 0.5))
Do
x1 = x
x = x - legeEval(LIM, x) / legeDiff(LIM, x)
Loop Until x = x1
lroots(i - 1) = x
x1 = legeDiff(LIM, x)
weight(i - 1) = 2 / ((1 - x * x) * x1 * x1)
Next i
End Sub
 
Function legeIntegrate(f As Function (As Double) As Double, a As Double, b As Double) As Double
Dim As Double c1 = (b - a) / 2
Dim As Double c2 = (b + a) / 2
Dim As Double sum = 0
For i As Integer = 0 To LIM - 1
sum = sum + weight(i) * f(c1 * lroots(i) + c2)
Next i
Return c1 * sum
End Function
 
legeCoef()
legeRoots()
 
Print "Roots: ";
For i As Integer = 0 To LIM - 1
Print Using " ##.######"; lroots(i);
Next i
Print
 
Print "Weight:";
For i As Integer = 0 To LIM - 1
Print Using " ##.######"; weight(i);
Next i
Print
 
Function f(x As Double) As Double
Return Exp(x)
End Function
 
Dim As Double actual = Exp(3) - Exp(-3)
Print Using !"Integrating exp(x) over [-3, 3]:\n\t########.######,\ncompared to actual\n\t########.######"; legeIntegrate(@f, -3, 3); actual
 
Sleep</syntaxhighlight>
{{out}}
<pre>Roots: 0.906180 0.538469 0.000000 -0.538469 -0.906180
Weight: 0.236927 0.478629 0.568889 0.478629 0.236927
Integrating exp(x) over [-3, 3]:
20.035578,
compared to actual
20.035750</pre>
 
=={{header|Go}}==
Implementation pretty much by the methods given in the task description.
<langsyntaxhighlight lang="go">package main
 
import (
Line 481 ⟶ 1,259:
}
panic("no convergence")
}</langsyntaxhighlight>
{{out}}
<pre>
Line 488 ⟶ 1,266:
integral: 20.035577718385564
</pre>
 
=={{header|Haskell}}==
Integration formula
<syntaxhighlight lang="haskell">gaussLegendre n f a b = d*sum [ w x*f(m + d*x) | x <- roots ]
where d = (b - a)/2
m = (b + a)/2
w x = 2/(1-x^2)/(legendreP' n x)^2
roots = map (findRoot (legendreP n) (legendreP' n) . x0) [1..n]
x0 i = cos (pi*(i-1/4)/(n+1/2))</syntaxhighlight>
 
Calculation of Legendre polynomials
<syntaxhighlight lang="haskell">legendreP n x = go n 1 x
where go 0 p2 _ = p2
go 1 _ p1 = p1
go n p2 p1 = go (n-1) p1 $ ((2*n-1)*x*p1 - (n-1)*p2)/n
 
legendreP' n x = n/(x^2-1)*(x*legendreP n x - legendreP (n-1) x)</syntaxhighlight>
 
Universal auxilary functions
<syntaxhighlight lang="haskell">findRoot f df = fixedPoint (\x -> x - f x / df x)
 
fixedPoint f x | abs (fx - x) < 1e-15 = x
| otherwise = fixedPoint f fx
where fx = f x</syntaxhighlight>
 
Integration on a given mesh using Gauss-Legendre quadrature:
<syntaxhighlight lang="haskell">integrate _ [] = 0
integrate f (m:ms) = sum $ zipWith (gaussLegendre 5 f) (m:ms) ms</syntaxhighlight>
 
{{out}}
 
λ> integrate exp [-3,3]
20.035577718385547
λ> integrate exp [-3..3]
20.03574985481217
λ> gaussLegendre 10 exp (-3) 3
20.035749854819695
 
Analytical solution
λ> exp 3 - exp (-3)
20.035749854819805
 
=={{header|J}}==
'''Solution:'''
<syntaxhighlight lang ="j">P =: 3 :0 NB. list ofreturns coefficientscoefficents for yth-order Legendre polynomial
getLegendreCoeffs=: verb define M.
if. y<:1 do. 1{.~->:y return. end.
if. y<:1 do. 1 {.~ - y+1 return. end.
y%~ (<:(,~+:)y) -/@:* (0,P<:y),:(P y-2)
(%~ <:@(,~ +:) -/@:* (0;'') ,&> [: getLegendreCoeffs&.> -&1 2) y
)
 
getPolyRoots=: 1 {:: p. NB. returns the roots of a polynomial
getpoints =: 3 :0 NB. points,:weights for y points
getGaussLegendreWeights=: 2 % -.@*:@[ * (*:@p.~ p..) NB. form: roots getGaussLegendreWeights coeffs
x=. 1{:: p. p=.P y
getGaussLegendrePoints=: (getPolyRoots ([ ,: getGaussLegendreWeights) ])@getLegendreCoeffs
w=. 2% (-.*:x)**:(p..p)p.x
x,:w
)
 
NB.*integrateGaussLegendre a Integrates a function u with a n-point Gauss-Legendre quadrature rule over the interval [a,b]
GaussLegendre =: 1 :0 NB. npoints function GaussLegendre (a,b)
NB. form: npoints function integrateGaussLegendre (a,b)
integrateGaussLegendre=: adverb define
:
'xnodes wwgts'=.getpoints getGaussLegendrePoints x
-: (-~/ y) * wgts +/w@:* u -:( nodes p.~ (+/ , -~/) y)p.x
)</langsyntaxhighlight>
{{out|Example use}}
<langsyntaxhighlight lang="j"> 5 ^ GaussLegendreintegrateGaussLegendre _3 3
20.0356</lang>
-~/ ^ _3 3 NB. true value
20.0357</syntaxhighlight>
 
=={{header|MathematicaJava}}==
{{trans|C}}
{{works with|Java|8}}
<syntaxhighlight lang="java">import static java.lang.Math.*;
import java.util.function.Function;
 
public class Test {
final static int N = 5;
 
static double[] lroots = new double[N];
static double[] weight = new double[N];
static double[][] lcoef = new double[N + 1][N + 1];
 
static void legeCoef() {
lcoef[0][0] = lcoef[1][1] = 1;
 
for (int n = 2; n <= N; n++) {
 
lcoef[n][0] = -(n - 1) * lcoef[n - 2][0] / n;
 
for (int i = 1; i <= n; i++) {
lcoef[n][i] = ((2 * n - 1) * lcoef[n - 1][i - 1]
- (n - 1) * lcoef[n - 2][i]) / n;
}
}
}
 
static double legeEval(int n, double x) {
double s = lcoef[n][n];
for (int i = n; i > 0; i--)
s = s * x + lcoef[n][i - 1];
return s;
}
 
static double legeDiff(int n, double x) {
return n * (x * legeEval(n, x) - legeEval(n - 1, x)) / (x * x - 1);
}
 
static void legeRoots() {
double x, x1;
for (int i = 1; i <= N; i++) {
x = cos(PI * (i - 0.25) / (N + 0.5));
do {
x1 = x;
x -= legeEval(N, x) / legeDiff(N, x);
} while (x != x1);
 
lroots[i - 1] = x;
 
x1 = legeDiff(N, x);
weight[i - 1] = 2 / ((1 - x * x) * x1 * x1);
}
}
 
static double legeInte(Function<Double, Double> f, double a, double b) {
double c1 = (b - a) / 2, c2 = (b + a) / 2, sum = 0;
for (int i = 0; i < N; i++)
sum += weight[i] * f.apply(c1 * lroots[i] + c2);
return c1 * sum;
}
 
public static void main(String[] args) {
legeCoef();
legeRoots();
 
System.out.print("Roots: ");
for (int i = 0; i < N; i++)
System.out.printf(" %f", lroots[i]);
 
System.out.print("\nWeight:");
for (int i = 0; i < N; i++)
System.out.printf(" %f", weight[i]);
 
System.out.printf("%nintegrating Exp(x) over [-3, 3]:%n\t%10.8f,%n"
+ "compared to actual%n\t%10.8f%n",
legeInte(x -> exp(x), -3, 3), exp(3) - exp(-3));
}
}</syntaxhighlight>
<pre>Roots: 0,906180 0,538469 0,000000 -0,538469 -0,906180
Weight: 0,236927 0,478629 0,568889 0,478629 0,236927
integrating Exp(x) over [-3, 3]:
20,03557772,
compared to actual
20,03574985</pre>
 
=={{header|JavaScript}}==
<syntaxhighlight lang="javascript">
const factorial = n => n <= 1 ? 1 : n * factorial(n - 1);
const M = n => (n - (n % 2 !== 0)) / 2;
const gaussLegendre = (fn, a, b, n) => {
// coefficients of the Legendre polynomial
const coef = [...Array(M(n) + 1)].map((v, m) => v = (-1) ** m * factorial(2 * n - 2 * m) / (2 ** n * factorial(m) * factorial(n - m) * factorial(n - 2 * m)));
// the polynomial function
const f = x => coef.map((v, i) => v * x ** (n - 2 * i)).reduce((sum, item) => sum + item, 0);
const terms = coef.length - (n % 2 === 0);
// coefficients of the derivative polybomial
const dcoef = [...Array(terms)].map((v, i) => v = n - 2 * i).map((val, i) => val * coef[i]);
// the derivative polynomial function
const df = x => dcoef.map((v, i) => v * x ** (n - 1 - 2 * i)).reduce((sum, item) => sum + item, 0);
const guess = [...Array(n)].map((v, i) => Math.cos(Math.PI * (i + 1 - 1 / 4) / (n + 1 / 2)));
// Newton Raphson
const roots = guess.map(xo => [...Array(100)].reduce(x => x - f(x) / df(x), xo));
const weights = roots.map(v => 2 / ((1 - v ** 2) * df(v) ** 2));
return (b - a) / 2 * weights.map((v, i) => v * fn((b - a) * roots[i] / 2 + (a + b) / 2)).reduce((sum, item) => sum + item, 0);
}
console.log(gaussLegendre(x => Math.exp(x), -3, 3, 5));
</syntaxhighlight>
{{output}}
<pre>
20.035577718385575
</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq, and with fq'''
<syntaxhighlight lang=jq>
# output: an array
def legendreCoef($N):
{lcoef: (reduce range(0;$N+1) as $i (null; .[$i] = [range(0;$N + 1)| 0]))}
| .lcoef[0][0] = 1
| .lcoef[1][1] = 1
| reduce range(2; $N+1) as $n (.;
.lcoef[$n][0] = -($n-1) * .lcoef[$n -2][0] / $n
| reduce range (1; $n+1) as $i (.;
.lcoef[$n][$i] = ((2*$n - 1) * .lcoef[$n-1][$i-1] - ($n - 1) * .lcoef[$n-2][$i]) / $n ) )
| .lcoef ;
 
# input: lcoef
# output: the value
def legendreEval($n; $x):
. as $lcoef
| reduce range($n; 0 ;-1) as $i ( $lcoef[$n][$n] ; . * $x + $lcoef[$n][$i-1] ) ;
 
# input: lcoef
def legendreDiff($n; $x):
$n * ($x * legendreEval($n; $x) - legendreEval($n-1; $x)) / ($x*$x - 1) ;
 
# input: lcoef
# output: {lroots, weight}
def legendreRoots($N):
def pi: 1|atan * 4;
. as $lcoef
| { x: 0, x1: null}
| reduce range(1; 1+$N) as $i (.;
.x = ((pi * ($i - 0.25) / ($N + 0.5)) | cos )
| until (.x == .x1;
.x1 = .x
| .x as $x
| .x = .x - ($lcoef | (legendreEval($N; $x) / legendreDiff($N; $x) )) )
| .lroots[$i-1] = .x
| .x as $x
| .x1 = ($lcoef|legendreDiff($N; $x))
| .weight[$i-1] = 2 / ((1 - .x*.x) * .x1 * .x1) ) ;
 
# Input: {lroots, weight}
def legendreIntegrate(f; $a; $b; $N):
.lroots as $lroots
| .weight as $weight
| (($b - $a) / 2) as $c1
| (($b + $a) / 2) as $c2
| reduce range(0;$N) as $i (0; . + $weight[$i] * (($c1* $lroots[$i] + $c2)|f) )
| $c1 * .;
 
def task($N):
def actual: 3|exp - ((-3)|exp);
legendreCoef($N)
| legendreRoots($N)
| "Roots: ",
.lroots,
"\nWeight:",
.weight,
 
"\nIntegrating exp(x) over [-3, 3]: \(legendreIntegrate(exp; -3; 3; N))",
"compared to actual: \(actual)" ;
 
task(5)
</syntaxhighlight>
'''Invocation:'''
<pre>
jq -ncr -f gauss-legendre-quadrature.jq
</pre>
{{output}}
<pre>
Roots:
[0.906179845938664,0.5384693101056831,0,-0.5384693101056831,-0.906179845938664]
 
Weight:
[0.23692688505618922,0.4786286704993667,0.5688888888888889,0.4786286704993667,0.23692688505618922]
 
Integrating exp(x) over [-3, 3]: 20.035577718385575
compared to actual: 20.035749854819805
</pre>
 
=={{header|Julia}}==
This function computes the points and weights of an ''N''-point Gauss–Legendre quadrature rule on the interval (''a'',''b''). It uses the O(''N''<sup>2</sup>) algorithm described in Trefethen & Bau, ''Numerical Linear Algebra'', which finds the points and weights by computing the eigenvalues and eigenvectors of a real-symmetric tridiagonal matrix:
<syntaxhighlight lang="julia">using LinearAlgebra
 
function gauss(a, b, N)
λ, Q = eigen(SymTridiagonal(zeros(N), [n / sqrt(4n^2 - 1) for n = 1:N-1]))
@. (λ + 1) * (b - a) / 2 + a, [2Q[1, i]^2 for i = 1:N] * (b - a) / 2
end</syntaxhighlight>
(This code is a simplified version of the <code>Base.gauss</code> subroutine in the Julia standard library.)
{{out}}
<pre>
julia> x, w = gauss(-3, 3, 5)
([-2.71854, -1.61541, 1.33227e-15, 1.61541, 2.71854], [0.710781, 1.43589, 1.70667, 1.43589, 0.710781])
 
julia> sum(exp.(x) .* w)
20.03557771838554
</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<syntaxhighlight lang="scala">import java.lang.Math.*
 
class Legendre(val N: Int) {
fun evaluate(n: Int, x: Double) = (n downTo 1).fold(c[n][n]) { s, i -> s * x + c[n][i - 1] }
 
fun diff(n: Int, x: Double) = n * (x * evaluate(n, x) - evaluate(n - 1, x)) / (x * x - 1)
 
fun integrate(f: (Double) -> Double, a: Double, b: Double): Double {
val c1 = (b - a) / 2
val c2 = (b + a) / 2
return c1 * (0 until N).fold(0.0) { s, i -> s + weights[i] * f(c1 * roots[i] + c2) }
}
 
private val roots = DoubleArray(N)
private val weights = DoubleArray(N)
private val c = Array(N + 1) { DoubleArray(N + 1) } // coefficients
 
init {
// coefficients:
c[0][0] = 1.0
c[1][1] = 1.0
for (n in 2..N) {
c[n][0] = (1 - n) * c[n - 2][0] / n
for (i in 1..n)
c[n][i] = ((2 * n - 1) * c[n - 1][i - 1] - (n - 1) * c[n - 2][i]) / n
}
 
// roots:
var x: Double
var x1: Double
for (i in 1..N) {
x = cos(PI * (i - 0.25) / (N + 0.5))
do {
x1 = x
x -= evaluate(N, x) / diff(N, x)
} while (x != x1)
 
x1 = diff(N, x)
roots[i - 1] = x
weights[i - 1] = 2 / ((1 - x * x) * x1 * x1)
}
 
print("Roots:")
roots.forEach { print(" %f".format(it)) }
println()
print("Weights:")
weights.forEach { print(" %f".format(it)) }
println()
}
}
 
fun main(args: Array<String>) {
val legendre = Legendre(5)
println("integrating Exp(x) over [-3, 3]:")
println("\t%10.8f".format(legendre.integrate(Math::exp, -3.0, 3.0)))
println("compared to actual:")
println("\t%10.8f".format(exp(3.0) - exp(-3.0)))
}</syntaxhighlight>
{{Out}}
<pre>Roots: 0.906180 0.538469 0.000000 -0.538469 -0.906180
Weights: 0.236927 0.478629 0.568889 0.478629 0.236927
integrating Exp(x) over [-3, 3]:
20.03557772
compared to actual:
20.03574985</pre>
 
=={{header|Lua}}==
<syntaxhighlight lang="lua">local order = 0
 
local legendreRoots = {}
local legendreWeights = {}
 
local function legendre(term, z)
if (term == 0) then
return 1
elseif (term == 1) then
return z
else
return ((2 * term - 1) * z * legendre(term - 1, z) - (term - 1) * legendre(term - 2, z)) / term
end
end
 
local function legendreDerivative(term, z)
if (term == 0) then
return 0
elseif (term == 1) then
return 1
else
return ( term * ((z * legendre(term, z)) - legendre(term - 1, z))) / (z * z - 1)
end
end
 
local function getLegendreRoots()
local y, y1
for index = 1, order do
y = math.cos(math.pi * (index - 0.25) / (order + 0.5))
repeat
y1 = y
y = y - (legendre(order, y) / legendreDerivative(order, y))
until y == y1
table.insert(legendreRoots, y)
end
end
 
local function getLegendreWeights()
for index = 1, order do
local weight = 2 / ((1 - (legendreRoots[index]) ^ 2) * (legendreDerivative(order, legendreRoots[index])) ^ 2)
table.insert(legendreWeights, weight)
end
end
 
function gaussLegendreQuadrature(f, lowerLimit, upperLimit, n)
order = n
do
getLegendreRoots()
getLegendreWeights()
end
local c1 = (upperLimit - lowerLimit) / 2
local c2 = (upperLimit + lowerLimit) / 2
local sum = 0
for i = 1, order do
sum = sum + legendreWeights[i] * f(c1 * legendreRoots[i] + c2)
end
return c1 * sum
end
 
do
print(gaussLegendreQuadrature(function(x) return math.exp(x) end, -3, 3, 5))
end</syntaxhighlight>
{{out}}<pre>20.035577718386</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
code assumes function to be integrated has attribute Listable which is true of most built in Mathematica functions
<langsyntaxhighlight Mathematicalang="mathematica">gaussLegendreQuadrature[func_, {a_, b_}, degree_: 5] :=
Block[{nodes, x, weights},
nodes = Cases[NSolve[LegendreP[degree, x] == 0, x], _?NumericQ, Infinity];
weights = 2 (1 - nodes^2)/(degree LegendreP[degree - 1, nodes])^2;
(b - a)/2 weights.func[(b - a)/2 nodes + (b + a)/2]]
gaussLegendreQuadrature[Exp, {-3, 3}]</syntaxhighlight>
{{out}}<pre>20.0356</pre>
gaussLegendreQuadrature[Exp, {-3, 3}]</lang>
 
=={{header|MATLAB}}==
Translated from the Python solution.
<syntaxhighlight lang="matlab">
%Print the result.
disp(GLGD_int(@(x) exp(x), -3, 3, 5));
 
%Integration using Gauss-Legendre quad
%Does almost the same as 'integral' in MATLAB
function y=GLGD_int(fun,xmin,xmax,n)
%fun: the intergrand as a function handle
%xmin: lower boundary of integration
%xmax: upper boundary of integration
%n: order of polynomials used (number of integration ponts)
[x_IP,weight]=GLGD_para(n);
%assign global coordinates to the integraton points
x_eval=x_IP*(xmax-xmin)/2+(xmax+xmin)/2;
y=0;
for aa=1:n
y=y+feval(fun,x_eval(aa))*weight(aa)*(xmax-xmin)/2;
end
end
 
function [x_IP,weight]=GLGD_para(n)
%n: the order of the polynomial
x_IP=legendreRoot(n,10^(-16));
weight=2./(1-x_IP.^2)./diff_legendrePoly(x_IP,n).^2;
end
 
%roots of the Legendre Polynomial using Newton-Raphson
function x_IP=legendreRoot(n,tol)
%n: order of the polynomial
%tol: tolerence of the error
if n<2
disp('No root can be found');
else
root=zeros(1,floor(n/2));
for aa=1:floor(n/2) %iterate to find half of the roots
x=cos(pi*(aa-0.25)/(n+0.5));
err=10*tol;
iter=0;
while (err>tol)&&(iter<1000)
dx=-legendrePoly(x,n)/diff_legendrePoly(x,n);
x=x+dx;
iter=iter+1;
err=abs(legendrePoly(x,n));
end
root(aa)=x;
end
if mod(n,2)==0
x_IP=[-1*root,root];
else
x_IP=[-1*root,0,root];
end
x_IP=sort(x_IP);
end
end
 
%derivative of the Legendre Polynomial
function y=diff_legendrePoly(x_IP,n)
%n: order of the polynomial
%x_IP: coordinates of the integration points
if n==0
y=0;
else
y=n./(x_IP.^2-1).*(x_IP.*legendrePoly(x_IP,n)-legendrePoly(x_IP,n-1));
end
end
 
%Produces Legendre Polynomials
function y=legendrePoly(x,n)
%n: order of polynomial
%x: input x
if n==0
y=1;
elseif n==1
y=x;
else
y=((2*n-1).*x.*legendrePoly(x,n-1)-(n-1)*legendrePoly(x,n-2))/n;
end
end
</syntaxhighlight>
{{out}}<pre>20.0356</pre>
 
=={{header|Maxima}}==
<langsyntaxhighlight lang="maxima">gauss_coeff(n) := block([p, q, v, w],
p: expand(legendre_p(n, x)),
q: expand(n/2*diff(p, x)*legendre_p(n - 1, x)),
Line 553 ⟶ 1,810:
% - bfloat(integrate(exp(x), x, -3, 3));
/* -1.721364342416440206515136565621888185351b-4 */</langsyntaxhighlight>
 
=={{header|Nim}}==
{{trans|Common Lisp}}
<syntaxhighlight lang="nim">
import math, strformat
 
proc legendreIn(x: float, n: int): float =
 
template prev1(idx: int; pn1: float): float =
(2*idx - 1).float * x * pn1
 
template prev2(idx: int; pn2: float): float =
(idx-1).float * pn2
 
if n == 0:
return 1.0
elif n == 1:
return x
else:
var
p1 = float x
p2 = 1.0
for i in 2 .. n:
result = (i.prev1(p1) - i.prev2(p2)) / i.float
p2 = p1
p1 = result
 
proc deriveLegendreIn(x: float, n: int): float =
template calcresult(curr, prev: float): untyped =
n.float / (x^2 - 1) * (x * curr - prev)
result = calcresult(x.legendreIn n, x.legendreIn(n-1))
 
func guess(n, i: int): float =
cos(PI * (i.float - 0.25) / (n.float + 0.5))
 
proc nodes(n: int): seq[(float, float)] =
result = newseq[(float, float)](n)
template calc(x: float): untyped =
x.legendreIn(n) / x.deriveLegendreIn(n)
 
for i in 0 .. result.high:
var x = guess(n, i+1)
block newton:
var x0 = x
x -= calc x
while abs(x-x0) > 1e-12:
x0 = x
x -= calc x
 
result[i][0] = x
result[i][1] = 2 / ((1.0 - x^2) * (x.deriveLegendreIn n)^2)
 
proc integ(f: proc(x: float): float; ns, p1, p2: int): float =
template dist: untyped =
(p2 - p1).float / 2.0
template avg: untyped =
(p1 + p2).float / 2.0
result = dist()
var
sum = 0'f
thenodes = newseq[float](ns)
weights = newseq[float](ns)
for i, nw in ns.nodes:
sum += nw[1] * f(dist() * nw[0] + avg())
thenodes[i] = nw[0]
weights[i] = nw[1]
 
let apos = ":"
stdout.write fmt"""{"nodes":>8}{apos}"""
for n in thenodes:
stdout.write &" {n:>6.5f}"
stdout.write "\n"
stdout.write &"""{"weights":>8}{apos}"""
for w in weights:
stdout.write &" {w:>6.5f}"
stdout.write "\n"
result *= sum
 
proc main =
echo "integral: ", integ(exp, 5, -3, 3)
 
main()
</syntaxhighlight>
{{out}}
<pre>
nodes: 0.90618 0.53847 0.00000 -0.53847 -0.90618
weights: 0.23693 0.47863 0.56889 0.47863 0.23693
integral: 20.03557634353638
</pre>
 
=={{header|OCaml}}==
<langsyntaxhighlight OCamllang="ocaml">let rec leg n x = match n with (* Evaluate Legendre polynomial *)
| 0 -> 1.0
| 1 -> x
Line 591 ⟶ 1,937:
let f1 x = f ((x*.(b-.a) +. a +. b)*.0.5) in
let eval s (x,w) = s +. w*.(f1 x) in
0.5*.(b-.a)*.(List.fold_left eval 0.0 (nodes n));;</langsyntaxhighlight>
which can be used in:
<langsyntaxhighlight OCamllang="ocaml">let calc n =
Printf.printf
"Gauss-Legendre %2d-point quadrature for exp over [-3..3] = %.16f\n"
Line 601 ⟶ 1,947:
calc 10;;
calc 15;;
calc 20;;</langsyntaxhighlight>
{{out}}
<pre>
Line 610 ⟶ 1,956:
</pre>
This shows convergence to the correct double-precision value of the integral
<langsyntaxhighlight Ocamllang="ocaml">Printf.printf "%.16f\n" ((exp 3.0) -.(exp (-3.0)));;
20.0357498548198052</langsyntaxhighlight>
although going beyond 20 points starts reducing the accuracy, due to accumulated rounding errors.
 
=={{header|PARI/GP}}==
{{works with|PARI/GP|2.4.2 and above}}
This task is easy in GP thanks to built-in support for Legendre polynomials and efficient (Schonhage-Gourdon) polynomial root finding.
<lang parigp>GLq(f,a,b,n)={
my(P=pollegendre(n),Pp=P',x=polroots(P));
(b-a)*sum(i=1,n,f((b-a)*x[i]/2+(a+b)/2)/(1-x[i]^2)/subst(Pp,'x,x[i])^2)
};
# \\ Turn on timer
GLq(x->exp(x), -3, 3, 5) \\ As of version 2.4.4, this can be written GLq(exp, -3, 3, 5)</lang>
{{out}}
<pre>time = 0 ms.
%1 = 20.035577718385562153928535725275093932 + 0.E-37*I</pre>
 
=={{header|ooRexx}}==
<langsyntaxhighlight lang="oorexx">/*---------------------------------------------------------------------
* 31.10.2013 Walter Pachl Translation from REXX (from PL/I)
* using ooRexx' rxmath package
Line 697 ⟶ 2,030:
Return
 
::requires 'rxmath' LIBRARY</langsyntaxhighlight>
Output:
<pre> 1 6.0000000000000000000000000000000000000000 -1.4036E+1
Line 721 ⟶ 2,054:
20.03574985481980606 (exact)</pre>
 
=={{header|Perl 6PARI/GP}}==
{{works with|PARI/GP|2.4.2 and above}}
This task is easy in GP thanks to built-in support for Legendre polynomials and efficient (Schonhage-Gourdon) polynomial root finding.
<syntaxhighlight lang="parigp">GLq(f,a,b,n)={
my(P=pollegendre(n),Pp=P',x=polroots(P));
(b-a)*sum(i=1,n,f((b-a)*x[i]/2+(a+b)/2)/(1-x[i]^2)/subst(Pp,'x,x[i])^2)
};
# \\ Turn on timer
GLq(x->exp(x), -3, 3, 5) \\ As of version 2.4.4, this can be written GLq(exp, -3, 3, 5)</syntaxhighlight>
{{out}}
<pre>time = 0 ms.
%1 = 20.035577718385562153928535725275093932 + 0.E-37*I</pre>
 
{{works with|PARI/GP|2.9.0 and above}}
A free translation of the OCaml solution. We save half the effort to calculate the nodes by exploiting the (skew-)symmetry of the Legendre Polynomials.
Gauss-Legendre quadrature is built-in from 2.9 forward.
The evaluation of Pn(x) is kept linear in n by also passing Pn-1(x) in the recursion.
<syntaxhighlight lang="parigp">intnumgauss(x=-3, 3, exp(x), intnumgaussinit(5))
intnumgauss(x=-3, 3, exp(x)) \\ determine number of points automatically; all digits shown should be accurate</syntaxhighlight>
{{out}}
<pre>%1 = 20.035746975092343883065457558549925374
%2 = 20.035749854819803797949187238931656120</pre>
 
=={{header|Pascal}}==
The <tt>quadrature</tt> function allows passing in a precalculated list of nodes for repeated integrations.
{{trans|Delphi}}
{{works with|Free Pascal|3.0.4}}
{{works with|Multics Pascal|8.0.4a}}
<syntaxhighlight lang="pascal">program Legendre(output);
const Order = 5;
Order1 = Order - 1;
Epsilon = 1E-12;
Pi = 3.1415926;
var Roots : array[0..Order1] of real;
Weight : array[0..Order1] of real;
LegCoef : array [0..Order,0..Order] of real;
I : integer;
function F(X:real) : real;
begin
F := Exp(X);
end;
procedure PrepCoef;
var I, N : integer;
begin
for I:=0 to Order do
for N := 0 to Order do
LegCoef[I,N] := 0;
LegCoef[0,0] := 1;
LegCoef[1,1] := 1;
For N:=2 to Order do
begin
LegCoef[N,0] := -(N-1) * LegCoef[N-2,0] / N;
For I := 1 to Order do
LegCoef[N,I] := ((2*N-1) * LegCoef[N-1,I-1] - (N-1)*LegCoef[N-2,I]) / N;
end;
end;
function LegEval(N:integer; X:real) : real;
var I : integer;
Result : real;
begin
Result := LegCoef[n][n];
for I := N-1 downto 0 do
Result := Result * X + LegCoef[N][I];
LegEval := Result;
end;
function LegDiff(N:integer; X:real) : real;
begin
LegDiff := N * (X * LegEval(N,X) - LegEval(N-1,X)) / (X*X-1);
end;
procedure LegRoots;
var I : integer;
X, X1 : real;
begin
for I := 1 to Order do
begin
X := Cos(Pi * (I-0.25) / (Order+0.5));
repeat
X1 := X;
X := X - LegEval(Order,X) / LegDiff(Order, X);
until Abs (X-X1) < Epsilon;
Roots[I-1] := X;
X1 := LegDiff(Order,X);
Weight[I-1] := 2 / ((1-X*X) * X1*X1);
end;
end;
function LegInt(A,B:real) : real;
var I : integer;
C1, C2, Result : real;
begin
C1 := (B-A)/2;
C2 := (B+A)/2;
Result := 0;
For I := 0 to Order-1 do
Result := Result + Weight[I] * F(C1*Roots[I] + C2);
Result := C1 * Result;
LegInt := Result;
end;
begin
PrepCoef;
LegRoots;
Write('Roots: ');
for I := 0 to Order-1 do
Write (' ',Roots[I]:13:10);
Writeln;
Write('Weight: ');
for I := 0 to Order-1 do
Write (' ', Weight[I]:13:10);
writeln;
Writeln('Integrating Exp(x) over [-3, 3]: ',LegInt(-3,3):13:10);
Writeln('Actual value: ',Exp(3)-Exp(-3):13:10);
end.</syntaxhighlight>
{{out}}
<pre>
Roots: 0.9061798459 0.5384693101 0.0000000000 -0.5384693101 -0.9061798459
Weight: 0.2369268851 0.4786286705 0.5688888889 0.4786286705 0.2369268851
Integrating Exp(x) over [-3, 3]: 20.0355777184
Actual value: 20.0357498548
</pre>
 
=={{header|Perl}}==
Note: The calculations of Pn(x) and P'n(x) could be combined to further reduce duplicated effort. We also could cache P'n(x) from the last Newton-Raphson step for the weight calculation.
{{trans|Raku}}
<syntaxhighlight lang="perl">use List::Util qw(sum);
use constant pi => 3.14159265;
 
sub legendre_pair {
<lang perl6>multi legendre-pair( 1 , $x) { $x, 1 }
multi legendre-pair(Int my($n, $x) {= @_;
myif ($m1,n $m2== 1) ={ return legendre-pair($n -x, 1, $x);}
my \u($m1, $m2) = 1legendre_pair($n - 1 /, $nx);
(1 +my $u) *= $x * $m11 - u1 * $m2,/ $m1n;
(1 + $u) * $x * $m1 - $u * $m2, $m1;
}
 
multisub legendre( 0 , $ ) { 1 }
multi legendre(Int $n, $x) { legendre-pairmy($n, $x)[0] }= @_;
(legendre_pair($n, $x))[0]
}
 
sub legendre_prime {
multi legendre-prime( 0 , $ ) { 0 }
multi legendre-prime( 1 my($n, $ x) { 1= }@_;
if ($n == 0) { return 0 }
multi legendre-prime(Int $n, $x) {
myif ($m0,n $m1== 1) ={ legendre-pair($n,return $x);1 }
my ($m0, $m1) = legendre_pair($n, $x);
($m1 - $x * $m0) * $n / (1 - $x**2);
}
 
sub approximate_legendre_root {
sub approximate-legendre-root(Int $n, Int $k) {
my($n, $k) = @_;
# Approximation due to Francesco Tricomi
my \$t = (4*$k - 1) / (4*$n + 2);
(1 - ($n - 1) / (8 * $n**3)) * cos(pi * $t);
}
 
sub newton_raphson {
sub newton-raphson(&f, &f-prime, $r is copy, :$eps = 2e-16) {
while abs(my \dr = - f($r)n, / f-prime($r)) >= $eps {@_;
while (abs(my $dr = - legendre($n,$r) / legendre_prime($n,$r)) >= 2e-16) {
$r += dr;
$r += $dr;
}
$r;
}
 
sub legendre_root {
sub legendre-root(Int $n, Int $k) {
my($n, $k) = @_;
newton-raphson(&legendre.assuming($n), &legendre-prime.assuming($n),
newton_raphson($n, approximate-legendre-rootapproximate_legendre_root($n, $k));
}
 
sub weight {
sub weight(Int $n, $r) { 2 / ((1 - $r**2) * legendre-prime($n, $r)**2) }
my($n, $r) = @_;
2 / ((1 - $r**2) * legendre_prime($n, $r)**2)
}
 
sub nodes(Int $n) {
gathermy($n) {= @_;
my %node;
take 0 => weight($n, 0) if $n !%% 2;
$node{'0'} = weight($n, 0) forif 10 ..!= $n div %2 {;
for (1 .. myint $r = legendre-root($n,/2) $_);{
my $wr = weightlegendre_root($n, $r_);
takemy $rw => weight($wn, -$r => $w);
$node{$r} = $w; $node{-$r} = $w;
}
return %node
}
 
sub quadrature(Int $n, &f, $a, $b, :@nodes = nodes($n)) {
sub scaleour($x) { ($x * ($b -n, $a) + $a +, $b) / 2= }@_;
sub scale { ($_[0] * ($b - $a) /+ 2 *$a [+] @nodes.map:$b) { .value/ * f(scale(.key))2 }
%nodes = nodes($n);
($b - $a) / 2 * sum map { $nodes{$_} * exp(scale($_)) } keys %nodes;
}
 
say printf("Gauss-Legendre $_.fmt('%2d')-point quadrature ∫₋₃⁺³ exp(x) dx ≈ %.13f\n", $_, quadrature($_, -3, +3) )
quadrature($_, &exp, -3, +3) for 5 .. 10, 20;</lang>
</syntaxhighlight>
 
{{out}}
<pre>Gauss-Legendre 5-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0355777183856
Line 794 ⟶ 2,263:
Gauss-Legendre 10-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548198
Gauss-Legendre 20-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548198</pre>
 
=={{header|Phix}}==
{{trans|Lua}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">order</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">legendreRoots</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
<span style="color: #000000;">legendreWeights</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">legendre</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">term</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">term</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">term</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">z</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">term</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">z</span><span style="color: #0000FF;">*</span><span style="color: #000000;">legendre</span><span style="color: #0000FF;">(</span><span style="color: #000000;">term</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)-(</span><span style="color: #000000;">term</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">legendre</span><span style="color: #0000FF;">(</span><span style="color: #000000;">term</span><span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">))/</span><span style="color: #000000;">term</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">legendreDerivative</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">term</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">term</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span>
<span style="color: #008080;">or</span> <span style="color: #000000;">term</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">term</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">term</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">*</span><span style="color: #000000;">legendre</span><span style="color: #0000FF;">(</span><span style="color: #000000;">term</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">legendre</span><span style="color: #0000FF;">(</span><span style="color: #000000;">term</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)))/(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">*</span><span style="color: #000000;">z</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">getLegendreRoots</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">legendreRoots</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">index</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">order</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">index</span><span style="color: #0000FF;">-</span><span style="color: #000000;">0.25</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">order</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">y1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span>
<span style="color: #000000;">y</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">legendre</span><span style="color: #0000FF;">(</span><span style="color: #000000;">order</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">legendreDerivative</span><span style="color: #0000FF;">(</span><span style="color: #000000;">order</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">-</span><span style="color: #000000;">y1</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">2e-16</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">legendreRoots</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">y</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">getLegendreWeights</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">legendreWeights</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">index</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">order</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">lri</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">legendreRoots</span><span style="color: #0000FF;">[</span><span style="color: #000000;">index</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">diff</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">legendreDerivative</span><span style="color: #0000FF;">(</span><span style="color: #000000;">order</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lri</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">weight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">/</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">1</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lri</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">))*</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">diff</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">legendreWeights</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">weight</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">gaussLegendreQuadrature</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lowerLimit</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">upperLimit</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">order</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
<span style="color: #000000;">getLegendreRoots</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">getLegendreWeights</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">c1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">upperLimit</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">lowerLimit</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">2</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">c2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">upperLimit</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">lowerLimit</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">2</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">order</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">legendreWeights</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c1</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">legendreRoots</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">c2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c1</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">s</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">fmt</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">machine_bits</span><span style="color: #0000FF;">()=</span><span style="color: #000000;">32</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"%.13f"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"%.14f"</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">11</span> <span style="color: #008080;">by</span> <span style="color: #000000;">6</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">gaussLegendreQuadrature</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">exp</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"roots:"</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">legendreRoots</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"weights:"</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">legendreWeights</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Gauss-Legendre %2d-point quadrature for exp over [-3..3] = %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">order</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)-</span><span style="color: #7060A8;">exp</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" compared to actual = %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
roots:{0.9061798459,0.5384693101,0,-0.5384693101,-0.9061798459}
weights:{0.2369268851,0.4786286705,0.5688888889,0.4786286705,0.2369268851}
Gauss-Legendre 5-point quadrature for exp over [-3..3] = 20.0355777183856
Gauss-Legendre 11-point quadrature for exp over [-3..3] = 20.0357498548198
compared to actual = 20.0357498548198
</pre>
Tests showed the result appeared to be accurate to 13 decimal places (15 significant figures) for
order 10 to 30 on 32-bit, and one more for order 11+ on 64-bit.
 
=={{header|PL/I}}==
Translated from Fortran.
<langsyntaxhighlight PLlang="pl/Ii">(subscriptrange, size, fofl):
Integration_Gauss: procedure options (main);
 
Line 851 ⟶ 2,410:
end gaussquad;
end Integration_Gauss;
</syntaxhighlight>
</lang>
<pre>
1 6.0000000000000000 -1.40E+0001
Line 879 ⟶ 2,438:
 
=={{header|Python}}==
{{libheader|numpyNumPy}}
<langsyntaxhighlight Pythonlang="python">from numpy import *
##################################################################
Line 976 ⟶ 2,535:
print "Integral : ", ans
else:
print "Integral evaluation failed"</langsyntaxhighlight>
{{out}}
<pre>
Line 984 ⟶ 2,543:
Integral : 20.0355777184
</pre>
===With library routine===
One can also use the already invented wheel in NumPy:
<syntaxhighlight lang="python">import numpy as np
 
# func is a function that takes a list-like input values
def gauss_legendre_integrate(func, domain, deg):
x, w = np.polynomial.legendre.leggauss(deg)
s = (domain[1] - domain[0])/2
a = (domain[1] + domain[0])/2
return np.sum(s*w*func(s*x + a))
 
for d in range(3, 10):
print(d, gauss_legendre_integrate(np.exp, [-3, 3], d))</syntaxhighlight>
{{out}}
<pre>3 19.853691996805587
4 20.028688395290693
5 20.035577718385575
6 20.035746975092323
7 20.03574981972664
8 20.035749854494522
9 20.03574985481744</pre>
 
=={{header|Racket}}==
Line 989 ⟶ 2,569:
Computation of the Legendre polynomials and derivatives:
 
<langsyntaxhighlight lang="racket">
(define (LegendreP n x)
(let compute ([n n] [Pn-1 x] [Pn-2 1])
Line 1,004 ⟶ 2,584:
(- (* x (LegendreP n x))
(LegendreP (- n 1) x))))
</syntaxhighlight>
</lang>
 
Computation of the Legendre polynomial roots:
 
<langsyntaxhighlight lang="racket">
(define (LegendreP-root n i)
; newton-raphson step
Line 1,022 ⟶ 2,602:
x′
(next (newton-step x′) x′)))))
</syntaxhighlight>
</lang>
 
Computation of Gauss-Legendre nodes and weights
 
<langsyntaxhighlight lang="racket">
(define (Gauss-Legendre-quadrature n)
;; positive roots
Line 1,043 ⟶ 2,623:
(if (odd? n) (list (/ 2 (sqr (LegendreP′ n 0)))) '())
(reverse weights))))
</syntaxhighlight>
</lang>
 
Integration using Gauss-Legendre quadratures:
 
<langsyntaxhighlight lang="racket">
(define (integrate f a b #:nodes (n 5))
(define m (/ (+ a b) 2))
Line 1,054 ⟶ 2,634:
(define (g x) (f (+ m (* d x))))
(* d (+ (apply + (map * w (map g x))))))
</syntaxhighlight>
</lang>
 
Usage:
 
<langsyntaxhighlight lang="racket"><
> (Gauss-Legendre-quadrature 5)
'(-0.906179845938664 -0.5384693101056831 0 0.5384693101056831 0.906179845938664)
Line 1,068 ⟶ 2,648:
> (- (exp 3) (exp -3)
20.035749854819805
</syntaxhighlight>
</lang>
 
Accuracy of the method:
 
<langsyntaxhighlight lang="racket">
> (require plot)
> (parameterize ([plot-x-label "Number of Gaussian nodes"]
Line 1,081 ⟶ 2,661:
(list n (abs (- (integrate exp -3 3 #:nodes n)
(- (exp 3) (exp -3)))))))))
</syntaxhighlight>
</lang>
[[File:gauss.png]]
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|rakudo|2015-09-24}}
A free translation of the OCaml solution. We save half the effort to calculate the nodes by exploiting the (skew-)symmetry of the Legendre Polynomials.
The evaluation of Pn(x) is kept linear in n by also passing Pn-1(x) in the recursion.
 
The <tt>quadrature</tt> function allows passing in a precalculated list of nodes for repeated integrations.
 
Note: The calculations of Pn(x) and P'n(x) could be combined to further reduce duplicated effort. We also could cache P'n(x) from the last Newton-Raphson step for the weight calculation.
 
<syntaxhighlight lang="raku" line>multi legendre-pair( 1 , $x) { $x, 1 }
multi legendre-pair(Int $n, $x) {
my ($m1, $m2) = legendre-pair($n - 1, $x);
my \u = 1 - 1 / $n;
(1 + u) * $x * $m1 - u * $m2, $m1;
}
multi legendre( 0 , $ ) { 1 }
multi legendre(Int $n, $x) { legendre-pair($n, $x)[0] }
multi legendre-prime( 0 , $ ) { 0 }
multi legendre-prime( 1 , $ ) { 1 }
multi legendre-prime(Int $n, $x) {
my ($m0, $m1) = legendre-pair($n, $x);
($m1 - $x * $m0) * $n / (1 - $x**2);
}
sub approximate-legendre-root(Int $n, Int $k) {
# Approximation due to Francesco Tricomi
my \t = (4*$k - 1) / (4*$n + 2);
(1 - ($n - 1) / (8 * $n**3)) * cos(pi * t);
}
sub newton-raphson(&f, &f-prime, $r is copy, :$eps = 2e-16) {
while abs(my \dr = - f($r) / f-prime($r)) >= $eps {
$r += dr;
}
$r;
}
sub legendre-root(Int $n, Int $k) {
newton-raphson(&legendre.assuming($n), &legendre-prime.assuming($n),
approximate-legendre-root($n, $k));
}
sub weight(Int $n, $r) { 2 / ((1 - $r**2) * legendre-prime($n, $r)**2) }
sub nodes(Int $n) {
flat gather {
take 0 => weight($n, 0) if $n !%% 2;
for 1 .. $n div 2 {
my $r = legendre-root($n, $_);
my $w = weight($n, $r);
take $r => $w, -$r => $w;
}
}
}
sub quadrature(Int $n, &f, $a, $b, :@nodes = nodes($n)) {
sub scale($x) { ($x * ($b - $a) + $a + $b) / 2 }
($b - $a) / 2 * [+] @nodes.map: { .value * f(scale(.key)) }
}
say "Gauss-Legendre $_.fmt('%2d')-point quadrature ∫₋₃⁺³ exp(x) dx ≈ ",
quadrature($_, &exp, -3, +3) for flat 5 .. 10, 20;</syntaxhighlight>
 
{{out}}
<pre>Gauss-Legendre 5-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0355777183856
Gauss-Legendre 6-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357469750923
Gauss-Legendre 7-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498197266
Gauss-Legendre 8-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498544945
Gauss-Legendre 9-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548174
Gauss-Legendre 10-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548198
Gauss-Legendre 20-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548198</pre>
 
=={{header|REXX}}==
===version 1===
<langsyntaxhighlight lang="rexx">/*---------------------------------------------------------------------
* 31.10.2013 Walter Pachl Translation from PL/I
* 01.11.2014 -"- see Version 2 for improvements
Line 1,199 ⟶ 2,854:
End
Numeric Digits (prec)
Return r+0</langsyntaxhighlight>
Output:
<pre> 1 6.0000000000000000000000000000000000000000 -1.4036E+1
Line 1,225 ⟶ 2,880:
 
===version 2===
This REXX version is (an optimized version (of version 1) which&nbsp; and uses:
:::* &nbsp; a faster &nbsp; '''cos''' subroutine&nbsp; (whichfunction uses&nbsp; (with radianfull normalizationprecision)
:::* &nbsp; a faster &nbsp; '''exp''' subroutine&nbsp; function &nbsp; (with full precision)
:::* &nbsp; some simple variables instead of stemmed arrays
:::* &nbsp; some static variables instead of repeated expressions
:::* &nbsp; calculations using full (specified) precision (''numeric digits'')
:::* &nbsp; multiplication instead of division
:::* &nbsp; multiplication using &nbsp; [<b>···</b> '''*.5'''] &nbsp; instead of division using &nbsp; [<b>···</b> '''/2''']
:::* &nbsp; a generic approach for setting the numeric DIGITS
:::* &nbsp; ana increasegeneric (byapproach +1)for ofsetting the number&nbsp; of''numeric iterationsdigits''
:::* &nbsp; a better test for earlier termination (stopping) of calculations
:::* &nbsp; about 1/6 the computing time
:::* &nbsp; a more precise value for &nbsp; '''pi'''
Note that the function values for &nbsp; '''pi''' &nbsp; and &nbsp; '''e''' &nbsp; should have more precision than the number of digits specified.
:::* &nbsp; shows an arrow that points where the GLQ number matches the exact value
<lang rexx>/*REXX pgm does numerical integration using Gauss-Legendre Quadrature.*/
:::* &nbsp; displays the number of decimal digits that match the exact value
digs=40; d2=digs*2
numeric digits digs; tiny='1e-'d2; pi=pi(); a=-3; b=3; bma=b-a; bpa=b+a
numeric digits d2; true=exp(b)-exp(a)
numeric digits digs+10
times=digs%2+1
say 'step' center("iterative value",digs+3) ' difference ' /*show hdr*/
sep='────' copies('─' ,digs+3) '────────────'; say sep
 
do step=1 for times; r.=0; p0z=1; p0.1=1
p1z=2; p1.1=1; p1.2=0
do k=2 to step; km=k-1
do L=1 for p1z; T.L=p1.L
end /*L*/
T.L=0; TT.=0
do L=1 for p0z; L2=L+2
TT.L2=p0.L
end /*L*/
 
[GLQ ≡ Gauss─Legendre quadrature.]
do j=1 for p1z+1;T.j=((k+km)*T.j-km*TT.j)/k; end /*j*/
p0z=p1z; do j=1 for p0z; p0.j=p1.j ; end /*j*/
p1z=p1z+1; do j=1 for p1z; p1.j= T.j ; end /*j*/
end /*k*/
 
do !=1 for step
x=cos(pi*(!-.25)/(step+.5))
do times%2 until abs(dx)<tiny
f=p1.1; df=0
do k=2 to p1z
df=f+x*df
f=p1.k+x*f
end /*k*/
dx=f/df; x=x-dx
end /*times%2 until···*/
r.1.!=x
r.2.!=2/((1-x*x)*df*df)
end /*!*/
sum=0
do m=1 for step
sum=sum + r.2.m * exp(bpa*.5 + r.1.m*bma*.5)
end /*m*/
z=bma*sum*.5
say right(step,4) format(z,2,digs) format(z-true,2,4,,0)
end /*step*/
 
The execution speed of this REXX program is largely dependent on the number of decimal digits in &nbsp; '''pi'''.
say sep; say left('',4) true " {exact}"
<br>If faster speed is desired, &nbsp; the number of the decimal digits of &nbsp; '''pi''' &nbsp; can be reduced.
exit /*stick a fork in it, we're done.*/
 
/*──────────────────────────────────COS subroutine───────────────────────────────*/
Each iteration yields around three more (fractional) decimal digits &nbsp; (past the decimal point).
cos: procedure; x=r2r(arg(1)); numeric fuzz min(9,digits()-9); _=1; z=1; p=1; x=x*x
 
do k=2 by 2; _=-_*x/(k*(k-1)); z=z+_; if z=p then return z; p=z; end
The use of "vertical bars" is one of the very few times to use leading comments, as there isn't that many
/*──────────────────────────────────E subroutine──────────────────────────────────────*/
<br>situations where there exists nested &nbsp; &nbsp; '''do''' &nbsp; &nbsp; loops with different (grouped) sizable indentations, &nbsp; and
e: return 2.7182818284590452353602874713526624977572470936999595749669676277240766303535
<br>where there's practically no space on the right side of the REXX source statements. &nbsp; It presents a good
/*──────────────────────────────────EXP subroutine────────────────────────────────────*/
<br>visual indication of what's what, &nbsp; but it's the dickens to pay when updating the source code.
exp: procedure; parse arg x; ix=x%1; if abs(x-ix)>.5 then ix=ix+sign(x); x=x-ix
<syntaxhighlight lang="rexx">/*REXX program does numerical integration using an N─point Gauss─Legendre quadrature rule. */
z=1; _=1; w=z; do j=1; _=_*x/j; z=(z+_)/1; if z==w then leave; w=z; end
pi= pi(); digs= length(pi) - length(.); numeric digits digs; reps= digs % 2
if z\==0 then z=z*e()**ix; return z
 
/*──────────────────────────────────PI subroutine──────────────────────────────────────*/
!.= .; b= 3; a= -b; bma= b - a; bmaH= bma / 2; tiny= '1e-'digs
pi: return 3.1415926535897932384626433832795028841971693993751058209749445923078164062862
trueV= exp(b)-exp(a); bpa= b + a; bpaH= bpa / 2
/*──────────────────────────────────R2R subroutine──────────────────────*/
hdr= 'iterate value (with ' digs " decimal digits being used)"
r2r: return arg(1)//(2*pi()) /*normalize radians►1 unit circle*/</lang>
say ' step ' center(hdr, digs+3) ' difference' /*show hdr*/
'''output'''
sep='──────' copies("─", digs+3) '─────────────'; say sep /* " sep*/
<pre style="overflow:scroll">
 
step iterative value difference
do #=1 until dif>0; p0z= 1; p0.1= 1; p1z= 2; p1.1= 1; p1.2= 0; ##= # + .5; r.= 0
──── ─────────────────────────────────────────── ────────────
/*█*/ do k=2 to #; km= k - 1
1 6.0000000000000000000000000000000000000000 -1.4036e+1
/*█*/ do y=1 for p1z; T.y= p1.y; end /*y*/
2 17.4874646410555689643606840462449458421154 -2.5483
/*█*/ T.y= 0; TT.= 0; do L=1 for p0z; _= L + 2; TT._= p0.L; end /*L*/
3 19.8536919968055821921309108927158495960775 -1.8206e-1
/*█*/ kkm= k + km; do j=1 for p1z +1; T.j= (kkm*T.j - km*TT.j)/k; end /*j*/
4 20.0286883952907008527738054439857661647073 -7.0615e-3
/*█*/ p0z= p1z; do n=1 for p0z; p0.n= p1.n ; end /*n*/
5 20.0355777183855621539285357252750939315016 -1.7214e-4
/*█*/ p1z= p1z + 1; do p=1 for p1z; p1.p= T.p ; end /*p*/
6 20.0357469750923438830654575585499253741530 -2.8797e-6
/*█*/ end /*k*/
7 20.0357498197266007755718729372891903369401 -3.5093e-8
/*▓*/ do !=1 for #; x= cos( pi * (! - .25) / ## )
8 20.0357498544945172882260918041683132616237 -3.2529e-10
/*▓*/ /*░*/ do reps until abs(dx) <= tiny
9 20.0357498548174338368864419454858704839263 -2.3700e-12
/*▓*/ /*░*/ f= p1.1; df= 0; do u=2 to p1z; df= f + x*df
10 20.0357498548197898711175766908543458234008 -1.3927e-14
/*▓*/ /*░*/ f= p1.u +x*f
11 20.0357498548198037305529147159697031241994 -6.7396e-17
/*▓*/ /*░*/ end /*u*/
12 20.0357498548198037976759531014454017742327 -2.7323e-19
/*▓*/ /*░*/ dx= f / df; x= x - dx
13 20.0357498548198037979482458119092690701863 -9.4143e-22
/*▓*/ /*░*/ end /*reps ···*/
14 20.0357498548198037979491844483599375945130 -2.7906e-24
/*▓*/ r.1.!= x
15 20.0357498548198037979491872317401917248453 -7.1915e-27
/*▓*/ r.2.!= 2 / ( (1 - x*x) * df*df)
16 20.0357498548198037979491872389153958789316 -1.6260e-29
/*▓*/ end /*!*/
17 20.0357498548198037979491872389316236038179 -3.2517e-32
$= 0
18 20.0357498548198037979491872389316560624361 -5.7920e-35
/*▒*/ do m=1 for #; $=$ + r.2.m * exp(bpaH + r.1.m*bmaH); end /*m*/
19 20.0357498548198037979491872389316561202637 -9.2480e-38
z= bmaH * $ /*calculate target value (Z)*/
20 20.0357498548198037979491872389316561203561 -1.3313e-40
dif= z - trueV; z= format(z, 3, digs - 2) /* " difference. */
21 20.0357498548198037979491872389316561203562 2.0044e-43
Ndif= translate( format(dif, 3, 4, 2, 0), 'e', "E")
──── ─────────────────────────────────────────── ────────────
if #\==1 then say center(#, 6) z' ' Ndif /*no display if not computed*/
20.035749854819803797949187238931656120356208246365726928811306502092785210360717 {exact}
end /*#*/
 
say sep; xdif= compare( strip(z), trueV); say right("↑", 6 + 1 + xdif)
say left('', 6 + 1) trueV " {exact value}"; say
say 'Using ' digs " digit precision, the" ,
'N-point Gauss─Legendre quadrature (GLQ) had an accuracy of ' xdif-2 " digits."
exit 0 /*stick a fork in it, we're all done. */
/*───────────────────────────────────────────────────────────────────────────────────────────*/
e: return 2.718281828459045235360287471352662497757247093699959574966967627724076630353547595
pi: return 3.141592653589793238462643383279502884197169399375105820974944592307816406286286209
/*───────────────────────────────────────────────────────────────────────────────────────────*/
cos: procedure expose !.; parse arg x; if !.x\==. then return !.x; _= 1; z=1; y= x*x
do k=2 by 2 until p==z; p=z; _= -_*y/(k*(k-1)); z=z+_; end; !.x=z; return z
/*───────────────────────────────────────────────────────────────────────────────────────────*/
exp: procedure; parse arg x; ix= x % 1; if abs(x-ix)>.5 then ix= ix + sign(x); x= x-ix; z= 1
_=1; do j=1 until p==z; p=z; _= _*x/j; z= z+_; end; return z * e()**ix</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
step iterate value (with 82 decimal digits being used) difference
────── ───────────────────────────────────────────────────────────────────────────────────── ─────────────
2 17.48746464105556896436068404624494584211542841793491350914872470595379166623788825 -2.5483
3 19.85369199680558219213091089271584959607746673197538889290500270758485925164498330 -1.8206e-01
4 20.02868839529070085277380544398576616470733632504815180772578876685215146483792186 -7.0615e-03
5 20.03557771838556215392853572527509393150162720744712830816732425295141661302212542 -1.7214e-04
6 20.03574697509234388306545755854992537415299478921975125717616705900225010375271175 -2.8797e-06
7 20.03574981972660077557187293728919033694006575323784891307591676343623185267840087 -3.5093e-08
8 20.03574985449451728822609180416831326162367525799440551006933045513903380452620872 -3.2529e-10
9 20.03574985481743383688644194548587048392631680869557979312925905853201983429400861 -2.3700e-12
10 20.03574985481978987111757669085434582340083496254465680809367957309381342059009668 -1.3927e-14
11 20.03574985481980373055291471596970312419935163064851758082919292076105448665845694 -6.7396e-17
12 20.03574985481980379767595310144540177423271389844296074380175787717157675883917151 -2.7323e-19
13 20.03574985481980379794824581190926907018626592287853070355830814733619000088357912 -9.4143e-22
14 20.03574985481980379794918444835993759451301483567068863329194414460270391327442654 -2.7906e-24
15 20.03574985481980379794918723174019172484527341186430917498972813563388327387142320 -7.1915e-27
16 20.03574985481980379794918723891539587893161294648949828480207158337867091213105210 -1.6260e-29
17 20.03574985481980379794918723893162360381792525574404539062822509053852218733547782 -3.2517e-32
18 20.03574985481980379794918723893165606243605713014841119742440194777360958854209572 -5.7920e-35
19 20.03574985481980379794918723893165612026372831720742415561589728335786348943623570 -9.2480e-38
20 20.03574985481980379794918723893165612035607513408575037519944422231638669124167990 -1.3311e-40
21 20.03574985481980379794918723893165612035620807276164638611436475769849940475037458 -1.7360e-43
22 20.03574985481980379794918723893165612035620824615962445370778636022384338924992003 -2.0610e-46
23 20.03574985481980379794918723893165612035620824636550325344849506916698800464997617 -2.2368e-49
24 20.03574985481980379794918723893165612035620824636572670605090159763145237587025264 -2.2276e-52
25 20.03574985481980379794918723893165612035620824636572692860700178828249236875179273 -2.0430e-55
26 20.03574985481980379794918723893165612035620824636572692881113337954261894220969394 -1.7312e-58
27 20.03574985481980379794918723893165612035620824636572692881130636614548220525870297 -1.3595e-61
28 20.03574985481980379794918723893165612035620824636572692881130650199357864896908624 -9.9207e-65
29 20.03574985481980379794918723893165612035620824636572692881130650209271775421848621 -6.7456e-68
30 20.03574985481980379794918723893165612035620824636572692881130650209278516823348154 -4.2128e-71
31 20.03574985481980379794918723893165612035620824636572692881130650209278518859457416 -2.1767e-71
32 20.03574985481980379794918723893165612035620824636572692881130650209278521040018937 3.8415e-74
────── ───────────────────────────────────────────────────────────────────────────────────── ─────────────
20.03574985481980379794918723893165612035620824636572692881130650209278521036177419 {exact value}
 
Using 82 digit precision, the N-point Gauss─Legendre quadrature (GLQ) had an accuracy of 74 digits.
</pre>
 
===version 3, more precision===
This REXX version is almost an exact copy of REXX version 2, &nbsp; but with about twice as the number of decimal digits of &nbsp; '''pi''' &nbsp; and &nbsp; '''e'''.
 
It is about twice as slow as version 2, &nbsp; due to the doubling of the number of decimal digits &nbsp; (precision).
<syntaxhighlight lang="rexx">/*REXX program does numerical integration using an N─point Gauss─Legendre quadrature rule. */
pi= pi(); digs= length(pi) - length(.); numeric digits digs; reps= digs % 2
!.= .; b= 3; a= -b; bma= b - a; bmaH= bma / 2; tiny= '1e-'digs
trueV= exp(b)-exp(a); bpa= b + a; bpaH= bpa / 2
hdr= 'iterate value (with ' digs " decimal digits being used)"
say ' step ' center(hdr, digs+3) ' difference' /*show hdr*/
sep='──────' copies("─", digs+3) '─────────────'; say sep /* " sep*/
 
do #=1 until dif>0; p0z= 1; p0.1= 1; p1z= 2; p1.1= 1; p1.2= 0; ##= # + .5; r.= 0
/*█*/ do k=2 to #; km= k - 1
/*█*/ do y=1 for p1z; T.y= p1.y; end /*y*/
/*█*/ T.y= 0; TT.= 0; do L=1 for p0z; _= L + 2; TT._= p0.L; end /*L*/
/*█*/ kkm= k + km; do j=1 for p1z +1; T.j= (kkm*T.j - km*TT.j)/k; end /*j*/
/*█*/ p0z= p1z; do n=1 for p0z; p0.n= p1.n ; end /*n*/
/*█*/ p1z= p1z + 1; do p=1 for p1z; p1.p= T.p ; end /*p*/
/*█*/ end /*k*/
/*▓*/ do !=1 for #; x= cos( pi * (! - .25) / ## )
/*▓*/ /*░*/ do reps until abs(dx) <= tiny
/*▓*/ /*░*/ f= p1.1; df= 0; do u=2 to p1z; df= f + x*df
/*▓*/ /*░*/ f= p1.u +x*f
/*▓*/ /*░*/ end /*u*/
/*▓*/ /*░*/ dx= f / df; x= x - dx
/*▓*/ /*░*/ end /*reps ···*/
/*▓*/ r.1.!= x
/*▓*/ r.2.!= 2 / ( (1 - x*x) * df*df)
/*▓*/ end /*!*/
$= 0
/*▒*/ do m=1 for #; $=$ + r.2.m * exp(bpaH + r.1.m*bmaH); end /*m*/
z= bmaH * $ /*calculate target value (Z)*/
dif= z - trueV; z= format(z, 3, digs - 2) /* " difference. */
Ndif= translate( format(dif, 3, 4, 3, 0), 'e', "E")
if #\==1 then say center(#, 6) z' ' Ndif /*no display if not computed*/
end /*#*/
 
say sep; xdif= compare( strip(z), trueV); say right("↑", 6 + 1 + xdif)
say left('', 6 + 1) trueV " {exact value}"; say
say 'Using ' digs " digit precision, the" ,
'N-point Gauss─Legendre quadrature (GLQ) had an accuracy of ' xdif-2 " digits."
exit 0 /*stick a fork in it, we're all done. */
/*───────────────────────────────────────────────────────────────────────────────────────────*/
e: return 2.71828182845904523536028747135266249775724709369995957496696762772407663035354759,
||457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794
/*───────────────────────────────────────────────────────────────────────────────────────────*/
pi: return 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899,
||862803482534211706798214808651328230664709384460955058223172535940812848111745028410270194
/*───────────────────────────────────────────────────────────────────────────────────────────*/
cos: procedure expose !.; parse arg x; if !.x\==. then return !.x; _= 1; z=1; y= x*x
do k=2 by 2 until p==z; p=z; _= -_*y/(k*(k-1)); z=z+_; end; !.x=z; return z
/*───────────────────────────────────────────────────────────────────────────────────────────*/
exp: procedure; parse arg x; ix= x % 1; if abs(x-ix)>.5 then ix= ix + sign(x); x= x-ix; z= 1
_=1; do j=1 until p==z; p=z; _= _*x/j; z= z+_; end; return z * e()**ix</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
 
(Shown at about two-thirds size.)
<pre style="font-size:67%">
step iterate value (with 171 decimal digits being used) difference
────── ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ─────────────
2 17.4874646410555689643606840462449458421154284179349135091487247059537916662378882444064336021640614626063744948781912964250403870127054497392082425535068464109311173377377 -2.5483
3 19.8536919968055821921309108927158495960774667319753888929050027075848592516449832906645902758379575999249091274157148988582792112906526877518087112700785494497813902725450 -1.8206e-001
4 20.0286883952907008527738054439857661647073363250481518077257887668521514648379218096268747927750038360903142778646220077613647092768733641727539206268833693587721944236294 -7.0615e-003
5 20.0355777183855621539285357252750939315016272074471283081673242529514166130221254213250349496939691709537643294259047823350162410908440808868981982394287542087129417151006 -1.7214e-004
6 20.0357469750923438830654575585499253741529947892197512571761670590022501037527117346339483928363770582109285164930728028479549289382406446621705905363209981936742762651248 -2.8797e-006
7 20.0357498197266007755718729372891903369400657532378489130759167634362318526784010016150667027038415189719144094529764766032097831604495667799067330556673881537789420232152 -3.5093e-008
8 20.0357498544945172882260918041683132616236752579944055100693304551390338045262089091194019302017562870527315644307417688383478919210145963055448428522264642589709805903057 -3.2529e-010
9 20.0357498548174338368864419454858704839263168086955797931292590585320198342940085570553927472311015418220675609961921140415760514983040167737226050690228927266115828876520 -2.3700e-012
10 20.0357498548197898711175766908543458234008349625446568080936795730938134205900980645938318794902592556558231569959762420203929344018773329199723457149763574278017459859529 -1.3927e-014
11 20.0357498548198037305529147159697031241993516306485175808291929207610544866584568009626862857221858328844106864371425322111609007302709732793823163103980149601875492907998 -6.7396e-017
12 20.0357498548198037976759531014454017742327138984429607438017578771715767588391691509175808718708593063121709896967107496243434245185896147055314894150234262032514577087792 -2.7323e-019
13 20.0357498548198037979482458119092690701862659228785307035583081473361900008835808932495328864420024278695427964698380448330606714160259282675390182203803538192726572599929 -9.4143e-022
14 20.0357498548198037979491844483599375945130148356706886332919441446027039132743905494286471338717783707421873433644754993992655580745072286831502363474798170771121237677390 -2.7906e-024
15 20.0357498548198037979491872317401917248452734118643091749897281356338832738714150881537113815780435230011480697467170623887897830301712412973655748924184136940242004265158 -7.1915e-027
16 20.0357498548198037979491872389153958789316129464894982848020715833786709121310547889685984881568546203564135185474792767674806869872650180714616455691318785641503320488704 -1.6260e-029
17 20.0357498548198037979491872389316236038179252557440453906282250905385221873347716826354198555233437240574026019817833907372014036252533047705435353247648512336234642790641 -3.2517e-032
18 20.0357498548198037979491872389316560624360571301484111974244019477736095885421361807599231231543821951618639462965984321643251022835234451110049047608124964855646728491571 -5.7920e-035
19 20.0357498548198037979491872389316561202637283172074241556158972833578634894365092635000776399956033063018069653085902399896542171129596405210008317497301938111107401607602 -9.2480e-038
20 20.0357498548198037979491872389316561203560751340857503751994442223163866912408434007886096643419528065940077022083150476496426837665378721283432879108630829513249759484353 -1.3311e-040
21 20.0357498548198037979491872389316561203562080727616463861143647576984994047530870779393715057751591887673397688454357985082021265151278191050057935329724914648356586984041 -1.7360e-043
22 20.0357498548198037979491872389316561203562082461596244537077863602238433892612703628843743785373313737563806457244053157873973239947461987202443878362980281616080907191625 -2.0610e-046
23 20.0357498548198037979491872389316561203562082463655032534484950691669880046406047078766996078695370527223056578914332723730363863326194707715142045831095238426102807682133 -2.2368e-049
24 20.0357498548198037979491872389316561203562082463657267060509015976314523758814742624773428457390528961843568960502876896215809857825164102337905868347722728364661655423691 -2.2276e-052
25 20.0357498548198037979491872389316561203562082463657269286070017882824923688080311511389836619043005851350331110867389220628954338053656628671036072512304656757933297348289 -2.0430e-055
26 20.0357498548198037979491872389316561203562082463657269288111333795426189423729667519158562143832977811003145168351321839626313132075697513253761673496847193697358302206599 -1.7312e-058
27 20.0357498548198037979491872389316561203562082463657269288113063661454822050198926197665008333893008724687497228278730367375441075263700413282548634210893951621431572014401 -1.3595e-061
28 20.0357498548198037979491872389316561203562082463657269288113065019935786483820352375621786828318969009163053743757325024448325026804644277866300802833735429200407643132066 -9.9207e-065
29 20.0357498548198037979491872389316561203562082463657269288113065020927177593233999249852447888627901300469719564790181325442944469692690797774430312247184030485560959159838 -6.7451e-068
30 20.0357498548198037979491872389316561203562082463657269288113065020927851675301934062025341716601075750412806887227020916063849030412480955063639628314158527843447097540104 -4.2832e-071
31 20.0357498548198037979491872389316561203562082463657269288113065020927852103363148863217394106431702791915956948972366384835732103508918001327415359845732098066185095970907 -2.5459e-074
32 20.0357498548198037979491872389316561203562082463657269288113065020927852103617599854934274435013875248206413049448382025586066461615726348079942124358556139880490254984356 -1.4196e-077
33 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741736109635347323907131494641377410353985987829217992622815976248321175867964752131506800051 -7.4395e-081
34 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810467715704772209566910717933633388969835872983190631663850670877761750073036465167190394 -3.6713e-084
35 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504412069378446854036859408497315019337333762510854198446941961781825098514532469683329 -1.7091e-087
36 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429152646383719980280460795167918691617029439367737607466797188696985999193933984760 -7.5175e-091
37 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160160714391043273984198489693834991216803247954607301723484371150995472545047773 -3.1292e-094
38 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163842341789925349746540298990681930753381942866562579916746319742876113289347 -1.2345e-097
39 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843575809851614709658383098559963930599249691243551258257666303808499450058 -4.6221e-101
40 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576271898405984614568086424291240202255560215708382127745410021921505433 -1.6447e-104
41 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062816325200556739918251890227721352129417700490117766374046259608 -5.5685e-108
42 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062871992591098295378332977741979460337046289653292852558991470138 -1.7962e-111
43 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010547683152388008632372342584044010171728180146818963258851 -5.5262e-115
44 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553207686109280576604524821212783897594720674601807871384 -1.6234e-118
45 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309007883789778553235095566868388697120439100484887 -4.5581e-122
46 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463568475856093621234235103013989004662708710524 -1.2245e-125
47 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690894669420459180906124959094321731281026582 -3.1504e-129
48 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926165554457660180369582395139692931382774 -7.7695e-133
49 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926173322092766618204788515060681700867922 -1.8383e-136
50 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926173323930673674948485214173181944866992 -4.1766e-140
51 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926173323931091242430000931491744551038314 -9.1189e-144
52 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926173323931091333599358956493201909187002 -1.9148e-147
53 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926173323931091333618502674999936415396203 -3.9287e-151
54 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926173323931091333618506574837300809273433 -2.8877e-153
55 20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926173323931091333618507014523492331476840 4.1081e-152
────── ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ─────────────
20.0357498548198037979491872389316561203562082463657269288113065020927852103617741810504429160163843576272062872010553209309463690926173323931091333618506603713959668429768 {exact value}
 
Using 171 digit precision, the N-point Gauss─Legendre quadrature (GLQ) had an accuracy of 152 digits.
</pre>
 
=={{header|Scala}}==
{{Out}}Best seen in running your browser either by [https://scalafiddle.io/sf/rrvzhH1/0 ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/yYqRqizfSZip2DhYbdfZ2w Scastie (remote JVM)].
<syntaxhighlight lang="scala">import scala.math.{Pi, cos, exp}
 
object GaussLegendreQuadrature extends App {
private val N = 5
 
private def legeInte(a: Double, b: Double): Double = {
val (c1, c2) = ((b - a) / 2, (b + a) / 2)
val tuples: IndexedSeq[(Double, Double)] = {
val lcoef = {
val lcoef = Array.ofDim[Double](N + 1, N + 1)
 
lcoef(0)(0) = 1
lcoef(1)(1) = 1
for (i <- 2 to N) {
lcoef(i)(0) = -(i - 1) * lcoef(i - 2)(0) / i
for (j <- 1 to i) lcoef(i)(j) =
((2 * i - 1) * lcoef(i - 1)(j - 1) - (i - 1) * lcoef(i - 2)(j)) / i
}
lcoef
}
 
def legeEval(n: Int, x: Double): Double =
lcoef(n).take(n).foldRight(lcoef(n)(n))((o, s) => s * x + o)
 
def legeDiff(n: Int, x: Double): Double =
n * (x * legeEval(n, x) - legeEval(n - 1, x)) / (x * x - 1)
 
@scala.annotation.tailrec
def convergention(x0: Double, x1: Double): Double = {
if (x0 == x1) x1
else convergention(x1, x1 - legeEval(N, x1) / legeDiff(N, x1))
}
 
for {i <- 0 until 5
x = convergention(0.0, cos(Pi * (i + 1 - 0.25) / (N + 0.5)))
x1 = legeDiff(N, x)
} yield (x, 2 / ((1 - x * x) * x1 * x1))
}
 
println(s"Roots: ${tuples.map(el => f" ${el._1}%10.6f").mkString}")
println(s"Weight:${tuples.map(el => f" ${el._2}%10.6f").mkString}")
 
c1 * tuples.map { case (lroot, weight) => weight * exp(c1 * lroot + c2) }.sum
}
 
println(f"Integrating exp(x) over [-3, 3]:\n\t${legeInte(-3, 3)}%10.8f,")
println(f"compared to actual%n\t${exp(3) - exp(-3)}%10.8f")
 
}</syntaxhighlight>
 
=={{header|Sidef}}==
{{trans|Raku}}
<syntaxhighlight lang="ruby">func legendre_pair((1), x) { (x, 1) }
func legendre_pair( n, x) {
var (m1, m2) = legendre_pair(n - 1, x)
var u = (1 - 1/n)
((1 + u)*x*m1 - u*m2, m1)
}
 
func legendre((0), _) { 1 }
func legendre( n, x) { [legendre_pair(n, x)][0] }
 
func legendre_prime({ .is_zero }, _) { 0 }
func legendre_prime({ .is_one }, _) { 1 }
 
func legendre_prime(n, x) {
var (m0, m1) = legendre_pair(n, x)
(m1 - x*m0) * n / (1 - x**2)
}
 
func approximate_legendre_root(n, k) {
# Approximation due to Francesco Tricomi
var t = ((4*k - 1) / (4*n + 2))
(1 - ((n - 1)/(8 * n**3))) * cos(Num.pi * t)
}
 
func newton_raphson(f, f_prime, r, eps = 2e-16) {
loop {
var dr = (-f(r) / f_prime(r))
dr.abs >= eps || break
r += dr
}
return r
}
 
func legendre_root(n, k) {
newton_raphson(legendre.method(:call, n), legendre_prime.method(:call, n),
approximate_legendre_root(n, k))
}
 
func weight(n, r) { 2 / ((1 - r**2) * legendre_prime(n, r)**2) }
 
func nodes(n) {
gather {
take(Pair(0, weight(n, 0))) if n.is_odd
{ |i|
var r = legendre_root(n, i)
var w = weight(n, r)
take(Pair(r, w), Pair(-r, w))
}.each(1 .. (n >> 1))
}
}
 
func quadrature(n, f, a, b, nds = nodes(n)) {
func scale(x) { (x*(b - a) + a + b) / 2 }
(b - a) / 2 * nds.sum { .second * f(scale(.first)) }
}
 
[(5..10)..., 20].each { |i|
printf("Gauss-Legendre %2d-point quadrature ∫₋₃⁺³ exp(x) dx ≈ %.15f\n",
i, quadrature(i, {.exp}, -3, +3))
}</syntaxhighlight>
{{out}}
<pre>Gauss-Legendre 5-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.035577718385561
Gauss-Legendre 6-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.035746975092344
Gauss-Legendre 7-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.035749819726600
Gauss-Legendre 8-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.035749854494515
Gauss-Legendre 9-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.035749854817432
Gauss-Legendre 10-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.035749854819791
Gauss-Legendre 20-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.035749854819805</pre>
 
=={{header|Tcl}}==
Line 1,329 ⟶ 3,247:
{{tcllib|math::polynomials}}
{{tcllib|math::special}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
package require math::special
package require math::polynomials
Line 1,391 ⟶ 3,309:
}
expr {$sum * $rangesize2}
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl">puts "nodes(5) = [nodes 5]"
puts "weights(5) = [weights [nodes 5]]"
set exp {x {expr {exp($x)}}}
puts "int(exp,-3,3) = [gausslegendreintegrate $exp 5 -3 3]"</langsyntaxhighlight>
{{out}}
<pre>
Line 1,406 ⟶ 3,324:
=={{header|Ursala}}==
using arbitrary precision arithmetic
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
 
Line 1,439 ⟶ 3,357:
mp..shrink^/~& difference\"p"+ mp..prec,
mp..mul^|/~& mp..add:-0E0+ * mp..mul^/~&rr ^H/~&ll mp..add^\~&lrr mp..mul@lrPrXl,
^(~&rl,-*nodes("p","n"))^|/~& mp..vid~~G/2E0+ ^/mp..bus mp..add+-</langsyntaxhighlight>
demonstration program:<langsyntaxhighlight Ursalalang="ursala">#show+
 
demo =
Line 1,446 ⟶ 3,364:
~&lNrCT (
^|lNrCT(:/'nodes:',:/'weights:')@lSrSX ..mp2str~~* nodes/160 5,
:/'integral:' ~&iNC ..mp2str integral(160,5) (mp..exp,-3E0,3E0))</langsyntaxhighlight>
{{out}}
<pre>
Line 1,465 ⟶ 3,383:
integral:
2.0035577718385562153928535725275093931501627207110E+01</pre>
 
=={{header|Wren}}==
{{trans|C}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
 
var N = 5
 
var lroots = List.filled(N, 0)
var weight = List.filled(N, 0)
 
var lcoef = List.filled(N+1, null)
for (i in 0..N) lcoef[i] = List.filled(N + 1, 0)
 
var legeCoef = Fn.new {
lcoef[0][0] = lcoef[1][1] = 1
for (n in 2..N) {
lcoef[n][0] = -(n-1) * lcoef[n -2][0] / n
for (i in 1..n) {
lcoef[n][i] = ((2*n - 1) * lcoef[n-1][i-1] - (n - 1) * lcoef[n-2][i]) / n
}
}
}
 
var legeEval = Fn.new { |n, x| (n..1).reduce(lcoef[n][n]) { |s, i| s*x + lcoef[n][i-1] } }
 
var legeDiff = Fn.new { |n, x|
return n * (x * legeEval.call(n, x) - legeEval.call(n-1, x)) / (x*x - 1)
}
 
var legeRoots = Fn.new {
var x = 0
var x1 = 0
for (i in 1..N) {
x = (Num.pi * (i - 0.25) / (N + 0.5)).cos
while (true) {
x1 = x
x = x - legeEval.call(N, x) / legeDiff.call(N, x)
if (x == x1) break
}
lroots[i-1] = x
x1 = legeDiff.call(N, x)
weight[i-1] = 2 / ((1 - x*x) * x1 * x1)
}
}
 
var legeIntegrate = Fn.new { |f, a, b|
var c1 = (b - a) / 2
var c2 = (b + a) / 2
var sum = 0
for (i in 0...N) sum = sum + weight[i] * f.call(c1*lroots[i] + c2)
return c1 * sum
}
 
legeCoef.call()
legeRoots.call()
System.write("Roots: ")
for (i in 0...N) Fmt.write(" $f", lroots[i])
System.write("\nWeight:")
for (i in 0...N) Fmt.write(" $f", weight[i])
 
var f = Fn.new { |x| x.exp }
var actual = 3.exp - (-3).exp
Fmt.print("\nIntegrating exp(x) over [-3, 3]:\n\t$10.8f,\n" +
"compared to actual\n\t$10.8f", legeIntegrate.call(f, -3, 3), actual)</syntaxhighlight>
 
{{out}}
<pre>
Roots: 0.906180 0.538469 0.000000 -0.538469 -0.906180
Weight: 0.236927 0.478629 0.568889 0.478629 0.236927
Integrating exp(x) over [-3, 3]:
20.03557772,
compared to actual
20.03574985
</pre>
 
=={{header|zkl}}==
{{trans|Raku}}
<syntaxhighlight lang="zkl">fcn legendrePair(n,x){ //-->(float,float)
if(n==1) return(x,1.0);
m1,m2:=legendrePair(n-1,x);
u:=1.0 - 1.0/n;
return( (u + 1)*x*m1 - u*m2, m1);
}
fcn legendre(n,x){ //-->float
if(n==0) return(0.0);
legendrePair(n,x)[0]
}
fcn legendrePrime(n,x){ //-->float
if(n==0) return(0.0);
if(n==1) return(1.0);
m0,m1:=legendrePair(n,x);
(m1 - m0*x)*n/(1.0 - x*x);
}
fcn approximateLegendreRoot(n,k){ # Approximation due to Francesco Tricomi
t:=(4.0*k - 1)/(4.0*n + 2);
(1.0 - (n - 1)/(8*n*n*n))*((0.0).pi*t).cos();
}
fcn newtonRaphson(f,fPrime,r,eps=2.0e-16){
while(not (dr:=-f(r)/fPrime(r)).closeTo(0.0,eps)){ r+=dr }
r;
}
fcn legendreRoot(n,k){
newtonRaphson(legendre.fp(n),legendrePrime.fp(n),
approximateLegendreRoot(n,k));
}
fcn weight(n,r){
lp:=legendrePrime(n,r);
2.0/((1.0 - r*r)*lp*lp)
}
fcn nodes(n){ //-->( (r,weight), (r,w), ...) length n
sink:=n.isOdd and L(T(0.0,weight(n,0))) or List;
(1).pump(n/2,sink,'wrap(m){
r:=legendreRoot(n,m);
w:=weight(n,r);
return( Void.Write,T(r,w),T(-r,w) )
})
}
fcn quadrature(n,f,a,b,nds=Void){
if(not nds) nds=nodes(n);
scale:='wrap(x){ (x*(b - a) + a + b) / 2 };
nds.reduce('wrap(p,[(r,w)]){ p + w*f(scale(r)) },0.0) * (b - a)/2
}</syntaxhighlight>
<syntaxhighlight lang="zkl">[5..10].walk().append(20).pump(Console.println,fcn(n){
("Gauss-Legendre %2d-point quadrature "
"\U222B;\U208B;\U2083;\U207A;\UB3; exp(x) dx = %.13f")
.fmt(n,quadrature(n, fcn(x){ x.exp() }, -3, 3))
})</syntaxhighlight>
{{out}}
<pre>
Gauss-Legendre 5-point quadrature ∫₋₃⁺³ exp(x) dx = 20.0355777183856
Gauss-Legendre 6-point quadrature ∫₋₃⁺³ exp(x) dx = 20.0357469750924
Gauss-Legendre 7-point quadrature ∫₋₃⁺³ exp(x) dx = 20.0357498197266
Gauss-Legendre 8-point quadrature ∫₋₃⁺³ exp(x) dx = 20.0357498544945
Gauss-Legendre 9-point quadrature ∫₋₃⁺³ exp(x) dx = 20.0357498548174
Gauss-Legendre 10-point quadrature ∫₋₃⁺³ exp(x) dx = 20.0357498548198
Gauss-Legendre 20-point quadrature ∫₋₃⁺³ exp(x) dx = 20.0357498548198
</pre>
 
 
{{omit from|GUISS}}
2,122

edits