HICONT

gauss.cpp (fixed)

Nov 14th, 2023 (edited)
936
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.38 KB | None | 0 0
  1. // Copyright 2023 Soloninko Andrey
  2.  
  3. #include "task_2/soloninko_a_gauss_horizontal/Gauss.h"
  4.  
  5. #include <iostream>
  6. #include <random>
  7. #include <vector>
  8.  
  9. bool check_res(std::vector<double>& matrix, std::vector<double>& res,
  10.                int size) {
  11.     for (int i = 0; i < size; i++) {
  12.         double sum = 0;
  13.         for (int j = 0; j < size; j++)
  14.             sum += matrix[i * (size + 1) + j] * res[j];
  15.  
  16.         if (std::abs(sum - matrix[i * (size + 1) + size]) > 0.0001)
  17.             return false;
  18.     }
  19.     return true;
  20. }
  21.  
  22. void rand_matr(std::vector<double>& matrix, int size) {
  23.     std::random_device rd;
  24.     std::uniform_int_distribution<int> unif(-100, 100);
  25.     int i, j;
  26.     for (i = 0; i < size; i++)
  27.         for (j = 0; j < size + 1; j++) matrix[i * (size + 1) + j] = unif(rd);
  28. }
  29.  
  30. void gaussian_elimination(std::vector<double>& matrix, std::vector<int>& rows,
  31.                           int size, int rank, int comm_size, int row,
  32.                           int numsegment) {
  33.     row = 0;
  34.     std::vector<double> tmp_matr(size + 1);
  35.     for (int i = 0; i < size - 1; i++) {
  36.         if (i == rows[row]) {
  37.             MPI_Bcast(&matrix.data()[rows[row] * (size + 1)], size + 1,
  38.                       MPI_DOUBLE, rank, MPI_COMM_WORLD);
  39.             for (int j = 0; j <= size; j++)
  40.                 tmp_matr[j] = matrix[rows[row] * (size + 1) + j];
  41.             row++;
  42.         } else {
  43.             MPI_Bcast(tmp_matr.data(), size + 1, MPI_DOUBLE, i % comm_size,
  44.                       MPI_COMM_WORLD);
  45.         }
  46.         for (int j = row; j < numsegment; j++) {
  47.             double mult_ratio = matrix[rows[j] * (size + 1) + i] / tmp_matr[i];
  48.             for (int k = i; k < size + 1; k++)
  49.                 matrix[rows[j] * (size + 1) + k] -= mult_ratio * tmp_matr[k];
  50.         }
  51.     }
  52. }
  53.  
  54. void gaussian_substitution(std::vector<double>& matrix,
  55.                            std::vector<double>& res, std::vector<int>& rows,
  56.                            int row, int numsegment, int rank, int comm_size,
  57.                            int size) {
  58.     row = 0;
  59.     for (int i = 0; i < size; i++) {
  60.         if (i == rows[row]) {
  61.             res[i] = matrix[i * (size + 1) + size];
  62.             row++;
  63.         }
  64.     }
  65.     row = numsegment - 1;
  66.     for (int i = size - 1; i > 0; i--) {
  67.         if (row >= 0) {
  68.             if (i == rows[row]) {
  69.                 res[i] /= matrix[i * (size + 1) + i];
  70.                 MPI_Bcast(&(res.data())[i], 1, MPI_DOUBLE, rank,
  71.                           MPI_COMM_WORLD);
  72.                 row--;
  73.             } else {
  74.                 MPI_Bcast(&(res.data())[i], 1, MPI_DOUBLE, i % comm_size,
  75.                           MPI_COMM_WORLD);
  76.             }
  77.         } else {
  78.             MPI_Bcast(&(res.data())[i], 1, MPI_DOUBLE, i % comm_size,
  79.                       MPI_COMM_WORLD);
  80.         }
  81.  
  82.         for (int j = 0; j <= row; j++)
  83.             res[rows[j]] -= matrix[rows[j] * (size + 1) + i] * res[i];
  84.     }
  85.     if (rank == 0) res[0] /= matrix[rows[row] * (size + 1)];
  86. }
  87.  
  88. void gauss_algo(std::vector<double>& matrix, std::vector<double>& res,
  89.                 int size) {
  90.     int rank, comm_size;
  91.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  92.     MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
  93.  
  94.     int numsegment, row, rows_div;
  95.  
  96.     rows_div = size / comm_size;
  97.     if (size % comm_size) rows_div++;
  98.  
  99.     numsegment = rows_div;
  100.     if (rank >= comm_size - (comm_size * rows_div - size))
  101.         numsegment = rows_div - 1;
  102.  
  103.     std::vector<int> rows(numsegment);
  104.  
  105.     for (int i = 0; i < numsegment; i++) rows[i] = rank;
  106.  
  107.     MPI_Bcast(matrix.data(), size * (size + 1), MPI_DOUBLE, 0, MPI_COMM_WORLD);
  108.  
  109.     gaussian_elimination(matrix, rows, size, rank, comm_size, row, numsegment);
  110.  
  111.     gaussian_substitution(matrix, res, rows, row, numsegment, rank, comm_size,
  112.                           size);
  113. }
  114.  
  115. // Copyright 2023 Soloninko Andrey
  116. #include <gtest/gtest.h>
  117. #include <mpi.h>
  118.  
  119. #include <iostream>
  120.  
  121. #include "./Gauss.h"
  122.  
  123. TEST(Gauss_Horizontal, Test_1) {
  124.     int rankProc = 0;
  125.     int numProc = 0;
  126.  
  127.     MPI_Comm_rank(MPI_COMM_WORLD, &rankProc);
  128.     MPI_Comm_size(MPI_COMM_WORLD, &numProc);
  129.     int size = 4;
  130.     std::vector<double> matrix(size * (size + 1));
  131.     std::vector<double> res(size);
  132.  
  133.     rand_matr(matrix, size);
  134.     gauss_algo(matrix, res, size);
  135.  
  136.     if (rankProc == 0) ASSERT_EQ(check_res(matrix, res, size), true);
  137. }
  138.  
  139. TEST(Gauss_Horizontal, Test_2) {
  140.     int rankProc = 0;
  141.     int numProc = 0;
  142.  
  143.     MPI_Comm_rank(MPI_COMM_WORLD, &rankProc);
  144.     MPI_Comm_size(MPI_COMM_WORLD, &numProc);
  145.     int size = 5;
  146.     std::vector<double> matrix(size * (size + 1));
  147.     std::vector<double> res(size);
  148.  
  149.     rand_matr(matrix, size);
  150.     gauss_algo(matrix, res, size);
  151.  
  152.     if (rankProc == 0) ASSERT_EQ(check_res(matrix, res, size), true);
  153. }
  154.  
  155. TEST(Gauss_Horizontal, Test_3) {
  156.     int rankProc = 0;
  157.     int numProc = 0;
  158.  
  159.     MPI_Comm_rank(MPI_COMM_WORLD, &rankProc);
  160.     MPI_Comm_size(MPI_COMM_WORLD, &numProc);
  161.     int size = 6;
  162.     std::vector<double> matrix(size * (size + 1));
  163.     std::vector<double> res(size);
  164.  
  165.     rand_matr(matrix, size);
  166.     gauss_algo(matrix, res, size);
  167.  
  168.     if (rankProc == 0) ASSERT_EQ(check_res(matrix, res, size), true);
  169. }
  170.  
  171. TEST(Gauss_Horizontal, Test_4) {
  172.     int rankProc = 0;
  173.     int numProc = 0;
  174.  
  175.     MPI_Comm_rank(MPI_COMM_WORLD, &rankProc);
  176.     MPI_Comm_size(MPI_COMM_WORLD, &numProc);
  177.     int size = 8;
  178.     std::vector<double> matrix(size * (size + 1));
  179.     std::vector<double> res(size);
  180.  
  181.     rand_matr(matrix, size);
  182.     gauss_algo(matrix, res, size);
  183.  
  184.     if (rankProc == 0) ASSERT_EQ(check_res(matrix, res, size), true);
  185. }
  186.  
  187. TEST(Gauss_Horizontal, Test_5) {
  188.     int rankProc = 0;
  189.     int numProc = 0;
  190.  
  191.     MPI_Comm_rank(MPI_COMM_WORLD, &rankProc);
  192.     MPI_Comm_size(MPI_COMM_WORLD, &numProc);
  193.     int size = 8;
  194.     std::vector<double> matrix(size * (size + 1));
  195.     std::vector<double> res(size);
  196.  
  197.     rand_matr(matrix, size);
  198.     gauss_algo(matrix, res, size);
  199.  
  200.     if (rankProc == 0) ASSERT_EQ(check_res(matrix, res, size), true);
  201. }
  202.  
  203. int main(int argc, char **argv) {
  204.     int res_c = 0;
  205.  
  206.     ::testing::InitGoogleTest(&argc, argv);
  207.     ::testing::TestEventListeners &listeners =
  208.         ::testing::UnitTest::GetInstance()->listeners();
  209.  
  210.     if (MPI_Init(&argc, &argv) != MPI_SUCCESS) MPI_Abort(MPI_COMM_WORLD, -1);
  211.     res_c = RUN_ALL_TESTS();
  212.     MPI_Finalize();
  213.  
  214.     return res_c;
  215. }
  216.  
Advertisement
Add Comment
Please, Sign In to add comment