Coverage Report

Created: 2026-03-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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