Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/minel1410/matrix_operations
https://github.com/minel1410/matrix_operations
Last synced: 15 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/minel1410/matrix_operations
- Owner: minel1410
- Created: 2024-05-30T09:22:05.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2024-08-27T13:43:04.000Z (5 months ago)
- Last Synced: 2024-08-27T15:12:04.328Z (5 months ago)
- Language: C++
- Size: 307 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Matrix Operations
**Minel SalihagiΔ**
The project theme is the implementation of a `Matrix` class that stores a matrix of arbitrary dimensions. The focus was on efficient matrix multiplication, determinant calculation, and the `>>` operator. Since it wasn't specified whether the class should be generic, I chose to implement the matrix using a vector of vectors, which stores `double` values. As `double` is used, automatic conversion from `int` to `double` is supported. An important aspect to highlight is the class member `scalar`, which indicates whether the matrix is truly a matrix or a number represented in matrix form, necessary for implementing the `>>` operator, which acts as an evaluator of expressions with matrices.
A few auxiliary private functions are included to simplify the implementation of other functions. Most function names and their implementations are straightforward, so I won't go into detail here; brief explanations are provided in the comments for each function. The `Strassen` function, which takes two matrices and returns a matrix, performs multiplication in π(π^2.81) time, which is slightly faster than the standard multiplication algorithm (π(π^3)). The function is implemented using the "divide and conquer" method, as required by the task. It works by dividing the matrices into 4 blocks, then multiplying each block separately. If a block is larger than 2x2, which is the base case, the matrix is recursively divided into blocks. After completing the algorithm, the result is 4 matrices, which are the submatrices of the result. These submatrices need to be merged into one. Since Strassen's algorithm only works for square matrices with dimensions that are powers of 2, some 0-columns and rows need to be added to achieve such matrices. Functions like `addRowToEnd()` serve this purpose. The `removeExcess()` function removes the rows and columns that are unnecessary after multiplication. The `correctZeros()` function rounds off very small numbers to 0 that arise due to floating point arithmetic during multiplication. All functions are implemented to work with both constant and non-constant matrices, without altering the data.
Regarding constructors, there is a parameterless constructor, a constructor with 2 parameters that creates an identity matrix of the specified dimensions (throwing an exception if the parameters are negative or zero), a copy constructor that takes a scalar and stores it as a matrix, and a constructor that takes a matrix and two parameters, returning the matrix without the specified row and column. This is useful for determinant calculation. Additionally, "The Big Five" are implemented, as well as an assignment operator for scalar matrices.
The `Inverse()` function returns the inverse of the provided matrix. It first checks if the matrix is invertible by calculating the determinant; if not, it throws an exception. The function operates using the formula:
`A^(-1) = (1/detA) * adjA`
where `adjA` is the transpose of the matrix of algebraic complements, i.e., a matrix where each element is equal to the determinant of the matrix without the row and column containing that element. The function works in π(π^3) time for an n x n matrix. The determinant calculation function is implemented using the Gaussian elimination method with pivoting, reducing the matrix to upper triangular form and operating in π(π^3) time.
Since some functions that are not declared as friends of the class need to check if the scalar is true or false, a getter for `scalar` is provided. Operators `==, !=, +=, -=, *=, /=, +, -, *, /, ^` are implemented to work even when one of the matrices is a scalar. The `^` operator follows the fast exponentiation algorithm. If the exponent is negative, the matrix is first inverted, the exponent is multiplied by -1, and then the operator is called on the inverted matrix with the positive exponent. If the exponent is 0, the identity matrix is returned; if it is greater than 0, the binary representation of the exponent is considered, i.e., the result during division by 2. If the number is divisible by 2, the matrix is multiplied by the base matrix (the matrix that was passed in), the exponent is divided by 2, and this continues until the exponent is greater than 0.
Additionally, input and output operators for matrices are supported. The final function is `extractMatrix()`, an auxiliary function used in the `>>` operator, which extracts the matrix from the input stream when encountering a `[`. It is important to note that the input expression assumes that the `[` symbol marks the beginning of the matrix input, and an error will be raised if the matrix is not entered in the correct format.
The `>>` operator works according to the "shunting yard" algorithm, similar to how the evaluator was implemented in exercises, with auxiliary functions to simplify the operator's implementation. In the `main` function, there are functions for generating random integers and doubles, as well as a function that generates a random matrix. Several `for` loops are created to test certain functions on randomly generated matrices. Additionally, 5 expressions that can be used to test the functionality of the `>>` operator are provided in comments. It is important to note that when using the `>>` operator for entering the inverse of a matrix, the input should be in the form `"[1 2; 3 4] ^(-1)"`.
**Minel SalihagiΔ, 5930/M**
*Data Structures and Algorithms, 17.01.2023.*