Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpMatrix_operators.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Stack matrix.
32 */
33
34#include <visp3/core/vpConfig.h>
35#include <visp3/core/vpMatrix.h>
36
37#if defined(VISP_HAVE_SIMDLIB)
38#include <Simd/SimdLib.h>
39#endif
40
42
60{
61 resize(A.getRows(), A.getCols(), false, false);
62
63 if ((data != nullptr) && (A.data != nullptr) && (data != A.data)) {
64 memcpy(data, A.data, dsize * sizeof(double));
65 }
66
67 return *this;
68}
69
83{
84 resize(M.getRows(), M.getCols(), false, false);
85
86 if ((data != nullptr) && (M.data != nullptr) && (data != M.data)) {
87 memcpy(data, M.data, dsize * sizeof(double));
88 }
89
90 return *this;
91}
92
106{
107 resize(R.getRows(), R.getCols(), false, false);
108
109 if ((data != nullptr) && (R.data != nullptr) && (data != R.data)) {
110 memcpy(data, R.data, dsize * sizeof(double));
111 }
112
113 return *this;
114}
115
129{
130 resize(V.getRows(), V.getCols(), false, false);
131
132 if ((data != nullptr) && (V.data != nullptr) && (data != V.data)) {
133 memcpy(data, V.data, dsize * sizeof(double));
134 }
135
136 return *this;
137}
138
152{
153 resize(F.getRows(), F.getCols(), false, false);
154
155 if ((data != nullptr) && (F.data != nullptr) && (data != F.data)) {
156 memcpy(data, F.data, dsize * sizeof(double));
157 }
158
159 return *this;
160}
161
175{
176 resize(v.getRows(), v.getCols(), false, false);
177
178 if ((data != nullptr) && (v.data != nullptr) && (data != v.data)) {
179 memcpy(data, v.data, dsize * sizeof(double));
180 }
181
182 return *this;
183}
184
198{
199 resize(v.getRows(), v.getCols(), false, false);
200
201 if ((data != nullptr) && (v.data != nullptr) && (data != v.data)) {
202 memcpy(data, v.data, dsize * sizeof(double));
203 }
204
205 return *this;
206}
207
221{
222 resize(t.getRows(), t.getCols(), false, false);
223
224 if ((data != nullptr) && (t.data != nullptr) && (data != t.data)) {
225 memcpy(data, t.data, dsize * sizeof(double));
226 }
227
228 return *this;
229}
230
232{
233 resize(A.getRows(), A.getCols(), false, false);
234
235 if ((data != nullptr) && (A.data != nullptr) && (data != A.data)) {
236 memcpy(data, A.data, dsize * sizeof(double));
237 }
238
239 return *this;
240}
241
242#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
244{
245 vpArray2D<double>::operator=(std::move(other));
246 return *this;
247}
248
279vpMatrix &vpMatrix::operator=(const std::initializer_list<double> &list)
280{
281 if (dsize != static_cast<unsigned int>(list.size())) {
282 resize(1, static_cast<unsigned int>(list.size()), false, false);
283 }
284
285 std::copy(list.begin(), list.end(), data);
286
287 return *this;
288}
289
317vpMatrix &vpMatrix::operator=(const std::initializer_list<std::initializer_list<double> > &lists)
318{
319 unsigned int nrows = static_cast<unsigned int>(lists.size()), ncols = 0;
320 for (auto &l : lists) {
321 if (static_cast<unsigned int>(l.size()) > ncols) {
322 ncols = static_cast<unsigned int>(l.size());
323 }
324 }
325
326 resize(nrows, ncols, false, false);
327 auto it = lists.begin();
328 for (unsigned int i = 0; i < rowNum; ++i, ++it) {
329 std::copy(it->begin(), it->end(), rowPtrs[i]);
330 }
331
332 return *this;
333}
334#endif
335
338{
339 std::fill(data, data + (rowNum * colNum), x);
340 return *this;
341}
342
349{
350 for (unsigned int i = 0; i < rowNum; ++i) {
351 for (unsigned int j = 0; j < colNum; ++j) {
352 rowPtrs[i][j] = *x++;
353 }
354 }
355 return *this;
356}
357
359{
360 resize(1, 1, false, false);
361 rowPtrs[0][0] = val;
362 return *this;
363}
364
366{
367 resize(1, colNum + 1, false, false);
368 rowPtrs[0][colNum - 1] = val;
369 return *this;
370}
371
377{
379
380 const unsigned int val_3 = 3;
381 if ((rowNum != val_3) || (colNum != val_3)) {
382 throw(vpException(vpException::dimensionError, "Cannot multiply a (%dx%d) matrix by a (%dx%d) translation vector",
383 rowNum, colNum, tv.getRows(), tv.getCols()));
384 }
385
386 for (unsigned int j = 0; j < val_3; ++j) {
387 t_out[j] = 0;
388 }
389
390 for (unsigned int j = 0; j < val_3; ++j) {
391 double tj = tv[j]; // optimization em 5/12/2006
392 for (unsigned int i = 0; i < val_3; ++i) {
393 t_out[i] += rowPtrs[i][j] * tj;
394 }
395 }
396 return t_out;
397}
398
404{
405 vpColVector v_out;
406 vpMatrix::multMatrixVector(*this, v, v_out);
407 return v_out;
408}
409
415{
416 vpMatrix C;
417
418 vpMatrix::mult2Matrices(*this, B, C);
419
420 return C;
421}
422
428{
429 if (colNum != R.getRows()) {
430 throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (3x3) rotation matrix", rowNum,
431 colNum));
432 }
433 vpMatrix C;
434 const unsigned int val_3 = 3;
435 C.resize(rowNum, val_3, false, false);
436
437 unsigned int RcolNum = R.getCols();
438 unsigned int RrowNum = R.getRows();
439 for (unsigned int i = 0; i < rowNum; ++i) {
440 double *rowptri = rowPtrs[i];
441 double *ci = C[i];
442 for (unsigned int j = 0; j < RcolNum; ++j) {
443 double s = 0;
444 for (unsigned int k = 0; k < RrowNum; ++k) {
445 s += rowptri[k] * R[k][j];
446 }
447 ci[j] = s;
448 }
449 }
450
451 return C;
452}
453
459{
460 if (colNum != M.getRows()) {
461 throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (3x3) rotation matrix", rowNum,
462 colNum));
463 }
464 vpMatrix C;
465 const unsigned int val_4 = 4;
466 C.resize(rowNum, val_4, false, false);
467
468 const unsigned int McolNum = M.getCols();
469 const unsigned int MrowNum = M.getRows();
470 for (unsigned int i = 0; i < rowNum; ++i) {
471 const double *rowptri = rowPtrs[i];
472 double *ci = C[i];
473 for (unsigned int j = 0; j < McolNum; ++j) {
474 double s = 0;
475 for (unsigned int k = 0; k < MrowNum; ++k) {
476 s += rowptri[k] * M[k][j];
477 }
478 ci[j] = s;
479 }
480 }
481
482 return C;
483}
484
485
491{
492 if (colNum != V.getRows()) {
493 throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (6x6) velocity twist matrix",
494 rowNum, colNum));
495 }
496 vpMatrix M;
497 const unsigned int val_6 = 6;
498 M.resize(rowNum, val_6, false, false);
499
500 // If available use Lapack only for large matrices
501 bool useLapack = ((rowNum > vpMatrix::m_lapack_min_size) || (colNum > vpMatrix::m_lapack_min_size) ||
502 (V.colNum > vpMatrix::m_lapack_min_size));
503#if !defined(VISP_HAVE_LAPACK)
504 useLapack = false;
505#endif
506
507 if (useLapack) {
508#if defined(VISP_HAVE_LAPACK)
509 const double alpha = 1.0;
510 const double beta = 0.0;
511 const char trans = 'n';
512#if defined(VISP_HAVE_GSL) // GSL matrix is row major
513 vpMatrix::blas_dgemm(trans, trans, rowNum, V.colNum, colNum, alpha, data, colNum, V.data, V.colNum, beta, M.data,
514 M.colNum);
515#else
516 vpMatrix::blas_dgemm(trans, trans, V.colNum, rowNum, colNum, alpha, V.data, V.colNum, data, colNum, beta, M.data,
517 M.colNum);
518#endif
519#endif
520 }
521 else {
522#if defined(VISP_HAVE_SIMDLIB)
523 SimdMatMulTwist(data, rowNum, V.data, M.data);
524#else
525 unsigned int VcolNum = V.getCols();
526 unsigned int VrowNum = V.getRows();
527 for (unsigned int i = 0; i < rowNum; ++i) {
528 double *rowptri = rowPtrs[i];
529 double *ci = M[i];
530 for (unsigned int j = 0; j < VcolNum; ++j) {
531 double s = 0;
532 for (unsigned int k = 0; k < VrowNum; ++k) {
533 s += rowptri[k] * V[k][j];
534 }
535 ci[j] = s;
536 }
537 }
538#endif
539 }
540
541 return M;
542}
543
549{
550 if (colNum != V.getRows()) {
551 throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (6x6) force/torque twist matrix",
552 rowNum, colNum));
553 }
554 vpMatrix M;
555 const unsigned int val_6 = 6;
556 M.resize(rowNum, val_6, false, false);
557
558 // If available use Lapack only for large matrices
559 bool useLapack = ((rowNum > vpMatrix::m_lapack_min_size) || (colNum > vpMatrix::m_lapack_min_size) ||
560 (V.getCols() > vpMatrix::m_lapack_min_size));
561#if !defined(VISP_HAVE_LAPACK)
562 useLapack = false;
563#endif
564
565 if (useLapack) {
566#if defined(VISP_HAVE_LAPACK)
567 const double alpha = 1.0;
568 const double beta = 0.0;
569 const char trans = 'n';
570#if defined(VISP_HAVE_GSL) // GSL matrix is row major
571 vpMatrix::blas_dgemm(trans, trans, rowNum, V.getCols(), colNum, alpha, data, colNum, V.data, V.getCols(), beta, M.data,
572 M.colNum);
573#else
574 vpMatrix::blas_dgemm(trans, trans, V.getCols(), rowNum, colNum, alpha, V.data, V.getCols(), data, colNum, beta, M.data,
575 M.colNum);
576#endif
577#endif
578 }
579 else {
580#if defined(VISP_HAVE_SIMDLIB)
581 SimdMatMulTwist(data, rowNum, V.data, M.data);
582#else
583 unsigned int VcolNum = V.getCols();
584 unsigned int VrowNum = V.getRows();
585 for (unsigned int i = 0; i < rowNum; ++i) {
586 double *rowptri = rowPtrs[i];
587 double *ci = M[i];
588 for (unsigned int j = 0; j < VcolNum; ++j) {
589 double s = 0;
590 for (unsigned int k = 0; k < VrowNum; ++k) {
591 s += rowptri[k] * V[k][j];
592 }
593 ci[j] = s;
594 }
595 }
596#endif
597 }
598
599 return M;
600}
601
607{
608 vpMatrix C;
609 vpMatrix::add2Matrices(*this, B, C);
610 return C;
611}
612
618{
619 vpMatrix C;
620 vpMatrix::sub2Matrices(*this, B, C);
621 return C;
622}
623
625
627{
628 if ((colNum != B.getCols()) || (rowNum != B.getRows())) {
629 throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix to (%dx%d) matrix", rowNum, colNum,
630 B.getRows(), B.getCols()));
631 }
632
633 double **BrowPtrs = B.rowPtrs;
634
635 for (unsigned int i = 0; i < rowNum; ++i) {
636 for (unsigned int j = 0; j < colNum; ++j) {
637 rowPtrs[i][j] += BrowPtrs[i][j];
638 }
639 }
640
641 return *this;
642}
643
646{
647 if ((colNum != B.getCols()) || (rowNum != B.getRows())) {
648 throw(vpException(vpException::dimensionError, "Cannot subtract (%dx%d) matrix to (%dx%d) matrix", rowNum, colNum,
649 B.getRows(), B.getCols()));
650 }
651
652 double **BrowPtrs = B.rowPtrs;
653 for (unsigned int i = 0; i < rowNum; ++i) {
654 for (unsigned int j = 0; j < colNum; ++j) {
655 rowPtrs[i][j] -= BrowPtrs[i][j];
656 }
657 }
658
659 return *this;
660}
661
667{
668 vpMatrix C;
669 vpMatrix::negateMatrix(*this, C);
670 return C;
671}
672
673double vpMatrix::sum() const
674{
675 double s = 0.0;
676 for (unsigned int i = 0; i < rowNum; ++i) {
677 for (unsigned int j = 0; j < colNum; ++j) {
678 s += rowPtrs[i][j];
679 }
680 }
681
682 return s;
683}
684
690{
691 if (std::fabs(x - 1.) < std::numeric_limits<double>::epsilon()) {
692 return *this;
693 }
694
695 vpMatrix M;
696 M.resize(rowNum, colNum, false, false);
697
698 for (unsigned int i = 0; i < rowNum; ++i) {
699 for (unsigned int j = 0; j < colNum; ++j) {
700 M[i][j] = rowPtrs[i][j] * x;
701 }
702 }
703
704 return M;
705}
706
707
710{
711 if (std::fabs(x - 1.) < std::numeric_limits<double>::epsilon()) {
712 return *this;
713 }
714
715 if (std::fabs(x) < std::numeric_limits<double>::epsilon()) {
716 throw vpException(vpException::divideByZeroError, "Divide matrix by zero scalar");
717 }
718
719 vpMatrix C;
720 C.resize(rowNum, colNum, false, false);
721
722 double xinv = 1 / x;
723
724 for (unsigned int i = 0; i < rowNum; ++i) {
725 for (unsigned int j = 0; j < colNum; ++j) {
726 C[i][j] = rowPtrs[i][j] * xinv;
727 }
728 }
729
730 return C;
731}
732
735{
736 for (unsigned int i = 0; i < rowNum; ++i) {
737 for (unsigned int j = 0; j < colNum; ++j) {
738 rowPtrs[i][j] += x;
739 }
740 }
741
742 return *this;
743}
744
747{
748 for (unsigned int i = 0; i < rowNum; ++i) {
749 for (unsigned int j = 0; j < colNum; ++j) {
750 rowPtrs[i][j] -= x;
751 }
752 }
753
754 return *this;
755}
756
762{
763 if (std::fabs(x - 1.) < std::numeric_limits<double>::epsilon()) {
764 return *this;
765 }
766
767 for (unsigned int i = 0; i < rowNum; ++i) {
768 for (unsigned int j = 0; j < colNum; ++j) {
769 rowPtrs[i][j] *= x;
770 }
771 }
772
773 return *this;
774}
775
778{
779 if (std::fabs(x - 1.) < std::numeric_limits<double>::epsilon()) {
780 return *this;
781 }
782
783 if (std::fabs(x) < std::numeric_limits<double>::epsilon()) {
784 throw vpException(vpException::divideByZeroError, "Divide matrix by zero scalar");
785 }
786
787 double xinv = 1 / x;
788
789 for (unsigned int i = 0; i < rowNum; ++i) {
790 for (unsigned int j = 0; j < colNum; ++j) {
791 rowPtrs[i][j] *= xinv;
792 }
793 }
794
795 return *this;
796}
797
802vpMatrix operator*(const double &x, const vpMatrix &B)
803{
804 if (std::fabs(x - 1.) < std::numeric_limits<double>::epsilon()) {
805 return B;
806 }
807
808 unsigned int Brow = B.getRows();
809 unsigned int Bcol = B.getCols();
810
811 VISP_NAMESPACE_ADDRESSING vpMatrix C;
812 C.resize(Brow, Bcol, false, false);
813
814 for (unsigned int i = 0; i < Brow; ++i) {
815 for (unsigned int j = 0; j < Bcol; ++j) {
816 C[i][j] = B[i][j] * x;
817 }
818 }
819
820 return C;
821}
822
823END_VISP_NAMESPACE
unsigned int getCols() const
Definition vpArray2D.h:423
vpArray2D< Type > & operator=(Type x)
Set all the elements of the array to x.
Definition vpArray2D.h:615
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:448
unsigned int rowNum
Definition vpArray2D.h:1201
unsigned int dsize
Definition vpArray2D.h:1207
unsigned int getRows() const
Definition vpArray2D.h:433
unsigned int colNum
Definition vpArray2D.h:1203
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ dimensionError
Bad dimension.
Definition vpException.h:71
@ divideByZeroError
Division by zero.
Definition vpException.h:70
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpMatrix operator-() const
vpMatrix & operator/=(double x)
Divide all the element of the matrix by x : Aij = Aij / x.
vpMatrix operator*(const vpMatrix &B) const
vpMatrix operator/(double x) const
Cij = Aij / x (A is unchanged).
vpMatrix & operator-=(const vpMatrix &B)
Operation A = A - B.
vpMatrix & operator*=(double x)
Multiply all the element of the matrix by x : Aij = Aij * x.
vpMatrix operator*(const double &x, const vpMatrix &B)
vpMatrix & operator<<(double *p)
static void sub2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
vpMatrix operator+(const vpMatrix &B) const
double sum() const
vpMatrix & operator+=(const vpMatrix &B)
Operation A = A + B.
vpMatrix & operator,(double val)
static void multMatrixVector(const vpMatrix &A, const vpColVector &v, vpColVector &w)
vpMatrix & operator=(const vpArray2D< double > &A)
static void add2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
static void mult2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
static void negateMatrix(const vpMatrix &A, vpMatrix &C)
vpMatrix t() const
Implementation of a rotation matrix and operations on such kind of matrices.
Implementation of row vector and the associated operations.
Class that consider the case of a translation vector.