Suppose that we wish to evaluate
where
where
For the case that
Gauss rules are usually computed in the following two steps.
Step 1: Compute the recursion coefficients in the three-step recurrence relation (Gautschi, 2004).
Step 2: Use these recursion coefficients to compute the Gauss quadrature nodes and weights.
In the classical case there are simple formulae for the recursion coefficients, making Step 1 trivial. In the non-classical case Step 1 is difficult. The treatise of Gautschi (2004) describes several methods for this computation that differ widely in both complexity and sensitivity to roundoff errors. However, Step 2 remains the same for both classical and non-classical cases. We carry out Step 2 by computing the eigenvalues and eigenvectors of a symmetric tridiagonal matrix using the package GenericLinearAlgebra.jl
.
The norm of the function
provided that this integral exists. For two functions
If
We consider only polynomials whose coefficients are real numbers.
A polynomial in
and
The Gauss quadrature nodes
The monic orthogonal polynomials with respect to the weight function
where
Computation of the recursion coefficients in the three-term recurrence relation using moment determinants
We carry out Step 1 using moment determinants (Theorem 2.2 of Gautschi, 2004).
The map from the vector
We use BigFloat
arithmetic, with number of bits of precision b
. For assurance that the chosen number of bits of precision b
is sufficiently large, we use the following simple method. Suppose that BigFloat
arithmetic with number of bits of precision b1
and b2
, respectively, where b2
is substantially larger than b1
.
The approximation
We require that there is a formula, which can be computed in BigFloat
arithmetic, for the
for all nonnegative integers moment_fn
, as illustrated in the examples below.
The function custom_gauss_quad_all_fn
is then used to compute the Gauss quadrature nodes and weights.
The aim of the method implemented in custom_gauss_quad_all_fn
is for (a) the absolute errors of each of the nodes to be less than
Float64
computations.
The inputs to custom_gauss_quad_all_fn
are
which_f
, n
, upto_n
and extra_check
. We describe this function for the default values of upto_n
and extra_check
, so that the inputs to this function are as follows.
-
which_f
specifies the weight function$f$ . It has the following components: (i) name, (ii) support specified by a two-vector of the endpoints of the interval, with finite endpoints specified by strings of numbers that are later converted to the appropriate floating-point type usingparse()
and (iii) parameter vector (if any). -
n
is the number of nodes.
For custom_gauss_quad_all_fn
the outputs are nodes
and weights
in the form of Double64
vectors (from the package DoubleFloats
).
Consider the "scaled chi pdf" weight function is
where
which_f = ["scaled chi pdf", [0,Inf], m]
for some assigned value of
For this weight function, the
for moment_fn
which has inputs T
(Floating Point type), which_f
and r
(moment order), as follows.
if r == 0
return(convert(T, 1))
end
T_2 = convert(T, 2)
m = which_f[3]
T_m = convert(T, m)
T_r = convert(T, r)
term1 = (T_r/T_2) * log(T_2 / T_m)
term2 = (logabsgamma((T_r + T_m)/T_2))[1]
term3 = (logabsgamma(T_m/T_2))[1]
moment = exp(term1 + term2 - term3)
The following commands compute the nodes and weights, as
Double64
vectors for a 5-point Gauss quadrature rule. This is followed by conversion to
Float64
vectors and printing using using the printf
function from the package Printf
.
using CustomGaussQuadrature
which_f = ["scaled chi pdf", [0,Inf], 160]::Vector{Any};
n = 5;
nodes, weights = custom_gauss_quad_all_fn(which_f, n);
nodes = convert(Vector{Float64}, nodes);
weights = convert(Vector{Float64}, nodes);
println(" nodes weights")
for i in 1:n
@printf "%2d " i
@printf "%.16e " nodes[i]
@printf "%.16e \n" weights[i]
end
The "chemistry example" weight function is
This weight function is considered by Gautschi (1983) and is specified by
which_f = ["chemistry example", [0,Inf]]::Vector{Any};
The first component is the name given to
For this weight function, the
for moment_fn
which has inputs T
(Floating Point type), which_f
and r
(moment order), as follows.
T_1 = convert(T, 1)
T_2 = convert(T, 2)
T_3 = convert(T, 3)
T_r = convert(T, r)
term1 = T_3^((T_r - T_2) / T_3)
term2 = gamma((T_r + T_1) / T_3)
moment = term1 * term2
The following commands compute the nodes and weights, as
Double64
vectors for a 15-point Gauss quadrature rule. This is followed by printing these nodes and weights in the same format as Table 2.2 of
Gautschi (1983), using the printf
function from the package Printf
.
using CustomGaussQuadrature
which_f = ["chemistry example", [0, Inf]]::Vector{Any}
n= 15;
nodes, weights = custom_gauss_quad_all_fn(which_f, n);
nodes = convert(Vector{BigFloat}, nodes);
weights = convert(Vector{BigFloat}, weights);
@printf " nodes weights"
for i in 1:n
@printf "%2d " i
@printf "%.15e " nodes[i]
@printf "%.15e \n" weights[i]
end
These results agree with Table 2.2 of Gautschi (1983).
Computation of the recursion coefficients in the three-term recurrence relation using the Stjieltjes procedure
The Stjeltjes procedure, given in subsections 2.2.2 and 2.2.3 of Gautschi (2004), applies the three-term recurrence relation (1) and (2) iteratively through the following sequence:
The inner products used in the computation of the recursion coefficients are found using a high-quality quadrature rule with
We describe the method used to compute the
to
Suppose that
where
where
A discrete approximation to the right-hand side of (3) can be found as follows.
Let
A high-quality quadrature rule then provides a discrete approximation to the integral
where
where
Consider the case that either Double64
arithmetic, from the package DoubleFloats
,
could result in some of these being NaN
's. To solve this problem, we compute the
where
All that the user needs to provide is a Julia
function to evaluate
which is used to compute the right-hand side of (4).
In the comments for his subroutine qgp
(available at cs.purdue.edu/archives/2002/wxg/codes), Gautschi states of this method that
"It takes no account of the special nature of the weight function involved and hence may result in slow convergence of the discretization procedure."
For the "scaled chi pdf" weight function considered in Example 1, the graph of the weight function has a single peak which becomes narrower as the positive integer parameter
Consider the same weight function as in Example 1.
The evaluation of the log-weight function ln_scaled_chi_pdf_fn
which has inputs T
(Floating Point type), x
and m
(positive integer parameter).
using CustomGaussQuadrature
m = 160;
lnf_fn = x -> ln_scaled_chi_pdf_fn(T, x, m);
This weight function is a probability density function. Therefore
T = BigFloat;
which_f = ["scaled chi pdf", [0,Inf], m];
μ₀, μ₁ = μ_offsetvec_fn(T, which_f, 1);
Carry out Step 1,
the computation of the recursion coefficients in the three-step recurrence
relation,
and print out the the chosen value of
n = 5;
a = convert(T,0);
b = Inf;
stjieltjes_a_vec, stjieltjes_b_vec, stjieltjes_nbits, r =
stjieltjes_a_vec_b_vec_final_fn(n, μ₀, lnf_fn, a, b);
println("r = ", r)
Carry out Step 2, the computation of the Gauss quadrature nodes and weights from the recursion coefficients, using
stjieltjes_nodes, stjieltjes_weights =
stjieltjes_custom_gauss_quad_all_fn(n, μ₀, μ₁, stjieltjes_a_vec, stjieltjes_b_vec, a, b);
Convert these nodes and weights to Float64
vectors using
stjieltjes_nodes = convert(Vector{Float64}, stjieltjes_nodes);
stjieltjes_weights = convert(Vector{Float64}, stjieltjes_weights);
Print these out in the same format as in Example 1 using
@printf " stjieltjes_nodes stjieltjes_weights"
for i in 1:lastindex(stjieltjes_nodes)
@printf "%2d " i
@printf "%.16e " stjieltjes_nodes[i]
@printf "%.16e \n" stjieltjes_weights[i]
end
Define the
The nodes
The matrix
We compute the eigenvalues and eigenvectors of a symmetric tridiagonal matrix using the package GenericLinearAlgebra
.
Gautschi, W. (1983). How and how not to check Gaussian quadrature formulae. BIT, 23, 209-216
Gautschi, W. (2004). Orthogonal Polynomials, Computation and Approximation. Oxford University Press, Oxford.