qpmad
Eigen-based C++ QP solver.
Loading...
Searching...
No Matches
givens.h
Go to the documentation of this file.
1/**
2 @file
3 @author Alexander Sherikov
4
5 @copyright 2017 Alexander Sherikov. Licensed under the Apache License,
6 Version 2.0. (see LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
7
8 @brief
9*/
10
11
12#pragma once
13
14#include "common.h"
15
16
17namespace qpmad
18{
19 /**
20 * @brief
21 *
22 * Represents Givens rotation
23 *
24 * [ cos, sin ]
25 * [ ]
26 * [ -sin, cos ]
27 *
28 * for a given vector (a, b) is defined with
29 *
30 * [ cos, sin ] [ a ] [ d ]
31 * [ ] * [ ] = [ ]
32 * [ -sin, cos ] [ b ] [ 0 ]
33 *
34 * sin^2 + cos^2 = 1
35 *
36 * Special cases:
37 * COPY b == 0: cos = 1, sin = 0
38 * SWAP (b != 0) && (a == 0): cos = 0, sin = 1
39 */
40 template <typename t_Scalar>
42 {
43 public:
44 enum Type
45 {
47 COPY = 1,
48 SWAP = 2
49 };
50
51
52 public:
53 GivensRotation() = default;
54
55 Type computeAndApply(t_Scalar &a, t_Scalar &b, const t_Scalar eps)
56 {
57 t_Scalar abs_b = std::fabs(b);
58
59 if (abs_b > eps)
60 {
61 t_Scalar abs_a = std::fabs(a);
62
63 if (abs_a > eps)
64 {
65 t_Scalar t;
66 if (abs_a > abs_b)
67 {
68 t = (abs_b / abs_a);
69 t = abs_a * std::sqrt(1.0 + t * t);
70 }
71 else
72 {
73 t = (abs_a / abs_b);
74 t = abs_b * std::sqrt(1.0 + t * t);
75 }
76 t = copysign(t, a);
77
78 cos = a / t;
79 sin = b / t;
80
81 a = t;
82 b = 0.0;
83
85 }
86 else
87 {
88 // cos = 0.0;
89 // sin = 1.0;
90 swap(a, b);
91 type = SWAP;
92 }
93 }
94 else
95 {
96 // cos = 1.0;
97 // sin = 0.0;
98 type = COPY;
99 }
100
101 return (type);
102 }
103
104
105 void apply(t_Scalar &a, t_Scalar &b) const
106 {
107 switch (type)
108 {
109 case COPY:
110 return;
111 case SWAP:
112 swap(a, b);
113 return;
114 case NONTRIVIAL:
115 applyNonTrivial(a, b);
116 return;
117 }
118 }
119
120 template <class t_MatrixType>
122 t_MatrixType &M,
123 MatrixIndex start,
124 MatrixIndex end,
125 MatrixIndex column_1,
126 MatrixIndex column_2) const
127 {
128 switch (type)
129 {
130 case COPY:
131 return;
132 case SWAP:
133 M.col(column_1).segment(start, end - start).swap(M.col(column_2).segment(start, end - start));
134 return;
135 case NONTRIVIAL:
136 M.middleRows(start, end - start)
137 .transpose()
138 .applyOnTheLeft(column_1, column_2, Eigen::JacobiRotation<t_Scalar>(cos, sin));
139 return;
140 }
141 }
142
143
144 template <class t_MatrixType>
145 void applyRowWise(t_MatrixType &M, MatrixIndex start, MatrixIndex end, MatrixIndex row_1, MatrixIndex row_2)
146 const
147 {
148 switch (type)
149 {
150 case COPY:
151 return;
152 case SWAP:
153 M.row(row_1).segment(start, end - start).swap(M.row(row_2).segment(start, end - start));
154 return;
155 case NONTRIVIAL:
156 M.middleCols(start, end - start)
157 .applyOnTheLeft(row_1, row_2, Eigen::JacobiRotation<t_Scalar>(cos, sin));
158 return;
159 }
160 }
161
162 private:
164 t_Scalar cos;
165 t_Scalar sin;
166
167
168 private:
169 inline void swap(t_Scalar &a, t_Scalar &b) const
170 {
171 std::swap(a, b);
172 }
173
174 inline void applyNonTrivial(t_Scalar &a, t_Scalar &b) const
175 {
176 t_Scalar t1 = a;
177 t_Scalar t2 = b;
178 a = t1 * cos + t2 * sin;
179 b = -sin * t1 + cos * t2;
180 }
181 };
182} // namespace qpmad
void applyRowWise(t_MatrixType &M, MatrixIndex start, MatrixIndex end, MatrixIndex row_1, MatrixIndex row_2) const
Definition givens.h:145
void applyNonTrivial(t_Scalar &a, t_Scalar &b) const
Definition givens.h:174
Type computeAndApply(t_Scalar &a, t_Scalar &b, const t_Scalar eps)
Definition givens.h:55
void swap(t_Scalar &a, t_Scalar &b) const
Definition givens.h:169
void applyColumnWise(t_MatrixType &M, MatrixIndex start, MatrixIndex end, MatrixIndex column_1, MatrixIndex column_2) const
Definition givens.h:121
void apply(t_Scalar &a, t_Scalar &b) const
Definition givens.h:105
EIGEN_DEFAULT_DENSE_INDEX_TYPE MatrixIndex
Definition common.h:37