qpmad
Eigen-based C++ QP solver.
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 
17 namespace 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 
84  type = NONTRIVIAL;
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
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: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