This file is indexed.

/usr/include/ql/math/solver1d.hpp is in libquantlib0-dev 1.7.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl

 This file is part of QuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://quantlib.org/

 QuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 <quantlib-dev@lists.sf.net>. The license is also available online at
 <http://quantlib.org/license.shtml>.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.
*/

/*! \file solver1d.hpp
    \brief Abstract 1-D solver class
*/

#ifndef quantlib_solver1d_hpp
#define quantlib_solver1d_hpp

#include <ql/math/comparison.hpp>
#include <ql/utilities/null.hpp>
#include <ql/patterns/curiouslyrecurring.hpp>
#include <ql/errors.hpp>
#include <iomanip>

namespace QuantLib {

    #define MAX_FUNCTION_EVALUATIONS 100

    //! Base class for 1-D solvers
    /*! The implementation of this class uses the so-called
        "Barton-Nackman trick", also known as "the curiously recurring
        template pattern". Concrete solvers will be declared as:
        \code
        class Foo : public Solver1D<Foo> {
          public:
            ...
            template <class F>
            Real solveImpl(const F& f, Real accuracy) const {
                ...
            }
        };
        \endcode
        Before calling <tt>solveImpl</tt>, the base class will set its
        protected data members so that:
        - <tt>xMin_</tt> and  <tt>xMax_</tt> form a valid bracket;
        - <tt>fxMin_</tt> and <tt>fxMax_</tt> contain the values of
          the function in <tt>xMin_</tt> and <tt>xMax_</tt>;
        - <tt>root_</tt> is a valid initial guess.
        The implementation of <tt>solveImpl</tt> can safely assume all
        of the above.

        \todo
        - clean up the interface so that it is clear whether the
          accuracy is specified for \f$ x \f$ or \f$ f(x) \f$.
        - add target value (now the target value is 0.0)
    */
    template <class Impl>
    class Solver1D : public CuriouslyRecurringTemplate<Impl> {
      public:
        Solver1D()
        : maxEvaluations_(MAX_FUNCTION_EVALUATIONS),
          lowerBoundEnforced_(false), upperBoundEnforced_(false) {}
        //! \name Modifiers
        //@{
        /*! This method returns the zero of the function \f$ f \f$,
            determined with the given accuracy \f$ \epsilon \f$;
            depending on the particular solver, this might mean that
            the returned \f$ x \f$ is such that \f$ |f(x)| < \epsilon
            \f$, or that \f$ |x-\xi| < \epsilon \f$ where \f$ \xi \f$
            is the real zero.

            This method contains a bracketing routine to which an
            initial guess must be supplied as well as a step used to
            scan the range of the possible bracketing values.
        */
        template <class F>
        Real solve(const F& f,
                   Real accuracy,
                   Real guess,
                   Real step) const {

            QL_REQUIRE(accuracy>0.0,
                       "accuracy (" << accuracy << ") must be positive");
            // check whether we really want to use epsilon
            accuracy = std::max(accuracy, QL_EPSILON);

            const Real growthFactor = 1.6;
            Integer flipflop = -1;

            root_ = guess;
            fxMax_ = f(root_);

            // monotonically crescent bias, as in optionValue(volatility)
            if (close(fxMax_,0.0))
                return root_;
            else if (fxMax_ > 0.0) {
                xMin_ = enforceBounds_(root_ - step);
                fxMin_ = f(xMin_);
                xMax_ = root_;
            } else {
                xMin_ = root_;
                fxMin_ = fxMax_;
                xMax_ = enforceBounds_(root_+step);
                fxMax_ = f(xMax_);
            }

            evaluationNumber_ = 2;
            while (evaluationNumber_ <= maxEvaluations_) {
                if (fxMin_*fxMax_ <= 0.0) {
                    if (close(fxMin_, 0.0))
                        return xMin_;
                    if (close(fxMax_, 0.0))
                        return xMax_;
                    root_ = (xMax_+xMin_)/2.0;
                    return this->impl().solveImpl(f, accuracy);
                }
                if (std::fabs(fxMin_) < std::fabs(fxMax_)) {
                    xMin_ = enforceBounds_(xMin_+growthFactor*(xMin_ - xMax_));
                    fxMin_= f(xMin_);
                } else if (std::fabs(fxMin_) > std::fabs(fxMax_)) {
                    xMax_ = enforceBounds_(xMax_+growthFactor*(xMax_ - xMin_));
                    fxMax_= f(xMax_);
                } else if (flipflop == -1) {
                    xMin_ = enforceBounds_(xMin_+growthFactor*(xMin_ - xMax_));
                    fxMin_= f(xMin_);
                    evaluationNumber_++;
                    flipflop = 1;
                } else if (flipflop == 1) {
                    xMax_ = enforceBounds_(xMax_+growthFactor*(xMax_ - xMin_));
                    fxMax_= f(xMax_);
                    flipflop = -1;
                }
                evaluationNumber_++;
            }

            QL_FAIL("unable to bracket root in " << maxEvaluations_
                    << " function evaluations (last bracket attempt: "
                    << "f[" << xMin_ << "," << xMax_ << "] "
                    << "-> [" << fxMin_ << "," << fxMax_ << "])");
        }
        /*! This method returns the zero of the function \f$ f \f$,
            determined with the given accuracy \f$ \epsilon \f$;
            depending on the particular solver, this might mean that
            the returned \f$ x \f$ is such that \f$ |f(x)| < \epsilon
            \f$, or that \f$ |x-\xi| < \epsilon \f$ where \f$ \xi \f$
            is the real zero.

            An initial guess must be supplied, as well as two values
            \f$ x_\mathrm{min} \f$ and \f$ x_\mathrm{max} \f$ which
            must bracket the zero (i.e., either \f$ f(x_\mathrm{min})
            \leq 0 \leq f(x_\mathrm{max}) \f$, or \f$
            f(x_\mathrm{max}) \leq 0 \leq f(x_\mathrm{min}) \f$ must
            be true).
        */
        template <class F>
        Real solve(const F& f,
                   Real accuracy,
                   Real guess,
                   Real xMin,
                   Real xMax) const {

            QL_REQUIRE(accuracy>0.0,
                       "accuracy (" << accuracy << ") must be positive");
            // check whether we really want to use epsilon
            accuracy = std::max(accuracy, QL_EPSILON);

            xMin_ = xMin;
            xMax_ = xMax;

            QL_REQUIRE(xMin_ < xMax_,
                       "invalid range: xMin_ (" << xMin_
                       << ") >= xMax_ (" << xMax_ << ")");
            QL_REQUIRE(!lowerBoundEnforced_ || xMin_ >= lowerBound_,
                       "xMin_ (" << xMin_
                       << ") < enforced low bound (" << lowerBound_ << ")");
            QL_REQUIRE(!upperBoundEnforced_ || xMax_ <= upperBound_,
                       "xMax_ (" << xMax_
                       << ") > enforced hi bound (" << upperBound_ << ")");

            fxMin_ = f(xMin_);
            if (close(fxMin_, 0.0))
                return xMin_;

            fxMax_ = f(xMax_);
            if (close(fxMax_, 0.0))
                return xMax_;

            evaluationNumber_ = 2;

            QL_REQUIRE(fxMin_*fxMax_ < 0.0,
                       "root not bracketed: f["
                       << xMin_ << "," << xMax_ << "] -> ["
                       << std::scientific
                       << fxMin_ << "," << fxMax_ << "]");

            QL_REQUIRE(guess > xMin_,
                       "guess (" << guess << ") < xMin_ (" << xMin_ << ")");
            QL_REQUIRE(guess < xMax_,
                       "guess (" << guess << ") > xMax_ (" << xMax_ << ")");

            root_ = guess;

            return this->impl().solveImpl(f, accuracy);
        }

        /*! This method sets the maximum number of function
            evaluations for the bracketing routine. An error is thrown
            if a bracket is not found after this number of
            evaluations.
        */
        void setMaxEvaluations(Size evaluations);
        //! sets the lower bound for the function domain
        void setLowerBound(Real lowerBound);
        //! sets the upper bound for the function domain
        void setUpperBound(Real upperBound);
        //@}
      protected:
        mutable Real root_, xMin_, xMax_, fxMin_, fxMax_;
        Size maxEvaluations_;
        mutable Size evaluationNumber_;
      private:
        Real enforceBounds_(Real x) const;
        Real lowerBound_, upperBound_;
        bool lowerBoundEnforced_, upperBoundEnforced_;
    };


    // inline definitions

    template <class T>
    inline void Solver1D<T>::setMaxEvaluations(Size evaluations) {
        maxEvaluations_ = evaluations;
    }

    template <class T>
    inline void Solver1D<T>::setLowerBound(Real lowerBound) {
        lowerBound_ = lowerBound;
        lowerBoundEnforced_ = true;
    }

    template <class T>
    inline void Solver1D<T>::setUpperBound(Real upperBound) {
        upperBound_ = upperBound;
        upperBoundEnforced_ = true;
    }

    template <class T>
    inline Real Solver1D<T>::enforceBounds_(Real x) const {
        if (lowerBoundEnforced_ && x < lowerBound_)
            return lowerBound_;
        if (upperBoundEnforced_ && x > upperBound_)
            return upperBound_;
        return x;
    }

}

#endif