Numerical integration/Gauss-Legendre Quadrature: Difference between revisions
Content added Content deleted
m (→version 3, more precision: got proactive concerning the last decimal digit of pi being shown.) |
|||
Line 1,457: | Line 1,457: | ||
Gauss-Legendre 10-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548198 |
Gauss-Legendre 10-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548198 |
||
Gauss-Legendre 20-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548198</pre> |
Gauss-Legendre 20-point quadrature ∫₋₃⁺³ exp(x) dx ≈ 20.0357498548198</pre> |
||
=={{header|Phix}}== |
|||
{{trans|Lua}} |
|||
<lang Phix>integer order = 0 |
|||
sequence legendreRoots = {}, |
|||
legendreWeights = {} |
|||
function legendre(integer term, atom z) |
|||
if term=0 then |
|||
return 1 |
|||
elsif term=1 then |
|||
return z |
|||
else |
|||
return ((2*term-1)*z*legendre(term-1,z)-(term-1)*legendre(term-2,z))/term |
|||
end if |
|||
end function |
|||
function legendreDerivative(integer term, atom z) |
|||
if term=0 |
|||
or term=1 then |
|||
return term |
|||
end if |
|||
return (term*(z*legendre(term,z)-legendre(term-1,z)))/(z*z-1) |
|||
end function |
|||
procedure getLegendreRoots() |
|||
legendreRoots = {} |
|||
for index=1 to order do |
|||
atom y = cos(PI*(index-0.25)/(order+0.5)) |
|||
while 1 do |
|||
atom y1 = y |
|||
y -= legendre(order,y)/legendreDerivative(order,y) |
|||
if abs(y-y1)<2e-16 then exit end if |
|||
end while |
|||
legendreRoots &= y |
|||
end for |
|||
end procedure |
|||
procedure getLegendreWeights() |
|||
legendreWeights = {} |
|||
for index=1 to order do |
|||
atom lri = legendreRoots[index], |
|||
diff = legendreDerivative(order,lri), |
|||
weight = 2 / ((1-power(lri,2))*power(diff,2)) |
|||
legendreWeights &= weight |
|||
end for |
|||
end procedure |
|||
function gaussLegendreQuadrature(integer f, lowerLimit, upperLimit, n) |
|||
order = n |
|||
getLegendreRoots() |
|||
getLegendreWeights() |
|||
atom c1 = (upperLimit - lowerLimit) / 2 |
|||
atom c2 = (upperLimit + lowerLimit) / 2 |
|||
atom s = 0 |
|||
for i = 1 to order do |
|||
s += legendreWeights[i] * call_func(f,{c1 * legendreRoots[i] + c2}) |
|||
end for |
|||
return c1 * s |
|||
end function |
|||
include pmaths.e -- exp() |
|||
constant r_exp = routine_id("exp") |
|||
string fmt = iff(machine_bits()=32?"%.13f":"%.14f") |
|||
string res |
|||
for i=5 to 11 by 6 do |
|||
res = sprintf(fmt,{gaussLegendreQuadrature(r_exp, -3, 3, i)}) |
|||
if i=5 then |
|||
puts(1,"roots:") ?legendreRoots |
|||
puts(1,"weights:") ?legendreWeights |
|||
end if |
|||
printf(1,"Gauss-Legendre %2d-point quadrature for exp over [-3..3] = %s\n",{order,res}) |
|||
end for |
|||
res = sprintf(fmt,{exp(3)-exp(-3)}) |
|||
printf(1," compared to actual = %s\n",{res})</lang> |
|||
{{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 accuracte 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}}== |
=={{header|PL/I}}== |