I need a function that multiply a matrix and a vector (Matrix*vector)
It takes in a matrix A and a vector B, with int describing the dimensions. Somehow it isn't running correctly. Any help??
void Multiply(double *res, double **A, double *B, int ARows, int ACols, int BRows)
{
if (ACols !=BRows)
{
return;
}
for (int i = 0; i < ACols; i++)
{
res[i] = 0;
for (int j = 0; j < BRows; j++)
{
res[i] += A[i][j]*B[j];
}
}
}
It seems you mean
for (int i = 0; i < ARows; i++)
{
res[i] = 0;
for (int j = 0; j < ACols; j++)
{
res[i] += A[i][j]*B[j];
}
}
It would be better if the function returns a boolean value that signals whether the function execution was successful for example
bool Multiply(double *res, double **A, double *B, int ARows, int ACols, int BRows)
{
bool success = ACols == BRows;
if ( success )
{
for (int i = 0; i < ARows; i++)
{
res[i] = 0;
for (int j = 0; j < ACols; j++)
{
res[i] += A[i][j]*B[j];
}
}
}
return success;
}
Instead of the manually written loops you could use the standard algorithm std::inner_product declared in the header <numeric>.
Related
I dont know why but my matrix multipication is very slow and I need to optimize it. and also the print of the matrix (1000X1000) taking long time.
The aim of the function is to calculate the matrix exponential, but my main problem is that this 2 actions are very slow for large matrices like 1000X1000.
These 2 actions implemented at poweMat() function and printeResult() function.
Here is the code:
#define M 1000
#define e 2.71828182845904523536;
//declaration of the functions
void sumMatrices(vector<vector<double> >& mat1, vector<vector<double> >& mat2);
void printResult(vector<vector<double> >&matRes);
void mulMatWithFactorial(long factorialValue);
long factorialCalculate(int n);
void initializeMatrix();
void initializeIdenticalMatrix();
void checkIfTheMatrixIsDiagonal();
void calculateExpoMatrixWithDiagonalMatrix();
void readMatrixFromFile();
void powerMat(vector<vector<double> >& mat, int powNum);
//declaration of the variables
vector<vector<double>> inputMatrix(M, vector<double>(M));
vector<vector<double>> sumMatrixResult(M, vector<double>(M));
vector<vector<double>> powerMatrixResult(M, vector<double>(M));
vector<vector<double>> mulFactorialMatrixResult(M, vector<double>(M));
vector<vector<double>> finalMatrixResult(M, vector<double>(M));
vector<vector<double>> identicalMatrix(M, vector<double>(M));
vector<vector<vector<double>>> listOfMatrices;
bool matrixIsNilpotent = false;
int diagonaMatrixlFlag = 1;
int main() {
//variables
long factorialValue;
initializeIdenticalMatrix();
readMatrixFromFile();
//check if the matrix is diagonal - so we will have easier and faster compute
checkIfTheMatrixIsDiagonal();
if (diagonaMatrixlFlag == 1) {
calculateExpoMatrixWithDiagonalMatrix();
goto endOfLoop;
}
//loop for taylor series
for (int i = 0; i < 5; i++) {
if (i == 0) { // first we add identical matrix when the power is 0
sumMatrices(finalMatrixResult, identicalMatrix); // summarize between this 2 matrices
finalMatrixResult = sumMatrixResult; //copy matrices
}
if (i == 1) { // we add the matrix itself because the power is 1
sumMatrices(finalMatrixResult, inputMatrix);
finalMatrixResult = sumMatrixResult; //copy matrices
}
if (i > 1 ) {
powerMat(inputMatrix, i);
if (matrixIsNilpotent) { // it means that A^i is 0 for some integer, so the series terminates after a finite number
goto endOfLoop;
}
factorialValue = factorialCalculate(i); // calculate the factorial of i
mulMatWithFactorial(factorialValue); // multiply (1/i) * matrix^i - like in the algorithm
sumMatrices(finalMatrixResult, mulFactorialMatrixResult); // summarize it with the previous result
finalMatrixResult = sumMatrixResult; //copy matrices
}
}
endOfLoop:
printResult(finalMatrixResult); // print the final result - e^M
return 0;
}
//Summarize matrices
void sumMatrices(vector<vector<double> >& mat1, vector<vector<double> >& mat2) {
for (int i = 0; i < M; i++)
for (int j = 0; j < M; j++)
sumMatrixResult[i][j] = mat1[i][j] + mat2[i][j];
}
//Print matrix
void printResult(vector<vector<double> >& matRes) {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
printf("%f ", matRes[i][j]);
if (j == M - 1) {
printf("\n");
}
}
}
}
//Calculate the factorial of n
long factorialCalculate(int n) {
long factorial = 1.0;
for (int i = 1; i <= n; ++i) {
factorial *= i;
}
return factorial;
}
// mutiply the matrix with scalar
void mulMatWithFactorial(long factorialValue) {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
mulFactorialMatrixResult[i][j] = powerMatrixResult[i][j] * 1/factorialValue;
}
}
}
//initialize matrix
void initializeMatrix() {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
powerMatrixResult[i][j] = 0;
}
}
}
void checkIfTheMatrixIsDiagonal() {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
if (i == j)
{
if (inputMatrix[i][j] == 0) {
diagonaMatrixlFlag = 0;
goto endOfLoop;
}
}
else
{
if (inputMatrix[i][j] != 0) {
diagonaMatrixlFlag = 0;
goto endOfLoop;
}
}
}
}
endOfLoop:
return;
}
void calculateExpoMatrixWithDiagonalMatrix() {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
if (i == j)
{
for (int k = 0; k < inputMatrix[i][j]; ++k)// loop to calculate the pow of e^alpha
{
finalMatrixResult[i][j] *= e;
}
}
else
{
finalMatrixResult[i][j] = 0;
}
}
}
}
void readMatrixFromFile() {
ifstream f("inv_matrix(1000x1000).txt");
for (int i = 0; i < M; i++)
for (int j = 0; j < M; j++) {
f >> inputMatrix[i][j];
if (f.peek() == ',')
f.ignore();
}
listOfMatrices.push_back(inputMatrix);
}
void initializeIdenticalMatrix() {
for (int i = 0; i < M; i++) {
for (int k = 0; k < M; k++) {
if (i == k) {
identicalMatrix[i][k] = 1;
}
else {
identicalMatrix[i][k] = 0;
}
}
}
}
void powerMat(vector<vector<double> >& mat, int powNum) {
int counterForNilpotent = 0;
initializeMatrix();
auto start = high_resolution_clock::now();
for (int i = 0; i < M; i++) {
for (int k = 0; k < M; k++) {
for (int j = 0; j < M; j++) {
powerMatrixResult[i][j] += mat[i][k] * listOfMatrices[powNum-2][k][j];
}
}
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<seconds>(stop - start);
cout << duration.count() << " seconds" << endl; // checking run time
listOfMatrices.push_back(powerMatrixResult);
// check if after we we did A^i , the matrix is equal to 0
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
if (powerMatrixResult[i][j] == 0) {
counterForNilpotent++;
}
}
}
if (counterForNilpotent == M * M) {
matrixIsNilpotent = true;
}
}
Going through each element of an array of size "n" will have some computational efficiency of O(n^2), meaning for large arrays it will take a while but won't be "life-time-of-the-universe" lengths of time.
Usually to do operations on massive arrays like this, they're reduced in some form first so that the computation can be closer to O(n) or better using some truths about reduced forms of matrices.
So, a faster implementation for matrix multiplication would start with some rref() function upon both matrices and then only evaluating parts of those matrices that would have objects in the columns and rows.
Here are some great places to review/learn (for free) Linear Algebra:
"3b1b (2016): Essence of Linear Algebra" = https://www.youtube.com/watch?v=kjBOesZCoqc&list=PL0-GT3co4r2y2YErbmuJw2L5tW4Ew2O5B
"MIT OpenCourseWare (2009): Linear Algebra" = https://www.youtube.com/watch?v=ZK3O402wf1c&list=PL49CF3715CB9EF31D&index=1
Use SSE2. It’s not a library. It’s a method to use cpu vector hardware.
You set up operations to run in parallel.
https://en.wikipedia.org/wiki/SSE2
when I tried to multiple two negative numbers the value it is zero in c++,
for example -5 * -3
the result is zero,
why?
this is my code
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
void Multiply(const int v_arr[], const int m_arr[][3], int signed
o_arr[], int size)
{
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
o_arr[i] = 0;
for (int k = 0; k < 3; k++)
o_arr[i] += v_arr[k] * m_arr[k][i];
}
}
//End your code here
}
int main()
{
int n;
cin >> n;
int v_array[n];
int m_array[n][3];
int signed o_array[3];
for (int i = 0; i < n; i++) {
cin >> v_array[i];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < 3; j++) {
cin >> m_array[i][j];
}
}
//fuction
Multiply(v_array, m_array, o_array, n);
for (int j = 0; j < 3; j++) {
cout << o_array[j] << " ";
}
return 0;
}
how to fix it to get the correct result?
the input is
2
2 -3
2 -3
2 -4
Your issue is here:
for (int k = 0; k < 3; k++)
o_arr[i] += v_arr[k] * m_arr[k][i];
}
You access elements at indices 0, 1 and 2 in v_arr, but it only has 2 elements. That's Undefined Behaviour.
Assuming this is matrix*vector multiplication code, it should look like this (untested):
for (int k = 0; k < 3; k++)
o_arr[k] += v_arr[i] * m_arr[i][k];
}
Also, your loop based on j is useless. You can remove it:
void Multiply(const int v_arr[], const int m_arr[][3], int signed o_arr[], int size)
{
for(int k = 0; k < 3; k++) { //initialize output array
o_arr[k] = 0;
}
for (int i = 0; i < size; i++) {
for (int k = 0; k < 3; k++)
o_arr[k] += v_arr[i] * m_arr[i][k];
}
}
I want to compare a 2D array with my custom compare function. I also reference some similar problem, but it doesn't work.
Following is what I did (compare 2D array with row and I need to use array instead of vector):
int n, dim;
int box[33][33];
bool cmp(const int a[], const int b[]){
for(int i = 0; i < dim; i++){
if(a[i] != b[i])
return a[i] < b[i];
}
return a[dim] < b[dim];
}
int main()
{
while(cin>>n>>dim){
for(int i = 0; i < n; i++){
for(int j = 0; j < dim; j++){
cin>>box[i][j];
}
box[i][dim] = i+1; // store index of box
sort(box[i], box[i]+dim);
}
sort(box, box + n, cmp); // This line is where I want to modify
for(int i = 0; i < n; i++){
for(int j = 0; j < dim; j++){
cout<<box[i][j]<<" ";
}
cout<<"\n";
}
}
return 0;
}
You could use std::qsort in this case, by providing the appropriate comparator:
int cmp(const void *l, const void *r)
{
const int *a = (const int*)l;
const int *b = (const int*)r;
for(int i = 0; i < dim; i++)
{
if(a[i] != b[i])
return (a[i] > b[i]) - (a[i] < b[i]);
}
return (a[dim] > b[dim]) - (a[dim] < b[dim]);
}
and then calling it like this:
std::qsort(box, n, sizeof(int) * (dim + 1), cmp);
You could also simplify the comparator like this:
int comp(const void *l, const void *r)
{
const int *a = (const int*)l;
const int *b = (const int*)r;
return std::lexicographical_compare(b, b + dim + 1, a, a + dim +1);
}
Note that the arguments are in opposite order to get ascending order.
So I wrote this:
Matrix.h:
#pragma once
class Matrix
{
private:
int m, n;
double** M = nullptr;
public:
Matrix();
Matrix(int,int);
Matrix(const Matrix&);
~Matrix();
void set_m(int);
void set_n(int);
int get_m() const;
int get_n() const;
void setM(double**,int,int);
double** getM() const;
void show();
Matrix operator*(Matrix&) const;
};
Matrix.cpp:
#include "Matrix.h"
#include<iostream>
using namespace std;
/*
*/
Matrix::Matrix()
{
set_n(1);
set_m(1);
delete[] M;
M = new double*[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = 1.0;
}
Matrix::Matrix(int m_,int n_)
{
set_n(n_);
set_m(m_);
delete[] M;
M = new double *[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = 1.0;
}
Matrix::Matrix(const Matrix& M_)
{
set_n(M_.get_n());
set_m(M_.get_m());
delete[] M;
M = new double*[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = M_.getM()[i][j];
}
void Matrix::set_m(int m_) {
if (m_ > 0)
m = m_;
else
m = 1;
}
void Matrix::set_n(int n_) {
if (n_ > 0)
n = n_;
else
n = 1;
}
double** Matrix::getM() const {
return M;
}
Matrix Matrix::operator*(Matrix &M_) const
{
if (get_n() != M_.get_m()) {
if (get_m() != M_.get_n()) return Matrix();
else {
Matrix T(*this);
return M_*T;
}
}
else {
//n = m
Matrix R(get_m(), M_.get_n());
for (int i = 0; i < get_m(); i++) {
for (int j = 0; j < M_.get_n(); j++) {
double res = 0;
for (int k = 0; k < get_n(); k++) {
res += getM()[i][k] * M_.getM()[k][j];
}
R.getM()[i][j] = res;
}
}
return R;
}
}
int Matrix::get_m() const {
return m;
}
int Matrix::get_n() const {
return n;
}
void Matrix::setM(double** M_, int m_, int n_) {
set_m(m_);
set_n(n_);
for (int i = 0; i < get_m(); i++) {
delete M[i];
}
delete[] M;
M = new double*[m_];
for (int i = 0; i < m; i++) {
M[i] = new double[n_];
}
for (int i = 0; i < m_; i++)
for (int j = 0; j < n_; j++) M[i][j] = M_[i][j];
}
void Matrix::show() {
for (int i = 0; i < get_m(); i++) {
for (int j = 0; j < get_n(); j++) {
cout << getM()[i][j]<<" ";
}
cout << endl;
}
}
Matrix::~Matrix()
{
for (int i = 0; i < get_m(); i++) {
delete M[i];
}
delete[] M;
}
It crashes at void Matrix::setM(...) when I try to delete M[i] for i = 1; it doe perfectly fine for i=0; but crashes later and I do not have a rational explanation why does it do that. I can see the debugger showing me that the memory cannot be read even before it actually crashing but I do not understand how to fix it. Thanks in advance!
You are setting your m before deleting your array based on the old value of m and end up deleting your old array using the new value of m. You should first delete your array, then set mm, and then create your new array.
I need to implement a matrix transpose procedure in C++.
The problem is the signature, the function has to be called like this:
transpose(in_mat[0][0], n, m, out_mat[0][0])
where n and m are the dimensions.
All values are doubles, both the matrices and the dimensions.
Since the code is automatically generated, I can't fix this.
My workaround looks like this:
void transpose(double& in_mat, const double _n, const double _m, double& out_mat)
{
int n = _n, m = _m;
double* in_pointer= &in_mat;
double* out_pointer= &out_mat;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
*(out_pointer+(j*n+i)) = *(in_pointer+(i*m + j));
}
}
}
It works fine.
I've constructed a test case with two matrices of different width and height. One is filled with random numbers, the other is filled with zeros. Then the transpose procedure is called and the two matrices are compared.
The functionality is correct.
But it corrupts the stack. When run in Visual Studio 2015 there is a warning
Run-Time Check Failure #2 - Stack around the variable 'in_mat' was corrupted.
What did I do wrong ? Why is the stack corrupted ?
Code after the invocation of transpose works correctly.
EDIT:
Here is the complete setup:
#include <random>
#include <iostream>
void transpose(double& in_mat, const double _n, const double _m, double& out_mat)
{
int n = _n, m = _m;
double* in_pointer = &in_mat;
double* out_pointer = &out_mat;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
*(out_pointer+(j*n+i)) = *(in_pointer+(i*m + j));
}
}
}
int main()
{
double in_mat[5][4];
double out_mat[4][5];// assign matrix
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
in_mat[i][j] = std::rand();
out_mat[j][i] = 0;
}
}
double n = 5;
double m = 4;
transpose(in_mat[0][0], n, m, out_mat[0][0]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (in_mat[i][j] - out_mat[j][i]>0.0001) {
std::cout << "code is broken" << std::endl; //never reached
}
}
}
std::cout << "finished" << std::endl;
}
Your subscripts (or loop limits) were backwards where you initialized the matrices.
You have
double in_mat[5][4];
double out_mat[4][5];// assign matrix
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
in_mat[i][j] = std::rand();
out_mat[j][i] = 0;
}
}
When j==4 you are writing beyond the end of out_mat