LinearAlgebra.cpp
Go to the documentation of this file.
1 // (C) Copyright Renaud Detry 2007-2015.
2 // Distributed under the GNU General Public License and under the
3 // BSD 3-Clause License (See accompanying file LICENSE.txt).
4 
5 /** @file */
6 
7 #include <boost/algorithm/string.hpp>
8 
9 #include <gsl/gsl_math.h>
10 #include <gsl/gsl_eigen.h>
11 #include <gsl/gsl_linalg.h>
12 
13 #include <nuklei/LinearAlgebra.h>
14 
15 namespace nuklei
16 {
17 
18  namespace la
19  {
20  void eigenDecomposition(Matrix3 &eVectors, Vector3& eValues, const Matrix3& sym)
21  {
22  coord_t data[9];
23  for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j)
24  data[i*3+j] = sym(i,j);
25 
26  gsl_matrix_view m
27  = gsl_matrix_view_array (data, 3, 3);
28 
29  gsl_vector *eval = gsl_vector_alloc (3);
30  gsl_matrix *evec = gsl_matrix_alloc (3, 3);
31 
32  gsl_eigen_symmv_workspace * w =
33  gsl_eigen_symmv_alloc (3);
34 
35  gsl_eigen_symmv (&m.matrix, eval, evec, w);
36 
37  gsl_eigen_symmv_free (w);
38 
39  gsl_eigen_symmv_sort (eval, evec,
40  GSL_EIGEN_SORT_ABS_DESC);
41 
42  for (int i = 0; i < 3; i++)
43  {
44  eValues[i]
45  = gsl_vector_get (eval, i);
46  //NUKLEI_ASSERT(eValues[i] >= 0);
47  gsl_vector_view evec_i
48  = gsl_matrix_column (evec, i);
49  for (int j = 0; j < 3; ++j)
50  eVectors(j, i) = gsl_vector_get(&evec_i.vector, j);
51  }
52 
53  // There should be a more efficient way to do this...
54  if (Vector3(eVectors.GetColumn(0)).Cross(eVectors.GetColumn(1)).Dot(eVectors.GetColumn(2)) < 0)
55  eVectors.SetColumn(2, -Vector3(eVectors.GetColumn(2)));
56 
57  gsl_vector_free (eval);
58  gsl_matrix_free (evec);
59  }
60 
61  // The following function
62  // Vector3 project(const Plane3& plane, const Vector3& point)
63  // is currently defined in KernelCollectionPCA.cpp
64 
65 
66  double determinant(const GMatrix& m)
67  {
68  NUKLEI_FAST_ASSERT(m.GetRows() == m.GetColumns());
69  const int dim = m.GetRows();
70 
71  gsl_matrix *lu;
72  gsl_permutation *perm;
73  int signum = 0;
74 
75  lu = gsl_matrix_alloc(dim, dim);
76  perm = gsl_permutation_alloc(dim);
77 
78  for (int i = 0; i < dim; ++i)
79  for (int j = 0; j < dim; ++j)
80  {
81  gsl_matrix_set(lu, i, j, m(i,j));
82  }
83 
84  gsl_linalg_LU_decomp(lu, perm, &signum);
85  double det = gsl_linalg_LU_det(lu, signum);
86 
87  gsl_matrix_free(lu);
88  gsl_permutation_free(perm);
89 
90  return det;
91  }
92 
93  GMatrix inverse(const GMatrix& m)
94  {
95  NUKLEI_FAST_ASSERT(m.GetRows() == m.GetColumns());
96  const int dim = m.GetRows();
97 
98  gsl_matrix *lu, *inverse;
99  gsl_permutation *perm;
100  int signum = 0;
101 
102  lu = gsl_matrix_alloc(dim, dim);
103  inverse = gsl_matrix_alloc(dim, dim);
104  perm = gsl_permutation_alloc(dim);
105 
106  for (int i = 0; i < dim; ++i)
107  for (int j = 0; j < dim; ++j)
108  {
109  gsl_matrix_set(lu, i, j, m(i,j));
110  }
111 
112  gsl_linalg_LU_decomp(lu, perm, &signum);
113  gsl_linalg_LU_invert(lu, perm, inverse);
114 
115  GMatrix inv(dim, dim);
116  for (int i = 0; i < dim; ++i)
117  for (int j = 0; j < dim; ++j)
118  {
119  inv(i,j) = gsl_matrix_get(inverse, i, j);
120  }
121 
122  gsl_matrix_free(lu);
123  gsl_matrix_free(inverse);
124  gsl_permutation_free(perm);
125 
126  return inv;
127  }
128 
129  }
130 
131  std::ostream& operator<<(std::ostream &out, const GMatrix &m)
132  {
133  for (int i = 0; i < m.GetRows(); ++i)
134  {
135  for (int j = 0; j < m.GetColumns(); ++j)
136  NUKLEI_ASSERT(out << m(i,j) << " ");
137  NUKLEI_ASSERT(out << "\n");
138  }
139  out << std::flush;
140  return out;
141  }
142 
143  std::istream& operator>>(std::istream &in, GMatrix &m)
144  {
145  std::vector< std::vector<double> > rows;
146  std::string line;
147  int ntok = -1;
148  while (std::getline(in, line))
149  {
150  cleanLine(line);
151  std::vector<std::string> tokens;
152  boost::split(tokens, line, boost::is_any_of(" "), boost::token_compress_on);
153  if (tokens.front() == "")
154  tokens.erase(tokens.begin());
155  if (tokens.back() == "")
156  tokens.pop_back();
157 
158  if (ntok == -1)
159  ntok = tokens.size();
160  else
161  NUKLEI_ASSERT(ntok == tokens.size());
162 
163  if (tokens.size() == 0)
164  break;
165 
166  rows.push_back(std::vector<double>());
167  for (std::vector<std::string>::const_iterator i = tokens.begin();
168  i != tokens.end(); ++i)
169  rows.back().push_back(numify<double>(*i));
170  }
171 
172  m.SetSize(rows.size(), ntok);
173  for (int i = 0; i < m.GetRows(); ++i)
174  for (int j = 0; j < m.GetColumns(); ++j)
175  m(i,j) = rows.at(i).at(j);
176 
177  return in;
178  }
179 
180 
181 }
Public namespace.
Definition: Color.cpp:9
#define NUKLEI_ASSERT(expression)
Throws an Error if expression is not true.
Definition: Common.h:113
double coord_t
Type for point coordinates.
Definition: Definitions.h:25
© Copyright 2007-2013 Renaud Detry.
Distributed under the terms of the GNU General Public License (GPL).
(See accompanying file LICENSE.txt or copy at http://www.gnu.org/copyleft/gpl.html.)
Revised Sun Sep 13 2020 19:10:06.