Related
EDITED
I am trying to calculate the exponent of a matrix or the e of a matrix. Using some expected results, e.g. for a simple complex number of 1 + I. I have implemented some changes to divide by n factorial. Still having a similar issue whereby after some iterations the values blow up like crazy.
Output
This program will calculat
> Blockquotee the exp of a matrix A
Calculating power of matrix
(1,1)(1,1)(1,1)
(1,1)(1,1)(1,1)
(1,1)(1,1)(1,1)
Performing scalar division
(1,1)(1,1)(1,1)
(1,1)(1,1)(1,1)
(1,1)(1,1)(1,1)
Performing Summation
(1,1)(1,1)(1,1)
(1,1)(1,1)(1,1)
(1,1)(1,1)(1,1)
1
Calculating power of matrix
(0,6)(0,6)(0,6)
(0,6)(0,6)(0,6)
(0,6)(0,6)(0,6)
Performing scalar division
(0,6)(0,6)(0,6)
(0,6)(0,6)(0,6)
(0,6)(0,6)(0,6)
Performing Summation
(1,7)(1,7)(1,7)
(1,7)(1,7)(1,7)
(1,7)(1,7)(1,7)
2
Calculating power of matrix
(-18,18)(-18,18)(-18,18)
(-18,18)(-18,18)(-18,18)
(-18,18)(-18,18)(-18,18)
Performing scalar division
(-18,18)(-18,18)(-18,18)
(-18,18)(-18,18)(-18,18)
(-18,18)(-18,18)(-18,18)
Performing Summation
(-17,25)(-17,25)(-17,25)
(-17,25)(-17,25)(-17,25)
(-17,25)(-17,25)(-17,25)
3
Calculating power of matrix
(-108,0)(-108,0)(-108,0)
(-108,0)(-108,0)(-108,0)
(-108,0)(-108,0)(-108,0)
Performing scalar division
(-108,0)(-108,0)(-108,0)
(-108,0)(-108,0)(-108,0)
(-108,0)(-108,0)(-108,0)
Performing Summation
(-125,25)(-125,25)(-125,25)
(-125,25)(-125,25)(-125,25)
(-125,25)(-125,25)(-125,25)
4
Calculating power of matrix
(-324,-324)(-324,-324)(-324,-324)
(-324,-324)(-324,-324)(-324,-324)
(-324,-324)(-324,-324)(-324,-324)
Performing scalar division
(-324,-324)(-324,-324)(-324,-324)
(-324,-324)(-324,-324)(-324,-324)
(-324,-324)(-324,-324)(-324,-324)
Performing Summation
(-449,-299)(-449,-299)(-449,-299)
(-449,-299)(-449,-299)(-449,-299)
(-449,-299)(-449,-299)(-449,-299)
5
Calculating power of matrix
(0,-1944)(0,-1944)(0,-1944)
(0,-1944)(0,-1944)(0,-1944)
(0,-1944)(0,-1944)(0,-1944)
Performing scalar division
(0,-1944)(0,-1944)(0,-1944)
(0,-1944)(0,-1944)(0,-1944)
(0,-1944)(0,-1944)(0,-1944)
Performing Summation
(-449,-2243)(-449,-2243)(-449,-2243)
(-449,-2243)(-449,-2243)(-449,-2243)
(-449,-2243)(-449,-2243)(-449,-2243)
6
Calculating power of matrix
(5832,-5832)(5832,-5832)(5832,-5832)
(5832,-5832)(5832,-5832)(5832,-5832)
(5832,-5832)(5832,-5832)(5832,-5832)
Performing scalar division
(5832,-5832)(5832,-5832)(5832,-5832)
(5832,-5832)(5832,-5832)(5832,-5832)
(5832,-5832)(5832,-5832)(5832,-5832)
Performing Summation
(5383,-8075)(5383,-8075)(5383,-8075)
(5383,-8075)(5383,-8075)(5383,-8075)
(5383,-8075)(5383,-8075)(5383,-8075)
7
Calculating power of matrix
(34992,0)(34992,0)(34992,0)
(34992,0)(34992,0)(34992,0)
(34992,0)(34992,0)(34992,0)
Performing scalar division
(34992,0)(34992,0)(34992,0)
(34992,0)(34992,0)(34992,0)
(34992,0)(34992,0)(34992,0)
Performing Summation
(40375,-8075)(40375,-8075)(40375,-8075)
(40375,-8075)(40375,-8075)(40375,-8075)
(40375,-8075)(40375,-8075)(40375,-8075)
8
Calculating power of matrix
(104976,104976)(104976,104976)(104976,104976)
(104976,104976)(104976,104976)(104976,104976)
(104976,104976)(104976,104976)(104976,104976)
Performing scalar division
(104976,104976)(104976,104976)(104976,104976)
(104976,104976)(104976,104976)(104976,104976)
(104976,104976)(104976,104976)(104976,104976)
Performing Summation
(145351,96901)(145351,96901)(145351,96901)
(145351,96901)(145351,96901)(145351,96901)
(145351,96901)(145351,96901)(145351,96901)
9
#pragma once
#include <iostream>
#include <complex>
#include <cmath>
#include <cassert>
using namespace std;
class ComplexMatrix
{
private:
complex<long double>** Arr;
int mi = 3;
int mj = 3;
public:
ComplexMatrix();
//~ComplexMatrix();
ComplexMatrix(int i, int j);
ComplexMatrix(const ComplexMatrix&);
void Initialise(complex<long double>);
void DisplayMatrix();
void DeleteMatrix();
void EnterComplexMatrix(int, int);
ComplexMatrix matrixPower(ComplexMatrix&, int);
ComplexMatrix ScalarDivision_Fac(ComplexMatrix& , complex<long
double>);
ComplexMatrix MatrixAddition(ComplexMatrix&, ComplexMatrix&);
ComplexMatrix matrixSq(ComplexMatrix&);
ComplexMatrix Multiply(ComplexMatrix, ComplexMatrix);
ComplexMatrix matrixe_A(ComplexMatrix&, int);
ComplexMatrix operator*(const ComplexMatrix&);
ComplexMatrix operator=(const ComplexMatrix&);
friend ComplexMatrix operator+(const ComplexMatrix&, const ComplexMatrix&);
};
//Constructor to initialise a default 3 x 3 complex matrix with 0s for real and imaginary values
ComplexMatrix::ComplexMatrix()
{
Arr = new complex<long double> * [mi];
for (int x = 0; x < mi; x++)
{
Arr[x] = new complex<long double> [mj];
}
for (int x1 = 0; x1 < mi; x1++)
{
for (int y1 = 0; y1 < mj; y1++)
{
Arr[x1][y1] = (0.0, 0.0);
}
}
}
//Constructor to initialise a user defined complex matrix of a particular size with 0s for real
and imaginary values
ComplexMatrix::ComplexMatrix(int i, int j)
{
mi = i;
mj = j;
Arr = new complex<long double> * [i];
for (int x = 0; x < i; x++)
{
Arr[x] = new complex<long double>[j];
}
for (int x1 = 0; x1 < i; x1++)
{
for (int y1 = 0; y1 < j; y1++)
{
Arr[x1][y1] = (0.0, 0.0);
}
}
}
//Copy Constructor
ComplexMatrix::ComplexMatrix(const ComplexMatrix& CM)
//lets only have ARR mean one thing to make it easier to read, understand,
and to avoid this->
clutter.
{
Arr = new complex<long double> * [mi];
for (int x = 0; x < mi; x++)
{
Arr[x] = new complex<long double>[mj];
}
for (int x1 = 0; x1 < mi; x1++)
{
for (int y1 = 0; y1 < mj; y1++)
{
Arr[x1][y1] = CM.Arr[x1][y1];
}
}
}
/*
ComplexMatrix::~ComplexMatrix()
{
for (int x = 0; x < mi; x++)
{
delete[] Arr[x];
}
delete[] Arr;
}
*/
//Initialise matrix elements to a particular value
void ComplexMatrix::Initialise(complex<long double> x)
{
for (int i = 0; i < mi; i++)
{
for (int j = 0; j < mj; j++)
{
Arr[i][j] = x;
}
}
}
//Display the matrix member function
void ComplexMatrix::DisplayMatrix()
{
for (int x = 0; x < mi; x++)
{
for (int y = 0; y < mj; y++)
{
cout << Arr[x][y];
}
cout << endl;
}
}
//Delete the memory allocated by the matrix member function
void ComplexMatrix::DeleteMatrix()
{
for (int x = 0; x < mi; x++)
{
delete[] Arr[x];
}
delete[] Arr;
}
//Enter complex matrix elements member function
void ComplexMatrix::EnterComplexMatrix(int i, int j)
{
double real, img;
complex < long double> temp = (0.0, 0.0);
cout << "Your matrix will have " << i * j << " elements" << endl;
//Prompt for user input and assign values for real and imaginary values
for (int x = 0; x < i; x++)
{
for (int y = 0; y < j; y++)
{
cout << "Enter the details for the real part of element" << "[" <<
x << "]" << "[" << y
<< "]" << endl;
cin >> real;
cout << "Enter the details for the real part of element" << "[" <<
x << "]" << "[" << y
<< "]" << endl;
cin >> img;
temp = (real, img);
Arr[x][y] = temp;
}
}
}
ComplexMatrix ComplexMatrix::Multiply(ComplexMatrix x, ComplexMatrix y)
{
ComplexMatrix z(3, 3);
for (int x1 = 0; x1 < 3; ++x1)
{
for (int y1 = 0; y1 < 3; ++y1)
{
for (int z1 = 0; z1 < 3; ++z1)
{
Arr[x1][y1] += x.Arr[x1][z1] * y.Arr[z1][y1];
}
}
}
return z;
}
ComplexMatrix ComplexMatrix::ScalarDivision_Fac(ComplexMatrix& x,
complex<long double> n)
{
ComplexMatrix newCompArr(3, 3);
complex <long double> fac = 0.0;
int n1 = static_cast <int>(n.real());
n1 = static_cast <int>(n1);
complex <long double> i1;
for (int i = 1; i < n1; i++)
{
i1 = i;
fac = fac * i1;
}
for (int x1 = 0; x1 < mi; x1++)
{
for (int y1 = 0; y1 < mj; y1++)
{
newCompArr.Arr[x1][y1] = x.Arr[x1][y1] / fac;
}
}
return newCompArr;
}
ComplexMatrix ComplexMatrix::matrixSq(ComplexMatrix& x)
{
ComplexMatrix result(mi, mj);
result = x * x;
return result;
}
ComplexMatrix ComplexMatrix::matrixPower(ComplexMatrix& a, int n)
{
ComplexMatrix result(mi, mj);
ComplexMatrix temp(mi, mj);
temp = a;
if (n % 2 == 0)
{
for (int i = 1; i < n / 2; i++)
{
result = temp * a;
temp = result;
}
result = temp;
result = result.matrixSq(result);
}
else
{
for (int j = 0; j < (n - 1) ; j++)
{
result = temp * a;
temp = result;
}
result = temp;
}
return result;
}
ComplexMatrix ComplexMatrix::matrixe_A(ComplexMatrix& A, int n)
{
ComplexMatrix expA(mi, mj);
ComplexMatrix sum(mi, mj);
sum.Initialise({ 0.0, 0.0 });
ComplexMatrix A_n(mi, mj);
ComplexMatrix A_n_div_n(mi, mj);
ComplexMatrix temp(mi, mj);
ComplexMatrix zero(mi, mj);
zero.Initialise({ 0.0, 0.0 });
complex <long double> j;
for (int i = 1; i < n; i++)
{
cout << "Calculating power of matrix" << endl;
A_n = A.matrixPower(A, i);
A_n.DisplayMatrix();
A_n_div_n = A_n;
cout << "Performing scalar division" << endl;
A_n_div_n.ScalarDivision(A_n_div_n, i);
A_n_div_n.DisplayMatrix();
cout << endl;
temp = zero;
temp = A_n_div_n;
cout << "Performing Summation" << endl;
sum = sum + temp;
sum.DisplayMatrix();
cout << i << endl;
cout << endl;
temp = zero;
A_n = A.matrixPower(A, i);
}
return sum;
}
ComplexMatrix ComplexMatrix::operator*(const ComplexMatrix& CompArr)
{
ComplexMatrix newCompArr(3, 3);
for (int x1 = 0; x1 < 3; ++x1)
{
for (int y1 = 0; y1 < 3; ++y1)
{
newCompArr.Arr[x1][y1] = {0.0, 0.0};
for (int z1 = 0; z1 < 3; ++z1)
{
newCompArr.Arr[x1][y1] += Arr[x1][z1] * CompArr.Arr[z1][y1];
}
}
}
return newCompArr;
}
ComplexMatrix ComplexMatrix::operator=(const ComplexMatrix& CM)
{
mi = 3;
mj = 3;
//ComplexMatrix Arr(3, 3);
for (int x1 = 0; x1 < mi; x1++)
{
for (int y1 = 0; y1 < mj; y1++)
{
Arr[x1][y1] = CM.Arr[x1][y1];
}
}
//return Arr;
return *this;
}
ComplexMatrix operator+(const ComplexMatrix &x, const ComplexMatrix &y)
{
int mi = 3;
int mj = 3;
ComplexMatrix newCompArr(3, 3);
for (int x1 = 0; x1 < mi; x1++)
{
for (int y1 = 0; y1 < mj; y1++)
{
newCompArr.Arr[x1][y1] = { (x.Arr[x1][y1].real() + y.Arr[x1][y1].real()) ,
(x.Arr[x1][y1].imag() + y.Arr[x1][y1].imag()) };
}
}
return newCompArr;
}
#include <iostream>
#include "Header.h"
#include <complex>
#include <cmath>
using namespace std;
int main()
{
std::cout << "This program will calculate the exp of a matrix A\n";
complex<long double> x = {1, 1};
complex<long double> y = {2, 2};
complex<long double> z = { 0.0, 0.0 };
ComplexMatrix z1(3, 3);
ComplexMatrix z2(3, 3);
ComplexMatrix z3(3, 3);
z2.Initialise(x);
z3 = z2.matrixe_A(z2, 10);
//z3.DisplayMatrix();
z1.DeleteMatrix();
z2.DeleteMatrix();
}
I'm trying to learn about matrix multiplication and encounter this code for Strassen multiplication vs standard matrix multiplication, so I've tried to implement it. However, this code uses too much memory to the point that when the matrix it's big enough it kills the program. Also, because it uses too much memory it takes longer to process.
I'm not too comfortable to mess around with the code too much since I don't fully understand complex memory management and I would really like to learn about this topic.
Build in the code there's a cut parameter and found that at 320 makes it run faster and seems like improves with memory management.
EDIT. I've implemented a copy constructor, destructor and a function to track memory usage and it fixed the memory leaks it was having, but the big jump on the time between 1990 dimension to 2100 still there for the Strassen matrix.
matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#include <vector>
using namespace std;
class matrix
{
public:
matrix(int dim, bool random, bool strassen);
matrix(const matrix& old_m);
inline int dim() {
return dim_;
}
inline int& operator()(unsigned row, unsigned col) {
return data_[dim_ * row + col];
}
inline int operator()(unsigned row, unsigned col) const {
return data_[dim_ * row + col];
}
void print();
matrix operator+(matrix b);
matrix operator-(matrix b);
~matrix();
private:
int dim_;
int* data_;
};
#endif
Matrix.cpp
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
#include "SAMmatrix.h"
using namespace std;
matrix::matrix(int dim, bool random, bool strassen) : dim_(dim) {
if (strassen) {
int dim2 = 2;
while (dim2 < dim)
dim2 *= 2;
dim_ = dim2;
}
data_ = new int[dim_ * dim_];
if (!random) return;
for (int i = 0; i < dim_ * dim_; i++)
data_[i] = rand() % 10;
}
matrix::matrix(const matrix& old_m){
dim_ = old_m.dim_;
data_ = new int[dim_ * dim_];
for (int i = 0; i < dim_ * dim_; i++)
data_[i] = old_m.data_[i];
}
void matrix::print() {
for (int i = 0; i < dim_; i++) {
for (int j = 0; j < dim_; j++)
cout << (*this)(i, j) << " ";
cout << "\n";
}
cout << "\n";
}
matrix matrix::operator+(matrix b) {
matrix c(dim_, false, false);
for (int i = 0; i < dim_; i++)
for (int j = 0; j < dim_; j++)
c(i, j) = (*this)(i, j) + b(i, j);
return c;
}
matrix matrix::operator-(matrix b) {
matrix c(dim_, false, false);
for (int i = 0; i < dim_; i++)
for (int j = 0; j < dim_; j++)
c(i, j) = (*this)(i, j) - b(i, j);
return c;
}
matrix::~matrix()
{
delete [] data_;
}
Matrix main
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include "SAMmatrix.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
typedef pair<matrix, long> result;
int cut = 64;
matrix mult_std(matrix a, matrix b)
{
matrix c(a.dim(), false, false);
for (int i = 0; i < a.dim(); i++)
for (int k = 0; k < a.dim(); k++)
for (int j = 0; j < a.dim(); j++)
c(i, j) += a(i, k) * b(k, j);
return c;
}
matrix get_part(int pi, int pj, matrix m)
{
matrix p(m.dim() / 2, false, true);
pi = pi * p.dim();
pj = pj * p.dim();
for (int i = 0; i < p.dim(); i++)
for (int j = 0; j < p.dim(); j++)
p(i, j) = m(i + pi, j + pj);
return p;
}
void set_part(int pi, int pj, matrix* m, matrix p)
{
pi = pi * p.dim();
pj = pj * p.dim();
for (int i = 0; i < p.dim(); i++)
for (int j = 0; j < p.dim(); j++)
(*m)(i + pi, j + pj) = p(i, j);
}
matrix mult_strassen(matrix a, matrix b)
{
if (a.dim() <= cut)
return mult_std(a, b);
matrix a11 = get_part(0, 0, a);
matrix a12 = get_part(0, 1, a);
matrix a21 = get_part(1, 0, a);
matrix a22 = get_part(1, 1, a);
matrix b11 = get_part(0, 0, b);
matrix b12 = get_part(0, 1, b);
matrix b21 = get_part(1, 0, b);
matrix b22 = get_part(1, 1, b);
matrix m1 = mult_strassen(a11 + a22, b11 + b22);
matrix m2 = mult_strassen(a21 + a22, b11);
matrix m3 = mult_strassen(a11, b12 - b22);
matrix m4 = mult_strassen(a22, b21 - b11);
matrix m5 = mult_strassen(a11 + a12, b22);
matrix m6 = mult_strassen(a21 - a11, b11 + b12);
matrix m7 = mult_strassen(a12 - a22, b21 + b22);
matrix c(a.dim(), false, true);
set_part(0, 0, &c, m1 + m4 - m5 + m7);
set_part(0, 1, &c, m3 + m5);
set_part(1, 0, &c, m2 + m4);
set_part(1, 1, &c, m1 - m2 + m3 + m6);
return c;
}
pair<matrix, long> run(matrix(*f)(matrix, matrix), matrix a, matrix b)
{
struct timeval start, end;
gettimeofday(&start, NULL);
matrix c = f(a, b);
gettimeofday(&end, NULL);
long e = (end.tv_sec * 1000 + end.tv_usec / 1000);
long s = (start.tv_sec * 1000 + start.tv_usec / 1000);
return pair<matrix, long>(c, e - s);
}
int parseLine(char* line){ /* overflow*/
// This assumes that a digit will be found and the line ends in " Kb".
int i = strlen(line);
const char* p = line;
while (*p <'0' || *p > '9') p++;
line[i-3] = '\0';
i = atoi(p);
return i;
}
int getValue(){ //Note: this value is in KB!
FILE* file = fopen("/proc/self/status", "r");
int result = -1;
char line[128];
while (fgets(line, 128, file) != NULL){
if (strncmp(line, "VmSize:", 7) == 0){
result = parseLine(line);
break;
}
}
fclose(file);
return result;
}
int main()
{
/* test cut of for strassen
/*
for (cut = 2; cut <= 512; cut++) {
matrix a(512, true, true);
matrix b(512, true, true);
result r = run(mult_strassen, a, b);
cout << cut << " " << r.second << "\n";
}
*/
/* performance test: standard and strassen */
/*1024 going up by 64*/
for (int dim = 1500; dim <= 2300; dim += 200)
{
double space = getValue() * .01;
cout << "Space before: " << space << "Mb" << "\n";
matrix a(dim, true, false);
matrix b(dim, true, false);
result std = run(mult_std, a, b);
matrix c(dim, true, true);
matrix d(dim, true, true);
result strassen = run(mult_strassen, c, d);
cout << "Dim " << " Std " << " Stranssen" << endl;
cout << dim << " " << std.second << "ms " << strassen.second << "ms " << "\n";
double spaceA = getValue() * .01;
cout << "Space: " << spaceA << "Mb" << "\n";
cout << " " << endl;
}
}
I set it to go from 1500 to 2300 by 200 and the program is "killed" before finishing
1500 2406 4250
1700 3463 4252
1900 4819 4247
2100 6487 30023
Killed
Also, it shouldn't make a big jump on time like that when the dimension goes from 1900 to 2100.
I wrote paralell program based on a Strassen multiplication algorithm using pointers.
this program return the result of multiplication of two matrices that are the same size.
when the size is 256 , program fill about 1 GB of ram, and when it is 512 ram total\y become full and my windows doesn't work then I must restart.
I replace whole pointers with vectors then incredibly Ram usage decreased!.for 1024 size , just 80 MB of ram used.
I know a little about vector that is bound statically at first then if we need more space during runtime its bound dynamically.
Why pointers needed more space than vectors ?
this is my first code :
#include <iostream>
#include<cilk\cilk.h>
#include <cilk/cilk_api.h>
#include<conio.h>
#include<ctime>
#include<string>
#include<random>
#include <Windows.h>
#include <Psapi.h>
#include<vector>
using namespace std;
int ** matrix_1;
int ** matrix_2;
#define number_thread:4;
void show(string name, int n, int **show)
{
cout << " matrix " << name << " :" << endl;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
cout << show[i][j] << " ";
cout << endl;
}
}
int ** strassen(int n, int **matrix_a, int ** matrix_b)
{
int ** A11;
int ** A12;
int ** A21;
int ** A22;
int ** B11;
int ** B12;
int ** B21;
int ** B22;
int ** result;
int **m1, **m2, **m3, ** m4, ** m5, ** m6, ** m7, ** m8;
A11 = new int*[n / 2];
A12 = new int*[n / 2];
A21 = new int*[n / 2];
A22 = new int*[n / 2];
B11 = new int*[n / 2];
B12 = new int*[n / 2];
B21 = new int*[n / 2];
B22 = new int*[n / 2];
result = new int *[n];
m1 = new int*[n / 2];
m2 = new int*[n / 2];
m3 = new int*[n / 2];
m4 = new int*[n / 2];
m5 = new int*[n / 2];
m6 = new int*[n / 2];
m7 = new int*[n / 2];
m8 = new int*[n / 2];
cilk_for(int i = 0; i < n / 2; i++)
{
//cout << " value i : " << i << endl;
A11[i] = new int[n / 2];
A12[i] = new int[n / 2];
A21[i] = new int[n / 2];
A22[i] = new int[n / 2];
B11[i] = new int[n / 2];
B12[i] = new int[n / 2];
B21[i] = new int[n / 2];
B22[i] = new int[n / 2];
m1[i] = new int[n / 2];
m2[i] = new int[n / 2];
m3[i] = new int[n / 2];
m4[i] = new int[n / 2];
m5[i] = new int[n / 2];
m6[i] = new int[n / 2];
m7[i] = new int[n / 2];
m8[i] = new int[n / 2];
}
cilk_for(int i = 0; i < n; i++) // matrix result
result[i] = new int[n];
if (n == 2)
{
result[0][0] = matrix_a[0][0] * matrix_b[0][0] + matrix_a[0][1] * matrix_b[1][0];
result[0][1] = matrix_a[0][0] * matrix_b[0][1] + matrix_a[0][1] * matrix_b[1][1];
result[1][0] = matrix_a[1][0] * matrix_b[0][0] + matrix_a[1][1] * matrix_b[1][0];
result[1][1] = matrix_a[1][0] * matrix_b[0][1] + matrix_a[1][1] * matrix_b[1][1];
return result;
}
// for (int i = 0; i < n;i++)
cilk_for(int i = 0; i < (n / 2); i++)
{
for (int j = 0; j < (n / 2); j++)
{
A11[i][j] = matrix_a[i][j];
B11[i][j] = matrix_b[i][j];
A12[i][j] = matrix_a[i][j + n / 2];
B12[i][j] = matrix_b[i][j + n / 2];
A21[i][j] = matrix_a[i + n / 2][j];
B21[i][j] = matrix_b[i + n / 2][j];
A22[i][j] = matrix_a[i + n / 2][j + n / 2];
B22[i][j] = matrix_b[i + n / 2][j + n / 2];
}
}
/*
show("A11", n / 2, A11);
show("A12", n / 2, A12);
show("A21", n / 2, A21);
show("A22", n / 2, A22);
show("B11", n / 2, B11);
show("B12", n / 2, B12);
show("B21", n / 2, B21);
show("B22", n / 2, B22);*/
// Run By eight_thread
m1 = cilk_spawn(strassen(n / 2, A11, B11));// A11B11
m2 = cilk_spawn(strassen(n / 2, A12, B21));// A12B21
m3 = cilk_spawn(strassen(n / 2, A11, B12));// A11B12
m4 = cilk_spawn(strassen(n / 2, A12, B22));// A12B22
m5 = cilk_spawn(strassen(n / 2, A21, B11));// A21B11
m6 = cilk_spawn(strassen(n / 2, A22, B21));// A22B21
m7 = cilk_spawn(strassen(n / 2, A21, B12));// A21B12
m8 = cilk_spawn(strassen(n / 2, A22, B22));// A22B22
cilk_sync;
/*
cout << "****************************\n";
cout << "*********** before add :\n";
show("m1", n / 2, m1);
show("m2", n / 2, m2);
show("m3", n / 2, m3);
show("m4", n / 2, m4);
show("m5", n / 2, m5);
show("m6", n / 2, m6);
show("m7", n / 2, m7);
show("m8", n / 2, m8);*/
cilk_for(int i = 0; i < n / 2; i++)
for (int j = 0; j < n / 2; j++)
{
m1[i][j] = m1[i][j] + m2[i][j];
m3[i][j] = m3[i][j] + m4[i][j];
m5[i][j] = m5[i][j] + m6[i][j];
m7[i][j] = m7[i][j] + m8[i][j];
}
/*cout << "after adding hello \n";
show("m1", n / 2, m1);
show("m3", n / 2, m3);
show("m5", n / 2, m5);
show("m7", n / 2, m7);*/
cilk_for(int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i < n / 2 && j < n / 2)
{
result[i][j] = m1[i][j];
}
else if (i < n / 2 && j >= n / 2)
{
result[i][j] = m3[i][j - n / 2];
}
else if (i >= n / 2 && j < n / 2)
{
result[i][j] = m5[i - n / 2][j];
}
else if (i >= n / 2 && j >= n / 2)
{
result[i][j] = m7[i - n / 2][j - n / 2];
}
}
}
/*
cilk_for(int i = 0; i < n / 2; i++)
{
for (int j = 0; j < n / 2; j++)
{
delete A11[i][j];
delete A12[i][j];
delete A21[i][j];
delete A22[i][j];
delete B11[i][j];
delete B12[i][j];
delete B21[i][j];
delete B22[i][j];
delete m1[i][j];
delete m2[i][j];
delete m3[i][j];
delete m4[i][j];
delete m5[i][j];
delete m6[i][j];
delete m7[i][j];
delete m8[i][j];*/
/* }
delete[] A11[i];
delete[] A12[i];
delete[] A21[i];
delete[] A22[i];
delete[] B11[i];
delete[] B12[i];
delete[] B21[i];
delete[] B22[i];
delete[] m1[i];
delete[] m2[i];
delete[] m3[i];
delete[] m4[i];
delete[] m5[i];
delete[] m6[i];
delete[] m7[i];
delete[] m8[i];
}*/
delete[] A11;
delete[] A12;
delete[] A21;
delete[] A22;
delete[] B11;
delete[] B12;
delete[] B21;
delete[] B22;
delete[] m1;
delete[] m2;
delete[] m3;
delete[] m4;
delete[] m5;
delete[] m6;
delete[] m7;
delete[] m8;
return result;
}
int main()
{
int size;
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
__cilkrts_set_param("nworkers", "4");
//cout << " please Enter the size OF ur matrix /n";
cin >> size;
matrix_1 = new int*[size];
matrix_2 = new int*[size];
if (size % 2 == 0)
{
//instialize matrix1
//cout << "matrix_1 :" << endl;
for (int i = 0; i < size; i++)
{
matrix_1[i] = new int[size];
for (int j = 0; j < size; j++)
{
matrix_1[i][j] = rand() % 3;
//cin >> matrix_1[i][j];
//cout << matrix_1[i][j] << " ";
}
//cout << endl;
}
//instialize matrix2
//cout << "matrix2_is :\n";
for (int i = 0; i < size; i++)
{
matrix_2[i] = new int[size];
for (int j = 0; j < size; j++)
{
matrix_2[i][j] = rand() % 3;
//cout << matrix_2[i][j]<<" ";
//cin >> matrix_2[i][j];
}
// cout << endl;
}
clock_t begin = clock();
matrix_2 = strassen(size, matrix_1, matrix_2);
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
cout << "*******\ntime is : " << elapsed_secs << endl;
//answer:
/* for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
cout<< matrix_2[i][j]<<" ";
}
cout << endl;
}*/
}
else
cout << " we couldnt use strasen ";
cout << "\nTotal Virtual Memory:" << endl;
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
printf("%u", totalVirtualMem);
cout << "\nVirtual Memory currently used:" << endl;
// MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
printf("%u", virtualMemUsed);
cout << "\nVirtual Memory currently used by current process:" << endl;
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
printf("%u", virtualMemUsedByMe);
cout << "\nPhysical Memory currently used: " << endl;
//MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
printf("%u", physMemUsed);
cout << endl;
cout << "\nPhysical Memory currently used by current process : " << endl;
// PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
printf("%u", physMemUsedByMe);
//cout << "memory usage :"<<double(totalVirtualMem) << endl;
//_getch();
return 0;
}
I replace whole pointers array with vectors :
#include <iostream>
#include<cilk\cilk.h>
#include <cilk/cilk_api.h>
#include<conio.h>
#include<ctime>
#include<string>
#include<random>
#include <Windows.h>
#include <Psapi.h>
#include<vector>
using namespace std;
vector<vector<int> > matrix_1, matrix_2;
//int matrix_1;
//int ** matrix_2;
#define number_thread:4;
void show(string name ,int n, int **show)
{
cout << " matrix " << name<<" :" << endl;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
cout << show[i][j] << " ";
cout << endl;
}
}
vector<vector<int>> strassen(int n, vector<vector<int>> matrix_a, vector<vector<int>> matrix_b)
{
vector<vector<int>> A11;
vector<vector<int>> A12;
vector<vector<int>> A21;
vector<vector<int>> A22;
vector<vector<int>> B11;
vector<vector<int>> B12;
vector<vector<int>> B21;
vector<vector<int>> B22;
vector<vector<int>> result;
vector<int> help;
vector<vector<int>> m1, m2, m3, m4, m5, m6, m7, m8;
help.clear();
for (int j = 0; j < n / 2; j++)
{
help.push_back(2);
}
for(int i = 0; i < n / 2; i++)
{
A11.push_back(help);
A12.push_back(help);
A21.push_back(help);
A22.push_back(help);
B11.push_back(help);
B12.push_back(help);
B21.push_back(help);
B22.push_back(help);
m1.push_back(help);
m2.push_back(help);
m3.push_back(help);
m4.push_back(help);
m5.push_back(help);
m6.push_back(help);
m7.push_back(help);
m8.push_back(help);
}
for (int j = 0; j < n / 2; j++)
help.push_back(2);
for(int i = 0; i < n; i++)
{
result.push_back(help);
}
if (n == 2)
{
result[0][0] = matrix_a[0][0] * matrix_b[0][0] + matrix_a[0][1] * matrix_b[1][0];
result[0][1] = matrix_a[0][0] * matrix_b[0][1] + matrix_a[0][1] * matrix_b[1][1];
result[1][0] = matrix_a[1][0] * matrix_b[0][0] + matrix_a[1][1] * matrix_b[1][0];
result[1][1] = matrix_a[1][0] * matrix_b[0][1] + matrix_a[1][1] * matrix_b[1][1];
return result;
}
// for (int i = 0; i < n;i++)
for(int i = 0; i < (n / 2); i++)
{
for(int j = 0; j <( n / 2); j++)
{
A11[i][j] = matrix_a[i][j];
B11[i][j] = matrix_b[i][j];
A12[i][j] = matrix_a[i][j + n / 2];
B12[i][j] = matrix_b[i][j + n / 2];
A21[i][j] = matrix_a[i + n / 2][j];
B21[i][j] = matrix_b[i + n / 2][j];
A22[i][j] = matrix_a[i + n / 2][j + n / 2];
B22[i][j] = matrix_b[i + n / 2][j + n / 2];
}
}
/*
show("A11", n / 2, A11);
show("A12", n / 2, A12);
show("A21", n / 2, A21);
show("A22", n / 2, A22);
show("B11", n / 2, B11);
show("B12", n / 2, B12);
show("B21", n / 2, B21);
show("B22", n / 2, B22);*/
// Run By eight_thread
m1 = cilk_spawn(strassen(n / 2, A11, B11));// A11B11
m2 = cilk_spawn(strassen(n / 2, A12, B21));// A12B21
m3 = cilk_spawn(strassen(n / 2, A11, B12));// A11B12
m4 = cilk_spawn(strassen(n / 2, A12, B22));// A12B22
m5 = cilk_spawn(strassen(n / 2, A21, B11));// A21B11
m6 = cilk_spawn(strassen(n / 2, A22, B21));// A22B21
m7 = cilk_spawn(strassen(n / 2, A21, B12));// A21B12
m8 = cilk_spawn(strassen(n / 2, A22, B22));// A22B22
cilk_sync;
/*
cout << "****************************\n";
cout << "*********** before add :\n";
show("m1", n / 2, m1);
show("m2", n / 2, m2);
show
("m3", n / 2, m3);
show("m4", n / 2, m4);
show("m5", n / 2, m5);
show("m6", n / 2, m6);
show("m7", n / 2, m7);
show("m8", n / 2, m8);*/
for(int i = 0; i < n / 2; i++)
for (int j = 0; j < n / 2; j++)
{
m1[i][j] = m1[i][j] + m2[i][j];
m3[i][j] = m3[i][j] + m4[i][j];
m5[i][j] = m5[i][j] + m6[i][j];
m7[i][j] = m7[i][j] + m8[i][j];
}
/*cout << "after adding hello \n";
show("m1", n / 2, m1);
show("m3", n / 2, m3);
show("m5", n / 2, m5);
show("m7", n / 2, m7);*/
for(int i = 0; i < n ; i++)
{
for(int j = 0; j < n ; j++)
{
if (i < n / 2 && j < n / 2)
{
result[i][j] = m1[i][j];
}
else if (i < n / 2 && j >= n / 2)
{
result[i][j] = m3[i][j - n / 2];
}
else if (i >= n / 2 && j < n / 2)
{
result[i][j] = m5[i - n / 2][j];
}
else if (i >= n / 2 && j >= n / 2)
{
result[i][j] = m7[i - n / 2][j - n / 2];
}
}
}
/*
cilk_for(int i = 0; i < n / 2; i++)
{
for (int j = 0; j < n / 2; j++)
{
delete A11[i][j];
delete A12[i][j];
delete A21[i][j];
delete A22[i][j];
delete B11[i][j];
delete B12[i][j];
delete B21[i][j];
delete B22[i][j];
delete m1[i][j];
delete m2[i][j];
delete m3[i][j];
delete m4[i][j];
delete m5[i][j];
delete m6[i][j];
delete m7[i][j];
delete m8[i][j];*/
/* }
delete[] A11[i];
delete[] A12[i];
delete[] A21[i];
delete[] A22[i];
delete[] B11[i];
delete[] B12[i];
delete[] B21[i];
delete[] B22[i];
delete[] m1[i];
delete[] m2[i];
delete[] m3[i];
delete[] m4[i];
delete[] m5[i];
delete[] m6[i];
delete[] m7[i];
delete[] m8[i];
}*/
/* for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << result[i][j] << " ";
}
cout << endl;
}*/
return result;
}
int main()
{
int size;
freopen("in.txt","r",stdin);
freopen("out.txt", "w", stdout);
__cilkrts_set_param("nworkers", "1");
//cout << " please Enter the size OF ur matrix /n";
cin >> size;
vector<int> inner;
if (size % 2 == 0)
{
//instialize matrix1
cout << "matrix_1 :" << endl;
for (int i = 0; i < size; i++)
{
inner.clear();
for (int j = 0; j < size; j++)
{
inner.push_back(rand()%3);
//cin >> matrix_1[i][j];
cout << inner[j]<<" ";
}
cout << endl;
matrix_1.push_back(inner);
}
//instialize matrix2
cout << "matrix2_is :\n";
inner.clear();
for (int i = 0; i < size; i++)
{
inner.clear();
//matrix_2[i] = new int[size];
for (int j = 0; j < size; j++)
{
inner.push_back(rand()%3);
cout << inner[j]<<" ";
//cin >> matrix_2[i][j];
}
cout << endl;
matrix_2.push_back(inner);
}
clock_t begin = clock();
matrix_2 = strassen(size, matrix_1, matrix_2);
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
cout << "*******\ntime is : " << elapsed_secs << endl;
//answer:
cout << "answerrr :" << endl;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
cout<< matrix_2[i][j]<<" ";
}
cout << endl;
}
}
else
cout << " we couldnt use strasen ";
cout << "\nTotal Virtual Memory:" << endl;
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
printf("%u", totalVirtualMem);
cout << "\nVirtual Memory currently used:" << endl;
// MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
printf("%u", virtualMemUsed);
cout << "\nVirtual Memory currently used by current process:" << endl;
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
printf("%u", virtualMemUsedByMe);
cout << "\nPhysical Memory currently used: " << endl;
//MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
printf("%u", physMemUsed);
cout << endl;
cout << "\nPhysical Memory currently used by current process : " << endl;
// PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
printf("%u", physMemUsedByMe);
//cout << "memory usage :"<<double(totalVirtualMem) << endl;
//_getch();
return 0;
}
Two likely reasons come to mind:
If you allocate memory manually and don't free it correctly you create memory leaks. With raw pointers this is much more likely to happen than with vectors.
If you allocate 1000 integers in 1000 separate allocations it will take much more space than allocating a single block of 1000 integers (what vectors do). Each allocation requires some additional memory for bookkeeping.
I am going to guess this is an allocation issue. Allocation from the OS seems to be quite time consuming from what I have seen.
Just a guess but maybe the std::vector default allocator is grabbing a much larger contiguous block of memory from the OS and is drawing from that to satisfy smaller vector allocations?
This answer may provide some insight:
https://stackoverflow.com/a/29659791/3807729
I managed to reduce the time taken to run a test program simply by allocating, then deallocating a large std::vector before running the timing operations.
I am speculating that the C++ runtime system (in some implementations) may hold on to memory it has received from the OS even after it has been deallocated because grabbing small chunks from the OS each time is much more expensive.
I'm getting the following errors due to the namespace cpl?
I included Wavepacket.cpp and Vector.hpp below.
obj\Debug\wavepacket.o||In function `Z10initializev':|
wavepacket.cpp|79|undefined reference to `cpl::Vector::Vector(int)'|
wavepacket.cpp|79|undefined reference to `cpl::Vector::operator=(cpl::Vector const&)'|
wavepacket.cpp|80|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|80|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
wavepacket.cpp|81|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|81|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
wavepacket.cpp|101|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|101|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
wavepacket.cpp|102|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|102|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
wavepacket.cpp|103|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|103|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
obj\Debug\wavepacket.o||In function `Z8timeStepv':|
wavepacket.cpp|124|undefined reference to `cpl::solveTridiagonalCyclic(cpl::ComplexVector&, cpl::ComplexVector&, cpl::ComplexVector&, std::complex<double>, std::complex<double>, cpl::ComplexVector&, cpl::ComplexVector&)'|
wavepacket.cpp|126|undefined reference to `cpl::solveTridiagonal(cpl::ComplexVector&, cpl::ComplexVector&, cpl::ComplexVector&, cpl::ComplexVector&, cpl::ComplexVector&)'|
obj\Debug\wavepacket.o||In function `_static_initialization_and_destruction_0':|
wavepacket.cpp|22|undefined reference to `cpl::Vector::Vector(int)'|
wavepacket.cpp|71|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|71|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|72|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|72|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|72|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
||=== Build finished: 20 errors, 0 warnings ===|
Wavepacket.cpp
#include <cmath>
#include <complex>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
#include <sstream>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include "Vector.hpp"
const double pi = 4*std::atan(1.0);
double h_bar = 1; // natural units
double mass = 1; // natural units
// The spatial grid
int N = 200; // number of interior grid points
double L = 100; // system extends from x=0 to x=L
double h = L / (N + 1); // grid size
double tau = 1; // time step
cpl::Vector x; // coordinates of grid points
bool periodic = true; // false = oo potential, true = periodic
// The potential V(x)
double V0 = 1.0; // height of potential well
double Vwidth = 10; // width of potential well
double Vcenter = 0.75 * L; // center of potential well
bool gaussian; // false = step potential
double V(double x) {
double halfWidth = std::abs(0.5 * Vwidth);
if (gaussian) {
double dx = (x - Vcenter) / halfWidth;
return V0 * std::exp( - dx * dx / 2);
} else {
if (std::abs(x - Vcenter) <= halfWidth)
return V0;
else
return 0;
}
}
// Inital wave packet
double x0 = L / 4; // location of center
double E = 1; // average energy
double sigma0 = L / 10; // width of wave packet
double Norm_psi; // norm of psi
double k0; // average wavenumber
double velocity; // average velocity
void getInput() {
std::cout << "Time-dependent Schroedinger Equation\n";
std::cout << "Enter size of x region L = ";
std::cin >> L;
std::cout << "Enter number of grid points N = ";
std::cin >> N;
std::cout << "Enter integration time step tau = ";
std::cin >> tau;
std::cout << "Enter width of potential = ";
std::cin >> Vwidth;
std::cout << "Enter height of potential V0 = ";
std::cin >> V0;
std::cout << "Enter width of packet sigma = ";
std::cin >> sigma0;
std::cout << "Enter energy of packet E = ";
std::cin >> E;
}
double t; // time
cpl::ComplexVector psi, chi; // complex wavefunction
cpl::ComplexVector a, b, c; // to represent tridiagonal Q matrix
std::complex<double> alpha, beta; // corner elements of Q
void initialize () {
t = 0;
// reset vectors
x = cpl::Vector(N);
psi = cpl::ComplexVector(N);
chi = cpl::ComplexVector(N);
// reset the lattice
h = L / (N + 1);
for (int j = 0; j < N; j++)
x[j] = (j + 1) * h;
// inititalize the packet
k0 = std::sqrt(2*mass*E - h_bar*h_bar/2/sigma0/sigma0) / h_bar;
velocity = k0 / mass;
Norm_psi = 1 / std::sqrt(sigma0 * std::sqrt(pi));
for (int j = 0; j < N; j++) {
double expFactor = std::exp(-(x[j] - x0) * (x[j] - x0)
/ (2 * sigma0 * sigma0));
psi[j] = std::complex<double>(
Norm_psi * std::cos(k0 * x[j]) * expFactor,
Norm_psi * std::sin(k0 * x[j]) * expFactor);
}
// elements of tridiagonal matrix Q = (1/2)(1 + i tau H / (2 hbar))
a = cpl::ComplexVector(N);
b = cpl::ComplexVector(N);
c = cpl::ComplexVector(N);
for (int j = 0; j < N; j++) {
const std::complex<double> i(0.0, 1.0);
b[j] = 0.5 + i * tau / (4 * h_bar) *
(V(x[j]) + h_bar * h_bar / (mass * h * h));
a[j] = c[j] = - i * tau * h_bar / (8 * mass * h * h);
}
alpha = c[N-1];
beta = a[0];
}
double T = 5; // time to travel length L
double framesPerSec = 50; // animation rate for screen redraws
void timeStep() {
static std::clock_t clockStart;
static bool done;
if (!done) {
double t0 = t;
do {
if (periodic)
solveTridiagonalCyclic(a, b, c, alpha, beta, psi, chi);
else
solveTridiagonal(a, b, c, psi, chi);
for (int j = 0; j < N; j++)
psi[j] = chi[j] - psi[j];
t += tau;
} while (std::abs(velocity * (t - t0)) < L / T / framesPerSec);
done = true;
}
std::clock_t clockNow = std::clock();
double seconds = (clockNow - clockStart) / double(CLOCKS_PER_SEC);
if ( seconds < 1 / framesPerSec ) {
return;
} else {
clockStart = clockNow;
done = false;
}
glutPostRedisplay();
glFlush();
}
void drawText(const std::string& str, double x, double y) {
glRasterPos2d(x, y);
int len = str.find('\0');
for (int i = 0; i < len; i++)
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, str[i]);
}
bool showRealImaginary; // false = probability only
void display() {
glClear(GL_COLOR_BUFFER_BIT);
if (showRealImaginary) {
glColor3f(0, 0, 1); // real part of psi blue
glBegin(GL_LINES);
for (int j = 1; j < N; j++) {
glVertex2d(x[j-1], psi[j-1].real());
glVertex2d(x[j], psi[j].real());
}
glEnd();
glColor3f(0, 1, 0); // imaginary part of psi green
glBegin(GL_LINES);
for (int j = 1; j < N; j++) {
glVertex2d(x[j-1], psi[j-1].imag());
glVertex2d(x[j], psi[j].imag());
}
glEnd();
}
glColor3f(1, 0, 0); // probability red
double pOld = psi[0].real() * psi[0].real() +
psi[0].imag() * psi[0].imag();
glBegin(GL_LINES);
for (int j = 1; j < N; j++) {
double p = psi[j].real() * psi[j].real() +
psi[j].imag() * psi[j].imag();
glVertex2d(x[j-1], 4 * pOld);
glVertex2d(x[j], 4 * p);
pOld = p;
}
glEnd();
glColor3ub(255, 165, 0); // potential orange
double Vold = V(x[1]);
glBegin(GL_LINES);
for (int j = 1; j < N; j++) {
double Vnew = V(x[j]);
glVertex2d(x[j-1], 0.2 * Vold);
glVertex2d(x[j], 0.2 * Vnew);
Vold = Vnew;
}
glEnd();
glColor3f(0, 0, 0); // text black
std::ostringstream os;
os << (periodic ? "Periodic " : "Infinite Wall ")
<< "Boundary Conditions" << std::ends;
drawText(os.str(), 0.02 * L, 0.28);
os.seekp(0); // beginning of string stream
os << "0" << std::ends;
drawText(os.str(), 0, -0.02);
drawText("0", 0, -0.02);
os.seekp(0);
os << "x = " << L << std::ends;
drawText(os.str(), (1 - 0.1) * L, -0.02);
os.seekp(0);
os << "t = " << t << std::ends;
drawText(os.str(), 0.02 * L, -0.29);
glutSwapBuffers();
}
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, L, -0.3, 0.3);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
bool running; // to control animation
void mouse(int button, int state, int x, int y) {
switch (button) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
if (running) {
glutIdleFunc(NULL);
running = false;
} else {
glutIdleFunc(timeStep);
running = true;
}
}
break;
default:
break;
}
}
void menu(int menuItem) {
switch (menuItem) {
case 1:
gaussian = !gaussian;
break;
case 2:
periodic = !periodic;
break;
case 3:
showRealImaginary = !showRealImaginary;
break;
case 4:
if (running) {
glutIdleFunc(NULL);
running = false;
}
initialize();
glutPostRedisplay();
break;
default:
break;
}
}
int main(int argc, char *argv[]) {
getInput();
initialize();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("Schroedinger Wave Packet Motion");
glClearColor(1.0, 1.0, 1.0, 0.0);
glShadeModel(GL_FLAT);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutCreateMenu(menu);
glutAddMenuEntry("Potential: Square/Gaussian", 1);
glutAddMenuEntry("Boundaries: Dirichlet/Periodic", 2);
glutAddMenuEntry("Real & Imag: Show/Hide", 3);
glutAddMenuEntry("Reset", 4);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
}
Vector.hpp
#ifndef CPL_VECTOR_HPP
#define CPL_VECTOR_HPP
#include <complex>
#include <iostream>
namespace cpl {
class Vector {
public:
Vector(int dim = 1);
Vector(const Vector& dv);
~Vector() { delete [] v; }
int dimension() const { return dim; }
void resize(const int);
const double operator[](const int i) const { return v[i]; }
double& operator[](const int i) { return v[i]; }
Vector& operator = (const Vector& dv);
Vector& operator += (const Vector& dv);
Vector& operator -= (const Vector& dv);
Vector& operator *= (double d);
Vector& operator /= (double d);
double abs();
double norm();
double dot(const Vector& dv);
friend std::ostream& operator<<(std::ostream& os, const Vector& dv);
private:
int dim;
double *v;
};
inline Vector operator + (const Vector& dv) {
return dv;
}
extern Vector operator - (const Vector& dv);
extern Vector operator * (const Vector& dv, double d);
extern Vector operator * (double d, const Vector& dv);
extern Vector operator / (const Vector& dv, double d);
extern Vector operator + (const Vector& v1, const Vector& v2);
extern Vector operator - (const Vector& v1, const Vector& v2);
class ComplexVector {
public:
ComplexVector(int dim = 1);
ComplexVector(const ComplexVector& cv);
~ComplexVector() { delete [] v; }
int dimension() const { return dim; }
const std::complex<double> operator[](const int i) const { return v[i]; }
std::complex<double>& operator[](const int i) { return v[i]; }
ComplexVector& operator = (const ComplexVector& cv);
private:
int dim;
std::complex<double> *v;
};
class FFT {
public:
FFT() { N = 0; f = 0; inverse = false; }
void transform(ComplexVector& data);
void inverseTransform(ComplexVector& data);
Vector power(ComplexVector& data);
private:
int N;
ComplexVector *f;
bool inverse;
void bitReverse();
void DanielsonLanczos(int n);
};
extern void solveTridiagonal(
ComplexVector& a, ComplexVector& b, ComplexVector& c,
ComplexVector& r, ComplexVector& u);
extern void solveTridiagonalCyclic(
ComplexVector& a, ComplexVector& b, ComplexVector& c,
std::complex<double> alpha, std::complex<double> beta,
ComplexVector& r, ComplexVector& x);
} /* end namespace cpl */
#endif /* CPL_VECTOR_HPP */
EDIT I didn't want to delete this post incase someone needed it but I forgot to use Vector.cpp which is below.
#include "Vector.hpp"
namespace cpl {
Vector::Vector(int dim) {
v = new double [this->dim = dim];
for (int i = 0; i < dim; i++) v[i] = 0;
}
Vector::Vector(const Vector& dv) {
v = new double [dim = dv.dim];
for (int i = 0; i < dim; i++) v[i] = dv.v[i];
}
void Vector::resize(const int dimension) {
delete [] v;
v = new double [dim = dimension];
for (int i = 0; i < dim; i++) v[i] = 0;
}
Vector& Vector::operator = (const Vector& dv) {
if (this != &dv) {
if (dim != dv.dim) {
delete [] v;
v = new double [dim = dv.dim];
}
for (int i = 0; i < dim; i++) v[i] = dv[i];
}
return *this;
}
Vector& Vector::operator += (const Vector& dv) {
for (int i = 0; i < dim; i++) v[i] += dv[i];
return *this;
}
Vector& Vector::operator -= (const Vector& dv) {
for (int i = 0; i < dim; i++) v[i] -= dv[i];
return *this;
}
Vector& Vector::operator *= (double d) {
for (int i = 0; i < dim; i++) v[i] *= d;
return *this;
}
Vector& Vector::operator /= (double d) {
for (int i = 0; i < dim; i++) v[i] /= d;
return *this;
}
Vector operator - (const Vector& dv) {
int dim = dv.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = -dv[i];
return temp;
}
Vector operator * (const Vector& dv, double d) {
int dim = dv.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = dv[i] * d;
return temp;
}
Vector operator * (double d, const Vector& dv) {
int dim = dv.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = dv[i] * d;
return temp;
}
Vector operator / (const Vector& dv, double d) {
int dim = dv.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = dv[i] / d;
return temp;
}
Vector operator + (const Vector& v1, const Vector& v2) {
int dim = v1.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = v1[i] + v2[i];
return temp;
}
Vector operator - (const Vector& v1, const Vector& v2) {
int dim = v1.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = v1[i] - v2[i];
return temp;
}
double Vector::abs() {
return std::sqrt(norm());
}
double Vector::norm() {
double sum = 0;
for (int i = 0; i < dim; i++) sum += v[i] * v[i];
return sum;
}
double Vector::dot(const Vector& dv) {
double sum = 0;
for (int i = 0; i < dim; i++) sum += v[i] * dv[i];
return sum;
}
std::ostream& operator<<(std::ostream& os, const Vector& dv) {
for (int i = 0; i < dv.dim; i++) {
os << dv.v[i];
if (i < dv.dim-1)
os << '\t';
else
os << '\n';
}
return os;
}
// ComplexVector implementation
ComplexVector::ComplexVector(int dim) {
v = new std::complex<double> [this->dim = dim];
for (int i = 0; i < dim; i++) v[i] = 0.0;
}
ComplexVector::ComplexVector(const ComplexVector& cv) {
v = new std::complex<double> [dim = cv.dim];
for (int i = 0; i < dim; i++) v[i] = cv.v[i];
}
ComplexVector& ComplexVector::operator = (const ComplexVector& cv) {
if (this != &cv) {
if (dim != cv.dim) {
delete [] v;
v = new std::complex<double> [dim = cv.dim];
}
for (int i = 0; i < dim; i++) v[i] = cv[i];
}
return *this;
}
// FFT implementation
void FFT::transform(ComplexVector& data) {
N = data.dimension();
f = &data;
bitReverse();
for (int n = 1; n < N; n *= 2)
DanielsonLanczos(n);
for (int i = 0; i < N; ++i)
(*f)[i] /= std::sqrt(double(N));
}
void FFT::inverseTransform(ComplexVector& data) {
inverse = true;
transform(data);
inverse = false;
}
void FFT::bitReverse() {
int j = 1;
for (int i = 1; i < N; ++i) {
if (i < j) {
std::complex<double> temp = (*f)[i-1];
(*f)[i-1] = (*f)[j-1];
(*f)[j-1] = temp;
}
int k = N / 2;
while ( k < j ) {
j -= k;
k /= 2;
}
j += k;
}
}
void FFT::DanielsonLanczos(int n) {
const double pi = 4 * atan(1.0);
std::complex<double> W(0, pi / n);
W = inverse ? std::exp(-W) : std::exp(W);
std::complex<double> W_j(1, 0);
for (int j = 0; j < n; ++j) {
for (int i = j; i < N; i += 2 * n) {
std::complex<double> temp = W_j * (*f)[n+i];
(*f)[n+i] = (*f)[i] - temp;
(*f)[i] += temp;
}
W_j *= W;
}
}
Vector FFT::power(ComplexVector& data) {
Vector P(1 + N / 2);
P[0] = std::norm(data[0]) / double(N);
for (int i = 1; i < N / 2; i++)
P[i] = (std::norm(data[i]) + std::norm(data[N-i])) / double(N);
P[N/2] = std::norm(data[N/2]) / double(N);
return P;
}
// Solving tridiagonal complex matrices
void solveTridiagonal(
ComplexVector& a, ComplexVector& b, ComplexVector& c,
ComplexVector& r, ComplexVector& u)
{
int n = a.dimension();
ComplexVector gamma(n);
std::complex<double> beta = b[0];
u[0] = r[0] / beta;
for (int j = 1; j < n; j++) {
gamma[j] = c[j-1] / beta;
beta = b[j] - a[j] * gamma[j];
u[j] = (r[j] - a[j] * u[j-1]) / beta;
}
for (int j = n - 2; j >= 0; j--)
u[j] -= gamma[j+1] * u[j+1];
}
void solveTridiagonalCyclic(
ComplexVector& a, ComplexVector& b, ComplexVector& c,
std::complex<double> alpha, std::complex<double> beta,
ComplexVector& r, ComplexVector& x)
{
int n = a.dimension();
ComplexVector bb(n), u(n), z(n);
std::complex<double> gamma = -b[0];
bb[0] = b[0] - gamma;
bb[n-1] = b[n-1] - alpha * beta / gamma;
for (int i = 1; i < n-1; i++)
bb[i] = b[i];
solveTridiagonal(a, bb, c, r, x);
u[0] = gamma;
u[n-1] = alpha;
for (int i = 1; i < n-1; i++)
u[i] = 0.0;
solveTridiagonal(a, bb, c, u, z);
std::complex<double> fact = x[0] + beta * x[n-1] / gamma;
fact /= 1.0 + z[0] + beta * z[n-1] / gamma;
for (int i = 0; i < n; i++)
x[i] -= fact * z[i];
}
} /* end namespace cpl */
it's probably your build script that's not configured correctly. Your code compiled for me when I used the following commands:
g++ -c Vector.cpp -o Vector.o
g++ -c Wavepacket.cpp -o Wavepacket.o
g++ Vector.o Wavepacket.o -lGL -lGLU -lglut -o app
What's the easiest way to compute a 3x3 matrix inverse?
I'm just looking for a short code snippet that'll do the trick for non-singular matrices, possibly using Cramer's rule. It doesn't need to be highly optimized. I'd prefer simplicity over speed. I'd rather not link in additional libraries.
Here's a version of batty's answer, but this computes the correct inverse. batty's version computes the transpose of the inverse.
// computes the inverse of a matrix m
double det = m(0, 0) * (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) -
m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0));
double invdet = 1 / det;
Matrix33d minv; // inverse of matrix m
minv(0, 0) = (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) * invdet;
minv(0, 1) = (m(0, 2) * m(2, 1) - m(0, 1) * m(2, 2)) * invdet;
minv(0, 2) = (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * invdet;
minv(1, 0) = (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) * invdet;
minv(1, 1) = (m(0, 0) * m(2, 2) - m(0, 2) * m(2, 0)) * invdet;
minv(1, 2) = (m(1, 0) * m(0, 2) - m(0, 0) * m(1, 2)) * invdet;
minv(2, 0) = (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1)) * invdet;
minv(2, 1) = (m(2, 0) * m(0, 1) - m(0, 0) * m(2, 1)) * invdet;
minv(2, 2) = (m(0, 0) * m(1, 1) - m(1, 0) * m(0, 1)) * invdet;
This piece of code computes the transposed inverse of the matrix A:
double determinant = +A(0,0)*(A(1,1)*A(2,2)-A(2,1)*A(1,2))
-A(0,1)*(A(1,0)*A(2,2)-A(1,2)*A(2,0))
+A(0,2)*(A(1,0)*A(2,1)-A(1,1)*A(2,0));
double invdet = 1/determinant;
result(0,0) = (A(1,1)*A(2,2)-A(2,1)*A(1,2))*invdet;
result(1,0) = -(A(0,1)*A(2,2)-A(0,2)*A(2,1))*invdet;
result(2,0) = (A(0,1)*A(1,2)-A(0,2)*A(1,1))*invdet;
result(0,1) = -(A(1,0)*A(2,2)-A(1,2)*A(2,0))*invdet;
result(1,1) = (A(0,0)*A(2,2)-A(0,2)*A(2,0))*invdet;
result(2,1) = -(A(0,0)*A(1,2)-A(1,0)*A(0,2))*invdet;
result(0,2) = (A(1,0)*A(2,1)-A(2,0)*A(1,1))*invdet;
result(1,2) = -(A(0,0)*A(2,1)-A(2,0)*A(0,1))*invdet;
result(2,2) = (A(0,0)*A(1,1)-A(1,0)*A(0,1))*invdet;
Though the question stipulated non-singular matrices, you might still want to check if determinant equals zero (or very near zero) and flag it in some way to be safe.
Why don't you try to code it yourself? Take it as a challenge. :)
For a 3×3 matrix
(source: wolfram.com)
the matrix inverse is
(source: wolfram.com)
I'm assuming you know what the determinant of a matrix |A| is.
Images (c) Wolfram|Alpha and
mathworld.wolfram (06-11-09,
22.06)
With all due respect to our unknown (yahoo) poster, I look at code like that and just die a little inside. Alphabet soup is just so insanely difficult to debug. A single typo anywhere in there can really ruin your whole day. Sadly, this particular example lacked variables with underscores. It's so much more fun when we have a_b-c_d*e_f-g_h. Especially when using a font where _ and - have the same pixel length.
Taking up Suvesh Pratapa on his suggestion, I note:
Given 3x3 matrix:
y0x0 y0x1 y0x2
y1x0 y1x1 y1x2
y2x0 y2x1 y2x2
Declared as double matrix [/*Y=*/3] [/*X=*/3];
(A) When taking a minor of a 3x3 array, we have 4 values of interest. The lower X/Y index is always 0 or 1. The higher X/Y index is always 1 or 2. Always! Therefore:
double determinantOfMinor( int theRowHeightY,
int theColumnWidthX,
const double theMatrix [/*Y=*/3] [/*X=*/3] )
{
int x1 = theColumnWidthX == 0 ? 1 : 0; /* always either 0 or 1 */
int x2 = theColumnWidthX == 2 ? 1 : 2; /* always either 1 or 2 */
int y1 = theRowHeightY == 0 ? 1 : 0; /* always either 0 or 1 */
int y2 = theRowHeightY == 2 ? 1 : 2; /* always either 1 or 2 */
return ( theMatrix [y1] [x1] * theMatrix [y2] [x2] )
- ( theMatrix [y1] [x2] * theMatrix [y2] [x1] );
}
(B) Determinant is now: (Note the minus sign!)
double determinant( const double theMatrix [/*Y=*/3] [/*X=*/3] )
{
return ( theMatrix [0] [0] * determinantOfMinor( 0, 0, theMatrix ) )
- ( theMatrix [0] [1] * determinantOfMinor( 0, 1, theMatrix ) )
+ ( theMatrix [0] [2] * determinantOfMinor( 0, 2, theMatrix ) );
}
(C) And the inverse is now:
bool inverse( const double theMatrix [/*Y=*/3] [/*X=*/3],
double theOutput [/*Y=*/3] [/*X=*/3] )
{
double det = determinant( theMatrix );
/* Arbitrary for now. This should be something nicer... */
if ( ABS(det) < 1e-2 )
{
memset( theOutput, 0, sizeof theOutput );
return false;
}
double oneOverDeterminant = 1.0 / det;
for ( int y = 0; y < 3; y ++ )
for ( int x = 0; x < 3; x ++ )
{
/* Rule is inverse = 1/det * minor of the TRANSPOSE matrix. *
* Note (y,x) becomes (x,y) INTENTIONALLY here! */
theOutput [y] [x]
= determinantOfMinor( x, y, theMatrix ) * oneOverDeterminant;
/* (y0,x1) (y1,x0) (y1,x2) and (y2,x1) all need to be negated. */
if( 1 == ((x + y) % 2) )
theOutput [y] [x] = - theOutput [y] [x];
}
return true;
}
And round it out with a little lower-quality testing code:
void printMatrix( const double theMatrix [/*Y=*/3] [/*X=*/3] )
{
for ( int y = 0; y < 3; y ++ )
{
cout << "[ ";
for ( int x = 0; x < 3; x ++ )
cout << theMatrix [y] [x] << " ";
cout << "]" << endl;
}
cout << endl;
}
void matrixMultiply( const double theMatrixA [/*Y=*/3] [/*X=*/3],
const double theMatrixB [/*Y=*/3] [/*X=*/3],
double theOutput [/*Y=*/3] [/*X=*/3] )
{
for ( int y = 0; y < 3; y ++ )
for ( int x = 0; x < 3; x ++ )
{
theOutput [y] [x] = 0;
for ( int i = 0; i < 3; i ++ )
theOutput [y] [x] += theMatrixA [y] [i] * theMatrixB [i] [x];
}
}
int
main(int argc, char **argv)
{
if ( argc > 1 )
SRANDOM( atoi( argv[1] ) );
double m[3][3] = { { RANDOM_D(0,1e3), RANDOM_D(0,1e3), RANDOM_D(0,1e3) },
{ RANDOM_D(0,1e3), RANDOM_D(0,1e3), RANDOM_D(0,1e3) },
{ RANDOM_D(0,1e3), RANDOM_D(0,1e3), RANDOM_D(0,1e3) } };
double o[3][3], mm[3][3];
if ( argc <= 2 )
cout << fixed << setprecision(3);
printMatrix(m);
cout << endl << endl;
SHOW( determinant(m) );
cout << endl << endl;
BOUT( inverse(m, o) );
printMatrix(m);
printMatrix(o);
cout << endl << endl;
matrixMultiply (m, o, mm );
printMatrix(m);
printMatrix(o);
printMatrix(mm);
cout << endl << endl;
}
Afterthought:
You may also want to detect very large determinants as round-off errors will affect your accuracy!
Don't try to do this yourself if you're serious about getting edge cases right. So while they many naive/simple methods are theoretically exact, they can have nasty numerical behavior for nearly singular matrices. In particular you can get cancelation/round-off errors that cause you to get arbitrarily bad results.
A "correct" way is Gaussian elimination with row and column pivoting so that you're always dividing by the largest remaining numerical value. (This is also stable for NxN matrices.). Note that row pivoting alone doesn't catch all the bad cases.
However IMO implementing this right and fast is not worth your time - use a well tested library and there are a heap of header only ones.
I have just created a QMatrix class. It uses the built in vector > container. QMatrix.h
It uses the Jordan-Gauss method to compute the inverse of a square matrix.
You can use it as follows:
#include "QMatrix.h"
#include <iostream>
int main(){
QMatrix<double> A(3,3,true);
QMatrix<double> Result = A.inverse()*A; //should give the idendity matrix
std::cout<<A.inverse()<<std::endl;
std::cout<<Result<<std::endl; // for checking
return 0;
}
The inverse function is implemented as follows:
Given a class with the following fields:
template<class T> class QMatrix{
public:
int rows, cols;
std::vector<std::vector<T> > A;
the inverse() function:
template<class T>
QMatrix<T> QMatrix<T>:: inverse(){
Identity<T> Id(rows); //the Identity Matrix as a subclass of QMatrix.
QMatrix<T> Result = *this; // making a copy and transforming it to the Identity matrix
T epsilon = 0.000001;
for(int i=0;i<rows;++i){
//check if Result(i,i)==0, if true, switch the row with another
for(int j=i;j<rows;++j){
if(std::abs(Result(j,j))<epsilon) { //uses Overloading()(int int) to extract element from Result Matrix
Result.replace_rows(i,j+1); //switches rows i with j+1
}
else break;
}
// main part, making a triangular matrix
Id(i)=Id(i)*(1.0/Result(i,i));
Result(i)=Result(i)*(1.0/Result(i,i)); // Using overloading ()(int) to get a row form the matrix
for(int j=i+1;j<rows;++j){
T temp = Result(j,i);
Result(j) = Result(j) - Result(i)*temp;
Id(j) = Id(j) - Id(i)*temp; //doing the same operations to the identity matrix
Result(j,i)=0; //not necessary, but looks nicer than 10^-15
}
}
// solving a triangular matrix
for(int i=rows-1;i>0;--i){
for(int j=i-1;j>=0;--j){
T temp = Result(j,i);
Id(j) = Id(j) - temp*Id(i);
Result(j)=Result(j)-temp*Result(i);
}
}
return Id;
}
A rather nice (I think) header file containing macros for most 2x2, 3x3 and 4x4 matrix operations has been available with most OpenGL toolkits. Not as standard but I've seen it at various places.
You can check it out here. At the end of it you will find both inverse of 2x2, 3x3 and 4x4.
vvector.h
I would also recommend Ilmbase, which is part of OpenEXR. It's a good set of templated 2,3,4-vector and matrix routines.
# include <conio.h>
# include<iostream.h>
const int size = 9;
int main()
{
char ch;
do
{
clrscr();
int i, j, x, y, z, det, a[size], b[size];
cout << " **** MATRIX OF 3x3 ORDER ****"
<< endl
<< endl
<< endl;
for (i = 0; i <= size; i++)
a[i]=0;
for (i = 0; i < size; i++)
{
cout << "Enter "
<< i + 1
<< " element of matrix=";
cin >> a[i];
cout << endl
<<endl;
}
clrscr();
cout << "your entered matrix is "
<< endl
<<endl;
for (i = 0; i < size; i += 3)
cout << a[i]
<< " "
<< a[i+1]
<< " "
<< a[i+2]
<< endl
<<endl;
cout << "Transpose of given matrix is"
<< endl
<< endl;
for (i = 0; i < 3; i++)
cout << a[i]
<< " "
<< a[i+3]
<< " "
<< a[i+6]
<< endl
<< endl;
cout << "Determinent of given matrix is = ";
x = a[0] * (a[4] * a[8] -a [5] * a[7]);
y = a[1] * (a[3] * a[8] -a [5] * a[6]);
z = a[2] * (a[3] * a[7] -a [4] * a[6]);
det = x - y + z;
cout << det
<< endl
<< endl
<< endl
<< endl;
if (det == 0)
{
cout << "As Determinent=0 so it is singular matrix and its inverse cannot exist"
<< endl
<< endl;
goto quit;
}
b[0] = a[4] * a[8] - a[5] * a[7];
b[1] = a[5] * a[6] - a[3] * a[8];
b[2] = a[3] * a[7] - a[4] * a[6];
b[3] = a[2] * a[7] - a[1] * a[8];
b[4] = a[0] * a[8] - a[2] * a[6];
b[5] = a[1] * a[6] - a[0] * a[7];
b[6] = a[1] * a[5] - a[2] * a[4];
b[7] = a[2] * a[3] - a[0] * a[5];
b[8] = a[0] * a[4] - a[1] * a[3];
cout << "Adjoint of given matrix is"
<< endl
<< endl;
for (i = 0; i < 3; i++)
{
cout << b[i]
<< " "
<< b[i+3]
<< " "
<< b[i+6]
<< endl
<<endl;
}
cout << endl
<<endl;
cout << "Inverse of given matrix is "
<< endl
<< endl
<< endl;
for (i = 0; i < 3; i++)
{
cout << b[i]
<< "/"
<< det
<< " "
<< b[i+3]
<< "/"
<< det
<< " "
<< b[i+6]
<< "/"
<< det
<< endl
<<endl;
}
quit:
cout << endl
<< endl;
cout << "Do You want to continue this again press (y/yes,n/no)";
cin >> ch;
cout << endl
<< endl;
} /* end do */
while (ch == 'y');
getch ();
return 0;
}
#include <iostream>
using namespace std;
int main()
{
double A11, A12, A13;
double A21, A22, A23;
double A31, A32, A33;
double B11, B12, B13;
double B21, B22, B23;
double B31, B32, B33;
cout << "Enter all number from left to right, from top to bottom, and press enter after every number: ";
cin >> A11;
cin >> A12;
cin >> A13;
cin >> A21;
cin >> A22;
cin >> A23;
cin >> A31;
cin >> A32;
cin >> A33;
B11 = 1 / ((A22 * A33) - (A23 * A32));
B12 = 1 / ((A13 * A32) - (A12 * A33));
B13 = 1 / ((A12 * A23) - (A13 * A22));
B21 = 1 / ((A23 * A31) - (A21 * A33));
B22 = 1 / ((A11 * A33) - (A13 * A31));
B23 = 1 / ((A13 * A21) - (A11 * A23));
B31 = 1 / ((A21 * A32) - (A22 * A31));
B32 = 1 / ((A12 * A31) - (A11 * A32));
B33 = 1 / ((A11 * A22) - (A12 * A21));
cout << B11 << "\t" << B12 << "\t" << B13 << endl;
cout << B21 << "\t" << B22 << "\t" << B23 << endl;
cout << B31 << "\t" << B32 << "\t" << B33 << endl;
return 0;
}
//Title: Matrix Header File
//Writer: Say OL
//This is a beginner code not an expert one
//No responsibilty for any errors
//Use for your own risk
using namespace std;
int row,col,Row,Col;
double Coefficient;
//Input Matrix
void Input(double Matrix[9][9],int Row,int Col)
{
for(row=1;row<=Row;row++)
for(col=1;col<=Col;col++)
{
cout<<"e["<<row<<"]["<<col<<"]=";
cin>>Matrix[row][col];
}
}
//Output Matrix
void Output(double Matrix[9][9],int Row,int Col)
{
for(row=1;row<=Row;row++)
{
for(col=1;col<=Col;col++)
cout<<Matrix[row][col]<<"\t";
cout<<endl;
}
}
//Copy Pointer to Matrix
void CopyPointer(double (*Pointer)[9],double Matrix[9][9],int Row,int Col)
{
for(row=1;row<=Row;row++)
for(col=1;col<=Col;col++)
Matrix[row][col]=Pointer[row][col];
}
//Copy Matrix to Matrix
void CopyMatrix(double MatrixInput[9][9],double MatrixTarget[9][9],int Row,int Col)
{
for(row=1;row<=Row;row++)
for(col=1;col<=Col;col++)
MatrixTarget[row][col]=MatrixInput[row][col];
}
//Transpose of Matrix
double MatrixTran[9][9];
double (*(Transpose)(double MatrixInput[9][9],int Row,int Col))[9]
{
for(row=1;row<=Row;row++)
for(col=1;col<=Col;col++)
MatrixTran[col][row]=MatrixInput[row][col];
return MatrixTran;
}
//Matrix Addition
double MatrixAdd[9][9];
double (*(Addition)(double MatrixA[9][9],double MatrixB[9][9],int Row,int Col))[9]
{
for(row=1;row<=Row;row++)
for(col=1;col<=Col;col++)
MatrixAdd[row][col]=MatrixA[row][col]+MatrixB[row][col];
return MatrixAdd;
}
//Matrix Subtraction
double MatrixSub[9][9];
double (*(Subtraction)(double MatrixA[9][9],double MatrixB[9][9],int Row,int Col))[9]
{
for(row=1;row<=Row;row++)
for(col=1;col<=Col;col++)
MatrixSub[row][col]=MatrixA[row][col]-MatrixB[row][col];
return MatrixSub;
}
//Matrix Multiplication
int mRow,nCol,pCol,kcol;
double MatrixMult[9][9];
double (*(Multiplication)(double MatrixA[9][9],double MatrixB[9][9],int mRow,int nCol,int pCol))[9]
{
for(row=1;row<=mRow;row++)
for(col=1;col<=pCol;col++)
{
MatrixMult[row][col]=0.0;
for(kcol=1;kcol<=nCol;kcol++)
MatrixMult[row][col]+=MatrixA[row][kcol]*MatrixB[kcol][col];
}
return MatrixMult;
}
//Interchange Two Rows
double RowTemp[9][9];
double MatrixInter[9][9];
double (*(InterchangeRow)(double MatrixInput[9][9],int Row,int Col,int iRow,int jRow))[9]
{
CopyMatrix(MatrixInput,MatrixInter,Row,Col);
for(col=1;col<=Col;col++)
{
RowTemp[iRow][col]=MatrixInter[iRow][col];
MatrixInter[iRow][col]=MatrixInter[jRow][col];
MatrixInter[jRow][col]=RowTemp[iRow][col];
}
return MatrixInter;
}
//Pivote Downward
double MatrixDown[9][9];
double (*(PivoteDown)(double MatrixInput[9][9],int Row,int Col,int tRow,int tCol))[9]
{
CopyMatrix(MatrixInput,MatrixDown,Row,Col);
Coefficient=MatrixDown[tRow][tCol];
if(Coefficient!=1.0)
for(col=1;col<=Col;col++)
MatrixDown[tRow][col]/=Coefficient;
if(tRow<Row)
for(row=tRow+1;row<=Row;row++)
{
Coefficient=MatrixDown[row][tCol];
for(col=1;col<=Col;col++)
MatrixDown[row][col]-=Coefficient*MatrixDown[tRow][col];
}
return MatrixDown;
}
//Pivote Upward
double MatrixUp[9][9];
double (*(PivoteUp)(double MatrixInput[9][9],int Row,int Col,int tRow,int tCol))[9]
{
CopyMatrix(MatrixInput,MatrixUp,Row,Col);
Coefficient=MatrixUp[tRow][tCol];
if(Coefficient!=1.0)
for(col=1;col<=Col;col++)
MatrixUp[tRow][col]/=Coefficient;
if(tRow>1)
for(row=tRow-1;row>=1;row--)
{
Coefficient=MatrixUp[row][tCol];
for(col=1;col<=Col;col++)
MatrixUp[row][col]-=Coefficient*MatrixUp[tRow][col];
}
return MatrixUp;
}
//Pivote in Determinant
double MatrixPiv[9][9];
double (*(Pivote)(double MatrixInput[9][9],int Dim,int pTarget))[9]
{
CopyMatrix(MatrixInput,MatrixPiv,Dim,Dim);
for(row=pTarget+1;row<=Dim;row++)
{
Coefficient=MatrixPiv[row][pTarget]/MatrixPiv[pTarget][pTarget];
for(col=1;col<=Dim;col++)
{
MatrixPiv[row][col]-=Coefficient*MatrixPiv[pTarget][col];
}
}
return MatrixPiv;
}
//Determinant of Square Matrix
int dCounter,dRow;
double Det;
double MatrixDet[9][9];
double Determinant(double MatrixInput[9][9],int Dim)
{
CopyMatrix(MatrixInput,MatrixDet,Dim,Dim);
Det=1.0;
if(Dim>1)
{
for(dRow=1;dRow<Dim;dRow++)
{
dCounter=dRow;
while((MatrixDet[dRow][dRow]==0.0)&(dCounter<=Dim))
{
dCounter++;
Det*=-1.0;
CopyPointer(InterchangeRow(MatrixDet,Dim,Dim,dRow,dCounter),MatrixDet,Dim,Dim);
}
if(MatrixDet[dRow][dRow]==0)
{
Det=0.0;
break;
}
else
{
Det*=MatrixDet[dRow][dRow];
CopyPointer(Pivote(MatrixDet,Dim,dRow),MatrixDet,Dim,Dim);
}
}
Det*=MatrixDet[Dim][Dim];
}
else Det=MatrixDet[1][1];
return Det;
}
//Matrix Identity
double MatrixIdent[9][9];
double (*(Identity)(int Dim))[9]
{
for(row=1;row<=Dim;row++)
for(col=1;col<=Dim;col++)
if(row==col)
MatrixIdent[row][col]=1.0;
else
MatrixIdent[row][col]=0.0;
return MatrixIdent;
}
//Join Matrix to be Augmented Matrix
double MatrixJoin[9][9];
double (*(JoinMatrix)(double MatrixA[9][9],double MatrixB[9][9],int Row,int ColA,int ColB))[9]
{
Col=ColA+ColB;
for(row=1;row<=Row;row++)
for(col=1;col<=Col;col++)
if(col<=ColA)
MatrixJoin[row][col]=MatrixA[row][col];
else
MatrixJoin[row][col]=MatrixB[row][col-ColA];
return MatrixJoin;
}
//Inverse of Matrix
double (*Pointer)[9];
double IdentMatrix[9][9];
int Counter;
double MatrixAug[9][9];
double MatrixInv[9][9];
double (*(Inverse)(double MatrixInput[9][9],int Dim))[9]
{
Row=Dim;
Col=Dim+Dim;
Pointer=Identity(Dim);
CopyPointer(Pointer,IdentMatrix,Dim,Dim);
Pointer=JoinMatrix(MatrixInput,IdentMatrix,Dim,Dim,Dim);
CopyPointer(Pointer,MatrixAug,Row,Col);
for(Counter=1;Counter<=Dim;Counter++)
{
Pointer=PivoteDown(MatrixAug,Row,Col,Counter,Counter);
CopyPointer(Pointer,MatrixAug,Row,Col);
}
for(Counter=Dim;Counter>1;Counter--)
{
Pointer=PivoteUp(MatrixAug,Row,Col,Counter,Counter);
CopyPointer(Pointer,MatrixAug,Row,Col);
}
for(row=1;row<=Dim;row++)
for(col=1;col<=Dim;col++)
MatrixInv[row][col]=MatrixAug[row][col+Dim];
return MatrixInv;
}
//Gauss-Jordan Elemination
double MatrixGJ[9][9];
double VectorGJ[9][9];
double (*(GaussJordan)(double MatrixInput[9][9],double VectorInput[9][9],int Dim))[9]
{
Row=Dim;
Col=Dim+1;
Pointer=JoinMatrix(MatrixInput,VectorInput,Dim,Dim,1);
CopyPointer(Pointer,MatrixGJ,Row,Col);
for(Counter=1;Counter<=Dim;Counter++)
{
Pointer=PivoteDown(MatrixGJ,Row,Col,Counter,Counter);
CopyPointer(Pointer,MatrixGJ,Row,Col);
}
for(Counter=Dim;Counter>1;Counter--)
{
Pointer=PivoteUp(MatrixGJ,Row,Col,Counter,Counter);
CopyPointer(Pointer,MatrixGJ,Row,Col);
}
for(row=1;row<=Dim;row++)
for(col=1;col<=1;col++)
VectorGJ[row][col]=MatrixGJ[row][col+Dim];
return VectorGJ;
}
//Generalized Gauss-Jordan Elemination
double MatrixGGJ[9][9];
double VectorGGJ[9][9];
double (*(GeneralizedGaussJordan)(double MatrixInput[9][9],double VectorInput[9][9],int Dim,int vCol))[9]
{
Row=Dim;
Col=Dim+vCol;
Pointer=JoinMatrix(MatrixInput,VectorInput,Dim,Dim,vCol);
CopyPointer(Pointer,MatrixGGJ,Row,Col);
for(Counter=1;Counter<=Dim;Counter++)
{
Pointer=PivoteDown(MatrixGGJ,Row,Col,Counter,Counter);
CopyPointer(Pointer,MatrixGGJ,Row,Col);
}
for(Counter=Dim;Counter>1;Counter--)
{
Pointer=PivoteUp(MatrixGGJ,Row,Col,Counter,Counter);
CopyPointer(Pointer,MatrixGGJ,Row,Col);
}
for(row=1;row<=Row;row++)
for(col=1;col<=vCol;col++)
VectorGGJ[row][col]=MatrixGGJ[row][col+Dim];
return VectorGGJ;
}
//Matrix Sparse, Three Diagonal Non-Zero Elements
double MatrixSpa[9][9];
double (*(Sparse)(int Dimension,double FirstElement,double SecondElement,double ThirdElement))[9]
{
MatrixSpa[1][1]=SecondElement;
MatrixSpa[1][2]=ThirdElement;
MatrixSpa[Dimension][Dimension-1]=FirstElement;
MatrixSpa[Dimension][Dimension]=SecondElement;
for(int Counter=2;Counter<Dimension;Counter++)
{
MatrixSpa[Counter][Counter-1]=FirstElement;
MatrixSpa[Counter][Counter]=SecondElement;
MatrixSpa[Counter][Counter+1]=ThirdElement;
}
return MatrixSpa;
}
Copy and save the above code as Matrix.h then try the following code:
#include<iostream>
#include<conio.h>
#include"Matrix.h"
int Dim;
double Matrix[9][9];
int main()
{
cout<<"Enter your matrix dimension: ";
cin>>Dim;
Input(Matrix,Dim,Dim);
cout<<"Your matrix:"<<endl;
Output(Matrix,Dim,Dim);
cout<<"The inverse:"<<endl;
Output(Inverse(Matrix,Dim),Dim,Dim);
getch();
}
//Function for inverse of the input square matrix 'J' of dimension 'dim':
vector<vector<double > > inverseVec33(vector<vector<double > > J, int dim)
{
//Matrix of Minors
vector<vector<double > > invJ(dim,vector<double > (dim));
for(int i=0; i<dim; i++)
{
for(int j=0; j<dim; j++)
{
invJ[i][j] = (J[(i+1)%dim][(j+1)%dim]*J[(i+2)%dim][(j+2)%dim] -
J[(i+2)%dim][(j+1)%dim]*J[(i+1)%dim][(j+2)%dim]);
}
}
//determinant of the matrix:
double detJ = 0.0;
for(int j=0; j<dim; j++)
{ detJ += J[0][j]*invJ[0][j];}
//Inverse of the given matrix.
vector<vector<double > > invJT(dim,vector<double > (dim));
for(int i=0; i<dim; i++)
{
for(int j=0; j<dim; j++)
{
invJT[i][j] = invJ[j][i]/detJ;
}
}
return invJT;
}
void main()
{
//given matrix:
vector<vector<double > > Jac(3,vector<double > (3));
Jac[0][0] = 1; Jac[0][1] = 2; Jac[0][2] = 6;
Jac[1][0] = -3; Jac[1][1] = 4; Jac[1][2] = 3;
Jac[2][0] = 5; Jac[2][1] = 1; Jac[2][2] = -4;`
//Inverse of the matrix Jac:
vector<vector<double > > JacI(3,vector<double > (3));
//call function and store inverse of J as JacI:
JacI = inverseVec33(Jac,3);
}