YARP
Yet Another Robot Platform
Matrix.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * Copyright (C) 2006-2010 RobotCub Consortium
4  * All rights reserved.
5  *
6  * This software may be modified and distributed under the terms of the
7  * BSD-3-Clause license. See the accompanying LICENSE file for details.
8  */
9 
10 #include <yarp/sig/Matrix.h>
11 
12 #include <yarp/conf/system.h>
13 
14 #include <yarp/sig/Vector.h>
15 #include <yarp/os/Bottle.h>
18 #include <yarp/os/ManagedBytes.h>
19 #include <yarp/os/NetFloat64.h>
20 #include <yarp/os/NetInt32.h>
21 
22 #include <vector>
23 #include <cstdio>
24 
25 using namespace yarp::sig;
26 using namespace yarp::os;
27 
28 #define RES(v) ((std::vector<T> *)v)
29 
32 {
33 public:
34  yarp::os::NetInt32 outerListTag{0};
35  yarp::os::NetInt32 outerListLen{0};
36  yarp::os::NetInt32 rowsTag{0};
38  yarp::os::NetInt32 colsTag{0};
40  yarp::os::NetInt32 listTag{0};
41  yarp::os::NetInt32 listLen{0};
42 
44 };
46 
47 // network stuff
48 #include <yarp/os/NetInt32.h>
49 
50 bool yarp::sig::removeCols(const Matrix &in, Matrix &out, size_t first_col, size_t how_many)
51 {
52  size_t nrows = in.rows();
53  size_t ncols = in.cols();
54  Matrix ret(nrows, ncols-how_many);
55  for(size_t r=0; r<nrows; r++)
56  for(size_t c_in=0,c_out=0;c_in<ncols; c_in++)
57  {
58  if (c_in==first_col)
59  {
60  c_in=c_in+(how_many-1);
61  continue;
62  }
63  ret[r][c_out]=(in)[r][c_in];
64  c_out++;
65  }
66  out=ret;
67  return true;
68 }
69 
70 bool yarp::sig::removeRows(const Matrix &in, Matrix &out, size_t first_row, size_t how_many)
71 {
72  size_t nrows = in.rows();
73  size_t ncols = in.cols();
74  Matrix ret(nrows-how_many, ncols);
75  for(size_t c=0; c<ncols; c++)
76  for(size_t r_in=0, r_out=0; r_in<nrows; r_in++)
77  {
78  if (r_in==first_row)
79  {
80  r_in=r_in+(how_many-1);
81  continue;
82  }
83  ret[r_out][c]=(in)[r_in][c];
84  r_out++;
85  }
86  out=ret;
87  return true;
88 }
89 
90 bool yarp::sig::submatrix(const Matrix &in, Matrix &out, size_t r1, size_t r2, size_t c1, size_t c2)
91 {
92  double *t=out.data();
93  const double *i=in.data()+in.cols()*r1+c1;
94  const int offset=in.cols()-(c2-c1+1);
95 
96  if(i == nullptr || t == nullptr)
97  return false;
98 
99  for(size_t r=0;r<=(r2-r1);r++)
100  {
101  for(size_t c=0;c<=(c2-c1);c++)
102  {
103  *t++=*i++;
104  }
105  i+=offset;
106  }
107 
108  return true;
109 }
110 
111 
113  // auto-convert text mode interaction
114  connection.convertTextMode();
116  bool ok = connection.expectBlock((char*)&header, sizeof(header));
117  if (!ok) return false;
118  size_t r=rows();
119  size_t c=cols();
120  if (header.listLen > 0)
121  {
122  if ( r != (size_t)(header.rows) || c!=(size_t)(header.cols))
123  {
124  resize(header.rows, header.cols);
125  }
126 
127  int l=0;
128  double *tmp=data();
129  for(l=0;l<header.listLen;l++)
130  tmp[l]=connection.expectFloat64();
131  }
132  else
133  return false;
134 
135  return true;
136 }
137 
138 
139 bool Matrix::write(yarp::os::ConnectionWriter& connection) const {
141 
142  //header.totalLen = sizeof(header)+sizeof(double)*this->size();
143  header.outerListTag = BOTTLE_TAG_LIST;
144  header.outerListLen = 3;
145  header.rowsTag = BOTTLE_TAG_INT32;
146  header.colsTag = BOTTLE_TAG_INT32;
148  header.rows=rows();
149  header.cols=cols();
150  header.listLen = header.rows*header.cols;
151 
152  connection.appendBlock((char*)&header, sizeof(header));
153 
154  int l=0;
155  const double *tmp=data();
156  for(l=0;l<header.listLen;l++)
157  connection.appendFloat64(tmp[l]);
158 
159  // if someone is foolish enough to connect in text mode,
160  // let them see something readable.
161  connection.convertTextMode();
162 
163  return true;
164 }
165 
166 
167 std::string Matrix::toString(int precision, int width, const char* endRowStr) const {
168 
169  // If the width is less than 1, use tabs, else use width number of spaces.
170  std::string spacer((width<0) ? "\t" : " ");
171 
172  // Buffering.
173  std::string ret = "";
174  char buffer[350];
175  const double* src = (*this).data();
176 
177  // Iterate through copying the contents from the matrix, into a string.
178  // Avoid unnecessary string resizes by only adding spacers at the beginning.
179  size_t r, c;
180  for (r = 0; r < nrows; r++) {
181  if (r) { ret += endRowStr; }
182  for (c = 0; c < ncols; c++) {
183  if (c) { ret += spacer; }
184  sprintf(buffer, "% *.*lf", width, precision, *src); src++;
185  ret += buffer;
186  }
187  }
188 
189  return ret;
190 }
191 
192 
193 void Matrix::updatePointers()
194 {
195  if (matrix!=nullptr)
196  delete [] matrix;
197 
198  size_t r=0;
199  matrix=new double* [nrows];
200  if (nrows>0) matrix[0]=storage;
201  for(r=1;r<nrows; r++)
202  {
203  matrix[r]=matrix[r-1]+ncols;
204  }
205 }
206 
208 {
209  if (this == &r) return *this;
210 
211  if(nrows!=r.nrows || ncols!=r.ncols)
212  {
213  if (storage)
214  delete [] storage;
215 
216  nrows=r.nrows;
217  ncols=r.ncols;
218 
219  storage=new double[ncols*nrows];
220  memcpy(storage, r.storage, ncols*nrows*sizeof(double));
221  updatePointers();
222  }
223  else
224  {
225  if(!storage)
226  storage=new double[ncols*nrows];
227  memcpy(storage, r.storage, ncols*nrows*sizeof(double));
228  }
229 
230  return *this;
231 }
232 
233 const Matrix &Matrix::operator=(double v)
234 {
235  size_t nelem = nrows*ncols;
236  for(size_t k=0; k<nelem; k++)
237  storage[k]=v;
238 
239  return *this;
240 }
241 
243 {
244  if (matrix!=nullptr)
245  delete [] matrix;
246 
247  if (storage!=nullptr)
248  delete [] storage;
249 }
250 
251 void Matrix::resize(size_t new_r, size_t new_c)
252 {
253  if(new_r==nrows && new_c==ncols)
254  return;
255 
256  auto* new_storage=new double[new_r*new_c];
257 
258  const size_t copy_r=(new_r<nrows) ? new_r:nrows;
259  const size_t copy_c=(new_c<ncols) ? new_c:ncols;
260  //copy_r = (new_r<nrows) ? new_r:nrows;
261 
262  if (storage!=nullptr)
263  {
264  double *tmp_new=new_storage;
265  double *tmp_current=storage;
266  // copy content
267 
268  // favor performance for small matrices
269 #if 0
270  const int stepN=(new_c-copy_c);
271  const int stepC=(ncols-copy_c);
272 
273  for(int r=0; r<copy_r;r++)
274  {
275  for(int c=0;c<copy_c;c++)
276  *tmp_new++=*tmp_current++;
277  tmp_new+=stepN;
278  tmp_current=matrix[r];
279  }
280 #endif
281 
282  // favor performance with large matrices
283  for(size_t r=0; r<copy_r;r++)
284  {
285  tmp_current=matrix[r];
286  memcpy(tmp_new, tmp_current, sizeof(double)*copy_c);
287  tmp_new+=new_c;
288  }
289 
290 
291  delete [] storage;
292  }
293  else
294  {
295  //zero memory
296  memset(new_storage, 0, sizeof(double)*new_r*new_c);
297  }
298 
299  storage=new_storage;
300 
301  nrows=new_r;
302  ncols=new_c;
303 
304  // storage.resize(r*c);
305  updatePointers();
306 }
307 
309 {
310  memset(storage, 0, sizeof(double)*ncols*nrows);
311 }
312 
313 Matrix Matrix::removeCols(size_t first_col, size_t how_many)
314 {
315  Matrix ret;
316  ret.resize(nrows, ncols-how_many);
317 
318  for(size_t r=0; r<nrows; r++)
319  for(size_t c_in=0,c_out=0;c_in<ncols; c_in++)
320  {
321  if (c_in==first_col)
322  {
323  c_in=c_in+(how_many-1);
324  continue;
325  }
326  ret[r][c_out]=(*this)[r][c_in];
327  c_out++;
328  }
329 
330  if (storage)
331  delete [] storage;
332 
333  nrows=ret.nrows;
334  ncols=ret.ncols;
335  storage=new double[ncols*nrows];
336  memcpy(storage, ret.storage, ncols*nrows*sizeof(double));
337  updatePointers();
338  return ret;
339 }
340 
341 Matrix Matrix::removeRows(size_t first_row, size_t how_many)
342 {
343  Matrix ret;
344  ret.resize(nrows-how_many, ncols);
345 
346  for(size_t c=0; c<ncols; c++)
347  for(size_t r_in=0, r_out=0; r_in<nrows; r_in++)
348  {
349  if (r_in==first_row)
350  {
351  r_in=r_in+(how_many-1);
352  continue;
353  }
354  ret[r_out][c]=(*this)[r_in][c];
355  r_out++;
356  }
357 
358  if (storage)
359  delete [] storage;
360 
361  nrows=ret.nrows;
362  ncols=ret.ncols;
363  storage=new double[ncols*nrows];
364  memcpy(storage, ret.storage, ncols*nrows*sizeof(double));
365  updatePointers();
366  return ret;
367 }
368 
370 {
371  Matrix ret;
372  ret.resize(ncols, nrows);
373 
374  for(size_t r=0; r<nrows; r++)
375  for(size_t c=0;c<ncols; c++)
376  ret[c][r]=(*this)[r][c];
377 
378  return ret;
379 }
380 
381 Vector Matrix::getRow(size_t r) const
382 {
383  Vector ret;
384  ret.resize(ncols);
385 
386  for(size_t c=0;c<ncols;c++)
387  ret[c]=(*this)[r][c];
388 
389  return ret;
390 }
391 
392 Vector Matrix::getCol(size_t c) const
393 {
394  Vector ret;
395  ret.resize(nrows);
396 
397  for(size_t r=0;r<nrows;r++)
398  ret[r]=(*this)[r][c];
399 
400  return ret;
401 }
402 
403 Vector Matrix::subrow(size_t r, size_t c, size_t size) const
404 {
405  if(r>=rows() || c+size-1>=cols())
406  return Vector(0);
407 
408  Vector ret(size);
409 
410  for(size_t i=0;i<size;i++)
411  ret[i]=(*this)[r][c+i];
412 
413  return ret;
414 }
415 
416 Vector Matrix::subcol(size_t r, size_t c, size_t size) const
417 {
418  if(r+size-1>=rows() || c>=cols())
419  return Vector(0);
420 
421  Vector ret(size);
422 
423  for(size_t i=0;i<size;i++)
424  ret[i]=(*this)[r+i][c];
425 
426  return ret;
427 }
428 
430 {
431  zero();
432  size_t tmpR=nrows;
433  if (ncols<nrows)
434  tmpR=ncols;
435 
436  size_t c=0;
437  for(size_t r=0; r<tmpR; r++,c++)
438  (*this)[r][c]=1.0;
439 
440  return *this;
441 }
442 
444 {
445  zero();
446  size_t tmpR=nrows;
447  if (ncols<nrows)
448  tmpR=ncols;
449 
450  size_t c=0;
451  for(size_t r=0; r<tmpR; r++,c++)
452  (*this)[r][c]=d[r];
453 
454  return *this;
455 }
456 
458 {
459  //check dimensions first
460  if ( (rows()!=r.rows()) || (cols()!=r.cols()))
461  return false;
462 
463  const double *tmp1=data();
464  const double *tmp2=r.data();
465 
466  if(tmp1 == nullptr || tmp2 == nullptr)
467  return false;
468 
469  int c=rows()*cols();
470  while(c--)
471  {
472  if (*tmp1++!=*tmp2++)
473  return false;
474  }
475 
476  return true;
477 }
478 
479 bool Matrix::setRow(size_t row, const Vector &r)
480 {
481  if((row>=nrows) || (r.length() != ncols))
482  return false;
483 
484  for(size_t c=0;c<ncols;c++)
485  (*this)[row][c]=r[c];
486 
487  return true;
488 }
489 
490 bool Matrix::setCol(size_t col, const Vector &c)
491 {
492  if((col>=ncols) || (c.length() != nrows))
493  return false;
494 
495  for(size_t r=0;r<nrows;r++)
496  (*this)[r][col]=c[r];
497 
498  return true;
499 }
500 
501 bool Matrix::setSubmatrix(const yarp::sig::Matrix &m, size_t r, size_t c)
502 {
503  if((c+m.cols()>ncols) || (r+m.rows()>nrows))
504  return false;
505 
506  for(size_t i=0;i<m.rows();i++)
507  for(size_t j=0;j<m.cols();j++)
508  (*this)[r+i][c+j] = m(i,j);
509  return true;
510 }
511 
512 bool Matrix::setSubrow(const Vector &v, size_t r, size_t c)
513 {
514  size_t s = v.size();
515  if(r>=nrows || c+s-1>=(size_t)ncols)
516  return false;
517 
518  for(size_t i=0;i<s;i++)
519  (*this)[r][i+c] = v[i];
520  return true;
521 }
522 
523 bool Matrix::setSubcol(const Vector &v, size_t r, size_t c)
524 {
525  size_t s = v.size();
526  if(r+s-1>=(size_t)nrows || c>=ncols)
527  return false;
528 
529  for(size_t i=0;i<s;i++)
530  (*this)[r+i][c] = v[i];
531  return true;
532 }
533 
534 Matrix::Matrix(size_t r, size_t c):
535  storage(nullptr),
536  matrix(nullptr),
537  nrows(r),
538  ncols(c)
539 {
540  storage=new double [r*c];
541  memset(storage, 0, r*c*sizeof(double));
542  updatePointers();
543 }
544 
545 Matrix::Matrix(const Matrix &m): yarp::os::Portable(),
546  storage(nullptr),
547  matrix(nullptr)
548 {
549  nrows=m.nrows;
550  ncols=m.ncols;
551 
552  if (m.storage!=nullptr)
553  {
554  storage=new double [nrows*ncols];
555  memcpy(storage, m.storage, nrows*ncols*sizeof(double));
556 
557  updatePointers();
558  }
559 }
yarp::sig::removeRows
bool removeRows(const Matrix &in, Matrix &out, size_t first_row, size_t how_many)
Definition: Matrix.cpp:70
yarp::sig::Matrix::toString
std::string toString(int precision=-1, int width=-1, const char *endRowStr="\n") const
Print matrix to a string.
Definition: Matrix.cpp:167
yarp::os::ConnectionWriter::appendBlock
virtual void appendBlock(const char *data, size_t len)=0
Send a block of data to the network connection.
yarp::os::Portable
This is a base class for objects that can be both read from and be written to the YARP network.
Definition: Portable.h:29
yarp::sig::Matrix::subrow
Vector subrow(size_t r, size_t c, size_t size) const
Get a subrow of the matrix as a vector.
Definition: Matrix.cpp:403
Vector.h
contains the definition of a Vector type
yarp::sig
Signal processing.
Definition: Image.h:25
t
float t
Definition: FfmpegWriter.cpp:74
YARP_END_PACK
#define YARP_END_PACK
Ends 1 byte packing for structs/classes.
Definition: system.h:194
BOTTLE_TAG_LIST
#define BOTTLE_TAG_LIST
Definition: Bottle.h:30
yarp::os::ConnectionWriter::appendFloat64
virtual void appendFloat64(yarp::conf::float64_t data)=0
Send a representation of a 64-bit floating point number to the network connection.
ConnectionWriter.h
NetInt32.h
yarp::sig::Matrix::setSubrow
bool setSubrow(const Vector &v, size_t r, size_t c)
Set a portion of a row of this matrix with the values of the specified vector v.
Definition: Matrix.cpp:512
yarp::sig::removeCols
bool removeCols(const Matrix &in, Matrix &out, size_t first_col, size_t how_many)
Definition: Matrix.cpp:50
yarp::sig::Matrix::transposed
Matrix transposed() const
Return the transposed of the matrix.
Definition: Matrix.cpp:369
yarp::sig::Matrix::diagonal
const Matrix & diagonal(const Vector &d)
Build a diagonal matrix, don't resize.
Definition: Matrix.cpp:443
YARP_BEGIN_PACK
#define YARP_BEGIN_PACK
Starts 1 byte packing for structs/classes.
Definition: system.h:193
yarp::sig::Matrix::removeCols
Matrix removeCols(size_t first_col, size_t how_many)
Modifies the matrix, removing one or more columns from it.
Definition: Matrix.cpp:313
yarp::sig::Matrix::rows
size_t rows() const
Return number of rows.
Definition: Matrix.h:95
Matrix.h
contains the definition of a Matrix type
MatrixPortContentHeader::listLen
yarp::os::NetInt32 listLen
Definition: Matrix.cpp:41
ret
bool ret
Definition: ImplementAxisInfo.cpp:72
yarp::sig::Matrix::setSubcol
bool setSubcol(const Vector &v, size_t r, size_t c)
Set a portion of a column of this matrix with the values of the specified vector v.
Definition: Matrix.cpp:523
BOTTLE_TAG_INT32
#define BOTTLE_TAG_INT32
Definition: Bottle.h:23
MatrixPortContentHeader
Definition: Matrix.cpp:32
yarp::sig::Matrix::~Matrix
~Matrix()
Destructor.
Definition: Matrix.cpp:242
yarp::sig::VectorOf< double >
yarp::sig::Matrix::read
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
Definition: Matrix.cpp:112
yarp::os::ConnectionReader::expectFloat64
virtual yarp::conf::float64_t expectFloat64()=0
Read a 64-bit floating point number from the network connection.
ManagedBytes.h
yarp::os::ConnectionWriter
An interface for writing to a network connection.
Definition: ConnectionWriter.h:40
yarp::sig::Matrix::eye
const Matrix & eye()
Build an identity matrix, don't resize.
Definition: Matrix.cpp:429
yarp::sig::Matrix::setCol
bool setCol(size_t col, const Vector &c)
Set a column of the matrix copying the values from a vector: the vector length must be equal to the n...
Definition: Matrix.cpp:490
NetFloat64.h
MatrixPortContentHeader::colsTag
yarp::os::NetInt32 colsTag
Definition: Matrix.cpp:38
buffer
Definition: V4L_camera.h:75
yarp::os::ConnectionReader::convertTextMode
virtual bool convertTextMode()=0
Reads in a standard description in text mode, and converts it to a standard description in binary.
yarp::sig::VectorOf::length
size_t length() const
Get the length of the vector.
Definition: Vector.h:363
yarp::sig::Matrix::Matrix
Matrix()
Definition: Matrix.h:61
MatrixPortContentHeader::listTag
yarp::os::NetInt32 listTag
Definition: Matrix.cpp:40
yarp::sig::Matrix::cols
size_t cols() const
Return number of columns.
Definition: Matrix.h:101
MatrixPortContentHeader::cols
yarp::os::NetInt32 cols
Definition: Matrix.cpp:39
system.h
yarp::sig::Matrix::resize
void resize(size_t r, size_t c)
Resize the matrix, if matrix is not empty preserve old content.
Definition: Matrix.cpp:251
yarp::os::ConnectionWriter::convertTextMode
virtual bool convertTextMode()=0
Converts a standard description in binary into a textual description, if the connection is in text-mo...
MatrixPortContentHeader::MatrixPortContentHeader
MatrixPortContentHeader()=default
yarp::os::ConnectionReader
An interface for reading from a network connection.
Definition: ConnectionReader.h:40
MatrixPortContentHeader::outerListLen
yarp::os::NetInt32 outerListLen
Definition: Matrix.cpp:35
BOTTLE_TAG_FLOAT64
#define BOTTLE_TAG_FLOAT64
Definition: Bottle.h:27
yarp::sig::Matrix::data
double * data()
Return a pointer to the first element.
Definition: Matrix.h:304
yarp::sig::Matrix::subcol
Vector subcol(size_t r, size_t c, size_t size) const
Get a subcolumn of the matrix as a vector.
Definition: Matrix.cpp:416
yarp::sig::Matrix::write
bool write(yarp::os::ConnectionWriter &connection) const override
Write vector to a connection.
Definition: Matrix.cpp:139
yarp::sig::Vector
VectorOf< double > Vector
Definition: Vector.h:33
yarp::os
An interface to the operating system, including Port based communication.
Definition: AbstractCarrier.h:17
yarp::sig::Matrix::getCol
Vector getCol(size_t c) const
Get a columns of the matrix as a vector.
Definition: Matrix.cpp:392
yarp
The main, catch-all namespace for YARP.
Definition: environment.h:18
yarp::sig::submatrix
bool submatrix(const Matrix &in, Matrix &out, size_t r1, size_t r2, size_t c1, size_t c2)
Definition: Matrix.cpp:90
yarp::sig::Matrix::operator==
bool operator==(const yarp::sig::Matrix &r) const
True iff all elements of a match all element of b.
Definition: Matrix.cpp:457
MatrixPortContentHeader::rowsTag
yarp::os::NetInt32 rowsTag
Definition: Matrix.cpp:36
yarp::sig::Matrix::removeRows
Matrix removeRows(size_t first_row, size_t how_many)
Modifies the matrix, removing one or more rows from it.
Definition: Matrix.cpp:341
yarp::sig::Matrix::zero
void zero()
Zero the matrix.
Definition: Matrix.cpp:308
yarp::sig::VectorOf::size
size_t size() const
Definition: Vector.h:355
yarp::os::ConnectionReader::expectBlock
virtual bool expectBlock(char *data, size_t len)=0
Read a block of data from the network connection.
yarp::sig::Matrix::getRow
Vector getRow(size_t r) const
Get a row of the matrix as a vector.
Definition: Matrix.cpp:381
yarp::sig::Matrix::operator=
const Matrix & operator=(const Matrix &r)
Copy operator.
Definition: Matrix.cpp:207
yarp::sig::Matrix::setRow
bool setRow(size_t row, const Vector &r)
Set a row of the matrix copying the values from a vector: the vector length must be equal to the numb...
Definition: Matrix.cpp:479
MatrixPortContentHeader::outerListTag
yarp::os::NetInt32 outerListTag
Definition: Matrix.cpp:34
Bottle.h
MatrixPortContentHeader::rows
yarp::os::NetInt32 rows
Definition: Matrix.cpp:37
ConnectionReader.h
yarp::sig::Matrix
A class for a Matrix.
Definition: Matrix.h:46
yarp::sig::Matrix::setSubmatrix
bool setSubmatrix(const Matrix &m, size_t r, size_t c)
Set a portion of this matrix with the values of the specified matrix m.
Definition: Matrix.cpp:501
yarp::os::NetInt32
std::int32_t NetInt32
Definition of the NetInt32 type.
Definition: NetInt32.h:33