From 63377b0110aa4391c1bea2ea42c7b95b78633183 Mon Sep 17 00:00:00 2001 From: mrdcvlsc Date: Sat, 22 Jul 2023 18:10:28 +0800 Subject: [PATCH 1/2] initial ongoing rewrite to improve the api --- .clang-format | 3 +- .vscode/settings.json | 13 +- cyfre/classes/assign.cpp | 54 +- cyfre/classes/comparison.cpp | 30 +- cyfre/classes/constructors.cpp | 410 +++++----- cyfre/classes/display.cpp | 76 +- cyfre/classes/indexing.cpp | 60 +- cyfre/classes/matrix_class.hpp | 360 ++++----- cyfre/cyfre.hpp | 20 - cyfre/helpers/helper_functions.hpp | 96 +-- cyfre/helpers/randomizer.hpp | 130 +-- .../col_operations.cpp | 248 +++--- .../row_operations.cpp | 244 +++--- cyfre/matrix-matrix/mm_addition.cpp | 64 +- cyfre/matrix-matrix/mm_division.cpp | 76 +- cyfre/matrix-matrix/mm_hadamard.cpp | 68 +- cyfre/matrix-matrix/mm_multiplication.cpp | 94 +-- cyfre/matrix-matrix/mm_subtraction.cpp | 64 +- cyfre/matrix-scalar/ms_addition.cpp | 60 +- cyfre/matrix-scalar/ms_division.cpp | 90 +-- cyfre/matrix-scalar/ms_multiplication.cpp | 60 +- cyfre/matrix-scalar/ms_subtraction.cpp | 60 +- cyfre/methods/determinant.cpp | 94 +-- cyfre/methods/minmax.cpp | 52 +- cyfre/methods/sum.cpp | 40 +- cyfre/methods/trace.cpp | 56 +- cyfre/shaping/padding.cpp | 88 +-- cyfre/shaping/transpose.cpp | 40 +- cyfre/statistics/matrix_stats.hpp | 240 +++--- cyfre/test/test.cpp | 742 +++++++++--------- cyfre/transform/apply.cpp | 16 +- cyfre/transform/inverse.cpp | 136 ++-- cyfre/transform/power.cpp | 68 +- cyfre/transform/ref.cpp | 86 +- cyfre/transform/rref.cpp | 98 +-- docs/specs.md | 5 + include/cyfre/cyfre.hpp | 44 ++ include/cyfre/enums.hpp | 12 + include/cyfre/heap_alloc.hpp | 33 + include/cyfre/stack_alloc.hpp | 33 + makefile | 24 +- src/cyfre/cyfre.cpp | 6 + src/cyfre/heap_alloc.cpp | 78 ++ src/cyfre/stack_alloc.cpp | 46 ++ test/tests.cpp | 421 ++++++++++ 45 files changed, 2754 insertions(+), 2084 deletions(-) delete mode 100644 cyfre/cyfre.hpp create mode 100644 docs/specs.md create mode 100644 include/cyfre/cyfre.hpp create mode 100644 include/cyfre/enums.hpp create mode 100644 include/cyfre/heap_alloc.hpp create mode 100644 include/cyfre/stack_alloc.hpp create mode 100644 src/cyfre/cyfre.cpp create mode 100644 src/cyfre/heap_alloc.cpp create mode 100644 src/cyfre/stack_alloc.cpp create mode 100644 test/tests.cpp diff --git a/.clang-format b/.clang-format index 8f3f112..cc2fde9 100644 --- a/.clang-format +++ b/.clang-format @@ -1,6 +1,6 @@ --- BasedOnStyle: Microsoft -# IndentWidth: 4 +IndentWidth: 2 Language: Cpp @@ -24,6 +24,7 @@ BraceWrapping: # AfterCaseLabel: false # INDENTATIONS +ContinuationIndentWidth: 2 AlignAfterOpenBracket: BlockIndent NamespaceIndentation: All IndentCaseLabels: true diff --git a/.vscode/settings.json b/.vscode/settings.json index 5a08fe3..32a9d2c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -39,6 +39,17 @@ "type_traits": "cpp", "tuple": "cpp", "typeinfo": "cpp", - "utility": "cpp" + "utility": "cpp", + "atomic": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "deque": "cpp", + "map": "cpp", + "set": "cpp", + "algorithm": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "random": "cpp" } } \ No newline at end of file diff --git a/cyfre/classes/assign.cpp b/cyfre/classes/assign.cpp index b240a1a..b72cbdf 100644 --- a/cyfre/classes/assign.cpp +++ b/cyfre/classes/assign.cpp @@ -5,39 +5,39 @@ #include namespace cyfre { - // copy assignment - template - mat &mat::operator=(const mat &original) { - if (this != &original) { - size_t n = original.height * original.width; - height = original.height; - width = original.width; + // copy assignment + template + mat &mat::operator=(const mat &original) { + if (this != &original) { + size_t n = original.height * original.width; + height = original.height; + width = original.width; - if (matrix != NULL) - delete[] matrix; - matrix = new T[n]; - std::memcpy(matrix, original.matrix, sizeof(T) * n); - } - return *this; + if (matrix != NULL) + delete[] matrix; + matrix = new T[n]; + std::memcpy(matrix, original.matrix, sizeof(T) * n); } + return *this; + } - // move assignment - template - mat &mat::operator=(mat &&temporary) { - if (this != &temporary) { - if (matrix != NULL) - delete[] matrix; + // move assignment + template + mat &mat::operator=(mat &&temporary) { + if (this != &temporary) { + if (matrix != NULL) + delete[] matrix; - height = temporary.height; - width = temporary.width; - matrix = temporary.matrix; + height = temporary.height; + width = temporary.width; + matrix = temporary.matrix; - temporary.height = 0; - temporary.width = 0; - temporary.matrix = NULL; - } - return *this; + temporary.height = 0; + temporary.width = 0; + temporary.matrix = NULL; } + return *this; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/classes/comparison.cpp b/cyfre/classes/comparison.cpp index d1f3101..8bea4a8 100644 --- a/cyfre/classes/comparison.cpp +++ b/cyfre/classes/comparison.cpp @@ -5,23 +5,23 @@ #include namespace cyfre { - /// compare matrix - template - inline bool mat::operator==(const mat &that) const { - size_t n = width * height; - for (size_t i = 0; i < n; ++i) { - if (matrix[i] != that.matrix[i]) { - return false; - } - } - - return true; + /// compare matrix + template + inline bool mat::operator==(const mat &that) const { + size_t n = width * height; + for (size_t i = 0; i < n; ++i) { + if (matrix[i] != that.matrix[i]) { + return false; + } } - template - inline bool mat::operator!=(const mat &that) const { - return !(*this == that); - } + return true; + } + + template + inline bool mat::operator!=(const mat &that) const { + return !(*this == that); + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/classes/constructors.cpp b/cyfre/classes/constructors.cpp index 9006f31..38e1e7b 100644 --- a/cyfre/classes/constructors.cpp +++ b/cyfre/classes/constructors.cpp @@ -5,239 +5,239 @@ #include namespace cyfre { - /// initializes a 1x1 matrix with a value of zero - template - mat::mat() : matrix(NULL), height(0), width(0) { + /// initializes a 1x1 matrix with a value of zero + template + mat::mat() : matrix(NULL), height(0), width(0) { #ifdef DISPLAY_FUNC_CALLS - std::cout << "mat()\n"; - auto start = std::chrono::high_resolution_clock::now(); - auto finish = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(finish - start); - std::cout << "took " << duration.count() << " nanoseconds\n\n"; + std::cout << "mat()\n"; + auto start = std::chrono::high_resolution_clock::now(); + auto finish = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(finish - start); + std::cout << "took " << duration.count() << " nanoseconds\n\n"; #endif + } + + template + mat::mat(T one_value) : matrix(new T[1]), height(1), width(1) { + matrix[0] = one_value; + } + + /// initializes a matrix from a text file + template + mat::mat(std::string text_file, char separator) { + std::ifstream filereader; + filereader.open(text_file.c_str()); + + if (filereader.fail()) { + throw std::ios_base::failure( + "\n\nERROR : constructor::mat(\"" + text_file + + "\")\n" + "\tinitialization error, text file not found or might not be supported\n" + ); } - template - mat::mat(T one_value) : matrix(new T[1]), height(1), width(1) { - matrix[0] = one_value; - } - - /// initializes a matrix from a text file - template - mat::mat(std::string text_file, char separator) { - std::ifstream filereader; - filereader.open(text_file.c_str()); - - if (filereader.fail()) { - throw std::ios_base::failure( - "\n\nERROR : constructor::mat(\"" + text_file + - "\")\n" - "\tinitialization error, text file not found or might not be supported\n" - ); - } - - std::vector strlines; - std::string tmp; - - while (!filereader.eof()) { - getline(filereader, tmp); - strlines.push_back(tmp); - } - - std::vector> matrix_strings; - bool an_integer = true; - for (size_t i = 0; i < strlines.size(); ++i) { - std::vector row_parse = cyfre::helpers::parse(strlines[i], separator); - for (size_t j = 0; j < row_parse.size(); ++j) { - std::pair isvalid_isrational = cyfre::helpers::isanumber(row_parse[j]); - if (!isvalid_isrational.first) { - throw std::ios_base::failure( - "\n\nERROR : constructor::mat(\"" + text_file + - "\")\n" - "\tinitialization error, invalid number inside the text file:" + - text_file + ", on line:" + std::to_string(i) + "\n" - ); - } - if (isvalid_isrational.second) - an_integer = false; - } - matrix_strings.push_back(row_parse); - } + std::vector strlines; + std::string tmp; - for (size_t i = 1; i < matrix_strings.size(); ++i) { - if (matrix_strings[i].size() != matrix_strings[i - 1].size()) { - throw std::length_error( - "\n\nERROR : constructor::mat(\"" + text_file + - "\")\n" - "\tinitialization error, the text file provided an unequal length of rows\n" - "\terror occurs in text file after comparison on line " + - std::to_string(i) + " & " + std::to_string(i + 1) + "\n" - ); - } - } - - height = matrix_strings.size(); - width = matrix_strings[0].size(); - - matrix = new T[height * width]; - - size_t cnt = 0; - for (size_t i = 0; i < matrix_strings.size(); ++i) { - for (size_t j = 0; j < matrix_strings[i].size(); ++j) { - if (an_integer) - matrix[cnt++] = (T) (std::stoll(matrix_strings[i][j])); - else - matrix[cnt++] = (T) (std::stold(matrix_strings[i][j])); - } - } + while (!filereader.eof()) { + getline(filereader, tmp); + strlines.push_back(tmp); } - /// initializes a matrix using a 2 dimension vector : @arg std::vector> matrix - template - mat::mat(std::initializer_list> matrix) { - auto outer_it = matrix.begin(); - size_t prev_row_len = (*outer_it).size(); - - for (auto &row: matrix) { - if (row.size() != prev_row_len) { - throw std::length_error( - "\n\nERROR : mat(std::initializer_list> matrix)\n" - "\tthe inner rows inside std::initializer_list> is not equal\n" - ); - } - } - - height = matrix.size(); - width = (*outer_it).size(); - - this->matrix = new T[height * width]; - - for (size_t i = 0; i < height; ++i, ++outer_it) { - std::copy((*outer_it).begin(), (*outer_it).end(), this->matrix + (i * width)); + std::vector> matrix_strings; + bool an_integer = true; + for (size_t i = 0; i < strlines.size(); ++i) { + std::vector row_parse = cyfre::helpers::parse(strlines[i], separator); + for (size_t j = 0; j < row_parse.size(); ++j) { + std::pair isvalid_isrational = cyfre::helpers::isanumber(row_parse[j]); + if (!isvalid_isrational.first) { + throw std::ios_base::failure( + "\n\nERROR : constructor::mat(\"" + text_file + + "\")\n" + "\tinitialization error, invalid number inside the text file:" + + text_file + ", on line:" + std::to_string(i) + "\n" + ); } + if (isvalid_isrational.second) + an_integer = false; + } + matrix_strings.push_back(row_parse); } - /// initializes a matrix using a vector : @arg std::vector matrix - template - mat::mat(std::initializer_list array_vector) : height(1), width(array_vector.size()) { - matrix = new T[height * width]; - std::copy(array_vector.begin(), array_vector.end(), matrix); + for (size_t i = 1; i < matrix_strings.size(); ++i) { + if (matrix_strings[i].size() != matrix_strings[i - 1].size()) { + throw std::length_error( + "\n\nERROR : constructor::mat(\"" + text_file + + "\")\n" + "\tinitialization error, the text file provided an unequal length of rows\n" + "\terror occurs in text file after comparison on line " + + std::to_string(i) + " & " + std::to_string(i + 1) + "\n" + ); + } } - /// initializes a matrix given a @arg height, @arg width for the matrix shape, and a @arg default_value of all - /// elements in the matrix - template - mat::mat(const size_t height, const size_t width, const T default_value) - : matrix(new T[height * width]), height(height), width(width) { - size_t n = height * width; + height = matrix_strings.size(); + width = matrix_strings[0].size(); - for (size_t i = 0; i < n; ++i) { - matrix[i] = default_value; - } - } + matrix = new T[height * width]; - /// initializes a matrix given a @arg height, @arg width for the matrix shape, that have a random values form the - /// given @arg lower_bound to @arg upper_bound - template - mat::mat( - const size_t height, const size_t width, const RANDOM typechoice, const T lower_bound, const T upper_bound - ) - : matrix(new T[height * width]), height(height), width(width) { - unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); - std::mt19937_64 rand_engine(seed); - std::uniform_real_distribution random_number_float(lower_bound, upper_bound); - std::uniform_int_distribution random_number_int(lower_bound, upper_bound); - - size_t n = height * width; - - for (size_t i = 0; i < n; ++i) { - switch (typechoice) { - case RANDOM::INTEGER: - matrix[i] = random_number_int(rand_engine); - break; - case RANDOM::REAL: - matrix[i] = random_number_float(rand_engine); - break; - default: - throw std::invalid_argument( - "\n\nERROR : mat(const size_t height, const size_t width, const RANDOM typechoice, const T " - "lower_bound, const T upper_bound)\n\tinvalid random type" - ); - } - } + size_t cnt = 0; + for (size_t i = 0; i < matrix_strings.size(); ++i) { + for (size_t j = 0; j < matrix_strings[i].size(); ++j) { + if (an_integer) + matrix[cnt++] = (T) (std::stoll(matrix_strings[i][j])); + else + matrix[cnt++] = (T) (std::stold(matrix_strings[i][j])); + } + } + } + + /// initializes a matrix using a 2 dimension vector : @arg std::vector> matrix + template + mat::mat(std::initializer_list> matrix) { + auto outer_it = matrix.begin(); + size_t prev_row_len = (*outer_it).size(); + + for (auto &row: matrix) { + if (row.size() != prev_row_len) { + throw std::length_error( + "\n\nERROR : mat(std::initializer_list> matrix)\n" + "\tthe inner rows inside std::initializer_list> is not equal\n" + ); + } } - /// initializes a square matrix with a given 'x' scalar values of elements in the main diagonal - template - mat::mat(const TYPE matrix_type, const size_t n, T scalar) { - if (matrix_type == TYPE::IDENTITY) - scalar = 1; - - height = width = n; + height = matrix.size(); + width = (*outer_it).size(); - matrix = new T[n * n]; + this->matrix = new T[height * width]; - size_t N = n * n; - for (size_t i = 0; i < N; ++i) { - matrix[i] = 0; - } - - for (size_t i = 0; i < n; ++i) { - matrix[i * width + i] = scalar; - } + for (size_t i = 0; i < height; ++i, ++outer_it) { + std::copy((*outer_it).begin(), (*outer_it).end(), this->matrix + (i * width)); } - - template - mat::mat(const TYPE matrix_type, const size_t n) : mat(matrix_type, n, 0) { - switch (matrix_type) { - case TYPE::IDENTITY: - break; - case TYPE::NULLZERO: - break; - case TYPE::SCALARMATRIX: - throw std::invalid_argument( - "\n\nERROR : mat(TYPE matrix_type, size_t n, T scalar)\n" - "\tSCALAR matrix initialization, missing argument\n" - ); - default: - throw std::invalid_argument( - "\n\nERROR : mat()\n\tmatrix initialization - constructor invalid given an invalid TYPE\n" - ); - } + } + + /// initializes a matrix using a vector : @arg std::vector matrix + template + mat::mat(std::initializer_list array_vector) : height(1), width(array_vector.size()) { + matrix = new T[height * width]; + std::copy(array_vector.begin(), array_vector.end(), matrix); + } + + /// initializes a matrix given a @arg height, @arg width for the matrix shape, and a @arg default_value of all + /// elements in the matrix + template + mat::mat(const size_t height, const size_t width, const T default_value) + : matrix(new T[height * width]), height(height), width(width) { + size_t n = height * width; + + for (size_t i = 0; i < n; ++i) { + matrix[i] = default_value; } + } + + /// initializes a matrix given a @arg height, @arg width for the matrix shape, that have a random values form the + /// given @arg lower_bound to @arg upper_bound + template + mat::mat( + const size_t height, const size_t width, const RANDOM typechoice, const T lower_bound, const T upper_bound + ) + : matrix(new T[height * width]), height(height), width(width) { + unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); + std::mt19937_64 rand_engine(seed); + std::uniform_real_distribution random_number_float(lower_bound, upper_bound); + std::uniform_int_distribution random_number_int(lower_bound, upper_bound); + + size_t n = height * width; + + for (size_t i = 0; i < n; ++i) { + switch (typechoice) { + case RANDOM::INTEGER: + matrix[i] = random_number_int(rand_engine); + break; + case RANDOM::REAL: + matrix[i] = random_number_float(rand_engine); + break; + default: + throw std::invalid_argument( + "\n\nERROR : mat(const size_t height, const size_t width, const RANDOM typechoice, const T " + "lower_bound, const T upper_bound)\n\tinvalid random type" + ); + } + } + } - /// copy constructor - template - mat::mat(const mat &original) { - size_t n = original.height * original.width; + /// initializes a square matrix with a given 'x' scalar values of elements in the main diagonal + template + mat::mat(const TYPE matrix_type, const size_t n, T scalar) { + if (matrix_type == TYPE::IDENTITY) + scalar = 1; - height = original.height; - width = original.width; + height = width = n; - matrix = new T[n]; + matrix = new T[n * n]; - std::memcpy(matrix, original.matrix, sizeof(T) * n); + size_t N = n * n; + for (size_t i = 0; i < N; ++i) { + matrix[i] = 0; } - /// move constructor - template - mat::mat(mat &&temporary) { - height = temporary.height; - width = temporary.width; - matrix = temporary.matrix; - - temporary.height = 0; - temporary.width = 0; - temporary.matrix = NULL; + for (size_t i = 0; i < n; ++i) { + matrix[i * width + i] = scalar; } - - template - mat::~mat() { - if (height && width) - delete[] matrix; - height = 0; - width = 0; + } + + template + mat::mat(const TYPE matrix_type, const size_t n) : mat(matrix_type, n, 0) { + switch (matrix_type) { + case TYPE::IDENTITY: + break; + case TYPE::NULLZERO: + break; + case TYPE::SCALARMATRIX: + throw std::invalid_argument( + "\n\nERROR : mat(TYPE matrix_type, size_t n, T scalar)\n" + "\tSCALAR matrix initialization, missing argument\n" + ); + default: + throw std::invalid_argument( + "\n\nERROR : mat()\n\tmatrix initialization - constructor invalid given an invalid TYPE\n" + ); } + } + + /// copy constructor + template + mat::mat(const mat &original) { + size_t n = original.height * original.width; + + height = original.height; + width = original.width; + + matrix = new T[n]; + + std::memcpy(matrix, original.matrix, sizeof(T) * n); + } + + /// move constructor + template + mat::mat(mat &&temporary) { + height = temporary.height; + width = temporary.width; + matrix = temporary.matrix; + + temporary.height = 0; + temporary.width = 0; + temporary.matrix = NULL; + } + + template + mat::~mat() { + if (height && width) + delete[] matrix; + height = 0; + width = 0; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/classes/display.cpp b/cyfre/classes/display.cpp index e5b8b35..87ef8fa 100644 --- a/cyfre/classes/display.cpp +++ b/cyfre/classes/display.cpp @@ -5,52 +5,52 @@ #include namespace cyfre { - template - void display(const mat &input) { - // 100 width can still be displayed - // 60 height can still be displayed + template + void display(const mat &input) { + // 100 width can still be displayed + // 60 height can still be displayed - std::vector matrixstr; + std::vector matrixstr; - size_t n = input.height * input.width; + size_t n = input.height * input.width; - for (size_t i = 0; i < n; ++i) - matrixstr.push_back(std::to_string(input.matrix[i])); + for (size_t i = 0; i < n; ++i) + matrixstr.push_back(std::to_string(input.matrix[i])); - std::vector max_cols_len(input.width, 0); + std::vector max_cols_len(input.width, 0); - for (size_t j = 0; j < input.width; ++j) { - for (size_t i = 0; i < input.height; ++i) { - if (matrixstr[i * input.width + j].size() > max_cols_len[j]) { - max_cols_len[j] = matrixstr[i * input.width + j].size(); - } - } - } - - for (size_t i = 0; i < input.height; ++i) { - if (i == 0) - std::cout << "[["; - else - std::cout << " ["; - - for (size_t j = 0; j < input.width; ++j) { - size_t front_space = max_cols_len[j] - matrixstr[i * input.width + j].size(); - while (front_space--) - std::cout << ' '; - std::cout << matrixstr[i * input.width + j]; - if (j != input.width - 1) - std::cout << ", "; - else - std::cout << "]"; - } - if (i != input.height - 1) - std::cout << ",\n"; - else - std::cout << "]\n"; + for (size_t j = 0; j < input.width; ++j) { + for (size_t i = 0; i < input.height; ++i) { + if (matrixstr[i * input.width + j].size() > max_cols_len[j]) { + max_cols_len[j] = matrixstr[i * input.width + j].size(); } + } + } - std::cout.width(0); + for (size_t i = 0; i < input.height; ++i) { + if (i == 0) + std::cout << "[["; + else + std::cout << " ["; + + for (size_t j = 0; j < input.width; ++j) { + size_t front_space = max_cols_len[j] - matrixstr[i * input.width + j].size(); + while (front_space--) + std::cout << ' '; + std::cout << matrixstr[i * input.width + j]; + if (j != input.width - 1) + std::cout << ", "; + else + std::cout << "]"; + } + if (i != input.height - 1) + std::cout << ",\n"; + else + std::cout << "]\n"; } + + std::cout.width(0); + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/classes/indexing.cpp b/cyfre/classes/indexing.cpp index 4d295db..fbfcb89 100644 --- a/cyfre/classes/indexing.cpp +++ b/cyfre/classes/indexing.cpp @@ -5,43 +5,43 @@ #include namespace cyfre { - template - inline T &mat::operator()(size_t i, size_t j) { + template + inline T &mat::operator()(size_t i, size_t j) { #ifndef CHECK_RANGE_DISABLE - if ((i > height - 1)) { - throw std::out_of_range( - "\n\nERROR : T& operator()(size_t i, size_t j)\n" - "\tthe given row index is out of bound\n" - ); - } else if ((j > width - 1)) { - throw std::out_of_range( - "\n\nERROR : T& operator()(size_t i, size_t j)\n" - "\tthe given column index is out of bound\n" - ); - } + if ((i > height - 1)) { + throw std::out_of_range( + "\n\nERROR : T& operator()(size_t i, size_t j)\n" + "\tthe given row index is out of bound\n" + ); + } else if ((j > width - 1)) { + throw std::out_of_range( + "\n\nERROR : T& operator()(size_t i, size_t j)\n" + "\tthe given column index is out of bound\n" + ); + } #endif - return matrix[i * width + j]; - } + return matrix[i * width + j]; + } - template - inline const T &mat::operator()(size_t i, size_t j) const { + template + inline const T &mat::operator()(size_t i, size_t j) const { #ifndef CHECK_RANGE_DISABLE - if ((i > height - 1)) { - throw std::out_of_range( - "\n\nERROR : const T& operator()(size_t i, size_t j)\n" - "\tthe given row index is out of bound\n" - ); - } else if ((j > width - 1)) { - throw std::out_of_range( - "\n\nERROR : const T& operator()(size_t i, size_t j)\n" - "\tthe given column index is out of bound\n" - ); - } + if ((i > height - 1)) { + throw std::out_of_range( + "\n\nERROR : const T& operator()(size_t i, size_t j)\n" + "\tthe given row index is out of bound\n" + ); + } else if ((j > width - 1)) { + throw std::out_of_range( + "\n\nERROR : const T& operator()(size_t i, size_t j)\n" + "\tthe given column index is out of bound\n" + ); + } #endif - return matrix[i * width + j]; - } + return matrix[i * width + j]; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/classes/matrix_class.hpp b/cyfre/classes/matrix_class.hpp index 57bf0eb..42f406f 100644 --- a/cyfre/classes/matrix_class.hpp +++ b/cyfre/classes/matrix_class.hpp @@ -23,204 +23,204 @@ namespace cyfre { #define TRANSPOSE_MT_TREASHOLD 3364000 - /// MATRIX TYPES FOR CONSTRUCTING A MATRIX - enum TYPE - { - /// @arg - a square matrix where every element is '0' - NULLZERO, - /// @arg - a square matrix where every elements in the main diagonal has a value of '1' - IDENTITY, - /// @arg - a square matrix where every elements in the main diagonal has a value of a given 'N' - SCALARMATRIX - }; - - /// enum type for random value constructor - enum RANDOM - { - INTEGER, - REAL - }; - - /// SCALAR OPERATIONS - enum SCALAR - { - ADD, - SUB, - MUL, - DIV - }; - - template - class mat { - public: - - T *matrix = NULL; - size_t height = 0; - size_t width = 0; - - // ============================== constructors ============================== - mat(); - mat(T one_value); - mat(std::string text_file, char separator); - mat(std::initializer_list> matrix); - mat(std::initializer_list array_vector); - mat(const size_t height, const size_t width, const T default_value); - mat(const size_t height, const size_t width, const RANDOM typechoice, const T lower_bound, const T upper_bound); - mat(const TYPE matrix_type, const size_t n, T scalar); - mat(const TYPE matrix_type, const size_t n); - ~mat(); - - // copy constructor - mat(const mat &original); - - // move constructor - mat(mat &&temporary); - - // copy assignment - mat &operator=(const mat &original); - - // move assignment - mat &operator=(mat &&temporary); - - // compare matrix - inline bool operator==(const mat &that) const; - inline bool operator!=(const mat &that) const; - - // =============================== methods =================================== - /// @returns T sum, the total sum of all the elements of the matrix - T sum() const; - T trace() const; - - T max(); - - T min(); - - void scale_row(const size_t row_index, const SCALAR scalar_operation, const T value); - void row_operation(const size_t output_index, const SCALAR scalar_operation, size_t input_index); - void row_swap(size_t row_a, size_t row_b); - void row_scale(T scalar, size_t base_row); - void row_scale(T scalar, size_t scale_row, size_t base_row); - - void scale_column(const size_t column_index, const SCALAR scalar_operation, const T value); - void column_operation(const size_t output_index, const SCALAR scalar_operation, size_t input_index); - void column_swap(size_t column_a, size_t column_b); - void column_scale(T scalar, size_t base_column); - void column_scale(T scalar, size_t scale_column, size_t base_column); - - // ============================== SAFE INDEXING ================================ - - inline T &operator()(size_t i, size_t j); - inline const T &operator()(size_t i, size_t j) const; - - // ============================== MATRIX OPERATIONS ============================== - - /// --------------------------- addition --------------------------------- - - /// @returns element by element addition - old - inline mat operator+(const mat &that) const; - inline void operator+=(const mat &that); - - inline mat operator+(const T scalar) const; - inline void operator+=(const T scalar); - - template - inline friend mat operator+(const S scalar, const mat &that); - - /// --------------------------- subtraction --------------------------------- - - /// @returns element by element subtraction - old - inline mat operator-(const mat &that) const; - inline void operator-=(const mat &that); + /// MATRIX TYPES FOR CONSTRUCTING A MATRIX + enum TYPE + { + /// @arg - a square matrix where every element is '0' + NULLZERO, + /// @arg - a square matrix where every elements in the main diagonal has a value of '1' + IDENTITY, + /// @arg - a square matrix where every elements in the main diagonal has a value of a given 'N' + SCALARMATRIX + }; + + /// enum type for random value constructor + enum class RANDOM + { + INTEGER, + REAL + }; + + /// SCALAR OPERATIONS + enum class SCALAR + { + ADD, + SUB, + MUL, + DIV + }; + + template + class mat { + public: + + T *matrix = NULL; + size_t height = 0; + size_t width = 0; + + // ============================== constructors ============================== + mat(); + mat(T one_value); + mat(std::string text_file, char separator); + mat(std::initializer_list> matrix); + mat(std::initializer_list array_vector); + mat(const size_t height, const size_t width, const T default_value); + mat(const size_t height, const size_t width, const RANDOM typechoice, const T lower_bound, const T upper_bound); + mat(const TYPE matrix_type, const size_t n, T scalar); + mat(const TYPE matrix_type, const size_t n); + ~mat(); + + // copy constructor + mat(const mat &original); + + // move constructor + mat(mat &&temporary); + + // copy assignment + mat &operator=(const mat &original); + + // move assignment + mat &operator=(mat &&temporary); + + // compare matrix + inline bool operator==(const mat &that) const; + inline bool operator!=(const mat &that) const; + + // =============================== methods =================================== + /// @returns T sum, the total sum of all the elements of the matrix + T sum() const; + T trace() const; + + T max(); + + T min(); + + void scale_row(const size_t row_index, const SCALAR scalar_operation, const T value); + void row_operation(const size_t output_index, const SCALAR scalar_operation, size_t input_index); + void row_swap(size_t row_a, size_t row_b); + void row_scale(T scalar, size_t base_row); + void row_scale(T scalar, size_t scale_row, size_t base_row); + + void scale_column(const size_t column_index, const SCALAR scalar_operation, const T value); + void column_operation(const size_t output_index, const SCALAR scalar_operation, size_t input_index); + void column_swap(size_t column_a, size_t column_b); + void column_scale(T scalar, size_t base_column); + void column_scale(T scalar, size_t scale_column, size_t base_column); + + // ============================== SAFE INDEXING ================================ + + inline T &operator()(size_t i, size_t j); + inline const T &operator()(size_t i, size_t j) const; + + // ============================== MATRIX OPERATIONS ============================== + + /// --------------------------- addition --------------------------------- + + /// @returns element by element addition - old + inline mat operator+(const mat &that) const; + inline void operator+=(const mat &that); + + inline mat operator+(const T scalar) const; + inline void operator+=(const T scalar); + + template + inline friend mat operator+(const S scalar, const mat &that); + + /// --------------------------- subtraction --------------------------------- + + /// @returns element by element subtraction - old + inline mat operator-(const mat &that) const; + inline void operator-=(const mat &that); - inline mat operator-(const T scalar) const; - inline void operator-=(const T scalar); + inline mat operator-(const T scalar) const; + inline void operator-=(const T scalar); - template - inline friend mat operator-(const S scalar, const mat &that); + template + inline friend mat operator-(const S scalar, const mat &that); - /// ---------------------- Division ----------------------------- - /// @returns element by element division - inline mat operator/(const mat &that) const; - inline void operator/=(const mat &that); + /// ---------------------- Division ----------------------------- + /// @returns element by element division + inline mat operator/(const mat &that) const; + inline void operator/=(const mat &that); - inline mat operator/(const T scalar) const; - inline void operator/=(const T scalar); + inline mat operator/(const T scalar) const; + inline void operator/=(const T scalar); - template - inline friend mat operator/(const S scalar, const mat &that); + template + inline friend mat operator/(const S scalar, const mat &that); - /// ---------------------- Multiplication ----------------------------- - /// @returns matrix multiplication / dot product - inline mat operator*(const mat &that) const; - inline void operator*=(const mat &that); - inline void hadamard(const mat &that); + /// ---------------------- Multiplication ----------------------------- + /// @returns matrix multiplication / dot product + inline mat operator*(const mat &that) const; + inline void operator*=(const mat &that); + inline void hadamard(const mat &that); - /// ---------------------- Division ---------------------------------- - inline mat operator*(const T scalar) const; - inline void operator*=(const T scalar); + /// ---------------------- Division ---------------------------------- + inline mat operator*(const T scalar) const; + inline void operator*=(const T scalar); - template - inline friend mat operator*(const S scalar, const mat &that); + template + inline friend mat operator*(const S scalar, const mat &that); - /// ---------------------- comparison -------------------------------- - int compare(const mat &with) const; + /// ---------------------- comparison -------------------------------- + int compare(const mat &with) const; - // ============================== SHAPING ============================== - void transpose(); - void padding(size_t pad_length); - void padding(size_t pad_height, size_t pad_width); + // ============================== SHAPING ============================== + void transpose(); + void padding(size_t pad_length); + void padding(size_t pad_height, size_t pad_width); - // ============================== MATRIX EXPOENTIAL ============================== + // ============================== MATRIX EXPOENTIAL ============================== - /// @returns raised matrix to a certain number 'p' - /// @note raising to a negative integer(inverse) is not supported yet but will be in the future - void power(size_t p); - void inv(); - void ref(); - void rref(); - void apply(std::function function_name); + /// @returns raised matrix to a certain number 'p' + /// @note raising to a negative integer(inverse) is not supported yet but will be in the future + void power(size_t p); + void inv(); + void ref(); + void rref(); + void apply(std::function function_name); - }; // end of mat class + }; // end of mat class - template - void display(const mat &input); + template + void display(const mat &input); } // namespace cyfre #ifndef MAKE_BUILD - #include "assign.cpp" - #include "comparison.cpp" - #include "constructors.cpp" - #include "display.cpp" - #include "indexing.cpp" - - #include "../matrix-elementary-operation/col_operations.cpp" - #include "../matrix-elementary-operation/row_operations.cpp" - - #include "../matrix-matrix/mm_addition.cpp" - #include "../matrix-matrix/mm_division.cpp" - #include "../matrix-matrix/mm_hadamard.cpp" - #include "../matrix-matrix/mm_multiplication.cpp" - #include "../matrix-matrix/mm_subtraction.cpp" - - #include "../matrix-scalar/ms_addition.cpp" - #include "../matrix-scalar/ms_division.cpp" - #include "../matrix-scalar/ms_multiplication.cpp" - #include "../matrix-scalar/ms_subtraction.cpp" - - #include "../methods/determinant.cpp" - #include "../methods/minmax.cpp" - #include "../methods/sum.cpp" - #include "../methods/trace.cpp" - - #include "../transform/apply.cpp" - #include "../transform/inverse.cpp" - #include "../transform/power.cpp" - #include "../transform/ref.cpp" - #include "../transform/rref.cpp" - - #include "../shaping/padding.cpp" - #include "../shaping/transpose.cpp" + #include "assign.cpp" + #include "comparison.cpp" + #include "constructors.cpp" + #include "display.cpp" + #include "indexing.cpp" + + #include "../matrix-elementary-operation/col_operations.cpp" + #include "../matrix-elementary-operation/row_operations.cpp" + + #include "../matrix-matrix/mm_addition.cpp" + #include "../matrix-matrix/mm_division.cpp" + #include "../matrix-matrix/mm_hadamard.cpp" + #include "../matrix-matrix/mm_multiplication.cpp" + #include "../matrix-matrix/mm_subtraction.cpp" + + #include "../matrix-scalar/ms_addition.cpp" + #include "../matrix-scalar/ms_division.cpp" + #include "../matrix-scalar/ms_multiplication.cpp" + #include "../matrix-scalar/ms_subtraction.cpp" + + #include "../methods/determinant.cpp" + #include "../methods/minmax.cpp" + #include "../methods/sum.cpp" + #include "../methods/trace.cpp" + + #include "../transform/apply.cpp" + #include "../transform/inverse.cpp" + #include "../transform/power.cpp" + #include "../transform/ref.cpp" + #include "../transform/rref.cpp" + + #include "../shaping/padding.cpp" + #include "../shaping/transpose.cpp" #endif diff --git a/cyfre/cyfre.hpp b/cyfre/cyfre.hpp deleted file mode 100644 index 757ab68..0000000 --- a/cyfre/cyfre.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CYFRE_HPP -#define CYFRE_HPP - -#include "classes/matrix_class.hpp" - -/* - INCLUDES ALL FILES IN THE CYFRE LIBRARY -*/ - -/* compiler -D flags - -CHECK_RANGE_DISABLE - Disable internal range checking, slightly speeds up the program (do not use in development) -CHECK_SHAPE_DISABLE - Disable internal shape checking of matricies in matrix operations, slightly speeds up the - -DISPLAY_FUNC_CALLS - Show console logs of function calls with duration - - -*/ - -#endif \ No newline at end of file diff --git a/cyfre/helpers/helper_functions.hpp b/cyfre/helpers/helper_functions.hpp index 9810c47..bcf0e40 100644 --- a/cyfre/helpers/helper_functions.hpp +++ b/cyfre/helpers/helper_functions.hpp @@ -7,60 +7,60 @@ #include namespace cyfre::helpers { - std::pair isanumber(const std::string &value) { - size_t rational_true = 0; - try { - size_t value_size = value.size(); - if (value_size <= 0) { - throw value_size; - } + std::pair isanumber(const std::string &value) { + size_t rational_true = 0; + try { + size_t value_size = value.size(); + if (value_size <= 0) { + throw value_size; + } - for (size_t i = 0; i < value_size; ++i) { - if (value[i] == '-' && i == 0) - continue; - if (value[i] == '.') { - rational_true++; - continue; - } - - if ((value[i] < '0') ^ (value[i] > '9')) { - throw value; - } - } + for (size_t i = 0; i < value_size; ++i) { + if (value[i] == '-' && i == 0) + continue; + if (value[i] == '.') { + rational_true++; + continue; + } - if (rational_true > 1) { - throw value; - } - } catch (size_t NO_VALUE_ERROR) { - return {false, false}; - } catch (std::string VALUE_ERROR) { - return {false, false}; + if ((value[i] < '0') ^ (value[i] > '9')) { + throw value; } - return {true, rational_true}; + } + + if (rational_true > 1) { + throw value; + } + } catch (size_t NO_VALUE_ERROR) { + return {false, false}; + } catch (std::string VALUE_ERROR) { + return {false, false}; } + return {true, rational_true}; + } - std::vector parse(const std::string &str, char separator) { - bool start = false; - size_t startwi, endwi; + std::vector parse(const std::string &str, char separator) { + bool start = false; + size_t startwi, endwi; - std::vector indecies; - size_t i = 0; - for (std::string::const_iterator pos = str.begin(); true; i++, pos++) { - if (pos == str.end()) { - endwi = i - startwi; - indecies.push_back(str.substr(startwi, endwi)); - start = false; - break; - } else if (str[i] != separator && !start) { - startwi = i; - start = true; - } else if (str[i] == separator && start) { - endwi = i - startwi; - indecies.push_back(str.substr(startwi, endwi)); - start = false; - } - } - return indecies; + std::vector indecies; + size_t i = 0; + for (std::string::const_iterator pos = str.begin(); true; i++, pos++) { + if (pos == str.end()) { + endwi = i - startwi; + indecies.push_back(str.substr(startwi, endwi)); + start = false; + break; + } else if (str[i] != separator && !start) { + startwi = i; + start = true; + } else if (str[i] == separator && start) { + endwi = i - startwi; + indecies.push_back(str.substr(startwi, endwi)); + start = false; + } } + return indecies; + } } // namespace cyfre::helpers #endif \ No newline at end of file diff --git a/cyfre/helpers/randomizer.hpp b/cyfre/helpers/randomizer.hpp index 3cdf403..812c73e 100644 --- a/cyfre/helpers/randomizer.hpp +++ b/cyfre/helpers/randomizer.hpp @@ -11,78 +11,78 @@ /// supports: C++11 and above only namespace randomize { - template - T integer() { - T machine_min = T(std::numeric_limits::min()); - T machine_max = T(std::numeric_limits::max()); - unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); - E rand_engine(seed); - std::uniform_int_distribution random_number(machine_min, machine_max); - return random_number(rand_engine); - } - - template - T integer(T min, T max) { - T machine_min = T(std::numeric_limits::min()); - T machine_max = T(std::numeric_limits::max()); + template + T integer() { + T machine_min = T(std::numeric_limits::min()); + T machine_max = T(std::numeric_limits::max()); + unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); + E rand_engine(seed); + std::uniform_int_distribution random_number(machine_min, machine_max); + return random_number(rand_engine); + } - if (min > max) { - throw std::range_error(std::string( - "\n\nERROR: randomize::integer(min,max)\n\tthe min(" + std::to_string(min) + - ") given is greater than the given max(" + std::to_string(max) + ")\n" - )); - } else if (max < min) { - throw std::range_error(std::string( - "\n\nERROR: randomize::integer(min,max)\n\tthe max(" + std::to_string(max) + - ") given is less than the given min(" + std::to_string(min) + ")\n" - )); - } else if (min < machine_min) { - throw std::range_error(std::string( - "\n\nERROR: randomize::integer(min,max)\n\tthe min(" + std::to_string(min) + - ") overflow - limit:" + std::to_string(machine_min) + "\n" - )); - } else if (max > machine_max) { - throw std::range_error(std::string( - "\n\nERROR: randomize::integer(min,max)\n\tthe max(" + std::to_string(max) + - ") overflow - limit:" + std::to_string(machine_max) + "\n" - )); - } + template + T integer(T min, T max) { + T machine_min = T(std::numeric_limits::min()); + T machine_max = T(std::numeric_limits::max()); - unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); - E rand_engine(seed); - std::uniform_int_distribution random_number(min, max); - return random_number(rand_engine); + if (min > max) { + throw std::range_error(std::string( + "\n\nERROR: randomize::integer(min,max)\n\tthe min(" + std::to_string(min) + + ") given is greater than the given max(" + std::to_string(max) + ")\n" + )); + } else if (max < min) { + throw std::range_error(std::string( + "\n\nERROR: randomize::integer(min,max)\n\tthe max(" + std::to_string(max) + + ") given is less than the given min(" + std::to_string(min) + ")\n" + )); + } else if (min < machine_min) { + throw std::range_error(std::string( + "\n\nERROR: randomize::integer(min,max)\n\tthe min(" + std::to_string(min) + + ") overflow - limit:" + std::to_string(machine_min) + "\n" + )); + } else if (max > machine_max) { + throw std::range_error(std::string( + "\n\nERROR: randomize::integer(min,max)\n\tthe max(" + std::to_string(max) + + ") overflow - limit:" + std::to_string(machine_max) + "\n" + )); } - template - T real() { - T machine_min = T(std::numeric_limits::min()); - T machine_max = T(std::numeric_limits::max()); - unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); - E rand_engine(seed); - std::uniform_real_distribution random_number(machine_min, machine_max); - return random_number(rand_engine); - } + unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); + E rand_engine(seed); + std::uniform_int_distribution random_number(min, max); + return random_number(rand_engine); + } - template - T real(T min, T max) { - if (min > max) { - throw std::range_error(std::string( - "\n\nERROR: randomize::real(min,max)\n\tthe min(" + std::to_string(min) + - ") given is greater than the given max(" + std::to_string(max) + ")\n" - )); - } else if (max < min) { - throw std::range_error(std::string( - "\n\nERROR: randomize::real(min,max)\n\tthe max(" + std::to_string(max) + - ") given is less than the given min(" + std::to_string(min) + ")\n" - )); - } + template + T real() { + T machine_min = T(std::numeric_limits::min()); + T machine_max = T(std::numeric_limits::max()); + unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); + E rand_engine(seed); + std::uniform_real_distribution random_number(machine_min, machine_max); + return random_number(rand_engine); + } - unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); - E rand_engine(seed); - std::uniform_real_distribution random_number(min, max); - return random_number(rand_engine); + template + T real(T min, T max) { + if (min > max) { + throw std::range_error(std::string( + "\n\nERROR: randomize::real(min,max)\n\tthe min(" + std::to_string(min) + + ") given is greater than the given max(" + std::to_string(max) + ")\n" + )); + } else if (max < min) { + throw std::range_error(std::string( + "\n\nERROR: randomize::real(min,max)\n\tthe max(" + std::to_string(max) + + ") given is less than the given min(" + std::to_string(min) + ")\n" + )); } + + unsigned seed = std::chrono::steady_clock::now().time_since_epoch().count(); + E rand_engine(seed); + std::uniform_real_distribution random_number(min, max); + return random_number(rand_engine); + } } // namespace randomize #endif diff --git a/cyfre/matrix-elementary-operation/col_operations.cpp b/cyfre/matrix-elementary-operation/col_operations.cpp index c32ef8b..f8a7037 100644 --- a/cyfre/matrix-elementary-operation/col_operations.cpp +++ b/cyfre/matrix-elementary-operation/col_operations.cpp @@ -5,156 +5,156 @@ #include namespace cyfre { - /// 'ADD,SUB,MUL, or DIV' a given 'const T value' to all elements of a selected 'const size_t column_index' - template - void mat::scale_column(const size_t column_index, const SCALAR scalar_operation, const T value) { + /// 'ADD,SUB,MUL, or DIV' a given 'const T value' to all elements of a selected 'const size_t column_index' + template + void mat::scale_column(const size_t column_index, const SCALAR scalar_operation, const T value) { #ifndef CHECK_RANGE_DISABLE - if ((column_index > width - 1)) { - throw std::out_of_range( - "\n\nERROR : void scale_column(const size_t column_index, const SCALAR scalar_operation, const T " - "value)\n" - "\tthe given column index is out of bound\n" - ); - } + if ((column_index > width - 1)) { + throw std::out_of_range( + "\n\nERROR : void scale_column(const size_t column_index, const SCALAR scalar_operation, const T " + "value)\n" + "\tthe given column index is out of bound\n" + ); + } #endif - auto operation_function = [scalar_operation](const T matrix_index, const T operation_value) { - switch (scalar_operation) { - case ADD: - return matrix_index + operation_value; - case SUB: - return matrix_index - operation_value; - case MUL: - return matrix_index * operation_value; - case DIV: - return matrix_index / operation_value; - default: - throw std::invalid_argument( - "\n\nERROR : scale_column(const size_t column_index, const SCALAR scalar_operation, const T " - "value)\n" - "\tscale_column was given an invalid scalar operation\n" - ); - } - }; + auto operation_function = [scalar_operation](const T matrix_index, const T operation_value) { + switch (scalar_operation) { + case ADD: + return matrix_index + operation_value; + case SUB: + return matrix_index - operation_value; + case MUL: + return matrix_index * operation_value; + case DIV: + return matrix_index / operation_value; + default: + throw std::invalid_argument( + "\n\nERROR : scale_column(const size_t column_index, const SCALAR scalar_operation, const T " + "value)\n" + "\tscale_column was given an invalid scalar operation\n" + ); + } + }; - for (size_t i = 0; i < height; ++i) { - matrix[i * width + column_index] = operation_function(matrix[i * width + column_index], value); - } + for (size_t i = 0; i < height; ++i) { + matrix[i * width + column_index] = operation_function(matrix[i * width + column_index], value); } + } - template - void mat::column_operation(const size_t output_index, const SCALAR scalar_operation, size_t input_index) { + template + void mat::column_operation(const size_t output_index, const SCALAR scalar_operation, size_t input_index) { #ifndef CHECK_RANGE_DISABLE - if ((output_index > width - 1)) { - throw std::out_of_range( - "\n\nERROR : void column_operation(const size_t output_index, const SCALAR scalar_operation, size_t " - "input_index)\n" - "\tthe given column 'output_index' is out of bound\n" - ); - } else if ((input_index > width - 1)) { - throw std::out_of_range( - "\n\nERROR : void column_operation(const size_t output_index, const SCALAR scalar_operation, size_t " - "input_index)\n" - "\tthe given column 'input_index' is out of bound\n" - ); - } + if ((output_index > width - 1)) { + throw std::out_of_range( + "\n\nERROR : void column_operation(const size_t output_index, const SCALAR scalar_operation, size_t " + "input_index)\n" + "\tthe given column 'output_index' is out of bound\n" + ); + } else if ((input_index > width - 1)) { + throw std::out_of_range( + "\n\nERROR : void column_operation(const size_t output_index, const SCALAR scalar_operation, size_t " + "input_index)\n" + "\tthe given column 'input_index' is out of bound\n" + ); + } #endif - auto operation_function = [scalar_operation](const T matrix_index, const T operation_value) { - switch (scalar_operation) { - case ADD: - return matrix_index + operation_value; - case SUB: - return matrix_index - operation_value; - case MUL: - return matrix_index * operation_value; - case DIV: - return matrix_index / operation_value; - default: - throw std::invalid_argument( - "\n\nERROR : void column_operation(const size_t output_index, const SCALAR scalar_operation, " - "size_t input_index)\n" - "\tthe 'scalar_operation' given was invalid\n" - ); - } - }; + auto operation_function = [scalar_operation](const T matrix_index, const T operation_value) { + switch (scalar_operation) { + case ADD: + return matrix_index + operation_value; + case SUB: + return matrix_index - operation_value; + case MUL: + return matrix_index * operation_value; + case DIV: + return matrix_index / operation_value; + default: + throw std::invalid_argument( + "\n\nERROR : void column_operation(const size_t output_index, const SCALAR scalar_operation, " + "size_t input_index)\n" + "\tthe 'scalar_operation' given was invalid\n" + ); + } + }; - for (size_t i = 0; i < height; ++i) { - matrix[i * width + output_index] = - operation_function(matrix[i * width + output_index], matrix[i * width + input_index]); - } + for (size_t i = 0; i < height; ++i) { + matrix[i * width + output_index] = + operation_function(matrix[i * width + output_index], matrix[i * width + input_index]); } + } - /// @note: swaps the values of a column to another column :: a<-->b - template - void mat::column_swap(size_t column_a, size_t column_b) { + /// @note: swaps the values of a column to another column :: a<-->b + template + void mat::column_swap(size_t column_a, size_t column_b) { #ifndef CHECK_RANGE_DISABLE - if ((column_a > width - 1)) { - throw std::out_of_range( - "\n\nERROR : void column_swap(size_t column_a, size_t column_b)\n" - "\tthe given column 'column_a' is out of bound\n" - ); - } else if ((column_b > width - 1)) { - throw std::out_of_range( - "\n\nERROR : void column_swap(size_t column_a, size_t column_b)\n" - "\tthe given column 'column_b' is out of bound\n" - ); - } + if ((column_a > width - 1)) { + throw std::out_of_range( + "\n\nERROR : void column_swap(size_t column_a, size_t column_b)\n" + "\tthe given column 'column_a' is out of bound\n" + ); + } else if ((column_b > width - 1)) { + throw std::out_of_range( + "\n\nERROR : void column_swap(size_t column_a, size_t column_b)\n" + "\tthe given column 'column_b' is out of bound\n" + ); + } #endif - T temp; - for (size_t i = 0; i < height; ++i) { - temp = matrix[i * width + column_a]; - matrix[i * width + column_a] = matrix[i * width + column_b]; - matrix[i * width + column_b] = temp; - } + T temp; + for (size_t i = 0; i < height; ++i) { + temp = matrix[i * width + column_a]; + matrix[i * width + column_a] = matrix[i * width + column_b]; + matrix[i * width + column_b] = temp; } + } - /// @note: multiply all the values of a column to a non-zero constant - /// @arg(scalar,base_column) - /// @param 1 scalar : template S type value that you want to multiply to all the elements of the column - /// @param 2 base_column : size_t index of the column you want to perform scaling - template - void mat::column_scale(T scalar, size_t base_column) { + /// @note: multiply all the values of a column to a non-zero constant + /// @arg(scalar,base_column) + /// @param 1 scalar : template S type value that you want to multiply to all the elements of the column + /// @param 2 base_column : size_t index of the column you want to perform scaling + template + void mat::column_scale(T scalar, size_t base_column) { #ifndef CHECK_RANGE_DISABLE - if ((base_column > width - 1)) { - throw std::out_of_range( - "\n\nERROR : void column_scale(S scalar, size_t base_column)\n" - "\tthe given column 'base_column' is out of bound\n" - ); - } + if ((base_column > width - 1)) { + throw std::out_of_range( + "\n\nERROR : void column_scale(S scalar, size_t base_column)\n" + "\tthe given column 'base_column' is out of bound\n" + ); + } #endif - for (size_t i = 0; i < height; ++i) { - matrix[i * width + base_column] *= scalar; - } + for (size_t i = 0; i < height; ++i) { + matrix[i * width + base_column] *= scalar; } + } - /// @note: multiply all the values of a column to a non-zero constant, then add the result to another column - /// @arg(scalar,scale_column,base_column) - /// @param 1 scalar : template S type value that you want to multiply to all the elements of the column - /// @param 2 scale_column : size_t index of the column you want to scale - /// @param 3 base_column : size_t index of the column you want to add the results of the scaled column - template - void mat::column_scale(T scalar, size_t scale_column, size_t base_column) { + /// @note: multiply all the values of a column to a non-zero constant, then add the result to another column + /// @arg(scalar,scale_column,base_column) + /// @param 1 scalar : template S type value that you want to multiply to all the elements of the column + /// @param 2 scale_column : size_t index of the column you want to scale + /// @param 3 base_column : size_t index of the column you want to add the results of the scaled column + template + void mat::column_scale(T scalar, size_t scale_column, size_t base_column) { #ifndef CHECK_RANGE_DISABLE - if ((scale_column > width - 1)) { - throw std::out_of_range( - "\n\nERROR : void column_scale(S scalar, size_t scale_column, size_t scale_column)\n" - "\tthe given column 'scale_column' is out of bound\n" - ); - } else if ((base_column > width - 1)) { - throw std::out_of_range( - "\n\nERROR : void column_scale(S scalar, size_t scale_column, size_t base_column)\n" - "\tthe given column 'base_column' is out of bound\n" - ); - } + if ((scale_column > width - 1)) { + throw std::out_of_range( + "\n\nERROR : void column_scale(S scalar, size_t scale_column, size_t scale_column)\n" + "\tthe given column 'scale_column' is out of bound\n" + ); + } else if ((base_column > width - 1)) { + throw std::out_of_range( + "\n\nERROR : void column_scale(S scalar, size_t scale_column, size_t base_column)\n" + "\tthe given column 'base_column' is out of bound\n" + ); + } #endif - for (size_t i = 0; i < height; ++i) { - matrix[i * width + base_column] += scalar * matrix[i * width + scale_column]; - } + for (size_t i = 0; i < height; ++i) { + matrix[i * width + base_column] += scalar * matrix[i * width + scale_column]; } + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-elementary-operation/row_operations.cpp b/cyfre/matrix-elementary-operation/row_operations.cpp index 0680c35..3f287b5 100644 --- a/cyfre/matrix-elementary-operation/row_operations.cpp +++ b/cyfre/matrix-elementary-operation/row_operations.cpp @@ -5,154 +5,154 @@ #include namespace cyfre { - /// 'ADD,SUB,MUL, or DIV' a given 'const T value' to all elements of a selected 'const size_t row_index' - template - void mat::scale_row(const size_t row_index, const SCALAR scalar_operation, const T value) { + /// 'ADD,SUB,MUL, or DIV' a given 'const T value' to all elements of a selected 'const size_t row_index' + template + void mat::scale_row(const size_t row_index, const SCALAR scalar_operation, const T value) { #ifndef CHECK_RANGE_DISABLE - if ((row_index > height - 1)) { - throw std::out_of_range( - "\n\nERROR : void scale_row(const size_t row_index, const SCALAR scalar_operation, const T value)\n" - "\tthe given row index is out of bound\n" - ); - } + if ((row_index > height - 1)) { + throw std::out_of_range( + "\n\nERROR : void scale_row(const size_t row_index, const SCALAR scalar_operation, const T value)\n" + "\tthe given row index is out of bound\n" + ); + } #endif - auto operation_function = [scalar_operation](const T matrix_index, const T operation_value) { - switch (scalar_operation) { - case ADD: - return matrix_index + operation_value; - case SUB: - return matrix_index - operation_value; - case MUL: - return matrix_index * operation_value; - case DIV: - return matrix_index / operation_value; - default: - throw std::invalid_argument( - "\n\nERROR : scale_row(const size_t row_index, const SCALAR scalar_operation, const T value)\n" - "\tscale_row was given an invalid operation\n" - ); - } - }; + auto operation_function = [scalar_operation](const T matrix_index, const T operation_value) { + switch (scalar_operation) { + case ADD: + return matrix_index + operation_value; + case SUB: + return matrix_index - operation_value; + case MUL: + return matrix_index * operation_value; + case DIV: + return matrix_index / operation_value; + default: + throw std::invalid_argument( + "\n\nERROR : scale_row(const size_t row_index, const SCALAR scalar_operation, const T value)\n" + "\tscale_row was given an invalid operation\n" + ); + } + }; - for (size_t i = 0; i < width; ++i) { - matrix[row_index * width + i] = operation_function(matrix[row_index * width + i], value); - } + for (size_t i = 0; i < width; ++i) { + matrix[row_index * width + i] = operation_function(matrix[row_index * width + i], value); } + } - template - void mat::row_operation(const size_t output_index, const SCALAR scalar_operation, size_t input_index) { + template + void mat::row_operation(const size_t output_index, const SCALAR scalar_operation, size_t input_index) { #ifndef CHECK_RANGE_DISABLE - if ((output_index > height - 1)) { - throw std::out_of_range( - "\n\nERROR : void row_operation(const size_t output_index, const SCALAR scalar_operation, size_t " - "input_index)\n" - "\tthe given row 'output_index' is out of bound\n" - ); - } else if ((input_index > height - 1)) { - throw std::out_of_range( - "\n\nERROR : void row_operation(const size_t output_index, const SCALAR scalar_operation, size_t " - "input_index)\n" - "\tthe given row 'input_index' is out of bound\n" - ); - } + if ((output_index > height - 1)) { + throw std::out_of_range( + "\n\nERROR : void row_operation(const size_t output_index, const SCALAR scalar_operation, size_t " + "input_index)\n" + "\tthe given row 'output_index' is out of bound\n" + ); + } else if ((input_index > height - 1)) { + throw std::out_of_range( + "\n\nERROR : void row_operation(const size_t output_index, const SCALAR scalar_operation, size_t " + "input_index)\n" + "\tthe given row 'input_index' is out of bound\n" + ); + } #endif - auto operation_function = [scalar_operation](const T matrix_index, const T operation_value) { - switch (scalar_operation) { - case ADD: - return matrix_index + operation_value; - case SUB: - return matrix_index - operation_value; - case MUL: - return matrix_index * operation_value; - case DIV: - return matrix_index / operation_value; - default: - throw std::invalid_argument( - "\n\nERROR : void row_operation(const size_t output_index, const SCALAR scalar_operation, " - "size_t input_index)\n" - "\tthe 'scalar_operation' given was invalid\n" - ); - } - }; + auto operation_function = [scalar_operation](const T matrix_index, const T operation_value) { + switch (scalar_operation) { + case ADD: + return matrix_index + operation_value; + case SUB: + return matrix_index - operation_value; + case MUL: + return matrix_index * operation_value; + case DIV: + return matrix_index / operation_value; + default: + throw std::invalid_argument( + "\n\nERROR : void row_operation(const size_t output_index, const SCALAR scalar_operation, " + "size_t input_index)\n" + "\tthe 'scalar_operation' given was invalid\n" + ); + } + }; - for (size_t i = 0; i < width; ++i) { - matrix[output_index * width + i] = - operation_function(matrix[output_index * width + i], matrix[input_index * width + i]); - } + for (size_t i = 0; i < width; ++i) { + matrix[output_index * width + i] = + operation_function(matrix[output_index * width + i], matrix[input_index * width + i]); } + } - /// @note: swaps the values of a row to another row :: a<-->b - template - void mat::row_swap(size_t row_a, size_t row_b) { + /// @note: swaps the values of a row to another row :: a<-->b + template + void mat::row_swap(size_t row_a, size_t row_b) { #ifndef CHECK_RANGE_DISABLE - if ((row_a > height - 1)) { - throw std::out_of_range( - "\n\nERROR : void row_swap(size_t row_a, size_t row_b)\n" - "\tthe given row 'row_a' is out of bound\n" - ); - } else if ((row_b > height - 1)) { - throw std::out_of_range( - "\n\nERROR : void row_swap(size_t row_a, size_t row_b)\n" - "\tthe given row 'row_b' is out of bound\n" - ); - } + if ((row_a > height - 1)) { + throw std::out_of_range( + "\n\nERROR : void row_swap(size_t row_a, size_t row_b)\n" + "\tthe given row 'row_a' is out of bound\n" + ); + } else if ((row_b > height - 1)) { + throw std::out_of_range( + "\n\nERROR : void row_swap(size_t row_a, size_t row_b)\n" + "\tthe given row 'row_b' is out of bound\n" + ); + } #endif - T temp; - for (size_t i = 0; i < width; ++i) { - temp = matrix[row_a * width + i]; - matrix[row_a * width + i] = matrix[row_b * width + i]; - matrix[row_b * width + i] = temp; - } + T temp; + for (size_t i = 0; i < width; ++i) { + temp = matrix[row_a * width + i]; + matrix[row_a * width + i] = matrix[row_b * width + i]; + matrix[row_b * width + i] = temp; } + } - /// @note: multiply all the values of a row to a non-zero constant - /// @arg(scalar,base_row) - /// @param 1 scalar : template T type value that you want to multiply to all the elements of the row - /// @param 2 base_row : size_t index of the row you want to perform scaling - template - void mat::row_scale(T scalar, size_t base_row) { + /// @note: multiply all the values of a row to a non-zero constant + /// @arg(scalar,base_row) + /// @param 1 scalar : template T type value that you want to multiply to all the elements of the row + /// @param 2 base_row : size_t index of the row you want to perform scaling + template + void mat::row_scale(T scalar, size_t base_row) { #ifndef CHECK_RANGE_DISABLE - if ((base_row > height - 1)) { - throw std::out_of_range( - "\n\nERROR : void row_scale(S scalar, size_t base_row)\n" - "\tthe given row 'base_row' is out of bound\n" - ); - } + if ((base_row > height - 1)) { + throw std::out_of_range( + "\n\nERROR : void row_scale(S scalar, size_t base_row)\n" + "\tthe given row 'base_row' is out of bound\n" + ); + } #endif - for (size_t i = 0; i < width; ++i) { - matrix[base_row * width + i] *= scalar; - } + for (size_t i = 0; i < width; ++i) { + matrix[base_row * width + i] *= scalar; } + } - /// @note: multiply all the values of a row to a non-zero constant, then add the result to another row - /// @arg(scalar,scale_row,base_row) - /// @param 1 scalar : template T type value that you want to multiply to all the elements of the row - /// @param 2 scale_row : size_t index of the row you want to scale - /// @param 3 base_row : size_t index of the row you want to add the results of the scaled row - template - void mat::row_scale(T scalar, size_t scale_row, size_t base_row) { + /// @note: multiply all the values of a row to a non-zero constant, then add the result to another row + /// @arg(scalar,scale_row,base_row) + /// @param 1 scalar : template T type value that you want to multiply to all the elements of the row + /// @param 2 scale_row : size_t index of the row you want to scale + /// @param 3 base_row : size_t index of the row you want to add the results of the scaled row + template + void mat::row_scale(T scalar, size_t scale_row, size_t base_row) { #ifndef CHECK_RANGE_DISABLE - if ((scale_row > height - 1)) { - throw std::out_of_range( - "\n\nERROR : void row_scale(S scalar, size_t scale_row, size_t scale_row)\n" - "\tthe given row 'scale_row' is out of bound\n" - ); - } else if ((base_row > height - 1)) { - throw std::out_of_range( - "\n\nERROR : void row_scale(S scalar, size_t scale_row, size_t base_row)\n" - "\tthe given row 'base_row' is out of bound\n" - ); - } + if ((scale_row > height - 1)) { + throw std::out_of_range( + "\n\nERROR : void row_scale(S scalar, size_t scale_row, size_t scale_row)\n" + "\tthe given row 'scale_row' is out of bound\n" + ); + } else if ((base_row > height - 1)) { + throw std::out_of_range( + "\n\nERROR : void row_scale(S scalar, size_t scale_row, size_t base_row)\n" + "\tthe given row 'base_row' is out of bound\n" + ); + } #endif - for (size_t i = 0; i < width; ++i) { - matrix[base_row * width + i] += scalar * matrix[scale_row * width + i]; - } + for (size_t i = 0; i < width; ++i) { + matrix[base_row * width + i] += scalar * matrix[scale_row * width + i]; } + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-matrix/mm_addition.cpp b/cyfre/matrix-matrix/mm_addition.cpp index a28996b..2c7694b 100644 --- a/cyfre/matrix-matrix/mm_addition.cpp +++ b/cyfre/matrix-matrix/mm_addition.cpp @@ -5,50 +5,50 @@ #include namespace cyfre { - /// --------------------------- addition --------------------------------- + /// --------------------------- addition --------------------------------- - /// @returns element by element addition - old - template - inline mat mat::operator+(const mat &that) const { + /// @returns element by element addition - old + template + inline mat mat::operator+(const mat &that) const { #ifndef CHECK_SHAPE_DISABLE - if (this->width != that.width || this->height != that.height) { - throw std::length_error( - "\n\nERROR : mat operator+(const mat& that) const\n" - "\taddition of two different shaped matrix is not allowed\n" - ); - } + if (this->width != that.width || this->height != that.height) { + throw std::length_error( + "\n\nERROR : mat operator+(const mat& that) const\n" + "\taddition of two different shaped matrix is not allowed\n" + ); + } #endif - size_t n = height * width; - - mat sum; - sum.height = height; - sum.width = width; - sum.matrix = new T[n]; + size_t n = height * width; - for (size_t i = 0; i < n; ++i) { - sum.matrix[i] = matrix[i] + that.matrix[i]; - } + mat sum; + sum.height = height; + sum.width = width; + sum.matrix = new T[n]; - return sum; + for (size_t i = 0; i < n; ++i) { + sum.matrix[i] = matrix[i] + that.matrix[i]; } - template - inline void mat::operator+=(const mat &that) { + return sum; + } + + template + inline void mat::operator+=(const mat &that) { #ifndef CHECK_SHAPE_DISABLE - if (this->width != that.width || this->height != that.height) { - std::string errmsg = - "\n\nERROR : mat operator+=(const mat& that) const\n" - "\taddition of two different shaped matrix is not allowed\n"; - throw std::length_error(errmsg); - } + if (this->width != that.width || this->height != that.height) { + std::string errmsg = + "\n\nERROR : mat operator+=(const mat& that) const\n" + "\taddition of two different shaped matrix is not allowed\n"; + throw std::length_error(errmsg); + } #endif - size_t n = height * width; - for (size_t i = 0; i < n; ++i) { - matrix[i] += that.matrix[i]; - } + size_t n = height * width; + for (size_t i = 0; i < n; ++i) { + matrix[i] += that.matrix[i]; } + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-matrix/mm_division.cpp b/cyfre/matrix-matrix/mm_division.cpp index 8e3fe6e..dd6772f 100644 --- a/cyfre/matrix-matrix/mm_division.cpp +++ b/cyfre/matrix-matrix/mm_division.cpp @@ -5,56 +5,56 @@ #include namespace cyfre { - /// ---------------------- Division ----------------------------- + /// ---------------------- Division ----------------------------- - /// @returns element by element division - template - inline mat mat::operator/(const mat &that) const { + /// @returns element by element division + template + inline mat mat::operator/(const mat &that) const { #ifndef CHECK_SHAPE_DISABLE - if (this->width != that.width || this->height != that.height) { - throw std::length_error( - "\n\nERROR : mat operator/(const mat& that) const\n" - "\taddition of two different shaped matrix is not allowed\n" - ); - } + if (this->width != that.width || this->height != that.height) { + throw std::length_error( + "\n\nERROR : mat operator/(const mat& that) const\n" + "\taddition of two different shaped matrix is not allowed\n" + ); + } #endif - size_t n = height * width; - - mat quotient; - quotient.height = height; - quotient.width = width; - quotient.matrix = new T[n]; + size_t n = height * width; - for (size_t i = 0; i < n; ++i) { - if (that.matrix[i] == 0) { - throw std::domain_error("ERROR : inline mat operator/(const mat& that) const - divide by zero"); - } - quotient.matrix[i] = matrix[i] / that.matrix[i]; - } + mat quotient; + quotient.height = height; + quotient.width = width; + quotient.matrix = new T[n]; - return quotient; + for (size_t i = 0; i < n; ++i) { + if (that.matrix[i] == 0) { + throw std::domain_error("ERROR : inline mat operator/(const mat& that) const - divide by zero"); + } + quotient.matrix[i] = matrix[i] / that.matrix[i]; } - template - inline void mat::operator/=(const mat &that) { + return quotient; + } + + template + inline void mat::operator/=(const mat &that) { #ifndef CHECK_SHAPE_DISABLE - if (this->width != that.width || this->height != that.height) { - throw std::length_error( - std::string("\n\nERROR : mat operator/=(const mat& that) const\n") + - "\taddition of two different shaped matrix is not allowed\n" - ); - } + if (this->width != that.width || this->height != that.height) { + throw std::length_error( + std::string("\n\nERROR : mat operator/=(const mat& that) const\n") + + "\taddition of two different shaped matrix is not allowed\n" + ); + } #endif - size_t n = height * width; - for (size_t i = 0; i < n; ++i) { - if (that.matrix[i] == 0) { - throw std::domain_error("ERROR : inline void operator/=(const mat& that) - divide by zero"); - } - matrix[i] /= that.matrix[i]; - } + size_t n = height * width; + for (size_t i = 0; i < n; ++i) { + if (that.matrix[i] == 0) { + throw std::domain_error("ERROR : inline void operator/=(const mat& that) - divide by zero"); + } + matrix[i] /= that.matrix[i]; } + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-matrix/mm_hadamard.cpp b/cyfre/matrix-matrix/mm_hadamard.cpp index bffa4dc..694e75a 100644 --- a/cyfre/matrix-matrix/mm_hadamard.cpp +++ b/cyfre/matrix-matrix/mm_hadamard.cpp @@ -5,52 +5,52 @@ #include namespace cyfre { - /// @returns hadamard matrix product - element by element multiplication, not to be confused with matrix - /// multiplication - template - inline void mat::hadamard(const mat &that) { + /// @returns hadamard matrix product - element by element multiplication, not to be confused with matrix + /// multiplication + template + inline void mat::hadamard(const mat &that) { #ifndef CHECK_SHAPE_DISABLE - if (this->width != that.width || this->height != that.height) { - throw std::length_error( - "\n\nERROR : static mat hadamard(const mat& left, const mat& that) const\n" - "\thadamard multiplication of two different shaped matrix is not allowed\n" - ); - } + if (this->width != that.width || this->height != that.height) { + throw std::length_error( + "\n\nERROR : static mat hadamard(const mat& left, const mat& that) const\n" + "\thadamard multiplication of two different shaped matrix is not allowed\n" + ); + } #endif - size_t n = height * width; + size_t n = height * width; - for (size_t i = 0; i < n; ++i) { - matrix[i] *= that.matrix[i]; - } + for (size_t i = 0; i < n; ++i) { + matrix[i] *= that.matrix[i]; } + } - /// @returns hadamard matrix product - element by element multiplication, not to be confused with matrix - /// multiplication - template - mat hadamard(const mat &left, const mat &right) { + /// @returns hadamard matrix product - element by element multiplication, not to be confused with matrix + /// multiplication + template + mat hadamard(const mat &left, const mat &right) { #ifndef CHECK_SHAPE_DISABLE - if (left.width != right.width || left.height != right.height) { - throw std::length_error( - "\n\nERROR : static mat hadamard(const mat& left, const mat& right) const\n" - "\thadamard multiplication of two different shaped matrix is not allowed\n" - ); - } + if (left.width != right.width || left.height != right.height) { + throw std::length_error( + "\n\nERROR : static mat hadamard(const mat& left, const mat& right) const\n" + "\thadamard multiplication of two different shaped matrix is not allowed\n" + ); + } #endif - size_t n = left.height * left.width; + size_t n = left.height * left.width; - mat hproduct; - hproduct.height = left.height; - hproduct.width = left.width; - hproduct.matrix = new T[n]; + mat hproduct; + hproduct.height = left.height; + hproduct.width = left.width; + hproduct.matrix = new T[n]; - for (size_t i = 0; i < n; ++i) { - hproduct.matrix[i] = left.matrix[i] * right.matrix[i]; - } - - return hproduct; + for (size_t i = 0; i < n; ++i) { + hproduct.matrix[i] = left.matrix[i] * right.matrix[i]; } + + return hproduct; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-matrix/mm_multiplication.cpp b/cyfre/matrix-matrix/mm_multiplication.cpp index c90e124..5cae433 100644 --- a/cyfre/matrix-matrix/mm_multiplication.cpp +++ b/cyfre/matrix-matrix/mm_multiplication.cpp @@ -5,65 +5,65 @@ #include namespace cyfre { - /// ---------------------- Multiplication ----------------------------- + /// ---------------------- Multiplication ----------------------------- - /// @returns matrix multiplication / dot product - template - inline mat mat::operator*(const mat &that) const { + /// @returns matrix multiplication / dot product + template + inline mat mat::operator*(const mat &that) const { #ifndef CHECK_SHAPE_DISABLE - if (this->width != that.height) { - throw std::length_error( - "\n\nERROR w: mat operator*(const mat& that) const\n" - "\tmultiplication of incompatible matrix shapes\n" - "\tmat_a columns is not equal to the mat_b rows\n" - ); - } + if (this->width != that.height) { + throw std::length_error( + "\n\nERROR w: mat operator*(const mat& that) const\n" + "\tmultiplication of incompatible matrix shapes\n" + "\tmat_a columns is not equal to the mat_b rows\n" + ); + } #endif - mat product; - product.height = height; - product.width = that.width; - product.matrix = new T[height * that.width]; + mat product; + product.height = height; + product.width = that.width; + product.matrix = new T[height * that.width]; - // naive_mmul - for (size_t i = 0; i < height; ++i) { - for (size_t j = 0; j < that.width; ++j) { - product.matrix[i * height + j] = 0; - for (size_t k = 0; k < width; ++k) { - product.matrix[i * height + j] += matrix[i * height + k] * that.matrix[k * that.width + j]; - } - } + // naive_mmul + for (size_t i = 0; i < height; ++i) { + for (size_t j = 0; j < that.width; ++j) { + product.matrix[i * height + j] = 0; + for (size_t k = 0; k < width; ++k) { + product.matrix[i * height + j] += matrix[i * height + k] * that.matrix[k * that.width + j]; } - - return product; + } } - template - inline void mat::operator*=(const mat &that) { + return product; + } + + template + inline void mat::operator*=(const mat &that) { #ifndef CHECK_SHAPE_DISABLE - if (width != height) { - throw std::length_error( - "\n\nERROR : mat operator*=(const mat& that) const\n" - "\tmultiplication of incompatible matrix shapes\n" - "\twhen multiplying matricies with the *= operator\n" - "\tthe two matrix involved should be a square matrix\n" - "\tlefthand matrix is not square\n" - ); - } + if (width != height) { + throw std::length_error( + "\n\nERROR : mat operator*=(const mat& that) const\n" + "\tmultiplication of incompatible matrix shapes\n" + "\twhen multiplying matricies with the *= operator\n" + "\tthe two matrix involved should be a square matrix\n" + "\tlefthand matrix is not square\n" + ); + } - if (that.width != that.height) { - throw std::length_error( - "\n\nERROR : mat operator*=(const mat& that) const\n" - "\tmultiplication of incompatible matrix shapes\n" - "\twhen multiplying matricies with the *= operator\n" - "\tthe two matrix involved should be a square matrix\n" - "\trighthand matrix is not square\n" - ); - } + if (that.width != that.height) { + throw std::length_error( + "\n\nERROR : mat operator*=(const mat& that) const\n" + "\tmultiplication of incompatible matrix shapes\n" + "\twhen multiplying matricies with the *= operator\n" + "\tthe two matrix involved should be a square matrix\n" + "\trighthand matrix is not square\n" + ); + } #endif - *this = *this * that; - } + *this = *this * that; + } } // namespace cyfre #endif diff --git a/cyfre/matrix-matrix/mm_subtraction.cpp b/cyfre/matrix-matrix/mm_subtraction.cpp index aab02c4..b904c12 100644 --- a/cyfre/matrix-matrix/mm_subtraction.cpp +++ b/cyfre/matrix-matrix/mm_subtraction.cpp @@ -5,51 +5,51 @@ #include namespace cyfre { - /// --------------------------- subtraction --------------------------------- + /// --------------------------- subtraction --------------------------------- - /// @returns element by element subtraction - old - template - inline mat mat::operator-(const mat &that) const { + /// @returns element by element subtraction - old + template + inline mat mat::operator-(const mat &that) const { #ifndef CHECK_SHAPE_DISABLE - if (this->width != that.width || this->height != that.height) { - std::string errmsg = - "\n\nERROR : mat operator-(const mat& that) const\n" - "\tsubtraction of two different shaped matrix is not allowed\n"; - throw std::length_error(errmsg); - } + if (this->width != that.width || this->height != that.height) { + std::string errmsg = + "\n\nERROR : mat operator-(const mat& that) const\n" + "\tsubtraction of two different shaped matrix is not allowed\n"; + throw std::length_error(errmsg); + } #endif - size_t n = height * width; - - mat difference; - difference.height = height; - difference.width = width; - difference.matrix = new T[n]; + size_t n = height * width; - for (size_t i = 0; i < n; ++i) { - difference.matrix[i] = matrix[i] - that.matrix[i]; - } + mat difference; + difference.height = height; + difference.width = width; + difference.matrix = new T[n]; - return difference; + for (size_t i = 0; i < n; ++i) { + difference.matrix[i] = matrix[i] - that.matrix[i]; } - template - inline void mat::operator-=(const mat &that) { + return difference; + } + + template + inline void mat::operator-=(const mat &that) { #ifndef CHECK_SHAPE_DISABLE - if (this->width != that.width || this->height != that.height) { - std::string errmsg = - "\n\nERROR : mat operator-=(const mat& that) const\n" - "\tsubtraction of two different shaped matrix is not allowed\n"; - throw std::length_error(errmsg); - } + if (this->width != that.width || this->height != that.height) { + std::string errmsg = + "\n\nERROR : mat operator-=(const mat& that) const\n" + "\tsubtraction of two different shaped matrix is not allowed\n"; + throw std::length_error(errmsg); + } #endif - size_t n = height * width; + size_t n = height * width; - for (size_t i = 0; i < n; ++i) { - matrix[i] -= that.matrix[i]; - } + for (size_t i = 0; i < n; ++i) { + matrix[i] -= that.matrix[i]; } + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-scalar/ms_addition.cpp b/cyfre/matrix-scalar/ms_addition.cpp index d2bf6dd..872c91d 100644 --- a/cyfre/matrix-scalar/ms_addition.cpp +++ b/cyfre/matrix-scalar/ms_addition.cpp @@ -5,46 +5,46 @@ #include namespace cyfre { - template - inline mat mat::operator+(const T scalar) const { - size_t n = height * width; + template + inline mat mat::operator+(const T scalar) const { + size_t n = height * width; - mat scaled_sum; - scaled_sum.height = height; - scaled_sum.width = width; - scaled_sum.matrix = new T[n]; + mat scaled_sum; + scaled_sum.height = height; + scaled_sum.width = width; + scaled_sum.matrix = new T[n]; - for (size_t i = 0; i < n; ++i) { - scaled_sum.matrix[i] = matrix[i] + scalar; - } - - return scaled_sum; + for (size_t i = 0; i < n; ++i) { + scaled_sum.matrix[i] = matrix[i] + scalar; } - template - inline void mat::operator+=(const T scalar) { - size_t n = height * width; + return scaled_sum; + } - for (size_t i = 0; i < n; ++i) { - matrix[i] += scalar; - } - } + template + inline void mat::operator+=(const T scalar) { + size_t n = height * width; - template - inline mat operator+(const T scalar, const mat &that) { - size_t n = that.height * that.width; + for (size_t i = 0; i < n; ++i) { + matrix[i] += scalar; + } + } - mat scaled_sum; - scaled_sum.height = that.height; - scaled_sum.width = that.width; - scaled_sum.matrix = new T[n]; + template + inline mat operator+(const T scalar, const mat &that) { + size_t n = that.height * that.width; - for (size_t i = 0; i < n; ++i) { - scaled_sum.matrix[i] = scalar + that.matrix[i]; - } + mat scaled_sum; + scaled_sum.height = that.height; + scaled_sum.width = that.width; + scaled_sum.matrix = new T[n]; - return scaled_sum; + for (size_t i = 0; i < n; ++i) { + scaled_sum.matrix[i] = scalar + that.matrix[i]; } + + return scaled_sum; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-scalar/ms_division.cpp b/cyfre/matrix-scalar/ms_division.cpp index 92ca1a2..5d888fb 100644 --- a/cyfre/matrix-scalar/ms_division.cpp +++ b/cyfre/matrix-scalar/ms_division.cpp @@ -5,59 +5,59 @@ #include namespace cyfre { - template - inline mat mat::operator/(const T scalar) const { - if (scalar == 0) { - throw std::domain_error("ERROR : inline mat operator/(const T scalar) const - divide by zero"); - } - - size_t n = height * width; + template + inline mat mat::operator/(const T scalar) const { + if (scalar == 0) { + throw std::domain_error("ERROR : inline mat operator/(const T scalar) const - divide by zero"); + } - mat scaled_quotient; - scaled_quotient.height = height; - scaled_quotient.width = width; - scaled_quotient.matrix = new T[n]; + size_t n = height * width; - for (size_t i = 0; i < n; ++i) { - scaled_quotient.matrix[i] = matrix[i] / scalar; - } + mat scaled_quotient; + scaled_quotient.height = height; + scaled_quotient.width = width; + scaled_quotient.matrix = new T[n]; - return scaled_quotient; + for (size_t i = 0; i < n; ++i) { + scaled_quotient.matrix[i] = matrix[i] / scalar; } - template - inline void mat::operator/=(const T scalar) { - size_t n = height * width; + return scaled_quotient; + } - for (size_t i = 0; i < n; ++i) { - if (scalar == 0) { - throw std::domain_error("ERROR : inline void operator/=(const T scalar) - divide by zero"); - } - matrix[i] /= scalar; - } - } + template + inline void mat::operator/=(const T scalar) { + size_t n = height * width; - template - inline mat operator/(const T scalar, const mat &that) { - size_t n = that.height * that.width; - - mat scaled_quotient; - scaled_quotient.height = that.height; - scaled_quotient.width = that.width; - scaled_quotient.matrix = new T[n]; - - for (size_t i = 0; i < n; ++i) { - if (that.matrix[i] == 0) { - throw std::domain_error( - "ERROR : template inline friend mat operator/(const S scalar, const mat& that) - " - "divide by zero" - ); - } - scaled_quotient.matrix[i] = scalar / that.matrix[i]; - } - - return scaled_quotient; + for (size_t i = 0; i < n; ++i) { + if (scalar == 0) { + throw std::domain_error("ERROR : inline void operator/=(const T scalar) - divide by zero"); + } + matrix[i] /= scalar; } + } + + template + inline mat operator/(const T scalar, const mat &that) { + size_t n = that.height * that.width; + + mat scaled_quotient; + scaled_quotient.height = that.height; + scaled_quotient.width = that.width; + scaled_quotient.matrix = new T[n]; + + for (size_t i = 0; i < n; ++i) { + if (that.matrix[i] == 0) { + throw std::domain_error( + "ERROR : template inline friend mat operator/(const S scalar, const mat& that) - " + "divide by zero" + ); + } + scaled_quotient.matrix[i] = scalar / that.matrix[i]; + } + + return scaled_quotient; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-scalar/ms_multiplication.cpp b/cyfre/matrix-scalar/ms_multiplication.cpp index 772cb63..86dfee9 100644 --- a/cyfre/matrix-scalar/ms_multiplication.cpp +++ b/cyfre/matrix-scalar/ms_multiplication.cpp @@ -5,46 +5,46 @@ #include namespace cyfre { - template - inline mat mat::operator*(const T scalar) const { - size_t n = height * width; + template + inline mat mat::operator*(const T scalar) const { + size_t n = height * width; - mat scaled_product; - scaled_product.height = height; - scaled_product.width = width; - scaled_product.matrix = new T[n]; + mat scaled_product; + scaled_product.height = height; + scaled_product.width = width; + scaled_product.matrix = new T[n]; - for (size_t i = 0; i < n; ++i) { - scaled_product.matrix[i] = matrix[i] * scalar; - } - - return scaled_product; + for (size_t i = 0; i < n; ++i) { + scaled_product.matrix[i] = matrix[i] * scalar; } - template - inline void mat::operator*=(const T scalar) { - size_t n = height * width; + return scaled_product; + } - for (size_t i = 0; i < n; ++i) { - matrix[i] *= scalar; - } - } + template + inline void mat::operator*=(const T scalar) { + size_t n = height * width; - template - inline mat operator*(const T scalar, const mat &that) { - size_t n = that.height * that.width; + for (size_t i = 0; i < n; ++i) { + matrix[i] *= scalar; + } + } - mat scaled_product; - scaled_product.height = that.height; - scaled_product.width = that.width; - scaled_product.matrix = new T[n]; + template + inline mat operator*(const T scalar, const mat &that) { + size_t n = that.height * that.width; - for (size_t i = 0; i < n; ++i) { - scaled_product.matrix[i] = scalar * that.matrix[i]; - } + mat scaled_product; + scaled_product.height = that.height; + scaled_product.width = that.width; + scaled_product.matrix = new T[n]; - return scaled_product; + for (size_t i = 0; i < n; ++i) { + scaled_product.matrix[i] = scalar * that.matrix[i]; } + + return scaled_product; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/matrix-scalar/ms_subtraction.cpp b/cyfre/matrix-scalar/ms_subtraction.cpp index 0ee4807..bfeb15b 100644 --- a/cyfre/matrix-scalar/ms_subtraction.cpp +++ b/cyfre/matrix-scalar/ms_subtraction.cpp @@ -5,46 +5,46 @@ #include namespace cyfre { - template - inline mat mat::operator-(const T scalar) const { - size_t n = height * width; + template + inline mat mat::operator-(const T scalar) const { + size_t n = height * width; - mat scaled_difference; - scaled_difference.height = height; - scaled_difference.width = width; - scaled_difference.matrix = new T[n]; + mat scaled_difference; + scaled_difference.height = height; + scaled_difference.width = width; + scaled_difference.matrix = new T[n]; - for (size_t i = 0; i < n; ++i) { - scaled_difference.matrix[i] = matrix[i] - scalar; - } - - return scaled_difference; + for (size_t i = 0; i < n; ++i) { + scaled_difference.matrix[i] = matrix[i] - scalar; } - template - inline void mat::operator-=(const T scalar) { - size_t n = height * width; + return scaled_difference; + } - for (size_t i = 0; i < n; ++i) { - matrix[i] -= scalar; - } - } + template + inline void mat::operator-=(const T scalar) { + size_t n = height * width; - template - inline mat operator-(const T scalar, const mat &that) { - size_t n = that.height * that.width; + for (size_t i = 0; i < n; ++i) { + matrix[i] -= scalar; + } + } - mat scaled_difference; - scaled_difference.height = that.height; - scaled_difference.width = that.width; - scaled_difference.matrix = new T[n]; + template + inline mat operator-(const T scalar, const mat &that) { + size_t n = that.height * that.width; - for (size_t i = 0; i < n; ++i) { - scaled_difference.matrix[i] = scalar - that.matrix[i]; - } + mat scaled_difference; + scaled_difference.height = that.height; + scaled_difference.width = that.width; + scaled_difference.matrix = new T[n]; - return scaled_difference; + for (size_t i = 0; i < n; ++i) { + scaled_difference.matrix[i] = scalar - that.matrix[i]; } + + return scaled_difference; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/methods/determinant.cpp b/cyfre/methods/determinant.cpp index 9f1ce83..5ba46ca 100644 --- a/cyfre/methods/determinant.cpp +++ b/cyfre/methods/determinant.cpp @@ -5,58 +5,58 @@ #include namespace cyfre { - template - T det(mat input) { + template + T det(mat input) { #ifndef CHECK_SHAPE_DISABLE - if (input.width != input.height) { - std::cerr << "\n\nERROR : T det(mat input) - non-square matricies has no determinant\n"; - exit(1); - } + if (input.width != input.height) { + std::cerr << "\n\nERROR : T det(mat input) - non-square matricies has no determinant\n"; + exit(1); + } #endif - auto nonzrow = [](const mat &input, size_t i, size_t j) -> long long int { - for (size_t r = i; r < input.height; ++r) { - if (input.matrix[r * input.width + j] != 0) { - return r; - } - } - return -1; - }; - - auto fix_nonzero_pivot = [](mat &input, size_t pi, size_t pj) { - for (size_t i = pi + 1; i < input.height; ++i) { - input.row_scale(-(input.matrix[i * input.width + pj] / input.matrix[pi * input.width + pj]), pi, i); - } - }; - - auto diag_product = [](const mat &input) { - T diagonal_product = 1; - for (size_t i = 0; i < input.height && i < input.width; ++i) { - diagonal_product *= input.matrix[i * input.width + i]; - } - return diagonal_product; - }; - - size_t cpi = 0; - size_t cpj = 0; - while (cpi < input.height && cpj < input.width) { - long long int nonzerorow = nonzrow(input, cpi, cpj); - - if (nonzerorow < 0) { - cpj++; - continue; - } - - if (nonzerorow != (long long int) cpi) { - input.row_swap(cpi, nonzerorow); - } - - fix_nonzero_pivot(input, cpi, cpj); - cpi++; - cpj++; + auto nonzrow = [](const mat &input, size_t i, size_t j) -> long long int { + for (size_t r = i; r < input.height; ++r) { + if (input.matrix[r * input.width + j] != 0) { + return r; } - return diag_product(input); + } + return -1; + }; + + auto fix_nonzero_pivot = [](mat &input, size_t pi, size_t pj) { + for (size_t i = pi + 1; i < input.height; ++i) { + input.row_scale(-(input.matrix[i * input.width + pj] / input.matrix[pi * input.width + pj]), pi, i); + } + }; + + auto diag_product = [](const mat &input) { + T diagonal_product = 1; + for (size_t i = 0; i < input.height && i < input.width; ++i) { + diagonal_product *= input.matrix[i * input.width + i]; + } + return diagonal_product; + }; + + size_t cpi = 0; + size_t cpj = 0; + while (cpi < input.height && cpj < input.width) { + long long int nonzerorow = nonzrow(input, cpi, cpj); + + if (nonzerorow < 0) { + cpj++; + continue; + } + + if (nonzerorow != (long long int) cpi) { + input.row_swap(cpi, nonzerorow); + } + + fix_nonzero_pivot(input, cpi, cpj); + cpi++; + cpj++; } + return diag_product(input); + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/methods/minmax.cpp b/cyfre/methods/minmax.cpp index 0a323d3..3be3164 100644 --- a/cyfre/methods/minmax.cpp +++ b/cyfre/methods/minmax.cpp @@ -5,37 +5,37 @@ #include namespace cyfre { - template - T mat::max() { - size_t n = height * width; - - if (!n) { - throw std::range_error("ERROR : T max() - the matrix is empty, there is no maximum"); - } - - T maximum = matrix[0]; - for (size_t i = 1; i < n; ++i) { - if (matrix[i] > maximum) { - maximum = matrix[i]; - } - } + template + T mat::max() { + size_t n = height * width; + + if (!n) { + throw std::range_error("ERROR : T max() - the matrix is empty, there is no maximum"); + } + + T maximum = matrix[0]; + for (size_t i = 1; i < n; ++i) { + if (matrix[i] > maximum) { + maximum = matrix[i]; + } } + } - template - T mat::min() { - size_t n = height * width; + template + T mat::min() { + size_t n = height * width; - if (!n) { - throw std::range_error("ERROR : T min() - the matrix is empty, there is no minimum"); - } + if (!n) { + throw std::range_error("ERROR : T min() - the matrix is empty, there is no minimum"); + } - T minimum = matrix[0]; - for (size_t i = 1; i < n; ++i) { - if (matrix[i] < minimum) { - minimum = matrix[i]; - } - } + T minimum = matrix[0]; + for (size_t i = 1; i < n; ++i) { + if (matrix[i] < minimum) { + minimum = matrix[i]; + } } + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/methods/sum.cpp b/cyfre/methods/sum.cpp index 1486e61..3e710a3 100644 --- a/cyfre/methods/sum.cpp +++ b/cyfre/methods/sum.cpp @@ -5,29 +5,29 @@ #include namespace cyfre { - /// @returns T sum, the total sum of all the elements of the matrix - template - T mat::sum() const { - T sum = 0; + /// @returns T sum, the total sum of all the elements of the matrix + template + T mat::sum() const { + T sum = 0; - for (size_t i = 0; i < height; ++i) { - for (size_t j = 0; j < width; ++j) { - sum += matrix[i * width + j]; - } - } - - return sum; + for (size_t i = 0; i < height; ++i) { + for (size_t j = 0; j < width; ++j) { + sum += matrix[i * width + j]; + } } - /// @arg accepts a cyfre::mat objects - /// @returns T sum, the total sum of all the elements of the matrix - template - T sum(const mat &input) { - T sum = 0, zero = 0; - for (auto row: input.matrix) - sum += std::accumulate(row.begin(), row.end(), zero); - return sum; - } + return sum; + } + + /// @arg accepts a cyfre::mat objects + /// @returns T sum, the total sum of all the elements of the matrix + template + T sum(const mat &input) { + T sum = 0, zero = 0; + for (auto row: input.matrix) + sum += std::accumulate(row.begin(), row.end(), zero); + return sum; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/methods/trace.cpp b/cyfre/methods/trace.cpp index 10d6626..abff384 100644 --- a/cyfre/methods/trace.cpp +++ b/cyfre/methods/trace.cpp @@ -5,42 +5,42 @@ #include namespace cyfre { - /// @returns T trace_total, the total sum of the main diagonal - template - T mat::trace() const { + /// @returns T trace_total, the total sum of the main diagonal + template + T mat::trace() const { #ifndef CHECK_SHAPE_DISABLE - if (width != height) { - throw std::length_error( - "\n\nERROR : mat.trace()\n" - "\tthe matrix is not a square matrix, cannot get trace\n" - ); - } + if (width != height) { + throw std::length_error( + "\n\nERROR : mat.trace()\n" + "\tthe matrix is not a square matrix, cannot get trace\n" + ); + } #endif - T trace_total = 0; - for (size_t i = 0; i < height; ++i) - trace_total += matrix[i * width + i]; + T trace_total = 0; + for (size_t i = 0; i < height; ++i) + trace_total += matrix[i * width + i]; - return trace_total; - } + return trace_total; + } - /// @arg accepts a cyfre::mat objects - /// @returns T trace_total, the total sum of the main diagonal - template - T trace(const mat &input) { + /// @arg accepts a cyfre::mat objects + /// @returns T trace_total, the total sum of the main diagonal + template + T trace(const mat &input) { #ifndef CHECK_SHAPE_DISABLE - if (input.width != input.height) { - std::cerr << "\n\nERROR : mat.trace()\n"; - std::cerr << "\tthe matrix is not a square matrix, cannot get trace\n"; - exit(1); - } + if (input.width != input.height) { + std::cerr << "\n\nERROR : mat.trace()\n"; + std::cerr << "\tthe matrix is not a square matrix, cannot get trace\n"; + exit(1); + } #endif - T trace_total = 0; - for (size_t i = 0; i < input.height; ++i) - trace_total += input.matrix[i * input.width + i]; - return trace_total; - } + T trace_total = 0; + for (size_t i = 0; i < input.height; ++i) + trace_total += input.matrix[i * input.width + i]; + return trace_total; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/shaping/padding.cpp b/cyfre/shaping/padding.cpp index 814c03d..6a6d19e 100644 --- a/cyfre/shaping/padding.cpp +++ b/cyfre/shaping/padding.cpp @@ -5,55 +5,55 @@ #include namespace cyfre { - /// padding self - template - void mat::padding(size_t pad_height, size_t pad_width) { - if (pad_height == 0 && pad_width == 0) { - return; - } - - size_t new_height = height + (2 * pad_height); - size_t new_width = width + (2 * pad_width); - size_t dim_total = new_height * new_width; - - T *padded_matrix = new T[dim_total]; - - for (size_t i = 0; i < dim_total; ++i) - padded_matrix[i] = 0; - - size_t i = pad_height, j = pad_width; - - for (i = pad_height; i < pad_height + height; ++i) { - for (j = pad_width; j < pad_width + width; ++j) { - padded_matrix[i * new_width + j] = matrix[(i - pad_height) * width + (j - pad_width)]; - } - } - - delete[] matrix; - matrix = padded_matrix; - height = new_height; - width = new_width; + /// padding self + template + void mat::padding(size_t pad_height, size_t pad_width) { + if (pad_height == 0 && pad_width == 0) { + return; } - /// padding self - template - void mat::padding(size_t pad_length) { - padding(pad_length, pad_length); - } + size_t new_height = height + (2 * pad_height); + size_t new_width = width + (2 * pad_width); + size_t dim_total = new_height * new_width; - /// @returns a paddingd matrix copy - template - mat padding(mat input, size_t pad_height, size_t pad_width) { - input.padding(pad_height, pad_width); - return input; - } + T *padded_matrix = new T[dim_total]; + + for (size_t i = 0; i < dim_total; ++i) + padded_matrix[i] = 0; - /// @returns a paddingd matrix copy - template - mat padding(mat input, size_t pad_length) { - input.padding(pad_length, pad_length); - return input; + size_t i = pad_height, j = pad_width; + + for (i = pad_height; i < pad_height + height; ++i) { + for (j = pad_width; j < pad_width + width; ++j) { + padded_matrix[i * new_width + j] = matrix[(i - pad_height) * width + (j - pad_width)]; + } } + + delete[] matrix; + matrix = padded_matrix; + height = new_height; + width = new_width; + } + + /// padding self + template + void mat::padding(size_t pad_length) { + padding(pad_length, pad_length); + } + + /// @returns a paddingd matrix copy + template + mat padding(mat input, size_t pad_height, size_t pad_width) { + input.padding(pad_height, pad_width); + return input; + } + + /// @returns a paddingd matrix copy + template + mat padding(mat input, size_t pad_length) { + input.padding(pad_length, pad_length); + return input; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/shaping/transpose.cpp b/cyfre/shaping/transpose.cpp index a37f861..bea9da5 100644 --- a/cyfre/shaping/transpose.cpp +++ b/cyfre/shaping/transpose.cpp @@ -5,30 +5,30 @@ #include namespace cyfre { - /// transpose self - template - void mat::transpose() { - size_t i, j, k = 0; + /// transpose self + template + void mat::transpose() { + size_t i, j, k = 0; - T *rht = new T[width * height]; + T *rht = new T[width * height]; - for (j = 0; j < width; ++j) { - for (i = 0; i < height; ++i) { - rht[k++] = matrix[i * width + j]; - } - } - - delete[] matrix; - matrix = rht; - std::swap(height, width); + for (j = 0; j < width; ++j) { + for (i = 0; i < height; ++i) { + rht[k++] = matrix[i * width + j]; + } } - /// @returns a transposed matrix copy - template - mat transpose(mat input) { - input.transpose(); - return input; - } + delete[] matrix; + matrix = rht; + std::swap(height, width); + } + + /// @returns a transposed matrix copy + template + mat transpose(mat input) { + input.transpose(); + return input; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/statistics/matrix_stats.hpp b/cyfre/statistics/matrix_stats.hpp index 3d3d373..1c081fc 100644 --- a/cyfre/statistics/matrix_stats.hpp +++ b/cyfre/statistics/matrix_stats.hpp @@ -9,133 +9,133 @@ #include namespace cyfre { - namespace sts { - enum OBSERVATIONS - { - POPULATION = 0, - SAMPLE = 1 - }; - - template - long double mean(const mat &input) { - T total = input.sum(); - size_t n = input.height * input.width; - return (long double) total / (long double) n; + namespace sts { + enum OBSERVATIONS + { + POPULATION = 0, + SAMPLE = 1 + }; + + template + long double mean(const mat &input) { + T total = input.sum(); + size_t n = input.height * input.width; + return (long double) total / (long double) n; + } + + template + long double median(const mat &input) { + auto oddmiddle = [](T odd) { + if (odd == 1) + return (long double) 0; + return std::floor(((long double) odd / (long double) 2)); + }; + + if (input.height % 2 == 0 && input.width % 2 == 0) { + size_t hh = (input.height / 2) - 1; + size_t hw = (input.width / 2) - 1; + + return ((long double) input.matrix[hh * input.width + hw] + + (long double) input.matrix[hh * input.width + hw + 1] + + (long double) input.matrix[(hh + 1) * input.width + hw] + + (long double) input.matrix[(hh + 1) * input.width + (hw + 1)]) / + (long double) 4; + } else if (input.height % 2 != 0 && input.width % 2 == 0) { + size_t hh = oddmiddle(input.height); + size_t hw = (input.width / 2) - 1; + return ((long double) input.matrix[hh * input.width + hw] + + (long double) input.matrix[hh * input.width + hw + 1]) / + (long double) 2; + } else if (input.height % 2 == 0 && input.width % 2 != 0) { + size_t hh = (input.height / 2) - 1; + size_t hw = oddmiddle(input.width); + return ((long double) input.matrix[hh * input.width + hw] + + (long double) input.matrix[(hh + 1) * input.width + hw]) / + (long double) 2; + } else if (input.height % 2 != 0 && input.width % 2 != 0) { + size_t hh = oddmiddle(input.height); + size_t hw = oddmiddle(input.width); + return (long double) input.matrix[hh * input.width + hw]; + } else if ((input.height == 1) && (input.height == input.width)) { + return (long double) input.matrix[0 * input.width + 0]; + } + return 0; + } + + template + std::pair> mode(const mat &input) { + std::map e_counts; + for (size_t i = 0; i < input.height; ++i) { + for (size_t j = 0; j < input.width; ++j) { + auto curr = e_counts.find(input.matrix[i * input.width + j]); + if (curr == e_counts.end()) { + e_counts.insert({input.matrix[i * input.width + j], 1}); + } else { + e_counts[input.matrix[i * input.width + j]]++; + } } + } - template - long double median(const mat &input) { - auto oddmiddle = [](T odd) { - if (odd == 1) - return (long double) 0; - return std::floor(((long double) odd / (long double) 2)); - }; - - if (input.height % 2 == 0 && input.width % 2 == 0) { - size_t hh = (input.height / 2) - 1; - size_t hw = (input.width / 2) - 1; - - return ((long double) input.matrix[hh * input.width + hw] + - (long double) input.matrix[hh * input.width + hw + 1] + - (long double) input.matrix[(hh + 1) * input.width + hw] + - (long double) input.matrix[(hh + 1) * input.width + (hw + 1)]) / - (long double) 4; - } else if (input.height % 2 != 0 && input.width % 2 == 0) { - size_t hh = oddmiddle(input.height); - size_t hw = (input.width / 2) - 1; - return ((long double) input.matrix[hh * input.width + hw] + - (long double) input.matrix[hh * input.width + hw + 1]) / - (long double) 2; - } else if (input.height % 2 == 0 && input.width % 2 != 0) { - size_t hh = (input.height / 2) - 1; - size_t hw = oddmiddle(input.width); - return ((long double) input.matrix[hh * input.width + hw] + - (long double) input.matrix[(hh + 1) * input.width + hw]) / - (long double) 2; - } else if (input.height % 2 != 0 && input.width % 2 != 0) { - size_t hh = oddmiddle(input.height); - size_t hw = oddmiddle(input.width); - return (long double) input.matrix[hh * input.width + hw]; - } else if ((input.height == 1) && (input.height == input.width)) { - return (long double) input.matrix[0 * input.width + 0]; - } - return 0; + size_t max = size_t(std::numeric_limits::min()); + for (auto e: e_counts) { + size_t curr_count = e.second; + if (curr_count > max) { + max = curr_count; } + } - template - std::pair> mode(const mat &input) { - std::map e_counts; - for (size_t i = 0; i < input.height; ++i) { - for (size_t j = 0; j < input.width; ++j) { - auto curr = e_counts.find(input.matrix[i * input.width + j]); - if (curr == e_counts.end()) { - e_counts.insert({input.matrix[i * input.width + j], 1}); - } else { - e_counts[input.matrix[i * input.width + j]]++; - } - } - } - - size_t max = size_t(std::numeric_limits::min()); - for (auto e: e_counts) { - size_t curr_count = e.second; - if (curr_count > max) { - max = curr_count; - } - } - - std::set modes; - - for (auto e: e_counts) { - T curr_key = e.first; - size_t curr_count = e.second; - if (curr_count == max && curr_count != 1) { - modes.insert(curr_key); - } - } - - if (modes.empty()) - max = 0; - - std::vector pair_second; - pair_second.reserve(modes.size()); - for (auto e: modes) { - pair_second.push_back(e); - } - - return {max, pair_second}; - } + std::set modes; - /// @returns sum of squares - template - long double sofs(const mat &input) { - long double input_mean = mean(input); - long double sum_of_squares = 0; - for (size_t i = 0; i < input.height; ++i) { - for (size_t j = 0; j < input.width; ++j) { - sum_of_squares += (input.matrix[i * input.width + j] - input_mean) * - (input.matrix[i * input.width + j] - input_mean); - } - } - return sum_of_squares; + for (auto e: e_counts) { + T curr_key = e.first; + size_t curr_count = e.second; + if (curr_count == max && curr_count != 1) { + modes.insert(curr_key); } - - /// @returns variance - template - long double variance(const mat &input, const OBSERVATIONS type) { - // long double input_mean = mean(input); - long double sum_of_squares = sofs(input); - long double n = input.height * input.width; - - return sum_of_squares / (long double) (n - (long double) type); - } - - /// @returns standard deviation - template - long double stddvn(const mat &input, const OBSERVATIONS type) { - return std::sqrt(variance(input, type)); + } + + if (modes.empty()) + max = 0; + + std::vector pair_second; + pair_second.reserve(modes.size()); + for (auto e: modes) { + pair_second.push_back(e); + } + + return {max, pair_second}; + } + + /// @returns sum of squares + template + long double sofs(const mat &input) { + long double input_mean = mean(input); + long double sum_of_squares = 0; + for (size_t i = 0; i < input.height; ++i) { + for (size_t j = 0; j < input.width; ++j) { + sum_of_squares += + (input.matrix[i * input.width + j] - input_mean) * (input.matrix[i * input.width + j] - input_mean); } - } // namespace sts + } + return sum_of_squares; + } + + /// @returns variance + template + long double variance(const mat &input, const OBSERVATIONS type) { + // long double input_mean = mean(input); + long double sum_of_squares = sofs(input); + long double n = input.height * input.width; + + return sum_of_squares / (long double) (n - (long double) type); + } + + /// @returns standard deviation + template + long double stddvn(const mat &input, const OBSERVATIONS type) { + return std::sqrt(variance(input, type)); + } + } // namespace sts } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/test/test.cpp b/cyfre/test/test.cpp index a3cccaf..cb69272 100644 --- a/cyfre/test/test.cpp +++ b/cyfre/test/test.cpp @@ -3,382 +3,378 @@ #include int main() { - // ############### test 01 ############### - { - cyfre::mat mat_object(cyfre::TYPE::IDENTITY, 3); - cyfre::mat idet({{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}); - if (mat_object != idet) - throw std::logic_error("error at test 01"); - std::cout << "test 1 correct\n"; - } - - // ############### test 02 ############### - { - cyfre::mat mat_object(cyfre::TYPE::SCALARMATRIX, 3, 7); - cyfre::mat scalars({{7, 0, 0}, {0, 7, 0}, {0, 0, 7}}); - if (mat_object != scalars) - throw std::logic_error("error at test 02"); - std::cout << "test 2 correct\n"; - } - - // ############### test 03 ############### - { - cyfre::mat subject(cyfre::TYPE::NULLZERO, 3); - cyfre::mat correct({{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}); - if (subject != correct) - throw std::logic_error("error at test 03"); - std::cout << "test 3 correct\n"; - } - - // ############### test 04 ############### - { - cyfre::mat subject(3, 2, 5); - cyfre::mat correct({{5, 5}, {5, 5}, {5, 5}}); - if (subject != correct) - throw std::logic_error("error at test 04"); - std::cout << "test 4 correct\n"; - } - - // ############### test 05 ############### - { - cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); - subject.row_swap(1, 2); - cyfre::mat correct({{1, 2, 3}, {7, 8, 9}, {4, 5, 6}}); - if (subject != correct) - throw std::logic_error("error at test 05"); - std::cout << "test 5 correct\n"; - } - - // ############### test 06 ############### - { - cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); - subject.row_scale(5, 0); - cyfre::mat correct({{5, 10, 15}, {4, 5, 6}, {7, 8, 9}}); - if (subject != correct) - throw std::logic_error("error at test 06"); - std::cout << "test 6 correct\n"; - } - - // ############### test 07 ############### - { - cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {0, 0, 0}}); - subject.row_scale(7, 0, 2); - cyfre::mat correct({{1, 2, 3}, {4, 5, 6}, {7, 14, 21}}); - if (subject != correct) - throw std::logic_error("error at test 07"); - std::cout << "test 7 correct\n"; - } - - // ############### test 08 ############### - { - cyfre::mat subject({{1, 2}, {3, 4}}); - subject.scale_row(0, cyfre::SCALAR::MUL, 2); - cyfre::mat correct({{2, 4}, {3, 4}}); - if (subject != correct) - throw std::logic_error("error at test 08"); - std::cout << "test 8 correct\n"; - } - - // ############### test 09 ############### - { - cyfre::mat subject({{2, 4}, {6, 8}}); - subject.scale_column(1, cyfre::SCALAR::DIV, 2); - cyfre::mat correct({{2, 2}, {6, 4}}); - if (subject != correct) - throw std::logic_error("error at test 09"); - std::cout << "test 9 correct\n"; - } - - // ############### test 10 ############### - { - cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); - subject.row_operation(1, cyfre::SCALAR::MUL, 2); - cyfre::mat correct({{1, 2, 3}, {28, 40, 54}, {7, 8, 9}}); - if (subject != correct) - throw std::logic_error("error at test 10"); - std::cout << "test 10 correct\n"; - } - - // ############### test 11 ############### - { - cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); - subject.column_operation(1, cyfre::SCALAR::DIV, 2); - cyfre::mat correct({{1, 0, 3}, {4, 0, 6}, {7, 0, 9}}); - if (subject != correct) - throw std::logic_error("error at test 11"); - std::cout << "test 11 correct\n"; - } - - // ############### test 12 ############### - { - cyfre::mat subject({{1, 2}, {3, 4}}); - subject = subject + 2; - cyfre::mat correct({{3, 4}, {5, 6}}); - if (subject != correct) - throw std::logic_error("error at test 12"); - std::cout << "test 12 correct\n"; - } - - // ############### test 13 ############### - { - cyfre::mat subject({{1, 2}, {3, 4}}); - subject += 2; - cyfre::mat correct({{3, 4}, {5, 6}}); - if (subject != correct) - throw std::logic_error("error at test 13"); - std::cout << "test 13 correct\n"; - } - - // ############### test 14 ############### - { - cyfre::mat A({{1, 2, 3}, {4, 5, 6}}); - - cyfre::mat B({{-1, -2, -3}, {-4, -5, -6}}); - cyfre::mat C = A + B; - cyfre::mat correct(2, 3, 0); - if (C != correct) - throw std::logic_error("error at test 14"); - std::cout << "test 14 correct\n"; - } - - // ############### test 15 ############### - { - cyfre::mat A({{10, 1, 33}, {44, 50, 12}}); - cyfre::mat B({{7, 19, 5}, {7, 6, 5}}); - cyfre::mat C = A - B; - ; - cyfre::mat correct({{3, -18, 28}, {37, 44, 7}}); - if (C != correct) - throw std::logic_error("error at test 15"); - std::cout << "test 15 correct\n"; - } - - // ############### test 16 ############### - { - cyfre::mat A({{2, 4, 6}, {8, 2, 4}}); - cyfre::mat B({{1, 4, 3}, {2, 2, 1}}); - cyfre::mat C = cyfre::hadamard(A, B); - cyfre::mat correct({{2, 16, 18}, {16, 4, 4}}); - if (C != correct) - throw std::logic_error("error at test 16"); - std::cout << "test 16 correct\n"; - } - - // ############### test 17 ############### - { - cyfre::mat X({{7, 12, 13}, {14, 5, 20}, {66, 42, -4}}); - cyfre::mat W{-3, 4, 56}; - - cyfre::mat C = W * X; - cyfre::mat correct{3731, 2336, -183}; - - if (C != correct) - throw std::logic_error("error at test 17"); - std::cout << "test 17 correct\n"; - } - - // ############### test 18 ############### - { - auto square = [](int x) { return x * x; }; - cyfre::mat X( - {{23, 12, 53, 34, 23}, - {33, 77, 53, 90, 28}, - {87, 26, 11, 24, 31}, - {84, 32, 73, 64, 26}, - {77, 88, 45, 97, 86}} - ); - X.apply(square); - cyfre::mat correct( - {{529, 144, 2809, 1156, 529}, - {1089, 5929, 2809, 8100, 784}, - {7569, 676, 121, 576, 961}, - {7056, 1024, 5329, 4096, 676}, - {5929, 7744, 2025, 9409, 7396}} - ); - if (X != correct) - throw std::logic_error("error at test 18"); - std::cout << "test 18 correct\n"; - } - - // ############### test 19 ############### - { - cyfre::mat X({ - {1, 2, 3, 4}, - {5, 6, 7, 8}, - }); - X.transpose(); - cyfre::mat correct({{1, 5}, {2, 6}, {3, 7}, {4, 8}}); - if (X != correct) - throw std::logic_error("error at test 19"); - std::cout << "test 19 correct\n"; - } - - // ############### test 20 ############### - { - cyfre::mat X({{7, 12, 13}, {14, 5, 20}, {66, 42, -4}}); - cyfre::mat X_cubed = cyfre::power(X, 3); - cyfre::mat X_squared = X; - X_squared.power(2); - - cyfre::mat C1({{35599, 28068, 26659}, {38210, 31505, 39196}, {130302, 85590, 20042}}); - cyfre::mat C2({{1075, 690, 279}, {1488, 1033, 202}, {786, 834, 1714}}); - if (X_cubed != C1) - throw std::logic_error("wrong answer on test 20 cube"); - if (X_squared != C2) - throw std::logic_error("wrong answer on test 20 square"); - std::cout << "CORRECT ANSWERS IN TEST 20\n"; - } - - // ############### test 21 ############### - { - cyfre::mat X({{23, 12, 53}, {33, 77, 53}, {87, 26, 11}}); - X.inv(); - cyfre::mat correct( - {{0.00196078L, -0.00460101L, 0.0127211L}, - {-0.0156863L, 0.0160925L, -0.00195709L}, - {0.0215686L, -0.00164691L, -0.00507736L}} - ); - for (size_t i = 0; i < 3; ++i) { - for (size_t j = 0; j < 3; ++j) { - if ((std::to_string(X(i, j))) != (std::to_string(correct(i, j)))) { - throw std::logic_error("wrong answer inverse 21\n"); - } - } + // ############### test 01 ############### + { + cyfre::mat mat_object(cyfre::TYPE::IDENTITY, 3); + cyfre::mat idet({{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}); + if (mat_object != idet) + throw std::logic_error("error at test 01"); + std::cout << "test 1 correct\n"; + } + + // ############### test 02 ############### + { + cyfre::mat mat_object(cyfre::TYPE::SCALARMATRIX, 3, 7); + cyfre::mat scalars({{7, 0, 0}, {0, 7, 0}, {0, 0, 7}}); + if (mat_object != scalars) + throw std::logic_error("error at test 02"); + std::cout << "test 2 correct\n"; + } + + // ############### test 03 ############### + { + cyfre::mat subject(cyfre::TYPE::NULLZERO, 3); + cyfre::mat correct({{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}); + if (subject != correct) + throw std::logic_error("error at test 03"); + std::cout << "test 3 correct\n"; + } + + // ############### test 04 ############### + { + cyfre::mat subject(3, 2, 5); + cyfre::mat correct({{5, 5}, {5, 5}, {5, 5}}); + if (subject != correct) + throw std::logic_error("error at test 04"); + std::cout << "test 4 correct\n"; + } + + // ############### test 05 ############### + { + cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + subject.row_swap(1, 2); + cyfre::mat correct({{1, 2, 3}, {7, 8, 9}, {4, 5, 6}}); + if (subject != correct) + throw std::logic_error("error at test 05"); + std::cout << "test 5 correct\n"; + } + + // ############### test 06 ############### + { + cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + subject.row_scale(5, 0); + cyfre::mat correct({{5, 10, 15}, {4, 5, 6}, {7, 8, 9}}); + if (subject != correct) + throw std::logic_error("error at test 06"); + std::cout << "test 6 correct\n"; + } + + // ############### test 07 ############### + { + cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {0, 0, 0}}); + subject.row_scale(7, 0, 2); + cyfre::mat correct({{1, 2, 3}, {4, 5, 6}, {7, 14, 21}}); + if (subject != correct) + throw std::logic_error("error at test 07"); + std::cout << "test 7 correct\n"; + } + + // ############### test 08 ############### + { + cyfre::mat subject({{1, 2}, {3, 4}}); + subject.scale_row(0, cyfre::SCALAR::MUL, 2); + cyfre::mat correct({{2, 4}, {3, 4}}); + if (subject != correct) + throw std::logic_error("error at test 08"); + std::cout << "test 8 correct\n"; + } + + // ############### test 09 ############### + { + cyfre::mat subject({{2, 4}, {6, 8}}); + subject.scale_column(1, cyfre::SCALAR::DIV, 2); + cyfre::mat correct({{2, 2}, {6, 4}}); + if (subject != correct) + throw std::logic_error("error at test 09"); + std::cout << "test 9 correct\n"; + } + + // ############### test 10 ############### + { + cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + subject.row_operation(1, cyfre::SCALAR::MUL, 2); + cyfre::mat correct({{1, 2, 3}, {28, 40, 54}, {7, 8, 9}}); + if (subject != correct) + throw std::logic_error("error at test 10"); + std::cout << "test 10 correct\n"; + } + + // ############### test 11 ############### + { + cyfre::mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + subject.column_operation(1, cyfre::SCALAR::DIV, 2); + cyfre::mat correct({{1, 0, 3}, {4, 0, 6}, {7, 0, 9}}); + if (subject != correct) + throw std::logic_error("error at test 11"); + std::cout << "test 11 correct\n"; + } + + // ############### test 12 ############### + { + cyfre::mat subject({{1, 2}, {3, 4}}); + subject = subject + 2; + cyfre::mat correct({{3, 4}, {5, 6}}); + if (subject != correct) + throw std::logic_error("error at test 12"); + std::cout << "test 12 correct\n"; + } + + // ############### test 13 ############### + { + cyfre::mat subject({{1, 2}, {3, 4}}); + subject += 2; + cyfre::mat correct({{3, 4}, {5, 6}}); + if (subject != correct) + throw std::logic_error("error at test 13"); + std::cout << "test 13 correct\n"; + } + + // ############### test 14 ############### + { + cyfre::mat A({{1, 2, 3}, {4, 5, 6}}); + + cyfre::mat B({{-1, -2, -3}, {-4, -5, -6}}); + cyfre::mat C = A + B; + cyfre::mat correct(2, 3, 0); + if (C != correct) + throw std::logic_error("error at test 14"); + std::cout << "test 14 correct\n"; + } + + // ############### test 15 ############### + { + cyfre::mat A({{10, 1, 33}, {44, 50, 12}}); + cyfre::mat B({{7, 19, 5}, {7, 6, 5}}); + cyfre::mat C = A - B; + ; + cyfre::mat correct({{3, -18, 28}, {37, 44, 7}}); + if (C != correct) + throw std::logic_error("error at test 15"); + std::cout << "test 15 correct\n"; + } + + // ############### test 16 ############### + { + cyfre::mat A({{2, 4, 6}, {8, 2, 4}}); + cyfre::mat B({{1, 4, 3}, {2, 2, 1}}); + cyfre::mat C = cyfre::hadamard(A, B); + cyfre::mat correct({{2, 16, 18}, {16, 4, 4}}); + if (C != correct) + throw std::logic_error("error at test 16"); + std::cout << "test 16 correct\n"; + } + + // ############### test 17 ############### + { + cyfre::mat X({{7, 12, 13}, {14, 5, 20}, {66, 42, -4}}); + cyfre::mat W{-3, 4, 56}; + + cyfre::mat C = W * X; + cyfre::mat correct{3731, 2336, -183}; + + if (C != correct) + throw std::logic_error("error at test 17"); + std::cout << "test 17 correct\n"; + } + + // ############### test 18 ############### + { + auto square = [](int x) { return x * x; }; + cyfre::mat X( + {{23, 12, 53, 34, 23}, {33, 77, 53, 90, 28}, {87, 26, 11, 24, 31}, {84, 32, 73, 64, 26}, {77, 88, 45, 97, 86}} + ); + X.apply(square); + cyfre::mat correct( + {{529, 144, 2809, 1156, 529}, + {1089, 5929, 2809, 8100, 784}, + {7569, 676, 121, 576, 961}, + {7056, 1024, 5329, 4096, 676}, + {5929, 7744, 2025, 9409, 7396}} + ); + if (X != correct) + throw std::logic_error("error at test 18"); + std::cout << "test 18 correct\n"; + } + + // ############### test 19 ############### + { + cyfre::mat X({ + {1, 2, 3, 4}, + {5, 6, 7, 8}, + }); + X.transpose(); + cyfre::mat correct({{1, 5}, {2, 6}, {3, 7}, {4, 8}}); + if (X != correct) + throw std::logic_error("error at test 19"); + std::cout << "test 19 correct\n"; + } + + // ############### test 20 ############### + { + cyfre::mat X({{7, 12, 13}, {14, 5, 20}, {66, 42, -4}}); + cyfre::mat X_cubed = cyfre::power(X, 3); + cyfre::mat X_squared = X; + X_squared.power(2); + + cyfre::mat C1({{35599, 28068, 26659}, {38210, 31505, 39196}, {130302, 85590, 20042}}); + cyfre::mat C2({{1075, 690, 279}, {1488, 1033, 202}, {786, 834, 1714}}); + if (X_cubed != C1) + throw std::logic_error("wrong answer on test 20 cube"); + if (X_squared != C2) + throw std::logic_error("wrong answer on test 20 square"); + std::cout << "CORRECT ANSWERS IN TEST 20\n"; + } + + // ############### test 21 ############### + { + cyfre::mat X({{23, 12, 53}, {33, 77, 53}, {87, 26, 11}}); + X.inv(); + cyfre::mat correct( + {{0.00196078L, -0.00460101L, 0.0127211L}, + {-0.0156863L, 0.0160925L, -0.00195709L}, + {0.0215686L, -0.00164691L, -0.00507736L}} + ); + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + if ((std::to_string(X(i, j))) != (std::to_string(correct(i, j)))) { + throw std::logic_error("wrong answer inverse 21\n"); } - std::cout << "test 21 correct\n"; + } } - - // ############### test 22 ############### - { - cyfre::mat X({{1, 2, 3, 4}, {5, 6, 7, 8}, {-2, 3, -4, 1}}); - X = cyfre::rref(X); - cyfre::mat correct({{1, 0, 0, -1}, {0, 1, 0, 1}, {0, 0, 1, 1}}); - for (size_t i = 0; i < 3; ++i) { - for (size_t j = 0; j < 3; ++j) { - if ((std::to_string(X(i, j))) != (std::to_string(correct(i, j)))) { - throw std::logic_error("wrong answer rref 22\n"); - } - } - } - std::cout << "test 22 correct\n"; - } - - // ############### test 23 ############### - { - cyfre::mat X({{5, 10, -15, 20}, {30, -35, -40, -45}, {55, 60, 75, -80}, {90, 95, 100, -105}}); - long double determinant = cyfre::det(X); - if (std::to_string((int) (float) determinant) != "-720000") - throw std::logic_error("wrong determinant (23)"); - std::cout << "correct determinant (23)\n"; - } - - // ############### test 24 ############### - { - cyfre::mat X({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); - int diag_sum = X.trace(); - if (diag_sum != 15) - throw std::logic_error("wrong trace (24)"); - std::cout << "correct trace (24)\n"; - } - - // ############### test 25 ############### - { - cyfre::mat X({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); - int diag_sum = X.sum(); - if (diag_sum != 45) - throw std::logic_error("wrong sum (25)"); - std::cout << "correct sum (25)\n"; - } - - // ############### test 26 ############### - { - cyfre::mat X({{7, 2, 4}, {4, 7, 6}, {7, 4, 9}}); - - long double mean = cyfre::sts::mean(X); - long double median = cyfre::sts::median(X); - - std::pair> getmode = cyfre::sts::mode(X); - - size_t numbers_of_modes = getmode.second.size(); - size_t modes_occurrence = getmode.first; - - std::vector modes = getmode.second; - - if (std::to_string(mean) != "5.555556") - throw std::logic_error("wrong mean (26:1)"); - if (std::to_string((int) (float) median) != "7") - throw std::logic_error("wrong median (26:2)"); - if (numbers_of_modes != 2) - throw std::logic_error("wrong numbers_of_modes (26:3)"); - if (modes_occurrence != 3) - throw std::logic_error("wrong modes_occurrence (26:4)"); - if (modes[0] != 4) - throw std::logic_error("wrong modes[0] (26:5)"); - if (modes[1] != 7) - throw std::logic_error("wrong modes[1] (26:6)"); - - std::cout << "mean, median modem correct outputs : 1 (26)\n"; - - /* - mean = 5.55556 - median = 7 - numbers_of_modes = 2 - modes_occurrence = 3 - modes = [7,4] - */ - cyfre::mat SSS({7, 2, 4, 3, 9}); - - long double sum_of_square = cyfre::sts::sofs(SSS), variance = cyfre::sts::variance(SSS, cyfre::sts::SAMPLE), - standard_deviation = cyfre::sts::stddvn(SSS, cyfre::sts::SAMPLE); - - // sum_of_square = 34 - // variance = 8.5 - // standard_deviation = 2.91548 - - if (std::to_string((int) (float) sum_of_square) != "34") - throw std::logic_error("wrong sum_of_square (26:7)"); - if (std::to_string((float) variance) != "8.500000") - throw std::logic_error("wrong variance (26:8)"); - if (std::to_string((float) standard_deviation) != "2.915476") - throw std::logic_error("wrong standard_deviation (26:9)"); - std::cout << "correct outputs : 2 (26)\n"; - } - - // ############### test 27 ############### - { - cyfre::mat subject1({{5, 10, 15, 20}, {30, 60, 2, -2}, {7, 6, 5, -232}}); - cyfre::mat target1( - {{0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - {0, 5, 10, 15, 20, 0}, - {0, 30, 60, 2, -2, 0}, - {0, 7, 6, 5, -232, 0}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}} - ); - subject1.padding(2, 1); - if (subject1 != target1) { - throw std::logic_error("test 27 error in padding output"); - } else { - std::cout << "correct (27)\n"; + std::cout << "test 21 correct\n"; + } + + // ############### test 22 ############### + { + cyfre::mat X({{1, 2, 3, 4}, {5, 6, 7, 8}, {-2, 3, -4, 1}}); + X = cyfre::rref(X); + cyfre::mat correct({{1, 0, 0, -1}, {0, 1, 0, 1}, {0, 0, 1, 1}}); + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + if ((std::to_string(X(i, j))) != (std::to_string(correct(i, j)))) { + throw std::logic_error("wrong answer rref 22\n"); } + } } - - // ############### test 28 ############### - { - cyfre::mat A{{1, 2, 3}, {4, 5, 6}, {6, 5, 4}}; - cyfre::mat B{{1, 2, 3}, {4, 5, 6}, {6, 5, 4}}; - cyfre::mat C = A; - cyfre::mat D; - D = B; - cyfre::mat E = B * A; - cyfre::mat F = B * A * E; - cyfre::mat G; - G = F * E; - cyfre::mat H; - H = F * G * B; - cyfre::mat Z(A * F); + std::cout << "test 22 correct\n"; + } + + // ############### test 23 ############### + { + cyfre::mat X({{5, 10, -15, 20}, {30, -35, -40, -45}, {55, 60, 75, -80}, {90, 95, 100, -105}}); + long double determinant = cyfre::det(X); + if (std::to_string((int) (float) determinant) != "-720000") + throw std::logic_error("wrong determinant (23)"); + std::cout << "correct determinant (23)\n"; + } + + // ############### test 24 ############### + { + cyfre::mat X({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + int diag_sum = X.trace(); + if (diag_sum != 15) + throw std::logic_error("wrong trace (24)"); + std::cout << "correct trace (24)\n"; + } + + // ############### test 25 ############### + { + cyfre::mat X({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + int diag_sum = X.sum(); + if (diag_sum != 45) + throw std::logic_error("wrong sum (25)"); + std::cout << "correct sum (25)\n"; + } + + // ############### test 26 ############### + { + cyfre::mat X({{7, 2, 4}, {4, 7, 6}, {7, 4, 9}}); + + long double mean = cyfre::sts::mean(X); + long double median = cyfre::sts::median(X); + + std::pair> getmode = cyfre::sts::mode(X); + + size_t numbers_of_modes = getmode.second.size(); + size_t modes_occurrence = getmode.first; + + std::vector modes = getmode.second; + + if (std::to_string(mean) != "5.555556") + throw std::logic_error("wrong mean (26:1)"); + if (std::to_string((int) (float) median) != "7") + throw std::logic_error("wrong median (26:2)"); + if (numbers_of_modes != 2) + throw std::logic_error("wrong numbers_of_modes (26:3)"); + if (modes_occurrence != 3) + throw std::logic_error("wrong modes_occurrence (26:4)"); + if (modes[0] != 4) + throw std::logic_error("wrong modes[0] (26:5)"); + if (modes[1] != 7) + throw std::logic_error("wrong modes[1] (26:6)"); + + std::cout << "mean, median modem correct outputs : 1 (26)\n"; + + /* + mean = 5.55556 + median = 7 + numbers_of_modes = 2 + modes_occurrence = 3 + modes = [7,4] + */ + cyfre::mat SSS({7, 2, 4, 3, 9}); + + long double sum_of_square = cyfre::sts::sofs(SSS), variance = cyfre::sts::variance(SSS, cyfre::sts::SAMPLE), + standard_deviation = cyfre::sts::stddvn(SSS, cyfre::sts::SAMPLE); + + // sum_of_square = 34 + // variance = 8.5 + // standard_deviation = 2.91548 + + if (std::to_string((int) (float) sum_of_square) != "34") + throw std::logic_error("wrong sum_of_square (26:7)"); + if (std::to_string((float) variance) != "8.500000") + throw std::logic_error("wrong variance (26:8)"); + if (std::to_string((float) standard_deviation) != "2.915476") + throw std::logic_error("wrong standard_deviation (26:9)"); + std::cout << "correct outputs : 2 (26)\n"; + } + + // ############### test 27 ############### + { + cyfre::mat subject1({{5, 10, 15, 20}, {30, 60, 2, -2}, {7, 6, 5, -232}}); + cyfre::mat target1( + {{0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 5, 10, 15, 20, 0}, + {0, 30, 60, 2, -2, 0}, + {0, 7, 6, 5, -232, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0}} + ); + subject1.padding(2, 1); + if (subject1 != target1) { + throw std::logic_error("test 27 error in padding output"); + } else { + std::cout << "correct (27)\n"; } - - return 0; + } + + // ############### test 28 ############### + { + cyfre::mat A{{1, 2, 3}, {4, 5, 6}, {6, 5, 4}}; + cyfre::mat B{{1, 2, 3}, {4, 5, 6}, {6, 5, 4}}; + cyfre::mat C = A; + cyfre::mat D; + D = B; + cyfre::mat E = B * A; + cyfre::mat F = B * A * E; + cyfre::mat G; + G = F * E; + cyfre::mat H; + H = F * G * B; + cyfre::mat Z(A * F); + } + + return 0; } \ No newline at end of file diff --git a/cyfre/transform/apply.cpp b/cyfre/transform/apply.cpp index 1598410..b76d750 100644 --- a/cyfre/transform/apply.cpp +++ b/cyfre/transform/apply.cpp @@ -5,15 +5,15 @@ #include namespace cyfre { - // ================ applying function ============================== - template - void mat::apply(std::function function_name) { - for (size_t i = 0; i < height; ++i) { - for (size_t j = 0; j < width; ++j) { - matrix[i * width + j] = function_name(matrix[i * width + j]); - } - } + // ================ applying function ============================== + template + void mat::apply(std::function function_name) { + for (size_t i = 0; i < height; ++i) { + for (size_t j = 0; j < width; ++j) { + matrix[i * width + j] = function_name(matrix[i * width + j]); + } } + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/transform/inverse.cpp b/cyfre/transform/inverse.cpp index d53a0b5..ff40963 100644 --- a/cyfre/transform/inverse.cpp +++ b/cyfre/transform/inverse.cpp @@ -5,84 +5,82 @@ #include namespace cyfre { - // ============================= INVERSE MATRIX ================================ + // ============================= INVERSE MATRIX ================================ - /// converts matrix to it's inverse form - template - void mat::inv() { + /// converts matrix to it's inverse form + template + void mat::inv() { #ifndef CHECK_SHAPE_DISABLE - if (height != width) - throw std::length_error("\n\nERROR : cyfre::mat::inv() - cannot inverse a non-square matrix"); + if (height != width) + throw std::length_error("\n\nERROR : cyfre::mat::inv() - cannot inverse a non-square matrix"); #endif - mat inverse(TYPE::IDENTITY, height); - - auto nonzrow = [](const mat &input, size_t i, size_t j) -> long long int { - for (size_t r = i; r < input.height; ++r) { - if (input.matrix[r * input.width + j] != 0) { - return r; - } - } - return -1; - }; - - auto fix_pivot = [&inverse](mat &input, size_t pi, size_t pj) { - for (size_t i = 0; i < input.height; ++i) { - if (i != pi) { - inverse.row_scale(-input.matrix[i * input.width + pj], pi, i); - input.row_scale(-input.matrix[i * input.width + pj], pi, i); - } - } - }; - - auto make_pivot = [&inverse](mat &input, size_t pi, size_t pj) { - inverse.scale_row(pi, DIV, input.matrix[pi * input.width + pj]); - input.scale_row(pi, DIV, input.matrix[pi * input.width + pj]); - }; - - size_t cpi = 0; - size_t cpj = 0; - - while (cpi < height && cpj < width) { - long long int nonzerorow = nonzrow(*this, cpi, cpj); - - if (nonzerorow < 0) { - cpj++; - continue; - } - - if (nonzerorow != (long long int) cpi) { - this->row_swap(cpi, nonzerorow); - inverse.row_swap(cpi, nonzerorow); - } - - if (matrix[cpi * width + cpj] != 1) - make_pivot(*this, cpi, cpj); - fix_pivot(*this, cpi, cpj); - cpi++; - cpj++; - } + mat inverse(TYPE::IDENTITY, height); - for (size_t i = 0; i < height; ++i) { - if (matrix[i * width + i] == 0) - throw std::domain_error( - "\n\nERROR: cyfre::mat::inv() - matrix determinant is zero, cannot invert matrix" - ); + auto nonzrow = [](const mat &input, size_t i, size_t j) -> long long int { + for (size_t r = i; r < input.height; ++r) { + if (input.matrix[r * input.width + j] != 0) { + return r; } - - delete[] matrix; - matrix = inverse.matrix; - inverse.matrix = nullptr; - inverse.height = 0; - inverse.width = 0; + } + return -1; + }; + + auto fix_pivot = [&inverse](mat &input, size_t pi, size_t pj) { + for (size_t i = 0; i < input.height; ++i) { + if (i != pi) { + inverse.row_scale(-input.matrix[i * input.width + pj], pi, i); + input.row_scale(-input.matrix[i * input.width + pj], pi, i); + } + } + }; + + auto make_pivot = [&inverse](mat &input, size_t pi, size_t pj) { + inverse.scale_row(pi, DIV, input.matrix[pi * input.width + pj]); + input.scale_row(pi, DIV, input.matrix[pi * input.width + pj]); + }; + + size_t cpi = 0; + size_t cpj = 0; + + while (cpi < height && cpj < width) { + long long int nonzerorow = nonzrow(*this, cpi, cpj); + + if (nonzerorow < 0) { + cpj++; + continue; + } + + if (nonzerorow != (long long int) cpi) { + this->row_swap(cpi, nonzerorow); + inverse.row_swap(cpi, nonzerorow); + } + + if (matrix[cpi * width + cpj] != 1) + make_pivot(*this, cpi, cpj); + fix_pivot(*this, cpi, cpj); + cpi++; + cpj++; } - /// @returns inverse of a matrix - template - mat inv(mat input) { - input.inv(); - return input; + for (size_t i = 0; i < height; ++i) { + if (matrix[i * width + i] == 0) + throw std::domain_error("\n\nERROR: cyfre::mat::inv() - matrix determinant is zero, cannot invert matrix"); } + + delete[] matrix; + matrix = inverse.matrix; + inverse.matrix = nullptr; + inverse.height = 0; + inverse.width = 0; + } + + /// @returns inverse of a matrix + template + mat inv(mat input) { + input.inv(); + return input; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/transform/power.cpp b/cyfre/transform/power.cpp index 79eea50..ba77892 100644 --- a/cyfre/transform/power.cpp +++ b/cyfre/transform/power.cpp @@ -5,50 +5,50 @@ #include namespace cyfre { - // ============================== MATRIX EXPOENTIAL ============================== + // ============================== MATRIX EXPOENTIAL ============================== - /// @returns raised matrix to a certain number 'p' - /// @note raising to a negative integer(inverse) is not supported yet but will be in the future - template - void mat::power(size_t p) { + /// @returns raised matrix to a certain number 'p' + /// @note raising to a negative integer(inverse) is not supported yet but will be in the future + template + void mat::power(size_t p) { #ifndef CHECK_SHAPE_DISABLE - if (width != height) { - throw std::length_error("\n\nERROR : mat.power(size_t p)\n\tcannot raise a non-square matrix\n"); - } + if (width != height) { + throw std::length_error("\n\nERROR : mat.power(size_t p)\n\tcannot raise a non-square matrix\n"); + } #endif - if (p == 0) { - mat identity(TYPE::IDENTITY, width); - *this = identity; - } else if (p >= 2) { - mat multiplier = *this; - for (size_t i = 2; i <= p; ++i) { - *this *= multiplier; - } - } + if (p == 0) { + mat identity(TYPE::IDENTITY, width); + *this = identity; + } else if (p >= 2) { + mat multiplier = *this; + for (size_t i = 2; i <= p; ++i) { + *this *= multiplier; + } } + } - /// @returns raised matrix to a certain number 'p' - /// @note raising to a negative integer(inverse) is not supported yet but will be in the future - template - mat power(mat base, size_t p) { + /// @returns raised matrix to a certain number 'p' + /// @note raising to a negative integer(inverse) is not supported yet but will be in the future + template + mat power(mat base, size_t p) { #ifndef CHECK_SHAPE_DISABLE - if (base.width != base.height) { - throw std::length_error("\n\nERROR : mat.power(size_t p)\n\tcannot raise a non-square matrix\n"); - } + if (base.width != base.height) { + throw std::length_error("\n\nERROR : mat.power(size_t p)\n\tcannot raise a non-square matrix\n"); + } #endif - if (p == 0) { - mat identity(IDENTITY, base.width); - base = identity; - } else if (p >= 2) { - mat multiplier = base; - for (size_t i = 2; i <= p; ++i) { - base *= multiplier; - } - } - return base; + if (p == 0) { + mat identity(IDENTITY, base.width); + base = identity; + } else if (p >= 2) { + mat multiplier = base; + for (size_t i = 2; i <= p; ++i) { + base *= multiplier; + } } + return base; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/transform/ref.cpp b/cyfre/transform/ref.cpp index 112faaa..0028500 100644 --- a/cyfre/transform/ref.cpp +++ b/cyfre/transform/ref.cpp @@ -5,51 +5,51 @@ #include namespace cyfre { - /// converts matrix to row echelon form of a matrix - template - void mat::ref() { - auto nonzrow = [](const mat &input, const size_t i, const size_t j) -> long long int { - for (size_t r = i; r < input.height; ++r) { - if (input.matrix[r * input.width + j] != 0) { - return r; - } - } - return -1; - }; - - auto fix_nonzero_pivot = [](mat &input, const size_t pi, const size_t pj) { - for (size_t i = pi + 1; i < input.height; ++i) { - input.row_scale(-(input.matrix[i * input.width + pj] / input.matrix[pi * input.width + pj]), pi, i); - } - }; - - size_t cpi = 0; - size_t cpj = 0; - - while (cpi < height && cpj < width) { - long long int nonzerorow = nonzrow(*this, cpi, cpj); - - if (nonzerorow < 0) { - cpj++; - continue; - } - - if (nonzerorow != (long long int) cpi) { - row_swap(cpi, nonzerorow); - } - - fix_nonzero_pivot(*this, cpi, cpj); - cpi++; - cpj++; + /// converts matrix to row echelon form of a matrix + template + void mat::ref() { + auto nonzrow = [](const mat &input, const size_t i, const size_t j) -> long long int { + for (size_t r = i; r < input.height; ++r) { + if (input.matrix[r * input.width + j] != 0) { + return r; } + } + return -1; + }; + + auto fix_nonzero_pivot = [](mat &input, const size_t pi, const size_t pj) { + for (size_t i = pi + 1; i < input.height; ++i) { + input.row_scale(-(input.matrix[i * input.width + pj] / input.matrix[pi * input.width + pj]), pi, i); + } + }; + + size_t cpi = 0; + size_t cpj = 0; + + while (cpi < height && cpj < width) { + long long int nonzerorow = nonzrow(*this, cpi, cpj); + + if (nonzerorow < 0) { + cpj++; + continue; + } + + if (nonzerorow != (long long int) cpi) { + row_swap(cpi, nonzerorow); + } + + fix_nonzero_pivot(*this, cpi, cpj); + cpi++; + cpj++; } - - /// @returns reduced row echelon form of a matrix - template - mat ref(mat input) { - input.ref(); - return input; - } + } + + /// @returns reduced row echelon form of a matrix + template + mat ref(mat input) { + input.ref(); + return input; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/cyfre/transform/rref.cpp b/cyfre/transform/rref.cpp index b07ef35..103fc09 100644 --- a/cyfre/transform/rref.cpp +++ b/cyfre/transform/rref.cpp @@ -5,57 +5,57 @@ #include namespace cyfre { - /// converts matrix to reduced row echelon form of a matrix - template - void mat::rref() { - auto nonzrow = [](const mat &input, size_t i, size_t j) -> long long int { - for (size_t r = i; r < input.height; ++r) { - if (input.matrix[r * input.width + j] != 0) { - return r; - } - } - return -1; - }; - - auto fix_pivot = [](mat &input, size_t pi, size_t pj) { - for (size_t i = 0; i < input.height; ++i) { - if (i != pi) { - input.row_scale(-input.matrix[i * input.width + pj], pi, i); - } - } - }; - - auto make_pivot = [](mat &input, size_t pi, size_t pj) { - input.scale_row(pi, DIV, input.matrix[pi * input.width + pj]); - }; - - size_t cpi = 0; - size_t cpj = 0; - - while (cpi < height && cpj < width) { - long long int nonzerorow = nonzrow(*this, cpi, cpj); - - if (nonzerorow < 0) { - cpj++; - continue; - } - - if (nonzerorow != (long long int) cpi) - this->row_swap(cpi, nonzerorow); - if (matrix[cpi * width + cpj] != 1) - make_pivot(*this, cpi, cpj); - fix_pivot(*this, cpi, cpj); - cpi++; - cpj++; + /// converts matrix to reduced row echelon form of a matrix + template + void mat::rref() { + auto nonzrow = [](const mat &input, size_t i, size_t j) -> long long int { + for (size_t r = i; r < input.height; ++r) { + if (input.matrix[r * input.width + j] != 0) { + return r; } + } + return -1; + }; + + auto fix_pivot = [](mat &input, size_t pi, size_t pj) { + for (size_t i = 0; i < input.height; ++i) { + if (i != pi) { + input.row_scale(-input.matrix[i * input.width + pj], pi, i); + } + } + }; + + auto make_pivot = [](mat &input, size_t pi, size_t pj) { + input.scale_row(pi, DIV, input.matrix[pi * input.width + pj]); + }; + + size_t cpi = 0; + size_t cpj = 0; + + while (cpi < height && cpj < width) { + long long int nonzerorow = nonzrow(*this, cpi, cpj); + + if (nonzerorow < 0) { + cpj++; + continue; + } + + if (nonzerorow != (long long int) cpi) + this->row_swap(cpi, nonzerorow); + if (matrix[cpi * width + cpj] != 1) + make_pivot(*this, cpi, cpj); + fix_pivot(*this, cpi, cpj); + cpi++; + cpj++; } - - /// @returns reduced row echelon form of a matrix - template - mat rref(mat input) { - input.rref(); - return input; - } + } + + /// @returns reduced row echelon form of a matrix + template + mat rref(mat input) { + input.rref(); + return input; + } } // namespace cyfre #endif \ No newline at end of file diff --git a/docs/specs.md b/docs/specs.md new file mode 100644 index 0000000..4a54348 --- /dev/null +++ b/docs/specs.md @@ -0,0 +1,5 @@ +# Implementation Specifications + +## **Rules** + +1. No virtual methods. \ No newline at end of file diff --git a/include/cyfre/cyfre.hpp b/include/cyfre/cyfre.hpp new file mode 100644 index 0000000..47b5534 --- /dev/null +++ b/include/cyfre/cyfre.hpp @@ -0,0 +1,44 @@ +#ifndef MRDCVLSC_CYFRE_HPP +#define MRDCVLSC_CYFRE_HPP + +#include "enums.hpp" +#include "heap_alloc.hpp" +#include "stack_alloc.hpp" + +/* + INCLUDES ALL FILES IN THE CYFRE LIBRARY +*/ + +/* compiler -D flags + +CHECK_RANGE_DISABLE - Disable internal range checking, slightly speeds up the program (do not use in development) +CHECK_SHAPE_DISABLE - Disable internal shape checking of matricies in matrix operations, slightly speeds up the + +*/ + +namespace cyfre { + + template , traversal ORDER = traversal::row_t> + class mat : public alloc_t { + private: + public: + + mat() : alloc_t() { + } + + mat(size_t rows, size_t cols) : alloc_t(rows, cols) { + } + + static mat nullzero(); + + static mat identity(); + + static mat scalar(); + }; + +} // namespace cyfre + +#include "../../src/cyfre/heap_alloc.cpp" +#include "../../src/cyfre/stack_alloc.cpp" + +#endif \ No newline at end of file diff --git a/include/cyfre/enums.hpp b/include/cyfre/enums.hpp new file mode 100644 index 0000000..7fc0062 --- /dev/null +++ b/include/cyfre/enums.hpp @@ -0,0 +1,12 @@ +#ifndef MRDCVLSC_ENUMS_HPP +#define MRDCVLSC_ENUMS_HPP + +namespace cyfre { + enum class traversal + { + row_t, + col_t + }; +} // namespace cyfre + +#endif \ No newline at end of file diff --git a/include/cyfre/heap_alloc.hpp b/include/cyfre/heap_alloc.hpp new file mode 100644 index 0000000..e35b6c2 --- /dev/null +++ b/include/cyfre/heap_alloc.hpp @@ -0,0 +1,33 @@ +#ifndef MRDCVLSC_HEAP_ALLOC_HPP +#define MRDCVLSC_HEAP_ALLOC_HPP + +#include + +namespace cyfre { + + template + struct dynamic { + T *matrix; + size_t rows; + size_t cols; + + dynamic(size_t rows, size_t cols); + + ~dynamic(); + + /// @brief Copy Constructor. + dynamic(const dynamic &that); + + /// @brief Move Constructor. + dynamic(dynamic &&that); + + /// @brief Copy Assignment. + dynamic &operator=(const dynamic &that); + + /// @brief Move Assignment. + dynamic &operator=(dynamic &&that); + }; + +} // namespace cyfre + +#endif \ No newline at end of file diff --git a/include/cyfre/stack_alloc.hpp b/include/cyfre/stack_alloc.hpp new file mode 100644 index 0000000..89d11b7 --- /dev/null +++ b/include/cyfre/stack_alloc.hpp @@ -0,0 +1,33 @@ +#ifndef MRDCVLSC_STACK_ALLOC_HPP +#define MRDCVLSC_STACK_ALLOC_HPP + +#include + +namespace cyfre { + + template + class fixed { + private: + + T matrix[COLS * ROWS]; + + public: + + fixed(); + + /// @brief Copy Constructor. + fixed(const fixed &that); + + /// @brief Move Constructor. + fixed(fixed &&that); + + /// @brief Copy Assignment. + fixed &operator=(const fixed &that); + + /// @brief Move Assignment. + fixed &operator=(fixed &&that); + }; + +} // namespace cyfre + +#endif \ No newline at end of file diff --git a/makefile b/makefile index ed09ce5..05aec2a 100644 --- a/makefile +++ b/makefile @@ -1,15 +1,18 @@ -CC:=g++ -SRC := cyfre/test -CXXFLAGS := -std=c++17 -Wall -Wextra -Og -g +CXX:=clang++ +CXXFLAGS:=-std=c++17 -Wall -Wextra + +HEADERS:=$(wildcard include/cyfre/*) +SRC:=$(wildcard src/cyfre/*) ifeq ($(OS), Linux) -CPPFLAGS += -fsanitize=address +CXXFLAGS+=-fsanitize=address endif -test: - $(CC) $(CXXFLAGS) $(SRC)/test.cpp -o $(SRC)/test.out - $(SRC)/test.out - $(MAKE) clean +test: test/test.out + @./test/test.out + +test/test.out: test/tests.cpp $(HEADERS) $(SRC) + $(CXX) $(CXXFLAGS) test/tests.cpp -o test/test.out -fsanitize=address clean: @echo "main makefile - clean" @@ -32,4 +35,7 @@ style: cyfre/shaping/*.*pp \ cyfre/statistics/*.*pp \ cyfre/transform/*.*pp \ - cyfre/test/*.*pp \ No newline at end of file + cyfre/test/*.*pp \ + include/cyfre/*.hpp \ + src/cyfre/*.cpp \ + test/*.cpp \ No newline at end of file diff --git a/src/cyfre/cyfre.cpp b/src/cyfre/cyfre.cpp new file mode 100644 index 0000000..ea0fdd9 --- /dev/null +++ b/src/cyfre/cyfre.cpp @@ -0,0 +1,6 @@ +#ifndef MRDCVLSC_CYFRE_CPP +#define MRDCVLSC_CYFRE_CPP + +#include "../../include/cyfre/cyfre.hpp" + +#endif \ No newline at end of file diff --git a/src/cyfre/heap_alloc.cpp b/src/cyfre/heap_alloc.cpp new file mode 100644 index 0000000..7f78356 --- /dev/null +++ b/src/cyfre/heap_alloc.cpp @@ -0,0 +1,78 @@ +#ifndef MRDCVLSC_HEAP_ALLOCATION_CPP +#define MRDCVLSC_HEAP_ALLOCATION_CPP + +#include +#include +#include + +#include "../../include/cyfre/heap_alloc.hpp" + +namespace cyfre { + + // =================== BASIC CONSTRUCTORS =================== + + template + dynamic::dynamic(size_t rows, size_t cols) : matrix(new T[rows * cols]), rows(rows), cols(cols) { + } + + // =================== DESTRUCTOR =================== + + template + dynamic::~dynamic() { + delete[] matrix; + } + + // =================== SPECIAL CONSTRUCTORS =================== + + /// @brief Copy Constructor. + template + dynamic::dynamic(dynamic const &that) + : matrix(new T[that.rows * that.cols]), rows(that.rows), cols(that.cols) { + memcpy(matrix, that.matrix, that.rows * that.cols); + } + + /// @brief Move Constructor. + template + dynamic::dynamic(dynamic &&that) : matrix(that.matrix), rows(that.rows), cols(that.cols) { + that.matrix = NULL; + } + + /// @brief Copy Assignment + template + dynamic &dynamic::operator=(dynamic const &that) { + if (this != &that) { + rows = that.rows; + cols = that.cols; + + if (matrix) { + delete[] matrix; + } + + size_t n = that.rows * that.cols; + matrix = new T[n]; + memcpy(matrix, that.matrix, sizeof(T) * n); + } + return *this; + } + + /// @brief Move Assignment + template + dynamic &dynamic::operator=(dynamic &&that) { + if (this != &that) { + if (matrix) { + delete[] matrix; + } + + rows = that.rows; + cols = that.cols; + matrix = that.matrix; + + that.rows = 0; + that.cols = 0; + that.matrix = NULL; + } + return *this; + } +} // namespace cyfre + +#endif \ No newline at end of file diff --git a/src/cyfre/stack_alloc.cpp b/src/cyfre/stack_alloc.cpp new file mode 100644 index 0000000..a40c712 --- /dev/null +++ b/src/cyfre/stack_alloc.cpp @@ -0,0 +1,46 @@ +#ifndef MRDCVLSC_STACK_ALLOCATION_CPP +#define MRDCVLSC_STACK_ALLOCATION_CPP + +#include +#include +#include + +#include "../../include/cyfre/stack_alloc.hpp" + +namespace cyfre { + template + fixed::fixed() : matrix() { + } + + /// @brief Copy Constructor. + template + fixed::fixed(fixed const &that) : matrix(new T[that.rows * that.cols]) { + memcpy(matrix, that.matrix, that.rows * that.cols); + } + + /// @brief Move Constructor. + template + fixed::fixed(fixed &&that) : matrix(that.matrix) { + memcpy(matrix, that.matrix, that.rows * that.cols); + } + + /// @brief Copy Assignment + template + fixed &fixed::operator=(fixed const &that) { + if (this != &that) { + memcpy(matrix, that.matrix, that.rows * that.cols); + } + return *this; + } + + /// @brief Move Assignment + template + fixed &fixed::operator=(fixed &&that) { + if (this != &that) { + memcpy(matrix, that.matrix, that.rows * that.cols); + } + return *this; + } +} // namespace cyfre + +#endif \ No newline at end of file diff --git a/test/tests.cpp b/test/tests.cpp new file mode 100644 index 0000000..abd9a74 --- /dev/null +++ b/test/tests.cpp @@ -0,0 +1,421 @@ +#include "../include/cyfre/cyfre.hpp" +#include +#include + +int main() { + using cyfre::mat; + using cyfre::dynamic; + using cyfre::fixed; + + dynamic a(4, 7); + assert(a.rows == 4); + assert(a.cols == 7); + static_assert(sizeof(a) == sizeof(size_t) * 3, "wrong dynamic container stack size"); + + dynamic b = a; + assert(b.rows == 4); + assert(b.cols == 7); + static_assert(sizeof(b) == sizeof(size_t) * 3, "wrong dynamic container stack size"); + + mat> c(2, 12); + assert(c.rows == 2); + assert(c.cols == 12); + static_assert(sizeof(c) == sizeof(size_t) * 3, "wrong dynamic container stack size"); + + mat> d; + static_assert(sizeof(d) == 25, "wrong stack size in initialization"); + + fixed e; + static_assert(sizeof(e) == 100, "wrong stack size in initialization"); + + // matrix test + + { mat> subject1; } + + std::cout << "Tests : PASSED\n"; + + return 0; +} + +#include + +#ifdef ENABLE_OLD_TEST + +int main() { + // ############### test 01 ############### + { + mat mat_object(cyfre::TYPE::IDENTITY, 3); + mat idet({{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}); + if (mat_object != idet) + throw std::logic_error("error at test 01"); + std::cout << "test 1 correct\n"; + } + + // ############### test 02 ############### + { + mat mat_object(cyfre::TYPE::SCALARMATRIX, 3, 7); + mat scalars({{7, 0, 0}, {0, 7, 0}, {0, 0, 7}}); + if (mat_object != scalars) + throw std::logic_error("error at test 02"); + std::cout << "test 2 correct\n"; + } + + // ############### test 03 ############### + { + mat subject(cyfre::TYPE::NULLZERO, 3); + mat correct({{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}); + if (subject != correct) + throw std::logic_error("error at test 03"); + std::cout << "test 3 correct\n"; + } + + // ############### test 04 ############### + { + mat subject(3, 2, 5); + mat correct({{5, 5}, {5, 5}, {5, 5}}); + if (subject != correct) + throw std::logic_error("error at test 04"); + std::cout << "test 4 correct\n"; + } + + // ############### test 05 ############### + { + mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + subject.row_swap(1, 2); + mat correct({{1, 2, 3}, {7, 8, 9}, {4, 5, 6}}); + if (subject != correct) + throw std::logic_error("error at test 05"); + std::cout << "test 5 correct\n"; + } + + // ############### test 06 ############### + { + mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + subject.row_scale(5, 0); + mat correct({{5, 10, 15}, {4, 5, 6}, {7, 8, 9}}); + if (subject != correct) + throw std::logic_error("error at test 06"); + std::cout << "test 6 correct\n"; + } + + // ############### test 07 ############### + { + mat subject({{1, 2, 3}, {4, 5, 6}, {0, 0, 0}}); + subject.row_scale(7, 0, 2); + mat correct({{1, 2, 3}, {4, 5, 6}, {7, 14, 21}}); + if (subject != correct) + throw std::logic_error("error at test 07"); + std::cout << "test 7 correct\n"; + } + + // ############### test 08 ############### + { + mat subject({{1, 2}, {3, 4}}); + subject.scale_row(0, cyfre::SCALAR::MUL, 2); + mat correct({{2, 4}, {3, 4}}); + if (subject != correct) + throw std::logic_error("error at test 08"); + std::cout << "test 8 correct\n"; + } + + // ############### test 09 ############### + { + mat subject({{2, 4}, {6, 8}}); + subject.scale_column(1, cyfre::SCALAR::DIV, 2); + mat correct({{2, 2}, {6, 4}}); + if (subject != correct) + throw std::logic_error("error at test 09"); + std::cout << "test 9 correct\n"; + } + + // ############### test 10 ############### + { + mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + subject.row_operation(1, cyfre::SCALAR::MUL, 2); + mat correct({{1, 2, 3}, {28, 40, 54}, {7, 8, 9}}); + if (subject != correct) + throw std::logic_error("error at test 10"); + std::cout << "test 10 correct\n"; + } + + // ############### test 11 ############### + { + mat subject({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + subject.column_operation(1, cyfre::SCALAR::DIV, 2); + mat correct({{1, 0, 3}, {4, 0, 6}, {7, 0, 9}}); + if (subject != correct) + throw std::logic_error("error at test 11"); + std::cout << "test 11 correct\n"; + } + + // ############### test 12 ############### + { + mat subject({{1, 2}, {3, 4}}); + subject = subject + 2; + mat correct({{3, 4}, {5, 6}}); + if (subject != correct) + throw std::logic_error("error at test 12"); + std::cout << "test 12 correct\n"; + } + + // ############### test 13 ############### + { + mat subject({{1, 2}, {3, 4}}); + subject += 2; + mat correct({{3, 4}, {5, 6}}); + if (subject != correct) + throw std::logic_error("error at test 13"); + std::cout << "test 13 correct\n"; + } + + // ############### test 14 ############### + { + mat A({{1, 2, 3}, {4, 5, 6}}); + + mat B({{-1, -2, -3}, {-4, -5, -6}}); + mat C = A + B; + mat correct(2, 3, 0); + if (C != correct) + throw std::logic_error("error at test 14"); + std::cout << "test 14 correct\n"; + } + + // ############### test 15 ############### + { + mat A({{10, 1, 33}, {44, 50, 12}}); + mat B({{7, 19, 5}, {7, 6, 5}}); + mat C = A - B; + ; + mat correct({{3, -18, 28}, {37, 44, 7}}); + if (C != correct) + throw std::logic_error("error at test 15"); + std::cout << "test 15 correct\n"; + } + + // ############### test 16 ############### + { + mat A({{2, 4, 6}, {8, 2, 4}}); + mat B({{1, 4, 3}, {2, 2, 1}}); + mat C = cyfre::hadamard(A, B); + mat correct({{2, 16, 18}, {16, 4, 4}}); + if (C != correct) + throw std::logic_error("error at test 16"); + std::cout << "test 16 correct\n"; + } + + // ############### test 17 ############### + { + mat X({{7, 12, 13}, {14, 5, 20}, {66, 42, -4}}); + mat W{-3, 4, 56}; + + mat C = W * X; + mat correct{3731, 2336, -183}; + + if (C != correct) + throw std::logic_error("error at test 17"); + std::cout << "test 17 correct\n"; + } + + // ############### test 18 ############### + { + auto square = [](int x) { return x * x; }; + mat X( + {{23, 12, 53, 34, 23}, {33, 77, 53, 90, 28}, {87, 26, 11, 24, 31}, {84, 32, 73, 64, 26}, {77, 88, 45, 97, 86}} + ); + X.apply(square); + mat correct( + {{529, 144, 2809, 1156, 529}, + {1089, 5929, 2809, 8100, 784}, + {7569, 676, 121, 576, 961}, + {7056, 1024, 5329, 4096, 676}, + {5929, 7744, 2025, 9409, 7396}} + ); + if (X != correct) + throw std::logic_error("error at test 18"); + std::cout << "test 18 correct\n"; + } + + // ############### test 19 ############### + { + mat X({ + {1, 2, 3, 4}, + {5, 6, 7, 8}, + }); + X.transpose(); + mat correct({{1, 5}, {2, 6}, {3, 7}, {4, 8}}); + if (X != correct) + throw std::logic_error("error at test 19"); + std::cout << "test 19 correct\n"; + } + + // ############### test 20 ############### + { + mat X({{7, 12, 13}, {14, 5, 20}, {66, 42, -4}}); + mat X_cubed = cyfre::power(X, 3); + mat X_squared = X; + X_squared.power(2); + + mat C1({{35599, 28068, 26659}, {38210, 31505, 39196}, {130302, 85590, 20042}}); + mat C2({{1075, 690, 279}, {1488, 1033, 202}, {786, 834, 1714}}); + if (X_cubed != C1) + throw std::logic_error("wrong answer on test 20 cube"); + if (X_squared != C2) + throw std::logic_error("wrong answer on test 20 square"); + std::cout << "CORRECT ANSWERS IN TEST 20\n"; + } + + // ############### test 21 ############### + { + mat X({{23, 12, 53}, {33, 77, 53}, {87, 26, 11}}); + X.inv(); + mat correct( + {{0.00196078L, -0.00460101L, 0.0127211L}, + {-0.0156863L, 0.0160925L, -0.00195709L}, + {0.0215686L, -0.00164691L, -0.00507736L}} + ); + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + if ((std::to_string(X(i, j))) != (std::to_string(correct(i, j)))) { + throw std::logic_error("wrong answer inverse 21\n"); + } + } + } + std::cout << "test 21 correct\n"; + } + + // ############### test 22 ############### + { + mat X({{1, 2, 3, 4}, {5, 6, 7, 8}, {-2, 3, -4, 1}}); + X = cyfre::rref(X); + mat correct({{1, 0, 0, -1}, {0, 1, 0, 1}, {0, 0, 1, 1}}); + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + if ((std::to_string(X(i, j))) != (std::to_string(correct(i, j)))) { + throw std::logic_error("wrong answer rref 22\n"); + } + } + } + std::cout << "test 22 correct\n"; + } + + // ############### test 23 ############### + { + mat X({{5, 10, -15, 20}, {30, -35, -40, -45}, {55, 60, 75, -80}, {90, 95, 100, -105}}); + long double determinant = cyfre::det(X); + if (std::to_string((int) (float) determinant) != "-720000") + throw std::logic_error("wrong determinant (23)"); + std::cout << "correct determinant (23)\n"; + } + + // ############### test 24 ############### + { + mat X({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + int diag_sum = X.trace(); + if (diag_sum != 15) + throw std::logic_error("wrong trace (24)"); + std::cout << "correct trace (24)\n"; + } + + // ############### test 25 ############### + { + mat X({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}); + int diag_sum = X.sum(); + if (diag_sum != 45) + throw std::logic_error("wrong sum (25)"); + std::cout << "correct sum (25)\n"; + } + + // ############### test 26 ############### + { + mat X({{7, 2, 4}, {4, 7, 6}, {7, 4, 9}}); + + long double mean = cyfre::sts::mean(X); + long double median = cyfre::sts::median(X); + + std::pair> getmode = cyfre::sts::mode(X); + + size_t numbers_of_modes = getmode.second.size(); + size_t modes_occurrence = getmode.first; + + std::vector modes = getmode.second; + + if (std::to_string(mean) != "5.555556") + throw std::logic_error("wrong mean (26:1)"); + if (std::to_string((int) (float) median) != "7") + throw std::logic_error("wrong median (26:2)"); + if (numbers_of_modes != 2) + throw std::logic_error("wrong numbers_of_modes (26:3)"); + if (modes_occurrence != 3) + throw std::logic_error("wrong modes_occurrence (26:4)"); + if (modes[0] != 4) + throw std::logic_error("wrong modes[0] (26:5)"); + if (modes[1] != 7) + throw std::logic_error("wrong modes[1] (26:6)"); + + std::cout << "mean, median modem correct outputs : 1 (26)\n"; + + /* + mean = 5.55556 + median = 7 + numbers_of_modes = 2 + modes_occurrence = 3 + modes = [7,4] + */ + mat SSS({7, 2, 4, 3, 9}); + + long double sum_of_square = cyfre::sts::sofs(SSS), variance = cyfre::sts::variance(SSS, cyfre::sts::SAMPLE), + standard_deviation = cyfre::sts::stddvn(SSS, cyfre::sts::SAMPLE); + + // sum_of_square = 34 + // variance = 8.5 + // standard_deviation = 2.91548 + + if (std::to_string((int) (float) sum_of_square) != "34") + throw std::logic_error("wrong sum_of_square (26:7)"); + if (std::to_string((float) variance) != "8.500000") + throw std::logic_error("wrong variance (26:8)"); + if (std::to_string((float) standard_deviation) != "2.915476") + throw std::logic_error("wrong standard_deviation (26:9)"); + std::cout << "correct outputs : 2 (26)\n"; + } + + // ############### test 27 ############### + { + mat subject1({{5, 10, 15, 20}, {30, 60, 2, -2}, {7, 6, 5, -232}}); + mat target1( + {{0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 5, 10, 15, 20, 0}, + {0, 30, 60, 2, -2, 0}, + {0, 7, 6, 5, -232, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0}} + ); + subject1.padding(2, 1); + if (subject1 != target1) { + throw std::logic_error("test 27 error in padding output"); + } else { + std::cout << "correct (27)\n"; + } + } + + // ############### test 28 ############### + { + mat A{{1, 2, 3}, {4, 5, 6}, {6, 5, 4}}; + mat B{{1, 2, 3}, {4, 5, 6}, {6, 5, 4}}; + mat C = A; + mat D; + D = B; + mat E = B * A; + mat F = B * A * E; + mat G; + G = F * E; + mat H; + H = F * G * B; + mat Z(A * F); + } + + return 0; +} + +#endif \ No newline at end of file From 6b74f894e3d6eaaa6dea80c8ce5fa6d5e1e2fedb Mon Sep 17 00:00:00 2001 From: mrdcvlsc Date: Sun, 23 Jul 2023 20:34:53 +0800 Subject: [PATCH 2/2] add type operator existence checks using SFINAE --- .vscode/settings.json | 5 +- README.md | 1112 +---------------------------- TODO.md | 8 - docs/initialization.md | 51 ++ include/cyfre/check_operators.hpp | 180 +++++ include/cyfre/stack_alloc.hpp | 12 - src/cyfre/heap_alloc.cpp | 5 +- src/cyfre/stack_alloc.cpp | 33 +- test/tests.cpp | 8 +- 9 files changed, 256 insertions(+), 1158 deletions(-) delete mode 100644 TODO.md create mode 100644 docs/initialization.md create mode 100644 include/cyfre/check_operators.hpp diff --git a/.vscode/settings.json b/.vscode/settings.json index 32a9d2c..8e68e5a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -50,6 +50,9 @@ "iterator": "cpp", "memory": "cpp", "memory_resource": "cpp", - "random": "cpp" + "random": "cpp", + "scoped_allocator": "cpp", + "iomanip": "cpp", + "sstream": "cpp" } } \ No newline at end of file diff --git a/README.md b/README.md index e60f14a..dc10d30 100644 --- a/README.md +++ b/README.md @@ -1,1113 +1,21 @@ # cyfre -### a Templated C++ matrix library - ------------------------------ - ![ubuntu](https://github.com/mrdcvlsc/cyfre/actions/workflows/ubuntu_test.yml/badge.svg) ![windows](https://github.com/mrdcvlsc/cyfre/actions/workflows/windows_test.yml/badge.svg) -### cyfre aims to provide an easy to use c++ matrix library with basic matrix operations. - - -_started : Dec 2020_ - - -- ### **To use, include the main header in your code** - - ```#include "cyfre/cyfre.hpp"``` - -- ### **compilation ```-D``` flags** - - ```CHECK_RANGE_DISABLE``` - Disable internal range checking, slightly speeds up the program (do not use in development) - - ```CHECK_SHAPE_DISABLE``` - Disable internal shape checking of matrices in matrix operations, slightly speeds up the program (do not use in development) - -- ### **for full performance you can disable checks :** - - ```-DCHECK_RANGE_DISABLE -DCHECK_SHAPE_DISABLE``` - -- ### **Don't forget the optimization flags for more speed-up :** - - ```-O3 -march=native``` - ----------------------------------------------- - -## Documentation - -
-CREATING MATRIX (CONSTRUCTORS) -
-
    - - -
    -identity matrix -
    -
      - - **construct an identity matrix** - - ```c++ - cyfre::mat mat_object(cyfre::TYPE::IDENTITY,3); /* - - mat_object = [[1,0,0], - [0,1,0], - [0,0,1]] - - */ - ``` - -
    -
    - - -
    -scalar matrix -
    -
      - - **construct a scalar matrix** - - ```c++ - cyfre::mat mat_object(cyfre::TYPE::SCALARMATRIX,3,7); /* - - mat_object = [[7,0,0], - [0,7,0], - [0,0,7]] - - */ - ``` - -
    -
    - - -
    -zero/null matrix -
    -
      - - **construct a zero/null matrix** - - ```c++ - cyfre::mat mat_object(cyfre::TYPE::NULLZERO,3); /* - - mat_object = [[0,0,0], - [0,0,0], - [0,0,0]] - - */ - ``` - -
    -
    - - -
    -shaped matrix with initial value -
    -
      - - **construct a custom shaped matrix, with initial values** - - ```c++ - cyfre::mat mat_object(3,2,5); /* - - mat_object = [[5,5], - [5,5], - [5,5]] - - */ - ``` - -
    -
    - - -
    -shaped matrix with random values -
    -
      - - **ex. constructs a 4x5 matrix with random integer values ranging from 10-99** - - ```c++ - cyfre::mat INT_MATRIX(4,5,cyfre::RANDOM::INTEGER,10,99); - ``` - - **ex. constructs a 3x3 matrix with random real values ranging from 0.0-1.0** - - ```c++ - cyfre::mat FLOAT_MATRIX(4,5,cyfre::RANDOM::REAL,0,1); - ``` - -
    -
    - - -
    -defined matrix (row) -
    -
      - - **construct and define a matrix** - - ```c++ - cyfre::mat mat_object {5,10,15,20,25}; - - // mat_object = [[5,10,15,20,25]] <-- (1x5 matrix) - ``` - -
    -
    - - -
    -defined matrix (2D) -
    -
      - - **construct and define a matrix** - - ```c++ - cyfre::mat mat_object { - {1,2,3}, - {4,5,6}, - {7,8,9} - }; - - /* - mat_object = [[1,2,3], - [4,5,6], - [7,8,9]] - */ - ``` - -
    -
    - - -
    -read matrix from a txt file -
    -
      - - *matrix1.txt* - - ```txt - 23 12 53 34 23 - 33 77 53 90 28 - 87 26 11 24 31 - 84 32 73 64 26 - 77 88 45 97 86 - ``` - - ```c++ - cyfre::mat mat_object("matrix1.txt",' '); /* - - mat_object = [ - [23,12,53,34,23] - [33,77,53,90,28] - [87,26,11,24,31] - [84,32,73,64,26] - [77,88,45,97,86] - ] - - */ - ``` - -
    -
    - -
-
- - -
-ELEMENTARY ROW/COLUMN OPERATIONS -
-
    - -- **basic elementary row/column operations** -
      - -
      -swaping rows/columns -
      -
        - -**row_swap(row1,row2)** - -```c++ -cyfre::mat mat_object({ - {1,2,3}, - {4,5,6}, - {7,8,9} -}); - -mat_object.row_swap(1,2); /* - -mat_object = [[ 1, 2, 3], - [ 7, 8, 9], - [ 4, 5, 6]] - -*/ -``` -
      -
      - - -
      -scaling rows/columns -
      -
        - -**row_scale(scalar_value,row_to_scale)** - -```c++ -cyfre::mat mat_object({ - {1,2,3}, - {4,5,6}, - {7,8,9} -}); - -mat_object.row_scale(5,0); /* - -mat_object = [[ 5,10,15], - [ 4, 5, 6], - [ 7, 8, 9]] - -*/ -``` -
      -
      - - -
      -scale a row/column then add the products to another row/column -
      -
        - -**row_scale(scalar_value,row_to_scale,base_row)** - -```c++ -cyfre::mat mat_object({ - {1,2,3}, - {4,5,6}, - {0,0,0} -}); - -mat_object.row_scale(7,0,2); /* - -mat_object = [[ 1, 2, 3], - [ 4, 5, 6], - [ 7,14,21]] - -*/ -``` -
      -
      -
    - -
    - -- **costum row/column operations** - -
      - -_: NOTE - anything these methods can do, the 3 elementary basic row/column operations can also do, just keep this in mind... the following methods are just more straight forward_ - -
    - -
      - -
      -row scalar operation -
      -
        - -**scales all the elements of the row using a scalar value [changes the matrix itself]** - -```c++ -cyfre::mat mat_object({ - {1,2}, - {3,4} -}); - -mat_object.scale_row(0,cyfre::SCALAR::MUL,2); /* - -mat_object = [[2,4], - [3,4]] - -*/ -``` - -multiply all elements of the row '0' to 3, changes the original matrix - -
      -
      - - -
      -column scalar operation -
      -
        - -**scales all the elements of the column using a scalar value [changes the matrix itself]** - -```c++ -cyfre::mat mat_object({ - {2,4}, - {6,8} -}); - -mat_object.scale_column(1,cyfre::SCALAR::DIV,2); /* - -mat_object = [[2,2], - [6,4]] - -*/ -``` - -divides all elements of the column '1' to 2, changes the original matrix - -
      -
      - - -
      -row to row operation -
      -
        - -**scale a row using another row [changes the matrix itself]** - -```c++ -cyfre::mat mat_object({ - {1,2,3}, - {4,5,6}, - {7,8,9} -}); - -mat_object.row_operation(1,cyfre::SCALAR::MUL,2); /* - -mat_object = [[ 1, 2, 3], - [28,40,54], - [ 7, 8, 9]] - -*/ -``` -__int mat_object(0,1) we multiply the value of mat_object(0,2) which is 7, into the previous value of mat_object(0,1) which is 4, the answer is 4*7 = 28, hence the 28 in mat_object(0,1)__ - -
      -
      - - -
      -column to column operation -
      -
        - -**scale a column using another column [changes the matrix itself]** - -```c++ -cyfre::mat mat_object({ - {1,2,3}, - {4,5,6}, - {7,8,9} -}); - -mat_object.column_operation(1,cyfre::SCALAR::DIV,2); /* - -mat_object = [[1, 0, 3], - [4, 0, 6], - [7, 0, 9]] - -*/ -``` -
      -
      - -
    - - -
-
- - -
-SCALAR OPERATIONS -
-
    - - - -
    -matrix scalar operation -
    -
      - -**returns a copy scaled matrix of the original one** - -```c++ -cyfre::mat mat_object({ - {1,2}, - {3,4} -}); - -cyfre::mat a = mat_object+2; /* - -a = [[3,4], - [5,6]] - -NOTE : cyfre::mat a = 2+mat_object; <-- is also a valid expression - -*/ -``` - -
    -
    - - -
    -matrix scalar operation [self] -
    -
      - -**scales all the elements of the matrix using a scalar value [changes the matrix itself]** - -```c++ -cyfre::mat mat_object({ - {1,2}, - {3,4} -}); - -mat_object-=2; /* - -mat_object = [[-1,0], - [ 1,2]] - -*/ -``` - -
    -
    - -
-
- - -
-MATRIX OPERATIONS -
-
    - - -
    -matrix addition -
    -
      - -```c++ -cyfre::mat A({{ 1, 2, 3}, - { 4, 5, 6}}); - -cyfre::mat B({{-1,-2,-3}, - {-4,-5,-6}}); - -cyfre::mat C = A+B; /* - -C = [[ 0, 0, 0], - [ 0, 0, 0]] - -*/ -``` -
    -
    - - -
    -matrix subtraction -
    -
      - -```c++ -cyfre::mat A({{10, 1,33}, - {44,50,12}}); - -cyfre::mat B({{ 7,19, 5}, - { 7, 6, 5}}); - -cyfre::mat C = A-B; /* - -C = [[ 3,-18,28], - [37, 44, 7]] - -*/ -``` -
    -
    - - -
    -matrix element-by-element division -
    -
      - -```c++ -cyfre::mat A({{2,4,6}, - {8,2,4}}); - -cyfre::mat B({{1,4,3}, - {2,2,1}}); - -cyfre::mat C = A/B; /* - -C = [[2,1,2], - [4,1,4]] - -*/ -``` -
    -
    - - -
    -hadamard product -
    -
      - -```c++ -cyfre::mat A({{2,4,6}, - {8,2,4}}); - -cyfre::mat B({{1,4,3}, - {2,2,1}}); - -cyfre::mat C = cyfre::hadamard(A,B); /* - -C = [[ 2,16,18], - [16, 4, 4]] - -*/ - -A.hadamard(B); /* faster in some cases because of direct operation on the A matrix - -A = [[ 2,16,18], - [16, 4, 4]] - -*/ -``` -
    -
    - - -
    -multiplying matrices (dot product) -
    -
      - -```c++ -cyfre::mat X({ - { 7,12,13}, - {14, 5,20}, - {66,42,-4} -}); - -cyfre::mat W({{-3,4,56}}); - -cyfre::mat Y = X*W; - -// C = [[3731,2336,-183]] -``` -
    -
    - -
-
- - - -
-SCALAR METHODS -
-
    - -_methods that returns a single/scalar value_ - - -
    -min & max -
    -
      - -```c++ -cyfre::mat X({ - { 1, 2, 3}, - { 4, 5,-6}, - {17, 8, 9} -}); - -int min = X.min(); // -6 -int max = X.max(); // 17 -``` -
    -
    - - -
    -sum of all elements -
    -
      - -```c++ -cyfre::mat X({ - {1,2,3}, - {4,5,6}, - {7,8,9} -}); - -int sum = X.total(); - -// sum = 45 - -``` -
    -
    - - -
    -sum of the main-diagonal -
    -
      - -```c++ -cyfre::mat X({ - {1,2,3}, - {4,5,6}, - {7,8,9} -}); - -int diag_sum = X.trace(); - -// diag_sum = 15 - -``` -
    -
    - - -
    -Determinant of a Matrix -
    -
      - -```c++ -cyfre::mat X({ - { 5, 10,-15, 20}, - {30,-35,-40, -45}, - {55, 60, 75, -80}, - {90, 95,100,-105} -}); - -long double determinant = cyfre::det(X); /* - -determiant = -720000 - -*/ - -``` -
    -
    - -
-
- - -
-TRANSFOM METHODS -
-
    - -_methods that transforms/changes the values, shape orientation of a matrix_ - - -
    -Applying functions to all elements of the matrix -
    -
      - -**.apply() is a shortcut method for applying a function to all elements of a matrix** - -```c++ - -int square(int x) { return x*x; } - -cyfre::mat X({ - {23,12,53,34,23}, - {33,77,53,90,28}, - {87,26,11,24,31}, - {84,32,73,64,26}, - {77,88,45,97,86} -}); - -X.apply(square); /* - -X = [[529 144 2809 1156 529], - [1089 5929 2809 8100 784], - [7569 676 121 576 961], - [7056 1024 5329 4096 676], - [5929 7744 2025 9409 7396]] - -*/ -``` -**NOTE:** - - the function should only have one parameter - - the function's return type, and parameter type should be the same as the matrix type - -
    -
    - - - - -
    -Transpose of a Matrix -
    -
      - -```c++ -cyfre::mat X({ - {1,2,3,4}, - {5,6,7,8}, -}); - -X.transpose(); - -/* - -X = [[1,5], - [2,6], - [3,7], - [4,8]] - -*/ - -``` -
    -
    - - -
    -rasing a matrix to a certain power -
    -
      - -```c++ -cyfre::mat X({ - { 7,12,13}, - {14, 5,20}, - {66,42,-4} -}); - - -cyfre::mat X_cubed = cyfre::power(X,3); /* - -X_cubed = [[35599 28068 26659], - [38210 31505 39196], - [130302 85590 20042]] - -*/ - -cyfre::mat X_squared = X; -X_squared.power(2); /* - -X_squared = [[1075 690 279], - [1488 1033 202], - [786 834 1714]] - -*/ - -``` -
    -
    - - -
    -Inverse of a Matrix -
    -
      - -```c++ -cyfre::mat X({ - {23,12,53}, - {33,77,53}, - {87,26,11} -}); - -X.inv(); /* or X = cyfre::inv(X); - -X = [[0.00196078 -0.00460101 0.0127211], - [-0.0156863 0.0160925 -0.00195709], - [0.0215686 -0.00164691 -0.00507736]] - -*/ - -``` -
    -
    - - -
    -Echelon Forms (ref & rref) -
    -
      - -**R***educe* **R***ow* **E***chelon* **F***orm* - -```c++ -cyfre::mat X({ - {1,2,3,4}, - {5,6,7,8}, - {-2,3,-4,1} -}); - -X = cyfre::rref(X); - -/* or - -X.rref(); - -X = [[1 0 0 -1], - [0 1 0 1], - [0 0 1 1]] - -*/ -``` - -**R***ow* **E***echelon* **F***orm* : **```X.ref()```** *or* **```X = cyfre::ref(X)```** - -
    -
    - - -
    -Padding -
    -
      - -increase the size of matrix by padding zeros - -```c++ -cyfre::mat X({ - {1,2,3,4}, - {5,6,7,8}, - {-2,3,-4,1} -}); - -X = cyfre::padding(X,1); /* - -each one of the 3 methods given below has also -the same effect with the method given above - -X = cyfre::padding(X,1,1); -X.padding(1); -X.padding(1,1); - -outputs: - -X = [[0, 0, 0, 0, 0, 0], - [0, 1, 2, 3, 4, 0], - [0, 5, 6, 7, 8, 0], - [0,-2, 3,-4, 1, 0], - [0, 0, 0, 0, 0, 0]] -*/ -``` - -
    -
    - -
-
- - -
-CYFRE::MAT MEMBERS -
-
    - -``` -.height -.width -matrix -``` - -_you can access the matrix values using the operator ()_ - -**operator(i,j)** - performs check of indices, terminates program if indices are out of range - -```c++ - cyfre::mat nums( - {{1,2,3}, - {4,5,6}, - {7,8,9} - }); - - for(size_t i=0; i -
- - -
-STATISTICS -
-
    - - -
    -mean, median, mode -
    -
      - -```c++ -cyfre::mat X({ - {7,2,4}, - {4,7,6}, - {7,4,9} -}); - -long double mean = cyfre::sts::mean(X); -long double median = cyfre::sts::median(X); - -std::pair> getmode = cyfre::sts::mode(X); - -size_t numbers_of_modes = getmode.second.size(); -size_t modes_occurrence = getmode.first; - -std::vector modes = getmode.second; - -/* - mean = 5.55556 - median = 7 - numbers_of_modes = 2 - modes_occurrence = 3 - modes = [7,4] -*/ - -``` -
    -
    +A Templated C++ matrix library which aims to provide an easy to use interface for basic and intermediate vector-vector, vector-matrix & matrix-matrix operations. - -
    -sum of squares, variance, standard deviation -
    -
      +> **Note** -```c++ -cyfre::mat X({7,2,4,3,9}); +> This library is on an ongoing re-write to improve the api and use more modern C++ features. To see the old working implementation of this library check the [version_1.9](https://github.com/mrdcvlsc/cyfre/tree/version_1.9) branch or [download it here](https://github.com/mrdcvlsc/cyfre/tree/version_1.9). -long double -sum_of_square = cyfre::sts::sofs(X), -variance = cyfre::sts::variance(X,cyfre::sts::SAMPLE), -standard_deviation = cyfre::sts::stddvn(X,cyfre::sts::SAMPLE);; +### **Docs** -/* - sum_of_square = 34 - variance = 8.5 - standard_deviation = 2.91548 +1. [Initialization](docs/initialization.md) +2. [vector-vector (not available yet)](docs/initialization.md) +3. [vector-matrix (not available yet)](docs/initialization.md) +4. [matrix-matrix (not available yet)](docs/initialization.md) - for population use 'cyfre::POPULATION' instead -*/ -``` -
    -
    +### **About** -
-
+This repository started in december 2020 as a personal hobby project **not intended** to replace big matrix libraries like [Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page), [OpenCV's - cv::Mat](https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html) or [BLAS](https://www.netlib.org/blas/) and is **only for didactic purposes**. Though performance is still a priority, meaning this library will... as much as possible, use the fastest and the most efficient algorithms and implementations THAT THE AUTHOR(s) KNOW OF. \ No newline at end of file diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 945a478..0000000 --- a/TODO.md +++ /dev/null @@ -1,8 +0,0 @@ -# **TODO** - -- [ ] fixed size matricies (on stack), currently this library only support dynamically allocated matrices (on heap). -- [ ] function rotate left - 90 degree -- [ ] function rotate right - 90 degree -- [ ] function rotate 180 degree -- [ ] function mirror/reflect x,y,main-diagonal & left-diagonal axis -- [ ] function flaten into x axis, or y axis \ No newline at end of file diff --git a/docs/initialization.md b/docs/initialization.md new file mode 100644 index 0000000..9abe10d --- /dev/null +++ b/docs/initialization.md @@ -0,0 +1,51 @@ +# cyfre matrix initialization + +When initializing a matrix this library offers a way to either allocate on stack or to allocate in heap. + +### Stack allocation initialization + +Here's how to allocate on stack, notice that we specify the dimension of the matrix inside template argument of `fixed`. + +```c++ +cyfre::mat> matrix; +``` + +### Heap allocation initialization + +Similarly here's how to allocate on the heap, the difference here is we used the `dynamic` allocation type to specify that we want a matrix in the heap, **also notice here that the size is provided in the constructor instead of the template arguments**. + +```c++ +cyfre::mat matrix(4, 4); +``` + +### Namespace advice + +Most people would use the namespace to shorten the declarations, and others will use a type definition or macro. + +```c++ +using namespace cyfre; +``` + +I would advice to use the new using keyword instead, first of all using namespace might cause some redefinitions, also using a typedef with the class provided by the `cyfre` namespace most of the time will not work since most of them are template classes. + +```c++ +// this things will not work +typedef cyfre::mat mat; +typedef cyfre::fixed fixed; +typedef cyfre::dynamic dynamic; +``` + +So it is suggested to use the using keyword. + +```c++ +using cyfre::mat; +using cyfre::dynamic; +using cyfre::fixed; +``` + +This way you can shorten the declarations like this. + +```c++ +mat matrix1; +mat matrix2(4, 4); +`````` \ No newline at end of file diff --git a/include/cyfre/check_operators.hpp b/include/cyfre/check_operators.hpp new file mode 100644 index 0000000..32d27d4 --- /dev/null +++ b/include/cyfre/check_operators.hpp @@ -0,0 +1,180 @@ +#ifndef MRDCVLSC_CHECK_OPERATORS_HPP +#define MRDCVLSC_CHECK_OPERATORS_HPP + +#include +#include + +// Using SFINAE to check for the pressence of operators for type T : replace this with C++ concepts in the future. + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// supported operators : + - * / += -= *= /= ++ -- < > == != <= >= +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace cyfre { + namespace check_t::op { + // equal + template + struct has_eq : std::false_type {}; + + template + struct has_eq() == std::declval())>> : std::true_type {}; + + // not equal + template + struct has_neq : std::false_type {}; + + template + struct has_neq() != std::declval())>> : std::true_type {}; + + // less than + template + struct has_lt : std::false_type {}; + + template + struct has_lt() < std::declval())>> : std::true_type {}; + + // less than equal + template + struct has_lte : std::false_type {}; + + template + struct has_lte() <= std::declval())>> : std::true_type {}; + + // greater than + template + struct has_gt : std::false_type {}; + + template + struct has_gt() > std::declval())>> : std::true_type {}; + + // greater than equal + template + struct has_gte : std::false_type {}; + + template + struct has_gte() >= std::declval())>> : std::true_type {}; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // add + template + struct has_add : std::false_type {}; + + template + struct has_add() + std::declval())>> : std::true_type {}; + + // sub + template + struct has_sub : std::false_type {}; + + template + struct has_sub() - std::declval())>> : std::true_type {}; + + // mul + template + struct has_mul : std::false_type {}; + + template + struct has_mul() * std::declval())>> : std::true_type {}; + + // div + template + struct has_div : std::false_type {}; + + template + struct has_div() / std::declval())>> : std::true_type {}; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // add assign + template + struct has_add_assign : std::false_type {}; + + template + struct has_add_assign() += std::declval())>> : std::true_type {}; + + // sub assign + template + struct has_sub_assign : std::false_type {}; + + template + struct has_sub_assign() -= std::declval())>> : std::true_type {}; + + // mul assign + template + struct has_mul_assign : std::false_type {}; + + template + struct has_mul_assign() *= std::declval())>> : std::true_type {}; + + // div assign + template + struct has_div_assign : std::false_type {}; + + template + struct has_div_assign() /= std::declval())>> : std::true_type {}; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // post increment + template + struct has_pre_inc : std::false_type {}; + + template + struct has_pre_inc()++)>> : std::true_type {}; + + // pre increment + template + struct has_post_inc : std::false_type {}; + + template + struct has_post_inc())>> : std::true_type {}; + + // post decrement + template + struct has_pre_dec : std::false_type {}; + + template + struct has_pre_dec()--)>> : std::true_type {}; + + // pre decrement + template + struct has_post_dec : std::false_type {}; + + template + struct has_post_dec())>> : std::true_type {}; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // // copy assign? + // template + // struct has_assign : std::false_type {}; + + // template + // struct has_assign() = std::declval())>> : std::true_type {}; + + // // move assign? + // template + // struct has_assign_ref : std::false_type {}; + + // template + // struct has_assign_ref() = std::declval())>> : std::true_type {}; + + } // namespace check_t::op + + template + struct valid_operators { + static constexpr bool value = + check_t::op::has_add::value && check_t::op::has_add_assign::value && check_t::op::has_sub::value && + check_t::op::has_sub_assign::value && check_t::op::has_mul::value && check_t::op::has_mul_assign::value && + check_t::op::has_div::value && check_t::op::has_div_assign::value && + + check_t::op::has_eq::value && check_t::op::has_neq::value && check_t::op::has_gt::value && + check_t::op::has_gte::value && check_t::op::has_lt::value && check_t::op::has_lte::value && + + check_t::op::has_post_inc::value && check_t::op::has_pre_inc::value && check_t::op::has_post_dec::value && + check_t::op::has_pre_dec::value; + }; +} // namespace cyfre + +#endif \ No newline at end of file diff --git a/include/cyfre/stack_alloc.hpp b/include/cyfre/stack_alloc.hpp index 89d11b7..9663ff6 100644 --- a/include/cyfre/stack_alloc.hpp +++ b/include/cyfre/stack_alloc.hpp @@ -14,18 +14,6 @@ namespace cyfre { public: fixed(); - - /// @brief Copy Constructor. - fixed(const fixed &that); - - /// @brief Move Constructor. - fixed(fixed &&that); - - /// @brief Copy Assignment. - fixed &operator=(const fixed &that); - - /// @brief Move Assignment. - fixed &operator=(fixed &&that); }; } // namespace cyfre diff --git a/src/cyfre/heap_alloc.cpp b/src/cyfre/heap_alloc.cpp index 7f78356..1f85b8f 100644 --- a/src/cyfre/heap_alloc.cpp +++ b/src/cyfre/heap_alloc.cpp @@ -5,6 +5,7 @@ #include #include +#include "../../include/cyfre/check_operators.hpp" #include "../../include/cyfre/heap_alloc.hpp" namespace cyfre { @@ -13,6 +14,7 @@ namespace cyfre { template dynamic::dynamic(size_t rows, size_t cols) : matrix(new T[rows * cols]), rows(rows), cols(cols) { + static_assert(!valid_operators::value, "mat type 'T' does not support the necessary operators"); } // =================== DESTRUCTOR =================== @@ -26,8 +28,7 @@ namespace cyfre { /// @brief Copy Constructor. template - dynamic::dynamic(dynamic const &that) - : matrix(new T[that.rows * that.cols]), rows(that.rows), cols(that.cols) { + dynamic::dynamic(dynamic const &that) : dynamic::dynamic(that.rows, that.cols) { memcpy(matrix, that.matrix, that.rows * that.cols); } diff --git a/src/cyfre/stack_alloc.cpp b/src/cyfre/stack_alloc.cpp index a40c712..2e58b70 100644 --- a/src/cyfre/stack_alloc.cpp +++ b/src/cyfre/stack_alloc.cpp @@ -4,42 +4,15 @@ #include #include #include +#include +#include "../../include/cyfre/check_operators.hpp" #include "../../include/cyfre/stack_alloc.hpp" namespace cyfre { template fixed::fixed() : matrix() { - } - - /// @brief Copy Constructor. - template - fixed::fixed(fixed const &that) : matrix(new T[that.rows * that.cols]) { - memcpy(matrix, that.matrix, that.rows * that.cols); - } - - /// @brief Move Constructor. - template - fixed::fixed(fixed &&that) : matrix(that.matrix) { - memcpy(matrix, that.matrix, that.rows * that.cols); - } - - /// @brief Copy Assignment - template - fixed &fixed::operator=(fixed const &that) { - if (this != &that) { - memcpy(matrix, that.matrix, that.rows * that.cols); - } - return *this; - } - - /// @brief Move Assignment - template - fixed &fixed::operator=(fixed &&that) { - if (this != &that) { - memcpy(matrix, that.matrix, that.rows * that.cols); - } - return *this; + static_assert(!valid_operators::value, "mat type 'T' does not support the necessary operators"); } } // namespace cyfre diff --git a/test/tests.cpp b/test/tests.cpp index abd9a74..f68525f 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -1,6 +1,10 @@ +// #include "../../extended-precision-integers/epi.hpp" #include "../include/cyfre/cyfre.hpp" -#include + #include +#include + +typedef unsigned long long ullint; int main() { using cyfre::mat; @@ -37,8 +41,6 @@ int main() { return 0; } -#include - #ifdef ENABLE_OLD_TEST int main() {