/src/quantlib/ql/math/matrixutilities/householder.cpp
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) 2024 Klaus Spanderen |
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 | | #include <ql/math/matrixutilities/householder.hpp> |
21 | | |
22 | | namespace QuantLib { |
23 | | |
24 | | HouseholderTransformation::HouseholderTransformation(Array v) |
25 | 0 | : v_(std::move(v)) {} |
26 | | |
27 | | |
28 | 0 | Array HouseholderTransformation::operator()(const Array& x) const { |
29 | 0 | return x - (2.0*DotProduct(v_, x))*v_; |
30 | 0 | } |
31 | | |
32 | 0 | Matrix HouseholderTransformation::getMatrix() const { |
33 | 0 | const Array y = v_ / Norm2(v_); |
34 | 0 | const Size n = y.size(); |
35 | |
|
36 | 0 | Matrix m(n, n); |
37 | 0 | for (Size i=0; i < n; ++i) |
38 | 0 | for (Size j=0; j < n; ++j) |
39 | 0 | m[i][j] = ((i == j)? 1.0: 0.0) - 2*y[i]*y[j]; |
40 | |
|
41 | 0 | return m; |
42 | 0 | } |
43 | | |
44 | | HouseholderReflection::HouseholderReflection(Array e) |
45 | 0 | : e_(std::move(e)) {} |
46 | | |
47 | 0 | Array HouseholderReflection::reflectionVector(const Array& a) const { |
48 | 0 | const Real na = Norm2(a); |
49 | 0 | QL_REQUIRE(na > 0, "vector of length zero given"); |
50 | | |
51 | 0 | const Real aDotE = DotProduct(a, e_); |
52 | 0 | const Array a1 = aDotE*e_; |
53 | 0 | const Array a2 = a - a1; |
54 | |
|
55 | 0 | const Real eps = DotProduct(a2, a2) / (aDotE*aDotE); |
56 | 0 | if (eps < QL_EPSILON*QL_EPSILON) { |
57 | 0 | return Array(a.size(), 0.0); |
58 | 0 | } |
59 | 0 | else if (eps < 1e-4) { |
60 | 0 | const Real eps2 = eps*eps; |
61 | 0 | const Real eps3 = eps*eps2; |
62 | 0 | const Real eps4 = eps2*eps2; |
63 | 0 | const Array v = |
64 | 0 | (a2 - a1*(eps/2.0 - eps2/8.0 + eps3/16.0 - 5/128.0*eps4)) |
65 | 0 | / (aDotE*std::sqrt(eps + eps2/4.0 - eps3/8.0 + 5/64.0*eps4)); |
66 | 0 | return v; |
67 | 0 | } |
68 | 0 | else { |
69 | 0 | const Array c = a - na*e_; |
70 | 0 | return c / Norm2(c); |
71 | 0 | } |
72 | 0 | } |
73 | | |
74 | 0 | Array HouseholderReflection::operator()(const Array& a) const { |
75 | 0 | const Array v = reflectionVector(a); |
76 | 0 | return HouseholderTransformation(v)(a); |
77 | 0 | } |
78 | | } |