Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
vpRowVector.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Operation on row vectors.
33  *
34  * Authors:
35  * Eric Marchand
36  *
37  *****************************************************************************/
38 
44 #include <assert.h>
45 #include <cmath>
46 #include <sstream>
47 #include <stdlib.h>
48 #include <string.h>
49 
50 #include <visp3/core/vpArray2D.h>
51 #include <visp3/core/vpColVector.h>
52 #include <visp3/core/vpDebug.h>
53 #include <visp3/core/vpException.h>
54 #include <visp3/core/vpMatrix.h>
55 #include <visp3/core/vpRowVector.h>
56 
59 {
60  unsigned int k = v.colNum;
61  if (colNum != k) {
62  try {
63  resize(k);
64  } catch (...) {
65  throw;
66  }
67  }
68 
69  memcpy(data, v.data, colNum * sizeof(double));
70 
71  return *this;
72 }
73 
82 {
83  if (M.getRows() != 1) {
84  throw(vpException(vpException::dimensionError, "Cannot initialize a (1x%d) row vector from a (%dx%d) matrix",
85  M.getCols(), M.getRows(), M.getCols()));
86  }
87 
88  if (M.getCols() != colNum)
89  resize(M.getCols());
90 
91  memcpy(data, M.data, colNum * sizeof(double));
92  return *this;
93 }
94 
98 vpRowVector &vpRowVector::operator=(const std::vector<double> &v)
99 {
100  resize((unsigned int)v.size());
101  for (unsigned int i = 0; i < v.size(); i++)
102  (*this)[i] = v[i];
103  return *this;
104 }
108 vpRowVector &vpRowVector::operator=(const std::vector<float> &v)
109 {
110  resize((unsigned int)v.size());
111  for (unsigned int i = 0; i < v.size(); i++)
112  (*this)[i] = (float)v[i];
113  return *this;
114 }
115 
118 {
119  for (unsigned int i = 0; i < rowNum; i++) {
120  for (unsigned int j = 0; j < colNum; j++) {
121  rowPtrs[i][j] = x;
122  }
123  }
124  return *this;
125 }
126 
141 double vpRowVector::operator*(const vpColVector &x) const
142 {
143  unsigned int nelements = x.getRows();
144  if (getCols() != nelements) {
145  throw(vpException(vpException::dimensionError, "Cannot multiply (1x%d) row vector by (%dx1) column vector", colNum,
146  x.getRows()));
147  }
148 
149  double scalar = 0.0;
150 
151  for (unsigned int i = 0; i < nelements; i++) {
152  scalar += (*this)[i] * x[i];
153  }
154  return scalar;
155 }
172 {
173  vpRowVector c(M.getCols());
174 
175  if (colNum != M.getRows()) {
176  throw(vpException(vpException::dimensionError, "Cannot multiply (1x%d) row vector by (%dx%d) matrix", colNum,
177  M.getRows(), M.getCols()));
178  }
179 
180  c = 0.0;
181 
182  for (unsigned int i = 0; i < colNum; i++) {
183  double bi = data[i]; // optimization em 5/12/2006
184  for (unsigned int j = 0; j < M.getCols(); j++) {
185  c[j] += bi * M[i][j];
186  }
187  }
188 
189  return c;
190 }
191 
212 {
213  vpRowVector v(colNum);
214 
215  double *vd = v.data;
216  double *d = data;
217 
218  for (unsigned int i = 0; i < colNum; i++)
219  *(vd++) = (*d++) * x;
220  return v;
221 }
222 
241 {
242  for (unsigned int i = 0; i < colNum; i++)
243  (*this)[i] *= x;
244  return (*this);
245 }
246 
267 {
268  vpRowVector v(colNum);
269 
270  double *vd = v.data;
271  double *d = data;
272 
273  for (unsigned int i = 0; i < colNum; i++)
274  *(vd++) = (*d++) / x;
275  return v;
276 }
277 
297 {
298  for (unsigned int i = 0; i < colNum; i++)
299  (*this)[i] /= x;
300  return (*this);
301 }
302 
314 {
315  vpRowVector A(colNum);
316 
317  double *vd = A.data;
318  double *d = data;
319 
320  for (unsigned int i = 0; i < colNum; i++)
321  *(vd++) = -(*d++);
322 
323  return A;
324 }
325 
331 {
332  if (getCols() != m.getCols()) {
333  throw(vpException(vpException::dimensionError, "Cannot substract (1x%d) row vector to (1x%d) row vector", getCols(),
334  m.getCols()));
335  }
336 
337  vpRowVector v(colNum);
338 
339  for (unsigned int i = 0; i < colNum; i++)
340  v[i] = (*this)[i] - m[i];
341  return v;
342 }
343 
349 {
350  if (getCols() != v.getCols()) {
351  throw(vpException(vpException::dimensionError, "Cannot add (1x%d) row vector to (1x%d) row vector", getCols(),
352  v.getCols()));
353  }
354 
355  vpRowVector r(colNum);
356 
357  for (unsigned int i = 0; i < colNum; i++)
358  r[i] = (*this)[i] + v[i];
359  return r;
360 }
361 
368 {
369  if (getCols() != v.getCols()) {
370  throw(vpException(vpException::dimensionError, "Cannot add (1x%d) row vector to (1x%d) row vector", getCols(),
371  v.getCols()));
372  }
373 
374  for (unsigned int i = 0; i < colNum; i++)
375  (*this)[i] += v[i];
376  return (*this);
377 }
378 
385 {
386  if (getCols() != v.getCols()) {
387  throw(vpException(vpException::dimensionError, "Cannot substract (1x%d) row vector to (1x%d) row vector", getCols(),
388  v.getCols()));
389  }
390 
391  for (unsigned int i = 0; i < colNum; i++)
392  (*this)[i] -= v[i];
393  return (*this);
394 }
395 
418 {
419  *this = v;
420  return *this;
421 }
422 
427 {
428  vpColVector v(colNum);
429  memcpy(v.data, data, colNum * sizeof(double));
430  return v;
431 }
432 
437 vpColVector vpRowVector::transpose() const { return t(); }
442 void vpRowVector::transpose(vpColVector &v) const { v = t(); }
443 
448 vpRowVector::vpRowVector(const vpMatrix &M, unsigned int i) : vpArray2D<double>(1, M.getCols())
449 {
450  for (unsigned int j = 0; j < M.getCols(); j++)
451  (*this)[j] = M[i][j];
452 }
460 {
461  if (M.getRows() != 1) {
462  throw(vpException(vpException::dimensionError, "Cannot construct a (1x%d) row vector from a (%dx%d) matrix",
463  M.getCols(), M.getRows(), M.getCols()));
464  }
465 
466  for (unsigned int j = 0; j < M.getCols(); j++)
467  (*this)[j] = M[0][j];
468 }
469 
473 vpRowVector::vpRowVector(const std::vector<double> &v) : vpArray2D<double>(1, (unsigned int)v.size())
474 {
475  for (unsigned int j = 0; j < v.size(); j++)
476  (*this)[j] = v[j];
477 }
481 vpRowVector::vpRowVector(const std::vector<float> &v) : vpArray2D<double>(1, (unsigned int)v.size())
482 {
483  for (unsigned int j = 0; j < v.size(); j++)
484  (*this)[j] = (double)(v[j]);
485 }
486 
500 vpRowVector::vpRowVector(const vpRowVector &v, unsigned int c, unsigned int ncols) : vpArray2D<double>(1, ncols)
501 {
502  init(v, c, ncols);
503 }
504 
515 {
516  x = x / sqrt(x.sumSquare());
517 
518  return x;
519 }
520 
530 {
531  double sum_square = sumSquare();
532  if (std::fabs(sum_square) > std::numeric_limits<double>::epsilon()) {
533  *this /= sqrt(sum_square);
534  }
535 
536  // If sum = 0, we have a nul vector. So we return just.
537  return *this;
538 }
539 
551 vpMatrix vpRowVector::reshape(const unsigned int &nrows, const unsigned int &ncols)
552 {
553  vpMatrix M(nrows, ncols);
554  reshape(M, nrows, ncols);
555  return M;
556 }
557 
601 void vpRowVector::reshape(vpMatrix &M, const unsigned int &nrows, const unsigned int &ncols)
602 {
603  if (dsize != nrows * ncols) {
604  throw(vpException(vpException::dimensionError, "Cannot reshape (1x%d) row vector in (%dx%d) matrix", colNum,
605  M.getRows(), M.getCols()));
606  }
607  try {
608  if ((M.getRows() != nrows) || (M.getCols() != ncols))
609  M.resize(nrows, ncols);
610  } catch (...) {
611  throw;
612  }
613  for (unsigned int i = 0; i < nrows; i++)
614  for (unsigned int j = 0; j < ncols; j++)
615  M[i][j] = data[i * ncols + j];
616 }
617 
649 void vpRowVector::insert(unsigned int i, const vpRowVector &v)
650 {
651  if (i + v.size() > this->size())
653  "Unable to insert (1x%d) row vector in (1x%d) row "
654  "vector at position (%d)",
655  v.getCols(), colNum, i));
656  for (unsigned int j = 0; j < v.size(); j++)
657  (*this)[i + j] = v[j];
658 }
659 
664 std::vector<double> vpRowVector::toStdVector()
665 {
666  std::vector<double> v(this->size());
667 
668  for (unsigned int i = 0; i < this->size(); i++)
669  v[i] = data[i];
670  return v;
671 }
672 
689 void vpRowVector::stack(double d)
690 {
691  this->resize(colNum + 1, false);
692  (*this)[colNum - 1] = d;
693 }
694 
714 void vpRowVector::stack(const vpRowVector &v) { *this = vpRowVector::stack(*this, v); }
715 
737 {
738  vpRowVector C;
739  vpRowVector::stack(A, B, C);
740  return C;
741 }
742 
764 {
765  unsigned int nrA = A.getCols();
766  unsigned int nrB = B.getCols();
767 
768  if (nrA == 0 && nrB == 0) {
769  C.resize(0);
770  return;
771  }
772 
773  if (nrB == 0) {
774  C = A;
775  return;
776  }
777 
778  if (nrA == 0) {
779  C = B;
780  return;
781  }
782 
783  // General case
784  C.resize(nrA + nrB);
785 
786  for (unsigned int i = 0; i < nrA; i++)
787  C[i] = A[i];
788 
789  for (unsigned int i = 0; i < nrB; i++)
790  C[nrA + i] = B[i];
791 }
792 
797 {
798  if (v.data == NULL || v.size() == 0) {
799  throw(vpException(vpException::dimensionError, "Cannot compute mean value of an empty row vector"));
800  }
801 
802  double mean = 0;
803  double *vd = v.data;
804  for (unsigned int i = 0; i < v.getCols(); i++)
805  mean += *(vd++);
806 
807  return mean / v.getCols();
808 }
809 
814 {
815  if (v.data == NULL || v.size() == 0) {
816  throw(vpException(vpException::dimensionError, "Cannot compute mean value of an empty row vector"));
817  }
818 
819  std::vector<double> vectorOfDoubles(v.data, v.data + v.colNum);
820 
821  return vpMath::getMedian(vectorOfDoubles);
822 }
823 
827 double vpRowVector::stdev(const vpRowVector &v, const bool useBesselCorrection)
828 {
829  if (v.data == NULL || v.size() == 0) {
830  throw(vpException(vpException::dimensionError, "Cannot compute mean value of an empty row vector"));
831  }
832 
833  double mean_value = mean(v);
834  double sum_squared_diff = 0.0;
835  for (unsigned int i = 0; i < v.size(); i++) {
836  sum_squared_diff += (v[i] - mean_value) * (v[i] - mean_value);
837  }
838 
839  double divisor = (double)v.size();
840  if (useBesselCorrection && v.size() > 1) {
841  divisor = divisor - 1;
842  }
843 
844  return std::sqrt(sum_squared_diff / divisor);
845 }
846 
866 int vpRowVector::print(std::ostream &s, unsigned int length, char const *intro) const
867 {
868  typedef std::string::size_type size_type;
869 
870  unsigned int m = 1;
871  unsigned int n = getCols();
872 
873  std::vector<std::string> values(m * n);
874  std::ostringstream oss;
875  std::ostringstream ossFixed;
876  std::ios_base::fmtflags original_flags = oss.flags();
877 
878  // ossFixed <<std::fixed;
879  ossFixed.setf(std::ios::fixed, std::ios::floatfield);
880 
881  size_type maxBefore = 0; // the length of the integral part
882  size_type maxAfter = 0; // number of decimals plus
883  // one place for the decimal point
884  for (unsigned int j = 0; j < n; ++j) {
885  oss.str("");
886  oss << (*this)[j];
887  if (oss.str().find("e") != std::string::npos) {
888  ossFixed.str("");
889  ossFixed << (*this)[j];
890  oss.str(ossFixed.str());
891  }
892 
893  values[j] = oss.str();
894  size_type thislen = values[j].size();
895  size_type p = values[j].find('.');
896 
897  if (p == std::string::npos) {
898  maxBefore = vpMath::maximum(maxBefore, thislen);
899  // maxAfter remains the same
900  } else {
901  maxBefore = vpMath::maximum(maxBefore, p);
902  maxAfter = vpMath::maximum(maxAfter, thislen - p - 1);
903  }
904  }
905 
906  size_type totalLength = length;
907  // increase totalLength according to maxBefore
908  totalLength = vpMath::maximum(totalLength, maxBefore);
909  // decrease maxAfter according to totalLength
910  maxAfter = (std::min)(maxAfter, totalLength - maxBefore);
911  if (maxAfter == 1)
912  maxAfter = 0;
913 
914  // the following line is useful for debugging
915  // std::cerr <<totalLength <<" " <<maxBefore <<" " <<maxAfter <<"\n";
916 
917  if (intro)
918  s << intro;
919  s << "[" << m << "," << n << "]=\n";
920 
921  s << " ";
922  for (unsigned int j = 0; j < n; j++) {
923  size_type p = values[j].find('.');
924  s.setf(std::ios::right, std::ios::adjustfield);
925  s.width((std::streamsize)maxBefore);
926  s << values[j].substr(0, p).c_str();
927 
928  if (maxAfter > 0) {
929  s.setf(std::ios::left, std::ios::adjustfield);
930  if (p != std::string::npos) {
931  s.width((std::streamsize)maxAfter);
932  s << values[j].substr(p, maxAfter).c_str();
933  } else {
934  assert(maxAfter > 1);
935  s.width((std::streamsize)maxAfter);
936  s << ".0";
937  }
938  }
939 
940  s << ' ';
941  }
942  s << std::endl;
943 
944  s.flags(original_flags); // restore s to standard state
945 
946  return (int)(maxBefore + maxAfter);
947 }
948 
952 vpRowVector operator*(const double &x, const vpRowVector &v)
953 {
954  vpRowVector vout;
955  vout = v * x;
956  return vout;
957 }
958 
964 double vpRowVector::sum() const
965 {
966  double sum = 0.0;
967 
968  for (unsigned int j = 0; j < colNum; j++) {
969  sum += rowPtrs[0][j];
970  }
971 
972  return sum;
973 }
974 
982 {
983  double sum_square = 0.0;
984 
985  for (unsigned int j = 0; j < colNum; j++) {
986  double x = rowPtrs[0][j];
987  sum_square += x * x;
988  }
989 
990  return sum_square;
991 }
992 
999 {
1000  double norm = 0.0;
1001  for (unsigned int i = 0; i < dsize; i++) {
1002  double x = *(data + i);
1003  norm += x * x;
1004  }
1005 
1006  return sqrt(norm);
1007 }
1008 
1044 void vpRowVector::init(const vpRowVector &v, unsigned int c, unsigned int ncols)
1045 {
1046  unsigned int cncols = c + ncols;
1047 
1048  if (cncols > v.getCols())
1049  throw(vpException(vpException::dimensionError, "Bad column dimension (%d > %d) used to initialize vpRowVector",
1050  cncols, v.getCols()));
1051  resize(ncols);
1052  if (this->rowPtrs == NULL) // Fix coverity scan: explicit null dereferenced
1053  return; // Noting to do
1054  for (unsigned int i = 0; i < ncols; i++)
1055  (*this)[i] = v[i + c];
1056 }
1057 
1088 std::ostream &vpRowVector::cppPrint(std::ostream &os, const std::string &matrixName, bool octet) const
1089 {
1090  os << "vpRowVector " << matrixName << " (" << this->getCols() << "); " << std::endl;
1091 
1092  for (unsigned int j = 0; j < this->getCols(); ++j) {
1093  if (!octet) {
1094  os << matrixName << "[" << j << "] = " << (*this)[j] << "; " << std::endl;
1095  } else {
1096  for (unsigned int k = 0; k < sizeof(double); ++k) {
1097  os << "((unsigned char*)&(" << matrixName << "[" << j << "]) )[" << k << "] = 0x" << std::hex
1098  << (unsigned int)((unsigned char *)&((*this)[j]))[k] << "; " << std::endl;
1099  }
1100  }
1101  }
1102  std::cout << std::endl;
1103  return os;
1104 }
1105 
1130 std::ostream &vpRowVector::csvPrint(std::ostream &os) const
1131 {
1132  for (unsigned int j = 0; j < this->getCols(); ++j) {
1133  os << (*this)[j];
1134  if (!(j == (this->getCols() - 1)))
1135  os << ", ";
1136  }
1137  os << std::endl;
1138  return os;
1139 }
1140 
1164 std::ostream &vpRowVector::maplePrint(std::ostream &os) const
1165 {
1166  os << "([ " << std::endl;
1167  os << "[";
1168  for (unsigned int j = 0; j < this->getCols(); ++j) {
1169  os << (*this)[j] << ", ";
1170  }
1171  os << "]," << std::endl;
1172  os << "])" << std::endl;
1173  return os;
1174 }
1175 
1206 std::ostream &vpRowVector::matlabPrint(std::ostream &os) const
1207 {
1208  os << "[ ";
1209  for (unsigned int j = 0; j < this->getCols(); ++j) {
1210  os << (*this)[j] << ", ";
1211  }
1212  os << "]" << std::endl;
1213  return os;
1214 }
vpRowVector & operator/=(double x)
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
vpRowVector & normalize()
static double median(const vpRowVector &v)
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:72
static double getMedian(const std::vector< double > &v)
Definition: vpMath.cpp:222
void resize(const unsigned int nrows, const unsigned int ncols, const bool flagNullify=true, const bool recopy_=true)
Definition: vpArray2D.h:171
std::ostream & cppPrint(std::ostream &os, const std::string &matrixName="A", bool octet=false) const
std::vector< double > toStdVector()
error that can be emited by ViSP classes.
Definition: vpException.h:71
static double mean(const vpRowVector &v)
vpRowVector operator+(const vpRowVector &v) const
vp_deprecated void init()
Definition: vpRowVector.h:263
static double stdev(const vpRowVector &v, const bool useBesselCorrection=false)
double * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
Implementation of a generic 2D array used as vase class of matrices and vectors.
Definition: vpArray2D.h:70
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:158
unsigned int getCols() const
Definition: vpArray2D.h:146
double sum() const
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
vpColVector transpose() const
unsigned int rowNum
Number of rows in the array.
Definition: vpArray2D.h:74
vpRowVector operator/(const double x) const
std::ostream & matlabPrint(std::ostream &os) const
vpColVector t() const
double euclideanNorm() const
double operator*(const vpColVector &x) const
vpRowVector & operator-=(vpRowVector v)
void stack(double d)
unsigned int getRows() const
Definition: vpArray2D.h:156
std::ostream & maplePrint(std::ostream &os) const
vpRowVector operator-() const
unsigned int colNum
Number of columns in the array.
Definition: vpArray2D.h:76
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpRowVector.h:213
vpRowVector & operator+=(vpRowVector v)
void reshape(vpMatrix &M, const unsigned int &nrows, const unsigned int &ncols)
std::ostream & csvPrint(std::ostream &os) const
vpRowVector & operator<<(const vpRowVector &v)
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
vpRowVector & operator*=(double x)
int print(std::ostream &s, unsigned int length, char const *intro=0) const
vpRowVector & operator=(const vpRowVector &v)
Copy operator. Allow operation such as A = v.
Definition: vpRowVector.cpp:58
unsigned int dsize
Current array size (rowNum * colNum)
Definition: vpArray2D.h:80
double sumSquare() const
double ** rowPtrs
Address of the first element of each rows.
Definition: vpArray2D.h:78
vpRowVector()
Basic constructor that creates an empty 0-size row vector.
Definition: vpRowVector.h:76
void insert(unsigned int i, const vpRowVector &v)