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)
78typedef MKL_INT integer;
80void 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)
93typedef long int integer;
97extern "C" integer dsyev_(
char *jobz,
char *uplo, integer *n,
double *a, integer *lda,
double *w,
double *WORK,
98 integer *lwork, integer *info);
100void 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))
117const unsigned int vpMatrix::m_lapack_min_size_default = 0;
118unsigned int vpMatrix::m_lapack_min_size = vpMatrix::m_lapack_min_size_default;
131 if (((r + nrows) > M.
rowNum) || ((c + ncols) > M.
colNum)) {
132 throw(vpException(vpException::dimensionError,
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)",
136 nrows, ncols, r, c, M.rowNum, M.colNum));
139 init(M, r, c, nrows, ncols);
205#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
371 unsigned int rnrows = r + nrows;
372 unsigned int cncols = c + ncols;
382 resize(nrows, ncols,
false,
false);
384 if (this->
rowPtrs ==
nullptr) {
387 for (
unsigned int i = 0; i < nrows; ++i) {
388 memcpy((*
this)[i], &M[i + r][c], ncols *
sizeof(
double));
438 unsigned int rnrows = r + nrows;
439 unsigned int cncols = c + ncols;
451 M.
resize(nrows, ncols,
false,
false);
452 for (
unsigned int i = 0; i < nrows; ++i) {
453 memcpy(M[i], &(*
this)[i + r][c], ncols *
sizeof(
double));
511 for (
unsigned int i = 0; i < column_size; ++i) {
512 c[i] = (*this)[i_begin + i][j];
653 if ((r.data !=
nullptr) && (
data !=
nullptr)) {
654 memcpy(r.data, (*
this)[i] + j_begin, row_size *
sizeof(
double));
701 unsigned int min_size = std::min<unsigned int>(
rowNum,
colNum);
705 diag.resize(min_size,
false);
707 for (
unsigned int i = 0; i < min_size; ++i) {
708 diag[i] = (*this)[i][i];
792 unsigned int nca = A.
getCols();
793 unsigned int ncb = B.
getCols();
802 if ((B.
getRows() == 0) || ((nca + ncb) == 0)) {
803 std::cerr <<
"B.getRows() == 0 || nca+ncb == 0" << std::endl;
836int vpMatrix::print(std::ostream &s,
unsigned int length,
const std::string &intro)
const
838 typedef std::string::size_type size_type;
843 std::vector<std::string> values(m * n);
844 std::ostringstream oss;
845 std::ostringstream ossFixed;
846 std::ios_base::fmtflags original_flags = oss.flags();
848 ossFixed.setf(std::ios::fixed, std::ios::floatfield);
850 size_type maxBefore = 0;
851 size_type maxAfter = 0;
853 for (
unsigned int i = 0; i < m; ++i) {
854 for (
unsigned int j = 0; j < n; ++j) {
856 oss << (*this)[i][j];
857 if (oss.str().find(
"e") != std::string::npos) {
859 ossFixed << (*this)[i][j];
860 oss.str(ossFixed.str());
863 values[(i * n) + j] = oss.str();
864 size_type thislen = values[(i * n) + j].
size();
865 size_type p = values[(i * n) + j].find(
'.');
867 if (p == std::string::npos) {
878 size_type totalLength = length;
882 maxAfter = std::min<size_type>(maxAfter, totalLength - maxBefore);
884 if (!intro.empty()) {
887 s <<
"[" << m <<
"," << n <<
"]=\n";
889 for (
unsigned int i = 0; i < m; ++i) {
891 for (
unsigned int j = 0; j < n; ++j) {
892 size_type p = values[(i * n) + j].find(
'.');
893 s.setf(std::ios::right, std::ios::adjustfield);
894 s.width(
static_cast<std::streamsize
>(maxBefore));
895 s << values[(i * n) + j].substr(0, p).c_str();
898 s.setf(std::ios::left, std::ios::adjustfield);
899 if (p != std::string::npos) {
900 s.width(
static_cast<std::streamsize
>(maxAfter));
901 s << values[(i * n) + j].substr(p, maxAfter).c_str();
904 s.width(
static_cast<std::streamsize
>(maxAfter));
914 s.flags(original_flags);
916 return static_cast<int>(maxBefore + maxAfter);
961 unsigned int this_rows = this->
getRows();
962 unsigned int this_col = this->
getCols();
964 for (
unsigned int i = 0; i < this_rows; ++i) {
965 for (
unsigned int j = 0; j < this_col; ++j) {
966 os << (*this)[i][j] <<
", ";
968 if (this->
getRows() != (i + 1)) {
969 os <<
";" << std::endl;
972 os <<
"]" << std::endl;
1012 unsigned int this_rows = this->
getRows();
1013 unsigned int this_col = this->
getCols();
1014 os <<
"([ " << std::endl;
1015 for (
unsigned int i = 0; i < this_rows; ++i) {
1017 for (
unsigned int j = 0; j < this_col; ++j) {
1018 os << (*this)[i][j] <<
", ";
1020 os <<
"]," << std::endl;
1022 os <<
"])" << std::endl;
1059 unsigned int this_rows = this->
getRows();
1060 unsigned int this_col = this->
getCols();
1061 for (
unsigned int i = 0; i < this_rows; ++i) {
1062 for (
unsigned int j = 0; j < this_col; ++j) {
1063 os << (*this)[i][j];
1064 if (!(j == (this->
getCols() - 1))) {
1114 os <<
"vpMatrix " << matrixName <<
" (" << this->
getRows() <<
", " << this->
getCols() <<
"); " << std::endl;
1116 unsigned int this_rows = this->
getRows();
1117 unsigned int this_col = this->
getCols();
1118 for (
unsigned int i = 0; i < this_rows; ++i) {
1119 for (
unsigned int j = 0; j < this_col; ++j) {
1121 os << matrixName <<
"[" << i <<
"][" << j <<
"] = " << (*this)[i][j] <<
"; " << std::endl;
1124 for (
unsigned int k = 0; k <
sizeof(double); ++k) {
1125 os <<
"((unsigned char*)&(" << matrixName <<
"[" << i <<
"][" << j <<
"]) )[" << k <<
"] = 0x" << std::hex
1126 <<
static_cast<unsigned int>(((
unsigned char *)&((*
this)[i][j]))[k]) <<
"; " << std::endl;
1152 unsigned int a_rows = A.
getRows();
1153 for (
unsigned int i = r; i < (r + a_rows); ++i) {
1214 vpMatrix At_A = (*this).t() - (*this);
1215 for (
unsigned int i = 0; i <
rowNum; ++i) {
1216 for (
unsigned int j = 0; j <
rowNum; ++j) {
1218 if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
1224#if defined(VISP_HAVE_LAPACK)
1225#if defined(VISP_HAVE_GSL)
1227 gsl_vector *eval = gsl_vector_alloc(
rowNum);
1230 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(
rowNum);
1233 unsigned int Atda =
static_cast<unsigned int>(m->tda);
1234 for (
unsigned int i = 0; i <
rowNum; i++) {
1235 unsigned int k = i * Atda;
1236 for (
unsigned int j = 0; j <
colNum; j++)
1237 m->data[k + j] = (*
this)[i][j];
1239 gsl_eigen_symmv(m, eval, evec, w);
1241 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
1243 for (
unsigned int i = 0; i <
rowNum; i++) {
1244 evalue[i] = gsl_vector_get(eval, i);
1247 gsl_eigen_symmv_free(w);
1248 gsl_vector_free(eval);
1250 gsl_matrix_free(evec);
1254 const char jobz =
'N';
1255 const char uplo =
'U';
1262 lwork =
static_cast<int>(wkopt);
1269 "You should install Lapack 3rd party"));
1335 vpMatrix At_A = (*this).t() - (*this);
1336 for (
unsigned int i = 0; i <
rowNum; ++i) {
1337 for (
unsigned int j = 0; j <
rowNum; ++j) {
1339 if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
1349#if defined(VISP_HAVE_LAPACK)
1350#if defined(VISP_HAVE_GSL)
1352 gsl_vector *eval = gsl_vector_alloc(
rowNum);
1355 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(
rowNum);
1358 unsigned int Atda =
static_cast<unsigned int>(m->tda);
1359 for (
unsigned int i = 0; i <
rowNum; i++) {
1360 unsigned int k = i * Atda;
1361 for (
unsigned int j = 0; j <
colNum; j++)
1362 m->data[k + j] = (*
this)[i][j];
1364 gsl_eigen_symmv(m, eval, evec, w);
1366 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
1368 for (
unsigned int i = 0; i <
rowNum; i++) {
1369 evalue[i] = gsl_vector_get(eval, i);
1371 Atda =
static_cast<unsigned int>(evec->tda);
1372 for (
unsigned int i = 0; i <
rowNum; i++) {
1373 unsigned int k = i * Atda;
1374 for (
unsigned int j = 0; j <
rowNum; j++) {
1375 evector[i][j] = evec->
data[k + j];
1379 gsl_eigen_symmv_free(w);
1380 gsl_vector_free(eval);
1382 gsl_matrix_free(evec);
1386 const char jobz =
'V';
1387 const char uplo =
'U';
1394 lwork =
static_cast<int>(wkopt);
1402 "You should install Lapack 3rd party"));
1426 unsigned int nbline =
getRows();
1427 unsigned int nbcol =
getCols();
1432 V.
resize(nbcol, nbcol,
false);
1438 if (nbline < nbcol) {
1439 U.
resize(nbcol, nbcol,
true);
1442 U.
resize(nbline, nbcol,
false);
1451 for (
unsigned int i = 0; i < nbcol; ++i) {
1452 if (sv[i] > maxsv) {
1457 unsigned int rank = 0;
1458 for (
unsigned int i = 0; i < nbcol; ++i) {
1459 if (sv[i] >(maxsv * svThreshold)) {
1464 kerAt.
resize(nbcol - rank, nbcol);
1465 if (rank != nbcol) {
1467 for (
unsigned int j = 0; j < nbcol; ++j) {
1469 if ((sv[j] <= (maxsv * svThreshold)) &&
1470 (std::fabs(V.
getCol(j).
sumSquare()) > std::numeric_limits<double>::epsilon())) {
1471 unsigned int v_rows = V.
getRows();
1472 for (
unsigned int i = 0; i < v_rows; ++i) {
1473 kerAt[k][i] = V[i][j];
1501 unsigned int nbrow =
getRows();
1502 unsigned int nbcol =
getCols();
1507 V.
resize(nbcol, nbcol,
false);
1513 if (nbrow < nbcol) {
1514 U.
resize(nbcol, nbcol,
true);
1517 U.
resize(nbrow, nbcol,
false);
1525 double maxsv = sv[0];
1527 unsigned int rank = 0;
1528 for (
unsigned int i = 0; i < nbcol; ++i) {
1529 if (sv[i] >(maxsv * svThreshold)) {
1534 kerA.
resize(nbcol, nbcol - rank);
1535 if (rank != nbcol) {
1537 for (
unsigned int j = 0; j < nbcol; ++j) {
1539 if (sv[j] <= (maxsv * svThreshold)) {
1540 for (
unsigned int i = 0; i < nbcol; ++i) {
1541 kerA[i][k] = V[i][j];
1548 return (nbcol - rank);
1569 unsigned int nbrow =
getRows();
1570 unsigned int nbcol =
getCols();
1571 unsigned int dim_ =
static_cast<unsigned int>(dim);
1576 V.
resize(nbcol, nbcol,
false);
1582 if (nbrow < nbcol) {
1583 U.
resize(nbcol, nbcol,
true);
1586 U.
resize(nbrow, nbcol,
false);
1593 kerA.
resize(nbcol, dim_);
1595 unsigned int rank = nbcol - dim_;
1596 for (
unsigned int k = 0; k < dim_; ++k) {
1597 unsigned int j = k + rank;
1598 for (
unsigned int i = 0; i < nbcol; ++i) {
1599 kerA[i][k] = V[i][j];
1604 double maxsv = sv[0];
1605 unsigned int rank = 0;
1606 for (
unsigned int i = 0; i < nbcol; ++i) {
1607 if (sv[i] >(maxsv * 1e-6)) {
1611 return (nbcol - rank);
1662#if defined(VISP_HAVE_EIGEN3)
1664#elif defined(VISP_HAVE_LAPACK)
1666#elif defined(VISP_HAVE_OPENCV)
1670 "Install Lapack, Eigen3 or OpenCV 3rd party"));
1690 double *b =
new double[size_];
1691 for (
size_t i = 0; i < size_; i++)
1694 gsl_matrix_view em = gsl_matrix_view_array(b,
rowNum,
colNum);
1695 gsl_linalg_exponential_ss(&m.matrix, &em.matrix, 0);
1699 memcpy(expA.
data, b, size_ *
sizeof(
double));
1720 for (
unsigned int i = 0; i <
rowNum; ++i) {
1722 for (
unsigned int j = 0; j <
colNum; ++j) {
1723 sum += fabs((*
this)[i][j]);
1725 if ((
sum > nA) || (i == 0)) {
1734 double sca = 1.0 / pow(2.0, s);
1737 v_expE = (c * exp) + v_eye;
1738 v_expD = (-c * exp) + v_eye;
1739 for (
int k = 2; k <= q; ++k) {
1740 c = (c * (
static_cast<double>((q - k) + 1))) / (
static_cast<double>(k * (((2.0 * q) - k) + 1)));
1741 v_expcX = exp * v_expX;
1743 v_expcX = c * v_expX;
1744 v_expE = v_expE + v_expcX;
1746 v_expD = v_expD + v_expcX;
1749 v_expD = v_expD - v_expcX;
1754 exp = v_expX * v_expE;
1755 for (
int k = 1; k <= s; ++k) {
1785 unsigned int m_rows = M.
getRows();
1786 unsigned int m_col = M.
getCols();
1787 for (
unsigned int i = 0; i < col; ++i) {
1788 for (
unsigned int j = 0; j < row; ++j) {
1789 M_comp[i][j] = M[i][j];
1791 for (
unsigned int j = row + 1;
j < m_rows; ++
j) {
1792 M_comp[
i][
j - 1] = M[
i][
j];
1795 for (
unsigned int i = col + 1;
i < m_col; ++
i) {
1796 for (
unsigned int j = 0;
j < row; ++
j) {
1797 M_comp[
i - 1][
j] = M[
i][
j];
1799 for (
unsigned int j = row + 1;
j < m_rows; ++
j) {
1800 M_comp[
i - 1][
j - 1] = M[
i][
j];
1817 unsigned int nbline =
getRows();
1818 unsigned int nbcol =
getCols();
1823 V.
resize(nbcol, nbcol,
false);
1829 if (nbline < nbcol) {
1830 U.
resize(nbcol, nbcol,
true);
1833 U.
resize(nbline, nbcol,
false);
1842 for (
unsigned int i = 0; i < nbcol; ++i) {
1843 if (sv[i] > maxsv) {
1849 unsigned int rank = 0;
1850 for (
unsigned int i = 0; i < nbcol; ++i) {
1851 if (sv[i] >(maxsv * svThreshold)) {
1857 double minsv = maxsv;
1858 for (
unsigned int i = 0; i < rank; ++i) {
1859 if (sv[i] < minsv) {
1864 if (std::fabs(minsv) > std::numeric_limits<double>::epsilon()) {
1865 return maxsv / minsv;
1868#if defined(VISP_HAVE_FAST_MATH)
1869 return std::numeric_limits<double>::max();
1871 return std::numeric_limits<double>::infinity();
1890 unsigned int h_col = H.
getCols();
1891 for (
unsigned int i = 0; i < h_col; ++i) {
1892 HLM[i][i] += alpha * H[i][i];
1906 for (
unsigned int i = 0; i <
dsize; ++i) {
1907 double x = *(
data + i);
1924 if (this->
dsize != 0) {
1933 unsigned int maxRank = std::min<unsigned int>(this->
getCols(), this->
getRows());
1936 unsigned int boundary = std::min<unsigned int>(maxRank, w.size());
1941 for (
unsigned int i = 0; i < boundary; ++i) {
1966 for (
unsigned int i = 0; i <
rowNum; ++i) {
1968 for (
unsigned int j = 0; j <
colNum; ++j) {
1969 x += fabs(*(*(
rowPtrs + i) + j));
1986 double sum_square = 0.0;
1989 for (
unsigned int i = 0; i <
rowNum; ++i) {
1990 for (
unsigned int j = 0; j <
colNum; ++j) {
1992 sum_square += x * x;
1998#if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
2032 for (
unsigned int j = 0; j <
getCols(); ++j) {
2033 c[j] = (*this)[i - 1][j];
2059 for (
unsigned int i = 0; i <
getRows(); ++i) {
2060 c[i] = (*this)[i][j - 1];
2073 for (
unsigned int i = 0; i <
rowNum; ++i) {
2074 for (
unsigned int j = 0; j <
colNum; ++j) {
2076 (*this)[i][j] = val;
unsigned int getCols() const
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)
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 rowNum
Number of rows in the array.
unsigned int size() const
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
VP_DEPRECATED void setIdentity(const double &val=1.0)
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)
VP_DEPRECATED double euclideanNorm() const
VP_DEPRECATED vpColVector column(unsigned int j)
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)
VP_DEPRECATED vpRowVector row(unsigned int i)
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)
VP_DEPRECATED void init()
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.