(* :Title: Gaussian quadrature *) (* :Author: Mark Fisher *) (* :Context: GaussianQuadrature` *) (* :Package Version: 1.0 (February 1999) 1.1 (April 1999) Use $MinPrecision to get precision up to WorkingPrecision 1.2 (June 1999) Apply N after computing exact solutions for abscissas and weights *) (* :Mathematica Version: 3.0 *) (* :Summary: This package provides two functions: GaussianQuadraturePairs and GaussianProductRule. GaussianQuadraturePairs produces a list of n abscissa/weight pairs {x, w} for n-point Gaussian quadrature. Four types of orthogonal polynomials are supported: HermiteH, LaguerreL, LegendreP, and ChebyshevT. (The Standard Package NumericalMath`GaussianQuadrature` computes abscissa/weight pairs only for the LegendreP case.) WorkingPrecision can be specified (including Infinity). The option ScalingParameters can be used to rescale the interval and/or weight function, depending on the type. In order to guarantee that all digits are correct up to the WorkingPrecision specified, the abscissas and weights are first computed exactly and then computed numerically with a precision of Max[WorkingPrecision, $MachinePrecision + 1]. If WorkingPrecision is $MachinePrecision or less, N is applied to the result to reduce the precision to $MachinePrecision. GaussianProductRule takes a sequence of pairs (produced by GaussianQuadraturePairs) and returns a tensor array of abscissa/weight tuples that can be used for multidimensional Gaussian quadrature. *) (* :Sources: Kenneth L. Judd (1998), Numerical Methods in Economics, MIT Press, chapter 7. Abramowitz and Stegun (1964), Handbook of Mathematical Tables, chapter 25. *) (* :Examples: p1 = GaussianQuadraturePairs[10, Type -> HermiteH, ScalingParameters -> {0, 1}] p2 = GaussianQuadraturePairs[7, Type -> LegendreP, ScalingParameters -> {-3, 10}] prod = GaussianProductRule[p1, p2] Needs["Graphics`Graphics3D`"] ListSurfacePlot3D[prod, Axes -> True, BoxRatios -> {1, 1, .5}, PlotRange -> All] *) BeginPackage["GaussianQuadrature`"] GaussianQuadrature::usage = "GaussianQuadrature is a package for doing Gaussian quadrature." GaussianQuadraturePairs::usage = "GaussianQuadraturePairs[n] returns n pairs of abscissas and weights suitable for n-point Gaussian quadrature. The default settings for the options are Type -> HermiteH, WorkingPrecision -> $MachinePrecision, and ScalingParameters -> Automatic. Other valid types are LaguerreL, LegendreP, and ChebyshevT. WorkingPrecision can be set to \[Infinity]. Setting WorkingPrecsion less than $MachinePrecision has no effect." Type::usage = "Type is an option that specifies which type of orthogonal polynomials to use for Gaussian quadrature. Valid types are HermiteH (the default), LaguerreL, LegendreP, and ChebyshevT." ScalingParameters::usage = "ScalingParameters is an options that specifies how to rescale the abscissas and the weights. The default is ScalingParameters -> Automatic, which does no rescaling. To affect rescaling, the proper usage is ScalingParameters -> {a, b}. The interpretation of the scaling parameters depends on the type of orthogonal polynomials used. If the type is either LegendreP or ChebyshevT, then a and b specify the minimum and maximum of a finite interval (a < b). If the type is HermiteH, then a and b specify the mean and the standard deviation of a Gaussian distribution. If the type is LaguerreL, then a and b specify the coefficient of x in the exponential weighting function and the lower bound of the integral, as in \!\(\[Integral]\_b\%\[Infinity]\( \[ExponentialE]\^\(\(-a\)\ x\)\) f[x] \[DifferentialD]x\), where a \[NotEqual] 0." GaussianProductRule::usage = "GaussianProductRule[pair1, pair2, ...] takes a sequence of lists of abscissa/weight pairs (produced by GaussianQuadraturePairs) and returns a tensor array of abscissa/weight tuples that can be used for multidimensional Gaussian quadrature. By setting the option Flatten -> True, GaussianProductRule will return a list of tuples instead." Begin["`Private`"] Options[GaussianQuadraturePairs] = { Type -> HermiteH, WorkingPrecision :> $MachinePrecision, ScalingParameters -> Automatic} GaussianQuadrature::badtype = "Unknown type: ``." GaussianQuadrature::badprec = "WorkingPrecision should be either a positive integer or \[Infinity]." GaussianQuadrature::badscale = "ScalingParameters should be either Automatic or a pair of numbers." GaussianQuadraturePairs[n_Integer?Positive, opts___?OptionQ] := Module[{type, wp, sp, a, b, A, B, C, wfun, x, abscissas, weights}, {type, wp, sp} = {Type, WorkingPrecision, ScalingParameters} /. {opts} /. Options[GaussianQuadraturePairs]; Switch[wp, _Integer?Positive | Infinity, {}, _, Message[GaussianQuadrature::badprec]; Return[$Failed]]; Switch[sp, Automatic, {A, B, C} = {1, 0, 1}, {_, _}, {a, b} = SetPrecision[sp, Infinity]; Switch[type, HermiteH, {A, B, C} = {Sqrt[2] b, a, 1/Sqrt[Pi]}, LegendreP | ChebyshevT, {A, B, C} = {0, a, 0} + (b-a)/2, LaguerreL, {A, B, C} = {1/a, b, Exp[-a b]/a}, _, Message[GaussianQuadrature::badtype, type]; Return[$Failed]], _, Message[GaussianQuadrature::badscale]; Return[$Failed]]; wfun = Function @ Evaluate @ Switch[type, HermiteH, 2^(n-1) n! Sqrt[\[Pi]]/(n HermiteH[n - 1, #])^2, LaguerreL, #/((n+1)^2 LaguerreL[n + 1, #]^2), LegendreP, -2/((n+1) LegendreP[n + 1, #] D[LegendreP[n, #], #]), ChebyshevT, Pi/n ]; abscissas = x /. Solve[type[n, x] == 0]; weights = wfun /@ abscissas; {abscissas, weights} = N[{abscissas, weights}, Max[wp, $MachinePrecision + 1]]; If[wp < Infinity, {abscissas, weights} = {abscissas, weights} /. Complex[x_, _] -> x]; If[wp <= $MachinePrecision, {abscissas, weights} = N[{abscissas, weights}]]; Sort @ Transpose[{A abscissas + B, C weights}] ] Options[GaussianProductRule] = {Flatten -> False} GaussianProductRule[pairs:{{_, _} ..} .., opts___?OptionQ] := Module[{len, weights, abscissas, tuples}, len = Length[{pairs}] - 1; ( weights = Outer[Times, ##]& @@ Map[Last, {pairs}, {2}]; abscissas = Outer[List, ##]& @@ Map[First, {pairs}, {2}]; tuples = MapThread[Append, {abscissas, weights}, Length[{pairs}]]; If[TrueQ[Flatten /. {opts} /. Options[TensorFromPairs]], Flatten[tuples, len], tuples] ) /; len > 0 ] End[] EndPackage[]