Article View: sci.math.num-analysis
Article #45Gauss-Legendre Integration
From: Uwe Hollerbach
Date: Fri, 30 Oct 1992 17:03
Date: Fri, 30 Oct 1992 17:03
111 lines
3707 bytes
3707 bytes
// Since there have been a few requests for Gauss-Legendre
// nodes & weights, I thought I'd post this here. I am not
// including the routine "myclib_error"; all it does is
// print the error message to cerr and to cout, then stop.
// I have compared the output of this routine to the tables
// in Abramowitz & Stegun, and they seem to be ok for all
// the orders listed. This code is not copyright-protected,
// so you can hack it to your heart's content.
// (You will anyway, I know :-) ) Enjoy!
#include <math.h>
// This routine calculates the value of the Nth-order Legendre
// polynomial and its first and second derivatives at the point X.
// The Legendre polynomials satisfy the recursion relation
// P_n+1 = A*X*P_n - B*P_n-1 (polynomial)
// P_n+1' = A*(X*P_n' + P_n) - B*P_n-1' (first derivative)
// P_n+1'' = A*(X*P_n'' + 2*P_n') - B*P_n-1'' (second derivative)
// where A and B are
// A = (2*n + 1)/(n+1)
// B = n/(n+1)
// On output, PNP contains the value of the polynomial, PND contains
// the value of the first derivative, and PNA contains the value of
// the second derivative.
void plegpda(int n, double x, double& pnp, double& pnd, double& pna)
{
int k;
double a, b, pm, dm, am, pc, dc, ac, pp, dp, ap;
if (n < 0) {
myclib_error("bad input to plegpda");
} else if (n == 0) {
pnp = 1.0;
pnd = 0.0;
pna = 0.0;
} else if (n == 1) {
pnp = x;
pnd = 1.0;
pna = 0.0;
} else {
pm = 1.0;
dm = 0.0;
am = 0.0;
pc = x;
dc = 1.0;
ac = 0.0;
for (k = 1; k < n; ++k) {
a = ((double) (2*k + 1))/((double) (k + 1));
b = ((double) k)/((double) (k + 1));
pp = a*x*pc - b*pm;
dp = a*(x*dc + pc) - b*dm;
ap = a*(x*ac + 2*dc) - b*am;
pm = pc;
pc = pp;
dm = dc;
dc = dp;
am = ac;
ac = ap;
}
pnp = pc;
pnd = dc;
pna = ac;
}
}
// This routine generates the Gauss-Legendre points, defined by
//
// P_{N+1}(z_i) = 0 i = 0, ... , N
//
// and the weights for Gauss-Legendre integration, given by
//
// 2
// W_i = -----------------------------
// (1 - z_i^2)*(P'_{N+1}(z_i))^2
static const double PI = 3.14159265358979323846264338327950288;
void glzw(int n, double *z, double *w, double eps)
{
int i, np;
double pin, zz, pp, pd, pa;
if (n >= 0) {
np = n + 1;
pin = PI/((double) np);
for (i = 0; i <= np/2; ++i) {
zz = cos(pin*(0.5 + ((double) i)));
pa = 1.0;
while (abs(pa) > eps) {
plegpda(np, zz, pp, pd, pa);
pa = -pp/pd;
zz += pa;
}
z[i] = -zz;
z[n-i] = zz;
}
for (i = 0; i <= np/2; ++i) {
plegpda(np, z[i], pp, pd, pa);
w[i] = 2.0/((1.0 - z[i]*z[i])*pd*pd);
w[n-i] = w[i];
}
} else {
myclib_error("negative N in glzw");
}
}
--
Uwe Hollerbach uh@acm.princeton.edu or uh@alumni.caltech.edu
"In His infinite mercy, Allah does not subtract from one's alloted span those
hours which are spent in contemplation of net.news. All praise be to Allah."
-- an obscure commentator on the early work of Al-Khowariszmi
Technical Details
Message-ID:
<1992Oct30.170352.6137@Princeton.EDU>Path:
arc1-ca.pugleaf.net!sparky!uunet!pmafire!news.dell.com!swrinde!zaphod.mps.ohio-state.edu!darwin.sura.net!jvnc.net!princeton!phoenix.Princeton.EDU!holerbchShow Full Headers
Complete Article Headers
Newsgroups: sci.math.num-analysis Path: arc1-ca.pugleaf.net!sparky!uunet!pmafire!news.dell.com!swrinde!zaphod.mps.ohio-state.edu!darwin.sura.net!jvnc.net!princeton!phoenix.Princeton.EDU!holerbch From: holerbch@phoenix.Princeton.EDU (Uwe Hollerbach) Subject: Gauss-Legendre Integration Message-ID: <1992Oct30.170352.6137@Princeton.EDU> Summary: Here is a routine for nodes & weights; enjoy Originator: news@nimaster Sender: news@Princeton.EDU (USENET News System) Nntp-Posting-Host: phoenix.princeton.edu Organization: Princeton University Date: Fri, 30 Oct 1992 17:03:52 GMT Lines: 111