@@ -39,34 +39,39 @@ std::string int2string(UInt i) {
39
39
return oss .str ();
40
40
}
41
41
42
- // Straight from numerical recipes in C
43
- void gauss_legendre (UInt n , double locs [], double * wgts ) {
44
- UInt m ;
45
- double z , z1 , pp , p1 , p2 , p3 ;
42
+ void gauss_legendre (UInt num_points , double locs [], double * wgts ) {
43
+ UInt half_points ;
44
+ double root_approx , root_approx_prev ;
45
+ double p1 , p2 , p3 ;
46
+ double p1_deriv ;
46
47
47
- m = (n + 1 )/2 ;
48
- for (UInt i = 1 ; i <= m ; i ++ ) {
49
- z = cos (M_PI * (i - 0.25 )/(n + 0.5 ));
48
+ half_points = (num_points + 1 )/2 ;
49
+ for (UInt i = 1 ; i <= half_points ; i ++ ) {
50
+ root_approx = cos (M_PI * (i - 0.25 )/(num_points + 0.5 ));
51
+
52
+ // Refine the root approximation by Newton's method
50
53
do {
51
54
52
55
p1 = 1.0 ; p2 = 0.0 ;
53
- for (UInt j = 1 ; j <= n ; j ++ ) {
56
+ for (UInt j = 1 ; j <= num_points ; j ++ ) {
54
57
p3 = p2 ;
55
58
p2 = p1 ;
56
- p1 = ((2.0 * j - 1.0 )* z * p2 - (j - 1 )* p3 )/j ;
59
+ p1 = ((2.0 * j - 1.0 )* root_approx * p2 - (j - 1 )* p3 )/j ;
57
60
}
61
+ // p1 is now the desired Legendre polynomial evaluated at root_approx
58
62
59
- pp = n * ( z * p1 - p2 )/(z * z - 1.0 );
60
- z1 = z ;
61
- z = z1 - p1 /pp ;
62
- //std::cout << "z-z1 =" << z-z1 << std::endl;
63
- } while (std ::abs (z - z1 )> 1e-10 );
63
+ p1_deriv = num_points * ( root_approx * p1 - p2 )/(root_approx * root_approx - 1.0 );
64
+ root_approx_prev = root_approx ;
65
+ root_approx = root_approx_prev - p1 /p1_deriv ;
66
+ //std::cout << "root_approx-root_approx_prev =" << root_approx-root_approx_prev << std::endl;
67
+ } while (std ::abs (root_approx - root_approx_prev )> 1e-10 );
64
68
65
- locs [i - 1 ] = - z ;
66
- locs [n + 1 - i - 1 ] = z ;
69
+ // The roots are symmetric, so each computed root is put in two locations
70
+ locs [i - 1 ] = - root_approx ;
71
+ locs [num_points + 1 - i - 1 ] = root_approx ;
67
72
if (wgts ) {
68
- wgts [i - 1 ] = 2.0 /((1.0 - z * z ) * pp * pp );
69
- wgts [n + 1 - i - 1 ] = wgts [i - 1 ];
73
+ wgts [i - 1 ] = 2.0 /((1.0 - root_approx * root_approx ) * p1_deriv * p1_deriv );
74
+ wgts [num_points + 1 - i - 1 ] = wgts [i - 1 ];
70
75
}
71
76
} // for i
72
77
}
0 commit comments