Visual Servoing Platform  version 3.6.1 under development (2024-04-24)
testArray2D.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2024 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 https://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 *****************************************************************************/
35 
42 #include <visp3/core/vpConfig.h>
43 
44 #if defined(VISP_HAVE_CATCH2)
45 #define CATCH_CONFIG_RUNNER
46 
47 #include <catch.hpp>
48 #include <cmath>
49 #include <limits>
50 #include <vector>
51 
52 #include <visp3/core/vpTranslationVector.h>
53 
54 template <typename Type> bool test(const std::string &s, const vpArray2D<Type> &A, const std::vector<Type> &bench)
55 {
56  static unsigned int cpt = 0;
57  std::cout << "** Test " << ++cpt << std::endl;
58  std::cout << s << "(" << A.getRows() << "," << A.getCols() << ") = \n" << A << std::endl;
59  if (bench.size() != A.size()) {
60  std::cout << "Test fails: bad size wrt bench" << std::endl;
61  return false;
62  }
63  for (unsigned int i = 0; i < A.size(); i++) {
64  if (std::fabs(A.data[i] - bench[i]) > std::fabs(A.data[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 template <typename Type>
74 bool test_hadamar(const vpArray2D<Type> &A, const vpArray2D<Type> &B, const vpArray2D<Type> &H)
75 {
76  if (A.getCols() != B.getCols() || A.getCols() != H.getCols()) {
77  std::cout << "Test fails: bad columns size" << std::endl;
78  return false;
79  }
80  if (A.getRows() != B.getRows() || A.getRows() != H.getRows()) {
81  std::cout << "Test fails: bad rows size" << std::endl;
82  return false;
83  }
84  for (unsigned int i = 0; i < A.size(); i++) {
85  if (std::fabs((A.data[i] * B.data[i]) - H.data[i]) > std::numeric_limits<double>::epsilon()) {
86  std::cout << "Test fails: bad content" << std::endl;
87  return false;
88  }
89  }
90 
91  return true;
92 }
93 
94 TEST_CASE("Test constructors with double", "[constructors]")
95 {
96  SECTION("Default constructor")
97  {
99  std::vector<double> bench;
100  CHECK(test("A", A, bench));
101  }
102  SECTION("Copy constructor")
103  {
104  vpArray2D<double> A(3, 4);
105 
106  std::vector<double> bench(12);
107  for (unsigned int i = 0; i < 3; i++) {
108  for (unsigned int j = 0; j < 4; j++) {
109  A[i][j] = (double)(i + j);
110  bench[i * 4 + j] = (double)(i + j);
111  }
112  }
113  CHECK(test("A", A, bench));
114 
115  vpArray2D<double> B(A);
116  CHECK(test("B", B, bench));
117  }
118  SECTION("Constructor with initial value")
119  {
120  vpArray2D<double> A(3, 4, 2.);
121  std::vector<double> bench1(12, 2);
122  CHECK(test("A", A, bench1));
123 
124  A.resize(5, 6);
125  std::vector<double> bench2(30, 0);
126  CHECK(test("A", A, bench2));
127 
128  A = -2.;
129  std::vector<double> bench3(30, -2);
130  CHECK(test("A", A, bench3));
131  }
132 
133  SECTION("Constructor from std::vector")
134  {
135  std::vector<double> bench(12);
136  for (unsigned int i = 0; i < 3; i++) {
137  for (unsigned int j = 0; j < 4; j++) {
138  bench[i * 4 + j] = (double)(i + j);
139  }
140  }
141  SECTION("Keep default size (r=0, c=0)")
142  {
143  std::cout << "A with default size (r=0, c=0):\n" << std::endl;
144  REQUIRE_THROWS(vpArray2D<double>(bench));
145  }
146  SECTION("Keep row size to 0")
147  {
148  vpArray2D<double> A(bench, 0, bench.size());
149  std::cout << "A with row size to 0:\n" << A << std::endl;
150  CHECK(test("A", A, bench));
151  CHECK(A.getRows() == 1);
152  CHECK(A.getCols() == bench.size());
153  }
154  SECTION("Keep col size to 0")
155  {
156  vpArray2D<double> A(bench, bench.size(), 0);
157  std::cout << "A with col size to 0:\n" << A << std::endl;
158  CHECK(test("A", A, bench));
159  CHECK(A.getRows() == bench.size());
160  CHECK(A.getCols() == 1);
161  }
162  SECTION("Set r=3 and c=4")
163  {
164  vpArray2D<double> A(bench, 3, 4);
165  std::cout << "A with r=3 and c=4:\n" << A << std::endl;
166  CHECK(test("A", A, bench));
167  CHECK(A.getRows() == 3);
168  CHECK(A.getCols() == 4);
169  }
170  }
171 }
172 
173 TEST_CASE("Test constructors with float", "[constructors]")
174 {
175  SECTION("Default constructor")
176  {
178  std::vector<float> bench;
179  CHECK(test("A", A, bench));
180  }
181  SECTION("Copy constructor")
182  {
183  vpArray2D<float> A(3, 4);
184 
185  std::vector<float> bench(12);
186  for (unsigned int i = 0; i < 3; i++) {
187  for (unsigned int j = 0; j < 4; j++) {
188  A[i][j] = (float)(i + j);
189  bench[i * 4 + j] = (float)(i + j);
190  }
191  }
192  CHECK(test("A", A, bench));
193 
194  vpArray2D<float> B(A);
195  CHECK(test("B", B, bench));
196  }
197  SECTION("Constructor with initial value")
198  {
199  vpArray2D<float> A(3, 4, 2.);
200  std::vector<float> bench1(12, 2);
201  CHECK(test("A", A, bench1));
202 
203  A.resize(5, 6);
204  std::vector<float> bench2(30, 0);
205  CHECK(test("A", A, bench2));
206 
207  A = -2.;
208  std::vector<float> bench3(30, -2);
209  CHECK(test("A", A, bench3));
210  }
211  SECTION("Constructor from std::vector")
212  {
213  std::vector<float> bench(12);
214  for (unsigned int i = 0; i < 3; i++) {
215  for (unsigned int j = 0; j < 4; j++) {
216  bench[i * 4 + j] = (float)(i + j);
217  }
218  }
219  SECTION("Keep default size (r=0, c=0)")
220  {
221  std::cout << "A with default size (r=0, c=0):\n" << std::endl;
222  REQUIRE_THROWS(vpArray2D<float>(bench));
223  }
224  SECTION("Keep row size to 0")
225  {
226  vpArray2D<float> A(bench, 0, bench.size());
227  std::cout << "A with row size to 0:\n" << A << std::endl;
228  CHECK(test("A", A, bench));
229  CHECK(A.getRows() == 1);
230  CHECK(A.getCols() == bench.size());
231  }
232  SECTION("Keep col size to 0")
233  {
234  vpArray2D<float> A(bench, bench.size(), 0);
235  std::cout << "A with col size to 0:\n" << A << std::endl;
236  CHECK(test("A", A, bench));
237  CHECK(A.getRows() == bench.size());
238  CHECK(A.getCols() == 1);
239  }
240  SECTION("Set r=3 and c=4")
241  {
242  vpArray2D<float> A(bench, 3, 4);
243  std::cout << "A with r=3 and c=4:\n" << A << std::endl;
244  CHECK(test("A", A, bench));
245  CHECK(A.getRows() == 3);
246  CHECK(A.getCols() == 4);
247  }
248  }
249 }
250 
251 TEST_CASE("Test Hadamar product", "[hadamar]")
252 {
253  vpArray2D<int> A1(3, 5), A2(3, 5), A3;
254  vpRowVector R1(15), R2(15), R3;
255  vpColVector C1(15), C2(15), C3;
256 
257  for (unsigned int i = 0; i < A1.size(); i++) {
258  A1.data[i] = i;
259  A2.data[i] = i + 2;
260  R1.data[i] = i;
261  R2.data[i] = i + 2;
262  C1.data[i] = i;
263  C2.data[i] = i + 2;
264  }
265 
266  std::cout << "A1:\n" << A1 << std::endl;
267  std::cout << "\nA2:\n" << A2 << std::endl;
268  A3 = A1.hadamard(A2);
269  CHECK(test_hadamar(A1, A2, A3));
270  std::cout << "\nRes hadamar(A1, A2):\n" << A3 << std::endl;
271 
272  std::cout << "\nR1:\n" << R1 << std::endl;
273  std::cout << "\nR2:\n" << R2 << std::endl;
274  R3 = R1.hadamard(R2);
275  CHECK(test_hadamar(R1, R2, R3));
276  std::cout << "\nRes hadamar(R1, R2):\n" << R3 << std::endl;
277 
278  std::cout << "\nC1:\n" << C1 << std::endl;
279  std::cout << "\nC2:\n" << C2 << std::endl;
280  C3 = C1.hadamard(C2);
281  CHECK(test_hadamar(C1, C2, C3));
282  std::cout << "\nRes hadamar(C1, C2):\n" << C3 << std::endl;
283 }
284 
285 int main(int argc, char *argv[])
286 {
287  Catch::Session session; // There must be exactly one instance
288 
289  // Let Catch (using Clara) parse the command line
290  session.applyCommandLine(argc, argv);
291 
292  int numFailed = session.run();
293 
294  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
295  // This clamping has already been applied, so just return it here
296  // You can also do any post run clean-up here
297  std::cout << (numFailed ? "Test failed" : "Test succeed") << std::endl;
298  return numFailed;
299 }
300 #else
301 int main() { return EXIT_SUCCESS; }
302 #endif
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition: vpArray2D.h:126
unsigned int getCols() const
Definition: vpArray2D.h:327
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:139
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:352
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:339
unsigned int getRows() const
Definition: vpArray2D.h:337
vpArray2D< Type > hadamard(const vpArray2D< Type > &m) const
Definition: vpArray2D.h:1116
Implementation of column vector and the associated operations.
Definition: vpColVector.h:163
vpColVector hadamard(const vpColVector &v) const
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:107