Coverage Report

Created: 2025-08-28 06:30

/src/quantlib/ql/math/solvers1d/ridder.hpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
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
 <http://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 ridder.hpp
21
    \brief Ridder 1-D solver
22
*/
23
24
#ifndef quantlib_solver1d_ridder_h
25
#define quantlib_solver1d_ridder_h
26
27
#include <ql/math/solver1d.hpp>
28
29
namespace QuantLib {
30
31
    //! %Ridder 1-D solver
32
    /*! \test the correctness of the returned values is tested by
33
              checking them against known good results.
34
35
        \ingroup solvers
36
    */
37
    class Ridder : public Solver1D<Ridder> {
38
      public:
39
        template <class F>
40
        Real solveImpl(const F& f,
41
0
                       Real xAcc) const {
42
43
            /* The implementation of the algorithm was inspired by
44
               Press, Teukolsky, Vetterling, and Flannery,
45
               "Numerical Recipes in C", 2nd edition,
46
               Cambridge University Press
47
            */
48
49
0
            Real fxMid, froot, s, xMid, nextRoot;
50
51
            // test on Black-Scholes implied volatility show that
52
            // Ridder solver algorithm actually provides an
53
            // accuracy 100 times below promised
54
0
            Real xAccuracy = xAcc/100.0;
55
56
            // Any highly unlikely value, to simplify logic below
57
0
            root_ = QL_MIN_REAL;
58
59
0
            while (evaluationNumber_<=maxEvaluations_) {
60
0
                xMid = 0.5*(xMin_+xMax_);
61
                // First of two function evaluations per iteraton
62
0
                fxMid = f(xMid);
63
0
                ++evaluationNumber_;
64
0
                s = std::sqrt(fxMid*fxMid-fxMin_*fxMax_);
65
0
                if (close(s, 0.0)) {
66
0
                    f(root_);
67
0
                    ++evaluationNumber_;
68
0
                    return root_;
69
0
                }
70
                // Updating formula
71
0
                nextRoot = xMid + (xMid - xMin_) *
72
0
                    ((fxMin_ >= fxMax_ ? 1.0 : -1.0) * fxMid / s);
73
0
                if (std::fabs(nextRoot-root_) <= xAccuracy) {
74
0
                    f(root_);
75
0
                    ++evaluationNumber_;
76
0
                    return root_;
77
0
                }
78
79
0
                root_ = nextRoot;
80
                // Second of two function evaluations per iteration
81
0
                froot = f(root_);
82
0
                ++evaluationNumber_;
83
0
                if (close(froot, 0.0))
84
0
                    return root_;
85
86
                // Bookkeeping to keep the root bracketed on next iteration
87
0
                if (sign(fxMid,froot) != fxMid) {
88
0
                    xMin_ = xMid;
89
0
                    fxMin_ = fxMid;
90
0
                    xMax_ = root_;
91
0
                    fxMax_ = froot;
92
0
                } else if (sign(fxMin_,froot) != fxMin_) {
93
0
                    xMax_ = root_;
94
0
                    fxMax_ = froot;
95
0
                } else if (sign(fxMax_,froot) != fxMax_) {
96
0
                    xMin_ = root_;
97
0
                    fxMin_ = froot;
98
0
                } else {
99
0
                    QL_FAIL("never get here.");
100
0
                }
101
102
0
                if (std::fabs(xMax_-xMin_) <= xAccuracy) {
103
0
                    f(root_);
104
0
                    ++evaluationNumber_;
105
0
                    return root_;
106
0
                }
107
0
            }
108
109
0
            QL_FAIL("maximum number of function evaluations ("
110
0
                    << maxEvaluations_ << ") exceeded");
111
0
        }
Unexecuted instantiation: double QuantLib::Ridder::solveImpl<QuantLib::detail::SumExponentialsRootSolver>(QuantLib::detail::SumExponentialsRootSolver const&, double) const
Unexecuted instantiation: double QuantLib::Ridder::solveImpl<QuantLib::QdPlusBoundaryEvaluator>(QuantLib::QdPlusBoundaryEvaluator const&, double) const
112
      private:
113
0
        Real sign(Real a, Real b) const {
114
0
            return b >= 0.0 ? std::fabs(a) : Real(-std::fabs(a));
115
0
        }
116
    };
117
118
}
119
120
#endif