Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
testColVector.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  * Test some vpColVector functionalities.
33  *
34  * Authors:
35  * Eric Marchand
36  *
37  *****************************************************************************/
38 
45 #include <stdio.h>
46 #include <stdlib.h>
47 
48 #include <visp3/core/vpColVector.h>
49 #include <visp3/core/vpGaussRand.h>
50 #include <visp3/core/vpMath.h>
51 
52 namespace
53 {
54 bool test(const std::string &s, const vpColVector &v, const std::vector<double> &bench)
55 {
56  static unsigned int cpt = 0;
57  std::cout << "** Test " << ++cpt << std::endl;
58  std::cout << s << "(" << v.getRows() << "," << v.getCols() << ") = [" << v.t() << "]^T" << std::endl;
59  if (bench.size() != v.size()) {
60  std::cout << "Test fails: bad size wrt bench" << std::endl;
61  return false;
62  }
63  for (unsigned int i = 0; i < v.size(); i++) {
64  if (std::fabs(v[i] - bench[i]) > std::fabs(v[i]) * std::numeric_limits<double>::epsilon()) {
65  std::cout << "Test fails: bad content" << std::endl;
66  return false;
67  }
68  }
69 
70  return true;
71 }
72 
73 double computeRegularSum(const vpColVector &v)
74 {
75  double sum = 0.0;
76 
77  for (unsigned int i = 0; i < v.getRows(); i++) {
78  sum += v[i];
79  }
80 
81  return sum;
82 }
83 
84 double computeRegularSumSquare(const vpColVector &v)
85 {
86  double sum_square = 0.0;
87 
88  for (unsigned int i = 0; i < v.getRows(); i++) {
89  sum_square += v[i] * v[i];
90  }
91 
92  return sum_square;
93 }
94 
95 double computeRegularStdev(const vpColVector &v)
96 {
97  double mean_value = computeRegularSum(v) / v.getRows();
98  double sum_squared_diff = 0.0;
99 
100  for (unsigned int i = 0; i < v.size(); i++) {
101  sum_squared_diff += (v[i] - mean_value) * (v[i] - mean_value);
102  }
103 
104  double divisor = (double)v.size();
105 
106  return std::sqrt(sum_squared_diff / divisor);
107 }
108 
109 double getRandomValues(double min, double max)
110 {
111  return (max - min) * ((double)rand() / (double)RAND_MAX) + min;
112 }
113 }
114 
115 int main()
116 {
117  {
118  vpColVector v1(7, 0.1), v2;
119  if (v1 == v2) {
120  std::cerr << "Issue with vpColVector comparison operator." << std::endl;
121  return EXIT_FAILURE;
122  }
123  v2 = v1;
124  if (v1 != v2) {
125  std::cerr << "Issue with vpColVector comparison operator." << std::endl;
126  return EXIT_FAILURE;
127  }
128  v2[3] = 0.2;
129  if (v1 == v2) {
130  std::cerr << "Issue with vpColVector comparison operator." << std::endl;
131  return EXIT_FAILURE;
132  }
133  }
134  {
135  vpColVector v;
136 
137  v.resize(4);
138  v = 3;
139  std::vector<double> bench1(4, 3);
140  if (test("v", v, bench1) == false)
141  return EXIT_FAILURE;
142  std::vector<double> bench2(4, 3. / 6);
143  v.normalize();
144  if (test("v", v, bench2) == false)
145  return EXIT_FAILURE;
146 
147  v.resize(5, 1, true);
148  std::vector<double> bench3(5, 0);
149  if (test("v", v, bench3) == false)
150  return EXIT_FAILURE;
151  }
152 
153  {
154  vpColVector v(4);
155  std::vector<double> bench1(4);
156  for (unsigned int i = 0; i < v.size(); i++) {
157  v[i] = (double)i;
158  bench1[i] = (double)i;
159  }
160  if (test("v", v, bench1) == false)
161  return EXIT_FAILURE;
162 
163  vpColVector w;
164  w.init(v, 0, 2);
165  std::vector<double> bench2;
166  bench2.push_back(0);
167  bench2.push_back(1);
168  if (test("w", w, bench2) == false)
169  return EXIT_FAILURE;
170 
171  std::vector<double> bench3;
172  bench3.push_back(1);
173  bench3.push_back(2);
174  bench3.push_back(3);
175 
176  vpColVector r1;
177  for (size_t i = 0; i < 4; i++)
178  r1.stack((double)i);
179 
180  vpColVector r2 = r1.extract(1, 3);
181  if (test("r2", r2, bench3) == false)
182  return EXIT_FAILURE;
183  }
184 
185  {
186  vpMatrix M(4, 1);
187  std::vector<double> bench(4);
188  for (unsigned int i = 0; i < M.getRows(); i++) {
189  M[i][0] = i;
190  bench[i] = i;
191  }
192  if (test("M", M, bench) == false)
193  return EXIT_FAILURE;
194  vpColVector v;
195  v = M;
196  if (test("v", v, bench) == false)
197  return EXIT_FAILURE;
198  vpColVector w(M);
199  if (test("w", w, bench) == false)
200  return EXIT_FAILURE;
201  vpColVector z1(bench);
202  if (test("z1", z1, bench) == false)
203  return EXIT_FAILURE;
204  vpColVector z2 = bench;
205  if (test("z2", z2, bench) == false)
206  return EXIT_FAILURE;
207  }
208 
209  {
210  vpColVector v(3);
211  v[0] = 1;
212  v[1] = 2;
213  v[2] = 3;
214  std::vector<double> bench1;
215  bench1.push_back(3);
216  bench1.push_back(6);
217  bench1.push_back(9);
218 
219  vpColVector w = v * 3;
220  // v is unchanged
221  // w is now equal to : [3 6 9]
222  if (test("w", w, bench1) == false)
223  return EXIT_FAILURE;
224 
225  vpColVector x(w);
226  if (test("x", x, bench1) == false)
227  return EXIT_FAILURE;
228 
229  std::vector<float> bench2;
230  bench2.push_back(3);
231  bench2.push_back(6);
232  bench2.push_back(9);
233  vpColVector y1(bench2);
234  if (test("y1", y1, bench1) == false)
235  return EXIT_FAILURE;
236  vpColVector y2 = bench2;
237  if (test("y2", y2, bench1) == false)
238  return EXIT_FAILURE;
239  }
240 
241  {
242  vpColVector r1(3, 1);
243  vpColVector r2 = -r1;
244  std::vector<double> bench(3, -1);
245  // v contains [-1 -1 -1]
246  if (test("r2", r2, bench) == false)
247  return EXIT_FAILURE;
248  r2.stack(-2);
249  bench.push_back(-2);
250  if (test("r2", r2, bench) == false)
251  return EXIT_FAILURE;
252  vpColVector r3 = vpColVector::stack(r1, r2);
253  std::vector<double> bench3(7, 1);
254  bench3[3] = bench3[4] = bench3[5] = -1;
255  bench3[6] = -2;
256  if (test("r3", r3, bench3) == false)
257  return EXIT_FAILURE;
258 
259  r1.stack(r2);
260  if (test("r1", r1, bench3) == false)
261  return EXIT_FAILURE;
262  }
263 
264  {
265  vpColVector r1(3, 2);
266  vpColVector r2(3, 4);
267  std::cout << "test r1: " << r1 << std::endl;
268  std::cout << "test r2: " << r2 << std::endl;
269  vpColVector r = r1 + r2;
270  std::cout << "test r1+r2: " << r1 + r2 << std::endl;
271  std::cout << "test r: " << r << std::endl;
272  std::vector<double> bench(3, 6);
273  if (test("r", r, bench) == false)
274  return EXIT_FAILURE;
275  r1 += r2;
276  if (test("r1", r1, bench) == false)
277  return EXIT_FAILURE;
278  }
279 
280  {
281  vpColVector r1(3, 2);
282  vpColVector r2(3, 4);
283  vpColVector r = r1 - r2;
284  std::vector<double> bench(3, -2);
285  if (test("r", r, bench) == false)
286  return EXIT_FAILURE;
287  r1 -= r2;
288  if (test("r1", r1, bench) == false)
289  return EXIT_FAILURE;
290  }
291 
292  {
293  vpColVector r(5, 1);
294  r.clear();
295  r.resize(5);
296  r = 5;
297  std::vector<double> bench(5, 5);
298  if (test("r", r, bench) == false)
299  return EXIT_FAILURE;
300  }
301 
302  {
303  // Test mean, median and standard deviation against Matlab with rng(0) and
304  // rand(10,1)*10
305  vpColVector r(10);
306  r[0] = 8.1472;
307  r[1] = 9.0579;
308  r[2] = 1.2699;
309  r[3] = 9.1338;
310  r[4] = 6.3236;
311  r[5] = 0.9754;
312  r[6] = 2.7850;
313  r[7] = 5.4688;
314  r[8] = 9.5751;
315  r[9] = 9.6489;
316 
317  std::cout << "** Test mean" << std::endl;
318  double res = vpColVector::mean(r);
319  if (!vpMath::equal(res, 6.2386, 0.001)) {
320  std::cout << "Test fails: bad mean " << res << std::endl;
321  return EXIT_FAILURE;
322  }
323 
324  std::cout << "** Test stdev" << std::endl;
325  res = vpColVector::stdev(r);
326  if (!vpMath::equal(res, 3.2810, 0.001)) {
327  std::cout << "Test fails: bad stdev " << res << std::endl;
328  return EXIT_FAILURE;
329  }
330 
331  std::cout << "** Test stdev(bessel)" << std::endl;
332  res = vpColVector::stdev(r, true);
333  if (!vpMath::equal(res, 3.4585, 0.001)) {
334  std::cout << "Test fails: bad stdev(bessel) " << res << std::endl;
335  return EXIT_FAILURE;
336  }
337 
338  std::cout << "** Test median" << std::endl;
339  res = vpColVector::median(r);
340  if (!vpMath::equal(res, 7.2354, 0.001)) {
341  std::cout << "Test fails: bad median " << res << std::endl;
342  return EXIT_FAILURE;
343  }
344 
345  // Test median with odd number of elements
346  std::cout << "** Test median (odd)" << std::endl;
347  r.stack(1.5761);
348  res = vpColVector::median(r);
349  if (!vpMath::equal(res, 6.3236, 0.001)) {
350  std::cout << "Test fails: bad median (odd) " << res << std::endl;
351  return EXIT_FAILURE;
352  }
353  std::cout << "r: [" << r << "]^T" << std::endl;
354  r.print(std::cout, 8, "r");
355  }
356 
357  // Test sum, sumSquare, stdev
358  {
359  srand(0);
360  vpGaussRand noise(10.0, 0.0);
361 
362  int nbIterations = 1000;
363  unsigned int size = 117;
364 
365  vpColVector v(size);
366  for (unsigned int cpt = 0; cpt < v.getRows(); cpt++) {
367  v[cpt] = rand() % 1000 + noise();
368  }
369 
370  std::cout << "\nv.getRows()=" << v.getRows() << std::endl;
371 
372  double regular_sum = 0.0;
373  double t_regular = vpTime::measureTimeMs();
374  for (int iteration = 0; iteration < nbIterations; iteration++) {
375  regular_sum += computeRegularSum(v);
376  }
377  t_regular = vpTime::measureTimeMs() - t_regular;
378 
379  double sse_sum = 0.0;
380  double t_sse = vpTime::measureTimeMs();
381  for (int iteration = 0; iteration < nbIterations; iteration++) {
382  sse_sum += v.sum();
383  }
384  t_sse = vpTime::measureTimeMs() - t_sse;
385 
386  std::cout << "\nregular_sum=" << regular_sum << " ; sse_sum=" << sse_sum << std::endl;
387  std::cout << "t_regular=" << t_regular << " ms ; t_sse=" << t_sse << " ms" << std::endl;
388  std::cout << "Speed-up: " << (t_regular / t_sse) << "X" << std::endl;
389 
390  if (!vpMath::equal(regular_sum, sse_sum, std::numeric_limits<double>::epsilon())) {
391  std::cerr << "Problem when computing v.sum()!" << std::endl;
392  return EXIT_FAILURE;
393  }
394 
395  double regular_sumSquare = 0.0;
396  t_regular = vpTime::measureTimeMs();
397  for (int iteration = 0; iteration < nbIterations; iteration++) {
398  regular_sumSquare += computeRegularSumSquare(v);
399  }
400  t_regular = vpTime::measureTimeMs() - t_regular;
401 
402  double sse_sumSquare = 0.0;
403  t_sse = vpTime::measureTimeMs();
404  for (int iteration = 0; iteration < nbIterations; iteration++) {
405  sse_sumSquare += v.sumSquare();
406  }
407  t_sse = vpTime::measureTimeMs() - t_sse;
408 
409  std::cout << "\nregular_sumSquare=" << regular_sumSquare << " ; sse_sumSquare=" << sse_sumSquare << std::endl;
410  std::cout << "t_regular=" << t_regular << " ms ; t_sse=" << t_sse << " ms" << std::endl;
411  std::cout << "Speed-up: " << (t_regular / t_sse) << "X" << std::endl;
412 
413  if (!vpMath::equal(regular_sumSquare, sse_sumSquare, std::numeric_limits<double>::epsilon())) {
414  std::cerr << "Problem when computing v.sumSquare()!" << std::endl;
415  return EXIT_FAILURE;
416  }
417 
418  double regular_stdev = 0.0;
419  t_regular = vpTime::measureTimeMs();
420  for (int iteration = 0; iteration < nbIterations; iteration++) {
421  regular_stdev += computeRegularStdev(v);
422  }
423  t_regular = vpTime::measureTimeMs() - t_regular;
424 
425  double sse_stdev = 0.0;
426  t_sse = vpTime::measureTimeMs();
427  for (int iteration = 0; iteration < nbIterations; iteration++) {
428  sse_stdev += vpColVector::stdev(v, false);
429  }
430  t_sse = vpTime::measureTimeMs() - t_sse;
431 
432  std::cout << "\nregular_stdev=" << regular_stdev << " ; sse_stdev=" << sse_stdev << std::endl;
433  std::cout << "t_regular=" << t_regular << " ms ; t_sse=" << t_sse << " ms" << std::endl;
434  std::cout << "Speed-up: " << (t_regular / t_sse) << "X" << std::endl;
435 
436  if (!vpMath::equal(regular_stdev, sse_stdev, std::numeric_limits<double>::epsilon())) {
437  std::cerr << "Problem when computing vpColVector::stdev()!" << std::endl;
438  return EXIT_FAILURE;
439  }
440  }
441 
442  {
443  // Test insert with big vector
444  unsigned int nb = 1000;
445  const unsigned int size = 10000;
446  std::vector<vpColVector> vec(nb);
447 
448  for (size_t i = 0; i < nb; i++) {
449  vpColVector v(size);
450  for (unsigned int j = 0; j < size; j++) {
451  v[j] = getRandomValues(-100.0, 100.0);
452  }
453  vec[i] = v;
454  }
455 
456  vpColVector v_big(nb * size);
457  double t = vpTime::measureTimeMs();
458  for (unsigned int i = 0; i < nb; i++) {
459  v_big.insert(i * size, vec[(size_t)i]);
460  }
461  t = vpTime::measureTimeMs() - t;
462  std::cout << "\nBig insert: " << t << " ms" << std::endl;
463 
464  for (unsigned int i = 0; i < nb; i++) {
465  for (unsigned int j = 0; j < size; j++) {
466  if (!vpMath::equal(v_big[i * size + j], vec[(size_t)i][j], std::numeric_limits<double>::epsilon())) {
467  std::cerr << "Problem in vpColVector insert()!" << std::endl;
468  return EXIT_FAILURE;
469  }
470  }
471  }
472 
473  // Try to insert empty vpColVector
474  vpColVector v1(2), v2, v3;
475  v1.insert(0, v2);
476  v3.insert(0, v2);
477 
478  std::cout << "Insert empty vectors:" << std::endl;
479  std::cout << "v1: " << v1.t() << std::endl;
480  std::cout << "v2: " << v2.t() << std::endl;
481  std::cout << "v3: " << v3.t() << std::endl;
482  }
483 
484  {
485  std::cout << "** Test conversion to/from std::vector" << std::endl;
486  std::vector<double> std_vector(5);
487  for (size_t i = 0; i < std_vector.size(); i++) {
488  std_vector[i] = (double) i;
489  }
490  vpColVector v(std_vector);
491  if (test("v", v, std_vector) == false)
492  return EXIT_FAILURE;
493 
494  std_vector.clear();
495  std_vector = v.toStdVector();
496  if (test("v", v, std_vector) == false)
497  return EXIT_FAILURE;
498  }
499  std::cout << "\nAll tests succeed" << std::endl;
500  return EXIT_SUCCESS;
501 }
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:164
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:296
vpColVector extract(unsigned int r, unsigned int colsize) const
Definition: vpColVector.h:220
unsigned int getRows() const
Definition: vpArray2D.h:289
vpRowVector t() const
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:291
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:126
double sum() const
static double median(const vpColVector &v)
unsigned int getCols() const
Definition: vpArray2D.h:279
vpColVector & normalize()
void clear()
Definition: vpColVector.h:175
static double mean(const vpColVector &v)
void insert(unsigned int i, const vpColVector &v)
std::vector< double > toStdVector()
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:310
int print(std::ostream &s, unsigned int length, char const *intro=0) const
Class for generating random number with normal probability density.
Definition: vpGaussRand.h:120
Implementation of column vector and the associated operations.
Definition: vpColVector.h:130
void stack(double d)
void init(const vpColVector &v, unsigned int r, unsigned int nrows)
double sumSquare() const
static double stdev(const vpColVector &v, bool useBesselCorrection=false)