LCOV - code coverage report
Current view: top level - tests/linalg - t_vector_vector_f64.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 220 220 100.0 %
Date: 2024-05-13 05:06:06 Functions: 60 60 100.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14