23 template <
typename Scalar,
class Derived>
28 if (Derived::RowsAtCompileTime == Eigen::Dynamic) mvbDerived() = Derived();
31 size_t ini =
s.find_first_not_of(
" \t\r\n");
32 if (ini == std::string::npos ||
s[ini] !=
'[')
37 size_t end =
s.find_last_not_of(
" \t\r\n");
38 if (
end == std::string::npos ||
s[
end] !=
']')
return false;
40 if (ini >
end)
return false;
42 std::vector<Scalar> lstElements;
50 size_t end_row =
s.find_first_of(
";]", i);
51 if (end_row == std::string::npos)
57 std::stringstream ss(
s.substr(i, end_row - i));
65 if (ss.bad() || ss.fail())
break;
66 lstElements.push_back(
val);
74 if (lstElements.empty())
82 if (Derived::RowsAtCompileTime == Eigen::Dynamic)
83 mvbDerived() = Derived();
88 const size_t N = lstElements.size();
91 if ((nRow > 0 &&
size_t(mvbDerived().cols()) != N) ||
92 (nRow == 0 && Derived::ColsAtCompileTime != Eigen::Dynamic &&
93 Derived::ColsAtCompileTime !=
int(N)))
96 dump_errors_here->get()
97 <<
"[fromMatlabStringFormat] Row " << nRow + 1
98 <<
" has invalid number of columns.\n";
103 if (Derived::RowsAtCompileTime == Eigen::Dynamic ||
104 Derived::ColsAtCompileTime == Eigen::Dynamic)
105 mvbDerived().resize(nRow + 1, N);
107 Derived::RowsAtCompileTime != Eigen::Dynamic &&
108 int(nRow) >= Derived::RowsAtCompileTime)
110 if (dump_errors_here)
111 dump_errors_here->get()
112 <<
"[fromMatlabStringFormat] Read more " 113 "rows than the capacity of the " 114 "fixed sized matrix.\n";
117 for (
size_t q = 0;
q < N;
q++)
118 mvbDerived()(nRow,
q) = lstElements[
q];
125 if (Derived::RowsAtCompileTime != Eigen::Dynamic &&
126 int(nRow) != Derived::RowsAtCompileTime)
128 if (dump_errors_here)
129 dump_errors_here->get()
130 <<
"[fromMatlabStringFormat] Read less rows " 131 "than the capacity of the fixed sized " 138 template <
typename Scalar,
class Derived>
140 const std::size_t decimal_digits)
const 142 using Index =
typename Derived::Index;
144 s <<
"[" << std::scientific;
145 s.precision(decimal_digits);
146 for (Index i = 0; i < mvbDerived().rows(); i++)
148 for (Index j = 0; j < mvbDerived().cols(); j++)
149 s << mvbDerived().coeff(i, j) <<
" ";
150 if (i < mvbDerived().rows() - 1)
s <<
";";
156 template <
typename Scalar,
class Derived>
159 bool appendMRPTHeader,
const std::string& userHeader)
const 161 using Index =
typename Derived::Index;
163 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 165 if (0 != ::fopen_s(&f, file.c_str(),
"wt")) f =
nullptr;
167 FILE* f =
::fopen(file.c_str(),
"wt");
170 throw std::runtime_error(
171 std::string(
"saveToTextFile: Error opening file ") + file +
174 if (!userHeader.empty())
fprintf(f,
"%s", userHeader.c_str());
176 if (appendMRPTHeader)
181 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 182 struct tm timeinfo_data;
184 if (0 != ::localtime_s(&timeinfo_data, &rawtime))
187 timeinfo = &timeinfo_data;
189 struct tm* timeinfo = ::localtime(&rawtime);
192 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 193 char strTimeBuf[100];
194 if (0 != asctime_s(strTimeBuf,
sizeof(strTimeBuf), timeinfo))
195 strTimeBuf[0] =
'\0';
196 char* strTime = &strTimeBuf[0];
198 char* strTime = asctime(timeinfo);
202 "%% File generated with mrpt-math at %s\n" 203 "%%------------------------------------\n",
207 const auto& m = mvbDerived();
208 for (Index i = 0; i < m.rows(); i++)
210 for (Index j = 0; j < m.cols(); j++)
215 ::fprintf(f,
"%.16e", static_cast<double>(m(i, j)));
218 ::fprintf(f,
"%.16f", static_cast<double>(m(i, j)));
221 ::fprintf(f,
"%i", static_cast<int>(m(i, j)));
224 throw std::runtime_error(
225 "Unsupported value for the parameter 'fileFormat'!");
228 if (j < (mvbDerived().cols() - 1))
::fprintf(f,
" ");
235 template <
typename Scalar,
class Derived>
238 using Index =
typename Derived::Index;
240 std::vector<double> fil(512);
242 while (!f.eof() && !f.fail())
244 std::getline(f, str);
245 if (str.size() && str[0] !=
'#' && str[0] !=
'%')
248 const char* ptr = str.c_str();
249 char* ptrEnd =
nullptr;
252 while (ptr[0] && ptr != ptrEnd)
256 (ptr[0] ==
' ' || ptr[0] ==
',' || ptr[0] ==
'\t' ||
257 ptr[0] ==
'\r' || ptr[0] ==
'\n'))
259 if (fil.size() <= i) fil.resize(fil.size() + (fil.size() >> 1));
261 fil[i] = strtod(ptr, &ptrEnd);
271 if (!i && nRows == 0)
272 throw std::runtime_error(
"loadFromTextFile: Empty first line!");
275 if ((Derived::ColsAtCompileTime != Eigen::Dynamic &&
276 Index(i) != Derived::ColsAtCompileTime))
277 throw std::runtime_error(
278 "loadFromTextFile: The matrix in the text file does not " 279 "match fixed matrix size");
280 if (Derived::ColsAtCompileTime == Eigen::Dynamic && nRows > 0 &&
281 Index(i) != mvbDerived().cols())
282 throw std::runtime_error(
283 "loadFromTextFile: The matrix in the text file does not " 284 "have the same number of columns in all rows");
287 if (Derived::RowsAtCompileTime == Eigen::Dynamic ||
288 Derived::ColsAtCompileTime == Eigen::Dynamic)
290 if (mvbDerived().rows() < static_cast<int>(nRows + 1) ||
291 mvbDerived().cols() < static_cast<int>(i))
293 const size_t extra_rows =
294 std::max(static_cast<size_t>(1), nRows >> 1);
295 mvbDerived().resize(nRows + extra_rows, i);
299 Derived::RowsAtCompileTime != Eigen::Dynamic &&
300 int(nRows) >= Derived::RowsAtCompileTime)
301 throw std::runtime_error(
302 "loadFromTextFile: Read more rows than the capacity of the " 303 "fixed sized matrix.");
305 for (
size_t q = 0;
q < i;
q++)
306 mvbDerived()(nRows,
q) =
Scalar(fil[
q]);
313 if (Derived::RowsAtCompileTime == Eigen::Dynamic ||
314 Derived::ColsAtCompileTime == Eigen::Dynamic)
315 mvbDerived().resize(nRows, mvbDerived().cols());
319 throw std::runtime_error(
320 "loadFromTextFile: Error loading from text file");
323 template <
typename Scalar,
class Derived>
327 std::ifstream f(file.c_str());
329 throw std::runtime_error(
330 std::string(
"loadFromTextFile: can't open file:") + file);
334 template <
typename Scalar,
class Derived>
337 std::stringstream ss;
338 ss << mvbDerived().asEigen();
342 template <
typename Scalar,
class Derived>
345 return mvbDerived().asEigen().array().sum();
348 template <
typename Scalar,
class Derived>
351 return mvbDerived().asEigen().array().abs().sum();
354 template <
typename Scalar,
class Derived>
357 return mvbDerived().asEigen().minCoeff();
360 template <
typename Scalar,
class Derived>
363 return mvbDerived().asEigen().maxCoeff();
366 template <
typename Scalar,
class Derived>
369 if constexpr (Derived::ColsAtCompileTime == 1)
371 typename Derived::Index idx;
372 auto r = mvbDerived().asEigen().minCoeff(&idx);
373 outIdx =
static_cast<std::size_t
>(idx);
377 throw std::runtime_error(
378 "minCoeff(idx): Signature only valid for column vectors");
381 template <
typename Scalar,
class Derived>
384 if constexpr (Derived::ColsAtCompileTime == 1)
386 typename Derived::Index idx;
387 auto r = mvbDerived().asEigen().maxCoeff(&idx);
388 outIdx =
static_cast<std::size_t
>(idx);
392 throw std::runtime_error(
393 "minCoeff(idx): Signature only valid for column vectors");
395 template <
typename Scalar,
class Derived>
397 std::size_t& rowIdx, std::size_t& colIdx)
const 399 typename Derived::Index
row, col;
400 auto r = mvbDerived().asEigen().minCoeff(&
row, &col);
401 rowIdx =
static_cast<std::size_t
>(
row);
402 colIdx =
static_cast<std::size_t
>(col);
406 template <
typename Scalar,
class Derived>
408 std::size_t& rowIdx, std::size_t& colIdx)
const 410 typename Derived::Index
row, col;
411 auto r = mvbDerived().asEigen().maxCoeff(&
row, &col);
412 rowIdx =
static_cast<std::size_t
>(
row);
413 colIdx =
static_cast<std::size_t
>(col);
417 template <
typename Scalar,
class Derived>
420 mvbDerived().asEigen().array() +=
s;
423 template <
typename Scalar,
class Derived>
426 mvbDerived().asEigen().array() -=
s;
429 template <
typename Scalar,
class Derived>
432 mvbDerived().asEigen().array() *=
s;
435 template <
typename Scalar,
class Derived>
440 (mvbDerived().asEigen() *
v.asEigen()).eval());
443 template <
typename Scalar,
class Derived>
446 Derived ret(mvbDerived().rows(), mvbDerived().cols());
447 ret.asEigen() = mvbDerived().asEigen() + m2.asEigen();
450 template <
typename Scalar,
class Derived>
453 mvbDerived().asEigen() += m2.asEigen();
455 template <
typename Scalar,
class Derived>
458 Derived ret(mvbDerived().rows(), mvbDerived().cols());
459 ret.asEigen() = mvbDerived().asEigen() - m2.asEigen();
462 template <
typename Scalar,
class Derived>
465 mvbDerived().asEigen() -= m2.asEigen();
467 template <
typename Scalar,
class Derived>
471 mvbDerived().cols() == mvbDerived().rows(),
472 "Operator* implemented only for square matrices. Use `A.asEigen() * " 473 "B.asEigen()` for general matrix products.");
474 Derived ret(mvbDerived().rows(), mvbDerived().rows());
475 if constexpr (Derived::RowsAtCompileTime == Derived::ColsAtCompileTime)
477 ret.asEigen() = mvbDerived().asEigen() * m2.asEigen();
482 template <
typename Scalar,
class Derived>
486 mvbDerived() =
A.asEigen() *
b.asEigen();
489 template <
typename Scalar,
class Derived>
493 mvbDerived() =
A.asEigen().transpose() *
b.asEigen();
496 template <
typename Scalar,
class Derived>
499 return mvbDerived().asEigen().template lpNorm<Eigen::Infinity>();
502 template <
typename Scalar,
class Derived>
505 return mvbDerived().asEigen().norm();
508 template <
typename Scalar,
class Derived>
512 if constexpr (Derived::ColsAtCompileTime == 1)
514 return mvbDerived().asEigen().dot(
v.mvbDerived().asEigen());
518 ASSERTMSG_(
false,
"dot(): Implemented for column vectors only.");
521 template <
typename Scalar,
class Derived>
525 if constexpr (Derived::ColsAtCompileTime == 1)
527 return mvbDerived().asEigen().dot(
v.mvbDerived().asEigen());
531 ASSERTMSG_(
false,
"dot(): Implemented for column vectors only.");
Scalar maxCoeff() const
Maximum value in the matrix/vector.
Scalar norm_inf() const
Compute the norm-infinite of a vector ($f[ ||{v}||_ $f]), ie the maximum absolute value of the elemen...
void impl_op_selfsubs(const Derived &m2)
auto operator*(const MatrixVectorBase< S2, D2 > &m2) const
std::string asString() const
Returns a string representation of the vector/matrix, using Eigen's default settings.
Template for column vectors of dynamic size, compatible with Eigen.
int void fclose(FILE *f)
An OS-independent version of fclose.
Scalar norm() const
Compute the L2 norm of a vector/array/matrix (the Euclidean distance to the origin, taking all the elements as a single vector).
GLdouble GLdouble GLdouble GLdouble q
engineering format 'e'
std::optional< std::reference_wrapper< T > > optional_ref
Shorter name for std::optional<std::reference_wrapper<T>>
void saveToTextFile(const std::string &file, mrpt::math::TMatrixTextFileFormat fileFormat=mrpt::math::MATRIX_FORMAT_ENG, bool appendMRPTHeader=false, const std::string &userHeader=std::string()) const
Saves the vector/matrix to a file compatible with MATLAB/Octave text format.
void operator*=(Scalar s)
This base provides a set of functions for maths stuff.
Scalar dot(const CVectorDynamic< Scalar > &v) const
dot product of this \cdot v
Derived impl_op_subs(const Derived &m2) const
void matProductOf_Ab(const CMatrixDynamic< Scalar > &A, const CVectorDynamic< Scalar > &b)
this = A * b , with A and b a dynamic matrix & vector
void operator+=(const MatrixVectorBase< S2, D2 > &m2)
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
bool fromMatlabStringFormat(const std::string &s, mrpt::optional_ref< std::ostream > dump_errors_here=std::nullopt)
Reads a matrix from a string in Matlab-like format, for example: "[1 0 2; 0 4 -1]" The string must st...
GLsizei const GLchar ** string
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Scalar sum_abs() const
Sum of the absolute value of all elements in matrix/vector.
fixed floating point 'f'
void operator-=(const MatrixVectorBase< S2, D2 > &m2)
GLdouble GLdouble GLdouble r
Scalar sum() const
Sum of all elements in matrix/vector.
Derived impl_op_add(const Derived &m2) const
GLenum GLenum GLvoid * row
void impl_op_selfadd(const Derived &m2)
std::string inMatlabFormat(const std::size_t decimal_digits=6) const
Exports the matrix as a string compatible with Matlab/Octave.
Scalar minCoeff() const
Minimum value in the matrix/vector.
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
Base CRTP class for all MRPT vectors and matrices.
void matProductOf_Atb(const CMatrixDynamic< Scalar > &A, const CVectorDynamic< Scalar > &b)
this = AT * b , with A and b a dynamic matrix & vector
This template class provides the basic functionality for a general 2D any-size, resizable container o...
void loadFromTextFile(std::istream &f)
Loads a vector/matrix from a text file, compatible with MATLAB text format.