/src/quantlib/ql/math/integrals/gaussianorthogonalpolynomial.cpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2005 Klaus Spanderen |
5 | | |
6 | | This file is part of QuantLib, a free-software/open-source library |
7 | | for financial quantitative analysts and developers - http://quantlib.org/ |
8 | | |
9 | | QuantLib is free software: you can redistribute it and/or modify it |
10 | | under the terms of the QuantLib license. You should have received a |
11 | | copy of the license along with this program; if not, please email |
12 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
13 | | <https://www.quantlib.org/license.shtml>. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, but WITHOUT |
16 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
17 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
18 | | */ |
19 | | |
20 | | /*! \file gaussianquadratures.hpp |
21 | | \brief Integral of a 1-dimensional function using the Gauss quadratures |
22 | | */ |
23 | | |
24 | | #include <ql/math/integrals/gaussianorthogonalpolynomial.hpp> |
25 | | #include <ql/math/distributions/gammadistribution.hpp> |
26 | | #include <ql/math/comparison.hpp> |
27 | | #include <ql/errors.hpp> |
28 | | #include <cmath> |
29 | | |
30 | | namespace QuantLib { |
31 | | |
32 | 0 | Real GaussianOrthogonalPolynomial::value(Size n, Real x) const { |
33 | 0 | if (n > 1) { |
34 | 0 | return (x-alpha(n-1)) * value(n-1, x) |
35 | 0 | - beta(n-1) * value(n-2, x); |
36 | 0 | } |
37 | 0 | else if (n == 1) { |
38 | 0 | return x-alpha(0); |
39 | 0 | } |
40 | | |
41 | 0 | return 1; |
42 | 0 | } |
43 | | |
44 | 0 | Real GaussianOrthogonalPolynomial::weightedValue(Size n, Real x) const { |
45 | 0 | return std::sqrt(w(x))*value(n, x); |
46 | 0 | } |
47 | | |
48 | | |
49 | | GaussLaguerrePolynomial::GaussLaguerrePolynomial(Real s) |
50 | 0 | : s_(s) { |
51 | 0 | QL_REQUIRE(s > -1.0, "s must be bigger than -1"); |
52 | 0 | } |
53 | | |
54 | 0 | Real GaussLaguerrePolynomial::mu_0() const { |
55 | 0 | return std::exp(GammaFunction().logValue(s_+1)); |
56 | 0 | } |
57 | | |
58 | 0 | Real GaussLaguerrePolynomial::alpha(Size i) const { |
59 | 0 | return 2*i+1+s_; |
60 | 0 | } |
61 | | |
62 | 0 | Real GaussLaguerrePolynomial::beta(Size i) const { |
63 | 0 | return i*(i+s_); |
64 | 0 | } |
65 | | |
66 | 0 | Real GaussLaguerrePolynomial::w(Real x) const { |
67 | 0 | return std::pow(x, s_)*std::exp(-x); |
68 | 0 | } |
69 | | |
70 | | |
71 | | GaussHermitePolynomial::GaussHermitePolynomial(Real mu) |
72 | 0 | : mu_(mu) { |
73 | 0 | QL_REQUIRE(mu > -0.5, "mu must be bigger than -0.5"); |
74 | 0 | } |
75 | | |
76 | 0 | Real GaussHermitePolynomial::mu_0() const { |
77 | 0 | return std::exp(GammaFunction().logValue(mu_+0.5)); |
78 | 0 | } |
79 | | |
80 | 0 | Real GaussHermitePolynomial::alpha(Size) const { |
81 | 0 | return 0.0; |
82 | 0 | } |
83 | | |
84 | 0 | Real GaussHermitePolynomial::beta(Size i) const { |
85 | 0 | return (i % 2) != 0U ? Real(i / 2.0 + mu_) : Real(i / 2.0); |
86 | 0 | } |
87 | | |
88 | 0 | Real GaussHermitePolynomial::w(Real x) const { |
89 | 0 | return std::pow(std::fabs(x), 2*mu_)*std::exp(-x*x); |
90 | 0 | } |
91 | | |
92 | | GaussJacobiPolynomial::GaussJacobiPolynomial(Real alpha, Real beta) |
93 | 0 | : alpha_(alpha), beta_ (beta) { |
94 | 0 | QL_REQUIRE(alpha_+beta_ > -2.0,"alpha+beta must be bigger than -2"); |
95 | 0 | QL_REQUIRE(alpha_ > -1.0,"alpha must be bigger than -1"); |
96 | 0 | QL_REQUIRE(beta_ > -1.0,"beta must be bigger than -1"); |
97 | 0 | } |
98 | | |
99 | 0 | Real GaussJacobiPolynomial::mu_0() const { |
100 | 0 | return std::pow(2.0, alpha_+beta_+1) |
101 | 0 | * std::exp( GammaFunction().logValue(alpha_+1) |
102 | 0 | +GammaFunction().logValue(beta_ +1) |
103 | 0 | -GammaFunction().logValue(alpha_+beta_+2)); |
104 | 0 | } |
105 | | |
106 | 0 | Real GaussJacobiPolynomial::alpha(Size i) const { |
107 | 0 | Real num = beta_*beta_ - alpha_*alpha_; |
108 | 0 | Real denom = (2.0*i+alpha_+beta_)*(2.0*i+alpha_+beta_+2); |
109 | |
|
110 | 0 | if (close_enough(denom,0.0)) { |
111 | 0 | if (!close_enough(num,0.0)) { |
112 | 0 | QL_FAIL("can't compute a_k for jacobi integration\n"); |
113 | 0 | } |
114 | 0 | else { |
115 | | // l'Hospital |
116 | 0 | num = 2*beta_; |
117 | 0 | denom= 2*(2.0*i+alpha_+beta_+1); |
118 | |
|
119 | 0 | QL_ASSERT(!close_enough(denom,0.0), "can't compute a_k for jacobi integration\n"); |
120 | 0 | } |
121 | 0 | } |
122 | | |
123 | 0 | return num / denom; |
124 | 0 | } |
125 | | |
126 | 0 | Real GaussJacobiPolynomial::beta(Size i) const { |
127 | 0 | Real num = 4.0*i*(i+alpha_)*(i+beta_)*(i+alpha_+beta_); |
128 | 0 | Real denom = (2.0*i+alpha_+beta_)*(2.0*i+alpha_+beta_) |
129 | 0 | * ((2.0*i+alpha_+beta_)*(2.0*i+alpha_+beta_)-1); |
130 | |
|
131 | 0 | if (close_enough(denom,0.0)) { |
132 | 0 | if (!close_enough(num,0.0)) { |
133 | 0 | QL_FAIL("can't compute b_k for jacobi integration\n"); |
134 | 0 | } else { |
135 | | // l'Hospital |
136 | 0 | num = 4.0*i*(i+beta_)* (2.0*i+2*alpha_+beta_); |
137 | 0 | denom= 2.0*(2.0*i+alpha_+beta_); |
138 | 0 | denom*=denom-1; |
139 | 0 | QL_ASSERT(!close_enough(denom,0.0), "can't compute b_k for jacobi integration\n"); |
140 | 0 | } |
141 | 0 | } |
142 | 0 | return num / denom; |
143 | 0 | } |
144 | | |
145 | 0 | Real GaussJacobiPolynomial::w(Real x) const { |
146 | 0 | return std::pow(1-x, alpha_)*std::pow(1+x, beta_); |
147 | 0 | } |
148 | | |
149 | | |
150 | | GaussLegendrePolynomial::GaussLegendrePolynomial() |
151 | 0 | : GaussJacobiPolynomial(0.0, 0.0) { |
152 | 0 | } |
153 | | |
154 | | GaussChebyshev2ndPolynomial::GaussChebyshev2ndPolynomial() |
155 | 0 | : GaussJacobiPolynomial(0.5, 0.5) { |
156 | 0 | } |
157 | | |
158 | | GaussChebyshevPolynomial::GaussChebyshevPolynomial() |
159 | 0 | : GaussJacobiPolynomial(-0.5, -0.5) { |
160 | 0 | } |
161 | | |
162 | | GaussGegenbauerPolynomial::GaussGegenbauerPolynomial(Real lambda) |
163 | 0 | : GaussJacobiPolynomial(lambda-0.5, lambda-0.5){ |
164 | 0 | } |
165 | | |
166 | 0 | Real GaussHyperbolicPolynomial::mu_0() const { |
167 | 0 | return M_PI; |
168 | 0 | } |
169 | | |
170 | 0 | Real GaussHyperbolicPolynomial::alpha(Size) const { |
171 | 0 | return 0.0; |
172 | 0 | } |
173 | | |
174 | 0 | Real GaussHyperbolicPolynomial::beta(Size i) const { |
175 | 0 | return i != 0U ? M_PI_2 * M_PI_2 * i * i : M_PI; |
176 | 0 | } |
177 | | |
178 | 0 | Real GaussHyperbolicPolynomial::w(Real x) const { |
179 | 0 | return 1/std::cosh(x); |
180 | 0 | } |
181 | | |
182 | | } |
183 | | |