started : Dec 2020
-
#include "cyfre/cyfre.hpp"
-
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 program (do not use in development)OMPTHREAD
- Enable OpenMP multi-threading / must include the openmp library -fopenmp
-
-DOMPTHREAD -fopenmp
-
-DCHECK_RANGE_DISABLE -DCHECK_SHAPE_DISABLE -DOMPTHREAD -fopenmp
-
-O3 -march=native
CREATING MATRIX (CONSTRUCTORS)
identity matrix
construct an identity matrix
cyfre::mat<int> mat_object(cyfre::TYPE::IDENTITY,3); /*
mat_object = [[1,0,0],
[0,1,0],
[0,0,1]]
*/
scalar matrix
construct an scalar matrix
cyfre::mat<int> mat_object(cyfre::TYPE::SCALARMATRIX,3,7); /*
mat_object = [[7,0,0],
[0,7,0],
[0,0,7]]
*/
zero/null matrix
construct an zero/null matrix
cyfre::mat<int> mat_object(cyfre::TYPE::NULLZERO,3); /*
mat_object = [[0,0,0],
[0,0,0],
[0,0,0]]
*/
shaped matrix with initial value
construct an costum shaped matrix, with initial values
cyfre::mat<int> 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
cyfre::mat<int> INT_MATRIX(4,5,cyfre::RANDOM::INTEGER,10,99);
ex. constructs a 3x3 matrix with random real values ranging from 0.0-1.0
cyfre::mat<double> FLOAT_MATRIX(4,5,cyfre::RANDOM::REAL,0,1);
defined matrix (row)
construct and define a matrix
cyfre::mat<int> mat_object({5,10,15,20,25});
// mat_object = [[5,10,15,20,25]] <-- (1x5 matrix)
defined matrix (2D)
construct and define a matrix
cyfre::mat<int> 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
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
cyfre::mat<int> 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
- costum row/column operations
swaping rows/columns
row_swap(row1,row2)
cyfre::mat<int> 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)
cyfre::mat<int> 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)
cyfre::mat<int> 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]]
*/
: 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 straigth forward
row scalar operation
scales all the elements of the row using a scalar value [changes the matrix itself]
cyfre::mat<int> 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]
cyfre::mat<int> 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]
cyfre::mat<int> 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, hench the 28 in mat_object(0,1)
column to column operation
scale a column using another column [changes the matrix itself]
cyfre::mat<int> 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
cyfre::mat<int> mat_object({
{1,2},
{3,4}
});
cyfre::mat<int> a = mat_object+2; /*
a = [[3,4],
[5,6]]
NOTE : cyfre::mat<int> 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]
cyfre::mat<int> mat_object({
{1,2},
{3,4}
});
mat_object-=2; /*
mat_object = [[-1,0],
[ 1,2]]
*/
MATRIX OPERATIONS
matrix addition
cyfre::mat<int> A({{ 1, 2, 3},
{ 4, 5, 6}});
cyfre::mat<int> B({{-1,-2,-3},
{-4,-5,-6}});
cyfre::mat<int> C = A+B; /*
C = [[ 0, 0, 0],
[ 0, 0, 0]]
*/
matrix subtraction
cyfre::mat<int> A({{10, 1,33},
{44,50,12}});
cyfre::mat<int> B({{ 7,19, 5},
{ 7, 6, 5}});
cyfre::mat<int> C = A-B; /*
C = [[ 3,-18,28],
[37, 44, 7]]
*/
matrix element-by-element division
cyfre::mat<int> A({{2,4,6},
{8,2,4}});
cyfre::mat<int> B({{1,4,3},
{2,2,1}});
cyfre::mat<int> C = A/B; /*
C = [[2,1,2],
[4,1,4]]
*/
hadamard product
cyfre::mat<int> A({{2,4,6},
{8,2,4}});
cyfre::mat<int> B({{1,4,3},
{2,2,1}});
cyfre::mat<int> 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)
cyfre::mat<int> X({
{ 7,12,13},
{14, 5,20},
{66,42,-4}
});
cyfre::mat<int> W({{-3,4,56}});
cyfre::mat<int> Y = X*W;
// C = [[3731,2336,-183]]
SCALAR METHODS
methods that returns a single/scalar value
min & max
cyfre::mat<int> X({
{ 1, 2, 3},
{ 4, 5,-6},
{17, 8, 9}
});
int min = X.min(); // -6
int max = X.max(); // 17
sum of all elements
cyfre::mat<int> X({
{1,2,3},
{4,5,6},
{7,8,9}
});
int sum = X.total();
// sum = 45
sum of the main-diagonal
cyfre::mat<int> X({
{1,2,3},
{4,5,6},
{7,8,9}
});
int diag_sum = X.trace();
// diag_sum = 15
Determinant of a Matrix
cyfre::mat<long double> 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
- the function should only have one parameter
- the function's return type, and parameter type should be the same as the matrix type
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
int square(int x) { return x*x; }
cyfre::mat<int> 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:
Transpose of a Matrix
cyfre::mat<int> 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
cyfre::mat<int> X({
{ 7,12,13},
{14, 5,20},
{66,42,-4}
});
cyfre::mat<int> X_cubed = cyfre::power(X,3); /*
X_cubed = [[35599 28068 26659],
[38210 31505 39196],
[130302 85590 20042]]
*/
cyfre::mat<int> X_squared = X;
X_squared.power(2); /*
X_squared = [[1075 690 279],
[1488 1033 202],
[786 834 1714]]
*/
Inverse of a Matrix
cyfre::mat<long double> 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)
Reduce Row Echelon Form
cyfre::mat<int> 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]]
*/
Row Eechelon Form : X.ref()
or X = cyfre::ref(X)
Padding
increase the size of matrix by padding zeros
cyfre::mat<int> 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
cyfre::mat<int> nums(
{{1,2,3},
{4,5,6},
{7,8,9}
});
for(size_t i=0; i<nums.height; ++i)
{
for(size_t j=0; j<nums.width; ++j)
{
/* use the operator() for matrix indexing */
nums(i,j)*=2;
std::cout<<nums(i,j)<<'\t';
}
std::cout<<'\n';
}
output :
2 4 6
8 10 12
14 16 18
STATISTICS
mean, median, mode
cyfre::mat<short> 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<size_t,std::vector<short>> getmode = cyfre::sts::mode(X);
size_t numbers_of_modes = getmode.second.size();
size_t modes_occurrence = getmode.first;
std::vector<short> modes = getmode.second;
/*
mean = 5.55556
median = 7
numbers_of_modes = 2
modes_occurrence = 3
modes = [7,4]
*/
sum of squares, variance, standard deviation
cyfre::mat<short> X({7,2,4,3,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);;
/*
sum_of_square = 34
variance = 8.5
standard_deviation = 2.91548
for population use 'cyfre::POPULATION' instead
*/