Coverage Report

Created: 2026-01-25 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/math/matrixutilities/bicgstab.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2009 Ralph Schreyer
5
 Copyright (C) 2009 Klaus Spanderen
6
7
 This file is part of QuantLib, a free-software/open-source library
8
 for financial quantitative analysts and developers - http://quantlib.org/
9
10
 QuantLib is free software: you can redistribute it and/or modify it
11
 under the terms of the QuantLib license.  You should have received a
12
 copy of the license along with this program; if not, please email
13
 <quantlib-dev@lists.sf.net>. The license is also available online at
14
 <https://www.quantlib.org/license.shtml>.
15
16
 This program is distributed in the hope that it will be useful, but WITHOUT
17
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 FOR A PARTICULAR PURPOSE.  See the license for more details.
19
*/
20
21
/*! \file bicgstab.cpp
22
    \brief bi-conjugated gradient stableized algorithm
23
*/
24
25
26
#include <ql/math/matrixutilities/bicgstab.hpp>
27
#include <utility>
28
29
namespace QuantLib {
30
31
    BiCGstab::BiCGstab(BiCGstab::MatrixMult A,
32
                       Size maxIter,
33
                       Real relTol,
34
                       BiCGstab::MatrixMult preConditioner)
35
0
    : A_(std::move(A)), M_(std::move(preConditioner)), maxIter_(maxIter), relTol_(relTol) {}
36
37
0
    BiCGStabResult BiCGstab::solve(const Array& b, const Array& x0) const {
38
0
        Real bnorm2 = Norm2(b);
39
0
        if (bnorm2 == 0.0) {
40
0
            BiCGStabResult result = { 0, 0.0, b};
41
0
            return result;
42
0
        }
43
44
0
        Array x = ((!x0.empty()) ? x0 : Array(b.size(), 0.0));
45
0
        Array r = b - A_(x);
46
47
0
        Array rTld = r;
48
0
        Array p, pTld, v, s, sTld, t;
49
0
        Real omega = 1.0;
50
0
        Real rho, rhoTld=1.0;
51
0
        Real alpha = 0.0, beta;
52
0
        Real error = Norm2(r)/bnorm2;
53
54
0
        Size i;
55
0
        for (i=0; i < maxIter_ && error >= relTol_; ++i) {
56
0
           rho = DotProduct(rTld, r);
57
0
           if  (rho == 0.0 || omega == 0.0)
58
0
               break;
59
60
0
           if (i != 0U) {
61
0
               beta = (rho / rhoTld) * (alpha / omega);
62
0
               p = r + beta * (p - omega * v);
63
0
           } else {
64
0
               p = r;
65
0
           }
66
67
0
           pTld = (!M_ ? p : M_(p));
68
0
           v     = A_(pTld);
69
70
0
           alpha = rho/DotProduct(rTld, v);
71
0
           s     = r-alpha*v;
72
0
           if (Norm2(s) < relTol_*bnorm2) {
73
0
              x += alpha*pTld;
74
0
              error = Norm2(s)/bnorm2;
75
0
              break;
76
0
           }
77
78
0
           sTld = (!M_ ? s : M_(s));
79
0
           t = A_(sTld);
80
0
           omega = DotProduct(t,s)/DotProduct(t,t);
81
0
           x += alpha*pTld + omega*sTld;
82
0
           r = s - omega*t;
83
0
           error = Norm2(r)/bnorm2;
84
0
           rhoTld = rho;
85
0
        }
86
87
0
        QL_REQUIRE(i < maxIter_, "max number of iterations exceeded");
88
0
        QL_REQUIRE(error < relTol_, "could not converge");
89
90
0
        BiCGStabResult result = { i, error, x};
91
0
        return result;
92
0
    }
93
94
}