DoubleShiftQR.h
Go to the documentation of this file.
1 // Copyright (C) 2016-2025 Yixuan Qiu <yixuan.qiu@cos.name>
2 //
3 // This Source Code Form is subject to the terms of the Mozilla
4 // Public License v. 2.0. If a copy of the MPL was not distributed
5 // with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
6 
7 #ifndef SPECTRA_DOUBLE_SHIFT_QR_H
8 #define SPECTRA_DOUBLE_SHIFT_QR_H
9 
10 #include <Eigen/Core>
11 #include <vector> // std::vector
12 #include <algorithm> // std::min, std::fill, std::copy
13 #include <utility> // std::swap
14 #include <cmath> // std::abs, std::sqrt, std::pow
15 #include <stdexcept> // std::invalid_argument, std::logic_error
16 
17 #include "../Util/TypeTraits.h"
18 
19 namespace Spectra {
20 
21 template <typename Scalar = double>
23 {
24 private:
30 
33 
34  // A very small value, but 1.0 / m_near_0 does not overflow
35  // ~= 1e-307 for the "double" type
37  // The machine precision, ~= 1e-16 for the "double" type
39 
40  Index m_n; // Dimension of the matrix
41  Matrix m_mat_H; // A copy of the matrix to be factorized
42  Scalar m_shift_s; // Shift constant
43  Scalar m_shift_t; // Shift constant
44  Matrix3X m_ref_u; // Householder reflectors
45  IntArray m_ref_nr; // How many rows does each reflector affects
46  // 3 - A general reflector
47  // 2 - A Givens rotation
48  // 1 - An identity transformation
49  bool m_computed; // Whether matrix has been factorized
50 
51  // Compute sqrt(x1^2 + x2^2 + x3^2) wit high precision
53  {
54  using std::abs;
55  using std::sqrt;
56 
57  x1 = abs(x1);
58  x2 = abs(x2);
59  x3 = abs(x3);
60  // Make x1 >= {x2, x3}
61  if (x1 < x2)
62  std::swap(x1, x2);
63  if (x1 < x3)
64  std::swap(x1, x3);
65  // If x1 is too small, return 0
66  const Scalar near_0 = TypeTraits<Scalar>::min() * Scalar(10);
67  if (x1 < near_0)
68  return Scalar(0);
69 
70  const Scalar r2 = x2 / x1, r3 = x3 / x1;
71  // We choose a cutoff such that cutoff^4 < eps
72  // If max(r2, r3) > cutoff, use the standard way; otherwise use Taylor series expansion
73  // to avoid an explicit sqrt() call that may lose precision
74  const Scalar eps = TypeTraits<Scalar>::epsilon();
75  const Scalar cutoff = Scalar(0.1) * pow(eps, Scalar(0.25));
76  Scalar r = r2 * r2 + r3 * r3;
77  r = (r2 >= cutoff || r3 >= cutoff) ?
78  sqrt(Scalar(1) + r) :
79  (Scalar(1) + r * (Scalar(0.5) - Scalar(0.125) * r)); // sqrt(1 + t) ~= 1 + t/2 - t^2/8
80  return x1 * r;
81  }
82 
83  // x[i] <- x[i] / r, r = sqrt(x1^2 + x2^2 + x3^2)
84  // Assume |x1| >= {|x2|, |x3|}, x1 != 0
86  {
87  using std::abs;
88  using std::pow;
89  using std::sqrt;
90 
91  const Scalar x1sign = (x1 > Scalar(0)) ? Scalar(1) : Scalar(-1);
92  x1 = abs(x1);
93  // Use the same method as in stable_norm3()
94  const Scalar r2 = x2 / x1, r3 = x3 / x1;
95  const Scalar eps = TypeTraits<Scalar>::epsilon();
96  const Scalar cutoff = Scalar(0.1) * pow(eps, Scalar(0.25));
97  Scalar r = r2 * r2 + r3 * r3;
98  // r = 1/sqrt(1 + r2^2 + r3^2)
99  r = (abs(r2) >= cutoff || abs(r3) >= cutoff) ?
100  Scalar(1) / sqrt(Scalar(1) + r) :
101  (Scalar(1) - r * (Scalar(0.5) - Scalar(0.375) * r)); // 1/sqrt(1 + t) ~= 1 - t * (1/2 - (3/8) * t)
102  x1 = x1sign * r;
103  x2 = r2 * r;
104  x3 = r3 * r;
105  }
106 
107  void compute_reflector(const Scalar& x1, const Scalar& x2, const Scalar& x3, Index ind)
108  {
109  using std::abs;
110 
111  Scalar* u = &m_ref_u.coeffRef(0, ind);
112  unsigned char* nr = m_ref_nr.data();
113  const Scalar x2m = abs(x2), x3m = abs(x3);
114  // If both x2 and x3 are zero, nr is 1, and we early exit
115  if (x2m < m_near_0 && x3m < m_near_0)
116  {
117  nr[ind] = 1;
118  return;
119  }
120 
121  // In general case the reflector affects 3 rows
122  // If x3 is zero, decrease nr by 1
123  nr[ind] = (x3m < m_near_0) ? 2 : 3;
124  const Scalar x_norm = (x3m < m_near_0) ? Eigen::numext::hypot(x1, x2) : stable_norm3(x1, x2, x3);
125 
126  // x1' = x1 - rho * ||x||
127  // rho = -sign(x1), if x1 == 0, we choose rho = 1
128  const Scalar rho = (x1 <= Scalar(0)) - (x1 > Scalar(0));
129  const Scalar x1_new = x1 - rho * x_norm, x1m = abs(x1_new);
130  // Copy x to u
131  u[0] = x1_new;
132  u[1] = x2;
133  u[2] = x3;
134  if (x1m >= x2m && x1m >= x3m)
135  {
136  stable_scaling(u[0], u[1], u[2]);
137  }
138  else if (x2m >= x1m && x2m >= x3m)
139  {
140  stable_scaling(u[1], u[0], u[2]);
141  }
142  else
143  {
144  stable_scaling(u[2], u[0], u[1]);
145  }
146  }
147 
149  {
150  compute_reflector(x[0], x[1], x[2], ind);
151  }
152 
153  // Update the block X = H(il:iu, il:iu)
154  void update_block(Index il, Index iu)
155  {
156  // Block size
157  const Index bsize = iu - il + 1;
158 
159  // If block size == 1, there is no need to apply reflectors
160  if (bsize == 1)
161  {
162  m_ref_nr.coeffRef(il) = 1;
163  return;
164  }
165 
166  const Scalar x00 = m_mat_H.coeff(il, il),
167  x01 = m_mat_H.coeff(il, il + 1),
168  x10 = m_mat_H.coeff(il + 1, il),
169  x11 = m_mat_H.coeff(il + 1, il + 1);
170  // m00 = x00 * (x00 - s) + x01 * x10 + t
171  const Scalar m00 = x00 * (x00 - m_shift_s) + x01 * x10 + m_shift_t;
172  // m10 = x10 * (x00 + x11 - s)
173  const Scalar m10 = x10 * (x00 + x11 - m_shift_s);
174 
175  // For block size == 2, do a Givens rotation on M = X * X - s * X + t * I
176  if (bsize == 2)
177  {
178  // This causes nr=2
179  compute_reflector(m00, m10, 0, il);
180  // Apply the reflector to X
181  apply_PX(m_mat_H.block(il, il, 2, m_n - il), m_n, il);
182  apply_XP(m_mat_H.block(0, il, il + 2, 2), m_n, il);
183 
184  m_ref_nr.coeffRef(il + 1) = 1;
185  return;
186  }
187 
188  // For block size >=3, use the regular strategy
189  // m20 = x21 * x10
190  const Scalar m20 = m_mat_H.coeff(il + 2, il + 1) * m_mat_H.coeff(il + 1, il);
191  compute_reflector(m00, m10, m20, il);
192 
193  // Apply the first reflector
194  apply_PX(m_mat_H.block(il, il, 3, m_n - il), m_n, il);
195  apply_XP(m_mat_H.block(0, il, il + (std::min)(bsize, Index(4)), 3), m_n, il);
196 
197  // Calculate the following reflectors
198  // If entering this loop, block size is at least 4.
199  for (Index i = 1; i < bsize - 2; i++)
200  {
201  compute_reflector(&m_mat_H.coeffRef(il + i, il + i - 1), il + i);
202  // Apply the reflector to X
203  apply_PX(m_mat_H.block(il + i, il + i - 1, 3, m_n - il - i + 1), m_n, il + i);
204  apply_XP(m_mat_H.block(0, il + i, il + (std::min)(bsize, Index(i + 4)), 3), m_n, il + i);
205  }
206 
207  // The last reflector
208  // This causes nr=2
209  compute_reflector(m_mat_H.coeff(iu - 1, iu - 2), m_mat_H.coeff(iu, iu - 2), 0, iu - 1);
210  // Apply the reflector to X
211  apply_PX(m_mat_H.block(iu - 1, iu - 2, 2, m_n - iu + 2), m_n, iu - 1);
212  apply_XP(m_mat_H.block(0, iu - 1, il + bsize, 2), m_n, iu - 1);
213 
214  m_ref_nr.coeffRef(iu) = 1;
215  }
216 
217  // P = I - 2 * u * u' = P'
218  // PX = X - 2 * u * (u'X)
219  void apply_PX(GenericMatrix X, Index stride, Index u_ind) const
220  {
221  const Index nr = m_ref_nr.coeff(u_ind);
222  if (nr == 1)
223  return;
224 
225  const Scalar u0 = m_ref_u.coeff(0, u_ind), u1 = m_ref_u.coeff(1, u_ind);
226  const Scalar u0_2 = Scalar(2) * u0, u1_2 = Scalar(2) * u1;
227 
228  const Index nrow = X.rows();
229  const Index ncol = X.cols();
230 
231  Scalar* xptr = X.data();
232  if (nr == 2 || nrow == 2)
233  {
234  for (Index i = 0; i < ncol; i++, xptr += stride)
235  {
236  const Scalar tmp = u0_2 * xptr[0] + u1_2 * xptr[1];
237  xptr[0] -= tmp * u0;
238  xptr[1] -= tmp * u1;
239  }
240  }
241  else
242  {
243  const Scalar u2 = m_ref_u.coeff(2, u_ind);
244  const Scalar u2_2 = Scalar(2) * u2;
245  for (Index i = 0; i < ncol; i++, xptr += stride)
246  {
247  const Scalar tmp = u0_2 * xptr[0] + u1_2 * xptr[1] + u2_2 * xptr[2];
248  xptr[0] -= tmp * u0;
249  xptr[1] -= tmp * u1;
250  xptr[2] -= tmp * u2;
251  }
252  }
253  }
254 
255  // x is a pointer to a vector
256  // Px = x - 2 * dot(x, u) * u
257  void apply_PX(Scalar* x, Index u_ind) const
258  {
259  const Index nr = m_ref_nr.coeff(u_ind);
260  if (nr == 1)
261  return;
262 
263  const Scalar u0 = m_ref_u.coeff(0, u_ind),
264  u1 = m_ref_u.coeff(1, u_ind),
265  u2 = m_ref_u.coeff(2, u_ind);
266 
267  // When the reflector only contains two elements, u2 has been set to zero
268  const bool nr_is_2 = (nr == 2);
269  const Scalar dot2 = Scalar(2) * (x[0] * u0 + x[1] * u1 + (nr_is_2 ? 0 : (x[2] * u2)));
270  x[0] -= dot2 * u0;
271  x[1] -= dot2 * u1;
272  if (!nr_is_2)
273  x[2] -= dot2 * u2;
274  }
275 
276  // XP = X - 2 * (X * u) * u'
277  void apply_XP(GenericMatrix X, Index stride, Index u_ind) const
278  {
279  const Index nr = m_ref_nr.coeff(u_ind);
280  if (nr == 1)
281  return;
282 
283  const Scalar u0 = m_ref_u.coeff(0, u_ind), u1 = m_ref_u.coeff(1, u_ind);
284  const Scalar u0_2 = Scalar(2) * u0, u1_2 = Scalar(2) * u1;
285 
286  const int nrow = X.rows();
287  const int ncol = X.cols();
288  Scalar *X0 = X.data(), *X1 = X0 + stride; // X0 => X.col(0), X1 => X.col(1)
289 
290  if (nr == 2 || ncol == 2)
291  {
292  // tmp = 2 * u0 * X0 + 2 * u1 * X1
293  // X0 => X0 - u0 * tmp
294  // X1 => X1 - u1 * tmp
295  for (Index i = 0; i < nrow; i++)
296  {
297  const Scalar tmp = u0_2 * X0[i] + u1_2 * X1[i];
298  X0[i] -= tmp * u0;
299  X1[i] -= tmp * u1;
300  }
301  }
302  else
303  {
304  Scalar* X2 = X1 + stride; // X2 => X.col(2)
305  const Scalar u2 = m_ref_u.coeff(2, u_ind);
306  const Scalar u2_2 = Scalar(2) * u2;
307  for (Index i = 0; i < nrow; i++)
308  {
309  const Scalar tmp = u0_2 * X0[i] + u1_2 * X1[i] + u2_2 * X2[i];
310  X0[i] -= tmp * u0;
311  X1[i] -= tmp * u1;
312  X2[i] -= tmp * u2;
313  }
314  }
315  }
316 
317 public:
319  m_n(size),
320  m_computed(false)
321  {}
322 
324  m_n(mat.rows()),
325  m_mat_H(m_n, m_n),
326  m_shift_s(s),
327  m_shift_t(t),
328  m_ref_u(3, m_n),
329  m_ref_nr(m_n),
330  m_computed(false)
331  {
332  compute(mat, s, t);
333  }
334 
335  void compute(ConstGenericMatrix& mat, const Scalar& s, const Scalar& t)
336  {
337  using std::abs;
338 
339  m_n = mat.rows();
340  if (m_n != mat.cols())
341  throw std::invalid_argument("DoubleShiftQR: matrix must be square");
342 
343  m_mat_H.resize(m_n, m_n);
344  m_shift_s = s;
345  m_shift_t = t;
346  m_ref_u.resize(3, m_n);
348 
349  // Make a copy of mat
350  m_mat_H.noalias() = mat;
351 
352  // Obtain the indices of zero elements in the subdiagonal,
353  // so that H can be divided into several blocks
354  const Scalar eps_abs = m_near_0 * (m_n / m_eps);
355  const Scalar eps_rel = m_eps;
356  std::vector<int> zero_ind;
357  zero_ind.reserve(m_n - 1);
358  zero_ind.push_back(0);
359  Scalar* Hii = m_mat_H.data();
360  for (Index i = 0; i < m_n - 1; i++, Hii += (m_n + 1))
361  {
362  // Hii[0] => m_mat_H(i, i)
363  // Hii[1] => m_mat_H(i + 1, i)
364  // Hii[m_n + 1] => m_mat_H(i + 1, i + 1)
365  const Scalar h = abs(Hii[1]);
366  // Deflate small sub-diagonal elements
367  const Scalar diag = abs(Hii[0]) + abs(Hii[m_n + 1]);
368  if (h <= eps_abs || h <= eps_rel * diag)
369  {
370  Hii[1] = 0;
371  zero_ind.push_back(i + 1);
372  }
373  // Make sure m_mat_H is upper Hessenberg
374  // Zero the elements below m_mat_H(i + 1, i)
375  std::fill(Hii + 2, Hii + m_n - i, Scalar(0));
376  }
377  zero_ind.push_back(m_n);
378 
379  const Index len = zero_ind.size() - 1;
380  for (Index i = 0; i < len; i++)
381  {
382  const Index start = zero_ind[i];
383  const Index end = zero_ind[i + 1] - 1;
384  // Compute refelctors and update each block
385  update_block(start, end);
386  }
387 
388  // Deflation on the computed result
389  Hii = m_mat_H.data();
390  for (Index i = 0; i < m_n - 1; i++, Hii += (m_n + 1))
391  {
392  const Scalar h = abs(Hii[1]);
393  const Scalar diag = abs(Hii[0]) + abs(Hii[m_n + 1]);
394  if (h <= eps_abs || h <= eps_rel * diag)
395  Hii[1] = 0;
396  }
397 
398  m_computed = true;
399  }
400 
401  void matrix_QtHQ(Matrix& dest) const
402  {
403  if (!m_computed)
404  throw std::logic_error("DoubleShiftQR: need to call compute() first");
405 
406  dest.noalias() = m_mat_H;
407  }
408 
409  // Q = P0 * P1 * ...
410  // Q'y = P_{n-2} * ... * P1 * P0 * y
411  void apply_QtY(Vector& y) const
412  {
413  if (!m_computed)
414  throw std::logic_error("DoubleShiftQR: need to call compute() first");
415 
416  Scalar* y_ptr = y.data();
417  const Index n1 = m_n - 1;
418  for (Index i = 0; i < n1; i++, y_ptr++)
419  {
420  apply_PX(y_ptr, i);
421  }
422  }
423 
424  // Q = P0 * P1 * ...
425  // YQ = Y * P0 * P1 * ...
427  {
428  if (!m_computed)
429  throw std::logic_error("DoubleShiftQR: need to call compute() first");
430 
431  const Index nrow = Y.rows();
432  const Index n2 = m_n - 2;
433  for (Index i = 0; i < n2; i++)
434  {
435  apply_XP(Y.block(0, i, nrow, 3), nrow, i);
436  }
437  apply_XP(Y.block(0, n2, nrow, 2), nrow, n2);
438  }
439 };
440 
441 } // namespace Spectra
442 
443 #endif // SPECTRA_DOUBLE_SHIFT_QR_H
ind
std::vector< int > ind
Definition: Slicing_stdvector_cxx11.cpp:1
Spectra::DoubleShiftQR::m_computed
bool m_computed
Definition: DoubleShiftQR.h:49
gtsam::utils.numerical_derivative.X2
X2
Definition: numerical_derivative.py:26
benchmark.n1
n1
Definition: benchmark.py:79
Spectra::DoubleShiftQR
Definition: DoubleShiftQR.h:22
s
RealScalar s
Definition: level1_cplx_impl.h:126
r2
static const double r2
Definition: testSmartRangeFactor.cpp:32
Spectra::DoubleShiftQR::m_shift_t
Scalar m_shift_t
Definition: DoubleShiftQR.h:43
Spectra::DoubleShiftQR::stable_norm3
static Scalar stable_norm3(Scalar x1, Scalar x2, Scalar x3)
Definition: DoubleShiftQR.h:52
gtsam::Y
GaussianFactorGraphValuePair Y
Definition: HybridGaussianProductFactor.cpp:29
Spectra::DoubleShiftQR::apply_XP
void apply_XP(GenericMatrix X, Index stride, Index u_ind) const
Definition: DoubleShiftQR.h:277
gtsam::diag
Matrix diag(const std::vector< Matrix > &Hs)
Definition: Matrix.cpp:196
Spectra::DoubleShiftQR::m_n
Index m_n
Definition: DoubleShiftQR.h:40
x
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
Definition: gnuplot_common_settings.hh:12
Spectra::DoubleShiftQR::compute_reflector
void compute_reflector(const Scalar &x1, const Scalar &x2, const Scalar &x3, Index ind)
Definition: DoubleShiftQR.h:107
Spectra::DoubleShiftQR::m_ref_nr
IntArray m_ref_nr
Definition: DoubleShiftQR.h:45
Spectra::DoubleShiftQR::compute
void compute(ConstGenericMatrix &mat, const Scalar &s, const Scalar &t)
Definition: DoubleShiftQR.h:335
Eigen::Array< unsigned char, Eigen::Dynamic, 1 >
X
#define X
Definition: icosphere.cpp:20
Spectra::DoubleShiftQR::DoubleShiftQR
DoubleShiftQR(Index size)
Definition: DoubleShiftQR.h:318
mat
MatrixXf mat
Definition: Tutorial_AdvancedInitialization_CommaTemporary.cpp:1
h
const double h
Definition: testSimpleHelicopter.cpp:19
Eigen::PlainObjectBase::resize
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:271
Spectra::DoubleShiftQR::apply_YQ
void apply_YQ(GenericMatrix Y) const
Definition: DoubleShiftQR.h:426
rows
int rows
Definition: Tutorial_commainit_02.cpp:1
x3
Pose3 x3(Rot3::Ypr(M_PI/4.0, 0.0, 0.0), l2)
size
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
epsilon
static double epsilon
Definition: testRot3.cpp:37
Spectra::DoubleShiftQR::Index
Eigen::Index Index
Definition: DoubleShiftQR.h:25
Spectra::DoubleShiftQR::matrix_QtHQ
void matrix_QtHQ(Matrix &dest) const
Definition: DoubleShiftQR.h:401
Spectra::DoubleShiftQR::compute_reflector
void compute_reflector(const Scalar *x, Index ind)
Definition: DoubleShiftQR.h:148
benchmark.n2
n2
Definition: benchmark.py:85
Spectra::DoubleShiftQR::stable_scaling
static void stable_scaling(Scalar &x1, Scalar &x2, Scalar &x3)
Definition: DoubleShiftQR.h:85
x1
Pose3 x1
Definition: testPose3.cpp:663
Spectra::DoubleShiftQR::update_block
void update_block(Index il, Index iu)
Definition: DoubleShiftQR.h:154
std::swap
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)
Definition: NearestNeighbor.hpp:827
Spectra::DoubleShiftQR::m_eps
const Scalar m_eps
Definition: DoubleShiftQR.h:38
r3
static const double r3
Definition: testSmartRangeFactor.cpp:32
Spectra::DoubleShiftQR::m_shift_s
Scalar m_shift_s
Definition: DoubleShiftQR.h:42
u2
Vector u2
Definition: testSimpleHelicopter.cpp:32
Eigen::Matrix::coeffRef
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar & coeffRef(Index rowId, Index colId)
Definition: PlainObjectBase.h:175
Eigen::Array::coeff
EIGEN_DEVICE_FUNC const EIGEN_STRONG_INLINE Scalar & coeff(Index rowId, Index colId) const
Definition: PlainObjectBase.h:152
ceres::pow
Jet< T, N > pow(const Jet< T, N > &f, double g)
Definition: jet.h:570
Spectra::DoubleShiftQR::apply_PX
void apply_PX(Scalar *x, Index u_ind) const
Definition: DoubleShiftQR.h:257
Spectra::DoubleShiftQR::m_near_0
const Scalar m_near_0
Definition: DoubleShiftQR.h:36
y
Scalar * y
Definition: level1_cplx_impl.h:124
u0
static const double u0
Definition: testCal3DFisheye.cpp:31
gtsam::utils.numerical_derivative.X1
X1
Definition: numerical_derivative.py:25
Eigen::Array::coeffRef
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar & coeffRef(Index rowId, Index colId)
Definition: PlainObjectBase.h:175
Eigen::Ref
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:281
Spectra::DoubleShiftQR::apply_PX
void apply_PX(GenericMatrix X, Index stride, Index u_ind) const
Definition: DoubleShiftQR.h:219
Spectra::DoubleShiftQR::m_ref_u
Matrix3X m_ref_u
Definition: DoubleShiftQR.h:44
Eigen::PlainObjectBase::coeff
EIGEN_DEVICE_FUNC const EIGEN_STRONG_INLINE Scalar & coeff(Index rowId, Index colId) const
Definition: PlainObjectBase.h:152
Spectra
Definition: LOBPCGSolver.h:19
Eigen::PlainObjectBase::data
EIGEN_DEVICE_FUNC const EIGEN_STRONG_INLINE Scalar * data() const
Definition: PlainObjectBase.h:247
min
#define min(a, b)
Definition: datatypes.h:19
Spectra::DoubleShiftQR::DoubleShiftQR
DoubleShiftQR(ConstGenericMatrix &mat, const Scalar &s, const Scalar &t)
Definition: DoubleShiftQR.h:323
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic >
abs
#define abs(x)
Definition: datatypes.h:17
len
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2446
Eigen::placeholders::end
static const EIGEN_DEPRECATED end_t end
Definition: IndexedViewHelper.h:181
align_3::t
Point2 t(10, 10)
Spectra::DoubleShiftQR::m_mat_H
Matrix m_mat_H
Definition: DoubleShiftQR.h:41
Spectra::DoubleShiftQR::apply_QtY
void apply_QtY(Vector &y) const
Definition: DoubleShiftQR.h:411
x2
Pose3 x2(Rot3::Ypr(0.0, 0.0, 0.0), l2)
ceres::sqrt
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Scalar
SCALAR Scalar
Definition: bench_gemm.cpp:46
Eigen::Index
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:74


gtsam
Author(s):
autogenerated on Sun Feb 16 2025 04:01:18