Line data Source code
1 : /**
2 : * Unit tests for the Linear Algebra module's Vector operations
3 : */
4 : #include <chrono>
5 : #include <cstdint>
6 : #include <cstdlib>
7 : #include <gtest/gtest.h>
8 : #include <iostream>
9 : #include <openGPMP/linalg/vector.hpp>
10 : #include <random>
11 : #include <stdexcept>
12 : #include <vector>
13 :
14 : const double TOLERANCE = 1e-3;
15 :
16 : #define TEST_COUT std::cerr << "\033[32m[ ] [ INFO ] \033[0m"
17 : #define INFO_COUT \
18 : std::cerr << "\033[32m[ ] [ INFO ] \033[0m\033[1;34m\033[1m"
19 : /*****************************************************************************/
20 : /** VECTOR<INT32> TESTS */
21 :
22 4 : TEST(VectorVectorTestI32, Addition) {
23 1 : INFO_COUT << "Vector (as Vectors) INT32" << std::endl;
24 :
25 : // Create input vectors
26 1 : std::vector<int32_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
27 1 : std::vector<int32_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
28 1 : std::vector<int32_t> result(vec1.size());
29 :
30 : // Perform vector addition
31 1 : gpmp::linalg::vector_add(vec1, vec2, result);
32 :
33 : // Check the result
34 1 : EXPECT_EQ(result.size(), vec1.size());
35 9 : for (size_t i = 0; i < result.size(); ++i) {
36 8 : EXPECT_EQ(result[i], vec1[i] + vec2[i]);
37 : }
38 1 : }
39 :
40 4 : TEST(VectorVectorTestI32, AdditionComparison) {
41 : // Create input vectors
42 1 : std::vector<int32_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
43 1 : std::vector<int32_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
44 1 : std::vector<int32_t> result_intrin(vec1.size());
45 1 : std::vector<int32_t> result_std(vec1.size());
46 :
47 : // Perform vector addition using INTRINSIC and standard methods
48 1 : gpmp::linalg::vector_add(vec1, vec2, result_intrin);
49 1 : gpmp::linalg::std_vector_add(vec1, vec2, result_std);
50 :
51 : // Check if the results match
52 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
53 9 : for (size_t i = 0; i < result_intrin.size(); ++i) {
54 8 : EXPECT_EQ(result_intrin[i], result_std[i]);
55 : }
56 1 : }
57 :
58 4 : TEST(VectorVectorTestI32, AdditionComparisonRandom) {
59 1 : const size_t size = 3333;
60 :
61 : // Create random number generator
62 1 : std::mt19937 rng(std::random_device{}());
63 1 : std::uniform_int_distribution<int32_t> dist(-1000, 1000);
64 :
65 : // Generate random vectors
66 1 : std::vector<int32_t> vec1(size);
67 1 : std::vector<int32_t> vec2(size);
68 3334 : for (size_t i = 0; i < size; ++i) {
69 3333 : vec1[i] = dist(rng);
70 3333 : vec2[i] = dist(rng);
71 : }
72 :
73 : // Perform vector addition using INTRINSIC and standard methods
74 1 : std::vector<int32_t> result_intrin(size);
75 1 : std::vector<int32_t> result_std(size);
76 1 : gpmp::linalg::vector_add(vec1, vec2, result_intrin);
77 1 : gpmp::linalg::std_vector_add(vec1, vec2, result_std);
78 :
79 : // Check if the results match
80 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
81 3334 : for (size_t i = 0; i < result_intrin.size(); ++i) {
82 3333 : EXPECT_EQ(result_intrin[i], result_std[i]);
83 : }
84 1 : }
85 :
86 4 : TEST(VectorVectorTestI32, AdditionPerformanceComparison) {
87 1 : const size_t size = 3333 * 3333;
88 :
89 1 : TEST_COUT << "Vector size : " << size << std::endl;
90 : // Create random number generator
91 1 : std::mt19937 rng(std::random_device{}());
92 1 : std::uniform_int_distribution<int32_t> dist(-1000, 1000);
93 :
94 : // Generate random vectors
95 1 : std::vector<int32_t> vec1(size);
96 1 : std::vector<int32_t> vec2(size);
97 11108890 : for (size_t i = 0; i < size; ++i) {
98 11108889 : vec1[i] = dist(rng);
99 11108889 : vec2[i] = dist(rng);
100 : }
101 :
102 : // Measure execution time for INTRINSIC vector addition
103 1 : std::vector<int32_t> result_intrin(size);
104 :
105 1 : auto start_intrin = std::chrono::high_resolution_clock::now();
106 1 : gpmp::linalg::vector_add(vec1, vec2, result_intrin);
107 1 : auto end_intrin = std::chrono::high_resolution_clock::now();
108 :
109 : std::chrono::duration<double> elapsed_seconds_intrin =
110 1 : end_intrin - start_intrin;
111 :
112 : // Measure execution time for standard vector addition
113 1 : std::vector<int32_t> result_std(size);
114 :
115 1 : auto start_std = std::chrono::high_resolution_clock::now();
116 1 : gpmp::linalg::std_vector_add(vec1, vec2, result_std);
117 1 : auto end_std = std::chrono::high_resolution_clock::now();
118 :
119 1 : std::chrono::duration<double> elapsed_seconds_std = end_std - start_std;
120 :
121 1 : TEST_COUT << "INTRINSIC Vector Addition Time : "
122 1 : << elapsed_seconds_intrin.count() << " seconds" << std::endl;
123 :
124 1 : TEST_COUT << "STANDARD Vector Addition Time : "
125 1 : << elapsed_seconds_std.count() << " seconds" << std::endl;
126 1 : }
127 :
128 4 : TEST(VectorVectorTestI32, Subtraction) {
129 : // Create input vectors
130 1 : std::vector<int32_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
131 1 : std::vector<int32_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
132 1 : std::vector<int32_t> result(vec1.size());
133 :
134 : // Perform vector subtraction
135 1 : gpmp::linalg::vector_sub(vec1, vec2, result);
136 :
137 : // Check the result
138 1 : EXPECT_EQ(result.size(), vec1.size());
139 9 : for (size_t i = 0; i < result.size(); ++i) {
140 8 : EXPECT_EQ(result[i], vec1[i] - vec2[i]);
141 : }
142 1 : }
143 :
144 4 : TEST(VectorVectorTestI32, SubtractionComparison) {
145 : // Create input vectors
146 1 : std::vector<int32_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
147 1 : std::vector<int32_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
148 1 : std::vector<int32_t> result_intrin(vec1.size());
149 1 : std::vector<int32_t> result_std(vec1.size());
150 :
151 : // Perform vector subtraction using INTRINSIC and standard methods
152 1 : gpmp::linalg::vector_sub(vec1, vec2, result_intrin);
153 1 : gpmp::linalg::std_vector_sub(vec1, vec2, result_std);
154 :
155 : // Check if the results match
156 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
157 9 : for (size_t i = 0; i < result_intrin.size(); ++i) {
158 8 : EXPECT_EQ(result_intrin[i], result_std[i]);
159 : }
160 1 : }
161 :
162 4 : TEST(VectorVectorTestI32, SubtractionComparisonRandom) {
163 1 : const size_t size = 3333;
164 :
165 : // Create random number generator
166 1 : std::mt19937 rng(std::random_device{}());
167 1 : std::uniform_int_distribution<int32_t> dist(-1000, 1000);
168 :
169 : // Generate random vectors
170 1 : std::vector<int32_t> vec1(size);
171 1 : std::vector<int32_t> vec2(size);
172 3334 : for (size_t i = 0; i < size; ++i) {
173 3333 : vec1[i] = dist(rng);
174 3333 : vec2[i] = dist(rng);
175 : }
176 :
177 : // Perform vector subtraction using INTRINSIC and standard methods
178 1 : std::vector<int32_t> result_intrin(size);
179 1 : std::vector<int32_t> result_std(size);
180 1 : gpmp::linalg::vector_sub(vec1, vec2, result_intrin);
181 1 : gpmp::linalg::std_vector_sub(vec1, vec2, result_std);
182 :
183 : // Check if the results match
184 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
185 3334 : for (size_t i = 0; i < result_intrin.size(); ++i) {
186 3333 : EXPECT_EQ(result_intrin[i], result_std[i]);
187 : }
188 1 : }
189 :
190 4 : TEST(VectorVectorTestI32, SubtractionPerformanceComparison) {
191 1 : const size_t size = 3333 * 3333;
192 :
193 1 : TEST_COUT << "Vector size : " << size << std::endl;
194 : // Create random number generator
195 1 : std::mt19937 rng(std::random_device{}());
196 1 : std::uniform_int_distribution<int32_t> dist(-1000, 1000);
197 :
198 : // Generate random vectors
199 1 : std::vector<int32_t> vec1(size);
200 1 : std::vector<int32_t> vec2(size);
201 11108890 : for (size_t i = 0; i < size; ++i) {
202 11108889 : vec1[i] = dist(rng);
203 11108889 : vec2[i] = dist(rng);
204 : }
205 :
206 : // Measure execution time for INTRINSIC vector addition
207 1 : std::vector<int32_t> result_intrin(size);
208 :
209 1 : auto start_intrin = std::chrono::high_resolution_clock::now();
210 1 : gpmp::linalg::vector_sub(vec1, vec2, result_intrin);
211 1 : auto end_intrin = std::chrono::high_resolution_clock::now();
212 :
213 : std::chrono::duration<double> elapsed_seconds_intrin =
214 1 : end_intrin - start_intrin;
215 :
216 : // Measure execution time for standard vector addition
217 1 : std::vector<int32_t> result_std(size);
218 :
219 1 : auto start_std = std::chrono::high_resolution_clock::now();
220 1 : gpmp::linalg::std_vector_sub(vec1, vec2, result_std);
221 1 : auto end_std = std::chrono::high_resolution_clock::now();
222 :
223 1 : std::chrono::duration<double> elapsed_seconds_std = end_std - start_std;
224 :
225 1 : TEST_COUT << "INTRINSIC Vector Subtraction Time : "
226 1 : << elapsed_seconds_intrin.count() << " seconds" << std::endl;
227 :
228 1 : TEST_COUT << "STANDARD Vector Subtraction Time : "
229 1 : << elapsed_seconds_std.count() << " seconds" << std::endl;
230 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
231 11108890 : for (size_t i = 0; i < result_intrin.size(); ++i) {
232 11108889 : EXPECT_EQ(result_intrin[i], result_std[i]);
233 : }
234 1 : }
235 :
236 : // Unit test for vector multiplication using INTRINSIC intrinsics
237 4 : TEST(VectorVectorTestI32, Multiplication) {
238 : // Create input vector and scalar
239 1 : std::vector<int32_t> vec = {1, 2, 3, 4, 5, 6, 7, 8};
240 1 : int scalar = 2;
241 1 : std::vector<int32_t> result(vec.size());
242 :
243 : // Perform vector multiplication
244 1 : gpmp::linalg::scalar_mult(vec, scalar, result);
245 :
246 : // Check the result
247 9 : for (size_t i = 0; i < result.size(); ++i) {
248 8 : EXPECT_EQ(result[i], vec[i] * scalar);
249 : }
250 1 : }
251 :
252 : // Unit test to compare results of INTRINSIC vector multiplication with standard
253 : // vector multiplication
254 4 : TEST(VectorVectorTestI32, MultComparison) {
255 : // Create input vector and scalar
256 1 : std::vector<int32_t> vec = {1, 2, 3, 4, 5, 6, 7, 8};
257 1 : int scalar = 2;
258 1 : std::vector<int32_t> result_intrin(vec.size());
259 1 : std::vector<int32_t> result_std(vec.size());
260 :
261 : // Perform vector multiplication using INTRINSIC and standard methods
262 1 : gpmp::linalg::scalar_mult(vec, scalar, result_intrin);
263 1 : gpmp::linalg::std_scalar_mult(vec, scalar, result_std);
264 :
265 : // Check if the results match
266 9 : for (size_t i = 0; i < result_intrin.size(); ++i) {
267 8 : EXPECT_EQ(result_intrin[i], result_std[i]);
268 : }
269 1 : }
270 :
271 : // Unit test to compare results of INTRINSIC vector multiplication with standard
272 : // vector multiplication using random vectors
273 4 : TEST(VectorVectorTestI32, MultComparisonRandom) {
274 1 : const size_t size = 3333;
275 :
276 : // Create random number generator
277 1 : std::mt19937 rng(std::random_device{}());
278 1 : std::uniform_int_distribution<int32_t> dist(-1000, 1000);
279 :
280 : // Generate random vector and scalar
281 1 : std::vector<int32_t> vec(size);
282 1 : int scalar = dist(rng);
283 3334 : for (size_t i = 0; i < size; ++i) {
284 3333 : vec[i] = dist(rng);
285 : }
286 :
287 : // Perform vector multiplication using INTRINSIC and standard methods
288 1 : std::vector<int32_t> result_intrin(size);
289 1 : std::vector<int32_t> result_std(size);
290 1 : gpmp::linalg::scalar_mult(vec, scalar, result_intrin);
291 1 : gpmp::linalg::std_scalar_mult(vec, scalar, result_std);
292 :
293 : // Check if the results match
294 3334 : for (size_t i = 0; i < result_intrin.size(); ++i) {
295 3333 : EXPECT_EQ(result_intrin[i], result_std[i]);
296 : }
297 1 : }
298 :
299 4 : TEST(VectorVectorTestI32, MultPerformanceComparison) {
300 1 : const size_t size = 3333 * 3333;
301 1 : TEST_COUT << "Vector size : " << size << std::endl;
302 :
303 : // Create random number generator
304 1 : std::mt19937 rng(std::random_device{}());
305 1 : std::uniform_int_distribution<int32_t> dist(-1000, 1000);
306 :
307 : // Generate random vector and scalar
308 1 : std::vector<int32_t> vec(size);
309 1 : int scalar = dist(rng);
310 11108890 : for (size_t i = 0; i < size; ++i) {
311 11108889 : vec[i] = dist(rng);
312 : }
313 :
314 : // Measure execution time for INTRINSIC vector multiplication
315 1 : std::vector<int32_t> result_intrin(size);
316 1 : auto start_intrin = std::chrono::high_resolution_clock::now();
317 1 : gpmp::linalg::scalar_mult(vec, scalar, result_intrin);
318 1 : auto end_intrin = std::chrono::high_resolution_clock::now();
319 : std::chrono::duration<double> elapsed_seconds_intrin =
320 1 : end_intrin - start_intrin;
321 :
322 : // Measure execution time for standard vector multiplication
323 1 : std::vector<int32_t> result_std(size);
324 1 : auto start_std = std::chrono::high_resolution_clock::now();
325 1 : gpmp::linalg::std_scalar_mult(vec, scalar, result_std);
326 1 : auto end_std = std::chrono::high_resolution_clock::now();
327 1 : std::chrono::duration<double> elapsed_seconds_std = end_std - start_std;
328 :
329 : // Print the results
330 1 : TEST_COUT << "INTRINSIC Vector Multiplication Time : "
331 1 : << elapsed_seconds_intrin.count() << " seconds" << std::endl;
332 1 : TEST_COUT << "STANDARD Vector Multiplication Time : "
333 1 : << elapsed_seconds_std.count() << " seconds" << std::endl;
334 :
335 : // Check if the results match
336 11108890 : for (size_t i = 0; i < result_intrin.size(); ++i) {
337 11108889 : EXPECT_EQ(result_intrin[i], result_std[i]);
338 : }
339 1 : }
340 :
341 : // Unit test for dot product using INTRINSIC intrinsics
342 4 : TEST(VectorVectorTestI32, DotProduct) {
343 : // Create input vectors
344 1 : std::vector<int32_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
345 1 : std::vector<int32_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
346 :
347 : // Calculate dot product
348 1 : int result = gpmp::linalg::dot_product(vec1, vec2);
349 :
350 : // Expected result
351 1 : int expected_result = 120;
352 :
353 : // Check the result
354 1 : EXPECT_EQ(result, expected_result);
355 1 : }
356 :
357 : // Unit test for dot product using INTRINSIC intrinsics with random vectors
358 4 : TEST(VectorVectorTestI32, DotProductRandom) {
359 1 : const size_t size = 3333;
360 :
361 : // Create random number generator
362 1 : std::mt19937 rng(std::random_device{}());
363 1 : std::uniform_int_distribution<int32_t> dist(-1000, 1000);
364 :
365 : // Generate random vectors
366 1 : std::vector<int32_t> vec1(size);
367 1 : std::vector<int32_t> vec2(size);
368 3334 : for (size_t i = 0; i < size; ++i) {
369 3333 : vec1[i] = dist(rng);
370 3333 : vec2[i] = dist(rng);
371 : }
372 :
373 : // Calculate dot product using INTRINSIC intrinsics
374 1 : int result = gpmp::linalg::dot_product(vec1, vec2);
375 :
376 : // Calculate dot product using standard method
377 1 : int expected_result = 0;
378 3334 : for (size_t i = 0; i < size; ++i) {
379 3333 : expected_result += vec1[i] * vec2[i];
380 : }
381 :
382 : // Check the result
383 1 : EXPECT_EQ(result, expected_result);
384 1 : }
385 :
386 4 : TEST(VectorVectorTestI32, DotProductPerformanceComparison) {
387 1 : const size_t size = 3333 * 3333;
388 1 : TEST_COUT << "Vector size : " << size << std::endl;
389 :
390 : // Create input vectors
391 1 : std::vector<int32_t> vec1(size, 1);
392 1 : std::vector<int32_t> vec2(size, 2);
393 :
394 : // Measure execution time for INTRINSIC dot product calculation
395 1 : auto start_intrin = std::chrono::high_resolution_clock::now();
396 1 : int result_intrin = gpmp::linalg::dot_product(vec1, vec2);
397 1 : auto end_intrin = std::chrono::high_resolution_clock::now();
398 : std::chrono::duration<double> elapsed_seconds_intrin =
399 1 : end_intrin - start_intrin;
400 :
401 : // Measure execution time for standard dot product calculation
402 1 : auto start_std = std::chrono::high_resolution_clock::now();
403 1 : int result_std = gpmp::linalg::std_dot_product(vec1, vec2);
404 1 : auto end_std = std::chrono::high_resolution_clock::now();
405 1 : std::chrono::duration<double> elapsed_seconds_std = end_std - start_std;
406 :
407 : // Print the results
408 1 : TEST_COUT << "INTRINSIC Dot Product Time : "
409 1 : << elapsed_seconds_intrin.count() << " seconds" << std::endl;
410 1 : TEST_COUT << "STANDARD Dot Product Time : "
411 1 : << elapsed_seconds_std.count() << " seconds" << std::endl;
412 :
413 1 : EXPECT_EQ(result_std, result_intrin);
414 1 : }
|