Graphite Version 3
An experimental 3D geometry processing program
Loading...
Searching...
No Matches
matrix.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40#ifndef GEOGRAM_BASIC_MATRIX
41#define GEOGRAM_BASIC_MATRIX
42
44#include <geogram/basic/vecg.h>
45#include <initializer_list>
46
52namespace GEO {
53
54 /************************************************************************/
55
56
65 template <index_t DIM, class FT>
66 class Matrix {
67 public:
70
72 typedef FT value_type;
73
75 static constexpr index_t dim = DIM;
76
82 inline Matrix() {
84 }
85
92 explicit Matrix(const FT* vals) {
93 for(index_t i = 0; i < DIM; i++) {
94 for(index_t j = 0; j < DIM; j++) {
95 coeff_[i][j] = *vals;
96 ++vals;
97 }
98 }
99 }
100
105 Matrix(const std::initializer_list< std::initializer_list<FT> >& Mi) {
106 index_t i = 0;
107 for(auto& it: Mi) {
108 index_t j = 0;
109 for(auto& jt: it) {
110 geo_debug_assert(i < DIM);
111 geo_debug_assert(j < DIM);
112 coeff_[i][j] = jt;
113 ++j;
114 }
115 ++i;
116 }
117 }
118
119
124 inline index_t dimension() const {
125 return DIM;
126 }
127
132 inline void load_zero() {
133 for(index_t i = 0; i < DIM; i++) {
134 for(index_t j = 0; j < DIM; j++) {
135 coeff_[i][j] = FT(0);
136 }
137 }
138 }
139
145 inline void load_identity() {
146 for(index_t i = 0; i < DIM; i++) {
147 for(index_t j = 0; j < DIM; j++) {
148 coeff_[i][j] = (i == j) ? FT(1) : FT(0);
149 }
150 }
151 }
152
158 inline bool is_identity() const {
159 for(index_t i = 0; i < DIM; i++) {
160 for(index_t j = 0; j < DIM; j++) {
161 FT rhs = ((i == j) ? FT(1) : FT(0));
162 if(coeff_[i][j] != rhs) {
163 return false;
164 }
165 }
166 }
167 return true;
168 }
169
178 inline FT& operator() (index_t i, index_t j) {
179 geo_debug_assert(i < DIM);
180 geo_debug_assert(j < DIM);
181 return coeff_[i][j];
182 }
183
192 inline const FT& operator() (index_t i, index_t j) const {
193 geo_debug_assert(i < DIM);
194 geo_debug_assert(j < DIM);
195 return coeff_[i][j];
196 }
197
205 for(index_t i = 0; i < DIM; i++) {
206 for(index_t j = 0; j < DIM; j++) {
207 coeff_[i][j] += m.coeff_[i][j];
208 }
209 }
210 return *this;
211 }
212
220 for(index_t i = 0; i < DIM; i++) {
221 for(index_t j = 0; j < DIM; j++) {
222 coeff_[i][j] -= m.coeff_[i][j];
223 }
224 }
225 return *this;
226 }
227
235 inline matrix_type& operator*= (FT val) {
236 for(index_t i = 0; i < DIM; i++) {
237 for(index_t j = 0; j < DIM; j++) {
238 coeff_[i][j] *= val;
239 }
240 }
241 return *this;
242 }
243
251 inline matrix_type& operator/= (FT val) {
252 for(index_t i = 0; i < DIM; i++) {
253 for(index_t j = 0; j < DIM; j++) {
254 coeff_[i][j] /= val;
255 }
256 }
257 return *this;
258 }
259
266 inline matrix_type operator+ (const matrix_type& m) const {
267 matrix_type result = *this;
268 result += m;
269 return result;
270 }
271
278 inline matrix_type operator- (const matrix_type& m) const {
279 matrix_type result = *this;
280 result -= m;
281 return result;
282 }
283
291 inline matrix_type operator* (FT val) const {
292 matrix_type result = *this;
293 result *= val;
294 return result;
295 }
296
304 inline matrix_type operator/ (FT val) const {
305 matrix_type result = *this;
306 result /= val;
307 return result;
308 }
309
318 matrix_type result;
319 for(index_t i = 0; i < DIM; i++) {
320 for(index_t j = 0; j < DIM; j++) {
321 result.coeff_[i][j] = FT(0);
322 for(index_t k = 0; k < DIM; k++) {
323 result.coeff_[i][j] += coeff_[i][k] * m.coeff_[k][j];
324 }
325 }
326 }
327 return result;
328 }
329
336 matrix_type result;
337 bool invertible = compute_inverse(result);
338 geo_assert(invertible);
339 return result;
340 }
341
342
353 matrix_type& result, value_type min_val = value_type(0)
354 ) const {
355 FT val=FT(0.0), val2=FT(0.0);
356 matrix_type tmp = (*this);
357
358 result.load_identity();
359
360 for(index_t i = 0; i != DIM; i++) {
361 val = tmp(i, i); /* find pivot */
362 index_t ind = i;
363 for(index_t j = i + 1; j != DIM; j++) {
364 if(fabs(tmp(j, i)) > fabs(val)) {
365 ind = j;
366 val = tmp(j, i);
367 }
368 }
369
370 if(ind != i) {
371 for(index_t j = 0; j != DIM; j++) {
372 val2 = result(i, j);
373 result(i, j) = result(ind, j);
374 result(ind, j) = val2; /* swap columns */
375 val2 = tmp(i, j);
376 tmp(i, j) = tmp(ind, j);
377 tmp(ind, j) = val2;
378 }
379 }
380
381 if(abs(val) <= min_val) {
382 return false;
383 }
384
385 for(index_t j = 0; j != DIM; j++) {
386 tmp(i, j) /= val;
387 result(i, j) /= val;
388 }
389
390 for(index_t j = 0; j != DIM; j++) {
391 if(j == i) {
392 continue; /* eliminate column */
393 }
394 val = tmp(j, i);
395 for(index_t k = 0; k != DIM; k++) {
396 tmp(j, k) -= tmp(i, k) * val;
397 result(j, k) -= result(i, k) * val;
398 }
399 }
400 }
401
402 return true;
403 }
404
410 matrix_type result;
411 for(index_t i = 0; i < DIM; i++) {
412 for(index_t j = 0; j < DIM; j++) {
413 result(i, j) = (* this)(j, i);
414 }
415 }
416 return result;
417 }
418
425 inline const FT* data() const {
426 return &(coeff_[0][0]);
427 }
428
435 inline FT* data() {
436 return &(coeff_[0][0]);
437 }
438
446 void get_lower_triangle(FT* store) const {
447 for(index_t i = 0; i < DIM; i++) {
448 for(index_t j = 0; j <= i; j++) {
449 *store++ = coeff_[i][j];
450 }
451 }
452 }
453
454 private:
455 FT coeff_[DIM][DIM];
456 };
457
458 /************************************************************************/
459
469 template <index_t DIM, class FT>
470 inline std::ostream& operator<< (
471 std::ostream& output, const Matrix<DIM, FT>& m
472 ) {
473 const char* sep = "";
474 for(index_t i = 0; i < DIM; i++) {
475 for(index_t j = 0; j < DIM; j++) {
476 output << sep << m(i, j);
477 sep = " ";
478 }
479 }
480 return output;
481 }
482
492 template <index_t DIM, class FT>
493 inline std::istream& operator>> (
494 std::istream& input, Matrix<DIM, FT>& m
495 ) {
496 for(index_t i = 0; i < DIM; i++) {
497 for(index_t j = 0; j < DIM; j++) {
498 input >> m(i, j);
499 }
500 }
501 return input;
502 }
503
504 /************************************************************************/
505
519 template <index_t DIM, class FT> inline
520 void mult(const Matrix<DIM, FT>& M, const FT* x, FT* y) {
521 for(index_t i = 0; i < DIM; i++) {
522 y[i] = 0;
523 for(index_t j = 0; j < DIM; j++) {
524 y[i] += M(i, j) * x[j];
525 }
526 }
527 }
528
529 /************************************************************************/
530
539 template <index_t DIM, class FT> inline
541 const Matrix<DIM, FT>& M, const vecng<DIM,FT>& x
542 ) {
544 for(index_t i = 0; i < DIM; i++) {
545 y[i] = 0;
546 for(index_t j = 0; j < DIM; j++) {
547 y[i] += M(i, j) * x[j];
548 }
549 }
550 return y;
551 }
552
553 /************************************************************************/
554
563 template <index_t DIM, class FT> inline
565 const vecng<DIM,FT>& x, const Matrix<DIM, FT>& M
566 ) {
568 for(index_t i = 0; i < DIM; i++) {
569 y[i] = 0;
570 for(index_t j = 0; j < DIM; j++) {
571 y[i] += M(j, i) * x[j];
572 }
573 }
574 return y;
575 }
576
577
578 /************************************************************************/
579
580#ifndef GOMGEN
581
590 template <index_t DIM, class FT>
591 [[deprecated("use operator*(matrix, vector) instead")]]
593 const Matrix<DIM, FT>& M, const vecng<DIM,FT>& x
594 ) {
596 for(index_t i = 0; i < DIM; i++) {
597 y[i] = 0;
598 for(index_t j = 0; j < DIM; j++) {
599 y[i] += M(i, j) * x[j];
600 }
601 }
602 return y;
603 }
604
605#endif
606
607 /************************************************************************/
608
609}
610
611#endif
#define geo_assert(x)
Verifies that a condition is met.
Definition assert.h:149
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
A matrix type.
Definition matrix.h:66
bool compute_inverse(matrix_type &result, value_type min_val=value_type(0)) const
Computes the inverse matrix.
Definition matrix.h:352
matrix_type transpose() const
Computes the transposed matrix.
Definition matrix.h:409
matrix_type & operator*=(FT val)
Multiplies by a scalar in place.
Definition matrix.h:235
void get_lower_triangle(FT *store) const
Gets the lower triangle of the matrix.
Definition matrix.h:446
matrix_type & operator-=(const matrix_type &m)
Subtracts a matrix in place.
Definition matrix.h:219
Matrix(const FT *vals)
Constructs a matrix from an array of values.
Definition matrix.h:92
FT value_type
Definition matrix.h:72
index_t dimension() const
Gets the matrix dimension.
Definition matrix.h:124
Matrix< DIM, FT > matrix_type
Definition matrix.h:69
matrix_type operator+(const matrix_type &m) const
Adds 2 matrices.
Definition matrix.h:266
const FT * data() const
Gets non-modifiable matrix data.
Definition matrix.h:425
FT & operator()(index_t i, index_t j)
Gets a modifiable element.
Definition matrix.h:178
matrix_type operator*(FT val) const
Multiplies a matrix by a scalar.
Definition matrix.h:291
void load_zero()
Clears the matrix.
Definition matrix.h:132
matrix_type & operator/=(FT val)
Divides by a scalar in place.
Definition matrix.h:251
Matrix(const std::initializer_list< std::initializer_list< FT > > &Mi)
Constructs a matrix from 2d array of initializers.
Definition matrix.h:105
bool is_identity() const
Tests whether a matrix is the identity matrix.
Definition matrix.h:158
matrix_type operator-(const matrix_type &m) const
Subtracts 2 matrices.
Definition matrix.h:278
void mult(const Matrix< DIM, FT > &M, const FT *x, FT *y)
Multiplies a matrix by a vector.
Definition matrix.h:520
FT * data()
Gets modifiable matrix data.
Definition matrix.h:435
matrix_type inverse() const
Computes the inverse matrix.
Definition matrix.h:335
void load_identity()
Sets the matrix to identity.
Definition matrix.h:145
Matrix()
Default constructor.
Definition matrix.h:82
static constexpr index_t dim
Definition matrix.h:75
matrix_type & operator+=(const matrix_type &m)
Adds a matrix in place.
Definition matrix.h:204
matrix_type operator/(FT val) const
Divides a matrix by a scalar.
Definition matrix.h:304
Generic maths vector.
Definition vecg.h:74
Common include file, providing basic definitions. Should be included before anything else by all head...
Global Vorpaline namespace.
std::istream & operator>>(std::istream &in, Quaternion &q)
Reads a Quaternion from a stream.
Definition quaternion.h:225
std::ostream & operator<<(std::ostream &out, const Quaternion &q)
Writes a Quaternion to a stream.
Definition quaternion.h:213
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:340
vecng< DIM, FT > mult(const Matrix< DIM, FT > &M, const vecng< DIM, FT > &x)
Computes a matrix vector product.
Definition matrix.h:592
vecng< DIM, FT > operator*(const Matrix< DIM, FT > &M, const vecng< DIM, FT > &x)
Computes a matrix vector product.
Definition matrix.h:540
Generic implementation of geometric vectors.