Coverage Report

Created: 2025-12-08 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/math/abcdmathfunction.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2006, 2007, 2015 Ferdinando Ametrano
5
 Copyright (C) 2006 Cristina Duminuco
6
 Copyright (C) 2005, 2006 Klaus Spanderen
7
 Copyright (C) 2007 Giorgio Facchinetti
8
 Copyright (C) 2015 Paolo Mazzocchi
9
10
 This file is part of QuantLib, a free-software/open-source library
11
 for financial quantitative analysts and developers - http://quantlib.org/
12
13
 QuantLib is free software: you can redistribute it and/or modify it
14
 under the terms of the QuantLib license.  You should have received a
15
 copy of the license along with this program; if not, please email
16
 <quantlib-dev@lists.sf.net>. The license is also available online at
17
 <https://www.quantlib.org/license.shtml>.
18
19
 This program is distributed in the hope that it will be useful, but WITHOUT
20
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21
 FOR A PARTICULAR PURPOSE.  See the license for more details.
22
*/
23
24
#include <ql/math/abcdmathfunction.hpp>
25
#include <utility>
26
27
namespace QuantLib {
28
29
    void AbcdMathFunction::validate(Real a,
30
                                    Real b,
31
                                    Real c,
32
0
                                    Real d) {
33
0
        QL_REQUIRE(c>0, "c (" << c << ") must be positive");
34
0
        QL_REQUIRE(d>=0, "d (" << d << ") must be non negative");
35
0
        QL_REQUIRE(a+d>=0,
36
0
                   "a+d (" << a << "+" << d << ") must be non negative");
37
38
0
        if (b>=0.0)
39
0
            return;
40
41
        // the one and only stationary point...
42
0
        Time zeroFirstDerivative = 1.0/c-a/b;
43
0
        if (zeroFirstDerivative>=0.0) {
44
            // ... is a minimum
45
            // must be abcd(zeroFirstDerivative)>=0
46
0
            QL_REQUIRE(b>=-(d*c)/std::exp(c*a/b-1.0),
47
0
                       "b (" << b << ") less than " <<
48
0
                       -(d*c)/std::exp(c*a/b-1.0) << ": negative function"
49
0
                       " value at stationary point " << zeroFirstDerivative);
50
0
        }
51
52
0
    }
53
54
0
    void AbcdMathFunction::initialize_() {
55
0
        validate(a_, b_, c_, d_);
56
0
        da_ = b_ - c_*a_;
57
0
        db_ = -c_*b_;
58
0
        dabcd_[0]=da_;
59
0
        dabcd_[1]=db_;
60
0
        dabcd_[2]=c_;
61
0
        dabcd_[3]=0.0;
62
63
0
        pa_ = -(a_ + b_/c_)/c_;
64
0
        pb_ = -b_/c_;
65
0
        K_ = 0.0;
66
67
0
        dibc_ = b_/c_;
68
0
        diacplusbcc_ = a_/c_ + dibc_/c_;
69
0
    }
70
71
    AbcdMathFunction::AbcdMathFunction(Real aa, Real bb, Real cc, Real dd)
72
0
    : a_(aa), b_(bb), c_(cc), d_(dd), abcd_(4), dabcd_(4) {
73
0
        abcd_[0]=a_;
74
0
        abcd_[1]=b_;
75
0
        abcd_[2]=c_;
76
0
        abcd_[3]=d_;
77
0
        initialize_();
78
0
    }
79
80
0
    AbcdMathFunction::AbcdMathFunction(std::vector<Real> abcd) : abcd_(std::move(abcd)), dabcd_(4) {
81
0
        a_=abcd_[0];
82
0
        b_=abcd_[1];
83
0
        c_=abcd_[2];
84
0
        d_=abcd_[3];
85
0
        initialize_();
86
0
    }
87
88
0
    Time AbcdMathFunction::maximumLocation() const {
89
0
        if (b_==0.0) {
90
0
            if (a_>=0.0)
91
0
                return 0.0;
92
0
            else
93
0
                return QL_MAX_REAL;
94
0
        }
95
96
        // stationary point
97
        // TODO check if minimum
98
        // TODO check if maximum at +inf
99
0
        Real zeroFirstDerivative = 1.0/c_-a_/b_;
100
0
        return (zeroFirstDerivative>0.0 ? zeroFirstDerivative : 0.0);
101
0
    }
102
103
    Real AbcdMathFunction::definiteIntegral(Time t1,
104
0
                                            Time t2) const {
105
0
        return primitive(t2)-primitive(t1);
106
0
    }
107
108
    std::vector<Real>
109
    AbcdMathFunction::definiteIntegralCoefficients(Time t,
110
0
                                                   Time t2) const {
111
0
        Time dt = t2 - t;
112
0
        Real expcdt = std::exp(-c_*dt);
113
0
        std::vector<Real> result(4);
114
0
        result[0] = diacplusbcc_ - (diacplusbcc_ + dibc_*dt)*expcdt;
115
0
        result[1] = dibc_ * (1.0 - expcdt);
116
0
        result[2] = c_;
117
0
        result[3] = d_*dt;
118
0
        return result;
119
0
    }
120
121
    std::vector<Real>
122
    AbcdMathFunction::definiteDerivativeCoefficients(Time t,
123
0
                                                     Time t2) const {
124
0
        Time dt = t2 - t;
125
0
        Real expcdt = std::exp(-c_*dt);
126
0
        std::vector<Real> result(4);
127
0
        result[1] = b_*c_/(1.0-expcdt);
128
0
        result[0] = a_*c_ - b_ + result[1]*dt*expcdt;
129
0
        result[0] /= 1.0-expcdt;
130
0
        result[2] = c_;
131
0
        result[3] = d_/dt;
132
0
        return result;
133
0
    }
134
135
}