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 Type computeAndApply(t_Scalar &a, t_Scalar &b, const t_Scalar eps)
54 {
55 t_Scalar abs_b = std::fabs(b);
56
57 if (abs_b > eps)
58 {
59 t_Scalar abs_a = std::fabs(a);
60
61 if (abs_a > eps)
62 {
63 t_Scalar t;
64 if (abs_a > abs_b)
65 {
66 t = (abs_b / abs_a);
67 t = abs_a * std::sqrt(1.0 + t * t);
68 }
69 else
70 {
71 t = (abs_a / abs_b);
72 t = abs_b * std::sqrt(1.0 + t * t);
73 }
74 t = copysign(t, a);
75
76 cos = a / t;
77 sin = b / t;
78
79 a = t;
80 b = 0.0;
81
83 }
84 else
85 {
86 // cos = 0.0;
87 // sin = 1.0;
88 swap(a, b);
89 type = SWAP;
90 }
91 }
92 else
93 {
94 // cos = 1.0;
95 // sin = 0.0;
96 type = COPY;
97 }
98
99 return (type);
100 }
101
102
103 void apply(t_Scalar &a, t_Scalar &b) const
104 {
105 switch (type)
106 {
107 case COPY:
108 return;
109 case SWAP:
110 swap(a, b);
111 return;
112 case NONTRIVIAL:
113 applyNonTrivial(a, b);
114 return;
115 }
116 }
117
118 template <class t_MatrixType>
120 t_MatrixType &M,
121 MatrixIndex start,
122 MatrixIndex end,
123 MatrixIndex column_1,
124 MatrixIndex column_2) const
125 {
126 switch (type)
127 {
128 case COPY:
129 return;
130 case SWAP:
131 M.col(column_1).segment(start, end - start).swap(M.col(column_2).segment(start, end - start));
132 return;
133 case NONTRIVIAL:
134 M.middleRows(start, end - start)
135 .transpose()
136 .applyOnTheLeft(column_1, column_2, Eigen::JacobiRotation<t_Scalar>(cos, sin));
137 return;
138 }
139 }
140
141
142 template <class t_MatrixType>
143 void applyRowWise(t_MatrixType &M, MatrixIndex start, MatrixIndex end, MatrixIndex row_1, MatrixIndex row_2)
144 const
145 {
146 switch (type)
147 {
148 case COPY:
149 return;
150 case SWAP:
151 M.row(row_1).segment(start, end - start).swap(M.row(row_2).segment(start, end - start));
152 return;
153 case NONTRIVIAL:
154 M.middleCols(start, end - start)
155 .applyOnTheLeft(row_1, row_2, Eigen::JacobiRotation<t_Scalar>(cos, sin));
156 return;
157 }
158 }
159
160 private:
162 t_Scalar cos;
163 t_Scalar sin;
164
165
166 private:
167 inline void swap(t_Scalar &a, t_Scalar &b) const
168 {
169 std::swap(a, b);
170 }
171
172 inline void applyNonTrivial(t_Scalar &a, t_Scalar &b) const
173 {
174 t_Scalar t1 = a;
175 t_Scalar t2 = b;
176 a = t1 * cos + t2 * sin;
177 b = -sin * t1 + cos * t2;
178 }
179 };
180} // namespace qpmad
Represents Givens rotation.
Definition: givens.h:42
void applyRowWise(t_MatrixType &M, MatrixIndex start, MatrixIndex end, MatrixIndex row_1, MatrixIndex row_2) const
Definition: givens.h:143
void applyNonTrivial(t_Scalar &a, t_Scalar &b) const
Definition: givens.h:172
Type computeAndApply(t_Scalar &a, t_Scalar &b, const t_Scalar eps)
Definition: givens.h:53
void swap(t_Scalar &a, t_Scalar &b) const
Definition: givens.h:167
void applyColumnWise(t_MatrixType &M, MatrixIndex start, MatrixIndex end, MatrixIndex column_1, MatrixIndex column_2) const
Definition: givens.h:119
void apply(t_Scalar &a, t_Scalar &b) const
Definition: givens.h:103
EIGEN_DEFAULT_DENSE_INDEX_TYPE MatrixIndex
Definition: common.h:33