/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 | | } |