Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
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
39
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
52using namespace VISP_NAMESPACE_NAME;
53#endif
54
55template <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
74template <typename Type>
75bool 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
95TEST_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] = static_cast<double>(i + j);
111 bench[i * 4 + j] = static_cast<double>(i + j);
112 }
113 }
114 CHECK(test("A", A, bench));
115
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] = static_cast<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
176TEST_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] = static_cast<float>(i + j);
192 bench[i * 4 + j] = static_cast<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] = static_cast<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
256TEST_CASE("Building array views", "[view]")
257{
258 std::cout << "Testing views" << std::endl;
259 SECTION("Modifying view modifies original array")
260 {
261 {
262 vpArray2D<int> A(5, 5, 0);
264 REQUIRE((A == v));
265 v[0][0] = 5;
266 v[0][1] = 2;
267 A[1][1] = 3;
268 REQUIRE((v[1][1] == 3));
269 REQUIRE((A[0][0] == 5));
270 REQUIRE((A == v));
271 }
272 {
273 int s = 5;
274 int *array = new int[s * s];
276 v[0][0] = 5;
277 v[s - 1][s - 1] = 2;
278 REQUIRE(array[0] == 5);
279 REQUIRE(array[s * s - 1] == 2);
280 delete[] array;
281 }
282 }
283
284 SECTION("A view can be moved and then used")
285 {
286 {
287 vpArray2D<int> A(5, 5, 0);
289 vpArray2D<int> v2 = std::move(v);
290 REQUIRE((A == v2));
291 v2[0][0] = 5;
292 v2[0][1] = 2;
293 REQUIRE((A[0][0] == 5));
294 REQUIRE((A == v2));
295 }
296 {
297 int s = 5;
298 int *array = new int[s * s];
300 vpArray2D<int> v2 = std::move(v);
301 v2[0][0] = 5;
302 v2[s - 1][s - 1] = 2;
303 REQUIRE(array[0] == 5);
304 REQUIRE(array[s * s - 1] == 2);
305 delete[] array;
306 }
307
308 }
309 SECTION("Array can still be used after destroying view")
310 {
311 int s = 5;
312 vpArray2D<int> A(s, s, 0);
313 {
315 v[0][0] = 5;
316 v[s - 1][s - 1] = 2;
317 }
318 REQUIRE((A[0][0] == 5));
319 REQUIRE(A[s - 1][s - 1] == 2);
320
321 int *array = new int[s * s];
322 {
324 v[0][0] = 5;
325 v[s - 1][s - 1] = 2;
326
327 }
328 REQUIRE(array[0] == 5);
329 REQUIRE(array[s * s - 1] == 2);
330 delete[] array;
331 }
332 SECTION("Cannot resize view")
333 {
334 int s = 5;
335 vpArray2D<int> A(s, s, 0);
337 REQUIRE_THROWS(v.resize(1, 5, false, false));
338
339
340 int *array = new int[s * s];
341 v = vpArray2D<int>::view(array, s, s);
342 REQUIRE_THROWS(v.resize(1, 5, false, false));
343 delete[] array;
344
345 }
346}
347
348TEST_CASE("Test Hadamar product", "[hadamar]")
349{
350 vpArray2D<int> A1(3, 5), A2(3, 5), A3;
351 vpRowVector R1(15), R2(15), R3;
352 vpColVector C1(15), C2(15), C3;
353
354 for (unsigned int i = 0; i < A1.size(); i++) {
355 A1.data[i] = i;
356 A2.data[i] = i + 2;
357 R1.data[i] = i;
358 R2.data[i] = i + 2;
359 C1.data[i] = i;
360 C2.data[i] = i + 2;
361 }
362
363 std::cout << "A1:\n" << A1 << std::endl;
364 std::cout << "\nA2:\n" << A2 << std::endl;
365 A3 = A1.hadamard(A2);
366 CHECK(test_hadamar(A1, A2, A3));
367 std::cout << "\nRes hadamar(A1, A2):\n" << A3 << std::endl;
368
369 std::cout << "\nR1:\n" << R1 << std::endl;
370 std::cout << "\nR2:\n" << R2 << std::endl;
371 R3 = R1.hadamard(R2);
372 CHECK(test_hadamar(R1, R2, R3));
373 std::cout << "\nRes hadamar(R1, R2):\n" << R3 << std::endl;
374
375 std::cout << "\nC1:\n" << C1 << std::endl;
376 std::cout << "\nC2:\n" << C2 << std::endl;
377 C3 = C1.hadamard(C2);
378 CHECK(test_hadamar(C1, C2, C3));
379 std::cout << "\nRes hadamar(C1, C2):\n" << C3 << std::endl;
380}
381
382int main(int argc, char *argv[])
383{
384 Catch::Session session;
385 session.applyCommandLine(argc, argv);
386 int numFailed = session.run();
387 std::cout << (numFailed ? "Test failed" : "Test succeed") << std::endl;
388 return numFailed;
389}
390#else
391int main() { return EXIT_SUCCESS; }
392#endif
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition vpArray2D.h:146
unsigned int getCols() const
Definition vpArray2D.h:423
Type * data
Address of the first element of the data array.
Definition vpArray2D.h:149
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:448
static vpArray2D< Type > view(const vpArray2D< Type > &A)
Creates a view of the Matrix A. A view shares the same underlying memory as the original array....
Definition vpArray2D.h:324
unsigned int size() const
Return the number of elements of the 2D array.
Definition vpArray2D.h:435
unsigned int getRows() const
Definition vpArray2D.h:433
vpArray2D< Type > hadamard(const vpArray2D< Type > &m) const
Definition vpArray2D.h:1257
Implementation of column vector and the associated operations.
vpColVector hadamard(const vpColVector &v) const
Implementation of row vector and the associated operations.
vpRowVector hadamard(const vpRowVector &v) const