Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
testArray2D.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Test some vpColVector functionalities.
32  */
33 
40 #include <visp3/core/vpConfig.h>
41 
42 #if defined(VISP_HAVE_CATCH2)
43 #define CATCH_CONFIG_RUNNER
44 
45 #include <catch.hpp>
46 #include <cmath>
47 #include <limits>
48 #include <vector>
49 
50 #include <visp3/core/vpTranslationVector.h>
51 
52 #ifdef ENABLE_VISP_NAMESPACE
53 using namespace VISP_NAMESPACE_NAME;
54 #endif
55 
56 template <typename Type> bool test(const std::string &s, const vpArray2D<Type> &A, const std::vector<Type> &bench)
57 {
58  static unsigned int cpt = 0;
59  std::cout << "** Test " << ++cpt << std::endl;
60  std::cout << s << "(" << A.getRows() << "," << A.getCols() << ") = \n" << A << std::endl;
61  if (bench.size() != A.size()) {
62  std::cout << "Test fails: bad size wrt bench" << std::endl;
63  return false;
64  }
65  for (unsigned int i = 0; i < A.size(); i++) {
66  if (std::fabs(A.data[i] - bench[i]) > std::fabs(A.data[i]) * std::numeric_limits<double>::epsilon()) {
67  std::cout << "Test fails: bad content" << std::endl;
68  return false;
69  }
70  }
71 
72  return true;
73 }
74 
75 template <typename Type>
76 bool test_hadamar(const vpArray2D<Type> &A, const vpArray2D<Type> &B, const vpArray2D<Type> &H)
77 {
78  if (A.getCols() != B.getCols() || A.getCols() != H.getCols()) {
79  std::cout << "Test fails: bad columns size" << std::endl;
80  return false;
81  }
82  if (A.getRows() != B.getRows() || A.getRows() != H.getRows()) {
83  std::cout << "Test fails: bad rows size" << std::endl;
84  return false;
85  }
86  for (unsigned int i = 0; i < A.size(); i++) {
87  if (std::fabs((A.data[i] * B.data[i]) - H.data[i]) > std::numeric_limits<double>::epsilon()) {
88  std::cout << "Test fails: bad content" << std::endl;
89  return false;
90  }
91  }
92 
93  return true;
94 }
95 
96 TEST_CASE("Test constructors with double", "[constructors]")
97 {
98  SECTION("Default constructor")
99  {
101  std::vector<double> bench;
102  CHECK(test("A", A, bench));
103  }
104  SECTION("Copy constructor")
105  {
106  vpArray2D<double> A(3, 4);
107 
108  std::vector<double> bench(12);
109  for (unsigned int i = 0; i < 3; i++) {
110  for (unsigned int j = 0; j < 4; j++) {
111  A[i][j] = (double)(i + j);
112  bench[i * 4 + j] = (double)(i + j);
113  }
114  }
115  CHECK(test("A", A, bench));
116 
117  vpArray2D<double> B(A);
118  CHECK(test("B", B, bench));
119  }
120  SECTION("Constructor with initial value")
121  {
122  vpArray2D<double> A(3, 4, 2.);
123  std::vector<double> bench1(12, 2);
124  CHECK(test("A", A, bench1));
125 
126  A.resize(5, 6);
127  std::vector<double> bench2(30, 0);
128  CHECK(test("A", A, bench2));
129 
130  A = -2.;
131  std::vector<double> bench3(30, -2);
132  CHECK(test("A", A, bench3));
133  }
134 
135  SECTION("Constructor from std::vector")
136  {
137  std::vector<double> bench(12);
138  for (unsigned int i = 0; i < 3; i++) {
139  for (unsigned int j = 0; j < 4; j++) {
140  bench[i * 4 + j] = (double)(i + j);
141  }
142  }
143  SECTION("Keep default size (r=0, c=0)")
144  {
145  std::cout << "A with default size (r=0, c=0):\n" << std::endl;
146  REQUIRE_THROWS(vpArray2D<double>(bench));
147  }
148  SECTION("Keep row size to 0")
149  {
150  unsigned int size = static_cast<unsigned int>(bench.size());
151  vpArray2D<double> A(bench, 0, size);
152  std::cout << "A with row size to 0:\n" << A << std::endl;
153  CHECK(test("A", A, bench));
154  CHECK(A.getRows() == 1);
155  CHECK(A.getCols() == bench.size());
156  }
157  SECTION("Keep col size to 0")
158  {
159  unsigned int size = static_cast<unsigned int>(bench.size());
160  vpArray2D<double> A(bench, size, 0);
161  std::cout << "A with col size to 0:\n" << A << std::endl;
162  CHECK(test("A", A, bench));
163  CHECK(A.getRows() == bench.size());
164  CHECK(A.getCols() == 1);
165  }
166  SECTION("Set r=3 and c=4")
167  {
168  vpArray2D<double> A(bench, 3, 4);
169  std::cout << "A with r=3 and c=4:\n" << A << std::endl;
170  CHECK(test("A", A, bench));
171  CHECK(A.getRows() == 3);
172  CHECK(A.getCols() == 4);
173  }
174  }
175 }
176 
177 TEST_CASE("Test constructors with float", "[constructors]")
178 {
179  SECTION("Default constructor")
180  {
182  std::vector<float> bench;
183  CHECK(test("A", A, bench));
184  }
185  SECTION("Copy constructor")
186  {
187  vpArray2D<float> A(3, 4);
188 
189  std::vector<float> bench(12);
190  for (unsigned int i = 0; i < 3; i++) {
191  for (unsigned int j = 0; j < 4; j++) {
192  A[i][j] = (float)(i + j);
193  bench[i * 4 + j] = (float)(i + j);
194  }
195  }
196  CHECK(test("A", A, bench));
197 
198  vpArray2D<float> B(A);
199  CHECK(test("B", B, bench));
200  }
201  SECTION("Constructor with initial value")
202  {
203  vpArray2D<float> A(3, 4, 2.);
204  std::vector<float> bench1(12, 2);
205  CHECK(test("A", A, bench1));
206 
207  A.resize(5, 6);
208  std::vector<float> bench2(30, 0);
209  CHECK(test("A", A, bench2));
210 
211  A = -2.;
212  std::vector<float> bench3(30, -2);
213  CHECK(test("A", A, bench3));
214  }
215  SECTION("Constructor from std::vector")
216  {
217  std::vector<float> bench(12);
218  for (unsigned int i = 0; i < 3; i++) {
219  for (unsigned int j = 0; j < 4; j++) {
220  bench[i * 4 + j] = (float)(i + j);
221  }
222  }
223  SECTION("Keep default size (r=0, c=0)")
224  {
225  std::cout << "A with default size (r=0, c=0):\n" << std::endl;
226  REQUIRE_THROWS(vpArray2D<float>(bench));
227  }
228  SECTION("Keep row size to 0")
229  {
230  unsigned int size = static_cast<unsigned int>(bench.size());
231  vpArray2D<float> A(bench, 0, size);
232  std::cout << "A with row size to 0:\n" << A << std::endl;
233  CHECK(test("A", A, bench));
234  CHECK(A.getRows() == 1);
235  CHECK(A.getCols() == bench.size());
236  }
237  SECTION("Keep col size to 0")
238  {
239  unsigned int size = static_cast<unsigned int>(bench.size());
240  vpArray2D<float> A(bench, size, 0);
241  std::cout << "A with col size to 0:\n" << A << std::endl;
242  CHECK(test("A", A, bench));
243  CHECK(A.getRows() == bench.size());
244  CHECK(A.getCols() == 1);
245  }
246  SECTION("Set r=3 and c=4")
247  {
248  vpArray2D<float> A(bench, 3, 4);
249  std::cout << "A with r=3 and c=4:\n" << A << std::endl;
250  CHECK(test("A", A, bench));
251  CHECK(A.getRows() == 3);
252  CHECK(A.getCols() == 4);
253  }
254  }
255 }
256 
257 TEST_CASE("Test Hadamar product", "[hadamar]")
258 {
259  vpArray2D<int> A1(3, 5), A2(3, 5), A3;
260  vpRowVector R1(15), R2(15), R3;
261  vpColVector C1(15), C2(15), C3;
262 
263  for (unsigned int i = 0; i < A1.size(); i++) {
264  A1.data[i] = i;
265  A2.data[i] = i + 2;
266  R1.data[i] = i;
267  R2.data[i] = i + 2;
268  C1.data[i] = i;
269  C2.data[i] = i + 2;
270  }
271 
272  std::cout << "A1:\n" << A1 << std::endl;
273  std::cout << "\nA2:\n" << A2 << std::endl;
274  A3 = A1.hadamard(A2);
275  CHECK(test_hadamar(A1, A2, A3));
276  std::cout << "\nRes hadamar(A1, A2):\n" << A3 << std::endl;
277 
278  std::cout << "\nR1:\n" << R1 << std::endl;
279  std::cout << "\nR2:\n" << R2 << std::endl;
280  R3 = R1.hadamard(R2);
281  CHECK(test_hadamar(R1, R2, R3));
282  std::cout << "\nRes hadamar(R1, R2):\n" << R3 << std::endl;
283 
284  std::cout << "\nC1:\n" << C1 << std::endl;
285  std::cout << "\nC2:\n" << C2 << std::endl;
286  C3 = C1.hadamard(C2);
287  CHECK(test_hadamar(C1, C2, C3));
288  std::cout << "\nRes hadamar(C1, C2):\n" << C3 << std::endl;
289 }
290 
291 int main(int argc, char *argv[])
292 {
293  Catch::Session session; // There must be exactly one instance
294 
295  // Let Catch (using Clara) parse the command line
296  session.applyCommandLine(argc, argv);
297 
298  int numFailed = session.run();
299 
300  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
301  // This clamping has already been applied, so just return it here
302  // You can also do any post run clean-up here
303  std::cout << (numFailed ? "Test failed" : "Test succeed") << std::endl;
304  return numFailed;
305 }
306 #else
307 int main() { return EXIT_SUCCESS; }
308 #endif
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition: vpArray2D.h:145
unsigned int getCols() const
Definition: vpArray2D.h:337
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:148
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:362
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:349
unsigned int getRows() const
Definition: vpArray2D.h:347
vpArray2D< Type > hadamard(const vpArray2D< Type > &m) const
Definition: vpArray2D.h:1147
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
vpColVector hadamard(const vpColVector &v) const
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:124
vpRowVector hadamard(const vpRowVector &v) const