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