diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ed05fc1..d21a4742 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,22 @@ include(cmake/function.cmake) # подхватываем функции, # и для создания исполняемого проекта в отдельные функции add_subdirectory(lib_easy_example) # подключаем дополнительный CMakeLists.txt из подкаталога с именем lib_easy_example +add_subdirectory(lib_algorithms) +add_subdirectory(lib_point) +add_subdirectory(lib_circle) +add_subdirectory(lib_point3d) +add_subdirectory(lib_sphere) +add_subdirectory(lib_tvector) +add_subdirectory(lib_mathvector) +add_subdirectory(lib_matrix) +add_subdirectory(lib_triangle_matrix) +add_subdirectory(lib_stack) +add_subdirectory(lib_queue) +add_subdirectory(lib_node) +add_subdirectory(lib_list) +add_subdirectory(lib_dlist) +add_subdirectory(lib_stack_list) +add_subdirectory(lib_queue_list) add_subdirectory(main) # подключаем дополнительный CMakeLists.txt из подкаталога с именем main option(BTEST "build test?" ON) # указываем подключаем ли google-тесты (ON или YES) или нет (OFF или NO) diff --git a/lib_algorithms/CMakeLists.txt b/lib_algorithms/CMakeLists.txt new file mode 100644 index 00000000..85a989dc --- /dev/null +++ b/lib_algorithms/CMakeLists.txt @@ -0,0 +1,8 @@ +create_project_lib(Algorithms) +add_depend(Algorithms Circle lib_circle) +add_depend(Algorithms Sphere lib_sphere) +add_depend(Algorithms Stack lib_stack) +add_depend(Algorithms Node lib_node) +add_depend(Algorithms List lib_list) +add_depend(Algorithms Matrix lib_matrix) +add_depend(Algorithms TriangleMatrix lib_triangle_matrix) \ No newline at end of file diff --git a/lib_algorithms/algorithms.cpp b/lib_algorithms/algorithms.cpp new file mode 100644 index 00000000..a28c49d1 --- /dev/null +++ b/lib_algorithms/algorithms.cpp @@ -0,0 +1,500 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include +#include +#include +#include + +#include "../lib_circle/circle.h" +#include "../lib_sphere/sphere.h" +#include "../lib_stack/stack.h" +#include "../lib_matrix/matrix.h" +#include "../lib_triangle_matrix/triangle_matrix.h" +#include "../lib_node/node.h" +#include "../lib_list/list.h" + +#define START_MENU_FOR_MATRIX_SIZE 3 +#define START_MENU_MATRIX_CALCULATE_SIZE 4 +#define WHAT_MATRIX_MENU 3 +#define YES 1 +#define NO 0 +#define MAX_COUNT_OF_SAVED_MATRICES 3 +#define EXIT_DELETED_SAVED_MATRICES_MENU 4 +#define MATRIX1 1 +#define MATRIX2 2 +#define MATRIX3 3 + +#define MATRIX_CALCULATOR 1 +#define VIEWING_SAVED_MATRICES 2 +#define EXIT_MAIN_MENU 3 + +#define ADD 1 +#define SUBTRACT 2 +#define MULTIPLY 3 +#define EXIT_CALCULATE_MATRIX_MENU 4 + +#define STANDART 1 +#define TRIANGLE 2 + +#define SIZE_OF_STACK_FOR_CHECK_BRACKETS 150 + +void set_color(int text_color, int bg_color) { + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hConsole, (bg_color << 4) | text_color); +} + +void print_result_position(const std::string& description, Location result) { + std::cout << description << ": "; + switch (result) { + case coinside: std::cout << "COINCIDE"; break; + case inside: std::cout << "INSIDE"; break; + case tangent: std::cout << "TANGENT"; break; + case intersecting: std::cout << "INTERSECTING"; break; + case do_not_intersecting: std::cout << "DO_NOT_INTERSECT"; break; + } + std::cout << std::endl; +} + +void in_development() { + std::cout << " Sorry, the function is in development " << std::endl; + std::cout << " Press Enter to exit " << std::endl; + getchar(); + getchar(); + system("cls"); +} +void start_menu_for_matrix() { + std::cout << "======================================================" << std::endl; + std::cout << " WORKING WITH MATRICES " << std::endl; + std::cout << "======================================================" << std::endl; + std::cout << " 1. Matrix calculator " << std::endl; + std::cout << " 2. Viewing saved matrices " << std::endl; + std::cout << " 3. Exit " << std::endl; + std::cout << "======================================================" << std::endl; + //std::cout << "======================================================" << std::endl; + //std::cout << "" << std::endl; +} +void print_menu_matrix_calculator() { + system("cls"); + std::cout << "======================================================" << std::endl; + std::cout << " What would you like to do with matrices:" << std::endl; + std::cout << " 1. Add " << std::endl; + std::cout << " 2. Subtract" << std::endl; + std::cout << " 3. multiply" << std::endl; + std::cout << " 4. Exit" << std::endl; + std::cout << "======================================================" << std::endl; +} + +void check_user_input(int user_choice, int true_number) { + if (user_choice > true_number) { + set_color(12, 0); + std::cout << "ERROR: "; + set_color(7, 0); + throw std::logic_error("your choice is more than points\n"); + } + else if (user_choice <= 0) { + set_color(12, 0); + std::cout << "ERROR: "; + set_color(7, 0); + throw std::logic_error("your choice is less than points\n"); + } +} +bool input_user_choice(int& user_choice, int true_number) { + std::cout << " Enter the menu you need: " << std::endl; + std::cout << " (if you are sure, press enter)" << std::endl; + std::cout << " "; + std::cin >> user_choice; + try { + check_user_input(user_choice, true_number); + } + catch (const std::exception& ex) { + std::cerr << ex.what(); + std::cout << " Try again:" << std::endl; + return false; + } + return true; +} +void what_matrices(int& what_the_first_matrix, int& what_the_second_matrix, int& isExit) { + int user_choice; + int& link_user_choice = user_choice; + std::cout << "======================================================" << std::endl; + std::cout << " What will the first matrix be like?" << std::endl; + std::cout << " 1. Standart" << std::endl; + std::cout << " 2. Triangle" << std::endl; + std::cout << " 3. Exit" << std::endl; + while (!input_user_choice(link_user_choice, WHAT_MATRIX_MENU)); + if (user_choice == 3) { + isExit = YES; + } + else { + if (user_choice == STANDART) { what_the_first_matrix = STANDART;} + else { what_the_first_matrix = TRIANGLE; } + std::cout << "======================================================" << std::endl; + std::cout << " What will the second matrix be like?" << std::endl; + std::cout << " 1. Standart" << std::endl; + std::cout << " 2. Triangle" << std::endl; + while (!input_user_choice(link_user_choice, 2)); + if (user_choice == STANDART) { what_the_second_matrix = STANDART; } + else { what_the_second_matrix = TRIANGLE; } + } +} +void what_matrix_sizes(const int& type_matrix, size_t& size_rows, size_t& size_cols) { + if (type_matrix == STANDART) { + std::cout << "======================================================" << std::endl; + std::cout << "Enter the number of rows (parametr M): "; + std::cin >> size_rows; + std::cout << "Enter the number of columns (parametr N): "; + std::cin >> size_cols; + } + else if (type_matrix == TRIANGLE) { + std::cout << "======================================================" << std::endl; + std::cout << "Enter the size of the triangle matrix (parametr N): "; + std::cin >> size_rows; + size_cols = size_rows; + } + else { + throw std::logic_error("The matrix has an invalid type!"); + } + +} +void do_user_want_to_save(int& want_to_save) { + std::cout << "======================================================" << std::endl; + std::cout << "Would you like to save result?" << std::endl; + std::cout << "======================================================" << std::endl; + std::cout << "If answer - yes - input 1. If no, then input 0: "; + std::cin >> want_to_save; + while (want_to_save != YES && want_to_save != NO) { + std::cout << "======================================================" << std::endl; + set_color(12, 0); + std::cout << "ERROR: "; + set_color(7, 0); + std::cout << "your choice is more than points" << std::endl; + std::cout << "======================================================" << std::endl; + std::cout << "Tru again" << std::endl; + std::cout << "If answer - yes - input 1. If no, then input 0: "; + std::cin >> want_to_save; + } +} +void input_standart_matrix(Matrix& matrix, size_t rows, size_t cols) { + std::cout << "Enter matrix elements:" << std::endl; + for (size_t i = 0; i < rows; ++i) { + for (size_t j = 0; j < cols; ++j) { + std::cout << "[" << i << "][" << j << "] = "; + std::cin >> matrix[i][j]; + } + } +} +void input_triangle_matrix(TriangleMatrix& matrix, size_t n) { + std::cout << "Enter upper-triangle elements (including diagonal):" << std::endl; + for (size_t i = 0; i < n; ++i) { + for (size_t j = i; j < n; ++j) { + std::cout << "[" << i << "][" << j << "] = "; + std::cin >> matrix.at(i, j); + } + } +} +Matrix triangle_to_full(const TriangleMatrix& matrix) { + Matrix result(matrix.n(), matrix.n()); + for (size_t i = 0; i < matrix.n(); ++i) + for (size_t j = 0; j < matrix.n(); ++j) + result.at(i, j) = matrix.at(i, j); + return result; +} +void start_matrix_calculator(int& link_user_choice, int& link_want_to_save, Matrix res, + int& count_of_saved_matrices, Matrix& matrix1, Matrix& matrix2, Matrix& matrix3, + int& isThereMatrix1, int& isThereMatrix2, int& isThereMatrix3) { + + int isExit = NO; + while (!isExit) { + print_menu_matrix_calculator(); + while (!input_user_choice(link_user_choice, START_MENU_MATRIX_CALCULATE_SIZE)); + system("cls"); + if (link_user_choice == EXIT_CALCULATE_MATRIX_MENU) { break; } + int what_the_first_matrix = 0; + int what_the_second_matrix = 0; + int inner_exit = NO; + what_matrices(what_the_first_matrix, what_the_second_matrix, inner_exit); + system("cls"); + if (inner_exit == YES) { break; } + size_t size_rows1 = 0, size_cols1 = 0, size_rows2 = 0, size_cols2 = 0; + size_t size_res_rows = 0, size_res_cols = 0; + if (what_the_first_matrix == TRIANGLE || what_the_second_matrix == TRIANGLE || link_user_choice == ADD || link_user_choice == SUBTRACT) { + if (what_the_first_matrix == TRIANGLE || what_the_second_matrix == TRIANGLE) { + what_matrix_sizes(TRIANGLE, size_rows1, size_cols1); + size_rows2 = size_rows1; + size_cols2 = size_cols1; + size_res_rows = size_rows1; + size_res_cols = size_cols1; + } + else { + what_matrix_sizes(what_the_first_matrix, size_rows1, size_cols1); + size_rows2 = size_rows1; + size_cols2 = size_cols1; + size_res_rows = size_rows1; + size_res_cols = size_cols1; + } + } + else { + std::cout << "======================================================" << std::endl; + std::cout << " For the first matrix" << std::endl; + what_matrix_sizes(what_the_first_matrix, size_cols1, size_rows1); + std::cout << "======================================================" << std::endl; + std::cout << " For the second matrix" << std::endl; + what_matrix_sizes(what_the_second_matrix, size_cols2, size_rows2); + while (size_cols1 != size_rows2) { + set_color(12, 0); + std::cout << "ERROR: "; + set_color(7, 0); + std::cout << "The parameter N for 1 of the matrix and the parametr M for 2 must be equal" << std::endl; + std::cout << "======================================================" << std::endl; + std::cout << " For the first matrix" << std::endl; + what_matrix_sizes(what_the_first_matrix, size_cols1, size_rows1); + std::cout << "======================================================" << std::endl; + std::cout << " For the second matrix" << std::endl; + what_matrix_sizes(what_the_second_matrix, size_cols2, size_rows2); + } + size_res_rows = size_cols1; + size_res_rows = size_rows2; + } + + if (what_the_first_matrix == STANDART && what_the_second_matrix == STANDART) { + Matrix matrix1(size_rows1, size_cols1); + Matrix matrix2(size_rows2, size_cols2); + Matrix intermediate_res; + std::cout << "======================================================" << std::endl; + std::cout << " For the first matrix:" << std::endl; + input_standart_matrix(matrix1, size_rows1, size_cols1); + std::cout << "======================================================" << std::endl; + std::cout << " For the second matrix:" << std::endl; + input_standart_matrix(matrix2, size_rows2, size_cols2); + switch (link_user_choice) { + case ADD: intermediate_res = matrix1 + matrix2; break; + case SUBTRACT: intermediate_res = matrix1 - matrix2; break; + case MULTIPLY: intermediate_res = matrix1 * matrix2; break; + } + res = intermediate_res; + std::cout << "======================================================" << std::endl; + std::cout << " RESULT:" << std::endl; + std::cout << res << std::endl; + do_user_want_to_save(link_want_to_save); + } + else if (what_the_first_matrix == TRIANGLE && what_the_second_matrix == TRIANGLE) { + TriangleMatrix matrix1(size_rows1); + TriangleMatrix matrix2(size_rows2); + TriangleMatrix intermediate_res; + std::cout << "======================================================" << std::endl; + std::cout << " For the first triangle matrix:" << std::endl; + input_triangle_matrix(matrix1, size_rows1); + std::cout << "======================================================" << std::endl; + std::cout << " For the second triangle matrix:" << std::endl; + input_triangle_matrix(matrix2, size_rows2); + switch (link_user_choice) { + case ADD: intermediate_res = matrix1 + matrix2; break; + case SUBTRACT: intermediate_res = matrix1 - matrix2; break; + case MULTIPLY: intermediate_res = matrix1 * matrix2; break; + } + res = triangle_to_full(intermediate_res); + std::cout << "======================================================" << std::endl; + std::cout << " RESULT:" << std::endl; + std::cout << res << std::endl; + do_user_want_to_save(link_want_to_save); + } + else if (what_the_first_matrix == STANDART && what_the_second_matrix == TRIANGLE) { + Matrix matrix1(size_rows1, size_cols1), intermediate_res; + TriangleMatrix matrix2(size_rows2); + std::cout << "======================================================" << std::endl; + std::cout << " For the first standart matrix:" << std::endl; + input_standart_matrix(matrix1, size_rows1, size_cols1); + std::cout << "======================================================" << std::endl; + std::cout << " For the second triangle matrix:" << std::endl; + input_triangle_matrix(matrix2, size_rows2); + switch (link_user_choice) { + case ADD: intermediate_res = matrix1 + matrix2; break; + case SUBTRACT: intermediate_res = matrix1 - matrix2; break; + case MULTIPLY: intermediate_res = matrix1 * matrix2; break; + } + res = intermediate_res; + std::cout << "======================================================" << std::endl; + std::cout << " RESULT:" << std::endl; + std::cout << res << std::endl; + do_user_want_to_save(link_want_to_save); + } + else if (what_the_first_matrix == TRIANGLE && what_the_second_matrix == STANDART) { + TriangleMatrix matrix1(size_rows1); + Matrix matrix2(size_rows2, size_cols2), intermediate_res; + std::cout << "======================================================" << std::endl; + std::cout << " For the first triangle matrix:" << std::endl; + input_triangle_matrix(matrix1, size_rows1); + std::cout << "======================================================" << std::endl; + std::cout << " For the second standart matrix:" << std::endl; + input_standart_matrix(matrix2, size_rows2, size_cols2); + switch (link_user_choice) { + case ADD: intermediate_res = matrix1 + matrix2; break; + case SUBTRACT: intermediate_res = matrix1 - matrix2; break; + case MULTIPLY: intermediate_res = matrix1 * matrix2; break; + } + res = intermediate_res; + std::cout << "======================================================" << std::endl; + std::cout << " RESULT:" << std::endl; + std::cout << res << std::endl; + do_user_want_to_save(link_want_to_save); + } + + if (link_want_to_save == YES) { + int user_choice_for_deleted; + while ((count_of_saved_matrices + 1) > MAX_COUNT_OF_SAVED_MATRICES) { + deleted_saved_matrix(user_choice_for_deleted, isThereMatrix1, isThereMatrix2, isThereMatrix3); + if (user_choice_for_deleted == EXIT_DELETED_SAVED_MATRICES_MENU) { break; } + else { count_of_saved_matrices--; } + } + if (isThereMatrix1 == NO) { + std::cout << "======================================================" << std::endl; + std::cout << " The result will be written to the matrix1" << std::endl; + isThereMatrix1 = YES; + count_of_saved_matrices++; + matrix1 = res; + } + else if (isThereMatrix2 == NO) { + std::cout << "======================================================" << std::endl; + std::cout << " The result will be written to the matrix2" << std::endl; + isThereMatrix2 = YES; + count_of_saved_matrices++; + matrix2 = res; + } + else if (isThereMatrix3 == NO) { + std::cout << "======================================================" << std::endl; + std::cout << " The result will be written to the matrix3" << std::endl; + isThereMatrix3 = YES; + count_of_saved_matrices++; + matrix3 = res; + } + std::cout << " Press Enter to exit " << std::endl; + getchar(); + getchar(); + system("cls"); + } + } +} +void deleted_saved_matrix(int& link_user_choice_for_deleted, int& isThereMatrix1, int& isThereMatrix2, int& isThereMatrix3) { + std::cout << "======================================================" << std::endl; + std::cout << " You can store a limited number of matrices" << std::endl; + std::cout << " Which one would you like to delete?" << std::endl; + std::cout << " 1. matrix1" << std::endl; + std::cout << " 2. matrix2" << std::endl; + std::cout << " 3. matrix3" << std::endl;; + std::cout << " 4. exit" << std::endl; + + while (!input_user_choice(link_user_choice_for_deleted, EXIT_DELETED_SAVED_MATRICES_MENU)); + switch (link_user_choice_for_deleted) { + case MATRIX1: isThereMatrix1 = NO; break; + case MATRIX2: isThereMatrix2 = NO; break; + case MATRIX3: isThereMatrix3 = NO; break; + case EXIT_DELETED_SAVED_MATRICES_MENU: break; + } +} +void viewing_saved_matrices(int count_of_saved_matrices, Matrix matrix1, Matrix matrix2, Matrix matrix3) { + std::cout << "======================================================" << std::endl; + if (count_of_saved_matrices > 0) { + std::cout << " Which matrix would you like to look at?" << std::endl; + if (count_of_saved_matrices == MAX_COUNT_OF_SAVED_MATRICES) { + std::cout << " 1. matrix1" << std::endl; + std::cout << " 2. matrix2" << std::endl; + std::cout << " 3. matrix3" << std::endl; + } + else if (count_of_saved_matrices == MAX_COUNT_OF_SAVED_MATRICES - 1) { + std::cout << " 1. matrix1" << std::endl; + std::cout << " 2. matrix2" << std::endl; + } + else if (count_of_saved_matrices == MAX_COUNT_OF_SAVED_MATRICES - 2) { + std::cout << " 1. matrix1" << std::endl; + } + int user_choice; + int& link_user_choice = user_choice; + while (!input_user_choice(link_user_choice, START_MENU_FOR_MATRIX_SIZE)); + if (user_choice == MATRIX1) { + std::cout << "======================================================" << std::endl << std::endl; + std::cout << matrix1 << std::endl; + } + else if (user_choice == MATRIX2) { + std::cout << "======================================================" << std::endl; + std::cout << matrix2 << std::endl; + } + else if (user_choice == MATRIX3) { + std::cout << "======================================================" << std::endl; + std::cout << matrix3 << std::endl; + } + } + else if (count_of_saved_matrices == 0) { + std::cout << " You don't have any saved matrices" << std::endl; + } + std::cout << "======================================================" << std::endl; + std::cout << " Press Enter to exit " << std::endl; + getchar(); + getchar(); + system("cls"); +} +void matrix_application() { + int user_choice = 0; + int isExit = NO; + int want_to_save = NO; + int count_of_saved_matrices = 0; + Matrix res, matrix1, matrix2, matrix3; + int isThereMatrix1 = NO; + int isThereMatrix2 = NO; + int isThereMatrix3 = NO; + while (!isExit) { + start_menu_for_matrix(); + while (!input_user_choice(user_choice, START_MENU_FOR_MATRIX_SIZE)); + system("cls"); + switch (user_choice) { + case MATRIX_CALCULATOR: + start_matrix_calculator(user_choice, want_to_save, res, count_of_saved_matrices, matrix1, matrix2, matrix3, isThereMatrix1, isThereMatrix2, isThereMatrix3); + break; + case VIEWING_SAVED_MATRICES: + viewing_saved_matrices(count_of_saved_matrices, matrix1, matrix2, matrix3); + break; + case EXIT_MAIN_MENU: + isExit = YES; + break; + } + } +} + + +inline bool is_open_bracket(char symbol) { + return symbol == '(' || symbol == '[' || symbol == '{'; +} +inline bool is_close_bracket(char symbol) { + return symbol == ')' || symbol == ']' || symbol == '}'; +} +inline bool matches_pair(char open, char close) { + return (open == '(' && close == ')') || + (open == '[' && close == ']') || + (open == '{' && close == '}'); +} +bool check_brackets(const std::string& str) { + Stack stack(SIZE_OF_STACK_FOR_CHECK_BRACKETS); + for (size_t i = 0; i < str.length(); ++i) { + char symbol = str[i]; + if (is_open_bracket(symbol)) { + try { + stack.push(symbol); + } + catch (const std::overflow_error&) { + std::cout << "Stack is full" << std::endl; + return false; + } + } + else if (is_close_bracket(symbol)) { + if (stack.is_empty()) { + return false; + } + char top = stack.top(); + if (!matches_pair(top, symbol)) { + return false; + } + stack.pop(); + } + } + return stack.is_empty(); +} \ No newline at end of file diff --git a/lib_algorithms/algorithms.h b/lib_algorithms/algorithms.h new file mode 100644 index 00000000..ebd9a309 --- /dev/null +++ b/lib_algorithms/algorithms.h @@ -0,0 +1,288 @@ +// Copyright 2025 Ekaterina Ushnitskaya + + +#ifndef LIB_ALGORITHMS_H +#define LIB_ALGORITHMS_H + +#include +#include "../lib_circle/circle.h" +#include "../lib_sphere/sphere.h" +#include "../lib_tvector/tvector.h" +#include "../lib_mathvector/MathVector.h" +#include "../lib_matrix/matrix.h" +#include "../lib_triangle_matrix/triangle_matrix.h" +#include "../lib_stack/stack.h" +#include "../lib_node/node.h" +#include "../lib_list/list.h" + +#define START_MENU_MATRIX_SIZE 3 +#define REALISED_Matrix + +#define NUMBER1 1 +#define NUMBER2 2 +#define NUMBER3 3 +#define NUMBER4 4 + +template class Matrix; +template class TriangleMatrix; + +enum Location { intersecting, do_not_intersecting, tangent, inside, coinside }; +//tangent - , intersecting - , inside - , coinside - + +void set_color(int text_color, int bg_color); +void print_result_position(const std::string& description, Location result); +void in_development(); + +template +Location check_position(const T& circle1, const T& circle2) { + Point center1 = circle1.get_center(); + Point center2 = circle2.get_center(); + int radius1 = circle1.get_radius(); + int radius2 = circle2.get_radius(); + + double distance = center1.distance_to(center2); + int sum_rad = radius1 + radius2; + int abs_difference = std::abs(radius1 - radius2); + + if (distance == 0 && radius1 == radius2) { + return coinside; // + } + else if (distance < abs_difference) { + return inside; // + } + else if (distance == abs_difference) { + return tangent; // + } + else if (distance < sum_rad && distance > abs_difference) { + return intersecting; // + } + else if (distance == sum_rad) { + return tangent; // + } + else { + return do_not_intersecting; // + } +} + +template +bool has_unique_elements(const Matrix& matrix) { + TVector elements; + for (size_t i = 0; i < matrix.rows(); i++) { + for (size_t j = 0; j < matrix.cols(); j++) { + elements.push_back(matrix.at(i, j)); + } + } + quick_sort(elements); + for (size_t i = 1; i < elements.size(); ++i) { + if (elements[i] == elements[i - 1]) { return false; } + } + return true; +} +template +int what_number_less(const T& num1, const T& num2, const T& num3, const T& num4) { + if (num1 < num2 && num1 < num3 && num1 < num4) { + return NUMBER1; + } + else if (num2 < num1 && num2 < num3 && num2 < num4) { + return NUMBER2; + } + else if (num3 < num1 && num3 < num2 && num3 < num4) { + return NUMBER3; + } + else { + return NUMBER4; + } +} +template +T gradient_descent(const Matrix& matrix) { + srand(time(0)); + if (matrix.cols() != matrix.rows()) { + throw std::invalid_argument("The Matrix should be square"); + } + if (!has_unique_elements(matrix)) { + throw std::invalid_argument("The Matrix should has only unique elements"); + } + + size_t start_row_pos = 0, start_col_pos = 0; + start_row_pos = rand() % matrix.rows() + 0; + start_col_pos = rand() % matrix.cols() + 0; + + if (start_row_pos >= matrix.rows() || start_col_pos >= matrix.cols()) { + throw std::out_of_range("Start position out of matrix bounds"); + } + + T current_value = matrix.at(start_row_pos, start_col_pos); + size_t current_row = start_row_pos; + size_t current_col = start_col_pos; + + const size_t max_steps = matrix.rows() * matrix.cols(); + size_t steps = 0; + bool improved = true; + + while (improved && steps < max_steps) { + improved = false; + T best_neighbor_value = current_value; + size_t best_neighbor_row = current_row; + size_t best_neighbor_col = current_col; + + if (current_row > 0) { // + T up_value = matrix.at(current_row - 1, current_col); + if (up_value < best_neighbor_value) { + best_neighbor_value = up_value; + best_neighbor_row = current_row - 1; + best_neighbor_col = current_col; + improved = true; + } + } + + if (current_col < matrix.cols() - 1) { // + T right_value = matrix.at(current_row, current_col + 1); + if (right_value < best_neighbor_value) { + best_neighbor_value = right_value; + best_neighbor_row = current_row; + best_neighbor_col = current_col + 1; + improved = true; + } + } + + if (current_row < matrix.rows() - 1) { // + T down_value = matrix.at(current_row + 1, current_col); + if (down_value < best_neighbor_value) { + best_neighbor_value = down_value; + best_neighbor_row = current_row + 1; + best_neighbor_col = current_col; + improved = true; + } + } + + if (current_col > 0) { // + T left_value = matrix.at(current_row, current_col - 1); + if (left_value < best_neighbor_value) { + best_neighbor_value = left_value; + best_neighbor_row = current_row; + best_neighbor_col = current_col - 1; + improved = true; + } + } + + if (improved) { + current_row = best_neighbor_row; + current_col = best_neighbor_col; + current_value = best_neighbor_value; + steps++; + } + } + std::cout << "Final value: " << current_value << std::endl; + + return current_value; +} + +void start_menu_for_matrix(); +void viewing_saved_matrices(int count_of_saved_matrices, Matrix matrix1, Matrix matrix2, Matrix matrix3); +void start_matrix_calculator(int& link_user_choice, int& link_want_to_save, Matrix res, int& count_of_saved_matrices, Matrix& matrix1, Matrix& matrix2, Matrix& matrix3, int& isThereMatrix1, int& isThereMatrix2, int& isThereMatrix3); +void do_user_want_to_save(int& want_to_save); +void input_standart_matrix(Matrix& matrix, size_t rows, size_t cols); +void input_triangle_matrix(TriangleMatrix& matrix, size_t n); +Matrix triangle_to_full(const TriangleMatrix& matrix); +void check_user_input(int user_choice, int true_number); +bool input_user_choice(int& user_choice, int true_number); +void what_matrices(int& what_the_first_matrix, int& what_the_second_matrix, int& isExit); +void print_menu_matrix_calculator(); +void what_matrix_sizes(const int& type_matrix, size_t& size_rows, size_t& size_cols); +void deleted_saved_matrix(int& link_user_choice_for_deleted, int& isThereMatrix1, int& isThereMatrix2, int& isThereMatrix3); +void matrix_application(); + +inline bool is_open_bracket(char symbol); +inline bool is_close_bracket(char symbol); +inline bool matches_pair(char open, char close); +bool check_brackets(const std::string& str); + +template +bool is_looped_hare_and_turtle(List& list) { + Node* head = list.head(); + if (head == nullptr) { + return false; + } + Node* fast = head; + Node* slow = head; + while (fast != nullptr && fast->next != nullptr) { + slow = slow->next; + fast = fast->next->next; + if (slow == fast) { + return true; + } + } + return false; +} + +template +bool is_looped_turn_ptr(List& list) { + Node* head = list.head(); + if (head == nullptr || head->next == nullptr) { + return false; + } + + Node* cur = head; + Node* prev = nullptr; + Node* next = nullptr; + + while (cur != nullptr) { + next = cur->next; + cur->next = prev; + prev = cur; + cur = next; + + if (cur == head) { + cur = prev; + prev = nullptr; + while (cur != nullptr) { + next = cur->next; + cur->next = prev; + prev = cur; + cur = next; + } + return true; + } + } + cur = prev; + prev = nullptr; + while (cur != nullptr) { + next = cur->next; + cur->next = prev; + prev = cur; + cur = next; + } + return false; +} + +template +Node* find_loop_node(List& list) { + Node* head = list.head(); + if (head == nullptr) { + return nullptr; + } + Node* slow = head; + Node* fast = head; + bool has_loop = false; + while (fast != nullptr && fast->next != nullptr) { + slow = slow->next; + fast = fast->next->next; + if (slow == fast) { + has_loop = true; + break; + } + } + if (!has_loop) { + return nullptr; + } + if (slow == fast) { + slow = head; + while (slow != fast) { + slow = slow->next; + fast = fast->next; + } + return slow; + } + return nullptr; +} +#endif // LIB_ALGORITHMS_H \ No newline at end of file diff --git a/lib_circle/CMakeLists.txt b/lib_circle/CMakeLists.txt new file mode 100644 index 00000000..51eabd81 --- /dev/null +++ b/lib_circle/CMakeLists.txt @@ -0,0 +1,2 @@ +create_project_lib(Circle) +add_depend(Circle Point lib_point) \ No newline at end of file diff --git a/lib_circle/circle.cpp b/lib_circle/circle.cpp new file mode 100644 index 00000000..e50cf301 --- /dev/null +++ b/lib_circle/circle.cpp @@ -0,0 +1,38 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include +////#include "../lib_point/point.h" +#include "../lib_circle/circle.h" + + +Circle::Circle() : _center(Point()), _radius(1) {}; +Circle::Circle(Point value_dot, int value_rad) { + if (value_rad < 0) { + throw std::logic_error("Error!!! The radius can't be less than zero"); + } + _center = value_dot; + _radius = value_rad; +} + +Circle::Circle(const Circle& other) { + if (&other == NULL) { + throw std::logic_error("Error!!!"); + } + _center = other._center; + _radius = other._radius; +} + +Point Circle::get_center() const { + return _center; +} +int Circle::get_radius() const { + return _radius; +} + +void Circle::set_center(Point dot) { + _center = dot; +} +void Circle::set_radius(int rad) { + _radius = rad; +} \ No newline at end of file diff --git a/lib_circle/circle.h b/lib_circle/circle.h new file mode 100644 index 00000000..1199d14e --- /dev/null +++ b/lib_circle/circle.h @@ -0,0 +1,24 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_CIRCLE_CIRCLE_H +#define LIB_CIRCLE_CIRCLE_H + +#include "../lib_point/point.h" + + +class Circle { + Point _center; + int _radius; +public: + Circle(); + Circle(Point, int); + Circle(const Circle&); + + Point get_center() const; + int get_radius() const; + + void set_center(Point); + void set_radius(int); +}; + +#endif // LIB_CIRCLE_CIRCLE_H diff --git a/lib_dlist/CMakeLists.txt b/lib_dlist/CMakeLists.txt new file mode 100644 index 00000000..22ed0e22 --- /dev/null +++ b/lib_dlist/CMakeLists.txt @@ -0,0 +1,2 @@ +create_project_lib(DList) +add_depend(DList Node lib_node) \ No newline at end of file diff --git a/lib_dlist/dlist.cpp b/lib_dlist/dlist.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_dlist/dlist.h b/lib_dlist/dlist.h new file mode 100644 index 00000000..ef9f27ee --- /dev/null +++ b/lib_dlist/dlist.h @@ -0,0 +1,323 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_DLIST_DLIST_H +#define LIB_DLIST_DLIST_H + +#include +#include + +#include "../lib_node/node.h" + +template +class DList { + NodeD* _head; + NodeD* _tail; +public: + DList() : _head(nullptr), _tail(nullptr) {} + DList(const DList& other) : _head(nullptr), _tail(nullptr) { + NodeD* cur = other._head; + while (cur != nullptr) { + push_back(cur->value); + cur = cur->next; + } + } + ~DList() { + clear(); + } + class Iterator { + NodeD* _current; + public: + Iterator() : _current(nullptr) {} + Iterator(NodeD* ptr) : _current(ptr) {} + + Iterator& operator=(const Iterator& other) { + if (this != &other) { + _current = other._current; + } + return *this; + } + Iterator operator++(int) { //iterator++ + Iterator tmp = *this; + if (_current != nullptr) { + _current = _current->next; + } + return tmp; + } + Iterator& operator++() { // ++iterator + if (_current != nullptr) { + _current = _current->next; + } + return *this; + } + bool operator!=(const Iterator& other) const { + return _current != other._current; + } + bool operator==(const Iterator& other) const { + return !(*this != other); + } + T& operator*() { + return _current->value; + } + Iterator& operator+=(size_t n) { + while (n > 0 && _current != nullptr) { + _current = _current->next; + n--; + } + return *this; + } + Iterator operator--(int) { //iterator-- + Iterator tmp = *this; + if (_current != nullptr) { + _current = _current->prev; + } + return tmp; + } + Iterator& operator--() { //--iterator + if (_current != nullptr) { + _current = _current->prev; + } + return *this; + } + Iterator& operator-=(size_t n) { + while (n > 0 && _current != nullptr) { + _current = _current->prev; + n--; + } + return *this; + } + }; + Iterator begin() { return Iterator(_head); } + Iterator end() { return Iterator(nullptr); } + Iterator rbegin() { return Iterator(_tail); } + Iterator rend() { return Iterator(nullptr); } + + inline NodeD* head(); + inline const NodeD* head() const; + inline NodeD* tail(); + inline const NodeD* tail() const; + bool is_empty() const; + void push_front(const T& value); + void push_back(const T& value); + void insert(size_t pos, const T& value); + void insert_after(NodeD* node, const T& value); + void insert_before(NodeD* node, const T& value); + void pop_front(); + void pop_back(); + void erase(NodeD* node); + void erase(size_t pos); + DList& operator=(const DList& other); +private: + void clear(); + bool is_node_in_list(NodeD* node) const; +}; + +template +inline NodeD* DList::head() { return _head; } + +template +inline const NodeD* DList::head() const { return _head; } + +template +inline NodeD* DList::tail() { return _tail; } +template +inline const NodeD* DList::tail() const { return _tail; } + +template +bool DList::is_empty() const { return _head == nullptr; } + +template +void DList::push_front(const T& value) { // O(1) + NodeD* node = new NodeD(value, _head, nullptr); + if (is_empty()) { + _tail = node; + } + else { + _head->prev = node; + } + _head = node; +} + +template +void DList::push_back(const T& value) { // O(1) + NodeD* node = new NodeD(value, nullptr, _tail); + if (is_empty()) { + _head = node; + } + else { + _tail->next = node; + } + _tail = node; +} + +template +void DList::insert(size_t pos, const T& value) { // O(n) + if (pos == 0) { + push_front(value); + return; + } + NodeD* cur = _head; + for (size_t i = 0; i < pos; ++i) { + if (cur == nullptr) { + throw std::out_of_range("Position out of range"); + } + cur = cur->next; + } + if (cur == nullptr) { + push_back(value); + return; + } + insert_before(cur, value); +} + +template +void DList::insert_after(NodeD* node, const T& value) { // O(1) + if (node == nullptr) { + throw std::invalid_argument("Node can't be nullptr"); + } + if (!is_node_in_list(node)) { + throw std::invalid_argument("Node is not in List"); + } + + NodeD* new_node = new NodeD(value, node->next, node); + node->next = new_node; + if (new_node->next != nullptr) { + new_node->next->prev = new_node; + } + else { + _tail = new_node; + } +} + +template +void DList::insert_before(NodeD* node, const T& value) { // O(1) + if (node == nullptr) { + throw std::invalid_argument("Node can't be nullptr"); + } + if (!is_node_in_list(node)) { + throw std::invalid_argument("Node is not in List"); + } + + NodeD* new_node = new NodeD(value, node, node->prev); + node->prev = new_node; + if (new_node->prev != nullptr) { + new_node->prev->next = new_node; + } + else { + _head = new_node; + } +} + +template +void DList::pop_front() { // O(1) + if (is_empty()) { + throw std::underflow_error("List is empty"); + } + NodeD* old_head = _head; + _head = _head->next; + if (_head != nullptr) { + _head->prev = nullptr; + } + else { + _tail = nullptr; + } + delete old_head; +} + +template +void DList::pop_back() { // O(1) + if (is_empty()) { + throw std::underflow_error("List is empty"); + } + NodeD* old_tail = _tail; + _tail = _tail->prev; + if (_tail != nullptr) { + _tail->next = nullptr; + } + else { + _head = nullptr; + } + delete old_tail; +} + +template +void DList::erase(NodeD* node) { // O(1) + if (node == nullptr) { + throw std::invalid_argument("Node can't be nullptr"); + } + if (is_empty()) { + throw std::underflow_error("List is empty"); + } + if (!is_node_in_list(node)) { + throw std::invalid_argument("Node is not in List"); + } + if (node == _head) { + pop_front(); + return; + } + if (node == _tail) { + pop_back(); + return; + } + node->prev->next = node->next; + node->next->prev = node->prev; + delete node; +} + + +template +void DList::erase(size_t pos) { // O(n) + if (is_empty()) { + throw std::underflow_error("List is empty"); + } + NodeD* cur = _head; + for (size_t i = 0; i < pos; ++i) { + if (cur == nullptr) { + throw std::out_of_range("Position out of range"); + } + cur = cur->next; + } + if (cur == nullptr) { + throw std::out_of_range("Position out of range"); + } + erase(cur); +} + +template +DList& DList::operator=(const DList& other) { + if (this == &other) { + return *this; + } + clear(); + NodeD* other_cur = other._head; + while (other_cur != nullptr) { + push_back(other_cur->value); + other_cur = other_cur->next; + } + return *this; +} + +template +void DList::clear() { + NodeD* cur = _head; + while (cur != nullptr) { + NodeD* next_node = cur->next; + delete cur; + cur = next_node; + } + _head = nullptr; + _tail = nullptr; +} + +template +bool DList::is_node_in_list(NodeD* node) const { + NodeD* cur = _head; + while (cur != nullptr) { + if (cur == node) { + return true; + } + cur = cur->next; + } + return false; +} + +#endif \ No newline at end of file diff --git a/lib_list/CMakeLists.txt b/lib_list/CMakeLists.txt new file mode 100644 index 00000000..ae414a82 --- /dev/null +++ b/lib_list/CMakeLists.txt @@ -0,0 +1,2 @@ +create_project_lib(List) +add_depend(List Node lib_node) \ No newline at end of file diff --git a/lib_list/list.cpp b/lib_list/list.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_list/list.h b/lib_list/list.h new file mode 100644 index 00000000..c4ae8886 --- /dev/null +++ b/lib_list/list.h @@ -0,0 +1,294 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_LIST_LIST_H +#define LIB_LIST_LIST_H + +#include +#include + +#include "../lib_node/node.h" + +template +class List { + Node* _head; + Node* _tail; +public: + List() : _head(nullptr), _tail(nullptr) {} + List(const List& other) : _head(nullptr), _tail(nullptr) { + Node* cur = other._head; + while (cur != nullptr) { + push_back(cur->value); + cur = cur->next; + } + } + ~List() { + clear(); + } + class Iterator { + Node* _current; + public: + Iterator() : _current(nullptr) {} + Iterator(Node* ptr) : _current(ptr) {} + + Iterator& operator=(const Iterator& other) { + if (this != &other) { + _current = other._current; + } + return *this; + } + Iterator operator++(int) { //iterator++ + Iterator tmp = *this; + if (_current != nullptr) { + _current = _current->next; + } + return tmp; + } + Iterator& operator++() { // ++iterator + if (_current != nullptr) { + _current = _current->next; + } + return *this; + } + bool operator!=(const Iterator& other) const { + return _current != other._current; + } + bool operator==(const Iterator& other) const { + return !(*this != other); + } + T& operator*() { + return _current->value; + } + Iterator& operator+=(size_t n) { + while (n > 0 && _current != nullptr) { + _current = _current->next; + n--; + } + return *this; + } + }; + Iterator begin() { return Iterator(_head); } + Iterator end() { return Iterator(nullptr); } + + inline Node* head(); + inline const Node* head() const; + inline Node* tail(); + inline const Node* tail() const; + bool is_empty() const; + void push_front(const T& value); + void push_back(const T& value); + void insert(size_t pos, const T& value); + void insert(Node* node, const T& value); + void pop_front(); + void pop_back(); + void erase(size_t pos); + void erase(Node* node); + List& operator=(const List& other); + void clear(); +private: + bool is_node_in_list(Node* node) const; +}; + +template +inline Node* List::head() { return _head; } + +template +inline const Node* List::head() const { return this->_head; } + +template +inline Node* List::tail() { return _tail; } + +template +inline const Node* List::tail() const { return this->_tail; } + +template +bool List::is_empty() const { + return _head == nullptr; +} + +template +void List::push_front(const T& value) { + Node* node = new Node(value, _head); + if (is_empty()) { + _tail = node; + } + _head = node; +} + +template +void List::push_back(const T& value) { + Node* node = new Node(value, nullptr); + if (is_empty()) { + _head = node; + _tail = node; + } + else { + _tail->next = node; + _tail = node; + } +} + +template +void List::insert(size_t pos, const T& value) { + if (pos == 0) { + push_front(value); + return; + } + Node* cur = _head; + for (size_t i = 0; i < pos - 1; ++i) { + if (cur == nullptr) { + throw std::out_of_range("Position out of range"); + } + cur = cur->next; + } + if (cur == nullptr) { + throw std::out_of_range("Position out of range"); + } + if (cur == _tail) { + push_back(value); + } + else { + Node* node = new Node(value, cur->next); + cur->next = node; + } +} + +template +void List::insert(Node* node, const T& value) { + if (node == nullptr) { + throw std::invalid_argument("Node can't be nullptr"); + } + if (!is_node_in_list(node)) { + throw std::invalid_argument("Node is not in List"); + } + Node* new_node = new Node(value, node->next); + node->next = new_node; + if (node == _tail) { + _tail = new_node; + } +} + +template +void List::pop_front() { + if (is_empty()) { + throw std::underflow_error("List is empty"); + } + Node* old_head = _head; + _head = _head->next; + if (old_head == _tail) { + _tail = nullptr; + } + delete old_head; +} + +template +void List::pop_back() { + if (is_empty()) { + throw std::underflow_error("List is empty"); + } + if (_head == _tail) { + Node* node_to_delete = _head; + _head = nullptr; + _tail = nullptr; + delete node_to_delete; + return; + } + Node* cur = _head; + while (cur->next != _tail) { + cur = cur->next; + } + Node* node_to_delete = _tail; + _tail = cur; + cur->next = nullptr; + delete node_to_delete; +} + +template +void List::erase(size_t pos) { + if (is_empty()) { + throw std::underflow_error("List is empty"); + } + if (pos == 0) { + pop_front(); + return; + } + Node* cur = _head; + for (size_t i = 0; i < pos - 1; ++i) { + if (cur == nullptr) { + throw std::out_of_range("Position out of range"); + } + cur = cur->next; + } + if (cur == nullptr || cur->next == nullptr) { + throw std::out_of_range("Position out of range"); + } + Node* node_to_delete = cur->next; + if (node_to_delete == _tail) { + _tail = cur; + } + cur->next = node_to_delete->next; + delete node_to_delete; +} + +template +void List::erase(Node* node) { + if (node == nullptr) { + throw std::invalid_argument("Node can't be nullptr"); + } + if (!is_node_in_list(node)) { + throw std::invalid_argument("Node is not in List"); + } + if (node == _head) { + pop_front(); + return; + } + Node* cur = _head; + while (cur->next != node) { + cur = cur->next; + } + Node* node_to_delete = cur->next; + if (node_to_delete == _tail) { + _tail = cur; + } + cur->next = node_to_delete->next; + delete node_to_delete; +} + +template +List& List::operator=(const List& other) { + if (this == &other) { + return *this; + } + clear(); + Node* other_cur = other._head; + while (other_cur != nullptr) { + push_back(other_cur->value); + other_cur = other_cur->next; + } + return *this; +} + +template +void List::clear() { + Node* cur = _head; + while (cur != nullptr) { + Node* next_node = cur->next; + delete cur; + cur = next_node; + } + _head = nullptr; + _tail = nullptr; +} + +template +bool List::is_node_in_list(Node* node) const { + Node* cur = _head; + while (cur != nullptr) { + if (cur == node) { + return true; + } + cur = cur->next; + } + return false; +} + +#endif \ No newline at end of file diff --git a/lib_mathvector/CMakeLists.txt b/lib_mathvector/CMakeLists.txt new file mode 100644 index 00000000..9970b8ab --- /dev/null +++ b/lib_mathvector/CMakeLists.txt @@ -0,0 +1,2 @@ +create_project_lib(MathVector) +add_depend(MathVector TVector lib_tvector) \ No newline at end of file diff --git a/lib_mathvector/MathVector.cpp b/lib_mathvector/MathVector.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_mathvector/MathVector.h b/lib_mathvector/MathVector.h new file mode 100644 index 00000000..6ed4ff9a --- /dev/null +++ b/lib_mathvector/MathVector.h @@ -0,0 +1,212 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_MATHVECTOR_MATHVECTOR_H +#define LIB_MATHVECTOR_MATHVECTOR_H + +#include // {} + +#include "../lib_tvector/tvector.h" +#include "../lib_algorithms/algorithms.h" + +template +class MathVector : public TVector { +public: + using TVector::TVector; // TVector + MathVector() : TVector() {} + MathVector(const MathVector& other) : TVector(other) {} + MathVector(const std::initializer_list list) { + this->_size= list.size(); + this->_capacity = this->size()+ TVector::RESERVE_MEMORY; + this->_deleted = 0; + this->_data = new T[this->_capacity]; + this->_states = new State[this->_capacity]; + size_t i = 0; + for (const auto& value : list) { //auto list + this->_data[i] = value; + this->_states[i] = busy; + ++i; + } + for (; i < this->_capacity; ++i) { + this->_states[i] = empty; + } + } + template + MathVector(const MathVector& other) { + this->_size = other.size(); + this->_capacity = this->size() + TVector::RESERVE_MEMORY; + this->_deleted = 0; + this->_data = new T[this->_capacity]; + this->_states = new State[this->_capacity]; + + for (size_t i = 0; i < this->_size; ++i) { + this->_data[i] = static_cast(other.data(i)); // U T + this->_states[i] = other.state(i); + } + for (size_t i = this->_size; i < this->_capacity; ++i) { + this->_states[i] = State::empty; + } + } + + MathVector operator+(const MathVector& other) const; + template + MathVector> operator+(const MathVector& other) const; + + MathVector operator-(const MathVector& other) const; + template + MathVector> operator-(const MathVector& other) const; + + MathVector operator*(const T& scalar) const; + template + MathVector> operator*(const U& scalar) const; + T operator*(const MathVector& other_vec) const; + template + std::common_type_t operator*(const MathVector& other) const; + + MathVector& operator+=(const MathVector& other); + MathVector& operator-=(const MathVector& other); + MathVector& operator*=(const T& scalar); + + auto length() const; +}; + +template +MathVector MathVector::operator+(const MathVector& other) const { + if (this->size() != other._size) { + throw std::invalid_argument("Vectors should have same size for addition"); + } + MathVector result(this->_size); + for (size_t i = 0; i < this->_size; ++i) { + result[i] = this->_data[i] + other._data[i]; + result._states[i] = busy; + } + return result; +} + +template +template +MathVector> MathVector::operator+(const MathVector& other) const { + using R = std::common_type_t; // std::common_type_t + if (this->size() != other.size()) { + throw std::invalid_argument("Vectors should have same size for addition"); + } + MathVector result(this->_size); + for (size_t i = 0; i < this->_size; ++i) { + result[i] = static_cast(this->_data[i]) + static_cast(other.data(i)); + } + return result; +} + +template +MathVector MathVector::operator-(const MathVector& other) const { + if (this->size() != other._size) { + throw std::invalid_argument("Vectors should have same size for subtraction"); + } + MathVector result(this->_size); + for (size_t i = 0; i < this->_size; ++i) { + result[i] = this->_data[i] - other._data[i]; + result._states[i] = busy; + } + return result; +} + +template +template +MathVector> MathVector::operator-(const MathVector& other) const { + using R = std::common_type_t; // std::common_type_t + if (this->size() != other.size()) { + throw std::invalid_argument("Vectors should have same size for subtraction"); + } + MathVector result(this->_size); + for (size_t i = 0; i < this->_size; ++i) { + result[i] = static_cast(this->_data[i]) - static_cast(other.data(i)); + } + return result; +} + +template +MathVector MathVector::operator*(const T& scalar) const { + MathVector result(this->_size); + for (size_t i = 0; i < this->_size; ++i) { + result._data[i] = this->_data[i] * scalar; + result._states[i] = busy; + } + return result; +} + +template +template +MathVector> MathVector::operator*(const U& scalar) const { + using R = std::common_type_t; + MathVector result(this->_size); + for (size_t i = 0; i < this->_size; ++i) { + result[i] = static_cast(this->_data[i]) * static_cast(scalar); + } + return result; +} + +template +T MathVector::operator*(const MathVector& other_vec) const { + if (this->size() != other_vec._size) { + throw std::invalid_argument("Vectors should have same size for dot product"); + } + T result = 0; + for (size_t i = 0; i < this->_size; ++i) { + result += this->_data[i] * other_vec._data[i]; + } + return result; +} + +template +template +std::common_type_t MathVector::operator*(const MathVector& other) const { + using R = std::common_type_t; + if (this->size() != other.size()) { + throw std::invalid_argument("Vectors should have same size for dot product"); + } + R result = 0; + for (size_t i = 0; i < this->_size; ++i) { + result += static_cast(this->_data[i]) * static_cast(other.data(i)); + } + return result; +} + +template +MathVector& MathVector::operator+=(const MathVector& other) { + if (this->size() != other._size) { + throw std::invalid_argument("Vectors should have same size for addition"); + } + for (size_t i = 0; i < this->_size; ++i) { + this->_data[i] = this->_data[i] + other._data[i]; + } + return *this; +} + +template +MathVector& MathVector::operator-=(const MathVector& other) { + if (this->size() != other._size) { + throw std::invalid_argument("Vectors should have same size for subtraction"); + } + for (size_t i = 0; i < this->_size; ++i) { + this->_data[i] = this->_data[i] - other._data[i]; + } + return *this; +} + +template +MathVector& MathVector::operator*=(const T& scalar) { + for (size_t i = 0; i < this->_size; ++i) { + this->_data[i] = this->_data[i] * scalar; + } + return *this; +} + +template +auto MathVector::length() const { // + T sum = 0; + for (size_t i = 0; i < this->_size; i++) { + sum += this->_data[i] * this->_data[i]; + } + return std::sqrt(sum); +} + +#endif // LIB_MATHVECTOR_MATHVECTOR_H \ No newline at end of file diff --git a/lib_matrix/CMakeLists.txt b/lib_matrix/CMakeLists.txt new file mode 100644 index 00000000..6adf2649 --- /dev/null +++ b/lib_matrix/CMakeLists.txt @@ -0,0 +1,3 @@ +create_project_lib(Matrix) +add_depend(Matrix TVector lib_tvector) +add_depend(Matrix MathVector lib_mathvector) \ No newline at end of file diff --git a/lib_matrix/matrix.cpp b/lib_matrix/matrix.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_matrix/matrix.h b/lib_matrix/matrix.h new file mode 100644 index 00000000..60ec2b68 --- /dev/null +++ b/lib_matrix/matrix.h @@ -0,0 +1,190 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_MATRIX_MATRIX_H +#define LIB_MATRIX_MATRIX_H + +#include +#include +template +class MathVector; +#include "../lib_mathvector/MathVector.h" + + +template +class Matrix : public MathVector> { +protected: + size_t _rows; // + size_t _cols; // +public: + using MathVector>::MathVector; + Matrix() : MathVector>(), _rows(0), _cols(0) {} + Matrix(size_t value_rows, size_t value_cols) : MathVector>(value_rows), _rows(value_rows), _cols(value_cols) { + for (size_t i = 0; i < value_rows; ++i) { + this->_data[i] = MathVector(value_cols); + this->_states[i] = busy; + for (size_t j = 0; j < value_cols; ++j) { + this->_data[i][j] = T{}; + } + } + } + Matrix(const std::initializer_list> list) { + if (list.size() == 0) { + _rows = 0; + _cols = 0; + this->_size = 0; + this->_capacity = TVector::RESERVE_MEMORY; + this->_deleted = 0; + + this->_data = new MathVector[this->_capacity]; + this->_states = new State[this->_capacity]; + for (size_t i = 0; i < this->_capacity; ++i) { + this->_states[i] = empty; + } + return; + } + _rows = list.size(); + _cols = list.begin()->size(); + + this->_size = _rows; + this->_capacity = _rows + TVector::RESERVE_MEMORY; + this->_deleted = 0; + + this->_data = new MathVector[this->_capacity]; + this->_states = new State[this->_capacity]; + + size_t i = 0; + for (const auto& row : list) { + if (row.size() != _cols) { + throw std::invalid_argument("All rows must have the same size"); + } + this->_data[i] = row; + this->_states[i] = busy; + ++i; + } + for (; i < this->_capacity; ++i) { + this->_states[i] = empty; + } + } + Matrix(const Matrix& other) : MathVector>(other), _rows(other._rows), _cols(other._cols) {} + + size_t rows() const noexcept { return _rows; } + size_t cols() const noexcept { return _cols; } + T& at(size_t row, size_t col) { + if (row >= _rows) { + throw std::out_of_range("Row index out of range"); + } + if (col >= _cols) { + throw std::out_of_range("Col index out of range"); + } + return this->_data[row][col]; + } + const T& at(size_t row, size_t col) const { + if (row >= _rows) { + throw std::out_of_range("Row index out of range"); + } + if (col >= _cols) { + throw std::out_of_range("Col index out of range"); + } + return this->_data[row][col]; + } + MathVector& operator[](size_t row) { return this->_data[row]; } + const MathVector& operator[](size_t row) const { return this->_data[row]; } + + Matrix& operator=(const Matrix& other) { + if (this != &other) { + MathVector>::operator=(other); + _rows = other._rows; + _cols = other._cols; + } + return *this; + } + + Matrix& transpose() { + Matrix result(_cols, _rows); + for (size_t i = 0; i < _rows; ++i) { + for (size_t j = 0; j < _cols; ++j) { + result[j][i] = this->at(i, j); + } + } + (*this) = result; + return *this; + } + + Matrix operator+(const Matrix& other) const { + if (_rows != other._rows) { + throw std::invalid_argument("Rows should have same size for addition"); + } + if (_cols != other._cols) { + throw std::invalid_argument("Cols should have same size for addition"); + } + Matrix result(*this); + result.MathVector>::operator+=(other); + return result; + } + Matrix operator-(const Matrix& other) const { + if (_rows != other._rows) { + throw std::invalid_argument("Rows should have same size for subtraction"); + } + if (_cols != other._cols) { + throw std::invalid_argument("Cols should have same size for subtraction"); + } + Matrix result(*this); + result.MathVector>::operator-=(other); + return result; + } + Matrix operator*(const T scalar) const { + Matrix result(_rows, _cols); + for (size_t i = 0; i < _rows; ++i) { + for (size_t j = 0; j < _cols; ++j) { + result[i][j] = this->at(i, j) * scalar; + } + } + return result; + } + MathVector operator*(const MathVector& vec) const { + if (_cols != vec.size()) { + throw std::invalid_argument("Size of vector should have same size of cols for mult"); + } + MathVector result(_rows); + for (size_t i = 0; i < _rows; ++i) { + result[i] = this->_data[i] * vec; + } + return result; + } + Matrix operator*(const Matrix& other) const { + if (_cols != other.rows()) { + throw std::invalid_argument("Cols of the first matrix should be equal rows of the second matrix for mult"); + } + Matrix result(_rows, other.cols()); + Matrix transport_other = other; + transport_other.transpose(); + for (size_t i = 0; i < _rows; ++i) { + for (size_t j = 0; j < transport_other.rows(); ++j) { + result[i][j] = (*this)[i] * transport_other[j]; + } + } + return result; + } + void print() const { + for (size_t i = 0; i < _rows; ++i) { + std::cout << "[ "; + for (size_t j = 0; j < _cols; ++j) { + std::cout << this->at(i, j) << " "; + } + std::cout << "]" << std::endl;; + } + } + friend std::ostream& operator<< <>(std::ostream& out, const Matrix& matrix); +}; +template +std::ostream& operator<< <>(std::ostream& out, const Matrix& matrix) { + for (size_t i = 0; i < matrix.rows(); ++i) { + out << "[ "; + for (size_t j = 0; j < matrix.cols(); ++j) { + out << matrix.at(i, j) << " "; + } + out << "]\n"; + } + return out; +} +#endif // LIB_MATRIX_MATRIX_H \ No newline at end of file diff --git a/lib_node/CMakeLists.txt b/lib_node/CMakeLists.txt new file mode 100644 index 00000000..33f68928 --- /dev/null +++ b/lib_node/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Node) \ No newline at end of file diff --git a/lib_node/node.cpp b/lib_node/node.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_node/node.h b/lib_node/node.h new file mode 100644 index 00000000..86b9254b --- /dev/null +++ b/lib_node/node.h @@ -0,0 +1,24 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_NODE_NODE_H +#define LIB_NODE_NODE_H + +template +struct Node { + T value; + Node* next; + + explicit Node(const T& value_, Node* next_ = nullptr) : value(value_), next(next_) {} +}; + +template +struct NodeD { + T value; + NodeD* next; + NodeD* prev; + + explicit NodeD(const T& value_, NodeD* next_ = nullptr, NodeD* prev_ = nullptr) + : value(value_), next(next_), prev(prev_) {} +}; + +#endif \ No newline at end of file diff --git a/lib_point/CMakeLists.txt b/lib_point/CMakeLists.txt new file mode 100644 index 00000000..baf8c535 --- /dev/null +++ b/lib_point/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Point) \ No newline at end of file diff --git a/lib_point/point.cpp b/lib_point/point.cpp new file mode 100644 index 00000000..9e86d577 --- /dev/null +++ b/lib_point/point.cpp @@ -0,0 +1,40 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include +#include +#include "../lib_point/point.h" + +Point::Point() : _ox(0), _oy(0) {}; + +Point::Point(int value_ox, int value_oy) : _ox(value_ox), _oy(value_oy) {}; + +Point::Point(const Point& other) { + if (&other == NULL) { + throw std::logic_error("Error!!!"); + } + _ox = other._ox; + _oy = other._oy; +} + +int Point::get_ox() const { + return _ox; +} +int Point::get_oy() const { + return _oy; +} +void Point::set_ox(int ox) { + _ox = ox; +} +void Point::set_oy(int oy) { + _oy = oy; +} + +bool Point:: operator == (const Point& other) const noexcept { + return this->_ox == other._ox && this->_oy == other._oy; +} + +float Point::distance_to(const Point& other) const { + float res = std::sqrt(std::pow(_ox - other._ox, 2) + std::pow(_oy - other._oy, 2)); //std::pow - + return res; +} \ No newline at end of file diff --git a/lib_point/point.h b/lib_point/point.h new file mode 100644 index 00000000..8a59624b --- /dev/null +++ b/lib_point/point.h @@ -0,0 +1,25 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_POINT_POINT_H +#define LIB_POINT_POINT_H + +class Point { +protected: + int _ox; + int _oy; +public: + Point(); + Point(int, int); + Point(const Point&); + + int get_ox() const; + int get_oy() const; + void set_ox(int ox); + void set_oy(int oy); + + bool operator == (const Point&) const noexcept; + + float distance_to(const Point&) const; // +}; + +#endif // LIB_POINT_POINT_H \ No newline at end of file diff --git a/lib_point3d/CMakeLists.txt b/lib_point3d/CMakeLists.txt new file mode 100644 index 00000000..d87a61b5 --- /dev/null +++ b/lib_point3d/CMakeLists.txt @@ -0,0 +1,2 @@ +create_project_lib(Point3d) +add_depend(Point3d Point lib_point) \ No newline at end of file diff --git a/lib_point3d/point3d.cpp b/lib_point3d/point3d.cpp new file mode 100644 index 00000000..cda174d4 --- /dev/null +++ b/lib_point3d/point3d.cpp @@ -0,0 +1,39 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include +#include +//#include "../lib_point/point.h" +#include "../lib_point3d/point3d.h" + +Point3D::Point3D() : Point(), _oz(0) {} +Point3D::Point3D(int value_ox, int value_oy, int value_oz) { + _ox = value_ox; + _oy = value_oy; + _oz = value_oz; +} + +Point3D::Point3D(const Point3D& other) { + if (&other == NULL) { + throw std::logic_error("Error!!!"); + } + _ox = other._ox; + _oy = other._oy; + _oz = other._oz; +} + +int Point3D::get_oz() const { + return _oz; +} +void Point3D::set_oz(int oz) { + _oz = oz; +} + +bool Point3D::operator==(const Point3D& other) const noexcept { + return this->_ox == other._ox && this->_oy == other._oy && this->_oy == other._oy; +} + +float Point3D::distance_to(const Point3D& other) const { + float res = std::sqrt(std::pow(_ox - other._ox, 2) + std::pow(_oy - other._oy, 2) + std::pow(_oz - other._oz, 2)); + return res; +} \ No newline at end of file diff --git a/lib_point3d/point3d.h b/lib_point3d/point3d.h new file mode 100644 index 00000000..36759756 --- /dev/null +++ b/lib_point3d/point3d.h @@ -0,0 +1,24 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_POINT3D_POINT3D_H +#define LIB_POINT3D_POINT3D_H + +#include "../lib_point/point.h" + +class Point3D : public Point { + int _oz; + +public: + Point3D(); + Point3D(int, int, int); + Point3D(const Point3D&); + + int get_oz() const; + void set_oz(int); + + bool operator == (const Point3D&) const noexcept; + + float distance_to(const Point3D&) const; +}; + +#endif // LIB_POINT3D_POINT3D_H diff --git a/lib_queue/CMakeLists.txt b/lib_queue/CMakeLists.txt new file mode 100644 index 00000000..f0846b24 --- /dev/null +++ b/lib_queue/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Queue) \ No newline at end of file diff --git a/lib_queue/queue.cpp b/lib_queue/queue.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_queue/queue.h b/lib_queue/queue.h new file mode 100644 index 00000000..590a81c8 --- /dev/null +++ b/lib_queue/queue.h @@ -0,0 +1,124 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_QUEUE_QUEUE_H +#define LIB_QUEUE_QUEUE_H + +#include +#include + +template +class Queue { + T* _data; + size_t _size; + size_t _head; // + size_t _tail; // + size_t _count; +public: + static const size_t RESERVE_MEMORY = 20; + Queue() : _data(new T[RESERVE_MEMORY]), _size(RESERVE_MEMORY), _head(0), _tail(0), _count(0) {} + explicit Queue(size_t size) : _data(new T[size]), _size(size), _head(0), _tail(0), _count(0) {} + + Queue(const Queue& other) : _data(new T[other._size]), _size(other._size), _head(other._head), _tail(other._tail), _count(other._count) { + for (size_t i = 0; i < _size; ++i) { + _data[i] = other._data[i]; + } + } + ~Queue() noexcept { delete[] _data; } + + T& tail(); + const T& tail() const; + T& head(); + const T& head() const; + inline size_t capacity() const noexcept; + inline size_t count() const noexcept; + bool is_empty() const noexcept; + bool is_full() const noexcept; + void clear() noexcept; + + void push(T value); + void pop(); +}; + + +template +T& Queue::tail() { + if (is_empty()) { + throw std::underflow_error("Queue is empty (no tail element)"); + } + size_t last; + if (_tail == 0) { + last = _size - 1; + } + else { + last = _tail - 1; + } + return _data[last]; +} +template +const T& Queue::tail() const { + if (is_empty()) { + throw std::underflow_error("Queue is empty (no tail element)"); + } + size_t last; + if (_tail == 0) { + last = _size - 1; + } + else { + last = _tail - 1; + } + return _data[last]; +} +template +T& Queue::head() { + if (is_empty()) { + throw std::underflow_error("Queue is empty (no head element)"); + } + return _data[_head]; +} +template +const T& Queue::head() const { + if (is_empty()) { + throw std::underflow_error("Queue is empty (no head element)"); + } + return _data[_head]; +} +template +inline size_t Queue::capacity() const noexcept { + return _size; +} +template +inline size_t Queue::count() const noexcept { + return _count; +} +template +bool Queue::is_empty() const noexcept { + return _count == 0; +} +template +bool Queue::is_full() const noexcept { + return _count == _size; +} +template +void Queue::clear() noexcept { + _head = 0; + _tail = 0; + _count = 0; +} +template +void Queue::push(T value) { + if (is_full()) { + throw std::overflow_error("Queue overflow (can't push element)"); + } + _data[_tail] = value; + _tail = (_tail + 1) % _size; + ++_count; +} +template +void Queue::pop() { + if (is_empty()) { + throw std::underflow_error("Queue underflow (can't pop element)"); + } + _head = (_head + 1) % _size; + --_count; +} +#endif // LIB_QUEUE_QUEUE_H \ No newline at end of file diff --git a/lib_queue_list/CMakeLists.txt b/lib_queue_list/CMakeLists.txt new file mode 100644 index 00000000..c4511154 --- /dev/null +++ b/lib_queue_list/CMakeLists.txt @@ -0,0 +1,3 @@ +create_project_lib(QueueList) +add_depend(QueueList Node lib_node) +add_depend(QueueList List lib_list) \ No newline at end of file diff --git a/lib_queue_list/queue_list.cpp b/lib_queue_list/queue_list.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_queue_list/queue_list.h b/lib_queue_list/queue_list.h new file mode 100644 index 00000000..1f25dad2 --- /dev/null +++ b/lib_queue_list/queue_list.h @@ -0,0 +1,78 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_QUEUE_LIST_QUEUE_LIST_H +#define LIB_QUEUE_LIST_QUEUE_LIST_H + +#include +#include +#include "../lib_list/list.h" + +template +class QueueList { + List _list; + size_t _capacity; + size_t _count; +public: + static const size_t RESERVE_MEMORY = 20; + QueueList() : _list(), _capacity(RESERVE_MEMORY), _count(0) {} + explicit QueueList(size_t size) : _list(), _capacity(size), _count(0) {} + QueueList(const QueueList& other) : _list(other._list), _capacity(other._capacity), _count(other._count) {} + + inline T& tail() { + if (is_empty()) { + throw std::underflow_error("Queue is empty (no tail element)"); + } + return _list.tail()->value; + } + inline const T& tail() const { + if (is_empty()) { + throw std::underflow_error("Queue is empty (no tail element)"); + } + return _list.tail()->value; + } + inline T& head() { + if (is_empty()) { + throw std::underflow_error("Queue is empty (no head element)"); + } + return _list.head()->value; + } + inline const T& head() const { + if (is_empty()) { + throw std::underflow_error("Queue is empty (no head element)"); + } + return _list.head()->value; + } + inline size_t capacity() const noexcept { + return _capacity; + } + inline size_t count() const noexcept { + return _count; + } + bool is_empty() const noexcept { + return _count == 0; + } + bool is_full() const noexcept { + return _count >= _capacity; + } + void clear() { + _list.clear(); + _count = 0; + } + + void push(const T& value) { + if (is_full()) { + throw std::overflow_error("Queue is full (can't push element)"); + } + _list.push_back(value); + _count++; + } + void pop() { + if (is_empty()) { + throw std::underflow_error("Queue is empty (can't pop element)"); + } + _list.pop_front(); + _count--; + } +}; + +#endif // LIB_QUEUE_LIST_QUEUE_LIST_H \ No newline at end of file diff --git a/lib_sphere/CMakeLists.txt b/lib_sphere/CMakeLists.txt new file mode 100644 index 00000000..e2b72646 --- /dev/null +++ b/lib_sphere/CMakeLists.txt @@ -0,0 +1,4 @@ +create_project_lib(Sphere) +add_depend(Sphere Point lib_point) +add_depend(Sphere Point3d lib_point3d) +add_depend(Sphere Circle lib_circle) \ No newline at end of file diff --git a/lib_sphere/sphere.cpp b/lib_sphere/sphere.cpp new file mode 100644 index 00000000..74d45592 --- /dev/null +++ b/lib_sphere/sphere.cpp @@ -0,0 +1,35 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_sphere/sphere.h" + +Sphere::Sphere() : _center3D(Point3D()), _radius(1) {} +Sphere::Sphere(Point3D center, int value_radius) { + if (value_radius < 0) { + throw std::logic_error("Error!!! The radius can't be less than zero"); + } + _center3D = center; + _radius = value_radius; +} +Sphere::Sphere(const Sphere& other) { + if (&other == NULL) { + throw std::logic_error("Error!!!"); + } + _center3D = other._center3D; + _radius = other._radius; +} + +Point3D Sphere::get_center() const { + return _center3D; +} +void Sphere::set_center(Point3D center) { + _center3D = center; +} + +int Sphere::get_radius() const { + return _radius; +} + +void Sphere::set_radius(int rad) { + _radius = rad; +} \ No newline at end of file diff --git a/lib_sphere/sphere.h b/lib_sphere/sphere.h new file mode 100644 index 00000000..43d3e148 --- /dev/null +++ b/lib_sphere/sphere.h @@ -0,0 +1,26 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_SPHERE_SPHERE_H +#define LIB_SPHERE_SPHERE_H +#include + +#include "../lib_point/point.h" +#include "../lib_point3d/point3d.h" +#include "../lib_circle/circle.h" + +class Sphere { + Point3D _center3D; + int _radius; +public: + Sphere(); + Sphere(Point3D, int); + Sphere(const Sphere&); + + Point3D get_center() const; + void set_center(Point3D); + + int get_radius() const; + void set_radius(int); +}; + +#endif // LIB_SPHERE_SPHERE_H diff --git a/lib_stack/CMakeLists.txt b/lib_stack/CMakeLists.txt new file mode 100644 index 00000000..64a9f0cc --- /dev/null +++ b/lib_stack/CMakeLists.txt @@ -0,0 +1,2 @@ +create_project_lib(Stack) +add_depend(Stack TVector lib_tvector) \ No newline at end of file diff --git a/lib_stack/stack.cpp b/lib_stack/stack.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_stack/stack.h b/lib_stack/stack.h new file mode 100644 index 00000000..c2023736 --- /dev/null +++ b/lib_stack/stack.h @@ -0,0 +1,94 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_STACK_STACK_H +#define LIB_STACK_STACK_H + +#include +#include +#include "../lib_tvector/tvector.h" + + +template +class Stack { + TVector _data; + size_t _count; // + size_t _max_capacity; // +public: + static const size_t RESERVE_MEMORY = 20; + Stack() : _data(), _count(0), _max_capacity(RESERVE_MEMORY) { + _data.reserve(_max_capacity); + } + explicit Stack(size_t size) : _data(), _count(0), _max_capacity(size) { + _data.reserve(_max_capacity); + } + Stack(const Stack& other) : _data(other._data), _count(other._count), _max_capacity(other._max_capacity) {} + + inline size_t count() const noexcept; + inline size_t capacity() const noexcept; + bool is_full() const noexcept; + bool is_empty() const noexcept; + void clear() noexcept; + + void push(const T& value); + void pop(); + T& top(); + const T& top() const; +}; + + +template +inline size_t Stack::count() const noexcept { + return _count; +} +template +inline size_t Stack::capacity() const noexcept { + return _max_capacity; +} +template +bool Stack::is_full() const noexcept { + return _count >= _max_capacity; +} +template +bool Stack::is_empty() const noexcept { + return _count == 0; +} +template +void Stack::clear() noexcept { + _count = 0; + _data.clear(); +} +template +void Stack::push(const T& value) { + if (is_full()) { + throw std::overflow_error("Stack overflow: cannot push, because stack is full"); + } + if (_data.size() >= _data.capacity()) { + throw std::overflow_error("Stack overflow: stack is full"); + } + _data.push_back(value); + ++_count; +} +template +void Stack::pop() { + if (is_empty()) { + throw std::underflow_error("Stack is empty (can't pop from empty stack)"); + } + _data.pop_back(); + --_count; +} +template +T& Stack::top() { + if (is_empty()) { + throw std::underflow_error("Stack is empty (no top element)"); + } + return _data.back(); +} +template +const T& Stack::top() const { + if (is_empty()) { + throw std::underflow_error("Stack is empty (no top element"); + } + return _data.back(); +} + +#endif // LIB_STACK_STACK_H \ No newline at end of file diff --git a/lib_stack_list/CMakeLists.txt b/lib_stack_list/CMakeLists.txt new file mode 100644 index 00000000..2241158b --- /dev/null +++ b/lib_stack_list/CMakeLists.txt @@ -0,0 +1,3 @@ +create_project_lib(StackList) +add_depend(StackList Node lib_node) +add_depend(StackList List lib_list) \ No newline at end of file diff --git a/lib_stack_list/stack_list.cpp b/lib_stack_list/stack_list.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_stack_list/stack_list.h b/lib_stack_list/stack_list.h new file mode 100644 index 00000000..7bcbf928 --- /dev/null +++ b/lib_stack_list/stack_list.h @@ -0,0 +1,65 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_STACK_LIST_STACK_LIST_H +#define LIB_STACK_LIST_STACK_LIST_H + +#include +#include +#include "../lib_list/list.h" + +template +class StackList { + List _list; + size_t _count; + size_t _max_capacity; +public: + static const size_t RESERVE_MEMORY = 20; + StackList() : _list(), _count(0), _max_capacity(RESERVE_MEMORY) {} + explicit StackList(size_t size) : _list(), _count(0), _max_capacity(size) {} + StackList(const StackList& other) : _list(other._list), _count(other._count), _max_capacity(other._max_capacity) {} + + inline size_t count() const noexcept { + return _count; + } + inline size_t capacity() const noexcept { + return _max_capacity; + } + bool is_full() const noexcept { + return _count >= _max_capacity; + } + bool is_empty() const noexcept { + return _count == 0; + } + void clear() noexcept { + _list.clear(); + _count = 0; + } + + void push(const T& value) { + if (is_full()) { + throw std::overflow_error("Stack overflow: cannot push, because stack is full"); + } + _list.push_front(value); + _count++; + } + void pop() { + if (is_empty()) { + throw std::underflow_error("Stack is empty"); + } + _list.pop_front(); + _count--; + } + T& top() { + if (is_empty()) { + throw std::underflow_error("Stack is empty"); + } + return _list.head()->value; + } + const T& top() const { + if (is_empty()) { + throw std::underflow_error("Stack is empty"); + } + return _list.head()->value; + } +}; +#endif // LIB_STACK_LIST_STACK_LIST_H \ No newline at end of file diff --git a/lib_triangle_matrix/CMakeLists.txt b/lib_triangle_matrix/CMakeLists.txt new file mode 100644 index 00000000..59f4b257 --- /dev/null +++ b/lib_triangle_matrix/CMakeLists.txt @@ -0,0 +1,4 @@ +create_project_lib(TriangleMatrix) +add_depend(TriangleMatrix TVector lib_tvector) +add_depend(TriangleMatrix MathVector lib_mathvector) +add_depend(TriangleMatrix Matrix lib_matrix) \ No newline at end of file diff --git a/lib_triangle_matrix/triangle_matrix.cpp b/lib_triangle_matrix/triangle_matrix.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_triangle_matrix/triangle_matrix.h b/lib_triangle_matrix/triangle_matrix.h new file mode 100644 index 00000000..27eeefe8 --- /dev/null +++ b/lib_triangle_matrix/triangle_matrix.h @@ -0,0 +1,262 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef TRIANGLE_MATRIX_TRIANGLE_MATRIX_X +#define TRIANGLE_MATRIX_TRIANGLE_MATRIX_X + +#include +#include +template +class Matrix; +#include "../lib_matrix/matrix.h" + +template +class TriangleMatrix : public Matrix { + size_t _n; +public: + TriangleMatrix() : Matrix(), _n(0) {} + explicit TriangleMatrix(size_t n) : Matrix(n, n), _n(n) { + this->_rows = n; + this->_cols = n; + this->_size = n; + this->_capacity = n + TVector::RESERVE_MEMORY; + this->_deleted = 0; + this->_data = new MathVector[this->_capacity]; + this->_states = new State[this->_capacity]; + + for (size_t i = 0; i < n; i++) { + this->_data[i] = MathVector(n - i); + this->_states[i] = busy; + for (size_t j = 0; j < n - i; ++j) { + this->_data[i][j] = T{}; + } + } + for (size_t i = n; i < this->_capacity; i++) { + this->_states[i] = empty; + } + + } + TriangleMatrix(const TriangleMatrix& other) : Matrix(other), _n(other._n) {} + ~TriangleMatrix() = default; + size_t n() const noexcept { return _n; } + T& at(size_t i, size_t j) { + if (i >= _n || j >= _n) { + throw std::out_of_range("Index out of range"); + } + if (i > j) { + static T zero{}; + return zero; + } + return this->_data[i][j - i]; + } + const T& at(size_t i, size_t j) const { + if (i >= _n || j >= _n) { + throw std::out_of_range("Index out of range"); + } + if (i > j) { + static const T zero{}; + return zero; + } + return this->_data[i][j - i]; + } + MathVector& operator[](size_t i) { + if (i >= _n) { + throw std::out_of_range("Index out of range"); + } + return this->_data[i]; + } + const MathVector& operator[](size_t row) const { + if (i >= _n) { + throw std::out_of_range("Index out of range"); + } + return this->_data[i]; + } + + TriangleMatrix& operator=(const TriangleMatrix& other) noexcept { + if (this != &other) { + Matrix::operator=(other); + _n = other._n; + } + return *this; + } + + TriangleMatrix operator+(const TriangleMatrix& other) const { + if (_n != other._n) { + throw std::invalid_argument("Triangle Matrix should have the same size for addition"); + } + TriangleMatrix result(*this); + result.Matrix::operator+=(other); + /*for (size_t i = 0; i < _n; ++i) { + for (size_t j = i; j < _n; ++j) { + result.at(i, j) = this->at(i, j) + other.at(i, j); + } + }*/ + return result; + } + TriangleMatrix operator-(const TriangleMatrix& other) const { + if (_n != other._n) { + throw std::invalid_argument("Triangle Matrix should have the same size for subtraction"); + } + TriangleMatrix result(*this); + result.Matrix::operator-=(other); + /* TriangleMatrix result(_n); + for (size_t i = 0; i < _n; ++i) { + for (size_t j = i; j < _n; ++j) { + result.at(i, j) = this->at(i, j) - other.at(i, j); + } + }*/ + return result; + } + TriangleMatrix operator*(const T scalar) const { + TriangleMatrix result(_n); + for (size_t i = 0; i < _n; ++i) { + for (size_t j = i; j < _n; ++j) { + result.at(i, j) = this->at(i, j) * scalar; + } + } + return result; + } + MathVector operator*(const MathVector& vec) const { + if (_n != vec.size()) { + throw std::invalid_argument("Size of vector should have same size of cols for mult"); + } + MathVector result(_n); + for (size_t i = 0; i < _n; ++i) { + T sum{}; + for (size_t j = i; j < _n; ++j) { + sum += this->at(i, j) * vec[j]; + } + result[i] = sum; + } + /*for (size_t i = 0; i < _n; ++i) { + for (size_t j = i; j < _n; ++j) { + T sum{}; + for (size_t k = i; k <= j; ++k) { + sum += this->at(i, k) * vec.at(k); + } + result[i] = sum; + } + }*/ + return result; + } + TriangleMatrix operator*(const TriangleMatrix& other) const { + if (_n != other._n) { + throw std::invalid_argument("Triangle Matrix should have the same size for mult"); + } + TriangleMatrix result(_n); + for (size_t i = 0; i < _n; ++i) { + for (size_t j = i; j < _n; ++j) { + T sum{}; + for (size_t k = i; k <= j; ++k) { + sum += this->at(i, k) * other.at(k, j); + } + result.at(i, j) = sum; + } + } + return result; + } + + friend std::ostream& operator<< <>(std::ostream& out, const TriangleMatrix& matrix); +}; +template +std::ostream& operator<< <>(std::ostream& out, const TriangleMatrix& matrix) { + for (size_t i = 0; i < matrix.n(); ++i) { + out << "[ "; + for (size_t j = 0; j < matrix.n(); ++j) { + out << matrix.at(i, j) << " "; + } + out << "]\n"; + } + return out; +} + +template +Matrix operator+(const Matrix& matrix, const TriangleMatrix& triangle_matrix) { + if (matrix.rows() != triangle_matrix.n() || matrix.cols() != triangle_matrix.n()) { + throw std::invalid_argument("Matrixes should have the same size for addition"); + } + Matrix result(matrix.rows(), matrix.cols()); + for (size_t i = 0; i < matrix.rows(); ++i) { + for (size_t j = 0; j < matrix.cols(); ++j) { + result[i][j] = matrix.at(i, j) + triangle_matrix.at(i, j); + } + } + return result; +} +template +Matrix operator+(const TriangleMatrix& triangle_matrix, const Matrix& matrix) { + if (matrix.rows() != triangle_matrix.n() || matrix.cols() != triangle_matrix.n()) { + throw std::invalid_argument("Matrixes should have the same size for addition"); + } + /*Matrix result(matrix.rows(), matrix.cols()); + for (size_t i = 0; i < matrix.rows(); ++i) { + for (size_t j = 0; j < matrix.cols(); ++j) { + result[i][j] = matrix.at(i, j) + triangle_matrix.at(i, j); + } + }*/ + return matrix + triangle_matrix; +} +template +Matrix operator-(const Matrix& matrix, const TriangleMatrix& triangle_matrix) { + if (matrix.rows() != triangle_matrix.n() || matrix.cols() != triangle_matrix.n()) { + throw std::invalid_argument("Matrixes should have the same size for subtraction"); + } + Matrix result(matrix.rows(), matrix.cols()); + for (size_t i = 0; i < matrix.rows(); ++i) { + for (size_t j = 0; j < matrix.cols(); ++j) { + result[i][j] = matrix.at(i, j) - triangle_matrix.at(i, j); + } + } + return result; +} +template +Matrix operator-(const TriangleMatrix& triangle_matrix, const Matrix& matrix) { + if (matrix.rows() != triangle_matrix.n() || matrix.cols() != triangle_matrix.n()) { + throw std::invalid_argument("Matrixes should have the same size for subtraction"); + } + Matrix result(matrix.rows(), matrix.cols()); + for (size_t i = 0; i < matrix.rows(); ++i) { + for (size_t j = 0; j < matrix.cols(); ++j) { + result[i][j] = triangle_matrix.at(i, j) - matrix.at(i, j); + } + } + return result; +} +template +Matrix operator*(const Matrix& matrix, const TriangleMatrix& triangle_matrix) { + if (matrix.cols() != triangle_matrix.n()) { + throw std::invalid_argument("Matrix should have the same size for mult"); + } + Matrix result(matrix.rows(), matrix.cols()); + TriangleMatrix transpose_triangle_matrix = triangle_matrix; + transpose_triangle_matrix.transpose(); + for (size_t i = 0; i < triangle_matrix.n(); ++i) { + for (size_t j = 0; j < triangle_matrix.n(); ++j) { + T sum{}; + for (size_t k = 0; k < triangle_matrix.n(); ++k) { + sum += matrix.at(i, k) * triangle_matrix.at(k, j); + } + result[i][j] = sum; + } + } + return result; +} +template +Matrix operator*(const TriangleMatrix& triangle_matrix, const Matrix& matrix) { + if (matrix.cols() != triangle_matrix.n()) { + throw std::invalid_argument("Matrix should have the same size for mult"); + } + Matrix result(matrix.rows(), matrix.cols()); + TriangleMatrix transpose_triangle_matrix = triangle_matrix; + transpose_triangle_matrix.transpose(); + for (size_t i = 0; i < triangle_matrix.n(); ++i) { + for (size_t j = 0; j < triangle_matrix.n(); ++j) { + T sum{}; + for (size_t k = 0; k < triangle_matrix.n(); ++k) { + sum += triangle_matrix.at(i, k) * matrix.at(k, j); + } + result[i][j] = sum; + } + } + return result; +} +#endif // TRIANGLE_MATRIX_TRIANGLE_MATRIX_X \ No newline at end of file diff --git a/lib_tvector/CMakeLists.txt b/lib_tvector/CMakeLists.txt new file mode 100644 index 00000000..a46980e1 --- /dev/null +++ b/lib_tvector/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(TVector) \ No newline at end of file diff --git a/lib_tvector/tvector.cpp b/lib_tvector/tvector.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_tvector/tvector.h b/lib_tvector/tvector.h new file mode 100644 index 00000000..286894f6 --- /dev/null +++ b/lib_tvector/tvector.h @@ -0,0 +1,793 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#ifndef LIB_TVECTOR_TVECTOR_H +#define LIB_TVECTOR_TVECTOR_H + +#include +#include // rand() +#include // std::out_of_range, std::invalid_argument + +enum State { empty, busy, deleted }; +template +class TVector { +protected: + T* _data; + State* _states; + size_t _size; + size_t _capacity; + size_t _deleted; + +public: + static const size_t RESERVE_MEMORY = 15; + static const size_t MAX_PERCENT_DELETED = 15; + + TVector() : _data(nullptr), _states(nullptr), _size(0), _capacity(0), _deleted(0) {} + TVector(size_t size) { + _size = size; + _capacity = size + RESERVE_MEMORY; + _deleted = 0; + _data = new T[_capacity]; + _states = new State[_capacity]; + for (size_t i = 0; i < _capacity; ++i) { + _states[i] = i < _size ? State::busy : State::empty; + } + } + TVector(T* data, size_t size) { + _size = size; + _capacity = size + RESERVE_MEMORY; + _deleted = 0; + if (size > 0 && data == nullptr) { + throw std::invalid_argument("You sent a nullptr but with a size greater than 0"); + } + _data = new T[_capacity]; + try { + _states = new State[_capacity]; + } + catch (const std::bad_alloc&) { + delete[] _data; + throw; + } + for (size_t i = 0; i < _capacity; ++i) { + if (i < size) { + _data[i] = data[i]; + _states[i] = State::busy; + } + else { + _states[i] = State::empty; + } + } + } + TVector(const TVector& other) { + _size = other._size; + _capacity = other._capacity; + _deleted = other._deleted; + _data = nullptr; + _states = nullptr; + try { + _data = new T[_capacity]; + } + catch (const std::bad_alloc&) { //Ловит ошибку нехватки памяти + throw; + std::cout << std::endl; + } + try { + _states = new State[_capacity]; + } + catch (const std::bad_alloc&) { + delete[] _data; + throw; + std::cout << std::endl; + } + for (size_t i = 0; i < other._size; ++i) { + _data[i] = other._data[i]; + _states[i] = other._states[i]; + } + for (size_t i = other._size; i < other._capacity; ++i) { + _states[i] = State::empty; + } + } + ~TVector() noexcept { + delete[] _data; + delete[] _states; + } + class Iterator { + T* _ptr; + State* _state_ptr; + size_t _index; + size_t _size; + public: + Iterator(T* ptr, State* state_ptr, size_t index, size_t size) + : _ptr(ptr), _state_ptr(state_ptr), _index(index), _size(size) { + } + + Iterator& operator=(const Iterator& other) { + if (this != &other) { + _ptr = other._ptr; + _state_ptr = other._state_ptr; + _index = other._index; + _size = other._size; + } + return *this; + } + + Iterator& operator++() { // ++it + do { + ++_index; + } while (_index < _size && _state_ptr[_index] != State::busy); + return *this; + } + + Iterator operator++(int) { // it++ + Iterator temp = *this; + ++(*this); + return temp; + } + + Iterator& operator--() { // --it + size_t original_index = _index; + while (_index > 0) { + --_index; + if (_state_ptr[_index] == State::busy) { + return *this; + } + } + if (original_index == _size) { + _index = _size; + } + else { + _index = original_index; + } + return *this; + } + + Iterator operator--(int) { // it-- + Iterator temp = *this; + --(*this); + return temp; + } + + bool operator==(const Iterator& other) const { + return _ptr == other._ptr && _index == other._index; + } + + bool operator!=(const Iterator& other) const { + return !(*this == other); + } + + T& operator*() { + return _ptr[_index]; + } + }; + + Iterator begin() { + size_t first_busy = 0; + while (first_busy < _size && _states[first_busy] != State::busy) { + ++first_busy; + } + return Iterator(_data, _states, first_busy, _size); + } + Iterator end() { + return Iterator(_data, _states, _size, _size); + } + + inline T& operator[](size_t index); + inline const T& operator[](size_t index) const; + inline T& at(size_t index); + inline const T& at(size_t index) const; + inline const T* data() const noexcept; + inline const T& data(size_t i) const; + inline const State* states() const noexcept; + inline const State state(size_t i) const; + inline const size_t size() const noexcept; + inline void size(size_t new_size) noexcept; + inline const size_t capacity() const noexcept; + inline void capacity(size_t new_capacity) noexcept; + /* + inline T* begin() noexcept; // возвращала _data указатель на начало + inline T* end() noexceptж + */ + inline const size_t deleted() const noexcept; + + inline T& front(); //Доступ к первому элементу, который не deleted и не empty + inline T& back(); //Доступ к последнему элементу, который не deleted и не empty + inline const T& back() const; //Доступ к последнему элементу, который не deleted и не empty + + inline bool is_empty() const noexcept; + + void push_front(const T& value) noexcept; + void push_back(const T& value) noexcept; + void insert(size_t index, const T& value); + + void pop_front(); + void pop_back(); + void erase(size_t index); + + void emplace(size_t index, T&& value); + void emplace(size_t index, const T& value); + + TVector& assign(const TVector& other); + TVector& operator=(const TVector& other); + + void clear() noexcept; + + bool operator == (const TVector& other) const noexcept; + bool operator != (const TVector& other) const noexcept; + + void reserve(size_t new_capacity); // увеличивает _capacity + + void resize(size_t new_size); + void resize(size_t new_size, const T& value); + + void shrink_to_fit(); // уменьшение размера, удаляя неиспользуемую память + + void print(); + + template + friend std::ostream& operator<<(std::ostream& out, const TVector& vec); + + template + friend void swap(U& a, U& b); + + template + friend void shuffle(TVector& vec); + + template + friend void quick_sort(TVector& vec); + + template + friend size_t find_first(const TVector& vec, const U& value); + + template + friend size_t find_last(const TVector& vec, const U& value); + + template + friend size_t* find_all(const TVector& vec, const U& value); + + template + friend void quick_sort_realisation(TVector& vec, int left, int right); + +private: + size_t check_index(size_t index) const; + inline bool is_full() const noexcept; +}; + +template +inline T& TVector::operator[](size_t index) { + return _data[index]; +} + +template +inline const T& TVector::operator[](size_t index) const { + return _data[index]; +} + +template +inline T& TVector::at(size_t index) { + size_t real_index = check_index(index); + return _data[real_index]; +} + +template +inline const T& TVector::at(size_t index) const { + size_t real_index = check_index(index); + return _data[real_index]; +} + +template +inline const T* TVector::data() const noexcept { + return _data; +} + +template +inline const T& TVector::data(size_t i) const { + size_t real_index = check_index(i); + return _data[real_index]; +} + +template +inline const State* TVector::states() const noexcept { + return _states; +} + +template +inline const State TVector::state(size_t i) const { + return _states[i]; +} + +template +inline const size_t TVector::size() const noexcept { + return _size; +} + +template +inline void TVector::size(size_t new_size) noexcept { + resize(new_size); +} + +template +inline const size_t TVector::capacity() const noexcept { + return _capacity; +} + +template +inline void TVector::capacity(size_t new_capacity) noexcept { + reserve(new_capacity); +} + +/* +template +inline T* TVector::begin() noexcept { // возвращает _data указатель на начало + return _data; +} + +template +inline T* TVector::end() noexcept { + return _data + _size; +} +*/ + +template +inline const size_t TVector::deleted() const noexcept { + return _deleted; +} + +template +inline T& TVector::front() { //Доступ к первому элементу, который не deleted и не empty + for (size_t i = 0; i < _size; ++i) + if (_states[i] == busy) + return _data[i]; + throw std::out_of_range("No busy elements in vector"); +} + +template +inline T& TVector::back() { //Доступ к последнему элементу, который не deleted и не empty + for (size_t i = _size; i-- > 0; ) + if (_states[i] == busy) + return _data[i]; + throw std::out_of_range("No busy elements in vector"); +} + +template +inline const T& TVector::back() const { //Доступ к последнему элементу, который не deleted и не empty + for (size_t i = _size; i-- > 0; ) + if (_states[i] == busy) + return _data[i]; + throw std::out_of_range("No busy elements in vector"); +} + +template +inline bool TVector::is_empty() const noexcept { return (_size - _deleted) == 0; } + +template +void TVector::push_front(const T& value) noexcept { + if (is_full()) { + reserve(_capacity + RESERVE_MEMORY); + } + + for (size_t i = _size; i > 0; --i) { // Сдвигаем всё вправо + _data[i] = _data[i - 1]; + _states[i] = _states[i - 1]; + } + _data[0] = value; + _states[0] = busy; + ++_size; +} + +template +void TVector::push_back(const T& value) noexcept { + if (is_full()) { + reserve(_capacity + RESERVE_MEMORY); + } + _data[_size] = value; + _states[_size] = busy; + ++_size; +} + +template +void TVector::insert(size_t index, const T& value) { + if (index > _size) { + throw std::out_of_range("Insert index out of range"); + } + if (is_full()) { + reserve(_capacity + RESERVE_MEMORY); + } + size_t real_index = check_index(index); + for (size_t i = _size; i > real_index; --i) { // Сдвигаем вправо + _data[i] = _data[i - 1]; + _states[i] = _states[i - 1]; + } + _data[real_index] = value; + _states[real_index] = busy; + ++_size; +} + +template +void TVector::pop_front() { + if (_data != nullptr && _states != nullptr) { + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == State::busy) { + _states[i] = State::deleted; + ++_deleted; + if (_size > 0 && ((_deleted * 100 / _size) > MAX_PERCENT_DELETED)) { + shrink_to_fit(); + } + return; + } + } + } + throw std::underflow_error("Vector is empty"); +} + +template +void TVector::pop_back() { + if (_data != nullptr && _states != nullptr) { + for (size_t i = _size - 1; ; --i) { + if (_states[i] == State::deleted) { + _states[i] = State::empty; + --_size; + --_deleted; + } + if (_states[i] == State::busy) { + _states[i] = State::empty; + --_size; + return; + } + if (i <= 0) break; // иначе уйдём в переполнение + } + } + throw std::underflow_error("Vector is empty"); +} + +template +void TVector::erase(size_t index) { + size_t real_index = check_index(index); + _states[real_index] = State::deleted; + ++_deleted; + if (_size > 0 && ((_deleted * 100 / _size) > MAX_PERCENT_DELETED)) { + shrink_to_fit(); + } +} + +template +void TVector::emplace(size_t index, T&& value) { + size_t real_index = check_index(index); + _data[real_index] = value; + _states[real_index] = State::busy; +} + +template +void TVector::emplace(size_t index, const T& value) { + size_t real_index = check_index(index); + _data[real_index] = value; + _states[real_index] = State::busy; +} + +template +TVector& TVector::assign(const TVector& other) { + if (this != &other) { + delete[] _data; + delete[] _states; + + _size = other._size; + _capacity = other._capacity; + _deleted = other._deleted; + + _data = new T[_capacity]; + _states = new State[_capacity]; + for (size_t i = 0; i < _size; ++i) { + _data[i] = other._data[i]; + _states[i] = other._states[i]; + } + for (size_t i = _size; i < _capacity; ++i) + _states[i] = State::empty; + } + return *this; +} + +template +TVector& TVector::operator=(const TVector& other) { + if (this != &other) { //проверка на самоприсваивание + delete[] _data; + delete[] _states; + + _size = other._size; + _capacity = other._capacity; + _deleted = other._deleted; + + _data = new T[_capacity]; + _states = new State[_capacity]; + + for (size_t i = 0; i < _size; ++i) { + _data[i] = other._data[i]; + _states[i] = other._states[i]; + } + for (size_t i = _size; i < _capacity; ++i) + _states[i] = State::empty; + } + return *this; +} + +template +void TVector::clear() noexcept { + for (size_t i = 0; i < _size; ++i) { + _states[i] = State::empty; + } + _size = 0; + _deleted = 0; +} + +template +bool TVector::operator == (const TVector& other) const noexcept { + if (_size != other._size) { + return false; + } + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == busy && _data[i] != other._data[i]) { + return false; + } + } + return true; +} + +template +bool TVector::operator != (const TVector& other) const noexcept { + if (*this == other) { + return false; + } + if (_size != other._size) { + return true; + } + for (size_t i = 0; i < _size; ++i) { + if (_states[i] != other._states[i]) { + return true; + } + if (_states[i] == busy && _data[i] != other._data[i]) { + return true; + } + } + return false; +} + +template +void TVector::reserve(size_t new_capacity) { // увеличивает _capacity + if (new_capacity <= _capacity) return; + + T* new_data = new T[new_capacity]; + State* new_states = new State[new_capacity]; + + for (size_t i = 0; i < _size; ++i) { // Копируем существующие элементы + new_data[i] = _data[i]; + new_states[i] = _states[i]; + } + + for (size_t i = _size; i < new_capacity; ++i) { // Помечаем оставшиеся ячейки как пустые + new_states[i] = State::empty; + } + + delete[] _data; + delete[] _states; + _data = new_data; + _states = new_states; + _capacity = new_capacity; +} + +template +void TVector::resize(size_t new_size) { + if (new_size < _size) { + for (size_t i = new_size; i < _size; ++i) { + if (_states[i] == State::deleted) + --_deleted; + _states[i] = State::empty; + _data[i].~T(); + } + _size = new_size; + return; + } + + if (new_size > _capacity) { + reserve(new_size + RESERVE_MEMORY); + } + + for (size_t i = _size; i < new_size; ++i) { + new (_data + i) T(); // размещает результат в уже выделенной памяти по адресу _data + i + _states[i] = busy; + } + _size = new_size; +} + +template +void TVector::resize(size_t new_size, const T& value) { + if (new_size == _size) { return; } + if (new_size < _size) { + for (size_t i = new_size; i < _size; ++i) { + if (_states[i] == State::deleted) + --_deleted; + _states[i] = empty; + _data[i].~T(); + } + _size = new_size; + return; + } + if (new_size > _capacity) { + reserve(new_size + RESERVE_MEMORY); + } + for (size_t i = _size; i < new_size; ++i) { + new (_data + i) T(value); // размещает результат в уже выделенной памяти по адресу _data + i + _states[i] = busy; + } + _size = new_size; +} + +template +void TVector::shrink_to_fit() { // уменьшение размера, удаляя неиспользуемую память + size_t busy_count = 0; + for (size_t i = 0; i < _size; ++i) { // Считаем busy элементы + if (_states[i] == busy) + ++busy_count; + } + if (busy_count == _size && _capacity == _size) { return; } + + size_t new_capacity = busy_count + RESERVE_MEMORY; + T* new_data = new T[new_capacity]; + State* new_states = new State[new_capacity]; + + size_t new_index = 0; + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == busy) { + new_data[new_index] = _data[i]; + new_states[new_index] = busy; + ++new_index; + } + } + + for (size_t i = new_index; i < new_capacity; ++i) { + new_states[i] = empty; + } + + delete[] _data; + delete[] _states; + + _data = new_data; + _states = new_states; + _capacity = new_capacity; + _size = busy_count; + _deleted = 0; +} + +template +void TVector::print() { + std::cout << "[ "; + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == State::busy) { + std::cout << _data[i] << " "; + } + } + std::cout << "]"; +} + +template +size_t TVector::check_index(size_t index) const { + if (index >= _size) { + throw std::out_of_range("Index out of bounds: index >= size"); + } + size_t count = 0; + for (size_t i = 0; i < _size; i++) { + if (_states[i] == State::busy) { + if (count == index) { + return i; + } + count++; + } + } + throw std::out_of_range("There no element with this index"); +} + +template +inline bool TVector::is_full() const noexcept { // функция проверки на заполненость + return _size >= _capacity; +} + + + +template +void swap(T& a, T& b) { + T temp = a; + a = b; + b = temp; +} + +template +void shuffle(TVector& vec) { + if (vec._size <= 1) { + return; + } + for (size_t i = vec._size - 1; i > 0; --i) { + if (vec._states[i] != busy) { + continue; + } + size_t j = std::rand() % (i + 1); + while (vec._states[j] != busy) { + j = std::rand() % (i + 1); + } + swap(vec._data[i], vec._data[j]); + } +} + +template +void quick_sort_realisation(TVector& vec, int left, int right) { + if (left > right) { + return; + } + T p = vec[(left + right) / 2]; + int i = left; + int j = right; + while (i <= j) { + while (vec[i] < p) i++; + while (vec[j] > p) j--; + if (i <= j) { + swap(vec._data[i], vec._data[j]); + swap(vec._states[i], vec._states[j]); + i++; + j--; + } + } + quick_sort_realisation(vec, left, j); + quick_sort_realisation(vec, i, right); +} +template +void quick_sort(TVector& vec) { + if (vec.size() > 1) + quick_sort_realisation(vec, 0, vec.size() - 1); +} + +template +size_t find_first(const TVector& vec, const T& value) { + for (size_t i = 0; i < vec.size(); ++i) + if (vec.state(i) == State::busy && vec.data(i) == value) { + return i; + } + throw std::logic_error("Element not found"); +} +template +size_t find_last(const TVector& vec, const T& value) { + for (size_t i = vec._size; i-- > 0;) + if (vec.state(i) == State::busy && vec.data(i) == value) { + return i; + } + throw std::logic_error("Element not found"); +} +template +size_t* find_all(const TVector& vec, const T& value) { + size_t result_size = 0; + for (size_t i = 0; i < vec.size(); ++i) { // Считаем количество подходящих элементов + if (vec.state(i) == State::busy && vec.data(i) == value) { + ++result_size; + } + } + + if (result_size == 0) { + return nullptr; + } + size_t* indices = new size_t[result_size]; + size_t j = 0; + for (size_t i = 0; i < vec.size(); ++i) { + if (vec.state(i) == State::busy && vec.data(i) == value) { + indices[j++] = i; + } + } + return indices; +} + +template +std::ostream& operator<<(std::ostream& out, const TVector& vec) { + out << "[ "; + for (size_t i = 0; i < vec._size; ++i) { + if (vec._states[i] == State::busy) { + out << vec._data[i] << " "; + } + } + out << "]"; + return out; +} + +#endif // LIB_TVECTOR \ No newline at end of file diff --git a/main/main.cpp b/main/main.cpp index 217f8971..f9f59130 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,6 +1,24 @@ -// Copyright 2024 Marina Usova +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include +#include +#include + +#include "../lib_algorithms/algorithms.h" + +// : +//#define EASY_EXAMPLE + +// /: +//#define POSITION_OF_TWO_CIRCLE +//#define POSITION_OF_TWO_SPHERE +// +//#define USER_INPUT + +// +#define WORKING_WITH_MATRIX -#define EASY_EXAMPLE #ifdef EASY_EXAMPLE #include @@ -35,3 +53,160 @@ int main() { } #endif // EASY_EXAMPLE + +#ifdef POSITION_OF_TWO_CIRCLE +#include "../lib_circle/circle.h" + +int main() { + std::cout << "POSITION OF TWO CIRCLES" << std::endl; + std::cout << "=======================================" << std::endl; + +#ifdef USER_INPUT + int value_dot1_ox, value_dot1_oy, value_radius1, value_dot2_ox, value_dot2_oy, value_radius2; + std::cout << "Input center of the first circle: " << std::endl << "Input ox "; + std::cin >> value_dot1_ox; + std::cout << "Input oy "; + std::cin >> value_dot1_oy; + std::cout << "Input radius of the first circle: "; + std::cin >> value_radius1; + Circle circle1(Point(value_dot1_ox, value_dot1_oy), value_radius1); + std::cout << "Input center of the second circle: " << std::endl << "Input ox "; + std::cin >> value_dot2_ox; + std::cout << "Input oy "; + std::cin >> value_dot2_oy; + std::cout << "Input radius of the second circle: "; + std::cin >> value_radius2; + Circle circle2(Point(value_dot2_ox, value_dot2_oy), value_radius2); + Location result = check_position(circle1, circle2); + set_color(12, 0); + std::cout << "RESULT:"; + set_color(7, 0); + print_result_position(" ", result); +#else + // 1 + Circle circle1(Point(0, 0), 5); + Circle circle2(Point(0, 0), 5); + Location result1 = check_position(circle1, circle2); + print_result_position("1 Coincide circles (same center, same radius)", result1); + + // 2 + Circle circle3(Point(0, 0), 10); + Circle circle4(Point(1, 1), 2); + Location result2 = check_position(circle3, circle4); + print_result_position("2 One circle inside another", result2); + + // 3 + Circle circle5(Point(0, 0), 5); + Circle circle6(Point(3, 0), 2); + Location result3 = check_position(circle5, circle6); + print_result_position("3 Internal tangent", result3); + + // 4 + Circle circle7(Point(0, 0), 3); + Circle circle8(Point(4, 0), 3); + Location result4 = check_position(circle7, circle8); + print_result_position("4 Intersecting circles", result4); + + // 5 + Circle circle9(Point(0, 0), 3); + Circle circle10(Point(8, 0), 5); + Location result5 = check_position(circle9, circle10); + print_result_position("5 External tangent", result5); + + // 6 + Circle circle11(Point(0, 0), 2); + Circle circle12(Point(10, 0), 3); + Location result6 = check_position(circle11, circle12); + print_result_position("6 Non-intersecting circles", result6); +#endif // USER_INPUT + std::cout << "=======================================" << std::endl; + return 0; +} +#endif // POSITION_OF_TWO_CIRCLE + +#ifdef POSITION_OF_TWO_SPHERE +#include "../lib_sphere/sphere.h" + + +int main() { + std::cout << "POSITION OF TWO SPHERE" << std::endl; + std::cout << "=======================================" << std::endl; + +#ifdef USER_INPUT + int value_dot1_ox, value_dot1_oy, value_dot1_oz, value_radius1, value_dot2_ox, value_dot2_oy, value_dot2_oz, value_radius2; + std::cout << "Input center of the first sphere: " << std::endl << "Input ox "; + std::cin >> value_dot1_ox; + std::cout << "Input oy "; + std::cin >> value_dot1_oy; + std::cout << "Input oz "; + std::cin >> value_dot1_oz; + std::cout << "Input radius of the first sphere: "; + std::cin >> value_radius1; + Sphere sphere1(Point3D(value_dot1_ox, value_dot1_oy, value_dot1_oz), value_radius1); + std::cout << "Input center of the second sphere: " << std::endl << "Input ox "; + std::cin >> value_dot2_ox; + std::cout << "Input oy "; + std::cin >> value_dot2_oy; + std::cout << "Input oz "; + std::cin >> value_dot2_oz; + std::cout << "Input radius of the second sphere: "; + std::cin >> value_radius2; + Sphere sphere2(Point3D(value_dot2_ox, value_dot2_oy, value_dot2_oz), value_radius2); + Location result = check_position(sphere1, sphere2); + set_color(12, 0); + std::cout << "RESULT:"; + set_color(7, 0); + print_result_position(" ", result); + std::cout << "=======================================" << std::endl; +#else + // 1 caths + Sphere sphere1(Point3D(0, 0, 0), 5); + Sphere sphere2(Point3D(0, 0, 0), 5); + Location result7 = check_position(sphere1, sphere2); + print_result_position("1 Coincide spheres (same center, same radius)", result7); + + // 2 + Sphere sphere3(Point3D(0, 0, 0), 8); + Sphere sphere4(Point3D(1, 1, 1), 2); + Location result8 = check_position(sphere3, sphere4); + print_result_position("2 One sphere inside another", result8); + + // 3 + Sphere sphere5(Point3D(0, 0, 0), 5); + Sphere sphere6(Point3D(3, 0, 0), 2); + Location result9 = check_position(sphere5, sphere6); + print_result_position("3 Internal tangent spheres", result9); + + // 4 + Sphere sphere7(Point3D(0, 0, 0), 4); + Sphere sphere8(Point3D(3, 0, 0), 3); + Location result10 = check_position(sphere7, sphere8); + print_result_position("4 Intersecting spheres", result10); + + // 5 + Sphere sphere9(Point3D(0, 0, 0), 3); + Sphere sphere10(Point3D(0, 8, 0), 5); + Location result11 = check_position(sphere9, sphere10); + print_result_position("5 External tangent spheres", result11); + + // 6 + Sphere sphere11(Point3D(0, 0, 0), 2); + Sphere sphere12(Point3D(0, 0, 15), 3); + Location result12 = check_position(sphere11, sphere12); + print_result_position("6 Non-intersecting spheres", result12); + + std::cout << "=======================================" << std::endl; +#endif // USER_INPUT + + return 0; +} + +#endif // POSITION_OF_TWO_SPHERE + +#ifdef WORKING_WITH_MATRIX +int main() { + matrix_application(); + return 0; +} +#endif // WORKING_WITH_MATRIX + diff --git a/tests/test_algorithms.cpp b/tests/test_algorithms.cpp new file mode 100644 index 00000000..020ed313 --- /dev/null +++ b/tests/test_algorithms.cpp @@ -0,0 +1,317 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_tvector/tvector.h" +#include "../lib_mathvector/MathVector.h" +#include "../lib_matrix/matrix.h" +#include "../lib_node/node.h" +#include "../lib_list/list.h" +#include "../lib_algorithms/algorithms.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestAlgorithmsLib, test_gradient_descent_from_example1) { + // Arrange + Matrix matrix{ {3, 1, 2}, {5, 8, 4}, {7, 6, 9} }; + + // Act + int res = gradient_descent(matrix); + + // Assert + EXPECT_TRUE(res == 6 || res == 1); +} + +TEST(TestAlgorithmsLib, test_gradient_descent_from_example2) { + // Arrange + Matrix matrix{ {11, 15, 10, 9}, {6, 16, 3, 8}, {7, 4, 2, 13}, {14, 12, 1, 5} }; + + // Act + int res = gradient_descent(matrix); + + // Assert + EXPECT_TRUE(res == 6 || res == 1); +} + +TEST(TestAlgorithmsLib, test_1_on_check_brackets_empty_list) { + // Arrange + std::string string = ""; + + // Act & Assert + EXPECT_TRUE(check_brackets(string)); +} + +TEST(TestAlgorithmsLib, test_2_on_check_brackets_easy) { + // Arrange + std::string string = "()"; + + // Act & Assert + EXPECT_TRUE(check_brackets(string)); +} + +TEST(TestAlgorithmsLib, test_3_on_check_brackets_easy) { + // Arrange + std::string string = "()()"; + + // Act & Assert + EXPECT_TRUE(check_brackets(string)); +} + +TEST(TestAlgorithmsLib, test_4_on_check_brackets) { + // Arrange + std::string string = "[(()())(())]"; + + // Act & Assert + EXPECT_TRUE(check_brackets(string)); +} + +TEST(TestAlgorithmsLib, test_5_on_check_brackets) { + // Arrange + std::string string = "(()()"; + + // Act & Assert + EXPECT_FALSE(check_brackets(string)); +} + +TEST(TestAlgorithmsLib, test_6_on_check_brackets) { + // Arrange + std::string string = "())(())"; + + // Act & Assert + EXPECT_FALSE(check_brackets(string)); +} + +TEST(TestAlgorithmsLib, test_7_on_check_brackets) { + // Arrange + std::string string = "((()()(()))"; + + // Act & Assert + EXPECT_FALSE(check_brackets(string)); +} + +TEST(TestAlgorithmsLib, different_types_of_brackets_correct) { + // Arrange + std::string str = "({[]})"; + + // Act & Assert + EXPECT_TRUE(check_brackets(str)); +} + +TEST(TestAlgorithmsLib, mixed_brackets_incorrect) { + // Arrange + std::string str = "({[}])"; + + // Act & Assert + EXPECT_FALSE(check_brackets(str)); +} + +TEST(TestAlgorithmsLib, real_example1_with_text) { + // Arrange + std::string str = "[5*(x+8)-9]/[(7/(y*1))*(y*1)]"; + + // Act & Assert + EXPECT_TRUE(check_brackets(str)); +} + +TEST(TestAlgorithmsLib, real_example2_with_text) { + // Arrange + std::string str = "[5*(x+(8)-9]/[(7/(y*1))*(y*1)]"; + + // Act & Assert + EXPECT_FALSE(check_brackets(str)); +} + +TEST(TestAlgorithmsLib, is_looped_hare_and_turtle_on_empty_list) { + // Arrange + List list; + + // Act & Assert + EXPECT_FALSE(is_looped_hare_and_turtle(list)); +} + +TEST(TestAlgorithmsLib, is_looped_hare_and_turtle_on_list_with_one_elem_no_loop) { + // Arrange + List list; + list.push_back(7654); + + // Act & Assert + EXPECT_FALSE(is_looped_hare_and_turtle(list)); +} + +TEST(TestAlgorithmsLib, is_looped_hare_and_turtle_on_list_with_one_elem_with_loop) { + // Arrange + List list; + list.push_back(8765); + list.head()->next = list.head(); + + // Act & Assert + EXPECT_TRUE(is_looped_hare_and_turtle(list)); + list.head()->next = nullptr; +} + +TEST(TestAlgorithmsLib, is_looped_hare_and_turtle_on_large_list_with_no_loop) { + // Arrange + List list; + for (int i = 0; i < 100; ++i) { + list.push_back(i); + } + + // Act & Assert + EXPECT_FALSE(is_looped_hare_and_turtle(list)); +} + +TEST(TestAlgorithmsLib, is_looped_hare_and_turtle_on_large_list_with_loop_in_middle) { + // Arrange + List list; + for (int i = 0; i < 100; ++i) { + list.push_back(i); + } + Node* middle = list.head(); + for (int i = 0; i < 50; ++i) { + middle = middle->next; + } + list.tail()->next = middle; + + // Act & Assert + EXPECT_TRUE(is_looped_hare_and_turtle(list)); + list.tail()->next = nullptr; +} + +TEST(TestAlgorithmsLib, is_looped_turn_ptr_on_empty_list) { + // Arrange + List list; + + // Act & Assert + EXPECT_FALSE(is_looped_turn_ptr(list)); +} + +TEST(TestAlgorithmsLib, is_looped_turn_ptr_on_list_with_one_elem_no_loop) { + // Arrange + List list; + list.push_back(7654); + + // Act & Assert + EXPECT_FALSE(is_looped_turn_ptr(list)); +} + +TEST(TestAlgorithmsLib, is_looped_turn_ptr_on_list_with_one_elem_with_loop) { + // Arrange + List list; + list.push_back(8765); + list.head()->next = list.head(); + + // Act & Assert + EXPECT_TRUE(is_looped_turn_ptr(list)); + list.head()->next = nullptr; +} + +TEST(TestAlgorithmsLib, is_looped_turn_ptr_on_large_list_with_no_loop) { + // Arrange + List list; + for (int i = 0; i < 100; ++i) { + list.push_back(i); + } + + // Act & Assert + EXPECT_FALSE(is_looped_turn_ptr(list)); +} + +TEST(TestAlgorithmsLib, is_looped_turn_ptr_on_large_list_with_loop_in_middle) { + // Arrange + List list; + for (int i = 0; i < 100; ++i) { + list.push_back(i); + } + Node* middle = list.head(); + for (int i = 0; i < 50; ++i) { + middle = middle->next; + } + list.tail()->next = middle; + + // Act & Assert + EXPECT_TRUE(is_looped_turn_ptr(list)); + list.tail()->next = nullptr; +} + +TEST(TestAlgorithmsLib, find_loop_node_in_empty_list) { + // Arrange + List list; + + // Act & Assert + EXPECT_EQ(nullptr, find_loop_node(list)); +} + +TEST(TestAlgorithmsLib, find_loop_node_no_loop) { + // Arrange + List list; + for (int i = 1; i < 5; ++i) { + list.push_back(i); + } + + // Act & Assert + EXPECT_EQ(nullptr, find_loop_node(list)); +} + +TEST(TestAlgorithmsLib, find_loop_node_with_loop_in_list_with_one_elem) { + // Arrange + List list; + list.push_back(1); + list.head()->next = list.head(); + + // Act & Assert + EXPECT_EQ(list.head(), find_loop_node(list)); + list.head()->next = nullptr; +} + +TEST(TestAlgorithmsLib, find_loop_node_with_loop_at_beginning) { + // Arrange + List list; + for (int i = 1; i < 5; ++i) { + list.push_back(i); + } + + // Act + list.tail()->next = list.head(); + + // Act & Assert + EXPECT_EQ(list.head(), find_loop_node(list)); + list.tail()->next = nullptr; +} + +TEST(TestAlgorithmsLib, find_loop_node_with_loop_in_middle) { + // Arrange + List list; + for (int i = 1; i < 6; ++i) { + list.push_back(i); + } + + // Act + Node* third_node = list.head()->next->next; + list.tail()->next = third_node; + + // Act & Assert + EXPECT_EQ(third_node, find_loop_node(list)); + EXPECT_EQ(3, find_loop_node(list)->value); + list.tail()->next = nullptr; +} + +TEST(TestAlgorithmsLib, find_loop_node_with_loop_in_large_list) { + // Arrange + List list; + for (int i = 0; i < 100; ++i) { + list.push_back(i); + } + Node* loop_node = list.head(); + for (int i = 0; i < 75; ++i) { + loop_node = loop_node->next; + } + list.tail()->next = loop_node; + + // Act & Assert + EXPECT_EQ(loop_node, find_loop_node(list)); + EXPECT_EQ(75, find_loop_node(list)->value); + + // + list.tail()->next = nullptr; +} \ No newline at end of file diff --git a/tests/test_circle.cpp b/tests/test_circle.cpp new file mode 100644 index 00000000..9d722fc1 --- /dev/null +++ b/tests/test_circle.cpp @@ -0,0 +1,58 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_circle/circle.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestCircleLib, default_constructor) { + // Arrange + Circle A; + Point b; + + // Act & Assert + EXPECT_EQ(1, A.get_radius()); // + EXPECT_EQ(b, A.get_center()); +} + +TEST(TestCircleLib, parameterized_constructor_with_normal_radius) { + // Arrange + Point a(5, 27); + Circle C(a, 6); + + // Act & Assert + EXPECT_EQ(6, C.get_radius()); // + EXPECT_EQ(a, C.get_center()); +} +TEST(TestCircleLib, parameterized_constructor_with_radius_less_than_zero) { + // Arrange + Point a(-3, 15); + + // Act & Assert + ASSERT_ANY_THROW(Circle C(a, -8)); +} + +TEST(TestCircleLib, copy_constructor_without_throw) { + // Arrange + Point M(-4, 10); + Circle A(M, 7); + + + // Act + Circle B(A); + + // Assert + EXPECT_EQ(M, B.get_center()); // + EXPECT_EQ(7, B.get_radius()); +} + +TEST(TestCircleLib, copy_constructor_with_throw) { + // Arrange + Circle* null_pointer = nullptr; + // Act & Assert + ASSERT_ANY_THROW(Circle C(*null_pointer)); +} + + diff --git a/tests/test_dlist.cpp b/tests/test_dlist.cpp new file mode 100644 index 00000000..5fb025b6 --- /dev/null +++ b/tests/test_dlist.cpp @@ -0,0 +1,868 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_dlist/dlist.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + + +TEST(TestDListLib, default_constructor) { + // Arrange & Act + DList list; + + // Assert + EXPECT_EQ(nullptr, list.head()); + EXPECT_EQ(nullptr, list.tail()); + EXPECT_TRUE(list.is_empty()); +} + +TEST(TestDListLib, copy_constructor_with_empty_list) { + // Arrange + DList list1; + + // Act + DList list2(list1); + + // Assert + EXPECT_TRUE(list2.is_empty()); + EXPECT_EQ(list1.head(), list2.head()); + EXPECT_EQ(list1.tail(), list2.tail()); + EXPECT_EQ(nullptr, list2.head()); + EXPECT_EQ(nullptr, list2.tail()); +} + +TEST(TestDListLib, copy_constructor_with_not_empty_list) { + // Arrange + DList list1; + list1.push_back(1); + list1.push_back(2); + list1.push_back(3); + + // Act + DList list2(list1); + + // Assert + EXPECT_FALSE(list2.is_empty()); + EXPECT_EQ(list1.head()->value, list2.head()->value); + EXPECT_EQ(list1.tail()->value, list2.tail()->value); + EXPECT_EQ(1, list2.head()->value); + EXPECT_EQ(3, list2.tail()->value); +} + +TEST(TestDListLib, push_front_to_empty_list_one_element) { + // Arrange + DList list; + + // Act + list.push_front(678); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(678, list.head()->value); + EXPECT_EQ(678, list.tail()->value); + EXPECT_EQ(list.head(), list.tail()); +} + +TEST(TestDListLib, push_front_to_empty_list_multiple_elements) { + // Arrange + DList list; + + // Act + list.push_front(1); + list.push_front(2); + list.push_front(3); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(3, list.head()->value); + EXPECT_EQ(1, list.tail()->value); + NodeD* cur = list.head(); + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(1, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestDListLib, push_back_to_empty_list_one_element) { + // Arrange + DList list; + + // Act + list.push_back(678); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(678, list.head()->value); + EXPECT_EQ(678, list.tail()->value); + EXPECT_EQ(list.head(), list.tail()); +} + +TEST(TestDListLib, push_back_to_empty_list_multiple_elements) { + // Arrange + DList list; + + // Act + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(3, list.tail()->value); + NodeD* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestDListLib, insert_with_position_at_beginning) { + // Arrange + DList list; + list.push_back(2); + list.push_back(3); + + // Act + list.insert((size_t)0, 345); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(345, list.head()->value); + EXPECT_EQ(2, list.head()->next->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestDListLib, insert_with_position_in_middle) { + // Arrange + DList list; + list.push_back(1); + list.push_back(3); + list.push_back(4); + + // Act + list.insert((size_t)1, 2); + + // Assert + EXPECT_FALSE(list.is_empty()); + NodeD* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(4, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestDListLib, insert_with_position_at_end) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + + // Act + list.insert((size_t)2, 3); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.head()->next->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestDListLib, insert_with_throw_out_of_range) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + + // Act & Assert + EXPECT_ANY_THROW(list.insert((size_t)7, 3)); +} + +TEST(TestDListLib, insert_after_node_in_middle) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(4); + NodeD* node = list.head()->next; + + // Act + list.insert_after(node, 3); + + // Assert + EXPECT_FALSE(list.is_empty()); + NodeD* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(4, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestDListLib, insert_after_tail_node) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + NodeD* node = list.tail(); + + // Act + list.insert_after(node, 4); + + // Assert + EXPECT_FALSE(list.is_empty()); + NodeD* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(4, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestDListLib, insert_after_nullptr) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + + // Act & Assert + EXPECT_ANY_THROW(list.insert_after(nullptr, 3)); +} + +TEST(TestDListLib, insert_after_node_not_in_list) { + // Arrange + DList list; + list.push_back(1); + NodeD* foreign_node = new NodeD(888); + + // Act & Assert + EXPECT_ANY_THROW(list.insert_after(foreign_node, 2)); + + // Cleanup + delete foreign_node; +} + +TEST(TestDListLib, insert_before_head) { + // Arrange + DList list; + list.push_back(2); + list.push_back(3); + + // Act + list.insert_before(list.head(), 1); + + // Assert + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.head()->next->value); + EXPECT_EQ(3, list.tail()->value); + EXPECT_EQ(nullptr, list.head()->prev); +} + +TEST(TestDListLib, insert_before_middle) { + // Arrange + DList list; + list.push_back(1); + list.push_back(3); + list.push_back(4); + NodeD* middle_node = list.head()->next; + + // Act + list.insert_before(middle_node, 2); + + // Assert + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(4, list.tail()->value); + NodeD* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(4, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestDListLib, insert_before_tail) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(4); + NodeD* tail_node = list.tail(); + + // Act + list.insert_before(tail_node, 3); + + // Assert + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(4, list.tail()->value); + NodeD* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(4, cur->value); + EXPECT_EQ(nullptr, cur->next); + EXPECT_EQ(3, list.tail()->prev->value); + EXPECT_EQ(4, list.tail()->value); +} + +TEST(TestDListLib, insert_before_in_empty_list) { + // Arrange + DList list; + NodeD* foreign_node = new NodeD(999); + + // Act & Assert + EXPECT_ANY_THROW(list.insert_before(foreign_node, 1)); + + // Cleanup + delete foreign_node; +} + +TEST(TestDListLib, insert_before_nullptr) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + + // Act & Assert + EXPECT_ANY_THROW(list.insert_before(nullptr, 3)); +} + +TEST(TestDListLib, insert_before_foreign_node) { + // Arrange + DList list1; + list1.push_back(1); + list1.push_back(2); + DList list2; + list2.push_back(10); + list2.push_back(20); + NodeD* foreign_node = list2.head(); + + // Act & Assert + EXPECT_ANY_THROW(list1.insert_before(foreign_node, 3)); +} + +TEST(TestDListLib, pop_front_single_element) { + // Arrange + DList list; + list.push_back(456); + + // Act + list.pop_front(); + + // Assert + EXPECT_TRUE(list.is_empty()); + EXPECT_EQ(nullptr, list.head()); + EXPECT_EQ(nullptr, list.tail()); +} + +TEST(TestDListLib, pop_front_multiple_elements) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.pop_front(); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(2, list.head()->value); + EXPECT_EQ(3, list.tail()->value); + EXPECT_EQ(nullptr, list.tail()->next); +} + +TEST(TestDListLib, pop_front_in_empty_list) { + // Arrange + DList list; + + // Act & Assert + EXPECT_ANY_THROW(list.pop_front()); +} + +TEST(TestDListLib, pop_back_single_element) { + // Arrange + DList list; + list.push_back(456); + + // Act + list.pop_back(); + + // Assert + EXPECT_TRUE(list.is_empty()); + EXPECT_EQ(nullptr, list.head()); + EXPECT_EQ(nullptr, list.tail()); +} + +TEST(TestDListLib, pop_back_multiple_elements) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.pop_back(); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.tail()->value); + EXPECT_EQ(nullptr, list.tail()->next); +} + +TEST(TestDListLib, pop_back_in_empty_list) { + // Arrange + DList list; + + // Act & Assert + EXPECT_ANY_THROW(list.pop_back()); +} + +TEST(TestDListLib, erase_with_position_at_beggining) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.erase((size_t)0); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(2, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestDListLib, erase_with_position_in_middle) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.erase((size_t)1); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestDListLib, erase_with_position_at_end) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.erase((size_t)2); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.tail()->value); +} + +TEST(TestDListLib, erase_with_position_in_empty_list) { + // Arrange + DList list; + + // Act & Assert + EXPECT_ANY_THROW(list.erase((size_t)0)); +} + +TEST(TestDListLib, erase_with_position_more_than_list) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act & Assert + EXPECT_ANY_THROW(list.erase((size_t)8)); +} + +TEST(TestDListLib, erase_first_node) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + NodeD* node = list.head(); + + // Act + list.erase(node); + + // Assert + EXPECT_EQ(2, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestDListLib, erase_with_node_in_middle) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + NodeD* node = list.head(); + + // Act + list.erase(node); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(2, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestDListLib, erase_with_node_at_end) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + NodeD* node = list.tail(); + + // Act + list.erase(node); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.tail()->value); +} + +TEST(TestDListLib, erase_after_node_not_in_list) { + // Arrange + DList list; + list.push_back(1); + NodeD* foreign_node = new NodeD(888); + + // Act & Assert + EXPECT_ANY_THROW(list.erase(foreign_node)); + + // Cleanup + delete foreign_node; +} + +TEST(TestDListLib, erase_nullptr) { + // Arrange + DList list; + list.push_back(1); + + // Act & Assert + ASSERT_ANY_THROW(list.erase(nullptr)); +} + +TEST(TestDListLib, operator_assign_empty_to_empty) { + // Arrange + DList list1; + DList list2; + + // Act + list1 = list2; + + // Assert + EXPECT_TRUE(list1.is_empty()); + EXPECT_TRUE(list2.is_empty()); +} + +TEST(TestDListLib, operator_assign_empty_to_not_empty) { + // Arrange + DList list1; + list1.push_front(1); + list1.push_front(2); + list1.push_front(3); + DList list2; + + // Act + list2 = list1; + + // Assert + EXPECT_FALSE(list2.is_empty()); + EXPECT_EQ(3, list2.head()->value); + EXPECT_EQ(2, list2.head()->next->value); + EXPECT_EQ(1, list2.tail()->value); +} + +TEST(TestDListLib, operator_assign_not_empty_to_empty) { + // Arrange + DList list1; + list1.push_back(1); + list1.push_back(2); + DList list2; + + // Act + list1 = list2; + + // Assert + EXPECT_TRUE(list1.is_empty()); + EXPECT_TRUE(list2.is_empty()); +} + +TEST(TestDListLib, operator_assign_self_assignment) { + // Arrange + DList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list = list; + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestDListLib, operator_assign_chain_of_assignment) { + // Arrange + DList list1; + list1.push_back(1); + DList list2; + list2.push_back(2); + DList list3; + list3.push_back(3); + + // Act + list1 = list2 = list3; + + // Assert + EXPECT_EQ(3, list1.head()->value); + EXPECT_EQ(3, list2.head()->value); + EXPECT_EQ(3, list3.head()->value); +} + +TEST(TestDListLib, test_complex_of_operations) { + // Arrange + DList list; + + // Act + list.push_back(1); + list.push_front(0); + list.push_back(3); + list.insert(2, 2); + list.push_back(4); + list.pop_front(); + list.pop_back(); + + // Assert + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(3, list.tail()->value); + const NodeD* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestDListLib, test_double_list) { + // Arrange + DList list; + + // Act + list.push_back(1.1); + list.push_back(2.2); + list.push_back(3.3); + + // Assert + EXPECT_NEAR(1.1, list.head()->value, EPSILON); + EXPECT_NEAR(3.3, list.tail()->value, EPSILON); + + // Act + list.erase((size_t)1); + + // Assert + EXPECT_NEAR(1.1, list.head()->value, EPSILON); + EXPECT_NEAR(3.3, list.tail()->value, EPSILON); + EXPECT_NEAR(3.3, list.head()->next->value, EPSILON); +} + +TEST(TestDListLib, test_string_list) { + // Arrange + DList list; + + // Act + list.push_back("Hello"); + list.push_back("World"); + list.push_front("Start"); + + // Assert + EXPECT_EQ("Start", list.head()->value); + EXPECT_EQ("World", list.tail()->value); + + // Act + list.pop_front(); + + // Assert + EXPECT_EQ("Hello", list.head()->value); +} + +TEST(TestDListLib, iterator_read) { + // Arrange + DList list; + for (int i = 0; i < 5; i++) { + list.push_back(i); + } + int i = 0; + + // Act & Assert + for (DList::Iterator it = list.begin(); it != list.end(); it++) { + EXPECT_EQ(i, *it); + i++; + } +} + +TEST(TestDListLib, iterator_write) { + // Arrange + DList list; + for (int i = 0; i < 5; i++) { + list.push_back(0); + } + int i = 1; + int j = 10; + + // Act + for (DList::Iterator it = list.begin(); it != list.end(); it++) { + *it = i * 10; + i++; + } + + // Assert + for (DList::Iterator it = list.begin(); it != list.end(); it++) { + EXPECT_EQ(j, *it); + j += 10; + } +} + +TEST(TestDListLib, back_iterator_write) { + // Arrange + DList list; + for (int i = 0; i < 5; i++) { + list.push_back(0); + } + int i = 1; + + // Act + for (DList::Iterator it = list.rbegin(); it != list.rend(); it--) { + *it = i; + i++; + } + + // Assert + for (DList::Iterator it = list.begin(); it != list.end(); it++) { + EXPECT_EQ(--i, *it); + } +} + +TEST(TestDListLib, iterator_in_empty_list) { + // Arrange + DList list; + + // Act + int iterator_count = 0; + for (DList::Iterator it = list.begin(); it != list.end(); it++) { + iterator_count++; + } + + // Assert + EXPECT_EQ(0, iterator_count); + EXPECT_TRUE(list.begin() == list.end()); + EXPECT_FALSE(list.begin() != list.end()); +} + +TEST(TestDListLib, iterator_operator_assigment) { + // Arrange + DList list; + list.push_back(76); + list.push_back(32); + + // Act + DList::Iterator it1 = list.begin(); + DList::Iterator it2 = it1; + + // Assert + EXPECT_EQ(*it1, *it2); + EXPECT_TRUE(it1 == it2); + ++it1; + EXPECT_EQ(32, *it1); + EXPECT_EQ(76, *it2); + EXPECT_FALSE(it1 == it2); +} + +TEST(TestDListLib, iterator_operator_prefix_plus_plus) { + // Arrange + DList list; + list.push_back(765); + list.push_back(324); + list.push_back(456); + + // Act + DList::Iterator it = list.begin(); + + // Assert + EXPECT_EQ(765, *it); + EXPECT_EQ(324, *++it); + EXPECT_EQ(324, *it); + EXPECT_EQ(456, *++it); +} + +TEST(TestDListLib, iterator_operator_postfix_plus_plus) { + // Arrange + DList list; + list.push_back(765); + list.push_back(324); + list.push_back(456); + + // Act + DList::Iterator it = list.begin(); + + // Assert + EXPECT_EQ(765, *it); + EXPECT_EQ(765, *it++); + EXPECT_EQ(324, *it); +} + +TEST(TestDListLib, iterator_operator_plus_assigment) { + // Arrange + DList list; + for (int i = 1; i < 7; i++) { + list.push_back(i * 10); + } + + // Act + DList::Iterator it = list.begin(); + it += 3; + + // Assert + EXPECT_EQ(40, *it); +} \ No newline at end of file diff --git a/tests/test_easy_example.cpp b/tests/test_easy_example.cpp index 3a67b612..7a303d32 100644 --- a/tests/test_easy_example.cpp +++ b/tests/test_easy_example.cpp @@ -1,17 +1,20 @@ -// Copyright 2024 Marina Usova +// Copyright 2025 Ekaterina Ushnitskaya #include #include "../lib_easy_example/easy_example.h" #define EPSILON 0.000001 +//ASSERT_... - , +//EXPECT_... - , + TEST(TestEasyExampleLib, can_div) { // Arrange int x = 10; int y = 2; // Act & Assert - ASSERT_NO_THROW(division(x, y)); + ASSERT_NO_THROW(division(x, y)); // } TEST(TestEasyExampleLib, can_div_correctly) { @@ -24,8 +27,15 @@ TEST(TestEasyExampleLib, can_div_correctly) { // Assert int expected_result = 3; - EXPECT_EQ(expected_result, actual_result); + EXPECT_EQ(expected_result, actual_result); // } +/* : +EXPECT_NE(a, b) - , a != b +EXPECT_LT(a, b) - , a < b(Less Than) +EXPECT_LE(a, b) - , a <= b(Less or Equal) +EXPECT_GT(a, b) - , a > b(Greater Than) +EXPECT_GE(a, b) - , a >= b(Greater or Equal) +*/ TEST(TestEasyExampleLib, can_div_correctly_with_remainder) { // Arrange @@ -37,7 +47,7 @@ TEST(TestEasyExampleLib, can_div_correctly_with_remainder) { // Assert float expected_result = 1.25; - EXPECT_NEAR(expected_result, actual_result, EPSILON); + EXPECT_NEAR(expected_result, actual_result, EPSILON); //, } TEST(TestEasyExampleLib, throw_when_try_div_by_zero) { @@ -46,5 +56,12 @@ TEST(TestEasyExampleLib, throw_when_try_div_by_zero) { int y = 0; // Act & Assert - ASSERT_ANY_THROW(division(x, y)); + ASSERT_ANY_THROW(division(x, y)); //, } +/* +* : +EXPECT_THROW(calc.Divide(10, 0), std::invalid_argument); //, +EXPECT_TRUE(value > 0); //, +EXPECT_FALSE(result.empty()); //, condition + +*/ diff --git a/tests/test_list.cpp b/tests/test_list.cpp new file mode 100644 index 00000000..fa4f7ac8 --- /dev/null +++ b/tests/test_list.cpp @@ -0,0 +1,743 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_list/list.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestListLib, default_constructor) { + // Arrange & Act + List list; + + // Assert + EXPECT_EQ(nullptr, list.head()); + EXPECT_EQ(nullptr, list.tail()); + EXPECT_TRUE(list.is_empty()); +} + +TEST(TestListLib, copy_constructor_with_empty_list) { + // Arrange + List list1; + + // Act + List list2(list1); + + // Assert + EXPECT_TRUE(list2.is_empty()); + EXPECT_EQ(list1.head(), list2.head()); + EXPECT_EQ(list1.tail(), list2.tail()); + EXPECT_EQ(nullptr, list2.head()); + EXPECT_EQ(nullptr, list2.tail()); +} + +TEST(TestListLib, copy_constructor_with_not_empty_list) { + // Arrange + List list1; + list1.push_back(1); + list1.push_back(2); + list1.push_back(3); + + // Act + List list2(list1); + + // Assert + EXPECT_FALSE(list2.is_empty()); + EXPECT_EQ(list1.head()->value, list2.head()->value); + EXPECT_EQ(list1.tail()->value, list2.tail()->value); + EXPECT_EQ(1, list2.head()->value); + EXPECT_EQ(3, list2.tail()->value); +} + +TEST(TestListLib, push_front_to_empty_list_one_element) { + // Arrange + List list; + + // Act + list.push_front(678); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(678, list.head()->value); + EXPECT_EQ(678, list.tail()->value); + EXPECT_EQ(list.head(), list.tail()); +} + +TEST(TestListLib, push_front_to_empty_list_multiple_elements) { + // Arrange + List list; + + // Act + list.push_front(1); + list.push_front(2); + list.push_front(3); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(3, list.head()->value); + EXPECT_EQ(1, list.tail()->value); + Node* cur = list.head(); + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(1, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestListLib, push_back_to_empty_list_one_element) { + // Arrange + List list; + + // Act + list.push_back(678); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(678, list.head()->value); + EXPECT_EQ(678, list.tail()->value); + EXPECT_EQ(list.head(), list.tail()); +} + +TEST(TestListLib, push_back_to_empty_list_multiple_elements) { + // Arrange + List list; + + // Act + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(3, list.tail()->value); + Node* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestListLib, insert_with_position_at_beginning) { + // Arrange + List list; + list.push_back(2); + list.push_back(3); + + // Act + list.insert((size_t)0, 345); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(345, list.head()->value); + EXPECT_EQ(2, list.head()->next->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestListLib, insert_with_position_in_middle) { + // Arrange + List list; + list.push_back(1); + list.push_back(3); + list.push_back(4); + + // Act + list.insert((size_t)1, 2); + + // Assert + EXPECT_FALSE(list.is_empty()); + Node* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(4, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestListLib, insert_with_position_at_end) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + + // Act + list.insert((size_t)2, 3); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.head()->next->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestListLib, insert_with_throw_out_of_range) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + + // Act & Assert + EXPECT_ANY_THROW(list.insert((size_t)7, 3)); +} + +TEST(TestListLib, insert_after_node_in_middle) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(4); + Node* node = list.head()->next; + + // Act + list.insert(node, 3); + + // Assert + EXPECT_FALSE(list.is_empty()); + Node* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(4, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestListLib, insert_after_tail_node) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + Node* node = list.tail(); + + // Act + list.insert(node, 4); + + // Assert + EXPECT_FALSE(list.is_empty()); + Node* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + cur = cur->next; + EXPECT_EQ(4, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestListLib, insert_after_nullptr) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + + // Act & Assert + EXPECT_ANY_THROW(list.insert(nullptr, 3)); +} + +TEST(TestListLib, insert_after_node_not_in_list) { + // Arrange + List list; + list.push_back(1); + Node* foreign_node = new Node(888); + + // Act & Assert + EXPECT_ANY_THROW(list.insert(foreign_node, 2)); + + // Cleanup + delete foreign_node; +} + +TEST(TestListLib, pop_front_single_element) { + // Arrange + List list; + list.push_back(456); + + // Act + list.pop_front(); + + // Assert + EXPECT_TRUE(list.is_empty()); + EXPECT_EQ(nullptr, list.head()); + EXPECT_EQ(nullptr, list.tail()); +} + +TEST(TestListLib, pop_front_multiple_elements) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.pop_front(); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(2, list.head()->value); + EXPECT_EQ(3, list.tail()->value); + EXPECT_EQ(nullptr, list.tail()->next); +} + +TEST(TestListLib, pop_front_in_empty_list) { + // Arrange + List list; + + // Act & Assert + EXPECT_ANY_THROW(list.pop_front()); +} + +TEST(TestListLib, pop_back_single_element) { + // Arrange + List list; + list.push_back(456); + + // Act + list.pop_back(); + + // Assert + EXPECT_TRUE(list.is_empty()); + EXPECT_EQ(nullptr, list.head()); + EXPECT_EQ(nullptr, list.tail()); +} + +TEST(TestListLib, pop_back_multiple_elements) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.pop_back(); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.tail()->value); + EXPECT_EQ(nullptr, list.tail()->next); +} + +TEST(TestListLib, pop_back_in_empty_list) { + // Arrange + List list; + + // Act & Assert + EXPECT_ANY_THROW(list.pop_back()); +} + +TEST(TestListLib, erase_with_position_at_beggining) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.erase((size_t)0); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(2, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestListLib, erase_with_position_in_middle) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.erase((size_t)1); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestListLib, erase_with_position_at_end) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list.erase((size_t)2); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.tail()->value); +} + +TEST(TestListLib, erase_with_position_in_empty_list) { + // Arrange + List list; + + // Act & Assert + EXPECT_ANY_THROW(list.erase((size_t)0)); +} + +TEST(TestListLib, erase_with_position_more_than_list) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act & Assert + EXPECT_ANY_THROW(list.erase((size_t)8)); +} + +TEST(TestListLib, erase_first_node) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + Node* node = list.head(); + + // Act + list.erase(node); + + // Assert + EXPECT_EQ(2, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestListLib, erase_with_node_in_middle) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + Node* node = list.head(); + + // Act + list.erase(node); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(2, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestListLib, erase_with_node_at_end) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + Node* node = list.tail(); + + // Act + list.erase(node); + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(2, list.tail()->value); +} + +TEST(TestListLib, erase_after_node_not_in_list) { + // Arrange + List list; + list.push_back(1); + Node* foreign_node = new Node(888); + + // Act & Assert + EXPECT_ANY_THROW(list.erase(foreign_node)); + + // Cleanup + delete foreign_node; +} + +TEST(TestListLib, erase_nullptr) { + // Arrange + List list; + list.push_back(1); + + // Act & Assert + ASSERT_ANY_THROW(list.erase(nullptr)); +} + +TEST(TestListLib, operator_assign_empty_to_empty) { + // Arrange + List list1; + List list2; + + // Act + list1 = list2; + + // Assert + EXPECT_TRUE(list1.is_empty()); + EXPECT_TRUE(list2.is_empty()); +} + +TEST(TestListLib, operator_assign_empty_to_not_empty) { + // Arrange + List list1; + list1.push_front(1); + list1.push_front(2); + list1.push_front(3); + List list2; + + // Act + list2 = list1; + + // Assert + EXPECT_FALSE(list2.is_empty()); + EXPECT_EQ(3, list2.head()->value); + EXPECT_EQ(2, list2.head()->next->value); + EXPECT_EQ(1, list2.tail()->value); +} + +TEST(TestListLib, operator_assign_not_empty_to_empty) { + // Arrange + List list1; + list1.push_back(1); + list1.push_back(2); + List list2; + + // Act + list1 = list2; + + // Assert + EXPECT_TRUE(list1.is_empty()); + EXPECT_TRUE(list2.is_empty()); +} + +TEST(TestListLib, operator_assign_self_assignment) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + list = list; + + // Assert + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(3, list.tail()->value); +} + +TEST(TestListLib, operator_assign_chain_of_assignment) { + // Arrange + List list1; + list1.push_back(1); + List list2; + list2.push_back(2); + List list3; + list3.push_back(3); + + // Act + list1 = list2 = list3; + + // Assert + EXPECT_EQ(3, list1.head()->value); + EXPECT_EQ(3, list2.head()->value); + EXPECT_EQ(3, list3.head()->value); +} + +TEST(TestListLib, test_complex_of_operations) { + // Arrange + List list; + + // Act + list.push_back(1); + list.push_front(0); + list.push_back(3); + list.insert(2, 2); + list.push_back(4); + list.pop_front(); + list.pop_back(); + + // Assert + EXPECT_EQ(1, list.head()->value); + EXPECT_EQ(3, list.tail()->value); + const Node* cur = list.head(); + EXPECT_EQ(1, cur->value); + cur = cur->next; + EXPECT_EQ(2, cur->value); + cur = cur->next; + EXPECT_EQ(3, cur->value); + EXPECT_EQ(nullptr, cur->next); +} + +TEST(TestListLib, test_double_list) { + // Arrange + List list; + + // Act + list.push_back(1.1); + list.push_back(2.2); + list.push_back(3.3); + + // Assert + EXPECT_NEAR(1.1, list.head()->value, EPSILON); + EXPECT_NEAR(3.3, list.tail()->value, EPSILON); + + // Act + list.erase((size_t)1); + + // Assert + EXPECT_NEAR(1.1, list.head()->value, EPSILON); + EXPECT_NEAR(3.3, list.tail()->value, EPSILON); + EXPECT_NEAR(3.3, list.head()->next->value, EPSILON); +} + +TEST(TestListLib, test_string_list) { + // Arrange + List list; + + // Act + list.push_back("Hello"); + list.push_back("World"); + list.push_front("Start"); + + // Assert + EXPECT_EQ("Start", list.head()->value); + EXPECT_EQ("World", list.tail()->value); + + // Act + list.pop_front(); + + // Assert + EXPECT_EQ("Hello", list.head()->value); +} + +TEST(TestListLib, iterator_read) { + // Arrange + List list; + for (int i = 0; i < 5; i++) { + list.push_back(i); + } + int i = 0; + + // Act & Assert + for (List::Iterator it = list.begin(); it != list.end(); it++) { + EXPECT_EQ(i, *it); + i++; + } +} + +TEST(TestListLib, iterator_write) { + // Arrange + List list; + for (int i = 0; i < 5; i++) { + list.push_back(0); + } + int i = 1; + int j = 10; + + // Act + for (List::Iterator it = list.begin(); it != list.end(); it++) { + *it = i * 10; + i++; + } + + // Assert + for (List::Iterator it = list.begin(); it != list.end(); it++) { + EXPECT_EQ(j, *it); + j += 10; + } +} + +TEST(TestListLib, iterator_in_empty_list) { + // Arrange + List list; + + // Act + int iterator_count = 0; + for (List::Iterator it = list.begin(); it != list.end(); it++) { + iterator_count++; + } + + // Assert + EXPECT_EQ(0, iterator_count); + EXPECT_TRUE(list.begin() == list.end()); + EXPECT_FALSE(list.begin() != list.end()); +} + +TEST(TestListLib, iterator_operator_assigment) { + // Arrange + List list; + list.push_back(76); + list.push_back(32); + + // Act + List::Iterator it1 = list.begin(); + List::Iterator it2 = it1; + + // Assert + EXPECT_EQ(*it1, *it2); + EXPECT_TRUE(it1 == it2); + ++it1; + EXPECT_EQ(32, *it1); + EXPECT_EQ(76, *it2); + EXPECT_FALSE(it1 == it2); +} + +TEST(TestListLib, iterator_operator_prefix_plus_plus) { + // Arrange + List list; + list.push_back(765); + list.push_back(324); + list.push_back(456); + + // Act + List::Iterator it = list.begin(); + + // Assert + EXPECT_EQ(765, *it); + EXPECT_EQ(324, *++it); + EXPECT_EQ(324, * it); + EXPECT_EQ(456, *++it); +} + +TEST(TestListLib, iterator_operator_postfix_plus_plus) { + // Arrange + List list; + list.push_back(765); + list.push_back(324); + list.push_back(456); + + // Act + List::Iterator it = list.begin(); + + // Assert + EXPECT_EQ(765, *it); + EXPECT_EQ(765, *it++); + EXPECT_EQ(324, *it); +} + +TEST(TestListLib, iterator_operator_plus_assigment) { + // Arrange + List list; + for (int i = 1; i < 7; i++) { + list.push_back(i*10); + } + + // Act + List::Iterator it = list.begin(); + it += 3; + + // Assert + EXPECT_EQ(40, *it); +} \ No newline at end of file diff --git a/tests/test_mathvector.cpp b/tests/test_mathvector.cpp new file mode 100644 index 00000000..68dd6f80 --- /dev/null +++ b/tests/test_mathvector.cpp @@ -0,0 +1,1139 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_mathvector/MathVector.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestMathVectorLib, default_constructor) { + // Arrange & Act + MathVector vec; + + // Assert + EXPECT_EQ(nullptr, vec.data()); // + EXPECT_EQ(nullptr, vec.states()); + EXPECT_EQ(0, vec.size()); + EXPECT_EQ(0, vec.capacity()); + EXPECT_EQ(0, vec.deleted()); + EXPECT_TRUE(vec.is_empty()); +} + +TEST(TestMathVectorLib, constructor_with_size) { + // Arrange () + size_t size = 10; + + // Act + MathVector vec(size); + + // Assert + EXPECT_EQ(size, vec.size()); + EXPECT_EQ(size + MathVector::RESERVE_MEMORY, vec.capacity()); + EXPECT_EQ(0, vec.deleted()); + EXPECT_FALSE(vec.is_empty()); + for (size_t i = 0; i < size; i++) { + EXPECT_EQ(State::busy, vec.state(i)); + } + for (size_t i = size; i < vec.capacity(); i++) { + EXPECT_EQ(State::empty, vec.state(i)); + } +} + +TEST(TestMathVectorLib, constructor_with_mass_all_parameters_are_good) { + // Arrange () + size_t size = 3; + int copy_mass[3] = { 1, 2, 3 }; + + // Act + MathVector vec(copy_mass, size); + + // Assert + EXPECT_EQ(size, vec.size()); + EXPECT_EQ(size + MathVector::RESERVE_MEMORY, vec.capacity()); + EXPECT_EQ(0, vec.deleted()); + EXPECT_FALSE(vec.is_empty()); + EXPECT_EQ(1, vec.data(0)); + EXPECT_EQ(2, vec.data(1)); + EXPECT_EQ(3, vec.data(2)); + for (size_t i = 0; i < size; i++) { + EXPECT_EQ(State::busy, vec.state(i)); + } + for (size_t i = size; i < vec.capacity(); i++) { + EXPECT_EQ(State::empty, vec.state(i)); + } +} + +TEST(TestMathVectorLib, constructor_with_mass_with_nullptr_and_size_gt_zero) { + // Arrange + int* null_data = nullptr; + + // Act & Assert + ASSERT_ANY_THROW(MathVector vec(null_data, 5)); +} + +TEST(TestMathVectorLib, copy_constructor) { + // Arrange + int arr[4] = { 1, 2, 3, 4 }; + MathVector vec1(arr, 4); + + // Act + MathVector vec2(vec1); + + // Assert + EXPECT_EQ(vec1.size(), vec2.size()); + EXPECT_EQ(vec1.capacity(), vec2.capacity()); + EXPECT_EQ(vec1.deleted(), vec2.deleted()); + for (size_t i = 0; i < vec1.size(); i++) { + EXPECT_EQ(vec1.data(i), vec2.data(i)); + EXPECT_EQ(vec1.state(i), vec2.state(i)); + } +} + +TEST(TestMathVectorLib, test_constructor_list_checking_without_problems) { + // Arrange & Act + MathVector vec{ 1, 2, 3 }; + + // Assert + EXPECT_EQ(vec.size(), 3); + EXPECT_EQ(vec[0], 1); + EXPECT_EQ(vec[1], 2); + EXPECT_EQ(vec[2], 3); +} + +TEST(TestMathVectorLib, test_constructor_list_empty_init) { + // Arrange & Act + MathVector vec{}; + + // Assert + EXPECT_EQ(vec.size(), 0); + EXPECT_TRUE(vec.is_empty()); +} + +TEST(TestMathVectorLib, test_constructor_list_double_init) { + // Arrange & Act + MathVector vec{ 1.1, 2.2, 3.3, 4.4 }; + + // Assert + EXPECT_EQ(vec.size(), 4); + EXPECT_EQ(vec[0], 1.1); + EXPECT_EQ(vec[1], 2.2); + EXPECT_EQ(vec[2], 3.3); + EXPECT_EQ(vec[3], 4.4); +} + +TEST(TestMathVectorLib, test_conversion_constructor) { + // Arrange + MathVector vec_int{ 1, 2, 3 }; + + // Act + MathVector vec_double(vec_int); + + // Assert + EXPECT_EQ(3, vec_double.size()); + EXPECT_NEAR(1.0, vec_double[0], EPSILON); + EXPECT_NEAR(2.0, vec_double[1], EPSILON); + EXPECT_NEAR(3.0, vec_double[2], EPSILON); +} + +TEST(TestMathVectorLib, test_at_checking_without_difficulties) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + MathVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(4, vec.at(4)); +} + +TEST(TestMathVectorLib, test_at_checking_with_pop_front) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + MathVector vec(arr, size); + + // Act + vec.pop_front(); + + // Assert + EXPECT_EQ(1, vec.at(0)); +} + +TEST(TestMathVectorLib, test_data_with_index) { + // Arrange + int arr[3] = { 11, 22, 33 }; + MathVector vec(arr, 3); + + // Act & Assert + EXPECT_EQ(11, vec.data(0)); + EXPECT_EQ(22, vec.data(1)); + EXPECT_EQ(33, vec.data(2)); + ASSERT_ANY_THROW(vec.data(10)); // +} + +TEST(TestMathVectorLib, test_state_state_deleted) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + MathVector vec(arr, size); + + // Act + vec.pop_front(); + + // Assert + EXPECT_EQ(State::deleted, vec.state(0)); +} + +TEST(TestMathVectorLib, test_state_state_busy) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + MathVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(State::busy, vec.state(4)); +} + +TEST(TestMathVectorLib, test_state_state_empty) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + MathVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(State::empty, vec.state(size + 1)); +} + +TEST(TestMathVectorLib, test_size_setter_increase) { // + // Arrange + MathVector vec(2); + + // Act + vec.size(5); + + // Assert + EXPECT_EQ(5, vec.size()); + for (size_t i = 2; i < 5; i++) { + EXPECT_EQ(State::busy, vec.state(i)); + } +} + +TEST(TestMathVectorLib, test_size_setter_decrease) { + // Arrange + MathVector vec(5); + vec[0] = 99; + + // Act + vec.size(2); + + // Assert + EXPECT_EQ(2, vec.size()); + EXPECT_EQ(99, vec[0]); // , +} + +TEST(TestMathVectorLib, test_capacity_setter) { + // Arrange + MathVector vec(2); + size_t old_capacity = vec.capacity(); + + // Act + vec.capacity(old_capacity + 20); + + // Assert + EXPECT_TRUE(vec.capacity() >= old_capacity + 20); +} + +/* +TEST(TestMathVectorLib, test_begin_and_end) { + // Arrange + size_t size = 3; + int arr[8] = { 11, 22, 37 }; + MathVector vec(arr, size); + int sum = 0; + + // Act + int* begin = vec.begin(); + int* end = vec.end(); + for (int* p = begin; p < end; ++p) { + sum += *p; + } + + // Assert + EXPECT_EQ(11 + 22 + 37, sum); +} +*/ + +TEST(TestMathVectorLib, test_deleted_counter) { + // Arrange + MathVector vec(35); + + // Act + vec.erase(1); + vec.erase(2); + + // Assert + EXPECT_EQ(2, vec.deleted()); +} + +TEST(TestMathVectorLib, test_front_without_deleted_elements) { + // Arrange + size_t size = 3; + int arr[8] = { 112, 234, 345 }; + MathVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(112, vec.front()); +} + +TEST(TestMathVectorLib, test_front_with_deleted_element) { + // Arrange + size_t size = 3; + int arr[8] = { 112, 234, 345 }; + MathVector vec(arr, size); + + // Act + vec.pop_front(); + + // Assert + EXPECT_EQ(234, vec.front()); +} + +TEST(TestMathVectorLib, test_back_without_deleted_elements) { + // Arrange + size_t size = 3; + int arr[8] = { 112, 234, 345 }; + MathVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(345, vec.back()); +} + +TEST(TestMathVectorLib, test_back_with_deleted_element) { + // Arrange + size_t size = 3; + int arr[8] = { 112, 234, 345 }; + MathVector vec(arr, size); + + // Act + vec.pop_back(); + + // Assert + EXPECT_EQ(234, vec.back()); +} + +TEST(TestMathVectorLib, test_is_empty_real_empty_vec) { + // Arrange + MathVector vec; + + // Act & Assert + EXPECT_TRUE(vec.is_empty()); +} + +TEST(TestMathVectorLib, test_is_empty_not_empty_vec) { + // Arrange + MathVector vec(3); + + // Act & Assert + EXPECT_FALSE(vec.is_empty()); +} + +TEST(TestMathVectorLib, test_push_front_checking_without_difficulties) { + // Arrange + MathVector vec(3); + vec[0] = 1; + vec[1] = 2; + vec[2] = 3; + const State* states_vec = vec.states(); + + // Act + vec.push_front(777); + + // Assert + EXPECT_EQ(4, vec.size()); + EXPECT_EQ(3 + vec.RESERVE_MEMORY, vec.capacity()); + EXPECT_TRUE(states_vec[3] == State::busy); + EXPECT_EQ(777, vec[0]); + EXPECT_EQ(3, vec[3]); +} + +TEST(TestMathVectorLib, test_push_front_with_reserve) { + // Arrange + MathVector vec(1); + size_t vec_capacity = vec.capacity(); + for (size_t i = 0; i < vec_capacity; ++i) { // capacity + vec.push_back(1); + } + + // Act + vec.push_front(0); // reserve() + + // Assert + EXPECT_TRUE(vec[0] == 0 && vec_capacity <= vec.capacity()); +} + +TEST(TestMathVectorLib, test_push_back_checking_without_difficulties) { + // Arrange + MathVector vec(3); + vec[0] = 1; + vec[1] = 2; + vec[2] = 3; + const State* states_vec = vec.states(); + + // Act + vec.push_back(42); + + // Assert + EXPECT_EQ(4, vec.size()); + EXPECT_EQ(3 + vec.RESERVE_MEMORY, vec.capacity()); + EXPECT_TRUE(states_vec[3] == State::busy); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(42, vec[3]); +} + +TEST(TestMathVectorLib, test_push_back_with_reserve) { + // Arrange + MathVector vec(1); + size_t vec_capacity1 = vec.capacity(); + for (size_t i = 0; i < vec_capacity1; ++i) { // capacity + vec.push_back(1); + } + + // Act + vec.push_back(0); // reserve() + + // Assert + EXPECT_TRUE(vec[vec.size() - 1] == 0 && vec_capacity1 <= vec.capacity()); +} + +TEST(TestMathVectorLib, test_insert_without_deleted_elements) { + // Arrange + MathVector vec(3); + vec[0] = 1; + vec[1] = 2; + vec[2] = 3; + + // Act + vec.insert(1, 66); + + // Assert + EXPECT_EQ(4, vec.size()); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(66, vec[1]); + EXPECT_EQ(2, vec[2]); + EXPECT_EQ(3, vec[3]); +} + +TEST(TestMathVectorLib, test_insert_with_deleted_elements) { + // Arrange + size_t size = 5; + int arr[5] = { 1, 6, 4, 5, 7 }; + MathVector vec(arr, size); + + // Act + vec.erase(1); + vec.insert(1, 667); + + // Assert + EXPECT_EQ(5, vec.size()); + EXPECT_EQ(1, vec.at(0)); + EXPECT_EQ(667, vec.at(1)); + EXPECT_EQ(4, vec.at(2)); + EXPECT_EQ(5, vec.at(3)); + EXPECT_EQ(7, vec.at(4)); +} + +TEST(TestMathVectorLib, test_insert_with_reserve) { + // Arrange + MathVector vec(3); + size_t vec_capacity = vec.capacity(); + for (size_t i = 0; i < vec_capacity; ++i) { // a capacity + vec.insert(1, 5); + } + + // Act + vec.insert(1, 5); + + // Assert + EXPECT_TRUE(vec[1] == 5 && vec_capacity <= vec.capacity()); +} + +TEST(TestMathVectorLib, test_insert_out_of_range) { + // Arrange + MathVector vec(2); + + // Act + vec.insert(1, 66); + + // Assert + ASSERT_ANY_THROW(vec.insert(5, 999)); +} + +TEST(TestMathVectorLib, test_pop_front_checking_without_difficulties) { + // Arrange + size_t size = 7; + int arr[7] = { 10, 20, 30, 10, 20, 30, 10 }; + MathVector vec(arr, size); + const State* states_vec = vec.states(); + + // Act + vec.pop_front(); + + // Assert + EXPECT_TRUE(states_vec[0] == State::deleted && vec.size() == 7 && vec.deleted() == 1); +} + +TEST(TestMathVectorLib, test_pop_front_with_shrink_to_fit) { + // Arrange + MathVector vec(6); + for (size_t i = 0; i < 1; ++i) { + vec.erase(i); // deleted 1 + } + // Act + vec.pop_front(); + + // Assert + EXPECT_EQ(0, vec.deleted()); +} + +TEST(TestMathVectorLib, test_pop_back_checking_without_difficulties) { + // Arrange + MathVector vec(3); + vec[2] = 99; + const State* states_vec = vec.states(); + + // Act + vec.pop_back(); + + // Assert + EXPECT_TRUE(states_vec[2] == State::empty && vec.size() == 2); +} + +TEST(TestMathVectorLib, test_pop_back_size_equal_0) { + // Arrange + MathVector vec; + + // Act & Assert + ASSERT_ANY_THROW(vec.pop_back()); +} + +TEST(TestMathVectorLib, test_erase_checking_without_difficulties) { + // Arrange + MathVector vec(9); + const State* states_vec = vec.states(); + + // Act + vec.erase(1); + + // Assert + EXPECT_TRUE(states_vec[1] == State::deleted); +} + +TEST(TestMathVectorLib, test_erase_with_shrink_to_fit) { + // Arrange + MathVector vec(20); + + // Act + for (int i = 0; i < 4; ++i) { vec.erase(i); } + + // Assert + EXPECT_EQ(0, vec.deleted()); + EXPECT_EQ(16, vec.size()); +} + +TEST(TestMathVectorLib, test_emplace) { + // Arrange + MathVector vec(3); + + // Act + vec.emplace(0, std::string("hello")); + + // Assert + EXPECT_EQ("hello", vec[0]); +} + +TEST(TestMathVectorLib, test_assign) { + // Arrange + size_t size = 3; + MathVector vec1(size); + vec1[0] = 1; + vec1[1] = 2; + vec1[2] = 3; + + // Act + MathVector vec2; + vec2.assign(vec1); + + // Assert + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(2, vec2[1]); + EXPECT_EQ(3, vec2[2]); +} + +TEST(TestMathVectorLib, test_operator_equal) { + // Arrange + size_t size = 3; + MathVector vec1(size); + vec1[0] = 100; + vec1[1] = 200; + vec1[2] = 369; + + // Act + MathVector vec2; + vec2 = vec1; + + // Assert + EXPECT_EQ(100, vec2[0]); + EXPECT_EQ(200, vec2[1]); + EXPECT_EQ(369, vec2[2]); +} + +TEST(TestMathVectorLib, test_clear) { + // Arrange + size_t size = 5; + MathVector vec(size); + const State* vec_states = vec.states(); + + // Act + vec.clear(); + + // Assert + for (size_t i = 0; i < size; ++i) { EXPECT_EQ(State::empty, vec_states[i]); } + EXPECT_EQ(0, vec.size()); + EXPECT_EQ(0, vec.deleted()); +} + +TEST(TestMathVectorLib, can_compare_with_operator_two_equal_object) { + // Arrange + size_t size = 2; + MathVector vec1(size); + vec1[0] = 5; + vec1[1] = 6; + MathVector vec2(size); + vec2[0] = 5; + vec2[1] = 6; + + // Act & Assert + EXPECT_TRUE(vec1 == vec2); +} + +TEST(TestMathVectorLib, can_compare_with_operator_two_not_equal_object) { + // Arrange + size_t size = 2; + MathVector vec1(size); + vec1[0] = 5; + vec1[1] = 6; + MathVector vec2(size); + vec2[0] = 5; + vec2[1] = 7; + + // Act & Assert + EXPECT_FALSE(vec1 == vec2); +} + +TEST(TestMathVectorLib, test_operator_equal_for_empty_vectors) { + // Arrange + MathVector vec1; + MathVector vec2; + + // Act & Assert + EXPECT_TRUE(vec1 == vec2); +} + +TEST(TestMathVectorLib, can_compare_with_operator_that_says_that_two_objects_are_not_equal_return_true) { + // Arrange + size_t size = 2; + MathVector vec1(size); + vec1[0] = 5; + vec1[1] = 6; + MathVector vec2(size); + vec2[0] = 3; + vec2[1] = -4; + + // Act & Assert + EXPECT_TRUE(vec1 != vec2); +} + +TEST(TestMathVectorLib, can_compare_with_operator_that_says_that_two_objects_are_not_equal_return_fale) { + // Arrange + size_t size = 2; + MathVector vec1(size); + vec1[0] = 5; + vec1[1] = 6; + MathVector vec2(size); + vec2[0] = 5; + vec2[1] = 6; + + // Act & Assert + EXPECT_FALSE(vec1 != vec2); +} + +TEST(TestMathVectorLib, test_reserve_new_capacity_more_than_old_capacity) { + // Arrange + MathVector vec(3); + size_t old_capacity = vec.capacity(); + size_t new_capacity = old_capacity + 10; + + // Act + vec.reserve(new_capacity); + + // Assert + EXPECT_TRUE(vec.capacity() >= new_capacity); +} + +TEST(TestMathVectorLib, test_reserve_no_change_if_new_capacity_less_than_old_capacity) { + // Arrange + MathVector vec(4); + size_t old_capacity = vec.capacity(); + + // Act + vec.reserve(old_capacity - 1); + + // Assert + EXPECT_TRUE(vec.capacity() == old_capacity); +} + +TEST(TestMathVectorLib, test_resize) { + // Arrange + MathVector vec(3); + vec[0] = 10; + vec[1] = 20; + vec[2] = 30; + const State* states = vec.states(); + + // Act + vec.resize(5); + + // Assert + EXPECT_EQ(5, vec.size()); + EXPECT_EQ(10, vec[0]); + EXPECT_EQ(20, vec[1]); + EXPECT_EQ(30, vec[2]); + EXPECT_EQ(busy, states[3]); + EXPECT_EQ(busy, states[4]); +} + +TEST(TestMathVectorLib, test_shrink_to_fit) { + // Arrange + size_t size = 5; + int arr[5] = { 10, 20, 30, 40, 50 }; + MathVector vec(arr, size); + size_t old_capacity = vec.capacity(); + + // Act + vec.erase(1); + vec.erase(3); + vec.shrink_to_fit(); + + // Assert + EXPECT_TRUE(vec.capacity() < old_capacity); + EXPECT_EQ(3, vec.size()); +} + +TEST(TestMathVectorLib, test_shuffle) { + // Arrange + size_t size = 5; + MathVector vec(size); + for (int i = 0; i < size; ++i) { vec[i] = i; } + MathVector old_vec(vec); + + // Act + shuffle(vec); + + // Assert + EXPECT_TRUE(old_vec != vec); +} + +TEST(TestMathVectorLib, test_quick_sort) { + // Arrange + size_t size = 5; + int arr_not_sort[5] = { 5, 3, 4, 1, 2 }; + int arr_sort[5] = { 1, 2, 3, 4, 5 }; + MathVector not_sort_vec(arr_not_sort, size); + MathVector sort_vec(arr_sort, size); + + // Act + quick_sort(not_sort_vec); + + // Assert + EXPECT_TRUE(sort_vec == not_sort_vec); +} + +TEST(TestMathVectorLib, test_find_first) { + // Arrange + size_t size = 5; + int arr[5] = { 7, 3, 5, 3, 9 }; + MathVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(1, find_first(vec, 3)); +} + +TEST(TestMathVectorLib, test_find_last) { + // Arrange + size_t size = 5; + int arr[5] = { 7, 3, 5, 3, 9 }; + MathVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(3, find_last(vec, 3)); +} + +TEST(TestMathVectorLib, test_find_all) { + // Arrange + size_t size = 6; + int arr[6] = { 1, 2, 3, 2, 5, 2 }; + MathVector vec(arr, size); + + // Act + size_t* result = find_all(vec, 2); + + // Assert + EXPECT_TRUE(result[0] == 1 && result[1] == 3 && result[2] == 5); + delete[] result; // ???? +} + +TEST(TestMathVectorLib, test_operator_add_for_int) { + // Arrange + MathVector vec1{ 1, 5, 3 }; + MathVector vec2{ 1, 5, 3 }; + + //Act + MathVector res = vec1 + vec2; + + // Assert + EXPECT_EQ(2, res[0]); + EXPECT_EQ(10, res[1]); + EXPECT_EQ(6, res[2]); +} + +TEST(TestMathVectorLib, test_operator_add_for_double) { + // Arrange + MathVector vec1{ 1.3, 5.7, 3.1 }; + MathVector vec2{ 2.7, 5.2, 9.5 }; + + //Act + MathVector res = vec1 + vec2; + + // Assert + EXPECT_NEAR(4.0, res[0], EPSILON); + EXPECT_NEAR(10.9, res[1], EPSILON); + EXPECT_NEAR(12.6, res[2], EPSILON); +} + +TEST(TestMathVectorLib, test_operator_add_for_different_size_vectors) { + // Arrange + MathVector vec1{ 1.3, 5.7 }; + MathVector vec2{ 2.7, 5.2, 9.5 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 + vec2); +} + +TEST(TestMathVectorLib, test_operator_add_for_double_and_int) { + // Arrange + MathVector vec1{ 1.3, 5.7, 3.1 }; + MathVector vec2{ 2, 5, 9 }; + + //Act + auto res = vec1 + vec2; + + // Assert + EXPECT_NEAR(3.3, res[0], EPSILON); + EXPECT_NEAR(10.7, res[1], EPSILON); + EXPECT_NEAR(12.1, res[2], EPSILON); +} + +TEST(TestMathVectorLib, test_operator_add_for_different_size_vectors_which_have_different_types) { + // Arrange + MathVector vec1{ 1, 5 }; + MathVector vec2{ 2.7, 5.2, 9.5 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 + vec2); +} + +TEST(TestMathVectorLib, states_after_addition) { + // Arrange + MathVector vec1{ 1, 2, 3 }; + MathVector vec2{ 4, 5, 6 }; + + //Act + MathVector res = vec1 + vec2; + + // Assert + for (size_t i = 0; i < res.size(); ++i) { + EXPECT_EQ(State::busy, res.state(i)); + } +} + +TEST(TestMathVectorLib, empty_vectors_addition) { + // Arrange + MathVector vec1; + MathVector vec2; + + //Act + MathVector res = vec1 + vec2; + + // Assert + EXPECT_EQ(0, res.size()); +} + +TEST(TestMathVectorLib, test_operator_sub_for_int) { + // Arrange + MathVector vec1{ 3, 5, -12 }; + MathVector vec2{ 1, 6, 3 }; + + //Act + MathVector res = vec1 - vec2; + + // Assert + EXPECT_EQ(2, res[0]); + EXPECT_EQ(-1, res[1]); + EXPECT_EQ(-15, res[2]); +} + +TEST(TestMathVectorLib, test_operator_sub_for_double) { + // Arrange + MathVector vec1{ 2.7, 5.7, -3.1 }; + MathVector vec2{ 1.3, 5.2, 9.5 }; + + //Act + MathVector res = vec1 - vec2; + + // Assert + EXPECT_NEAR(1.4, res[0], EPSILON); + EXPECT_NEAR(0.5, res[1], EPSILON); + EXPECT_NEAR(-12.6, res[2], EPSILON); +} + +TEST(TestMathVectorLib, test_operator_sub_for_different_size_vectors) { + // Arrange + MathVector vec1{ 1.3, 5.7 }; + MathVector vec2{ 2.7, 5.2, 9.5 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 - vec2); +} + +TEST(TestMathVectorLib, test_operator_sub_for_double_and_int) { + // Arrange + MathVector vec1{ 2.7, 5.7, -3.1 }; + MathVector vec2{ 1, 5, 9 }; + + //Act + auto res = vec1 - vec2; + + // Assert + EXPECT_NEAR(1.7, res[0], EPSILON); + EXPECT_NEAR(0.7, res[1], EPSILON); + EXPECT_NEAR(-12.1, res[2], EPSILON); +} + +TEST(TestMathVectorLib, test_operator_sub_for_different_size_vectors_which_have_different_types) { + // Arrange + MathVector vec1{ 1, 5 }; + MathVector vec2{ 2.7, 5.2, 9.5 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 - vec2); +} + +TEST(TestMathVectorLib, states_after_subtraction) { + // Arrange + MathVector vec1{ 1, 2, 3 }; + MathVector vec2{ 4, 5, 6 }; + + //Act + MathVector res = vec1 - vec2; + + // Assert + for (size_t i = 0; i < res.size(); ++i) { + EXPECT_EQ(State::busy, res.state(i)); + } +} + +TEST(TestMathVectorLib, empty_vectors_subtraction) { + // Arrange + MathVector vec1; + MathVector vec2; + + //Act + MathVector res = vec1 - vec2; + + // Assert + EXPECT_EQ(0, res.size()); +} + +TEST(TestMathVectorLib, test_operator_mult_for_scalar) { + // Arrange + MathVector vec{ 1, 2, 6 }; + + // Act + MathVector result = vec * 2; + + // Assert + EXPECT_EQ(2, result[0]); + EXPECT_EQ(4, result[1]); + EXPECT_EQ(12, result[2]); +} + +TEST(TestMathVectorLib, test_operator_mult_dot_product) { + // Arrange + MathVector vec1{ 1, 2, 6 }; + MathVector vec2{ 3, 1, 5 }; + + // Act & Assert + EXPECT_EQ(35, vec1*vec2); +} + +TEST(TestMathVectorLib, test_operator_mult_which_vectors_have_sizes_not_equal) { + // Arrange + MathVector vec1{ 1, 2, 6 }; + MathVector vec2{ 3, 1, 5, 8 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 * vec2); +} + +TEST(TestMathVectorLib, test_operator_mult_for_scalar_with_different_types) { + // Arrange + MathVector vec{ 1, 2, 6 }; + + // Act + auto result = vec * 2.3; + + // Assert + EXPECT_NEAR(2.3, result[0], EPSILON); + EXPECT_NEAR(4.6, result[1], EPSILON); + EXPECT_NEAR(13.8, result[2], EPSILON); +} + +TEST(TestMathVectorLib, test_operator_mult_dot_product_with_different_types) { + // Arrange + MathVector vec1{ 1, 2, 6 }; + MathVector vec2{ 3.0, 1.1, 5.3 }; + + // Act & Assert + EXPECT_NEAR(37.0, vec1 * vec2, EPSILON); +} + +TEST(TestMathVectorLib, test_operator_mult__with_different_types_which_vectors_have_sizes_not_equal) { + // Arrange + MathVector vec1{ 1, 2, 6 }; + MathVector vec2{ 3, 1, 5, 8 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 * vec2); +} + +TEST(TestMathVectorLib, test_operator_mult_for_different_size_vectors_which_have_different_types) { + // Arrange + MathVector vec1{ 1, 5 }; + MathVector vec2{ 2.7, 5.2, 9.5 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 * vec2); +} + +TEST(TestMathVectorLib, test_operator_add_equal_for_int) { + // Arrange + MathVector vec1{ 1, 5, 3 }; + MathVector vec2{ 2, 5, 9 }; + + //Act + vec1 += vec2; + + // Assert + EXPECT_EQ(3, vec1[0]); + EXPECT_EQ(10, vec1[1]); + EXPECT_EQ(12, vec1[2]); +} + +TEST(TestMathVectorLib, test_operator_add_equal_for_double) { + // Arrange + MathVector vec1{ 1.3, 5.7, 3.1 }; + MathVector vec2{ 2.7, 5.2, 9.5 }; + + //Act + vec1 += vec2; + + // Assert + EXPECT_NEAR(4.0, vec1[0], EPSILON); + EXPECT_NEAR(10.9, vec1[1], EPSILON); + EXPECT_NEAR(12.6, vec1[2], EPSILON); +} + +TEST(TestMathVectorLib, test_operator_add_equal_for_different_size_vectors) { + // Arrange + MathVector vec1{ 1.3, 5.7, 9.5 }; + MathVector vec2{ 2.7, 5.2 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 += vec2); +} + +TEST(TestMathVectorLib, test_operator_sub_equal_for_int) { + // Arrange + MathVector vec1{ 3, 5, -12 }; + MathVector vec2{ 1, 6, 3 }; + + //Act + vec1 -= vec2; + + // Assert + EXPECT_EQ(2, vec1[0]); + EXPECT_EQ(-1, vec1[1]); + EXPECT_EQ(-15, vec1[2]); +} + +TEST(TestMathVectorLib, test_operator_sub_equal_for_double) { + // Arrange + MathVector vec1{ 2.7, 5.7, -3.1 }; + MathVector vec2{ 1.3, 5.2, 9.5 }; + + //Act + vec1 -= vec2; + + // Assert + EXPECT_NEAR(1.4, vec1[0], EPSILON); + EXPECT_NEAR(0.5, vec1[1], EPSILON); + EXPECT_NEAR(-12.6, vec1[2], EPSILON); +} + +TEST(TestMathVectorLib, test_operator_sub_equal_for_different_size_vectors) { + // Arrange + MathVector vec1{ 1.3, 5.7 }; + MathVector vec2{ 2.7, 5.2, 9.5 }; + + // Act & Assert + ASSERT_ANY_THROW(vec1 -= vec2); +} + +TEST(TestMathVectorLib, test_operator_mult_equal_for_scalar) { + // Arrange + MathVector vec{ 1, 2, 6 }; + + // Act + vec *= 3; + + // Assert + EXPECT_EQ(3, vec[0]); + EXPECT_EQ(6, vec[1]); + EXPECT_EQ(18, vec[2]); +} + +TEST(TestMathVectorLib, test_length_of_the_double_vector) { + // Arrange + MathVector vec{ 3, 4 }; + + // Act & Assert + EXPECT_EQ(5.0, vec.length()); +} + +TEST(TestMathVectorLib, test_length_of_the_float_vector) { + // Arrange + MathVector vec{ 3.0f, 4.0f }; + + // Act & Assert + EXPECT_NEAR(5.0, vec.length(), EPSILON); +} \ No newline at end of file diff --git a/tests/test_matrix.cpp b/tests/test_matrix.cpp new file mode 100644 index 00000000..5490f318 --- /dev/null +++ b/tests/test_matrix.cpp @@ -0,0 +1,367 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_matrix/matrix.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestMatrixLib, default_constructor) { + // Arrange & Act + Matrix m; + + // Assert + EXPECT_EQ(0, m.rows()); + EXPECT_EQ(0, m.cols()); +} + +TEST(TestMatrixLib, constructor_with_size) { + // Arrange & Act + Matrix m(3, 4); + + // Assert + EXPECT_EQ(3, m.rows()); + EXPECT_EQ(4, m.cols()); + for (size_t i = 0; i < m.rows(); ++i) { + for (size_t j = 0; j < m.cols(); ++j) { + EXPECT_EQ(0, m.at(i, j)); + } + } +} + +TEST(TestMatrixLib, constructor_with_initializer_list_of_int_vectors_with_equal_size) { + // Arrange + MathVector vec1{ 1, 2, 3 }; + MathVector vec2{ 4, 5, 6 }; + int number = 1; + + // Act + Matrix m{ vec1, vec2 }; + + // Assert + EXPECT_EQ(2, m.rows()); + EXPECT_EQ(3, m.cols()); + for (size_t i = 0; i < m.rows(); ++i) { + for (size_t j = 0; j < m.cols(); ++j) { + EXPECT_EQ(number, m.at(i, j)); + number++; + } + } +} + +TEST(TestMatrixLib, constructor_with_initializer_list_of_double_vectors_with_equal_size) { + // Arrange + MathVector vec1{ 1.1, 2.2 }; + MathVector vec2{ 4.4, 5.5 }; + + // Act + Matrix m{ vec1, vec2 }; + + // Assert + EXPECT_EQ(2, m.rows()); + EXPECT_EQ(2, m.cols()); + EXPECT_NEAR(1.1, m.at(0, 0), EPSILON); + EXPECT_NEAR(2.2, m.at(0, 1), EPSILON); + EXPECT_NEAR(4.4, m.at(1, 0), EPSILON); + EXPECT_NEAR(5.5, m.at(1, 1), EPSILON); +} + +TEST(TestMatrixLib, constructor_with_initializer_list_of_vectors_with_different_size) { + // Arrange + MathVector vec1{ 1, 2 }; + MathVector vec2{ 4, 5, 6 }; + + // Act & Assert + ASSERT_ANY_THROW((Matrix{ vec1, vec2 })); +} + +TEST(TestMatrixLib, constructor_with_initializer_list_without_vectors_with_int) { + // Arrange & Act + int number = 1; + Matrix m{ { 1, 2, 3 }, { 4, 5, 6 } }; + + // Assert + EXPECT_EQ(2, m.rows()); + EXPECT_EQ(3, m.cols()); + for (size_t i = 0; i < m.rows(); ++i) { + for (size_t j = 0; j < m.cols(); ++j) { + EXPECT_EQ(number, m.at(i, j)); + number++; + } + } +} + +TEST(TestMatrixLib, constructor_with_empty_initializer_list) { + // Arrange & Act + Matrix matrix{}; + + // Assert + EXPECT_EQ(0, matrix.rows()); + EXPECT_EQ(0, matrix.cols()); +} + +TEST(TestMatrixLib, copy_constructor) { + // Arrange + int number = 1; + Matrix m{ { 1, 2, 3 }, { 4, 5, 6 }, {7, 8, 9}, {10, 11, 12} }; + + // Act + Matrix matrix(m); + + // Assert + EXPECT_EQ(4, matrix.rows()); + EXPECT_EQ(3, matrix.cols()); + for (size_t i = 0; i < matrix.rows(); ++i) { + for (size_t j = 0; j < matrix.cols(); ++j) { + EXPECT_EQ(number, matrix.at(i, j)); + number++; + } + } +} + +TEST(TestMatrixLib, test_at_row_out_of_range) { + // Arrange & Act + Matrix matrix(2, 2); + + // Assert + ASSERT_ANY_THROW(matrix.at(2, 0)); +} + +TEST(TestMatrixLib, test_at_col_out_of_range) { + // Arrange & Act + Matrix matrix(2, 2); + + // Assert + ASSERT_ANY_THROW(matrix.at(0, 4)); +} + +TEST(TestMatrixLib, test_element_access) { + // Arrange & Act + Matrix matrix(2, 3); + matrix[0][0] = 10; + matrix[0][1] = 20; + matrix[1][2] = 30; + + // Assert + EXPECT_EQ(10, matrix[0][0]); + EXPECT_EQ(20, matrix[0][1]); + EXPECT_EQ(30, matrix[1][2]); +} + +TEST(TestMatrixLib, test_operator_equal) { + // Arrange + int number = 1; + Matrix m{ { 1, 2, 3 }, { 4, 5, 6 }, {7, 8, 9}, {10, 11, 12} }; + + // Act + Matrix matrix = m; + + // Assert + EXPECT_EQ(4, matrix.rows()); + EXPECT_EQ(3, matrix.cols()); + for (size_t i = 0; i < matrix.rows(); ++i) { + for (size_t j = 0; j < matrix.cols(); ++j) { + EXPECT_EQ(number, matrix.at(i, j)); + number++; + } + } +} + +TEST(TestMatrixLib, test_transpose) { + // Arrange + int number = 1; + Matrix matrix{ { 1, 2, 3 }, { 4, 5, 6 } }; + + // Act + matrix.transpose(); + + // Assert + EXPECT_EQ(1, matrix[0][0]); + EXPECT_EQ(4, matrix[0][1]); + EXPECT_EQ(2, matrix[1][0]); + EXPECT_EQ(5, matrix[1][1]); + EXPECT_EQ(3, matrix[2][0]); + EXPECT_EQ(6, matrix[2][1]); +} + +TEST(TestMatrixLib, test_double_transpose_returns_original) { + // Arrange + Matrix matrix{ { 1, 2, 3 }, { 4, 5, 6 } }; + Matrix original = matrix; + + // Act + matrix.transpose(); + matrix.transpose(); + + // Assert + EXPECT_TRUE(matrix == original); +} + +TEST(TestMatrixLib, test_add_to_int_matrixes) { + // Arrange + Matrix matrix1{ { 1, 2, 3 }, { 4, 5, 6 } }; + Matrix matrix2{ { 1, 2, 3 }, { 4, 5, 6 } }; + int number = 1; + + // Act + Matrix result = matrix1 + matrix2; + + // Assert + EXPECT_EQ(2, result.rows()); + EXPECT_EQ(3, result.cols()); + for (size_t i = 0; i < result.rows(); ++i) { + for (size_t j = 0; j < result.cols(); ++j) { + EXPECT_EQ(number * 2, result[i][j]); + number++; + } + } +} + +TEST(TestMatrixLib, test_add_to_int_matrixes_with_different_rows) { + // Arrange + Matrix matrix1{ { 1, 2, 3 }, { 4, 5, 6 } }; + Matrix matrix2{ { 1, 2, 3 }, { 4, 5, 6 }, { 4, 5, 6 } }; + + // Act & Assert + ASSERT_ANY_THROW(matrix1 + matrix2); +} + +TEST(TestMatrixLib, test_add_to_int_matrixes_with_different_cols) { + // Arrange + Matrix matrix1{ { 1, 2, 3 }, { 4, 5, 6 } }; + Matrix matrix2{ { 1, 2, 3, 1 }, { 4, 5, 6, 1 } }; + + // Act & Assert + ASSERT_ANY_THROW(matrix1 + matrix2); +} + +TEST(TestMatrixLib, test_sub_to_int_matrixes) { + // Arrange + Matrix matrix1{ { 1, 2, 3 }, { 4, 5, 6 } }; + Matrix matrix2{ { 1, 2, 3 }, { 4, 5, 6 } }; + + // Act + Matrix result = matrix1 - matrix2; + + // Assert + EXPECT_EQ(2, result.rows()); + EXPECT_EQ(3, result.cols()); + for (size_t i = 0; i < result.rows(); ++i) { + for (size_t j = 0; j < result.cols(); ++j) { + EXPECT_EQ(0, result[i][j]); + } + } +} + +TEST(TestMatrixLib, test_sub_to_int_matrixes_with_different_rows) { + // Arrange + Matrix matrix1{ { 1, 2, 3 }, { 4, 5, 6 } }; + Matrix matrix2{ { 1, 2, 3 }, { 4, 5, 6 }, { 4, 5, 6 } }; + + // Act & Assert + ASSERT_ANY_THROW(matrix1 - matrix2); +} + +TEST(TestMatrixLib, test_sub_to_int_matrixes_with_different_cols) { + // Arrange + Matrix matrix1{ { 1, 2, 3 }, { 4, 5, 6 } }; + Matrix matrix2{ { 1, 2, 3, 1 }, { 4, 5, 6, 1 } }; + + // Act & Assert + ASSERT_ANY_THROW(matrix1 - matrix2); +} + +TEST(TestMatrixLib, test_mult_a_matrix_by_a_scalar) { + // Arrange + Matrix matrix1{ { 1, 2, 3 }, { 4, 5, 6 } }; + int number = 1; + + // Act + Matrix result = matrix1 * 2; + + // Assert + EXPECT_EQ(2, result.rows()); + EXPECT_EQ(3, result.cols()); + for (size_t i = 0; i < result.rows(); ++i) { + for (size_t j = 0; j < result.cols(); ++j) { + EXPECT_EQ(number * 2, result[i][j]); + number++; + } + } +} + +TEST(TestMatrixLib, test_mult_a_matrix_by_a_zero_scalar) { + // Arrange + Matrix matrix1{ { 1, 2, 3 }, { 4, 5, 6 } }; + int number = 1; + + // Act + Matrix result = matrix1 * 0; + + // Assert + EXPECT_EQ(2, result.rows()); + EXPECT_EQ(3, result.cols()); + for (size_t i = 0; i < result.rows(); ++i) { + for (size_t j = 0; j < result.cols(); ++j) { + EXPECT_EQ(0, result[i][j]); + } + } +} + +TEST(TestMatrixLib, test_mult_a_matrix_by_a_vector) { + // Arrange + Matrix matrix{ { 1, 2 }, { 3, 4 }, { 5, 6 } }; + MathVector vector{ 10, 20 }; + + // Act + MathVector result = matrix * vector; + + // Assert + EXPECT_EQ(50, result[0]); + EXPECT_EQ(110, result[1]); + EXPECT_EQ(170, result[2]); +} + +TEST(TestMatrixLib, test_mult_a_int_matrix_by_a_int_matrix_with_correct_equal_size) { + // Arrange + Matrix A{ {1, 2}, {3, 4} }; + Matrix B{ {2, 0}, {1, 2} }; + + // Act + Matrix C = A * B; + + // Assert + EXPECT_EQ(2, C.rows()); + EXPECT_EQ(2, C.cols()); + EXPECT_EQ(1 * 2 + 2 * 1, C.at(0, 0)); + EXPECT_EQ(1 * 0 + 2 * 2, C.at(0, 1)); + EXPECT_EQ(3 * 2 + 4 * 1, C.at(1, 0)); + EXPECT_EQ(3 * 0 + 4 * 2, C.at(1, 1)); +} + +TEST(TestMatrixLib, test_mult_a_int_matrix_by_a_int_matrix_with_correct_not_equal_size) { + // Arrange + Matrix A{ {2, 3, 4}, {1, 2, 0} }; + Matrix B{ {1, 0}, {2, 2}, {1, 4} }; + + // Act + Matrix C = A * B; + + // Assert + EXPECT_EQ(2, C.rows()); + EXPECT_EQ(2, C.cols()); + EXPECT_EQ(12, C.at(0, 0)); + EXPECT_EQ(22, C.at(0, 1)); + EXPECT_EQ(5, C.at(1, 0)); + EXPECT_EQ(4, C.at(1, 1)); +} + +TEST(TestMatrixLib, test_mult_a_int_matrix_by_a_int_matrix_without_correct_size) { + // Arrange + Matrix A{ {1, 2}, {3, 4} }; + Matrix B{ {2, 0}, {1, 2}, {3, 4} }; + + // Act & Assert + ASSERT_ANY_THROW(A * B); +} \ No newline at end of file diff --git a/tests/test_node.cpp b/tests/test_node.cpp new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_point.cpp b/tests/test_point.cpp new file mode 100644 index 00000000..a74b0a8f --- /dev/null +++ b/tests/test_point.cpp @@ -0,0 +1,73 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_point/point.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestPointLib, default_constructor) { + // Arrange () + Point a; + + // Act & Assert + EXPECT_EQ(0, a.get_oy()); + EXPECT_EQ(0, a.get_ox()); // +} + +TEST(TestPointLib, parameterized_constructor) { + // Arrange & act + Point a(5, 27); + + // Assert () + EXPECT_EQ(5, a.get_ox()); + EXPECT_EQ(27, a.get_oy()); +} + +TEST(TestPointLib, copy_constructor_without_throw) { + // Arrange () + Point a(-3, 72); + + // Act () + Point b(a); + + // Assert () + EXPECT_EQ(-3, b.get_ox()); + EXPECT_EQ(72, b.get_oy()); // +} + +TEST(TestPointLib, copy_constructor_with_throw) { + // Arrange + Point* null_pointer = nullptr; + + // Act & Assert + ASSERT_ANY_THROW(Point a(*null_pointer)); +} + +TEST(TestPointLib, can_compare_with_operator_two_equal_object) { + // Arrange + Point a(1, 2); + Point b(1, 2); + + // Act & Assert + EXPECT_TRUE(a == b); +} + +TEST(TestPointLib, can_compare_with_operator_two_not_equal_object) { + // Arrange + Point a(1, 2); + Point b(4, 2); + + // Act & Assert + EXPECT_FALSE(a == b); +} + +TEST(TestPointLib, can_distance_to) { + // Arrange + Point a(1, 2); + Point b(4, 6); + + // Act & Assert + EXPECT_NEAR(5.0, a.distance_to(b), EPSILON); //, +} \ No newline at end of file diff --git a/tests/test_point3d.cpp b/tests/test_point3d.cpp new file mode 100644 index 00000000..5c95b471 --- /dev/null +++ b/tests/test_point3d.cpp @@ -0,0 +1,76 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_point3d/point3d.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestPoint3dLib, default_constructor) { + // Arrange () + Point3D a; + + // Assert & Act + EXPECT_EQ(0, a.get_ox()); // + EXPECT_EQ(0, a.get_oy()); + EXPECT_EQ(0, a.get_oz()); +} + +TEST(TestPoint3dLib, parameterized_constructor) { + // Arrange + Point3D a(5, 27, -45); + + // Assert & Act + EXPECT_EQ(5, a.get_ox()); // + EXPECT_EQ(27, a.get_oy()); + EXPECT_EQ(-45, a.get_oz()); +} + +TEST(TestPoint3dLib, copy_constructor_without_throw) { + // Arrange + Point3D a(-3, 72, 15); + + // Act + Point3D b(a); + + // Assert + EXPECT_EQ(-3, b.get_ox()); // + EXPECT_EQ(72, b.get_oy()); + EXPECT_EQ(15, b.get_oz()); +} + +TEST(TestPoint3dLib, copy_constructor_with_throw) { + // Arrange + Point3D* null_pointer = nullptr; + + // Act & Assert + ASSERT_ANY_THROW(Point3D a(*null_pointer)); +} + +TEST(TestPoint3dLib, can_compare_with_operator_two_equal_object) { + // Arrange + Point3D a(1, 2, 3); + Point3D b(1, 2, 3); + + // Act & Assert + EXPECT_TRUE(a == b); +} + +TEST(TestPoint3dLib, can_compare_with_operator_two_not_equal_object) { + // Arrange + Point3D a(1, 2, 7); + Point3D b(4, 2, 7); + + // Act & Assert + EXPECT_FALSE(a == b); +} + +TEST(TestPoint3dLib, can_distance_to) { + // Arrange + Point3D a(0, -3, 3); + Point3D b(3, 1, 3); + + // Act & Assert + EXPECT_NEAR(5.0, a.distance_to(b), EPSILON); //, +} \ No newline at end of file diff --git a/tests/test_queue.cpp b/tests/test_queue.cpp new file mode 100644 index 00000000..e28d2ee7 --- /dev/null +++ b/tests/test_queue.cpp @@ -0,0 +1,221 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_queue/queue.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestQueueLib, default_constructor_creates_empty_queue) { + // Arrange + Queue queue; + + // Act & Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_FALSE(queue.is_full()); + EXPECT_EQ(0, queue.count()); + EXPECT_EQ(Queue::RESERVE_MEMORY, queue.capacity()); +} + +TEST(TestQueueLib, constructor_with_size) { + // Arrange + size_t size = 10; + Queue queue(size); + + // Act & Assert + EXPECT_EQ(size, queue.capacity()); + EXPECT_TRUE(queue.is_empty()); + EXPECT_FALSE(queue.is_full()); +} + +TEST(TestQueueLib, copy_constructor_without_difficulties) { + // Arrange + size_t size = 10; + Queue queue1(size); + + // Act + Queue queue2(queue1); + + // Assert + EXPECT_EQ(queue1.count(), queue2.count()); + EXPECT_EQ(queue1.is_empty(), queue2.is_empty()); + EXPECT_EQ(queue1.is_full(), queue2.is_full()); +} + +TEST(TestQueueLib, copy_constructor_with_overflow_head_and_tail) { + // Arrange + Queue queue1(3); + + // Act + queue1.push(1); + queue1.push(2); + queue1.push(3); + queue1.pop(); + queue1.push(4); + Queue queue2(queue1); + + // Assert + EXPECT_EQ(queue1.count(), queue2.count()); + EXPECT_EQ(queue1.head(), queue2.head()); + EXPECT_EQ(queue1.tail(), queue2.tail()); +} + +TEST(TestQueueLib, test_push_and_check_head_and_tail_without_an_overflowing_queue) { + // Arrange + Queue queue; + + // Act + queue.push(10); + queue.push(20); + queue.push(30); + + // Assert + EXPECT_EQ(3, queue.count()); + EXPECT_EQ(10, queue.head()); + EXPECT_EQ(30, queue.tail()); + EXPECT_FALSE(queue.is_empty()); +} + +TEST(TestQueueLib, test_push_and_check_head_and_tail_with_an_overflowing_queue) { + // Arrange + Queue queue(3); + + // Act + queue.push(10); + queue.push(20); + queue.push(30); + + // Assert + EXPECT_ANY_THROW(queue.push(40)); +} + +TEST(TestQueueLib, test_pop_without_an_underflowing_queue) { + // Arrange + Queue queue; + queue.push(1); + queue.push(2); + queue.push(3); + + // Act + queue.pop(); + + // Assert + EXPECT_FALSE(queue.is_empty()); + EXPECT_EQ(2, queue.count()); + EXPECT_EQ(2, queue.head()); + EXPECT_EQ(3, queue.tail()); +} + +TEST(TestQueueLib, test_pop_all_elements_in_queue_without_an_underflowing_stack) { + // Arrange + Queue queue; + queue.push(1); + + // Act + queue.pop(); + + // Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_EQ(0, queue.count()); +} + +TEST(TestQueueLib, test_pop_with_an_underflowing_queue) { + // Arrange + Queue queue; + + // Act & Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_ANY_THROW(queue.pop()); +} + +TEST(TestQueueLib, test_clear) { + // Arrange + Queue queue; + queue.push(1); + queue.push(2); + + // Act + queue.clear(); + + // Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_EQ(0, queue.count()); +} + +TEST(TestQueueLib, test_is_full_checking_for_a_full_queue) { + // Arrange + Queue queue(3); + queue.push(1); + queue.push(2); + queue.push(3); + + // Act & Assert + EXPECT_TRUE(queue.is_full()); + EXPECT_ANY_THROW(queue.push(4)); +} + +TEST(TestQueueLib, test_is_full_checking_for_an_empty_queue) { + // Arrange + Queue queue(3); + + // Act & Assert + EXPECT_FALSE(queue.is_full()); + EXPECT_ANY_THROW(queue.pop()); +} + +TEST(TestQueueLib, test_is_empty_checking_for_a_full_queue) { + // Arrange + Queue queue(3); + queue.push(1); + queue.push(2); + queue.push(3); + + // Act & Assert + EXPECT_FALSE(queue.is_empty()); + EXPECT_ANY_THROW(queue.push(4)); +} + +TEST(TestQueueLib, test_is_empty_checking_for_an_empty_queue) { + // Arrange + Queue queue(3); + + // Act & Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_ANY_THROW(queue.pop()); +} + +TEST(TestQueueLib, test_push_after_overflow_tail) { + // Arrange + Queue queue(3); + + // Act + queue.push(1); + queue.push(2); + queue.pop(); + queue.pop(); + queue.push(100); + queue.push(200); + + // Assert + EXPECT_EQ(2, queue.count()); + EXPECT_EQ(100, queue.head()); + EXPECT_EQ(200, queue.tail()); +} + +TEST(TestQueueLib, test_push_after_overflow_head) { + // Arrange + Queue queue(3); + + // Act + queue.push(1); + queue.push(2); + queue.push(3); + queue.pop(); + queue.push(555); + + // Assert + EXPECT_EQ(3, queue.count()); + EXPECT_EQ(2, queue.head()); + EXPECT_EQ(555, queue.tail()); +} \ No newline at end of file diff --git a/tests/test_queue_list.cpp b/tests/test_queue_list.cpp new file mode 100644 index 00000000..6ef0bc32 --- /dev/null +++ b/tests/test_queue_list.cpp @@ -0,0 +1,221 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_queue_list/queue_list.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestQueueListLib, default_constructor_creates_empty_queue) { + // Arrange + QueueList queue; + + // Act & Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_FALSE(queue.is_full()); + EXPECT_EQ(0, queue.count()); + EXPECT_EQ(QueueList::RESERVE_MEMORY, queue.capacity()); +} + +TEST(TestQueueListLib, constructor_with_size) { + // Arrange + size_t size = 10; + QueueList queue(size); + + // Act & Assert + EXPECT_EQ(size, queue.capacity()); + EXPECT_TRUE(queue.is_empty()); + EXPECT_FALSE(queue.is_full()); +} + +TEST(TestQueueListLib, copy_constructor_without_difficulties) { + // Arrange + size_t size = 10; + QueueList queue1(size); + + // Act + QueueList queue2(queue1); + + // Assert + EXPECT_EQ(queue1.count(), queue2.count()); + EXPECT_EQ(queue1.is_empty(), queue2.is_empty()); + EXPECT_EQ(queue1.is_full(), queue2.is_full()); +} + +TEST(TestQueueListLib, copy_constructor_with_overflow_head_and_tail) { + // Arrange + QueueList queue1(3); + + // Act + queue1.push(1); + queue1.push(2); + queue1.push(3); + queue1.pop(); + queue1.push(4); + QueueList queue2(queue1); + + // Assert + EXPECT_EQ(queue1.count(), queue2.count()); + EXPECT_EQ(queue1.head(), queue2.head()); + EXPECT_EQ(queue1.tail(), queue2.tail()); +} + +TEST(TestQueueListLib, test_push_and_check_head_and_tail_without_an_overflowing_queue) { + // Arrange + QueueList queue; + + // Act + queue.push(10); + queue.push(20); + queue.push(30); + + // Assert + EXPECT_EQ(3, queue.count()); + EXPECT_EQ(10, queue.head()); + EXPECT_EQ(30, queue.tail()); + EXPECT_FALSE(queue.is_empty()); +} + +TEST(TestQueueListLib, test_push_and_check_head_and_tail_with_an_overflowing_queue) { + // Arrange + QueueList queue(3); + + // Act + queue.push(10); + queue.push(20); + queue.push(30); + + // Assert + EXPECT_ANY_THROW(queue.push(40)); +} + +TEST(TestQueueListLib, test_pop_without_an_underflowing_queue) { + // Arrange + QueueList queue; + queue.push(1); + queue.push(2); + queue.push(3); + + // Act + queue.pop(); + + // Assert + EXPECT_FALSE(queue.is_empty()); + EXPECT_EQ(2, queue.count()); + EXPECT_EQ(2, queue.head()); + EXPECT_EQ(3, queue.tail()); +} + +TEST(TestQueueListLib, test_pop_all_elements_in_queue_without_an_underflowing_stack) { + // Arrange + QueueList queue; + queue.push(1); + + // Act + queue.pop(); + + // Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_EQ(0, queue.count()); +} + +TEST(TestQueueListLib, test_pop_with_an_underflowing_queue) { + // Arrange + QueueList queue; + + // Act & Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_ANY_THROW(queue.pop()); +} + +TEST(TestQueueListLib, test_clear) { + // Arrange + QueueList queue; + queue.push(1); + queue.push(2); + + // Act + queue.clear(); + + // Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_EQ(0, queue.count()); +} + +TEST(TestQueueListLib, test_is_full_checking_for_a_full_queue) { + // Arrange + QueueList queue(3); + queue.push(1); + queue.push(2); + queue.push(3); + + // Act & Assert + EXPECT_TRUE(queue.is_full()); + EXPECT_ANY_THROW(queue.push(4)); +} + +TEST(TestQueueListLib, test_is_full_checking_for_an_empty_queue) { + // Arrange + QueueList queue(3); + + // Act & Assert + EXPECT_FALSE(queue.is_full()); + EXPECT_ANY_THROW(queue.pop()); +} + +TEST(TestQueueListLib, test_is_empty_checking_for_a_full_queue) { + // Arrange + QueueList queue(3); + queue.push(1); + queue.push(2); + queue.push(3); + + // Act & Assert + EXPECT_FALSE(queue.is_empty()); + EXPECT_ANY_THROW(queue.push(4)); +} + +TEST(TestQueueListLib, test_is_empty_checking_for_an_empty_queue) { + // Arrange + QueueList queue(3); + + // Act & Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_ANY_THROW(queue.pop()); +} + +TEST(TestQueueListLib, test_push_after_overflow_tail) { + // Arrange + QueueList queue(3); + + // Act + queue.push(1); + queue.push(2); + queue.pop(); + queue.pop(); + queue.push(100); + queue.push(200); + + // Assert + EXPECT_EQ(2, queue.count()); + EXPECT_EQ(100, queue.head()); + EXPECT_EQ(200, queue.tail()); +} + +TEST(TestQueueListLib, test_push_after_overflow_head) { + // Arrange + QueueList queue(3); + + // Act + queue.push(1); + queue.push(2); + queue.push(3); + queue.pop(); + queue.push(555); + + // Assert + EXPECT_EQ(3, queue.count()); + EXPECT_EQ(2, queue.head()); + EXPECT_EQ(555, queue.tail()); +} \ No newline at end of file diff --git a/tests/test_sphere.cpp b/tests/test_sphere.cpp new file mode 100644 index 00000000..7e3a1e7f --- /dev/null +++ b/tests/test_sphere.cpp @@ -0,0 +1,55 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_sphere/sphere.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestSphereLib, default_constructor) { + // Arrange + Sphere A; + Point3D b; + + // Act & Assert + EXPECT_EQ(b, A.get_center()); // + EXPECT_EQ(1, A.get_radius()); +} + +TEST(TestSphereLib, parameterized_constructor_with_normal_radius) { + // Arrange + Point3D A(5, 27, 14); + Sphere C(A, 6); + + // Act & Assert + EXPECT_EQ(A, C.get_center()); // + EXPECT_EQ(6, C.get_radius()); +} +TEST(TestSphereLib, parameterized_constructor_with_radius_less_than_zero) { + // Arrange + Point3D a(7, 6, 14); + + // Act & Assert + ASSERT_ANY_THROW( Sphere C(a, -1)); +} + +TEST(TestSphereLib, copy_constructor_without_throw) { + // Arrange + Point3D C(-4, 10, 54); + Sphere A(C, 7); + + // Act + Sphere B(A); + + // Assert + EXPECT_EQ(C, B.get_center()); // + EXPECT_EQ(7, B.get_radius()); +} + +TEST(TestSphereLib, copy_constructor_with_throw) { + // Arrange + Sphere* null_pointer = nullptr; + // Act & Assert + ASSERT_ANY_THROW( Sphere C(*null_pointer)); +} \ No newline at end of file diff --git a/tests/test_stack.cpp b/tests/test_stack.cpp new file mode 100644 index 00000000..04a4acb7 --- /dev/null +++ b/tests/test_stack.cpp @@ -0,0 +1,182 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_stack/stack.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestStackLib, default_constructor_creates_empty_stack) { + // Arrange + Stack stack; + + // Act & Assert + EXPECT_EQ(0, stack.count()); + EXPECT_EQ(20, stack.capacity()); + EXPECT_TRUE(stack.is_empty()); + EXPECT_FALSE(stack.is_full()); +} + +TEST(TestStackLib, constructor_with_capacity) { + // Arrange + size_t capacity = 10; + Stack stack(capacity); + + // Act & Assert + EXPECT_EQ(0, stack.count()); + EXPECT_EQ(capacity, stack.capacity()); + EXPECT_TRUE(stack.is_empty()); + EXPECT_FALSE(stack.is_full()); +} + +TEST(TestStackLib, copy_constructor) { + // Arrange + size_t capacity = 10; + Stack stack1(capacity); + stack1.push(10); + stack1.push(20); + + // Act + Stack stack2(stack1); + + // Assert + EXPECT_EQ(stack1.count(), stack2.count()); + EXPECT_EQ(stack1.capacity(), stack2.capacity()); + EXPECT_EQ(stack1.is_empty(), stack2.is_empty()); + EXPECT_EQ(stack1.is_full(), stack2.is_full()); +} + +TEST(TestStackLib, test_push_and_top_without_an_overflowing_stack) { + // Arrange + Stack stack; + + // Act + stack.push(10); + stack.push(20); + + // Assert + EXPECT_FALSE(stack.is_empty()); + EXPECT_EQ(2, stack.count()); + EXPECT_EQ(20, stack.top()); +} + +TEST(TestStackLib, test_push_with_an_overflowing_stack) { + // Arrange + Stack stack(2); + + // Act + stack.push(10); + stack.push(20); + + // Assert + EXPECT_TRUE(stack.is_full()); + EXPECT_ANY_THROW(stack.push(30)); +} + +TEST(TestStackLib, test_top_with_empty_stack) { + // Arrange + Stack stack; + + // Act & Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_ANY_THROW(stack.top()); +} + +TEST(TestStackLib, test_pop_not_all_elements_in_stack_and_top_without_an_underflowing_stack) { + // Arrange + Stack stack; + stack.push(1); + stack.push(2); + stack.push(3); + + // Act + stack.pop(); + + // Assert + EXPECT_FALSE(stack.is_empty()); + EXPECT_EQ(2, stack.count()); + EXPECT_EQ(2, stack.top()); +} + +TEST(TestStackLib, test_pop_all_elements_in_stack_and_top_without_an_underflowing_stack) { + // Arrange + Stack stack; + stack.push(1); + + // Act + stack.pop(); + + // Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_EQ(0, stack.count()); + EXPECT_ANY_THROW(stack.top()); +} + +TEST(TestStackLib, test_pop_with_an_underflowing_stack) { + // Arrange + Stack stack; + + // Act & Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_ANY_THROW(stack.pop()); +} + +TEST(TestStackLib, test_clear) { + // Arrange + Stack stack; + stack.push(1); + stack.push(2); + stack.push(3); + + // Act + stack.clear(); + + // Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_EQ(0, stack.count()); + EXPECT_ANY_THROW(stack.top()); + EXPECT_NO_THROW(stack.push(10)); +} + +TEST(TestStackLib, test_is_full_checking_for_a_full_stack) { + // Arrange + Stack stack(3); + stack.push(1); + stack.push(2); + stack.push(3); + + // Act & Assert + EXPECT_TRUE(stack.is_full()); + EXPECT_ANY_THROW(stack.push(4)); +} + +TEST(TestStackLib, test_is_full_checking_for_an_empty_stack) { + // Arrange + Stack stack(3); + + // Act & Assert + EXPECT_FALSE(stack.is_full()); + EXPECT_ANY_THROW(stack.pop()); +} + +TEST(TestStackLib, test_is_empty_checking_for_a_full_stack) { + // Arrange + Stack stack(3); + stack.push(1); + stack.push(2); + stack.push(3); + + // Act & Assert + EXPECT_FALSE(stack.is_empty()); + EXPECT_ANY_THROW(stack.push(4)); +} + +TEST(TestStackLib, test_is_empty_checking_for_an_empty_stack) { + // Arrange + Stack stack(3); + + // Act & Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_ANY_THROW(stack.pop()); +} \ No newline at end of file diff --git a/tests/test_stack_list.cpp b/tests/test_stack_list.cpp new file mode 100644 index 00000000..d3b61511 --- /dev/null +++ b/tests/test_stack_list.cpp @@ -0,0 +1,182 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_stack_list/stack_list.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestStackListLib, default_constructor_creates_empty_stack) { + // Arrange + StackList stack; + + // Act & Assert + EXPECT_EQ(0, stack.count()); + EXPECT_EQ(StackList::RESERVE_MEMORY, stack.capacity()); + EXPECT_TRUE(stack.is_empty()); + EXPECT_FALSE(stack.is_full()); +} + +TEST(TestStackListLib, constructor_with_capacity) { + // Arrange + size_t capacity = 10; + StackList stack(capacity); + + // Act & Assert + EXPECT_EQ(0, stack.count()); + EXPECT_EQ(capacity, stack.capacity()); + EXPECT_TRUE(stack.is_empty()); + EXPECT_FALSE(stack.is_full()); +} + +TEST(TestStackListLib, copy_constructor) { + // Arrange + size_t capacity = 10; + StackList stack1(capacity); + stack1.push(10); + stack1.push(20); + + // Act + StackList stack2(stack1); + + // Assert + EXPECT_EQ(stack1.count(), stack2.count()); + EXPECT_EQ(stack1.capacity(), stack2.capacity()); + EXPECT_EQ(stack1.is_empty(), stack2.is_empty()); + EXPECT_EQ(stack1.is_full(), stack2.is_full()); +} + +TEST(TestStackListLib, test_push_and_top_without_an_overflowing_stack) { + // Arrange + StackList stack; + + // Act + stack.push(10); + stack.push(20); + + // Assert + EXPECT_FALSE(stack.is_empty()); + EXPECT_EQ(2, stack.count()); + EXPECT_EQ(20, stack.top()); +} + +TEST(TestStackListLib, test_push_with_an_overflowing_stack) { + // Arrange + StackList stack(2); + + // Act + stack.push(10); + stack.push(20); + + // Assert + EXPECT_TRUE(stack.is_full()); + EXPECT_ANY_THROW(stack.push(30)); +} + +TEST(TestStackListLib, test_top_with_empty_stack) { + // Arrange + StackList stack; + + // Act & Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_ANY_THROW(stack.top()); +} + +TEST(TestStackListLib, test_pop_not_all_elements_in_stack_and_top_without_an_underflowing_stack) { + // Arrange + StackList stack; + stack.push(1); + stack.push(2); + stack.push(3); + + // Act + stack.pop(); + + // Assert + EXPECT_FALSE(stack.is_empty()); + EXPECT_EQ(2, stack.count()); + EXPECT_EQ(2, stack.top()); +} + +TEST(TestStackListLib, test_pop_all_elements_in_stack_and_top_without_an_underflowing_stack) { + // Arrange + StackList stack; + stack.push(1); + + // Act + stack.pop(); + + // Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_EQ(0, stack.count()); + EXPECT_ANY_THROW(stack.top()); +} + +TEST(TestStackListLib, test_pop_with_an_underflowing_stack) { + // Arrange + StackList stack; + + // Act & Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_ANY_THROW(stack.pop()); +} + +TEST(TestStackListLib, test_clear) { + // Arrange + StackList stack; + stack.push(1); + stack.push(2); + stack.push(3); + + // Act + stack.clear(); + + // Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_EQ(0, stack.count()); + EXPECT_ANY_THROW(stack.top()); + EXPECT_NO_THROW(stack.push(10)); +} + +TEST(TestStackListLib, test_is_full_checking_for_a_full_stack) { + // Arrange + StackList stack(3); + stack.push(1); + stack.push(2); + stack.push(3); + + // Act & Assert + EXPECT_TRUE(stack.is_full()); + EXPECT_ANY_THROW(stack.push(4)); +} + +TEST(TestStackListLib, test_is_full_checking_for_an_empty_stack) { + // Arrange + StackList stack(3); + + // Act & Assert + EXPECT_FALSE(stack.is_full()); + EXPECT_ANY_THROW(stack.pop()); +} + +TEST(TestStackListLib, test_is_empty_checking_for_a_full_stack) { + // Arrange + StackList stack(3); + stack.push(1); + stack.push(2); + stack.push(3); + + // Act & Assert + EXPECT_FALSE(stack.is_empty()); + EXPECT_ANY_THROW(stack.push(4)); +} + +TEST(TestStackListLib, test_is_empty_checking_for_an_empty_stack) { + // Arrange + StackList stack(3); + + // Act & Assert + EXPECT_TRUE(stack.is_empty()); + EXPECT_ANY_THROW(stack.pop()); +} \ No newline at end of file diff --git a/tests/test_triangle_matrix.cpp b/tests/test_triangle_matrix.cpp new file mode 100644 index 00000000..ce6f104f --- /dev/null +++ b/tests/test_triangle_matrix.cpp @@ -0,0 +1,376 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_triangle_matrix/triangle_matrix.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestTriangleMatrixLib, default_constructor) { + // Arrange & Act + TriangleMatrix m; + + // Assert + EXPECT_EQ(0, m.rows()); + EXPECT_EQ(0, m.cols()); +} + +TEST(TestTriangleMatrixLib, constructor_for_int_matrix_with_size) { + // Arrange & Act + TriangleMatrix m(4); + + // Assert + EXPECT_EQ(4, m.rows()); + EXPECT_EQ(4, m.cols()); + for (size_t i = 0; i < m.rows(); ++i) { + for (size_t j = 0; j < m.cols(); ++j) { + EXPECT_EQ(0, m.at(i, j)); + } + } +} + +TEST(TestTriangleMatrixLib, constructor_for_double_matrix_with_size) { + // Arrange & Act + TriangleMatrix m(5); + + // Assert + EXPECT_EQ(5, m.rows()); + EXPECT_EQ(5, m.cols()); + for (size_t i = 0; i < m.rows(); ++i) { + for (size_t j = 0; j < m.cols(); ++j) { + EXPECT_EQ(0.0, m.at(i, j)); + } + } +} + +TEST(TestTriangleMatrixLib, constructor_copy) { + // Arrange + TriangleMatrix matrix1(3); + matrix1.at(0, 0) = 1; + matrix1.at(0, 1) = 2; + + // Act + TriangleMatrix matrix2(matrix1); + + // Assert + EXPECT_EQ(3, matrix2.rows()); + EXPECT_EQ(3, matrix2.cols()); + EXPECT_EQ(1, matrix2.at(0, 0)); + EXPECT_EQ(2, matrix2.at(0, 1)); +} + +TEST(TestTriangleMatrixLib, test_addition_int_triangle_matrix_with_the_same_size) { + // Arrange + TriangleMatrix a(3), b(3); + a.at(0, 0) = 1; a.at(0, 1) = 2; a.at(0, 2) = 3; a.at(1, 1) = 4; a.at(1, 2) = 5; a.at(2, 2) = 6; + b.at(0, 0) = 7; b.at(0, 1) = 8; b.at(0, 2) = 9; b.at(1, 1) = 10; b.at(1, 2) = 11; b.at(2, 2) = 12; + + // Act + TriangleMatrix c = a + b; + + // Assert + EXPECT_EQ(8, c.at(0, 0)); + EXPECT_EQ(10, c.at(0, 1)); + EXPECT_EQ(12, c.at(0, 2)); + EXPECT_EQ(0, c.at(1, 0)); + EXPECT_EQ(14, c.at(1, 1)); + EXPECT_EQ(16, c.at(1, 2)); + EXPECT_EQ(0, c.at(2, 0)); + EXPECT_EQ(0, c.at(2, 1)); + EXPECT_EQ(18, c.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_addition_int_triangle_matrix_without_the_same_size) { + // Arrange + TriangleMatrix a(3), b(4); + + // Act & Assert + ASSERT_ANY_THROW(a + b); +} + +TEST(TestTriangleMatrixLib, test_subtraction_int_triangle_matrix_with_the_same_size) { + // Arrange + TriangleMatrix a(3), b(3); + a.at(0, 0) = 1; a.at(0, 1) = 2; a.at(0, 2) = 3; a.at(1, 1) = 4; a.at(1, 2) = 5; a.at(2, 2) = 6; + b.at(0, 0) = 7; b.at(0, 1) = 8; b.at(0, 2) = 9; b.at(1, 1) = 10; b.at(1, 2) = 11; b.at(2, 2) = 12; + + // Act + TriangleMatrix c = b - a; + + // Assert + EXPECT_EQ(6, c.at(0, 0)); + EXPECT_EQ(6, c.at(0, 1)); + EXPECT_EQ(6, c.at(0, 2)); + EXPECT_EQ(0, c.at(1, 0)); + EXPECT_EQ(6, c.at(1, 1)); + EXPECT_EQ(6, c.at(1, 2)); + EXPECT_EQ(0, c.at(2, 0)); + EXPECT_EQ(0, c.at(2, 1)); + EXPECT_EQ(6, c.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_subtraction_int_triangle_matrix_without_the_same_size) { + // Arrange + TriangleMatrix a(4), b(3); + + // Act & Assert + ASSERT_ANY_THROW(a - b); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_TriangleMatrix_by_a_scalar) { + // Arrange + TriangleMatrix A(3); + A.at(0, 0) = 1; A.at(0, 1) = 2; A.at(0, 2) = 3; A.at(1, 1) = 4; A.at(1, 2) = 5; A.at(2, 2) = 6; + + // Act + TriangleMatrix C = A * 2; + + // Assert + EXPECT_EQ(2, C.at(0, 0)); + EXPECT_EQ(4, C.at(0, 1)); + EXPECT_EQ(6, C.at(0, 2)); + EXPECT_EQ(0, C.at(1, 0)); + EXPECT_EQ(8, C.at(1, 1)); + EXPECT_EQ(10, C.at(1, 2)); + EXPECT_EQ(0, C.at(2, 0)); + EXPECT_EQ(0, C.at(2, 1)); + EXPECT_EQ(12, C.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_TriangleMatrix_by_a_vector_with_correct_equal_size) { + // Arrange + TriangleMatrix A(3); + A.at(0, 0) = 1; A.at(0, 1) = 2; A.at(0, 2) = 3; A.at(1, 1) = 4; A.at(1, 2) = 5; A.at(2, 2) = 6; + MathVector vec{ 7, 8, 9 }; + + // Act + MathVector C = A * vec; + + // Assert + EXPECT_EQ(50, C.at(0)); + EXPECT_EQ(77, C.at(1)); + EXPECT_EQ(54, C.at(2)); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_TriangleMatrix_by_a_vector_without_correct_equal_size) { + // Arrange + TriangleMatrix A(3); + MathVector vec(4); + + // Act & Assert + ASSERT_ANY_THROW(A * vec); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_TriangleMatrix_by_a_int_TriangleMatrix_with_correct_equal_size) { + // Arrange + TriangleMatrix A(3), B(3); + A.at(0, 0) = 1; A.at(0, 1) = 2; A.at(0, 2) = 3; A.at(1, 1) = 4; A.at(1, 2) = 5; A.at(2, 2) = 6; + B.at(0, 0) = 7; B.at(0, 1) = 8; B.at(0, 2) = 9; B.at(1, 1) = 10; B.at(1, 2) = 11; B.at(2, 2) = 12; + + // Act + TriangleMatrix C = A * B; + + // Assert + EXPECT_EQ(7, C.at(0, 0)); + EXPECT_EQ(28, C.at(0, 1)); + EXPECT_EQ(67, C.at(0, 2)); + EXPECT_EQ(0, C.at(1, 0)); + EXPECT_EQ(40, C.at(1, 1)); + EXPECT_EQ(104, C.at(1, 2)); + EXPECT_EQ(0, C.at(2, 0)); + EXPECT_EQ(0, C.at(2, 1)); + EXPECT_EQ(72, C.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_TriangleMatrix_by_a_int_TriangleMatrix_without_correct_equal_size) { + // Arrange + TriangleMatrix A(3), B(4); + + // Act & Assert + ASSERT_ANY_THROW(A * B); +} + +TEST(TestTriangleMatrixLib, test_addition_int_matrix_and_int_triangle_matrix_with_the_same_size) { + // Arrange + TriangleMatrix a(3); + a.at(0, 0) = 1; a.at(0, 1) = 2; a.at(0, 2) = 3; a.at(1, 1) = 4; a.at(1, 2) = 5; a.at(2, 2) = 6; + Matrix b{ {1, 1, 1}, {1, 1, 1}, {1, 1, 1} }; + + // Act + Matrix c = b + a; + + // Assert + EXPECT_EQ(2, c.at(0, 0)); + EXPECT_EQ(3, c.at(0, 1)); + EXPECT_EQ(4, c.at(0, 2)); + EXPECT_EQ(1, c.at(1, 0)); + EXPECT_EQ(5, c.at(1, 1)); + EXPECT_EQ(6, c.at(1, 2)); + EXPECT_EQ(1, c.at(2, 0)); + EXPECT_EQ(1, c.at(2, 1)); + EXPECT_EQ(7, c.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_addition_int_matrix_and_int_triangle_matrix_without_the_same_size) { + // Arrange + TriangleMatrix a(3); + a.at(0, 0) = 1; a.at(0, 1) = 2; a.at(0, 2) = 3; a.at(1, 1) = 4; a.at(1, 2) = 5; a.at(2, 2) = 6; + Matrix b{ {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1} }; + + // Act & Assert + ASSERT_ANY_THROW(b + a); +} + +TEST(TestTriangleMatrixLib, test_addition_int_triangle_matrix_and_int_matrix_with_the_same_size) { + // Arrange + TriangleMatrix a(3); + a.at(0, 0) = 1; a.at(0, 1) = 2; a.at(0, 2) = 3; a.at(1, 1) = 4; a.at(1, 2) = 5; a.at(2, 2) = 6; + Matrix b{ {1, 1, 1}, {1, 1, 1}, {1, 1, 1} }; + + // Act + Matrix c = a + b; + + // Assert + EXPECT_EQ(2, c.at(0, 0)); + EXPECT_EQ(3, c.at(0, 1)); + EXPECT_EQ(4, c.at(0, 2)); + EXPECT_EQ(1, c.at(1, 0)); + EXPECT_EQ(5, c.at(1, 1)); + EXPECT_EQ(6, c.at(1, 2)); + EXPECT_EQ(1, c.at(2, 0)); + EXPECT_EQ(1, c.at(2, 1)); + EXPECT_EQ(7, c.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_addition_int_triangle_matrix_and_int_matrix_without_the_same_size) { + // Arrange + TriangleMatrix a(3); + a.at(0, 0) = 1; a.at(0, 1) = 2; a.at(0, 2) = 3; a.at(1, 1) = 4; a.at(1, 2) = 5; a.at(2, 2) = 6; + Matrix b{ {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1} }; + + // Act & Assert + ASSERT_ANY_THROW(a + b); +} + +TEST(TestTriangleMatrixLib, test_subtraction_int_matrix_and_int_triangle_matrix_with_the_same_size) { + // Arrange + TriangleMatrix a(3); + a.at(0, 0) = 1; a.at(0, 1) = 2; a.at(0, 2) = 3; a.at(1, 1) = 4; a.at(1, 2) = 5; a.at(2, 2) = 6; + Matrix b{ {20, 20, 20}, {20, 20, 20}, {20, 20, 20} }; + + // Act + Matrix c = b - a; + + // Assert + EXPECT_EQ(19, c.at(0, 0)); + EXPECT_EQ(18, c.at(0, 1)); + EXPECT_EQ(17, c.at(0, 2)); + EXPECT_EQ(20, c.at(1, 0)); + EXPECT_EQ(16, c.at(1, 1)); + EXPECT_EQ(15, c.at(1, 2)); + EXPECT_EQ(20, c.at(2, 0)); + EXPECT_EQ(20, c.at(2, 1)); + EXPECT_EQ(14, c.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_subtraction_int_matrix_and_int_triangle_matrix_without_the_same_size) { + // Arrange + TriangleMatrix a(4); + Matrix b{ {20, 20, 20}, {20, 20, 20}, {20, 20, 20} }; + + // Act & Assert + ASSERT_ANY_THROW(b - a); +} + +TEST(TestTriangleMatrixLib, test_subtraction_int_triangle_matrix_and_int_matrix_with_the_same_size) { + // Arrange + TriangleMatrix a(3); + a.at(0, 0) = 1; a.at(0, 1) = 2; a.at(0, 2) = 3; a.at(1, 1) = 4; a.at(1, 2) = 5; a.at(2, 2) = 6; + Matrix b{ {20, 20, 20}, {20, 20, 20}, {20, 20, 20} }; + + // Act + Matrix c = a - b; + + // Assert + EXPECT_EQ(-19, c.at(0, 0)); + EXPECT_EQ(-18, c.at(0, 1)); + EXPECT_EQ(-17, c.at(0, 2)); + EXPECT_EQ(-20, c.at(1, 0)); + EXPECT_EQ(-16, c.at(1, 1)); + EXPECT_EQ(-15, c.at(1, 2)); + EXPECT_EQ(-20, c.at(2, 0)); + EXPECT_EQ(-20, c.at(2, 1)); + EXPECT_EQ(-14, c.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_subtraction_int_triangle_matrix_and_int_matrix_without_the_same_size) { + // Arrange + TriangleMatrix a(4); + Matrix b{ {20, 20, 20}, {20, 20, 20}, {20, 20, 20} }; + + // Act & Assert + ASSERT_ANY_THROW(a - b); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_Matrix_by_a_int_Triangle_Matrix_with_correct_equal_size) { + // Arrange + TriangleMatrix A(3); + A.at(0, 0) = 1; A.at(0, 1) = 2; A.at(0, 2) = 3; A.at(1, 1) = 4; A.at(1, 2) = 5; A.at(2, 2) = 6; + Matrix B{ {2, 2, 2}, {2, 2, 2}, {2, 2, 2} }; + + // Act + Matrix C = B * A; + + // Assert + EXPECT_EQ(2, C.at(0, 0)); + EXPECT_EQ(12, C.at(0, 1)); + EXPECT_EQ(28, C.at(0, 2)); + EXPECT_EQ(2, C.at(1, 0)); + EXPECT_EQ(12, C.at(1, 1)); + EXPECT_EQ(28, C.at(1, 2)); + EXPECT_EQ(2, C.at(2, 0)); + EXPECT_EQ(12, C.at(2, 1)); + EXPECT_EQ(28, C.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_Matrix_by_a_int_Triangle_Matrix_without_correct_equal_size) { + // Arrange + TriangleMatrix A(4); + A.at(0, 0) = 1; A.at(0, 1) = 2; A.at(0, 2) = 3; A.at(1, 1) = 4; A.at(1, 2) = 5; A.at(2, 2) = 6; + Matrix B{ {2, 2, 2}, {2, 2, 2}, {2, 2, 2} }; + + // Act & Assert + ASSERT_ANY_THROW(B * A); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_Triangle_Matrix_by_a_int_Matrix_with_correct_equal_size) { + // Arrange + TriangleMatrix A(3); + A.at(0, 0) = 1; A.at(0, 1) = 2; A.at(0, 2) = 3; A.at(1, 1) = 4; A.at(1, 2) = 5; A.at(2, 2) = 6; + Matrix B{ {2, 2, 2}, {2, 2, 2}, {2, 2, 2} }; + + // Act + Matrix C = A * B; + + // Assert + EXPECT_EQ(12, C.at(0, 0)); + EXPECT_EQ(12, C.at(0, 1)); + EXPECT_EQ(12, C.at(0, 2)); + EXPECT_EQ(18, C.at(1, 0)); + EXPECT_EQ(18, C.at(1, 1)); + EXPECT_EQ(18, C.at(1, 2)); + EXPECT_EQ(12, C.at(2, 0)); + EXPECT_EQ(12, C.at(2, 1)); + EXPECT_EQ(12, C.at(2, 2)); +} + +TEST(TestTriangleMatrixLib, test_mult_a_int_Triangle_Matrix_by_a_int_Matrix_without_correct_equal_size) { + // Arrange + TriangleMatrix A(4); + A.at(0, 0) = 1; A.at(0, 1) = 2; A.at(0, 2) = 3; A.at(1, 1) = 4; A.at(1, 2) = 5; A.at(2, 2) = 6; + Matrix B{ {2, 2, 2}, {2, 2, 2}, {2, 2, 2} }; + + // Act & Assert + ASSERT_ANY_THROW(A * B); +} \ No newline at end of file diff --git a/tests/test_tvector.cpp b/tests/test_tvector.cpp new file mode 100644 index 00000000..839af71b --- /dev/null +++ b/tests/test_tvector.cpp @@ -0,0 +1,813 @@ +// Copyright 2025 Ekaterina Ushnitskaya + +#include +#include "../lib_tvector/tvector.h" + +#define EPSILON 0.000001 +#define TRUE 1 +#define FALSE 0 + +TEST(TestTVectorLib, default_constructor) { + // Arrange () + TVector vec; + + // Act & Assert + EXPECT_EQ(nullptr, vec.data()); // + EXPECT_EQ(nullptr, vec.states()); + EXPECT_EQ(0, vec.size()); + EXPECT_EQ(0, vec.capacity()); + EXPECT_EQ(0, vec.deleted()); + EXPECT_TRUE(vec.is_empty()); +} + +TEST(TestTVectorLib, constructor_with_size) { + // Arrange () + size_t size = 10; + TVector vec(size); + + // Act & Assert + EXPECT_EQ(size, vec.size()); + EXPECT_EQ(size + TVector::RESERVE_MEMORY, vec.capacity()); + EXPECT_EQ(0, vec.deleted()); + EXPECT_FALSE(vec.is_empty()); + for (size_t i = 0; i < size; i++) { + EXPECT_EQ(State::busy, vec.state(i)); + } + for (size_t i = size; i < vec.capacity(); i++) { + EXPECT_EQ(State::empty, vec.state(i)); + } +} + +TEST(TestTVectorLib, constructor_with_mass_all_parameters_are_good) { + // Arrange () + size_t size = 3; + int copy_mass[3] = { 1, 2, 3 }; + + // Act + TVector vec(copy_mass, size); + + // Assert + EXPECT_EQ(size, vec.size()); + EXPECT_EQ(size + TVector::RESERVE_MEMORY, vec.capacity()); + EXPECT_EQ(0, vec.deleted()); + EXPECT_FALSE(vec.is_empty()); + EXPECT_EQ(1, vec.data(0)); + EXPECT_EQ(2, vec.data(1)); + EXPECT_EQ(3, vec.data(2)); + for (size_t i = 0; i < size; i++) { + EXPECT_EQ(State::busy, vec.state(i)); + } + for (size_t i = size; i < vec.capacity(); i++) { + EXPECT_EQ(State::empty, vec.state(i)); + } +} + +TEST(TestTVectorLib, constructor_with_mass_with_nullptr_and_size_gt_zero) { + // Arrange + int* null_data = nullptr; + + // Act & Assert + ASSERT_ANY_THROW(TVector vec(null_data, 5)); +} + +TEST(TestTVectorLib, copy_constructor) { + // Arrange + int arr[4] = { 1, 2, 3, 4 }; + TVector vec1(arr, 4); + + // Act + TVector vec2(vec1); + + // Assert + EXPECT_EQ(vec1.size(), vec2.size()); + EXPECT_EQ(vec1.capacity(), vec2.capacity()); + EXPECT_EQ(vec1.deleted(), vec2.deleted()); + for (size_t i = 0; i < vec1.size(); i++) { + EXPECT_EQ(vec1.data(i), vec2.data(i)); + EXPECT_EQ(vec1.state(i), vec2.state(i)); + } +} + +TEST(TestTVectorLib, test_at_checking_without_difficulties) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + TVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(4, vec.at(4)); +} + +TEST(TestTVectorLib, test_at_checking_with_pop_front) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + TVector vec(arr, size); + + // Act + vec.pop_front(); + + // Assert + EXPECT_EQ(1, vec.at(0)); +} + +TEST(TestTVectorLib, test_data_with_index) { + // Arrange + int arr[3] = { 11, 22, 33 }; + TVector vec(arr, 3); + + // Act & Assert + EXPECT_EQ(11, vec.data(0)); + EXPECT_EQ(22, vec.data(1)); + EXPECT_EQ(33, vec.data(2)); + ASSERT_ANY_THROW(vec.data(10)); // +} + +TEST(TestTVectorLib, test_state_state_deleted) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + TVector vec(arr, size); + + // Act + vec.pop_front(); + + // Assert + EXPECT_EQ(State::deleted, vec.state(0)); +} + +TEST(TestTVectorLib, test_state_state_busy) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + TVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(State::busy, vec.state(4)); +} + +TEST(TestTVectorLib, test_state_state_empty) { + // Arrange + size_t size = 8; + int arr[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + TVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(State::empty, vec.state(size+1)); +} + +TEST(TestTVectorLib, test_size_setter_increase) { // + // Arrange + TVector vec(2); + + // Act + vec.size(5); + + // Assert + EXPECT_EQ(5, vec.size()); + for (size_t i = 2; i < 5; i++) { + EXPECT_EQ(State::busy, vec.state(i)); + } +} + +TEST(TestTVectorLib, test_size_setter_decrease) { + // Arrange + TVector vec(5); + vec[0] = 99; + + // Act + vec.size(2); + + // Assert + EXPECT_EQ(2, vec.size()); + EXPECT_EQ(99, vec[0]); // , +} + +TEST(TestTVectorLib, test_capacity_setter) { + // Arrange + TVector vec(2); + size_t old_capacity = vec.capacity(); + + // Act + vec.capacity(old_capacity + 20); + + // Assert + EXPECT_TRUE(vec.capacity() >= old_capacity + 20); +} + +/* +TEST(TestTVectorLib, test_begin_and_end) { + // Arrange + size_t size = 3; + int arr[8] = { 11, 22, 37 }; + TVector vec(arr, size); + int sum = 0; + + // Act + int* begin = vec.begin(); + int* end = vec.end(); + for (int* p = begin; p < end; ++p) { + sum += *p; + } + + // Assert + EXPECT_EQ(11+22+37, sum); +} +*/ + +TEST(TestTVectorLib, test_deleted_counter) { + // Arrange + TVector vec(35); + + // Act + vec.erase(1); + vec.erase(2); + + // Assert + EXPECT_EQ(2, vec.deleted()); +} + +TEST(TestTVectorLib, test_front_without_deleted_elements) { + // Arrange + size_t size = 3; + int arr[8] = { 112, 234, 345 }; + TVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(112, vec.front()); +} + +TEST(TestTVectorLib, test_front_with_deleted_element) { + // Arrange + size_t size = 3; + int arr[8] = { 112, 234, 345 }; + TVector vec(arr, size); + + // Act + vec.pop_front(); + + // Assert + EXPECT_EQ(234, vec.front()); +} + +TEST(TestTVectorLib, test_back_without_deleted_elements) { + // Arrange + size_t size = 3; + int arr[8] = { 112, 234, 345 }; + TVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(345, vec.back()); +} + +TEST(TestTVectorLib, test_back_with_deleted_element) { + // Arrange + size_t size = 3; + int arr[8] = { 112, 234, 345 }; + TVector vec(arr, size); + + // Act + vec.pop_back(); + + // Assert + EXPECT_EQ(234, vec.back()); +} + +TEST(TestTVectorLib, test_is_empty_real_empty_vec) { + // Arrange + TVector vec; + + // Act & Assert + EXPECT_TRUE(vec.is_empty()); +} + +TEST(TestTVectorLib, test_is_empty_not_empty_vec) { + // Arrange + TVector vec(3); + + // Act & Assert + EXPECT_FALSE(vec.is_empty()); +} + +TEST(TestTVectorLib, test_push_front_checking_without_difficulties) { + // Arrange + TVector vec(3); + vec[0] = 1; + vec[1] = 2; + vec[2] = 3; + const State* states_vec = vec.states(); + + // Act + vec.push_front(777); + + // Assert + EXPECT_EQ(4, vec.size()); + EXPECT_EQ(3 + vec.RESERVE_MEMORY, vec.capacity()); + EXPECT_TRUE(states_vec[3] == State::busy); + EXPECT_EQ(777, vec[0]); + EXPECT_EQ(3, vec[3]); +} + +TEST(TestTVectorLib, test_push_front_with_reserve) { + // Arrange + TVector vec(1); + size_t vec_capacity = vec.capacity(); + for (size_t i = 0; i < vec_capacity; ++i) { // capacity + vec.push_back(1); + } + + // Act + vec.push_front(0); // reserve() + + // Assert + EXPECT_TRUE(vec[0] == 0 && vec_capacity <= vec.capacity()); +} + +TEST(TestTVectorLib, test_push_back_checking_without_difficulties) { + // Arrange + TVector vec(3); + vec[0] = 1; + vec[1] = 2; + vec[2] = 3; + const State* states_vec = vec.states(); + + // Act + vec.push_back(42); + + // Assert + EXPECT_EQ(4, vec.size()); + EXPECT_EQ(3 + vec.RESERVE_MEMORY, vec.capacity()); + EXPECT_TRUE(states_vec[3] == State::busy); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(42, vec[3]); +} + +TEST(TestTVectorLib, test_push_back_with_reserve) { + // Arrange + TVector vec(1); + size_t vec_capacity1 = vec.capacity(); + for (size_t i = 0; i < vec_capacity1; ++i) { // capacity + vec.push_back(1); + } + + // Act + vec.push_back(0); // reserve() + + // Assert + EXPECT_TRUE(vec[vec.size() - 1] == 0 && vec_capacity1 <= vec.capacity()); +} + +TEST(TestTVectorLib, test_insert_without_deleted_elements) { + // Arrange + TVector vec(3); + vec[0] = 1; + vec[1] = 2; + vec[2] = 3; + + // Act + vec.insert(1, 66); + + // Assert + EXPECT_EQ(4, vec.size()); + EXPECT_EQ(1, vec[0]); + EXPECT_EQ(66, vec[1]); + EXPECT_EQ(2, vec[2]); + EXPECT_EQ(3, vec[3]); +} + +TEST(TestTVectorLib, test_insert_with_deleted_elements) { + // Arrange + size_t size = 5; + int arr[5] = { 1, 6, 4, 5, 7 }; + TVector vec(arr, size); + + // Act + vec.erase(1); + vec.insert(1, 667); + + // Assert + EXPECT_EQ(5, vec.size()); + EXPECT_EQ(1, vec.at(0)); + EXPECT_EQ(667, vec.at(1)); + EXPECT_EQ(4, vec.at(2)); + EXPECT_EQ(5, vec.at(3)); + EXPECT_EQ(7, vec.at(4)); +} + +TEST(TestTVectorLib, test_insert_with_reserve) { + // Arrange + TVector vec(3); + size_t vec_capacity = vec.capacity(); + for (size_t i = 0; i < vec_capacity; ++i) { // a capacity + vec.insert(1, 5); + } + + // Act + vec.insert(1, 5); + + // Assert + EXPECT_TRUE(vec[1] == 5 && vec_capacity <= vec.capacity()); +} + +TEST(TestTVectorLib, test_insert_out_of_range) { + // Arrange + TVector vec(2); + + // Act + vec.insert(1, 66); + + // Assert + ASSERT_ANY_THROW(vec.insert(5, 999)); +} + +TEST(TestTVectorLib, test_pop_front_checking_without_difficulties) { + // Arrange + size_t size = 7; + int arr[7] = { 10, 20, 30, 10, 20, 30, 10 }; + TVector vec(arr, size); + const State* states_vec = vec.states(); + + // Act + vec.pop_front(); + + // Assert + EXPECT_TRUE(states_vec[0] == State::deleted && vec.size() == 7 && vec.deleted() == 1); +} + +TEST(TestTVectorLib, test_pop_front_with_shrink_to_fit) { + // Arrange + TVector vec(6); + for (size_t i = 0; i < 1; ++i) { + vec.erase(i); // deleted 1 + } + // Act + vec.pop_front(); + + // Assert + EXPECT_EQ(0, vec.deleted()); +} + +TEST(TestTVectorLib, test_pop_back_checking_without_difficulties) { + // Arrange + TVector vec(3); + vec[2] = 99; + const State* states_vec = vec.states(); + + // Act + vec.pop_back(); + + // Assert + EXPECT_TRUE(states_vec[2] == State::empty && vec.size() == 2); +} + +TEST(TestTVectorLib, test_pop_back_size_equal_0) { + // Arrange + TVector vec; + + // Act & Assert + ASSERT_ANY_THROW(vec.pop_back()); +} + +TEST(TestTVectorLib, test_erase_checking_without_difficulties) { + // Arrange + TVector vec(9); + const State* states_vec = vec.states(); + + // Act + vec.erase(1); + + // Assert + EXPECT_TRUE(states_vec[1] == State::deleted); +} + +TEST(TestTVectorLib, test_erase_with_shrink_to_fit) { + // Arrange + TVector vec(20); + + // Act + for (int i = 0; i < 4; ++i) { vec.erase(i); } + + // Assert + EXPECT_EQ(0, vec.deleted()); + EXPECT_EQ(16, vec.size()); +} + +TEST(TestTVectorLib, test_emplace) { + // Arrange + TVector vec(3); + + // Act + vec.emplace(0, std::string("hello")); + + // Assert + EXPECT_EQ("hello", vec[0]); +} + +TEST(TestTVectorLib, test_assign) { + // Arrange + size_t size = 3; + TVector vec1(size); + vec1[0] = 1; + vec1[1] = 2; + vec1[2] = 3; + + // Act + TVector vec2; + vec2.assign(vec1); + + // Assert + EXPECT_EQ(1, vec2[0]); + EXPECT_EQ(2, vec2[1]); + EXPECT_EQ(3, vec2[2]); +} + +TEST(TestTVectorLib, test_operator_equal) { + // Arrange + size_t size = 3; + TVector vec1(size); + vec1[0] = 100; + vec1[1] = 200; + vec1[2] = 369; + + // Act + TVector vec2; + vec2 = vec1; + + // Assert + EXPECT_EQ(100, vec2[0]); + EXPECT_EQ(200, vec2[1]); + EXPECT_EQ(369, vec2[2]); +} + +TEST(TestTVectorLib, test_clear) { + // Arrange + size_t size = 5; + TVector vec(size); + const State* vec_states = vec.states(); + + // Act + vec.clear(); + + // Assert + for (size_t i = 0; i < size; ++i) { EXPECT_EQ(State::empty, vec_states[i]); } + EXPECT_EQ(0, vec.size()); + EXPECT_EQ(0, vec.deleted()); +} + +TEST(TestTVectorLib, can_compare_with_operator_two_equal_object) { + // Arrange + size_t size = 2; + TVector vec1(size); + vec1[0] = 5; + vec1[1] = 6; + TVector vec2(size); + vec2[0] = 5; + vec2[1] = 6; + + // Act & Assert + EXPECT_TRUE(vec1 == vec2); +} + +TEST(TestTVectorLib, can_compare_with_operator_two_not_equal_object) { + // Arrange + size_t size = 2; + TVector vec1(size); + vec1[0] = 5; + vec1[1] = 6; + TVector vec2(size); + vec2[0] = 5; + vec2[1] = 7; + + // Act & Assert + EXPECT_FALSE(vec1 == vec2); +} + +TEST(TestTVectorLib, test_operator_equal_for_empty_vectors) { + // Arrange + TVector vec1; + TVector vec2; + + // Act & Assert + EXPECT_TRUE(vec1 == vec2); +} + +TEST(TestTVectorLib, can_compare_with_operator_that_says_that_two_objects_are_not_equal_return_true) { + // Arrange + size_t size = 2; + TVector vec1(size); + vec1[0] = 5; + vec1[1] = 6; + TVector vec2(size); + vec2[0] = 3; + vec2[1] = -4; + + // Act & Assert + EXPECT_TRUE(vec1 != vec2); +} + +TEST(TestTVectorLib, can_compare_with_operator_that_says_that_two_objects_are_not_equal_return_fale) { + // Arrange + size_t size = 2; + TVector vec1(size); + vec1[0] = 5; + vec1[1] = 6; + TVector vec2(size); + vec2[0] = 5; + vec2[1] = 6; + + // Act & Assert + EXPECT_FALSE(vec1 != vec2); +} + +TEST(TestTVectorLib, test_reserve_new_capacity_more_than_old_capacity) { + // Arrange + TVector vec(3); + size_t old_capacity = vec.capacity(); + size_t new_capacity = old_capacity + 10; + + // Act + vec.reserve(new_capacity); + + // Assert + EXPECT_TRUE(vec.capacity() >= new_capacity); +} + +TEST(TestTVectorLib, test_reserve_no_change_if_new_capacity_less_than_old_capacity) { + // Arrange + TVector vec(4); + size_t old_capacity = vec.capacity(); + + // Act + vec.reserve(old_capacity - 1); + + // Assert + EXPECT_TRUE(vec.capacity() == old_capacity); +} + +TEST(TestTVectorLib, test_resize) { + // Arrange + TVector vec(3); + vec[0] = 10; + vec[1] = 20; + vec[2] = 30; + const State* states = vec.states(); + + // Act + vec.resize(5); + + // Assert + EXPECT_EQ(5, vec.size()); + EXPECT_EQ(10, vec[0]); + EXPECT_EQ(20, vec[1]); + EXPECT_EQ(30, vec[2]); + EXPECT_EQ(busy, states[3]); + EXPECT_EQ(busy, states[4]); +} + +TEST(TestTVectorLib, test_shrink_to_fit) { + // Arrange + size_t size = 5; + int arr[5] = { 10, 20, 30, 40, 50 }; + TVector vec(arr, size); + size_t old_capacity = vec.capacity(); + + // Act + vec.erase(1); + vec.erase(3); + vec.shrink_to_fit(); + + // Assert + EXPECT_TRUE(vec.capacity() < old_capacity); + EXPECT_EQ(3, vec.size()); +} + +TEST(TestTVectorLib, test_shuffle) { + // Arrange + size_t size = 5; + TVector vec(size); + for (int i = 0; i < size; ++i) { vec[i] = i; } + TVector old_vec(vec); + + // Act + shuffle(vec); + + // Assert + EXPECT_TRUE(old_vec != vec); +} + +TEST(TestTVectorLib, test_quick_sort) { + // Arrange + size_t size = 5; + int arr_not_sort[5] = { 5, 3, 4, 1, 2 }; + int arr_sort[5] = { 1, 2, 3, 4, 5 }; + TVector not_sort_vec(arr_not_sort, size); + TVector sort_vec(arr_sort, size); + + // Act + quick_sort(not_sort_vec); + + // Assert + EXPECT_TRUE(sort_vec == not_sort_vec); +} + +TEST(TestTVectorLib, test_find_first) { + // Arrange + size_t size = 5; + int arr[5] = { 7, 3, 5, 3, 9 }; + TVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(1, find_first(vec, 3)); +} + +TEST(TestTVectorLib, test_find_last) { + // Arrange + size_t size = 5; + int arr[5] = { 7, 3, 5, 3, 9 }; + TVector vec(arr, size); + + // Act & Assert + EXPECT_EQ(3, find_last(vec, 3)); +} + +TEST(TestTVectorLib, test_find_all) { + // Arrange + size_t size = 6; + int arr[6] = { 1, 2, 3, 2, 5, 2 }; + TVector vec(arr, size); + + // Act + size_t* result = find_all(vec, 2); + + // Assert + EXPECT_TRUE(result[0] == 1 && result[1] == 3 && result[2] == 5); + delete[] result; // ???? +} + +TEST(TestTVectorLib, iteration_empty_vector) { + // Arrange + TVector vec; + + // Act + auto it = vec.begin(); + auto end_it = vec.end(); + + // Assert + EXPECT_EQ(it, end_it); + int count = 0; + while (it != end_it) { + ++count; + ++it; + } + EXPECT_EQ(0, count); +} + +TEST(TestTVectorLib, write_iterator) { + // Arrange + TVector vec; + vec.push_back(10); + vec.push_back(20); + vec.push_back(30); + + // Act + int k = 2; + for (auto it = vec.begin(); it != vec.end(); ++it) { + *it = *it * k; + k++; + } + + // Assert + EXPECT_EQ(20, vec.at(0)); + EXPECT_EQ(60, vec.at(1)); + EXPECT_EQ(120, vec.at(2)); + auto it = vec.begin(); + EXPECT_EQ(*it, 20); + ++it; + EXPECT_EQ(*it, 60); + ++it; + EXPECT_EQ(*it, 120); + ++it; + EXPECT_EQ(it, vec.end()); +} + +TEST(TestTVectorLib, read_iterator) { + // Arrange + TVector vec; + vec.push_back(5); + vec.push_back(15); + vec.push_back(25); + vec.push_back(35); + vec.erase(1); + + // Act + int sum = 0; + int count = 0; + for (auto it = vec.begin(); it != vec.end(); ++it) { + sum += *it; + ++count; + } + + // Assert + EXPECT_EQ(3, count); + EXPECT_EQ(65, sum); +} \ No newline at end of file