Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpMatrix_operations.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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
46vpMatrix vpMatrix::t() const { return transpose(); }
47
54{
55 vpMatrix At;
56 transpose(At);
57 return At;
58}
59
66{
67 At.resize(colNum, rowNum, false, false);
68
69 const unsigned int val_16 = 16;
70 if ((rowNum <= val_16) || (colNum <= val_16)) {
71 for (unsigned int i = 0; i < rowNum; ++i) {
72 for (unsigned int j = 0; j < colNum; ++j) {
73 At[j][i] = (*this)[i][j];
74 }
75 }
76 }
77 else {
78#if defined(VISP_HAVE_SIMDLIB)
79 SimdMatTranspose(data, rowNum, colNum, At.data);
80#else
81 // https://stackoverflow.com/a/21548079
82 const int tileSize = 32;
83 for (unsigned int i = 0; i < rowNum; i += tileSize) {
84 for (unsigned int j = 0; j < colNum; ++j) {
85 for (unsigned int b = 0; ((b < static_cast<unsigned int>(tileSize)) && ((i + b) < rowNum)); ++b) {
86 At[j][i + b] = (*this)[i + b][j];
87 }
88 }
89 }
90#endif
91 }
92}
93
103{
104 if (A.colNum != v.getRows()) {
105 throw(vpException(vpException::dimensionError, "Cannot multiply a (%dx%d) matrix by a (%d) column vector",
106 A.getRows(), A.getCols(), v.getRows()));
107 }
108
109 if (A.rowNum != w.rowNum) {
110 w.resize(A.rowNum, false);
111 }
112
113 // If available use Lapack only for large matrices
114 bool useLapack = ((A.rowNum > vpMatrix::m_lapack_min_size) || (A.colNum > vpMatrix::m_lapack_min_size));
115#if !defined(VISP_HAVE_LAPACK)
116 useLapack = false;
117#endif
118
119 if (useLapack) {
120#if defined(VISP_HAVE_LAPACK)
121 double alpha = 1.0;
122 double beta = 0.0;
123 int incr = 1;
124
125#ifdef VISP_HAVE_GSL // GSL matrix is row major
126 const char trans = 'n';
127 vpMatrix::blas_dgemv(trans, A.rowNum, A.colNum, alpha, A.data, A.colNum, v.data, incr, beta, w.data, incr);
128#else // BLAS matrix is column major
129 const char trans = 't';
130 vpMatrix::blas_dgemv(trans, A.colNum, A.rowNum, alpha, A.data, A.colNum, v.data, incr, beta, w.data, incr);
131#endif
132#endif
133 }
134 else {
135 w = 0.0;
136 for (unsigned int j = 0; j < A.colNum; ++j) {
137 double vj = v[j]; // optimization em 5/12/2006
138 for (unsigned int i = 0; i < A.rowNum; ++i) {
139 w[i] += A.rowPtrs[i][j] * vj;
140 }
141 }
142 }
143}
144
145//---------------------------------
146// Matrix operations.
147//---------------------------------
148
159{
160 if ((A.getRows() != C.getRows()) || (B.getCols() != C.getCols())) {
161 C.resize(A.getRows(), B.getCols(), false, false);
162 }
163
164 if (A.getCols() != B.getRows()) {
165 throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (%dx%d) matrix", A.getRows(),
166 A.getCols(), B.getRows(), B.getCols()));
167 }
168
169 // If available use Lapack only for large matrices
170 bool useLapack = ((A.getRows() > vpMatrix::m_lapack_min_size) || (A.getCols() > vpMatrix::m_lapack_min_size) ||
171 (B.getCols() > vpMatrix::m_lapack_min_size));
172#if !defined(VISP_HAVE_LAPACK)
173 useLapack = false;
174#endif
175
176 if (useLapack) {
177#if defined(VISP_HAVE_LAPACK)
178 const double alpha = 1.0;
179 const double beta = 0.0;
180 const char trans = 'n';
181
182#if defined(VISP_HAVE_GSL) // GSL matrix is row major
183 vpMatrix::blas_dgemm(trans, trans, A.getRows(), B.getCols(), A.getCols(), alpha, A.data, A.getCols(), B.data, B.getCols(), beta,
184 C.data, B.getCols());
185#else
186 vpMatrix::blas_dgemm(trans, trans, B.getCols(), A.getRows(), A.getCols(), alpha, B.data, B.getCols(), A.data, A.getCols(), beta,
187 C.data, B.getCols());
188#endif
189#endif
190 }
191 else {
192 const unsigned int BcolNum = B.getCols();
193 const unsigned int BrowNum = B.getRows();
194 double **BrowPtrs = B.rowPtrs;
195 for (unsigned int i = 0; i < A.getRows(); ++i) {
196 const double *rowptri = A.rowPtrs[i];
197 double *ci = C[i];
198 for (unsigned int j = 0; j < BcolNum; ++j) {
199 double s = 0;
200 for (unsigned int k = 0; k < BrowNum; ++k) {
201 s += rowptri[k] * BrowPtrs[k][j];
202 }
203 ci[j] = s;
204 }
205 }
206 }
207}
208
219{
220 if ((A.getRows() != C.getRows()) || (B.getCols() != C.getCols())) {
221 C.resize(A.getRows(), B.getCols(), false, false);
222 }
223
224 if (A.getCols() != B.getRows()) {
225 throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) rotation matrix by (%dx%d) matrix", A.getRows(),
226 A.getCols(), B.getRows(), B.getCols()));
227 }
228
229 // If available use Lapack only for large matrices
230 bool useLapack = ((A.getRows() > vpMatrix::m_lapack_min_size) || (A.getCols() > vpMatrix::m_lapack_min_size) ||
231 (B.getCols() > vpMatrix::m_lapack_min_size));
232#if !defined(VISP_HAVE_LAPACK)
233 useLapack = false;
234#endif
235
236 if (useLapack) {
237#if defined(VISP_HAVE_LAPACK)
238 const double alpha = 1.0;
239 const double beta = 0.0;
240 const char trans = 'n';
241
242#if defined(VISP_HAVE_GSL) // GSL matrix is row major
243 vpMatrix::blas_dgemm(trans, trans, A.getRows(), B.getCols(), A.getCols(), alpha, A.data, A.getCols(), B.data, B.getCols(), beta,
244 C.data, B.getCols());
245#else
246 vpMatrix::blas_dgemm(trans, trans, B.getCols(), A.getRows(), A.getCols(), alpha, B.data, B.getCols(), A.data, A.getCols(), beta,
247 C.data, B.getCols());
248#endif
249#endif
250 }
251 else {
252 const unsigned int BcolNum = B.getCols();
253 const unsigned int BrowNum = B.getRows();
254 for (unsigned int i = 0; i < A.getRows(); ++i) {
255 const double *rowptri = A.rowPtrs[i];
256 double *ci = C[i];
257 for (unsigned int j = 0; j < BcolNum; ++j) {
258 double s = 0;
259 for (unsigned int k = 0; k < BrowNum; ++k) {
260 s += rowptri[k] * B.data[k * B.getCols() + j];
261 }
262 ci[j] = s;
263 }
264 }
265 }
266}
267
278{
279 if ((A.getRows() != C.getRows()) || (B.getCols() != C.getCols())) {
280 C.resize(A.getRows(), B.colNum, false, false);
281 }
282
283 if (A.getCols() != B.getRows()) {
284 throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) rotation matrix by (%dx%d) matrix", A.getRows(),
285 A.getCols(), B.getRows(), B.getCols()));
286 }
287
288 // If available use Lapack only for large matrices
289 bool useLapack = ((A.getRows() > vpMatrix::m_lapack_min_size) || (A.getCols() > vpMatrix::m_lapack_min_size) ||
290 (B.colNum > vpMatrix::m_lapack_min_size));
291#if !defined(VISP_HAVE_LAPACK)
292 useLapack = false;
293#endif
294
295 if (useLapack) {
296#if defined(VISP_HAVE_LAPACK)
297 const double alpha = 1.0;
298 const double beta = 0.0;
299 const char trans = 'n';
300
301#if defined(VISP_HAVE_GSL) // GSL matrix is row major
302 vpMatrix::blas_dgemm(trans, trans, A.getRows(), B.getCols(), A.getCols(), alpha, A.data, A.getCols(), B.data, B.getCols(), beta,
303 C.data, B.getCols());
304#else
305 vpMatrix::blas_dgemm(trans, trans, B.getCols(), A.getRows(), A.getCols(), alpha, B.data, B.getCols(), A.data, A.getCols(), beta,
306 C.data, B.getCols());
307#endif
308#endif
309 }
310 else {
311 const unsigned int BcolNum = B.getCols();
312 const unsigned int BrowNum = B.getRows();
313 double **BrowPtrs = B.rowPtrs;
314 for (unsigned int i = 0; i < A.getRows(); ++i) {
315 const double *rowptri = &A.data[i*A.getCols()];
316 double *ci = C[i];
317 for (unsigned int j = 0; j < BcolNum; ++j) {
318 double s = 0;
319 for (unsigned int k = 0; k < BrowNum; ++k) {
320 s += rowptri[k] * BrowPtrs[k][j];
321 }
322 ci[j] = s;
323 }
324 }
325 }
326}
327
341{
342 const unsigned int val_3 = 3;
343 if ((A.colNum != val_3) || (A.rowNum != val_3) || (B.colNum != val_3) || (B.rowNum != val_3)) {
345 "Cannot multiply (%dx%d) matrix by (%dx%d) matrix as a "
346 "rotation matrix",
347 A.getRows(), A.getCols(), B.getRows(), B.getCols()));
348 }
349 // 5/12/06 some "very" simple optimization to avoid indexation
350 const unsigned int BcolNum = B.colNum;
351 const unsigned int BrowNum = B.rowNum;
352 double **BrowPtrs = B.rowPtrs;
353 for (unsigned int i = 0; i < A.rowNum; ++i) {
354 const double *rowptri = A.rowPtrs[i];
355 double *ci = C[i];
356 for (unsigned int j = 0; j < BcolNum; ++j) {
357 double s = 0;
358 for (unsigned int k = 0; k < BrowNum; ++k) {
359 s += rowptri[k] * BrowPtrs[k][j];
360 }
361 ci[j] = s;
362 }
363 }
364}
365
379{
380 const unsigned int val_4 = 4;
381 if ((A.colNum != val_4) || (A.rowNum != val_4) || (B.colNum != val_4) || (B.rowNum != val_4)) {
383 "Cannot multiply (%dx%d) matrix by (%dx%d) matrix as a homogeneous matrix",
384 A.getRows(), A.getCols(), B.getRows(), B.getCols()));
385 }
386
387 // If available use Lapack only for large matrices
388 bool useLapack = ((A.rowNum > vpMatrix::m_lapack_min_size) || (A.colNum > vpMatrix::m_lapack_min_size) ||
389 (B.colNum > vpMatrix::m_lapack_min_size));
390#if !defined(VISP_HAVE_LAPACK)
391 useLapack = false;
392#endif
393
394 if (useLapack) {
395#if defined(VISP_HAVE_LAPACK)
396 const double alpha = 1.0;
397 const double beta = 0.0;
398 const char trans = 'n';
399
400#if defined(VISP_HAVE_GSL) // GSL matrix is row major
401 vpMatrix::blas_dgemm(trans, trans, A.getRows(), B.getCols(), A.getCols(), alpha, A.data, A.getCols(), B.data, B.getCols(), beta,
402 C.data, B.getCols());
403#else
404 vpMatrix::blas_dgemm(trans, trans, B.getCols(), A.getRows(), A.getCols(), alpha, B.data, B.getCols(), A.data, A.getCols(), beta,
405 C.data, B.getCols());
406#endif
407#endif
408 }
409 else {
410 // 5/12/06 some "very" simple optimization to avoid indexation
411 const unsigned int BcolNum = B.colNum;
412 const unsigned int BrowNum = B.rowNum;
413 double **BrowPtrs = B.rowPtrs;
414 for (unsigned int i = 0; i < A.rowNum; ++i) {
415 const double *rowptri = A.rowPtrs[i];
416 double *ci = C[i];
417 for (unsigned int j = 0; j < BcolNum; ++j) {
418 double s = 0;
419 for (unsigned int k = 0; k < BrowNum; ++k) {
420 s += rowptri[k] * BrowPtrs[k][j];
421 }
422 ci[j] = s;
423 }
424 }
425 }
426}
427
441{
443}
444
454
455void vpMatrix::add2WeightedMatrices(const vpMatrix &A, const double &wA, const vpMatrix &B, const double &wB,
456 vpMatrix &C)
457{
458 if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum)) {
459 C.resize(A.rowNum, B.colNum, false, false);
460 }
461
462 if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
463 throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
464 A.getCols(), B.getRows(), B.getCols()));
465 }
466
467 double **ArowPtrs = A.rowPtrs;
468 double **BrowPtrs = B.rowPtrs;
469 double **CrowPtrs = C.rowPtrs;
470
471 for (unsigned int i = 0; i < A.rowNum; ++i) {
472 for (unsigned int j = 0; j < A.colNum; ++j) {
473 CrowPtrs[i][j] = (wB * BrowPtrs[i][j]) + (wA * ArowPtrs[i][j]);
474 }
475 }
476}
477
488{
489 if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum)) {
490 C.resize(A.rowNum, B.colNum, false, false);
491 }
492
493 if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
494 throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
495 A.getCols(), B.getRows(), B.getCols()));
496 }
497
498 double **ArowPtrs = A.rowPtrs;
499 double **BrowPtrs = B.rowPtrs;
500 double **CrowPtrs = C.rowPtrs;
501
502 for (unsigned int i = 0; i < A.rowNum; ++i) {
503 for (unsigned int j = 0; j < A.colNum; ++j) {
504 CrowPtrs[i][j] = BrowPtrs[i][j] + ArowPtrs[i][j];
505 }
506 }
507}
508
522{
523 if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum)) {
524 C.resize(A.rowNum);
525 }
526
527 if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
528 throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
529 A.getCols(), B.getRows(), B.getCols()));
530 }
531
532 double **ArowPtrs = A.rowPtrs;
533 double **BrowPtrs = B.rowPtrs;
534 double **CrowPtrs = C.rowPtrs;
535
536 for (unsigned int i = 0; i < A.rowNum; ++i) {
537 for (unsigned int j = 0; j < A.colNum; ++j) {
538 CrowPtrs[i][j] = BrowPtrs[i][j] + ArowPtrs[i][j];
539 }
540 }
541}
542
559{
560 if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum)) {
561 C.resize(A.rowNum);
562 }
563
564 if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
565 throw(vpException(vpException::dimensionError, "Cannot subtract (%dx%d) matrix to (%dx%d) matrix", A.getRows(),
566 A.getCols(), B.getRows(), B.getCols()));
567 }
568
569 double **ArowPtrs = A.rowPtrs;
570 double **BrowPtrs = B.rowPtrs;
571 double **CrowPtrs = C.rowPtrs;
572
573 for (unsigned int i = 0; i < A.rowNum; ++i) {
574 for (unsigned int j = 0; j < A.colNum; ++j) {
575 CrowPtrs[i][j] = ArowPtrs[i][j] - BrowPtrs[i][j];
576 }
577 }
578}
579
593{
594 if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum)) {
595 C.resize(A.rowNum, A.colNum, false, false);
596 }
597
598 if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
599 throw(vpException(vpException::dimensionError, "Cannot subtract (%dx%d) matrix to (%dx%d) matrix", A.getRows(),
600 A.getCols(), B.getRows(), B.getCols()));
601 }
602
603 double **ArowPtrs = A.rowPtrs;
604 double **BrowPtrs = B.rowPtrs;
605 double **CrowPtrs = C.rowPtrs;
606
607 for (unsigned int i = 0; i < A.rowNum; ++i) {
608 for (unsigned int j = 0; j < A.colNum; ++j) {
609 CrowPtrs[i][j] = ArowPtrs[i][j] - BrowPtrs[i][j];
610 }
611 }
612}
613
624{
625 if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum)) {
626 C.resize(A.rowNum, A.colNum, false, false);
627 }
628
629 double **ArowPtrs = A.rowPtrs;
630 double **CrowPtrs = C.rowPtrs;
631
632 for (unsigned int i = 0; i < A.rowNum; ++i) {
633 for (unsigned int j = 0; j < A.colNum; ++j) {
634 CrowPtrs[i][j] = -ArowPtrs[i][j];
635 }
636 }
637}
638
645{
646 vpMatrix B;
647
648 AAt(B);
649
650 return B;
651}
652
665{
666 if ((B.rowNum != rowNum) || (B.colNum != rowNum)) {
667 B.resize(rowNum, rowNum, false, false);
668 }
669
670 // If available use Lapack only for large matrices
671 bool useLapack = ((rowNum > vpMatrix::m_lapack_min_size) || (colNum > vpMatrix::m_lapack_min_size));
672#if !defined(VISP_HAVE_LAPACK)
673 useLapack = false;
674#endif
675
676 if (useLapack) {
677#if defined(VISP_HAVE_LAPACK)
678 const double alpha = 1.0;
679 const double beta = 0.0;
680
681#if defined(VISP_HAVE_GSL) // GSL matrix is row major
682 const char transa = 'n';
683 const char transb = 't';
684#else
685 const char transa = 't';
686 const char transb = 'n';
687#endif
688
689 vpMatrix::blas_dgemm(transa, transb, rowNum, rowNum, colNum, alpha, data, colNum, data, colNum, beta, B.data, rowNum);
690#endif
691 }
692 else {
693 // compute A*A^T
694 for (unsigned int i = 0; i < rowNum; ++i) {
695 for (unsigned int j = i; j < rowNum; ++j) {
696 double *pi = rowPtrs[i]; // row i
697 double *pj = rowPtrs[j]; // row j
698
699 // sum (row i .* row j)
700 double ssum = 0;
701 for (unsigned int k = 0; k < colNum; ++k) {
702 ssum += (*pi) * (*pj);
703 ++pi;
704 ++pj;
705 }
706
707 B[i][j] = ssum; // upper triangle
708 if (i != j) {
709 B[j][i] = ssum; // lower triangle
710 }
711 }
712 }
713 }
714}
715
728{
729 if ((B.rowNum != colNum) || (B.colNum != colNum)) {
730 B.resize(colNum, colNum, false, false);
731 }
732
733 // If available use Lapack only for large matrices
734 bool useLapack = ((rowNum > vpMatrix::m_lapack_min_size) || (colNum > vpMatrix::m_lapack_min_size));
735#if !defined(VISP_HAVE_LAPACK)
736 useLapack = false;
737#endif
738
739 if (useLapack) {
740#if defined(VISP_HAVE_LAPACK)
741 const double alpha = 1.0;
742 const double beta = 0.0;
743
744#if defined(VISP_HAVE_GSL) // GSL matrix is row major
745 const char transa = 't';
746 const char transb = 'n';
747 vpMatrix::blas_dgemm(transa, transb, colNum, colNum, rowNum, alpha, data, colNum, data, colNum, beta, B.data, colNum);
748#else
749 const char transa = 'n';
750 const char transb = 't';
751
752 vpMatrix::blas_dgemm(transa, transb, colNum, colNum, rowNum, alpha, data, colNum, data, colNum, beta, B.data, colNum);
753#endif
754#endif
755 }
756 else {
757 for (unsigned int i = 0; i < colNum; ++i) {
758 double *Bi = B[i];
759 for (unsigned int j = 0; j < i; ++j) {
760 double *ptr = data;
761 double s = 0;
762 for (unsigned int k = 0; k < rowNum; ++k) {
763 s += (*(ptr + i)) * (*(ptr + j));
764 ptr += colNum;
765 }
766 *Bi++ = s;
767 B[j][i] = s;
768 }
769 double *ptr = data;
770 double s = 0;
771 for (unsigned int k = 0; k < rowNum; ++k) {
772 s += (*(ptr + i)) * (*(ptr + i));
773 ptr += colNum;
774 }
775 *Bi = s;
776 }
777 }
778}
779
786{
787 vpMatrix B;
788
789 AtA(B);
790
791 return B;
792}
793
834{
835 unsigned int rows = A.getRows();
836 this->resize(rows, rows);
837
838 (*this) = 0;
839 for (unsigned int i = 0; i < rows; ++i) {
840 (*this)[i][i] = A[i];
841 }
842}
843
878void vpMatrix::diag(const double &val)
879{
880 (*this) = 0;
881 unsigned int min_ = (rowNum < colNum) ? rowNum : colNum;
882 for (unsigned int i = 0; i < min_; ++i) {
883 (*this)[i][i] = val;
884 }
885}
886
896
898{
899 unsigned int rows = A.getRows();
900 DA.resize(rows, rows, true);
901
902 for (unsigned int i = 0; i < rows; ++i) {
903 DA[i][i] = A[i];
904 }
905}
906
911void vpMatrix::eye(unsigned int n) { eye(n, n); }
912
917void vpMatrix::eye(unsigned int m, unsigned int n)
918{
919 resize(m, n);
920
921 eye();
922}
923
929{
930 for (unsigned int i = 0; i < rowNum; ++i) {
931 for (unsigned int j = 0; j < colNum; ++j) {
932 if (i == j) {
933 (*this)[i][j] = 1.0;
934 }
935 else {
936 (*this)[i][j] = 0;
937 }
938 }
939 }
940}
941
949{
950 if ((m.getRows() != rowNum) || (m.getCols() != colNum)) {
951 throw(vpException(vpException::dimensionError, "In Hadamard product: bad dimension of input matrix"));
952 }
953
954 vpMatrix out;
955 out.resize(rowNum, colNum, false, false);
956
957#if defined(VISP_HAVE_SIMDLIB)
958 SimdVectorHadamard(data, m.data, dsize, out.data);
959#else
960 for (unsigned int i = 0; i < dsize; ++i) {
961 out.data[i] = data[i] * m.data[i];
962 }
963#endif
964
965 return out;
966}
967
974void vpMatrix::kron(const vpMatrix &m1, const vpMatrix &m2, vpMatrix &out)
975{
976 unsigned int r1 = m1.getRows();
977 unsigned int c1 = m1.getCols();
978 unsigned int r2 = m2.getRows();
979 unsigned int c2 = m2.getCols();
980
981 out.resize(r1 * r2, c1 * c2, false, false);
982
983 for (unsigned int r = 0; r < r1; ++r) {
984 for (unsigned int c = 0; c < c1; ++c) {
985 double alpha = m1[r][c];
986 double *m2ptr = m2[0];
987 unsigned int roffset = r * r2;
988 unsigned int coffset = c * c2;
989 for (unsigned int rr = 0; rr < r2; ++rr) {
990 for (unsigned int cc = 0; cc < c2; ++cc) {
991 out[roffset + rr][coffset + cc] = alpha * (*m2ptr);
992 ++m2ptr;
993 }
994 }
995 }
996 }
997}
998
1005void vpMatrix::kron(const vpMatrix &m, vpMatrix &out) const { kron(*this, m, out); }
1006
1014{
1015 unsigned int r1 = m1.getRows();
1016 unsigned int c1 = m1.getCols();
1017 unsigned int r2 = m2.getRows();
1018 unsigned int c2 = m2.getCols();
1019
1020 vpMatrix out;
1021 out.resize(r1 * r2, c1 * c2, false, false);
1022
1023 for (unsigned int r = 0; r < r1; ++r) {
1024 for (unsigned int c = 0; c < c1; ++c) {
1025 double alpha = m1[r][c];
1026 double *m2ptr = m2[0];
1027 unsigned int roffset = r * r2;
1028 unsigned int coffset = c * c2;
1029 for (unsigned int rr = 0; rr < r2; ++rr) {
1030 for (unsigned int cc = 0; cc < c2; ++cc) {
1031 out[roffset + rr][coffset + cc] = alpha * (*m2ptr);
1032 ++m2ptr;
1033 }
1034 }
1035 }
1036 }
1037 return out;
1038}
1039
1045vpMatrix vpMatrix::kron(const vpMatrix &m) const { return kron(*this, m); }
1046
1047vpMatrix vpMatrix::conv2(const vpMatrix &M, const vpMatrix &kernel, const std::string &mode)
1048{
1049 vpMatrix res;
1050 conv2(M, kernel, res, mode);
1051 return res;
1052}
1053
1054void vpMatrix::conv2(const vpMatrix &M, const vpMatrix &kernel, vpMatrix &res, const std::string &mode)
1055{
1056 if (((M.getRows() * M.getCols()) == 0) || ((kernel.getRows() * kernel.getCols()) == 0)) {
1057 return;
1058 }
1059
1060 if (mode == "valid") {
1061 if ((kernel.getRows() > M.getRows()) || (kernel.getCols() > M.getCols())) {
1062 return;
1063 }
1064 }
1065
1066 vpMatrix M_padded, res_same;
1067
1068 if ((mode == "full") || (mode == "same")) {
1069 const unsigned int pad_x = kernel.getCols() - 1;
1070 const unsigned int pad_y = kernel.getRows() - 1;
1071 const unsigned int pad = 2;
1072 M_padded.resize(M.getRows() + (pad * pad_y), M.getCols() + (pad * pad_x), true, false);
1073 M_padded.insert(M, pad_y, pad_x);
1074
1075 if (mode == "same") {
1076 res.resize(M.getRows(), M.getCols(), false, false);
1077 res_same.resize(M.getRows() + pad_y, M.getCols() + pad_x, true, false);
1078 }
1079 else {
1080 res.resize(M.getRows() + pad_y, M.getCols() + pad_x, true, false);
1081 }
1082 }
1083 else if (mode == "valid") {
1084 M_padded = M;
1085 res.resize((M.getRows() - kernel.getRows()) + 1, (M.getCols() - kernel.getCols()) + 1);
1086 }
1087 else {
1088 return;
1089 }
1090
1091 if (mode == "same") {
1092 unsigned int res_same_rows = res_same.getRows();
1093 unsigned int res_same_cols = res_same.getCols();
1094 unsigned int kernel_rows = kernel.getRows();
1095 unsigned int kernel_cols = kernel.getCols();
1096 for (unsigned int i = 0; i < res_same_rows; ++i) {
1097 for (unsigned int j = 0; j < res_same_cols; ++j) {
1098 for (unsigned int k = 0; k < kernel_rows; ++k) {
1099 for (unsigned int l = 0; l < kernel_cols; ++l) {
1100 res_same[i][j] += M_padded[i + k][j + l] * kernel[kernel.getRows() - k - 1][kernel.getCols() - l - 1];
1101 }
1102 }
1103 }
1104 }
1105
1106 const unsigned int start_i = kernel.getRows() / 2;
1107 const unsigned int start_j = kernel.getCols() / 2;
1108 unsigned int m_rows = M.getRows();
1109 for (unsigned int i = 0; i < m_rows; ++i) {
1110 memcpy(res.data + (i * M.getCols()), res_same.data + ((i + start_i) * res_same.getCols()) + start_j,
1111 sizeof(double) * M.getCols());
1112 }
1113 }
1114 else {
1115 unsigned int res_rows = res.getRows();
1116 unsigned int res_cols = res.getCols();
1117 unsigned int kernel_rows = kernel.getRows();
1118 unsigned int kernel_cols = kernel.getCols();
1119 for (unsigned int i = 0; i < res_rows; ++i) {
1120 for (unsigned int j = 0; j < res_cols; ++j) {
1121 for (unsigned int k = 0; k < kernel_rows; ++k) {
1122 for (unsigned int l = 0; l < kernel_cols; ++l) {
1123 res[i][j] += M_padded[i + k][j + l] * kernel[kernel.getRows() - k - 1][kernel.getCols() - l - 1];
1124 }
1125 }
1126 }
1127 }
1128 }
1129}
1130END_VISP_NAMESPACE
unsigned int getCols() const
Definition vpArray2D.h:423
Type ** rowPtrs
Address of the first element of each rows.
Definition vpArray2D.h:1205
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.
void resize(unsigned int i, bool flagNullify=true)
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ dimensionError
Bad dimension.
Definition vpException.h:71
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpMatrix hadamard(const vpMatrix &m) const
unsigned int kernel(vpMatrix &kerAt, double svThreshold=1e-6) const
static void sub2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
void diag(const double &val=1.0)
static void add2WeightedMatrices(const vpMatrix &A, const double &wA, const vpMatrix &B, const double &wB, vpMatrix &C)
vpMatrix AtA() const
static void createDiagonalMatrix(const vpColVector &A, vpMatrix &DA)
static void multMatrixVector(const vpMatrix &A, const vpColVector &v, vpColVector &w)
static void add2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
void insert(const vpMatrix &A, unsigned int r, unsigned int c)
void kron(const vpMatrix &m1, vpMatrix &out) const
vpMatrix AAt() const
static vpMatrix conv2(const vpMatrix &M, const vpMatrix &kernel, const std::string &mode)
vpMatrix transpose() const
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.