forked from leto/LeMA
164 lines
4.3 KiB
C++
164 lines
4.3 KiB
C++
#include <string>
|
|
#include <vector>
|
|
#include <cassert>
|
|
|
|
#define assertm(exp, msg) assert((void(msg), exp))
|
|
|
|
class Matrix{
|
|
private:
|
|
std::vector<std::vector<float>> values;
|
|
public:
|
|
void Randomize();
|
|
void Randomize(float, float);
|
|
|
|
void Set(float);
|
|
|
|
void Multiply(float);
|
|
Matrix Multiply(Matrix*);
|
|
|
|
void Add(float);
|
|
void Add(Matrix*);
|
|
|
|
void Substract(float);
|
|
void Substract(Matrix*);
|
|
|
|
void Print(std::string_view);
|
|
|
|
void Transpose();
|
|
|
|
// Constructors
|
|
Matrix(int, int);
|
|
Matrix(Matrix*);
|
|
};
|
|
|
|
// Constructs a zero matrix
|
|
Matrix::Matrix(int rows, int cols){
|
|
for(int m = 0; m < rows; m++){
|
|
std::vector<float> buffer = {};
|
|
for(int n = 0; n < cols; n++){
|
|
buffer.push_back(0.0F);
|
|
}
|
|
this->values.push_back(buffer);
|
|
}
|
|
}
|
|
|
|
Matrix::Matrix(Matrix* other){
|
|
this->values = other->values;
|
|
}
|
|
|
|
// Multiply 2 matrices (AxB = this x other)
|
|
Matrix Matrix::Multiply(Matrix* other){
|
|
// Resulting size is this->M x other->N
|
|
Matrix result(this->values.size(), other->values[0].size());
|
|
for(int m = 0; m < result.values.size(); m++){
|
|
for(int n = 0; n < result.values[m].size(); n++){
|
|
// Sum multiplications
|
|
float buffer = 0.0F;
|
|
for(int i = 0; i < this->values[0].size(); i++){
|
|
buffer += this->values[m][i] * other->values[i][n];
|
|
}
|
|
result.values[m][n] = buffer;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Add 2 matrices
|
|
void Matrix::Add(Matrix* other){
|
|
// Matrices need to be the same size
|
|
assertm(this->values.size() == other->values.size() &&
|
|
this->values[0].size() == other->values[0].size(),
|
|
"Matrices need to be the same size");
|
|
for(int m = 0; m < this->values.size(); m++){
|
|
for(int n = 0; n < this->values[m].size(); n++){
|
|
this->values[m][n] += other->values[m][n];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Substract 2 matrices
|
|
void Matrix::Substract(Matrix* other){
|
|
// Matrices need to be the same size
|
|
assertm(this->values.size() == other->values.size() &&
|
|
this->values[0].size() == other->values[0].size(),
|
|
"Matrices need to be the same size");
|
|
for(int m = 0; m < this->values.size(); m++){
|
|
for(int n = 0; n < this->values[m].size(); n++){
|
|
this->values[m][n] -= other->values[m][n];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print a matrix in terminal, with a title
|
|
void Matrix::Print(std::string_view titre){
|
|
std::cout << titre << std::endl;
|
|
for(int m = 0; m < values.size(); m++){
|
|
std::cout << '|';
|
|
for(int n = 0; n < values[m].size(); n++){
|
|
std::cout << values[m][n] << "|";
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
}
|
|
|
|
// Add a constant value to every matrix case
|
|
void Matrix::Add(float value){
|
|
for(int m = 0; m < this->values.size(); m++){
|
|
for(int n = 0; n < this->values[m].size(); n++){
|
|
this->values[m][n] += value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Substract a constant value to every matrix case
|
|
void Matrix::Substract(float value){
|
|
for(int m = 0; m < this->values.size(); m++){
|
|
for(int n = 0; n < this->values[m].size(); n++){
|
|
this->values[m][n] -= value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Multiply every matrix case by a given factor
|
|
void Matrix::Multiply(float value){
|
|
for(int m = 0; m < this->values.size(); m++){
|
|
for(int n = 0; n < this->values[m].size(); n++){
|
|
this->values[m][n] *= value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set a matrix to a given value
|
|
void Matrix::Set(float value){
|
|
this->Multiply(0.0F);
|
|
this->Add(value);
|
|
}
|
|
|
|
// Transpose a matrix
|
|
void Matrix::Transpose(){
|
|
std::vector<std::vector<float>> buffer = this->values;
|
|
this->values = {};
|
|
|
|
// Invert matrix size
|
|
for(int m = 0; m < buffer[0].size(); m++){
|
|
std::vector<float> row = {};
|
|
for(int n = 0; n < buffer.size(); n++){
|
|
row.push_back(buffer[n][m]);
|
|
}
|
|
this->values.push_back(row);
|
|
}
|
|
}
|
|
|
|
// Randomize a matrix from 0.0F to 10.0F
|
|
void Matrix::Randomize(){
|
|
this->Randomize(0.0F, 10.0F);
|
|
}
|
|
|
|
// Randomize a matrix from min to max
|
|
void Matrix::Randomize(float min, float max){
|
|
for(int m = 0; m < this->values.size(); m++){
|
|
for(int n = 0; n < this->values[m].size(); n++){
|
|
this->values[m][n] = min + ((float)rand()/(float)(RAND_MAX)) * (max - min);
|
|
}
|
|
}
|
|
} |