Unexpected Output for calculating a matrix's exponent - c++
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();
}
Related
How do I find the average of a column in a list?
I have a list of vectors currently, stored as a std::list<Vec3f> unsortedRays; -4.5 4.5 -8.66025 -3.5 4.5 -8.66025 -2.5 4.5 -8.66025 -1.5 4.5 -8.66025 -0.5 4.5 -8.66025 I'm generating these earlier in the program and can calculate the size beforehand (or after too). How do I find the average of each column (0, 1, 2)? In Python, I can do: x_avg = np.mean(column(list, 0)) y_avg = np.mean(column(list, 1)) z_avg = np.mean(column(list, 2)) I have tried the answer here but haven't been able to get it to work so far. Edit: Here's what I have so far in my simple.cpp file: std::list<Vec3f> unsortedRays; void generateRays() { for (size_t y = 0; y < height; ++y) { for (size_t x = 0; x < width; ++x) { Vec3f direction; float dir_x = (x + 0.5) - width/2.; float dir_y = -(y + 0.5) + height/2.; float dir_z = -height/(2.*tan(fov/2.)); direction = Vec3f(dir_x, dir_y, dir_z); unsortedRays.push_back (direction); } } } static void sortRays() { const int rows = width * height, columns = 3; std::vector<double> matrix; double sum=0; for (auto const& i : unsortedRays) { // for each row //std::vector<double> row; //row.push_back[i]; for (unsigned int j = 0; j < columns; ++j) { // for each column, or "value" double value = i[j]; //std::cout << value; matrix.push_back (value); sum += value; //std::cout << "sum: " << sum << "\n"; } } const double quantity = unsortedRays.size(); const double average = sum / quantity; std::cout << "average: " << average << "\n"; }
You could do something like this: std::vector<std::vector<double>> matrix; double c1, c2, c3; double sum1=0.0, sum2=0.0, sum3=0.0; while (my_file >> c1 >> c2 >> c3) { std::vector<double> row; row.push_back(c1); row.push_back(c2); row.push_back(c3); matrix.push_back(row); sum1 += c1; sum2 += c2; sum3 += c3; } const double quantity = matrix.size(); const double average_c1 = sum1 / quantity; const double average_c2 = sum2 / quantity; const double average_c3 = sum3 / quantity; The above code calculates the sum of each column as the data is read, and stores the values into a matrix. The average of each column is calculated using the sum variables for the appropriate column and the amount of data read in.
How to improve memory management for matrix multiplication
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.
How to find coefficients of polynomial equation?
Given two points in the x, y plane: x, f(x) 1, 3 2, 5 I can interpolate them using Lagrange and find f(1.5), which result in 4. Thinking a little I managed to find a way to discover the coefficients of the equation: void l1Coefficients(const vector<double> &x, const vector<double> &y) { double a0 = y[0]/(x[0]-x[1]); double a1 = y[1]/(x[1]-x[0]); double b0 = (-x[1]*y[0])/(x[0]-x[1]); double b1 = (-x[0]*y[1])/(x[1]-x[0]); double a = a0 + a1; double b = b0 + b1; cout << "P1(x) = " << a << "x +" << b << endl; } That gives me P1(x) = 2x +1. Thinking a little more I was able to extend that to 2nd order equations. So, given the points: 1, 1 2, 4 3, 9 I found the equation P2(x) = 1x^2 +0x +0 with the following: void l2Coefficients(const vector<double> &x, const vector<double> &y) { double a0 = y[0] / ((x[0]-x[1])*(x[0]-x[2])); double a1 = y[1] / ((x[1]-x[0])*(x[1]-x[2])); double a2 = y[2] / ((x[2]-x[0])*(x[2]-x[1])); double b0 = -(x[1]+x[2])*y[0] / ((x[0]-x[1])*(x[0]-x[2])); double b1 = -(x[0]+x[2])*y[1] / ((x[1]-x[0])*(x[1]-x[2])); double b2 = -(x[0]+x[1])*y[2] / ((x[2]-x[0])*(x[2]-x[1])); double c0 = (x[1]*x[2])*y[0] / ((x[0]-x[1])*(x[0]-x[2])); double c1 = (x[0]*x[2])*y[1] / ((x[1]-x[0])*(x[1]-x[2])); double c2 = (x[0]*x[1])*y[2] / ((x[2]-x[0])*(x[2]-x[1])); double a = a0 + a1 + a2; double b = b0 + b1 + b2; double c = c0 + c1 + c2; cout << "P2(x) = " << a << "x^2 +" << b << "x +" << c << endl; } Working hard I actually was able to find the coefficients for equations of order up to 4th. How to find the coefficients of order n equations? Where Pn(x) = c_2x^2 + c_1x^1 + c_0x^0 + ...
It's a simple linear algebra problem. We have a set of N samples of the form xk -> f(xk) and we know the general form of function f(x), which is: f(x) = c0x0 + c1x1 + ... + cN-1xN-1 We want to find the coefficients c0 ... cN-1. To achieve that, we build a system of N equations of the form: c0xk0 + c1xk1 + ... + cN-1xkN-1 = f(xk) where k is the sample number. Since xk and f(xk) are constants rather than variables, we have a linear system of equations. Expressed in terms of linear algebra, we have to solve: Ac = b where A is a Vandermonde matrix of powers of x and b is a vector of f(xk) values. To solve such a system, you need a linear algebra library, such as Eigen. See here for example code. The only thing that can go wrong with such an approach is the system of linear equations being under-determined, which will happen if your N samples can be fit with with a polynomial of degree less than N-1. In such a case you can still solve this system with Moore-Penrose pseudo inverse like this: c = pinv(A)*b Unfortunately, Eigen doesn't have a pinv() implementation, though it's pretty easy to code it by yourself in terms of Singular Value Decomposition (SVD).
I created a naive implementation of the matrix solution: #include <iostream> #include <vector> #include <stdexcept> class Matrix { private: class RowIterator { public: RowIterator(Matrix* mat, int rowNum) :_mat(mat), _rowNum(rowNum) {} double& operator[] (int colNum) { return _mat->_data[_rowNum*_mat->_sizeX + colNum]; } private: Matrix* _mat; int _rowNum; }; int _sizeY, _sizeX; std::vector<double> _data; public: Matrix(int sizeY, int sizeX) : _sizeY(sizeY), _sizeX(sizeX), _data(_sizeY*_sizeX){} Matrix(std::vector<std::vector<double> > initList) : _sizeY(initList.size()), _sizeX(_sizeY>0 ? initList.begin()->size() : 0), _data() { _data.reserve(_sizeY*_sizeX); for (const std::vector<double>& list : initList) { _data.insert(_data.end(), list.begin(), list.end()); } } RowIterator operator[] (int rowNum) { return RowIterator(this, rowNum); } int getSize() { return _sizeX*_sizeY; } int getSizeX() { return _sizeX; } int getSizeY() { return _sizeY; } Matrix reduce(int rowNum, int colNum) { Matrix mat(_sizeY-1, _sizeX-1); int rowRem = 0; for (int y = 0; y < _sizeY; y++) { if (rowNum == y) { rowRem = 1; continue; } int colRem = 0; for (int x = 0; x < _sizeX; x++) { if (colNum == x) { colRem = 1; continue; } mat[y - rowRem][x - colRem] = (*this)[y][x]; } } return mat; } Matrix replaceCol(int colNum, std::vector<double> newCol) { Matrix mat = *this; for (int y = 0; y < _sizeY; y++) { mat[y][colNum] = newCol[y]; } return mat; } }; double solveMatrix(Matrix mat) { if (mat.getSizeX() != mat.getSizeY()) throw std::invalid_argument("Not square matrix"); if (mat.getSize() > 1) { double sum = 0.0; int sign = 1; for (int x = 0; x < mat.getSizeX(); x++) { sum += sign * mat[0][x] * solveMatrix(mat.reduce(0, x)); sign = -sign; } return sum; } return mat[0][0]; } std::vector<double> solveEq(std::vector< std::pair<double, double> > points) { std::vector<std::vector<double> > xes(points.size()); for (int i = 0; i<points.size(); i++) { xes[i].push_back(1); for (int j = 1; j<points.size(); j++) { xes[i].push_back(xes[i].back() * points[i].first); } } Matrix mat(xes); std::vector<double> ys(points.size()); for (int i = 0; i < points.size(); i++) { ys[i] = points[i].second; } double w = solveMatrix(mat); std::vector<double> result(points.size(), 0.0); if(w!=0) for (int i = 0; i < ys.size(); i++) { result[i] = solveMatrix(mat.replaceCol(i, ys)); result[i] /= w; } return result; } void printCoe(std::vector<double> coe) { std::cout << "f(x)="; bool notFirstSign = false; for (int i = coe.size() - 1; i >= 0; i--) { if (coe[i] != 0.0) { if (coe[i] >= 0.0 && notFirstSign) std::cout << "+"; notFirstSign = true; if (coe[i] != 1.0) if (coe[i] == -1.0) std::cout << "-"; else std::cout << coe[i]; if (i == 1) std::cout << "x"; if (i>1) std::cout << "x^" << i; } } std::cout << std::endl; } int main() { std::vector< std::pair<double, double> > points1 = { {3,31}, {6,94}, {4,48}, {0,4} }; std::vector<double> coe = solveEq(points1); printCoe(coe); std::vector< std::pair<double, double> > points2 = { { 0,0 },{ 1,-1 },{ 2,-16 },{ 3,-81 },{ 4,-256 } }; printCoe(solveEq(points2)); printCoe(solveEq({ { 0,0 },{ 1,1 },{ 2,8 },{ 3,27 } })); std::cin.ignore(); return 0; }
Gradient descent converging towards the wrong value
I'm trying to implement a gradient descent algorithm in C++. Here's the code I have so far : #include <iostream> double X[] {163,169,158,158,161,172,156,161,154,145}; double Y[] {52, 68, 49, 73, 71, 99, 50, 82, 56, 46 }; double m, p; int n = sizeof(X)/sizeof(X[0]); int main(void) { double alpha = 0.00004; // 0.00007; m = (Y[1] - Y[0]) / (X[1] - X[0]); p = Y[0] - m * X[0]; for (int i = 1; i <= 8; i++) { gradientStep(alpha); } return 0; } double Loss_function(void) { double res = 0; double tmp; for (int i = 0; i < n; i++) { tmp = Y[i] - m * X[i] - p; res += tmp * tmp; } return res / 2.0 / (double)n; } void gradientStep(double alpha) { double pg = 0, mg = 0; for (int i = 0; i < n; i++) { pg += Y[i] - m * X[i] - p; mg += X[i] * (Y[i] - m * X[i] - p); } p += alpha * pg / n; m += alpha * mg / n; } This code converges towards m = 2.79822, p = -382.666, and an error of 102.88. But if I use my calculator to find out the correct linear regression model, I find that the correct values of m and p should respectively be 1.601 and -191.1. I also noticed that the algorithm won't converge for alpha > 0.00007, which seems quite low, and the value of p barely changes during the 8 iterations (or even after 2000 iterations). What's wrong with my code? Here's a good overview of the algorithm I'm trying to implement. The values of theta0 and theta1 are called p and m in my program. Other implementation in python More about the algorithm
This link gives a comprehensive view of the algorithm; it turns out I was following a completely wrong approach. The following code does not work properly (and I have no plans to work on it further), but should put on track anyone who's confronted to the same problem as me : #include <vector> #include <iostream> typedef std::vector<double> vect; std::vector<double> y, omega(2, 0), omega2(2, 0);; std::vector<std::vector<double>> X; int n = 10; int main(void) { /* Initialize x so that each members contains (1, x_i) */ /* Initialize x so that each members contains y_i */ double alpha = 0.00001; display(); for (int i = 1; i <= 8; i++) { gradientStep(alpha); display(); } return 0; } double f_function(const std::vector<double> &x) { double c; for (unsigned int i = 0; i < omega.size(); i++) { c += omega[i] * x[i]; } return c; } void gradientStep(double alpha) { for (int i = 0; i < n; i++) { for (unsigned int j = 0; j < X[0].size(); j++) { omega2[j] -= alpha/(double)n * (f_function(X[i]) - y[i]) * X[i][j]; } } omega = omega2; } void display(void) { double res = 0, tmp = 0; for (int i = 0; i < n; i++) { tmp = y[i] - f_function(X[i]); res += tmp * tmp; // Loss functionn } std::cout << "omega = "; for (unsigned int i = 0; i < omega.size(); i++) { std::cout << "[" << omega[i] << "] "; } std::cout << "\tError : " << res * .5/(double)n << std::endl; }
Trouble with a namespace in a header file, "undefined reference to" error?
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