51 #include <visp3/core/vpCPUFeatures.h>
52 #include <visp3/core/vpColVector.h>
53 #include <visp3/core/vpConfig.h>
54 #include <visp3/core/vpException.h>
55 #include <visp3/core/vpMath.h>
56 #include <visp3/core/vpMatrix.h>
57 #include <visp3/core/vpTranslationVector.h>
59 #if defined(VISP_HAVE_SIMDLIB)
60 #include <Simd/SimdLib.h>
63 #ifdef VISP_HAVE_LAPACK
65 #include <gsl/gsl_eigen.h>
66 #include <gsl/gsl_linalg.h>
67 #include <gsl/gsl_math.h>
68 #elif defined(VISP_HAVE_MKL)
75 #ifdef VISP_HAVE_LAPACK
77 #elif defined(VISP_HAVE_MKL)
78 typedef MKL_INT integer;
80 void vpMatrix::blas_dsyev(
char jobz,
char uplo,
unsigned int n_,
double *a_data,
unsigned int lda_,
double *w_data,
81 double *work_data,
int lwork_,
int &info_)
83 MKL_INT n =
static_cast<MKL_INT
>(n_);
84 MKL_INT lda =
static_cast<MKL_INT
>(lda_);
85 MKL_INT lwork =
static_cast<MKL_INT
>(lwork_);
86 MKL_INT info =
static_cast<MKL_INT
>(info_);
88 dsyev(&jobz, &uplo, &n, a_data, &lda, w_data, work_data, &lwork, &info);
92 #if defined(VISP_HAVE_LAPACK_BUILT_IN)
93 typedef long int integer;
97 extern "C" integer dsyev_(
char *jobz,
char *uplo, integer *n,
double *a, integer *lda,
double *w,
double *WORK,
98 integer *lwork, integer *info);
100 void vpMatrix::blas_dsyev(
char jobz,
char uplo,
unsigned int n_,
double *a_data,
unsigned int lda_,
double *w_data,
101 double *work_data,
int lwork_,
int &info_)
103 integer n =
static_cast<integer
>(n_);
104 integer lda =
static_cast<integer
>(lda_);
105 integer lwork =
static_cast<integer
>(lwork_);
106 integer info =
static_cast<integer
>(info_);
108 dsyev_(&jobz, &uplo, &n, a_data, &lda, w_data, work_data, &lwork, &info);
110 lwork_ =
static_cast<int>(lwork);
111 info_ =
static_cast<int>(info);
116 #if !defined(VISP_USE_MSVC) || (defined(VISP_USE_MSVC) && !defined(VISP_BUILD_SHARED_LIBS))
117 const unsigned int vpMatrix::m_lapack_min_size_default = 0;
118 unsigned int vpMatrix::m_lapack_min_size = vpMatrix::m_lapack_min_size_default;
131 if (((r + nrows) > M.
rowNum) || ((c + ncols) > M.
colNum)) {
133 "Cannot construct a sub matrix (%dx%d) starting at "
134 "position (%d,%d) that is not contained in the "
135 "original matrix (%dx%d)",
139 init(M, r, c, nrows, ncols);
205 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
264 vpMatrix::vpMatrix(
unsigned int nrows,
unsigned int ncols,
const std::initializer_list<double> &list)
365 unsigned int rnrows = r + nrows;
366 unsigned int cncols = c + ncols;
376 resize(nrows, ncols,
false,
false);
378 if (this->
rowPtrs ==
nullptr) {
381 for (
unsigned int i = 0; i < nrows; ++i) {
382 memcpy((*
this)[i], &M[i + r][c], ncols *
sizeof(
double));
432 unsigned int rnrows = r + nrows;
433 unsigned int cncols = c + ncols;
445 M.
resize(nrows, ncols,
false,
false);
446 for (
unsigned int i = 0; i < nrows; ++i) {
447 memcpy(M[i], &(*
this)[i + r][c], ncols *
sizeof(
double));
505 for (
unsigned int i = 0; i < column_size; ++i) {
506 c[i] = (*this)[i_begin + i][j];
647 if ((r.
data !=
nullptr) && (
data !=
nullptr)) {
648 memcpy(r.
data, (*
this)[i] + j_begin, row_size *
sizeof(
double));
695 unsigned int min_size = std::min<unsigned int>(
rowNum,
colNum);
699 diag.resize(min_size,
false);
701 for (
unsigned int i = 0; i < min_size; ++i) {
702 diag[i] = (*this)[i][i];
786 unsigned int nca = A.
getCols();
787 unsigned int ncb = B.
getCols();
796 if ((B.
getRows() == 0) || ((nca + ncb) == 0)) {
797 std::cerr <<
"B.getRows() == 0 || nca+ncb == 0" << std::endl;
830 int vpMatrix::print(std::ostream &s,
unsigned int length,
const std::string &intro)
const
832 typedef std::string::size_type size_type;
837 std::vector<std::string> values(m * n);
838 std::ostringstream oss;
839 std::ostringstream ossFixed;
840 std::ios_base::fmtflags original_flags = oss.flags();
842 ossFixed.setf(std::ios::fixed, std::ios::floatfield);
844 size_type maxBefore = 0;
845 size_type maxAfter = 0;
847 for (
unsigned int i = 0; i < m; ++i) {
848 for (
unsigned int j = 0; j < n; ++j) {
850 oss << (*this)[i][j];
851 if (oss.str().find(
"e") != std::string::npos) {
853 ossFixed << (*this)[i][j];
854 oss.str(ossFixed.str());
857 values[(i * n) + j] = oss.str();
858 size_type thislen = values[(i * n) + j].
size();
859 size_type p = values[(i * n) + j].find(
'.');
861 if (p == std::string::npos) {
872 size_type totalLength = length;
876 maxAfter = std::min<size_type>(maxAfter, totalLength - maxBefore);
878 if (!intro.empty()) {
881 s <<
"[" << m <<
"," << n <<
"]=\n";
883 for (
unsigned int i = 0; i < m; ++i) {
885 for (
unsigned int j = 0; j < n; ++j) {
886 size_type p = values[(i * n) + j].find(
'.');
887 s.setf(std::ios::right, std::ios::adjustfield);
888 s.width(
static_cast<std::streamsize
>(maxBefore));
889 s << values[(i * n) + j].substr(0, p).c_str();
892 s.setf(std::ios::left, std::ios::adjustfield);
893 if (p != std::string::npos) {
894 s.width(
static_cast<std::streamsize
>(maxAfter));
895 s << values[(i * n) + j].substr(p, maxAfter).c_str();
898 s.width(
static_cast<std::streamsize
>(maxAfter));
908 s.flags(original_flags);
910 return static_cast<int>(maxBefore + maxAfter);
955 unsigned int this_rows = this->
getRows();
956 unsigned int this_col = this->
getCols();
958 for (
unsigned int i = 0; i < this_rows; ++i) {
959 for (
unsigned int j = 0; j < this_col; ++j) {
960 os << (*this)[i][j] <<
", ";
962 if (this->
getRows() != (i + 1)) {
963 os <<
";" << std::endl;
966 os <<
"]" << std::endl;
1006 unsigned int this_rows = this->
getRows();
1007 unsigned int this_col = this->
getCols();
1008 os <<
"([ " << std::endl;
1009 for (
unsigned int i = 0; i < this_rows; ++i) {
1011 for (
unsigned int j = 0; j < this_col; ++j) {
1012 os << (*this)[i][j] <<
", ";
1014 os <<
"]," << std::endl;
1016 os <<
"])" << std::endl;
1053 unsigned int this_rows = this->
getRows();
1054 unsigned int this_col = this->
getCols();
1055 for (
unsigned int i = 0; i < this_rows; ++i) {
1056 for (
unsigned int j = 0; j < this_col; ++j) {
1057 os << (*this)[i][j];
1058 if (!(j == (this->
getCols() - 1))) {
1108 os <<
"vpMatrix " << matrixName <<
" (" << this->
getRows() <<
", " << this->
getCols() <<
"); " << std::endl;
1110 unsigned int this_rows = this->
getRows();
1111 unsigned int this_col = this->
getCols();
1112 for (
unsigned int i = 0; i < this_rows; ++i) {
1113 for (
unsigned int j = 0; j < this_col; ++j) {
1115 os << matrixName <<
"[" << i <<
"][" << j <<
"] = " << (*this)[i][j] <<
"; " << std::endl;
1118 for (
unsigned int k = 0; k <
sizeof(double); ++k) {
1119 os <<
"((unsigned char*)&(" << matrixName <<
"[" << i <<
"][" << j <<
"]) )[" << k <<
"] = 0x" << std::hex
1120 <<
static_cast<unsigned int>(((
unsigned char *)&((*
this)[i][j]))[k]) <<
"; " << std::endl;
1146 unsigned int a_rows = A.
getRows();
1147 for (
unsigned int i = r; i < (r + a_rows); ++i) {
1209 for (
unsigned int i = 0; i <
rowNum; ++i) {
1210 for (
unsigned int j = 0; j <
rowNum; ++j) {
1212 if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
1218 #if defined(VISP_HAVE_LAPACK)
1219 #if defined(VISP_HAVE_GSL)
1221 gsl_vector *eval = gsl_vector_alloc(
rowNum);
1224 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(
rowNum);
1227 unsigned int Atda = (
unsigned int)m->tda;
1228 for (
unsigned int i = 0; i <
rowNum; i++) {
1229 unsigned int k = i * Atda;
1230 for (
unsigned int j = 0; j <
colNum; j++)
1231 m->data[k + j] = (*
this)[i][j];
1233 gsl_eigen_symmv(m, eval, evec, w);
1235 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
1237 for (
unsigned int i = 0; i <
rowNum; i++) {
1238 evalue[i] = gsl_vector_get(eval, i);
1241 gsl_eigen_symmv_free(w);
1242 gsl_vector_free(eval);
1244 gsl_matrix_free(evec);
1248 const char jobz =
'N';
1249 const char uplo =
'U';
1256 lwork =
static_cast<int>(wkopt);
1263 "You should install Lapack 3rd party"));
1330 for (
unsigned int i = 0; i <
rowNum; ++i) {
1331 for (
unsigned int j = 0; j <
rowNum; ++j) {
1333 if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
1343 #if defined(VISP_HAVE_LAPACK)
1344 #if defined(VISP_HAVE_GSL)
1346 gsl_vector *eval = gsl_vector_alloc(
rowNum);
1349 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(
rowNum);
1352 unsigned int Atda = (
unsigned int)m->tda;
1353 for (
unsigned int i = 0; i <
rowNum; i++) {
1354 unsigned int k = i * Atda;
1355 for (
unsigned int j = 0; j <
colNum; j++)
1356 m->data[k + j] = (*
this)[i][j];
1358 gsl_eigen_symmv(m, eval, evec, w);
1360 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
1362 for (
unsigned int i = 0; i <
rowNum; i++) {
1363 evalue[i] = gsl_vector_get(eval, i);
1365 Atda = (
unsigned int)evec->tda;
1366 for (
unsigned int i = 0; i <
rowNum; i++) {
1367 unsigned int k = i * Atda;
1368 for (
unsigned int j = 0; j <
rowNum; j++) {
1369 evector[i][j] = evec->
data[k + j];
1373 gsl_eigen_symmv_free(w);
1374 gsl_vector_free(eval);
1376 gsl_matrix_free(evec);
1380 const char jobz =
'V';
1381 const char uplo =
'U';
1388 lwork =
static_cast<int>(wkopt);
1396 "You should install Lapack 3rd party"));
1420 unsigned int nbline =
getRows();
1421 unsigned int nbcol =
getCols();
1426 V.
resize(nbcol, nbcol,
false);
1432 if (nbline < nbcol) {
1433 U.
resize(nbcol, nbcol,
true);
1436 U.
resize(nbline, nbcol,
false);
1445 for (
unsigned int i = 0; i < nbcol; ++i) {
1446 if (sv[i] > maxsv) {
1451 unsigned int rank = 0;
1452 for (
unsigned int i = 0; i < nbcol; ++i) {
1453 if (sv[i] >(maxsv * svThreshold)) {
1458 kerAt.
resize(nbcol - rank, nbcol);
1459 if (rank != nbcol) {
1461 for (
unsigned int j = 0; j < nbcol; ++j) {
1463 if ((sv[j] <= (maxsv * svThreshold)) &&
1464 (std::fabs(V.
getCol(j).
sumSquare()) > std::numeric_limits<double>::epsilon())) {
1465 unsigned int v_rows = V.
getRows();
1466 for (
unsigned int i = 0; i < v_rows; ++i) {
1467 kerAt[k][i] = V[i][j];
1495 unsigned int nbrow =
getRows();
1496 unsigned int nbcol =
getCols();
1501 V.
resize(nbcol, nbcol,
false);
1507 if (nbrow < nbcol) {
1508 U.
resize(nbcol, nbcol,
true);
1511 U.
resize(nbrow, nbcol,
false);
1519 double maxsv = sv[0];
1521 unsigned int rank = 0;
1522 for (
unsigned int i = 0; i < nbcol; ++i) {
1523 if (sv[i] >(maxsv * svThreshold)) {
1528 kerA.
resize(nbcol, nbcol - rank);
1529 if (rank != nbcol) {
1531 for (
unsigned int j = 0; j < nbcol; ++j) {
1533 if (sv[j] <= (maxsv * svThreshold)) {
1534 for (
unsigned int i = 0; i < nbcol; ++i) {
1535 kerA[i][k] = V[i][j];
1542 return (nbcol - rank);
1563 unsigned int nbrow =
getRows();
1564 unsigned int nbcol =
getCols();
1565 unsigned int dim_ =
static_cast<unsigned int>(dim);
1570 V.
resize(nbcol, nbcol,
false);
1576 if (nbrow < nbcol) {
1577 U.
resize(nbcol, nbcol,
true);
1580 U.
resize(nbrow, nbcol,
false);
1587 kerA.
resize(nbcol, dim_);
1589 unsigned int rank = nbcol - dim_;
1590 for (
unsigned int k = 0; k < dim_; ++k) {
1591 unsigned int j = k + rank;
1592 for (
unsigned int i = 0; i < nbcol; ++i) {
1593 kerA[i][k] = V[i][j];
1598 double maxsv = sv[0];
1599 unsigned int rank = 0;
1600 for (
unsigned int i = 0; i < nbcol; ++i) {
1601 if (sv[i] >(maxsv * 1e-6)) {
1605 return (nbcol - rank);
1656 #if defined(VISP_HAVE_EIGEN3)
1658 #elif defined(VISP_HAVE_LAPACK)
1660 #elif defined(VISP_HAVE_OPENCV)
1664 "Install Lapack, Eigen3 or OpenCV 3rd party"));
1682 #ifdef VISP_HAVE_GSL
1684 double *b =
new double[size_];
1685 for (
size_t i = 0; i < size_; i++)
1687 gsl_matrix_view m = gsl_matrix_view_array(this->
data,
rowNum, colNum);
1688 gsl_matrix_view em = gsl_matrix_view_array(b,
rowNum,
colNum);
1689 gsl_linalg_exponential_ss(&m.matrix, &em.matrix, 0);
1693 memcpy(expA.
data, b, size_ *
sizeof(
double));
1714 for (
unsigned int i = 0; i <
rowNum; ++i) {
1716 for (
unsigned int j = 0; j <
colNum; ++j) {
1717 sum += fabs((*
this)[i][j]);
1719 if ((
sum > nA) || (i == 0)) {
1728 double sca = 1.0 / pow(2.0, s);
1731 v_expE = (c * exp) + v_eye;
1732 v_expD = (-c * exp) + v_eye;
1733 for (
int k = 2; k <= q; ++k) {
1734 c = (c * (
static_cast<double>((q - k) + 1))) / (
static_cast<double>(k * (((2.0 * q) - k) + 1)));
1735 v_expcX = exp * v_expX;
1737 v_expcX = c * v_expX;
1738 v_expE = v_expE + v_expcX;
1740 v_expD = v_expD + v_expcX;
1743 v_expD = v_expD - v_expcX;
1748 exp = v_expX * v_expE;
1749 for (
int k = 1; k <= s; ++k) {
1782 unsigned int m_rows = M.
getRows();
1783 unsigned int m_col = M.
getCols();
1784 for (
unsigned int i = 0; i < col; ++i) {
1785 for (
unsigned int j = 0; j < row; ++j) {
1786 M_comp[i][j] = M[i][j];
1788 for (
unsigned int j = row + 1; j < m_rows; ++j) {
1789 M_comp[i][j - 1] = M[i][j];
1792 for (
unsigned int i = col + 1; i < m_col; ++i) {
1793 for (
unsigned int j = 0; j < row; ++j) {
1794 M_comp[i - 1][j] = M[i][j];
1796 for (
unsigned int j = row + 1; j < m_rows; ++j) {
1797 M_comp[i - 1][j - 1] = M[i][j];
1814 unsigned int nbline =
getRows();
1815 unsigned int nbcol =
getCols();
1820 V.
resize(nbcol, nbcol,
false);
1826 if (nbline < nbcol) {
1827 U.
resize(nbcol, nbcol,
true);
1830 U.
resize(nbline, nbcol,
false);
1839 for (
unsigned int i = 0; i < nbcol; ++i) {
1840 if (sv[i] > maxsv) {
1846 unsigned int rank = 0;
1847 for (
unsigned int i = 0; i < nbcol; ++i) {
1848 if (sv[i] >(maxsv * svThreshold)) {
1854 double minsv = maxsv;
1855 for (
unsigned int i = 0; i < rank; ++i) {
1856 if (sv[i] < minsv) {
1861 if (std::fabs(minsv) > std::numeric_limits<double>::epsilon()) {
1862 return maxsv / minsv;
1865 return std::numeric_limits<double>::infinity();
1883 unsigned int h_col = H.
getCols();
1884 for (
unsigned int i = 0; i < h_col; ++i) {
1885 HLM[i][i] += alpha * H[i][i];
1899 for (
unsigned int i = 0; i <
dsize; ++i) {
1900 double x = *(
data + i);
1917 if (this->
dsize != 0) {
1926 unsigned int maxRank = std::min<unsigned int>(this->
getCols(), this->
getRows());
1929 unsigned int boundary = std::min<unsigned int>(maxRank, w.
size());
1934 for (
unsigned int i = 0; i < boundary; ++i) {
1959 for (
unsigned int i = 0; i <
rowNum; ++i) {
1961 for (
unsigned int j = 0; j <
colNum; ++j) {
1962 x += fabs(*(*(
rowPtrs + i) + j));
1979 double sum_square = 0.0;
1982 for (
unsigned int i = 0; i <
rowNum; ++i) {
1983 for (
unsigned int j = 0; j <
colNum; ++j) {
1985 sum_square += x * x;
1991 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
2001 double vpMatrix::euclideanNorm()
const {
return frobeniusNorm(); }
2025 for (
unsigned int j = 0; j <
getCols(); ++j) {
2026 c[j] = (*this)[i - 1][j];
2052 for (
unsigned int i = 0; i <
getRows(); ++i) {
2053 c[i] = (*this)[i][j - 1];
2064 void vpMatrix::setIdentity(
const double &val)
2066 for (
unsigned int i = 0; i <
rowNum; ++i) {
2067 for (
unsigned int j = 0; j <
colNum; ++j) {
2069 (*this)[i][j] = val;
Implementation of a generic 2D array used as base class for matrices and vectors.
unsigned int getCols() const
double * data
Address of the first element of the data array.
double ** rowPtrs
Address of the first element of each rows.
void insert(const vpArray2D< Type > &A, unsigned int r, unsigned int c)
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
unsigned int rowNum
Number of rows in the array.
static vpArray2D< Type > view(const vpArray2D< Type > &A)
Creates a view of the Matrix A. A view shares the same underlying memory as the original array....
unsigned int dsize
Current array size (rowNum * colNum)
unsigned int size() const
Return the number of elements of the 2D array.
unsigned int getRows() const
unsigned int colNum
Number of columns in the array.
Implementation of column vector and the associated operations.
void resize(unsigned int i, bool flagNullify=true)
error that can be emitted by ViSP classes.
@ functionNotImplementedError
Function not implemented.
@ dimensionError
Bad dimension.
Implementation of an homogeneous matrix and operations on such kind of matrices.
static Type maximum(const Type &a, const Type &b)
Implementation of a matrix and operations on matrices.
vpColVector eigenValues() const
std::ostream & cppPrint(std::ostream &os, const std::string &matrixName="A", bool octet=false) const
double cond(double svThreshold=1e-6) const
int print(std::ostream &s, unsigned int length, const std::string &intro="") const
std::ostream & maplePrint(std::ostream &os) const
void init(const vpMatrix &M, unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols)
vpMatrix cholesky() const
unsigned int kernel(vpMatrix &kerAt, double svThreshold=1e-6) const
vpMatrix inverseByLU() const
static vpMatrix juxtaposeMatrices(const vpMatrix &A, const vpMatrix &B)
void svd(vpColVector &w, vpMatrix &V)
void diag(const double &val=1.0)
vpRowVector getRow(unsigned int i) const
vpMatrix choleskyByOpenCV() const
Compute the Cholesky decomposition of a Hermitian positive-definite matrix using OpenCV library.
vpMatrix choleskyByEigen3() const
Compute the Cholesky decomposition of a Hermitian positive-definite matrix using Eigen3 library.
double inducedL2Norm() const
double infinityNorm() const
double frobeniusNorm() const
vpColVector getDiag() const
static void computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
vpColVector getCol(unsigned int j) const
vpMatrix choleskyByLapack() const
Compute the Cholesky decomposition of a Hermitian positive-definite matrix using Lapack library.
double det(vpDetMethod method=LU_DECOMPOSITION) const
void insert(const vpMatrix &A, unsigned int r, unsigned int c)
std::ostream & csvPrint(std::ostream &os) const
static vpMatrix view(double *data, unsigned int rows, unsigned int cols)
Create a matrix view of a raw data array. The view can modify the contents of the raw data array,...
unsigned int nullSpace(vpMatrix &kerA, double svThreshold=1e-6) const
std::ostream & matlabPrint(std::ostream &os) const
vpMatrix extract(unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols) 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.