47 #include <visp3/core/vpConfig.h>
48 #include <visp3/core/vpException.h>
156 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
174 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
192 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
198 resize(r, c,
false,
false);
202 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
220 resize(1,
static_cast<unsigned int>(list.size()),
false,
false);
221 std::copy(list.begin(), list.end(),
data);
224 explicit vpArray2D<Type>(
unsigned int nrows,
unsigned int ncols,
const std::initializer_list<Type> &list)
227 if (nrows * ncols !=
static_cast<unsigned int>(list.size())) {
228 std::ostringstream oss;
229 oss <<
"Cannot create a vpArray2D of size (" << nrows <<
", " << ncols <<
") with a list of size " << list.size();
233 resize(nrows, ncols,
false,
false);
234 std::copy(list.begin(), list.end(),
data);
239 unsigned int nrows =
static_cast<unsigned int>(lists.size()), ncols = 0;
240 for (
auto &l : lists) {
241 if (
static_cast<unsigned int>(l.size()) > ncols) {
242 ncols =
static_cast<unsigned int>(l.size());
246 resize(nrows, ncols,
false,
false);
247 auto it = lists.begin();
248 for (
unsigned int i = 0; i <
rowNum; i++, ++it) {
249 std::copy(it->begin(), it->end(),
rowPtrs[i]);
303 void resize(
unsigned int nrows,
unsigned int ncols,
bool flagNullify =
true,
bool recopy_ =
true)
306 if (flagNullify && this->data != NULL) {
307 memset(this->data, 0, this->dsize *
sizeof(Type));
310 bool recopy = !flagNullify && recopy_;
311 const bool recopyNeeded = (ncols != this->colNum && this->colNum > 0 && ncols > 0 && (!flagNullify || recopy));
312 Type *copyTmp = NULL;
313 unsigned int rowTmp = 0, colTmp = 0;
317 if (recopyNeeded && this->data != NULL) {
318 copyTmp =
new Type[this->
dsize];
319 memcpy(copyTmp, this->data,
sizeof(Type) * this->dsize);
325 this->dsize = nrows * ncols;
326 this->data = (Type *)realloc(this->data, this->dsize *
sizeof(Type));
327 if ((NULL == this->data) && (0 != this->
dsize)) {
328 if (copyTmp != NULL) {
334 this->rowPtrs = (Type **)realloc(this->rowPtrs, nrows *
sizeof(Type *));
335 if ((NULL == this->rowPtrs) && (0 != this->
dsize)) {
336 if (copyTmp != NULL) {
340 "Memory allocation error when allocating 2D array rowPtrs"));
346 for (
unsigned int i = 0; i <
dsize; i += ncols) {
347 *t_++ = this->data + i;
351 this->rowNum = nrows;
352 this->colNum = ncols;
356 memset(this->data, 0, (
size_t)(this->dsize) *
sizeof(Type));
357 }
else if (recopyNeeded && this->rowPtrs != NULL) {
359 unsigned int minRow = (this->rowNum < rowTmp) ? this->rowNum : rowTmp;
360 unsigned int minCol = (this->colNum < colTmp) ? this->colNum : colTmp;
361 for (
unsigned int i = 0; i < this->
rowNum; ++i) {
362 for (
unsigned int j = 0; j < this->
colNum; ++j) {
363 if ((minRow > i) && (minCol > j)) {
364 (*this)[i][j] = copyTmp[i * colTmp + j];
372 if (copyTmp != NULL) {
378 void reshape(
unsigned int nrows,
unsigned int ncols)
385 if (nrows * ncols !=
dsize) {
386 std::ostringstream oss;
387 oss <<
"Cannot reshape array of total size " <<
dsize <<
" into shape (" << nrows <<
", " << ncols <<
")";
393 rowPtrs =
reinterpret_cast<Type **
>(realloc(
rowPtrs, nrows *
sizeof(Type *)));
396 for (
unsigned int i = 0; i <
dsize; i += ncols) {
429 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
432 if (
this != &other) {
444 other.rowPtrs = NULL;
454 if (
dsize !=
static_cast<unsigned int>(list.size())) {
455 resize(1,
static_cast<unsigned int>(list.size()),
false,
false);
457 std::copy(list.begin(), list.end(),
data);
464 unsigned int nrows =
static_cast<unsigned int>(lists.size()), ncols = 0;
465 for (
auto &l : lists) {
466 if (
static_cast<unsigned int>(l.size()) > ncols) {
467 ncols =
static_cast<unsigned int>(l.size());
471 resize(nrows, ncols,
false,
false);
472 auto it = lists.begin();
473 for (
unsigned int i = 0; i <
rowNum; i++, ++it) {
474 std::copy(it->begin(), it->end(),
rowPtrs[i]);
493 if (A.
data == NULL || A.
size() == 0) {
496 std::ios_base::fmtflags original_flags = s.flags();
499 for (
unsigned int i = 0; i < A.
getRows(); i++) {
500 for (
unsigned int j = 0; j < A.
getCols() - 1; j++) {
506 if (i < A.getRows() - 1) {
511 s.flags(original_flags);
538 static bool load(
const std::string &filename,
vpArray2D<Type> &A,
bool binary =
false,
char *header = NULL)
543 file.open(filename.c_str(), std::fstream::in);
545 file.open(filename.c_str(), std::fstream::in | std::fstream::binary);
555 bool headerIsDecoded =
false;
557 std::streampos pos = file.tellg();
559 file.getline(line, 256);
560 std::string prefix(
"# ");
561 std::string line_(line);
562 if (line_.compare(0, 2, prefix.c_str()) == 0) {
569 h += line_.substr(2);
572 file.seekg(pos, file.beg);
573 headerIsDecoded =
true;
575 }
while (!headerIsDecoded);
577 if (header != NULL) {
578 #if defined(__MINGW32__) || \
579 !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
580 snprintf(header, h.size() + 1,
"%s", h.c_str());
582 _snprintf_s(header, h.size() + 1, _TRUNCATE,
"%s", h.c_str());
586 unsigned int rows, cols;
590 if (rows >= (std::numeric_limits<unsigned int>::max)() || cols >= (std::numeric_limits<unsigned int>::max)()) {
597 for (
unsigned int i = 0; i < rows; i++) {
598 for (
unsigned int j = 0; j < cols; j++) {
611 if (header != NULL) {
612 #if defined(__MINGW32__) || \
613 !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
614 snprintf(header, h.size() + 1,
"%s", h.c_str());
616 _snprintf_s(header, h.size() + 1, _TRUNCATE,
"%s", h.c_str());
620 unsigned int rows, cols;
621 file.read((
char *)&rows,
sizeof(
unsigned int));
622 file.read((
char *)&cols,
sizeof(
unsigned int));
626 for (
unsigned int i = 0; i < rows; i++) {
627 for (
unsigned int j = 0; j < cols; j++) {
628 file.read((
char *)&value,
sizeof(Type));
653 file.open(filename.c_str(), std::fstream::in);
660 unsigned int rows = 0, cols = 0;
662 std::string line, subs;
663 bool inheader =
true;
664 unsigned int i = 0, j;
665 unsigned int lineStart = 0;
667 while (getline(file, line)) {
669 if (rows == 0 && line.compare(0, 5,
"rows:") == 0) {
670 std::stringstream ss(line);
673 }
else if (cols == 0 && line.compare(0, 5,
"cols:") == 0) {
674 std::stringstream ss(line);
677 }
else if (line.compare(0, 5,
"data:") == 0) {
686 if (rows == 0 || cols == 0) {
692 lineStart = (
unsigned int)line.find(
"[") + 1;
694 std::stringstream ss(line.substr(lineStart, line.find(
"]") - lineStart));
696 while (getline(ss, subs,
',')) {
697 A[i][j++] = atof(subs.c_str());
703 if (header != NULL) {
704 std::string h_ = h.substr(0, h.size() - 1);
705 #if defined(__MINGW32__) || \
706 !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
707 snprintf(header, h_.size() + 1,
"%s", h_.c_str());
709 _snprintf_s(header, h_.size() + 1, _TRUNCATE,
"%s", h_.c_str());
733 static bool save(
const std::string &filename,
const vpArray2D<Type> &A,
bool binary =
false,
const char *header =
"")
738 file.open(filename.c_str(), std::fstream::out);
740 file.open(filename.c_str(), std::fstream::out | std::fstream::binary);
751 while (header[i] !=
'\0') {
753 if (header[i] ==
'\n') {
760 file << A << std::endl;
763 while (header[headerSize] !=
'\0') {
766 file.write(header, (
size_t)headerSize + (
size_t)1);
767 unsigned int matrixSize;
769 file.write((
char *)&matrixSize,
sizeof(
unsigned int));
771 file.write((
char *)&matrixSize,
sizeof(
unsigned int));
773 for (
unsigned int i = 0; i < A.
getRows(); i++) {
774 for (
unsigned int j = 0; j < A.
getCols(); j++) {
776 file.write((
char *)&value,
sizeof(Type));
828 file.open(filename.c_str(), std::fstream::out);
836 bool inIndent =
false;
837 std::string indent =
"";
838 bool checkIndent =
true;
839 while (header[i] !=
'\0') {
843 if (header[i] ==
' ') {
845 }
else if (indent.length() > 0) {
849 if (header[i] ==
'\n' || (inIndent && header[i] ==
' ')) {
861 file <<
"rows: " << A.
getRows() << std::endl;
862 file <<
"cols: " << A.
getCols() << std::endl;
864 if (indent.length() == 0) {
868 file <<
"data: " << std::endl;
870 for (i = 0; i < A.
getRows(); ++i) {
871 file << indent <<
"- [";
872 for (j = 0; j < A.
getCols() - 1; ++j) {
873 file << A[i][j] <<
", ";
875 file << A[i][j] <<
"]" << std::endl;
889 Type *dataptr = data;
892 for (
unsigned int i = 0; i < dsize - 1; i++) {
893 if (*dataptr < min) {
906 Type *dataptr = data;
909 for (
unsigned int i = 0; i < dsize - 1; i++) {
910 if (*dataptr > max) {
931 out.
resize(rowNum, colNum,
false);
933 for (
unsigned int i = 0; i < dsize; i++) {
946 for (
unsigned int i = 0; i < A.
size(); i++) {
947 if (data[i] != A.
data[i]) {
964 for (
unsigned int i = 0; i < A.
size(); i++) {
965 if (fabs(
data[i] - A.
data[i]) > std::numeric_limits<double>::epsilon()) {
979 for (
unsigned int i = 0; i < A.
size(); i++) {
980 if (fabsf(data[i] - A.
data[i]) > std::numeric_limits<float>::epsilon()) {
Implementation of a generic 2D array used as base class for matrices and vectors.
static bool load(const std::string &filename, vpArray2D< Type > &A, bool binary=false, char *header=NULL)
unsigned int getCols() const
vpArray2D< Type > & operator=(const std::initializer_list< Type > &list)
Type * data
Address of the first element of the data array.
bool operator!=(const vpArray2D< Type > &A) const
Type ** rowPtrs
Address of the first element of each rows.
vpArray2D< Type > & operator=(const vpArray2D< Type > &A)
Type * operator[](unsigned int i)
Set element using A[i][j] = x.
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
vpArray2D< Type > & operator=(vpArray2D< Type > &&other) noexcept
static bool saveYAML(const std::string &filename, const vpArray2D< Type > &A, const char *header="")
unsigned int rowNum
Number of rows in the array.
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
unsigned int dsize
Current array size (rowNum * colNum)
unsigned int size() const
Return the number of elements of the 2D array.
static bool loadYAML(const std::string &filename, vpArray2D< Type > &A, char *header=NULL)
unsigned int getRows() const
vpArray2D< Type > & operator=(Type x)
Set all the elements of the array to x.
vpArray2D< Type > & operator=(const std::initializer_list< std::initializer_list< Type > > &lists)
vpArray2D< Type > hadamard(const vpArray2D< Type > &m) const
static bool save(const std::string &filename, const vpArray2D< Type > &A, bool binary=false, const char *header="")
void reshape(unsigned int nrows, unsigned int ncols)
Type * operator[](unsigned int i) const
Get element using x = A[i][j].
unsigned int colNum
Number of columns in the array.
bool operator==(const vpArray2D< Type > &A) const
error that can be emited by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
@ dimensionError
Bad dimension.
@ memoryAllocationError
Memory allocation error.