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<INT8> TESTS */
21 :
22 4 : TEST(VectorVectorTestI8, Addition) {
23 1 : INFO_COUT << "Vector (as Vectors) INT8" << std::endl;
24 :
25 : // Create input vectors
26 1 : std::vector<int8_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
27 1 : std::vector<int8_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
28 1 : std::vector<int8_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(VectorVectorTestI8, AdditionComparison) {
41 : // Create input vectors
42 1 : std::vector<int8_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
43 1 : std::vector<int8_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
44 1 : std::vector<int8_t> result_intrin(vec1.size());
45 1 : std::vector<int8_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(VectorVectorTestI8, AdditionComparisonRandom) {
59 1 : const size_t size = 3333;
60 :
61 1 : std::random_device rd;
62 1 : std::mt19937 rng(rd());
63 1 : std::uniform_int_distribution<int8_t> dist(-127, 127);
64 :
65 : // Generate random vectors
66 1 : std::vector<int8_t> vec1;
67 1 : std::vector<int8_t> vec2;
68 3334 : for (size_t i = 0; i < size; ++i) {
69 3333 : vec1.push_back(dist(rng));
70 3333 : vec2.push_back(dist(rng));
71 : }
72 :
73 : // Perform vector addition using INTRINSIC and standard methods
74 1 : std::vector<int8_t> result_intrin(size);
75 1 : std::vector<int8_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 4 : TEST(VectorVectorTestI8, AdditionPerformanceComparison) {
86 1 : const size_t size = 3333 * 3333;
87 :
88 1 : TEST_COUT << "Vector size : " << size << std::endl;
89 : // Create random number generator
90 1 : std::random_device rd;
91 1 : std::mt19937 rng(rd());
92 1 : std::uniform_int_distribution<int8_t> dist(-127, 127);
93 :
94 : // Generate random vectors
95 1 : std::vector<int8_t> vec1;
96 1 : std::vector<int8_t> vec2;
97 11108890 : for (size_t i = 0; i < size; ++i) {
98 11108889 : vec1.push_back(dist(rng));
99 11108889 : vec2.push_back(dist(rng));
100 : }
101 :
102 : // Measure execution time for INTRINSIC vector addition
103 1 : std::vector<int8_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<int8_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 :
127 : // Check if the results match
128 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
129 11108890 : for (size_t i = 0; i < result_intrin.size(); ++i) {
130 11108889 : EXPECT_EQ(result_intrin[i], result_std[i]);
131 : }
132 1 : }
133 :
134 4 : TEST(VectorVectorTestI8, Subtraction) {
135 : // Create input vectors
136 1 : std::vector<int8_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
137 1 : std::vector<int8_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
138 1 : std::vector<int8_t> result(vec1.size());
139 :
140 : // Perform vector subtraction
141 1 : gpmp::linalg::vector_sub(vec1, vec2, result);
142 :
143 : // Check the result
144 1 : EXPECT_EQ(result.size(), vec1.size());
145 9 : for (size_t i = 0; i < result.size(); ++i) {
146 8 : EXPECT_EQ(result[i], vec1[i] - vec2[i]);
147 : }
148 1 : }
149 :
150 4 : TEST(VectorVectorTestI8, SubtractionComparison) {
151 : // Create input vectors
152 1 : std::vector<int8_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
153 1 : std::vector<int8_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
154 1 : std::vector<int8_t> result_intrin(vec1.size());
155 1 : std::vector<int8_t> result_std(vec1.size());
156 :
157 : // Perform vector subtraction using INTRINSIC and standard methods
158 1 : gpmp::linalg::vector_sub(vec1, vec2, result_intrin);
159 1 : gpmp::linalg::std_vector_sub(vec1, vec2, result_std);
160 :
161 : // Check if the results match
162 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
163 9 : for (size_t i = 0; i < result_intrin.size(); ++i) {
164 8 : EXPECT_EQ(result_intrin[i], result_std[i]);
165 : }
166 1 : }
167 :
168 4 : TEST(VectorVectorTestI8, SubtractionComparisonRandom) {
169 1 : const size_t size = 3333;
170 : // Create random number generator
171 1 : std::random_device rd;
172 1 : std::mt19937 rng(rd());
173 1 : std::uniform_int_distribution<int8_t> dist(-127, 127);
174 :
175 : // Generate random vectors
176 1 : std::vector<int8_t> vec1;
177 1 : std::vector<int8_t> vec2;
178 3334 : for (size_t i = 0; i < size; ++i) {
179 3333 : vec1.push_back(dist(rng));
180 3333 : vec2.push_back(dist(rng));
181 : }
182 :
183 : // Perform vector addition using INTRINSIC and standard methods
184 1 : std::vector<int8_t> result_intrin(size);
185 1 : std::vector<int8_t> result_std(size);
186 1 : gpmp::linalg::vector_add(vec1, vec2, result_intrin);
187 1 : gpmp::linalg::std_vector_add(vec1, vec2, result_std);
188 :
189 : // Check if the results match
190 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
191 3334 : for (size_t i = 0; i < result_intrin.size(); ++i) {
192 3333 : EXPECT_EQ(result_intrin[i], result_std[i]);
193 : }
194 1 : }
195 :
196 4 : TEST(VectorVectorTestI8, SubtractionPerformanceComparison) {
197 1 : const size_t size = 3333 * 3333;
198 :
199 1 : TEST_COUT << "Vector size : " << size << std::endl;
200 : // Create random number generator
201 1 : std::random_device rd;
202 1 : std::mt19937 rng(rd());
203 1 : std::uniform_int_distribution<int8_t> dist(-127, 127);
204 :
205 : // Generate random vectors
206 1 : std::vector<int8_t> vec1;
207 1 : std::vector<int8_t> vec2;
208 11108890 : for (size_t i = 0; i < size; ++i) {
209 11108889 : vec1.push_back(dist(rng));
210 11108889 : vec2.push_back(dist(rng));
211 : }
212 :
213 : // Measure execution time for INTRINSIC vector addition
214 1 : std::vector<int8_t> result_intrin(size);
215 :
216 1 : auto start_intrin = std::chrono::high_resolution_clock::now();
217 1 : gpmp::linalg::vector_sub(vec1, vec2, result_intrin);
218 1 : auto end_intrin = std::chrono::high_resolution_clock::now();
219 :
220 : std::chrono::duration<double> elapsed_seconds_intrin =
221 1 : end_intrin - start_intrin;
222 :
223 : // Measure execution time for standard vector addition
224 1 : std::vector<int8_t> result_std(size);
225 :
226 1 : auto start_std = std::chrono::high_resolution_clock::now();
227 1 : gpmp::linalg::std_vector_sub(vec1, vec2, result_std);
228 1 : auto end_std = std::chrono::high_resolution_clock::now();
229 :
230 1 : std::chrono::duration<double> elapsed_seconds_std = end_std - start_std;
231 :
232 1 : TEST_COUT << "INTRINSIC Vector Subtraction Time : "
233 1 : << elapsed_seconds_intrin.count() << " seconds" << std::endl;
234 :
235 1 : TEST_COUT << "STANDARD Vector Subtraction Time : "
236 1 : << elapsed_seconds_std.count() << " seconds" << std::endl;
237 :
238 : // Check if the results match
239 1 : ASSERT_EQ(result_intrin.size(), result_std.size());
240 11108890 : for (size_t i = 0; i < result_intrin.size(); ++i) {
241 11108889 : EXPECT_EQ(result_intrin[i], result_std[i]);
242 : }
243 1 : }
244 :
245 : // Unit test for vector multiplication using INTRINSIC intrinsics
246 4 : TEST(VectorVectorTestI8, Multiplication) {
247 : // Create input vector and scalar
248 1 : std::vector<int8_t> vec = {1, 2, 3, 4, 5, 6, 7, 8};
249 1 : int scalar = 2;
250 1 : std::vector<int8_t> result(vec.size());
251 :
252 : // Perform vector multiplication
253 1 : gpmp::linalg::scalar_mult(vec, scalar, result);
254 :
255 : // Check the result
256 9 : for (size_t i = 0; i < result.size(); ++i) {
257 8 : EXPECT_EQ(result[i], vec[i] * scalar);
258 : }
259 1 : }
260 :
261 : // Unit test to compare results of INTRINSIC vector multiplication with standard
262 : // vector multiplication
263 4 : TEST(VectorVectorTestI8, MultComparison) {
264 : // Create input vector and scalar
265 1 : std::vector<int8_t> vec = {1, 2, 3, 4, 5, 6, 7, 8};
266 1 : int scalar = 2;
267 1 : std::vector<int8_t> result_intrin(vec.size());
268 1 : std::vector<int8_t> result_std(vec.size());
269 :
270 : // Perform vector multiplication using INTRINSIC and standard methods
271 1 : gpmp::linalg::scalar_mult(vec, scalar, result_intrin);
272 1 : gpmp::linalg::std_scalar_mult(vec, scalar, result_std);
273 :
274 : // Check if the results match
275 9 : for (size_t i = 0; i < result_intrin.size(); ++i) {
276 8 : EXPECT_EQ(result_intrin[i], result_std[i]);
277 : }
278 1 : }
279 :
280 : // Unit test to compare results of INTRINSIC vector multiplication with standard
281 : // vector multiplication using random vectors
282 4 : TEST(VectorVectorTestI8, MultComparisonRandom) {
283 1 : const size_t size = 3333;
284 : // Create random number generator
285 1 : std::random_device rd;
286 1 : std::mt19937 rng(rd());
287 1 : std::uniform_int_distribution<int8_t> dist(0, 11);
288 :
289 1 : std::vector<int8_t> vec;
290 1 : int scalar = dist(rng);
291 3334 : for (size_t i = 0; i < size; ++i) {
292 3333 : vec.push_back(dist(rng));
293 : }
294 :
295 : // Perform vector multiplication using INTRINSIC and standard methods
296 1 : std::vector<int8_t> result_intrin(size);
297 1 : std::vector<int8_t> result_std(size);
298 1 : gpmp::linalg::scalar_mult(vec, scalar, result_intrin);
299 1 : gpmp::linalg::std_scalar_mult(vec, scalar, result_std);
300 :
301 : // Check if the results match
302 3334 : for (size_t i = 0; i < result_intrin.size(); ++i) {
303 3333 : EXPECT_EQ(result_intrin[i], result_std[i]);
304 : }
305 1 : }
306 :
307 : // Unit test to compare execution time of INTRINSIC vector multiplication with
308 : // standard vector multiplication
309 4 : TEST(VectorVectorTestI8, MultPerformanceComparison) {
310 1 : const size_t size = 3333 * 3333;
311 1 : TEST_COUT << "Vector size : " << size << std::endl;
312 :
313 1 : std::random_device rd;
314 1 : std::mt19937 rng(rd());
315 1 : std::uniform_int_distribution<int8_t> dist(0, 11);
316 :
317 1 : std::vector<int8_t> vec;
318 1 : int scalar = dist(rng);
319 11108890 : for (size_t i = 0; i < size; ++i) {
320 11108889 : vec.push_back(dist(rng));
321 : }
322 :
323 : // Measure execution time for INTRINSIC vector multiplication
324 1 : std::vector<int8_t> result_intrin(size);
325 1 : auto start_intrin = std::chrono::high_resolution_clock::now();
326 1 : gpmp::linalg::scalar_mult(vec, scalar, result_intrin);
327 1 : auto end_intrin = std::chrono::high_resolution_clock::now();
328 : std::chrono::duration<double> elapsed_seconds_intrin =
329 1 : end_intrin - start_intrin;
330 :
331 : // Measure execution time for standard vector multiplication
332 1 : std::vector<int8_t> result_std(size);
333 1 : auto start_std = std::chrono::high_resolution_clock::now();
334 1 : gpmp::linalg::std_scalar_mult(vec, scalar, result_std);
335 1 : auto end_std = std::chrono::high_resolution_clock::now();
336 1 : std::chrono::duration<double> elapsed_seconds_std = end_std - start_std;
337 :
338 : // Print the results
339 1 : TEST_COUT << "INTRINSIC Vector Multiplication Time : "
340 1 : << elapsed_seconds_intrin.count() << " seconds" << std::endl;
341 1 : TEST_COUT << "STANDARD Vector Multiplication Time : "
342 1 : << elapsed_seconds_std.count() << " seconds" << std::endl;
343 :
344 : // Check if the results match
345 11108890 : for (size_t i = 0; i < result_intrin.size(); ++i) {
346 : // EXPECT_EQ(result_intrin[i], result_std[i]);
347 : }
348 1 : }
349 :
350 : // Unit test for dot product using INTRINSIC intrinsics
351 4 : TEST(VectorVectorTestI8, DotProduct) {
352 : // Create input vectors
353 1 : std::vector<int8_t> vec1 = {1, 2, 3, 4, 5, 6, 7, 8};
354 1 : std::vector<int8_t> vec2 = {8, 7, 6, 5, 4, 3, 2, 1};
355 :
356 : // Calculate dot product
357 1 : int result = gpmp::linalg::dot_product(vec1, vec2);
358 :
359 : // Expected result
360 1 : int expected_result = 120;
361 :
362 : // Check the result
363 1 : EXPECT_EQ(result, expected_result);
364 1 : }
365 :
366 : // Unit test for dot product using INTRINSIC intrinsics with random vectors
367 4 : TEST(VectorVectorTestI8, DotProductRandom) {
368 1 : const size_t size = 3333;
369 :
370 1 : std::random_device rd;
371 1 : std::mt19937 rng(rd());
372 1 : std::uniform_int_distribution<int8_t> dist(-128, 127);
373 :
374 1 : std::vector<int8_t> vec1;
375 1 : std::vector<int8_t> vec2;
376 3334 : for (size_t i = 0; i < size; ++i) {
377 3333 : vec1.push_back(dist(rng));
378 3333 : vec2.push_back(dist(rng));
379 : }
380 :
381 : // Calculate dot product using INTRINSIC intrinsics
382 1 : int result = gpmp::linalg::dot_product(vec1, vec2);
383 1 : int expected_result = gpmp::linalg::std_dot_product(vec1, vec2);
384 :
385 : // Check the result
386 1 : EXPECT_EQ(result, expected_result);
387 1 : }
388 :
389 4 : TEST(VectorVectorTestI8, DotProductPerformanceComparison) {
390 1 : const size_t size = 3333 * 3333;
391 1 : TEST_COUT << "Vector size : " << size << std::endl;
392 :
393 1 : std::random_device rd;
394 1 : std::mt19937 rng(rd());
395 1 : std::uniform_int_distribution<int8_t> dist(0, 11);
396 :
397 1 : std::vector<int8_t> vec1;
398 1 : std::vector<int8_t> vec2;
399 11108890 : for (size_t i = 0; i < size; ++i) {
400 11108889 : vec1.push_back(dist(rng));
401 11108889 : vec2.push_back(dist(rng));
402 : }
403 :
404 : // Measure execution time for INTRINSIC dot product calculation
405 1 : auto start_intrin = std::chrono::high_resolution_clock::now();
406 1 : int result_intrin = gpmp::linalg::dot_product(vec1, vec2);
407 1 : auto end_intrin = std::chrono::high_resolution_clock::now();
408 : std::chrono::duration<double> elapsed_seconds_intrin =
409 1 : end_intrin - start_intrin;
410 :
411 : // Measure execution time for standard dot product calculation
412 1 : auto start_std = std::chrono::high_resolution_clock::now();
413 1 : int result_std = gpmp::linalg::std_dot_product(vec1, vec2);
414 1 : auto end_std = std::chrono::high_resolution_clock::now();
415 1 : std::chrono::duration<double> elapsed_seconds_std = end_std - start_std;
416 :
417 : // Print the results
418 1 : TEST_COUT << "INTRINSIC Dot Product Time : "
419 1 : << elapsed_seconds_intrin.count() << " seconds" << std::endl;
420 1 : TEST_COUT << "STANDARD Dot Product Time : "
421 1 : << elapsed_seconds_std.count() << " seconds" << std::endl;
422 :
423 1 : EXPECT_EQ(result_std, result_intrin);
424 1 : }
|