Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
catchArray2D.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 
44 #include <catch_amalgamated.hpp>
45 #include <cmath>
46 #include <limits>
47 #include <vector>
48 
49 #include <visp3/core/vpTranslationVector.h>
50 
51 #ifdef ENABLE_VISP_NAMESPACE
52 using namespace VISP_NAMESPACE_NAME;
53 #endif
54 
55 template <typename Type> bool test(const std::string &s, const vpArray2D<Type> &A, const std::vector<Type> &bench)
56 {
57  static unsigned int cpt = 0;
58  std::cout << "** Test " << ++cpt << std::endl;
59  std::cout << s << "(" << A.getRows() << "," << A.getCols() << ") = \n" << A << std::endl;
60  if (bench.size() != A.size()) {
61  std::cout << "Test fails: bad size wrt bench" << std::endl;
62  return false;
63  }
64  for (unsigned int i = 0; i < A.size(); i++) {
65  if (std::fabs(A.data[i] - bench[i]) > std::fabs(A.data[i]) * std::numeric_limits<double>::epsilon()) {
66  std::cout << "Test fails: bad content" << std::endl;
67  return false;
68  }
69  }
70 
71  return true;
72 }
73 
74 template <typename Type>
75 bool test_hadamar(const vpArray2D<Type> &A, const vpArray2D<Type> &B, const vpArray2D<Type> &H)
76 {
77  if (A.getCols() != B.getCols() || A.getCols() != H.getCols()) {
78  std::cout << "Test fails: bad columns size" << std::endl;
79  return false;
80  }
81  if (A.getRows() != B.getRows() || A.getRows() != H.getRows()) {
82  std::cout << "Test fails: bad rows size" << std::endl;
83  return false;
84  }
85  for (unsigned int i = 0; i < A.size(); i++) {
86  if (std::fabs((A.data[i] * B.data[i]) - H.data[i]) > std::numeric_limits<double>::epsilon()) {
87  std::cout << "Test fails: bad content" << std::endl;
88  return false;
89  }
90  }
91 
92  return true;
93 }
94 
95 TEST_CASE("Test constructors with double", "[constructors]")
96 {
97  SECTION("Default constructor")
98  {
100  std::vector<double> bench;
101  CHECK(test("A", A, bench));
102  }
103  SECTION("Copy constructor")
104  {
105  vpArray2D<double> A(3, 4);
106 
107  std::vector<double> bench(12);
108  for (unsigned int i = 0; i < 3; i++) {
109  for (unsigned int j = 0; j < 4; j++) {
110  A[i][j] = (double)(i + j);
111  bench[i * 4 + j] = (double)(i + j);
112  }
113  }
114  CHECK(test("A", A, bench));
115 
116  vpArray2D<double> B(A);
117  CHECK(test("B", B, bench));
118  }
119  SECTION("Constructor with initial value")
120  {
121  vpArray2D<double> A(3, 4, 2.);
122  std::vector<double> bench1(12, 2);
123  CHECK(test("A", A, bench1));
124 
125  A.resize(5, 6);
126  std::vector<double> bench2(30, 0);
127  CHECK(test("A", A, bench2));
128 
129  A = -2.;
130  std::vector<double> bench3(30, -2);
131  CHECK(test("A", A, bench3));
132  }
133 
134  SECTION("Constructor from std::vector")
135  {
136  std::vector<double> bench(12);
137  for (unsigned int i = 0; i < 3; i++) {
138  for (unsigned int j = 0; j < 4; j++) {
139  bench[i * 4 + j] = (double)(i + j);
140  }
141  }
142  SECTION("Keep default size (r=0, c=0)")
143  {
144  std::cout << "A with default size (r=0, c=0):\n" << std::endl;
145  REQUIRE_THROWS(vpArray2D<double>(bench));
146  }
147  SECTION("Keep row size to 0")
148  {
149  unsigned int size = static_cast<unsigned int>(bench.size());
150  vpArray2D<double> A(bench, 0, size);
151  std::cout << "A with row size to 0:\n" << A << std::endl;
152  CHECK(test("A", A, bench));
153  CHECK(A.getRows() == 1);
154  CHECK(A.getCols() == bench.size());
155  }
156  SECTION("Keep col size to 0")
157  {
158  unsigned int size = static_cast<unsigned int>(bench.size());
159  vpArray2D<double> A(bench, size, 0);
160  std::cout << "A with col size to 0:\n" << A << std::endl;
161  CHECK(test("A", A, bench));
162  CHECK(A.getRows() == bench.size());
163  CHECK(A.getCols() == 1);
164  }
165  SECTION("Set r=3 and c=4")
166  {
167  vpArray2D<double> A(bench, 3, 4);
168  std::cout << "A with r=3 and c=4:\n" << A << std::endl;
169  CHECK(test("A", A, bench));
170  CHECK(A.getRows() == 3);
171  CHECK(A.getCols() == 4);
172  }
173  }
174 }
175 
176 TEST_CASE("Test constructors with float", "[constructors]")
177 {
178  SECTION("Default constructor")
179  {
181  std::vector<float> bench;
182  CHECK(test("A", A, bench));
183  }
184  SECTION("Copy constructor")
185  {
186  vpArray2D<float> A(3, 4);
187 
188  std::vector<float> bench(12);
189  for (unsigned int i = 0; i < 3; i++) {
190  for (unsigned int j = 0; j < 4; j++) {
191  A[i][j] = (float)(i + j);
192  bench[i * 4 + j] = (float)(i + j);
193  }
194  }
195  CHECK(test("A", A, bench));
196 
197  vpArray2D<float> B(A);
198  CHECK(test("B", B, bench));
199  }
200  SECTION("Constructor with initial value")
201  {
202  vpArray2D<float> A(3, 4, 2.);
203  std::vector<float> bench1(12, 2);
204  CHECK(test("A", A, bench1));
205 
206  A.resize(5, 6);
207  std::vector<float> bench2(30, 0);
208  CHECK(test("A", A, bench2));
209 
210  A = -2.;
211  std::vector<float> bench3(30, -2);
212  CHECK(test("A", A, bench3));
213  }
214  SECTION("Constructor from std::vector")
215  {
216  std::vector<float> bench(12);
217  for (unsigned int i = 0; i < 3; i++) {
218  for (unsigned int j = 0; j < 4; j++) {
219  bench[i * 4 + j] = (float)(i + j);
220  }
221  }
222  SECTION("Keep default size (r=0, c=0)")
223  {
224  std::cout << "A with default size (r=0, c=0):\n" << std::endl;
225  REQUIRE_THROWS(vpArray2D<float>(bench));
226  }
227  SECTION("Keep row size to 0")
228  {
229  unsigned int size = static_cast<unsigned int>(bench.size());
230  vpArray2D<float> A(bench, 0, size);
231  std::cout << "A with row size to 0:\n" << A << std::endl;
232  CHECK(test("A", A, bench));
233  CHECK(A.getRows() == 1);
234  CHECK(A.getCols() == bench.size());
235  }
236  SECTION("Keep col size to 0")
237  {
238  unsigned int size = static_cast<unsigned int>(bench.size());
239  vpArray2D<float> A(bench, size, 0);
240  std::cout << "A with col size to 0:\n" << A << std::endl;
241  CHECK(test("A", A, bench));
242  CHECK(A.getRows() == bench.size());
243  CHECK(A.getCols() == 1);
244  }
245  SECTION("Set r=3 and c=4")
246  {
247  vpArray2D<float> A(bench, 3, 4);
248  std::cout << "A with r=3 and c=4:\n" << A << std::endl;
249  CHECK(test("A", A, bench));
250  CHECK(A.getRows() == 3);
251  CHECK(A.getCols() == 4);
252  }
253  }
254 }
255 
256 TEST_CASE("Test Hadamar product", "[hadamar]")
257 {
258  vpArray2D<int> A1(3, 5), A2(3, 5), A3;
259  vpRowVector R1(15), R2(15), R3;
260  vpColVector C1(15), C2(15), C3;
261 
262  for (unsigned int i = 0; i < A1.size(); i++) {
263  A1.data[i] = i;
264  A2.data[i] = i + 2;
265  R1.data[i] = i;
266  R2.data[i] = i + 2;
267  C1.data[i] = i;
268  C2.data[i] = i + 2;
269  }
270 
271  std::cout << "A1:\n" << A1 << std::endl;
272  std::cout << "\nA2:\n" << A2 << std::endl;
273  A3 = A1.hadamard(A2);
274  CHECK(test_hadamar(A1, A2, A3));
275  std::cout << "\nRes hadamar(A1, A2):\n" << A3 << std::endl;
276 
277  std::cout << "\nR1:\n" << R1 << std::endl;
278  std::cout << "\nR2:\n" << R2 << std::endl;
279  R3 = R1.hadamard(R2);
280  CHECK(test_hadamar(R1, R2, R3));
281  std::cout << "\nRes hadamar(R1, R2):\n" << R3 << std::endl;
282 
283  std::cout << "\nC1:\n" << C1 << std::endl;
284  std::cout << "\nC2:\n" << C2 << std::endl;
285  C3 = C1.hadamard(C2);
286  CHECK(test_hadamar(C1, C2, C3));
287  std::cout << "\nRes hadamar(C1, C2):\n" << C3 << std::endl;
288 }
289 
290 int main(int argc, char *argv[])
291 {
292  Catch::Session session;
293  session.applyCommandLine(argc, argv);
294  int numFailed = session.run();
295  std::cout << (numFailed ? "Test failed" : "Test succeed") << std::endl;
296  return numFailed;
297 }
298 #else
299 int main() { return EXIT_SUCCESS; }
300 #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:1150
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