Visual Servoing Platform  version 3.1.0
vpRowVector.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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 
676 void vpRowVector::stack(const double &d)
677 {
678  this->resize(colNum + 1, false);
679  (*this)[colNum - 1] = d;
680 }
681 
701 void vpRowVector::stack(const vpRowVector &v) { *this = vpRowVector::stack(*this, v); }
702 
724 {
725  vpRowVector C;
726  vpRowVector::stack(A, B, C);
727  return C;
728 }
729 
751 {
752  unsigned int nrA = A.getCols();
753  unsigned int nrB = B.getCols();
754 
755  if (nrA == 0 && nrB == 0) {
756  C.resize(0);
757  return;
758  }
759 
760  if (nrB == 0) {
761  C = A;
762  return;
763  }
764 
765  if (nrA == 0) {
766  C = B;
767  return;
768  }
769 
770  // General case
771  C.resize(nrA + nrB);
772 
773  for (unsigned int i = 0; i < nrA; i++)
774  C[i] = A[i];
775 
776  for (unsigned int i = 0; i < nrB; i++)
777  C[nrA + i] = B[i];
778 }
779 
784 {
785  if (v.data == NULL || v.size() == 0) {
786  throw(vpException(vpException::dimensionError, "Cannot compute mean value of an empty row vector"));
787  }
788 
789  double mean = 0;
790  double *vd = v.data;
791  for (unsigned int i = 0; i < v.getCols(); i++)
792  mean += *(vd++);
793 
794  return mean / v.getCols();
795 }
796 
801 {
802  if (v.data == NULL || v.size() == 0) {
803  throw(vpException(vpException::dimensionError, "Cannot compute mean value of an empty row vector"));
804  }
805 
806  std::vector<double> vectorOfDoubles(v.data, v.data + v.colNum);
807 
808  return vpMath::getMedian(vectorOfDoubles);
809 }
810 
814 double vpRowVector::stdev(const vpRowVector &v, const bool useBesselCorrection)
815 {
816  if (v.data == NULL || v.size() == 0) {
817  throw(vpException(vpException::dimensionError, "Cannot compute mean value of an empty row vector"));
818  }
819 
820  double mean_value = mean(v);
821  double sum_squared_diff = 0.0;
822  for (unsigned int i = 0; i < v.size(); i++) {
823  sum_squared_diff += (v[i] - mean_value) * (v[i] - mean_value);
824  }
825 
826  double divisor = (double)v.size();
827  if (useBesselCorrection && v.size() > 1) {
828  divisor = divisor - 1;
829  }
830 
831  return std::sqrt(sum_squared_diff / divisor);
832 }
833 
853 int vpRowVector::print(std::ostream &s, unsigned int length, char const *intro) const
854 {
855  typedef std::string::size_type size_type;
856 
857  unsigned int m = 1;
858  unsigned int n = getCols();
859 
860  std::vector<std::string> values(m * n);
861  std::ostringstream oss;
862  std::ostringstream ossFixed;
863  std::ios_base::fmtflags original_flags = oss.flags();
864 
865  // ossFixed <<std::fixed;
866  ossFixed.setf(std::ios::fixed, std::ios::floatfield);
867 
868  size_type maxBefore = 0; // the length of the integral part
869  size_type maxAfter = 0; // number of decimals plus
870  // one place for the decimal point
871  for (unsigned int j = 0; j < n; ++j) {
872  oss.str("");
873  oss << (*this)[j];
874  if (oss.str().find("e") != std::string::npos) {
875  ossFixed.str("");
876  ossFixed << (*this)[j];
877  oss.str(ossFixed.str());
878  }
879 
880  values[j] = oss.str();
881  size_type thislen = values[j].size();
882  size_type p = values[j].find('.');
883 
884  if (p == std::string::npos) {
885  maxBefore = vpMath::maximum(maxBefore, thislen);
886  // maxAfter remains the same
887  } else {
888  maxBefore = vpMath::maximum(maxBefore, p);
889  maxAfter = vpMath::maximum(maxAfter, thislen - p - 1);
890  }
891  }
892 
893  size_type totalLength = length;
894  // increase totalLength according to maxBefore
895  totalLength = vpMath::maximum(totalLength, maxBefore);
896  // decrease maxAfter according to totalLength
897  maxAfter = (std::min)(maxAfter, totalLength - maxBefore);
898  if (maxAfter == 1)
899  maxAfter = 0;
900 
901  // the following line is useful for debugging
902  // std::cerr <<totalLength <<" " <<maxBefore <<" " <<maxAfter <<"\n";
903 
904  if (intro)
905  s << intro;
906  s << "[" << m << "," << n << "]=\n";
907 
908  s << " ";
909  for (unsigned int j = 0; j < n; j++) {
910  size_type p = values[j].find('.');
911  s.setf(std::ios::right, std::ios::adjustfield);
912  s.width((std::streamsize)maxBefore);
913  s << values[j].substr(0, p).c_str();
914 
915  if (maxAfter > 0) {
916  s.setf(std::ios::left, std::ios::adjustfield);
917  if (p != std::string::npos) {
918  s.width((std::streamsize)maxAfter);
919  s << values[j].substr(p, maxAfter).c_str();
920  } else {
921  assert(maxAfter > 1);
922  s.width((std::streamsize)maxAfter);
923  s << ".0";
924  }
925  }
926 
927  s << ' ';
928  }
929  s << std::endl;
930 
931  s.flags(original_flags); // restore s to standard state
932 
933  return (int)(maxBefore + maxAfter);
934 }
935 
939 vpRowVector operator*(const double &x, const vpRowVector &v)
940 {
941  vpRowVector vout;
942  vout = v * x;
943  return vout;
944 }
945 
951 double vpRowVector::sum() const
952 {
953  double sum = 0.0;
954 
955  for (unsigned int j = 0; j < colNum; j++) {
956  sum += rowPtrs[0][j];
957  }
958 
959  return sum;
960 }
961 
969 {
970  double sum_square = 0.0;
971 
972  for (unsigned int j = 0; j < colNum; j++) {
973  double x = rowPtrs[0][j];
974  sum_square += x * x;
975  }
976 
977  return sum_square;
978 }
979 
986 {
987  double norm = 0.0;
988  for (unsigned int i = 0; i < dsize; i++) {
989  double x = *(data + i);
990  norm += x * x;
991  }
992 
993  return sqrt(norm);
994 }
995 
1031 void vpRowVector::init(const vpRowVector &v, unsigned int c, unsigned int ncols)
1032 {
1033  unsigned int cncols = c + ncols;
1034 
1035  if (cncols > v.getCols())
1036  throw(vpException(vpException::dimensionError, "Bad column dimension (%d > %d) used to initialize vpRowVector",
1037  cncols, v.getCols()));
1038  resize(ncols);
1039  if (this->rowPtrs == NULL) // Fix coverity scan: explicit null dereferenced
1040  return; // Noting to do
1041  for (unsigned int i = 0; i < ncols; i++)
1042  (*this)[i] = v[i + c];
1043 }
1044 
1075 std::ostream &vpRowVector::cppPrint(std::ostream &os, const std::string &matrixName, bool octet) const
1076 {
1077  os << "vpRowVector " << matrixName << " (" << this->getCols() << "); " << std::endl;
1078 
1079  for (unsigned int j = 0; j < this->getCols(); ++j) {
1080  if (!octet) {
1081  os << matrixName << "[" << j << "] = " << (*this)[j] << "; " << std::endl;
1082  } else {
1083  for (unsigned int k = 0; k < sizeof(double); ++k) {
1084  os << "((unsigned char*)&(" << matrixName << "[" << j << "]) )[" << k << "] = 0x" << std::hex
1085  << (unsigned int)((unsigned char *)&((*this)[j]))[k] << "; " << std::endl;
1086  }
1087  }
1088  }
1089  std::cout << std::endl;
1090  return os;
1091 }
1092 
1117 std::ostream &vpRowVector::csvPrint(std::ostream &os) const
1118 {
1119  for (unsigned int j = 0; j < this->getCols(); ++j) {
1120  os << (*this)[j];
1121  if (!(j == (this->getCols() - 1)))
1122  os << ", ";
1123  }
1124  os << std::endl;
1125  return os;
1126 }
1127 
1151 std::ostream &vpRowVector::maplePrint(std::ostream &os) const
1152 {
1153  os << "([ " << std::endl;
1154  os << "[";
1155  for (unsigned int j = 0; j < this->getCols(); ++j) {
1156  os << (*this)[j] << ", ";
1157  }
1158  os << "]," << std::endl;
1159  os << "])" << std::endl;
1160  return os;
1161 }
1162 
1193 std::ostream &vpRowVector::matlabPrint(std::ostream &os) const
1194 {
1195  os << "[ ";
1196  for (unsigned int j = 0; j < this->getCols(); ++j) {
1197  os << (*this)[j] << ", ";
1198  }
1199  os << "]" << std::endl;
1200  return os;
1201 }
vpRowVector & operator/=(double x)
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
vpRowVector & normalize()
static double median(const vpRowVector &v)
vpRowVector operator+(const vpRowVector &v) const
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
error that can be emited by ViSP classes.
Definition: vpException.h:71
unsigned int getRows() const
Definition: vpArray2D.h:156
static double mean(const vpRowVector &v)
vp_deprecated void init()
Definition: vpRowVector.h:262
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
std::ostream & cppPrint(std::ostream &os, const std::string &matrixName="A", bool octet=false) const
vpRowVector operator/(const double x) const
std::ostream & matlabPrint(std::ostream &os) const
int print(std::ostream &s, unsigned int length, char const *intro=0) const
std::ostream & csvPrint(std::ostream &os) const
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
unsigned int getCols() const
Definition: vpArray2D.h:146
std::ostream & maplePrint(std::ostream &os) const
unsigned int rowNum
Number of rows in the array.
Definition: vpArray2D.h:74
double operator*(const vpColVector &x) const
void stack(const double &d)
vpRowVector & operator-=(vpRowVector v)
vpColVector transpose() 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)
vpColVector t() const
vpRowVector & operator<<(const vpRowVector &v)
double sum() const
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
vpRowVector & operator*=(double x)
vpRowVector & operator=(const vpRowVector &v)
Copy operator. Allow operation such as A = v.
Definition: vpRowVector.cpp:58
double sumSquare() const
unsigned int dsize
Current array size (rowNum * colNum)
Definition: vpArray2D.h:80
double euclideanNorm() 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)
vpRowVector operator-() const