23 template <
typename Scalar,
class Derived>
28 if (Derived::RowsAtCompileTime == Eigen::Dynamic) mvbDerived().resize(0, 0);
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().setZero(0, 0);
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)
106 mvbDerived().resize(nRow + 1, N);
109 Derived::RowsAtCompileTime != Eigen::Dynamic &&
110 int(nRow) >= Derived::RowsAtCompileTime)
112 if (dump_errors_here)
113 dump_errors_here->get()
114 <<
"[fromMatlabStringFormat] Read more " 115 "rows than the capacity of the " 116 "fixed sized matrix.\n";
119 for (
size_t q = 0; q < N; q++)
120 mvbDerived()(nRow, q) = lstElements[q];
127 if (Derived::RowsAtCompileTime != Eigen::Dynamic &&
128 int(nRow) != Derived::RowsAtCompileTime)
130 if (dump_errors_here)
131 dump_errors_here->get()
132 <<
"[fromMatlabStringFormat] Read less rows " 133 "than the capacity of the fixed sized " 140 template <
typename Scalar,
class Derived>
142 const std::size_t decimal_digits)
const 144 using Index =
typename Derived::Index;
146 s <<
"[" << std::scientific;
147 s.precision(decimal_digits);
148 for (Index i = 0; i < mvbDerived().rows(); i++)
150 for (Index j = 0; j < mvbDerived().cols(); j++)
151 s << mvbDerived().coeff(i, j) <<
" ";
152 if (i < mvbDerived().rows() - 1) s <<
";";
158 template <
typename Scalar,
class Derived>
161 bool appendMRPTHeader,
const std::string& userHeader)
const 163 using Index =
typename Derived::Index;
165 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 167 if (0 != ::fopen_s(&f, file.c_str(),
"wt")) f =
nullptr;
169 FILE* f =
::fopen(file.c_str(),
"wt");
172 throw std::runtime_error(
173 std::string(
"saveToTextFile: Error opening file ") + file +
174 std::string(
"' for writing a matrix as text."));
176 if (!userHeader.empty())
fprintf(f,
"%s", userHeader.c_str());
178 if (appendMRPTHeader)
183 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 184 struct tm timeinfo_data;
186 if (0 != ::localtime_s(&timeinfo_data, &rawtime))
189 timeinfo = &timeinfo_data;
191 struct tm* timeinfo = ::localtime(&rawtime);
194 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 195 char strTimeBuf[100];
196 if (0 != asctime_s(strTimeBuf,
sizeof(strTimeBuf), timeinfo))
197 strTimeBuf[0] =
'\0';
198 char* strTime = &strTimeBuf[0];
200 char* strTime = asctime(timeinfo);
204 "%% File generated with mrpt-math at %s\n" 205 "%%------------------------------------\n",
209 const auto& m = mvbDerived();
210 for (Index i = 0; i < m.rows(); i++)
212 for (Index j = 0; j < m.cols(); j++)
217 ::fprintf(f,
"%.16e", static_cast<double>(m(i, j)));
220 ::fprintf(f,
"%.16f", static_cast<double>(m(i, j)));
223 ::fprintf(f,
"%i", static_cast<int>(m(i, j)));
226 throw std::runtime_error(
227 "Unsupported value for the parameter 'fileFormat'!");
230 if (j < (mvbDerived().cols() - 1))
::fprintf(f,
" ");
237 template <
typename Scalar,
class Derived>
240 using Index =
typename Derived::Index;
242 std::vector<double> fil(512);
244 while (!f.eof() && !f.fail())
246 std::getline(f, str);
247 if (str.size() && str[0] !=
'#' && str[0] !=
'%')
250 const char* ptr = str.c_str();
251 char* ptrEnd =
nullptr;
254 while (ptr[0] && ptr != ptrEnd)
258 (ptr[0] ==
' ' || ptr[0] ==
',' || ptr[0] ==
'\t' ||
259 ptr[0] ==
'\r' || ptr[0] ==
'\n'))
261 if (fil.size() <= i) fil.resize(fil.size() + (fil.size() >> 1));
263 fil[i] = strtod(ptr, &ptrEnd);
273 if (!i && nRows == 0)
274 throw std::runtime_error(
"loadFromTextFile: Empty first line!");
277 if ((Derived::ColsAtCompileTime != Eigen::Dynamic &&
278 Index(i) != Derived::ColsAtCompileTime))
279 throw std::runtime_error(
280 "loadFromTextFile: The matrix in the text file does not " 281 "match fixed matrix size");
282 if (Derived::ColsAtCompileTime == Eigen::Dynamic && nRows > 0 &&
283 Index(i) != mvbDerived().cols())
284 throw std::runtime_error(
285 "loadFromTextFile: The matrix in the text file does not " 286 "have the same number of columns in all rows");
289 if (Derived::RowsAtCompileTime == Eigen::Dynamic ||
290 Derived::ColsAtCompileTime == Eigen::Dynamic)
292 if (mvbDerived().rows() < static_cast<int>(nRows + 1) ||
293 mvbDerived().cols() < static_cast<int>(i))
295 const size_t extra_rows =
296 std::max(static_cast<size_t>(1), nRows >> 1);
297 mvbDerived().resize(nRows + extra_rows, i);
301 Derived::RowsAtCompileTime != Eigen::Dynamic &&
302 int(nRows) >= Derived::RowsAtCompileTime)
303 throw std::runtime_error(
304 "loadFromTextFile: Read more rows than the capacity of the " 305 "fixed sized matrix.");
307 for (
size_t q = 0; q < i; q++)
308 mvbDerived()(nRows, q) =
Scalar(fil[q]);
315 if (Derived::RowsAtCompileTime == Eigen::Dynamic ||
316 Derived::ColsAtCompileTime == Eigen::Dynamic)
317 mvbDerived().resize(nRows, mvbDerived().cols());
321 throw std::runtime_error(
322 "loadFromTextFile: Error loading from text file");
325 template <
typename Scalar,
class Derived>
327 const std::string& file)
329 std::ifstream f(file.c_str());
331 throw std::runtime_error(
332 std::string(
"loadFromTextFile: can't open file:") + file);
336 template <
typename Scalar,
class Derived>
339 std::stringstream ss;
340 ss << mvbDerived().asEigen();
344 template <
typename Scalar,
class Derived>
347 return mvbDerived().asEigen().array().sum();
350 template <
typename Scalar,
class Derived>
353 return mvbDerived().asEigen().array().abs().sum();
356 template <
typename Scalar,
class Derived>
359 return mvbDerived().asEigen().minCoeff();
362 template <
typename Scalar,
class Derived>
365 return mvbDerived().asEigen().maxCoeff();
368 template <
typename Scalar,
class Derived>
371 if constexpr (Derived::ColsAtCompileTime == 1)
373 typename Derived::Index idx;
374 auto r = mvbDerived().asEigen().minCoeff(&idx);
375 outIdx =
static_cast<std::size_t
>(idx);
379 throw std::runtime_error(
380 "minCoeff(idx): Signature only valid for column vectors");
383 template <
typename Scalar,
class Derived>
386 if constexpr (Derived::ColsAtCompileTime == 1)
388 typename Derived::Index idx;
389 auto r = mvbDerived().asEigen().maxCoeff(&idx);
390 outIdx =
static_cast<std::size_t
>(idx);
394 throw std::runtime_error(
395 "minCoeff(idx): Signature only valid for column vectors");
397 template <
typename Scalar,
class Derived>
399 std::size_t& rowIdx, std::size_t& colIdx)
const 401 typename Derived::Index row, col;
402 auto r = mvbDerived().asEigen().minCoeff(&row, &col);
403 rowIdx =
static_cast<std::size_t
>(row);
404 colIdx =
static_cast<std::size_t
>(col);
408 template <
typename Scalar,
class Derived>
410 std::size_t& rowIdx, std::size_t& colIdx)
const 412 typename Derived::Index row, col;
413 auto r = mvbDerived().asEigen().maxCoeff(&row, &col);
414 rowIdx =
static_cast<std::size_t
>(row);
415 colIdx =
static_cast<std::size_t
>(col);
419 template <
typename Scalar,
class Derived>
422 mvbDerived().asEigen().array() += s;
425 template <
typename Scalar,
class Derived>
428 mvbDerived().asEigen().array() -= s;
431 template <
typename Scalar,
class Derived>
434 mvbDerived().asEigen().array() *= s;
437 template <
typename Scalar,
class Derived>
442 (mvbDerived().asEigen() * v.
asEigen()).eval());
445 template <
typename Scalar,
class Derived>
448 Derived ret(mvbDerived().rows(), mvbDerived().cols());
449 ret.asEigen() = mvbDerived().asEigen() + m2.asEigen();
452 template <
typename Scalar,
class Derived>
455 mvbDerived().asEigen() += m2.asEigen();
457 template <
typename Scalar,
class Derived>
460 Derived ret(mvbDerived().rows(), mvbDerived().cols());
461 ret.asEigen() = mvbDerived().asEigen() - m2.asEigen();
464 template <
typename Scalar,
class Derived>
467 mvbDerived().asEigen() -= m2.asEigen();
469 template <
typename Scalar,
class Derived>
473 mvbDerived().cols() == mvbDerived().rows(),
474 "Operator* implemented only for square matrices. Use `A.asEigen() * " 475 "B.asEigen()` for general matrix products.");
476 Derived ret(mvbDerived().rows(), mvbDerived().rows());
477 if constexpr (Derived::RowsAtCompileTime == Derived::ColsAtCompileTime)
479 ret.asEigen() = mvbDerived().asEigen() * m2.asEigen();
484 template <
typename Scalar,
class Derived>
488 mvbDerived() =
A.asEigen() * b.
asEigen();
491 template <
typename Scalar,
class Derived>
495 mvbDerived() =
A.asEigen().transpose() * b.
asEigen();
498 template <
typename Scalar,
class Derived>
501 return mvbDerived().asEigen().template lpNorm<Eigen::Infinity>();
504 template <
typename Scalar,
class Derived>
507 return mvbDerived().asEigen().norm();
510 template <
typename Scalar,
class Derived>
514 if constexpr (Derived::ColsAtCompileTime == 1)
516 return mvbDerived().asEigen().dot(v.
mvbDerived().asEigen());
520 ASSERTMSG_(
false,
"dot(): Implemented for column vectors only.");
523 template <
typename Scalar,
class Derived>
527 if constexpr (Derived::ColsAtCompileTime == 1)
529 return mvbDerived().asEigen().dot(v.
mvbDerived().asEigen());
533 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).
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...
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'
const_iterator end() const
void operator-=(const MatrixVectorBase< S2, D2 > &m2)
Scalar sum() const
Sum of all elements in matrix/vector.
Derived impl_op_add(const Derived &m2) const
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.
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
void matProductOf_Atb(const CMatrixDynamic< Scalar > &A, const CVectorDynamic< Scalar > &b)
this = AT * b , with A and b a dynamic matrix & vector
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
This template class provides the basic functionality for a general 2D any-size, resizable container o...
CVectorDynamic< T > & mvbDerived()
void loadFromTextFile(std::istream &f)
Loads a vector/matrix from a text file, compatible with MATLAB text format.