621 lines
21 KiB
MQL5
621 lines
21 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| cmath.mqh |
|
||
|
|
//| Copyright 2025, MetaQuotes Ltd. |
|
||
|
|
//| https://www.mql5.com |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||
|
|
#property link "https://www.mql5.com"
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| utilities for working with complex numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| get real part from container of complex numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void real(complex& data[],double& out[])
|
||
|
|
{
|
||
|
|
// Resize the output array to match the source array size
|
||
|
|
ArrayResize(out,data.Size());
|
||
|
|
// Extract the real component element-by-element
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
out[i] = data[i].real;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| get imaginary part from container of complex numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void imaginary(complex& data[],double& out[])
|
||
|
|
{
|
||
|
|
// Resize the output array to match the source array size
|
||
|
|
ArrayResize(out,data.Size());
|
||
|
|
// Extract the imaginary component element-by-element
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
out[i] = data[i].imag;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| get real part from container of complex numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vector real(vectorc& data)
|
||
|
|
{
|
||
|
|
// Initialize an output vector of the same size with zeros
|
||
|
|
vector out=vector::Zeros(data.Size());
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
out[i] = data[i].real;
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| get imaginary part from container of complex numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vector imaginary(vectorc& data)
|
||
|
|
{
|
||
|
|
// Initialize an output vector of the same size with zeros
|
||
|
|
vector out=vector::Zeros(data.Size());
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
out[i] = data[i].imag;
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| get real part from container of complex numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrix real(matrixc& data)
|
||
|
|
{
|
||
|
|
// Initialize an output matrix matching dimensions with zeros
|
||
|
|
matrix out=matrix::Zeros(data.Rows(),data.Cols());
|
||
|
|
// Iterate through rows and columns to copy real values
|
||
|
|
for(ulong i = 0; i<out.Rows(); i++)
|
||
|
|
for(ulong j = 0; j<out.Cols(); j++)
|
||
|
|
out[i,j] = data[i,j].real;
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| get imaginary part from container of complex numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrix imaginary(matrixc& data)
|
||
|
|
{
|
||
|
|
// Initialize an output matrix matching dimensions with zeros
|
||
|
|
matrix out=matrix::Zeros(data.Rows(),data.Cols());
|
||
|
|
// Iterate through rows and columns to copy imaginary values
|
||
|
|
for(ulong i = 0; i<out.Rows(); i++)
|
||
|
|
for(ulong j = 0; j<out.Cols(); j++)
|
||
|
|
out[i,j] = data[i,j].imag;
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| create complex containers from real numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vectorc as_complex(vector& re,vector& im)
|
||
|
|
{
|
||
|
|
// Size output based on the largest input vector to prevent truncation
|
||
|
|
vectorc out = vectorc::Zeros(MathMax(re.Size(),im.Size()));
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
{
|
||
|
|
// Fallback to 0.0 if index exceeds the size of an uneven input vector
|
||
|
|
out[i].real = i<re.Size()?re[i]:0.0;
|
||
|
|
out[i].imag = i<im.Size()?im[i]:0.0;
|
||
|
|
}
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| create complex containers from real numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrixc as_complex(matrix& re,matrix& im)
|
||
|
|
{
|
||
|
|
// Size output based on the maximum bounds of both matrices
|
||
|
|
matrixc out = matrixc::Zeros((ulong)MathMax(re.Rows(),im.Rows()),(ulong)MathMax(re.Cols(),im.Cols()));
|
||
|
|
for(ulong i = 0; i<out.Rows(); i++)
|
||
|
|
{
|
||
|
|
for(ulong j = 0; j<out.Cols(); j++)
|
||
|
|
{
|
||
|
|
// Safely extract real and imaginary values within bound checks
|
||
|
|
out[i,j].real = (i<re.Rows() && j<re.Cols())?re[i,j]:0.0;
|
||
|
|
out[i,j].imag = (i<im.Rows() && j<im.Cols())?im[i,j]:0.0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| create complex containers from real numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vectorc as_complex(vector& re)
|
||
|
|
{
|
||
|
|
vectorc out = vectorc::Zeros(re.Size());
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
{
|
||
|
|
out[i].real = re[i];
|
||
|
|
out[i].imag = 0.0; // Imaginary part defaults to zero
|
||
|
|
}
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| create complex containers from real numbers |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrixc as_complex(matrix& re)
|
||
|
|
{
|
||
|
|
matrixc out = matrixc::Zeros(re.Rows(),re.Cols());
|
||
|
|
for(ulong i = 0; i<out.Rows(); i++)
|
||
|
|
{
|
||
|
|
for(ulong j = 0; j<out.Cols(); j++)
|
||
|
|
{
|
||
|
|
out[i,j].real = re[i,j];
|
||
|
|
out[i,j].imag = 0.0; // Imaginary part defaults to zero
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| struct for complex vectors |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
struct CComplexVector
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
// Unpack vectorc structured data into separate real and imaginary vectors
|
||
|
|
void to_real(vectorc& data)
|
||
|
|
{
|
||
|
|
im = re = vector::Zeros(data.Size());
|
||
|
|
for(ulong i = 0; i<data.Size(); i++)
|
||
|
|
{
|
||
|
|
re[i] = data[i].real;
|
||
|
|
im[i] = data[i].imag;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convert purely real vector input by initializing the imaginary vector to zero
|
||
|
|
void to_complex(vector& in)
|
||
|
|
{
|
||
|
|
im = vector::Zeros(in.Size());
|
||
|
|
re = in;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Unpack array of complex structures into internal real/imaginary vectors
|
||
|
|
void to_real(complex & data[])
|
||
|
|
{
|
||
|
|
im = re = vector::Zeros(data.Size());
|
||
|
|
for(uint i = 0; i<data.Size(); i++)
|
||
|
|
{
|
||
|
|
re[i] = data[i].real;
|
||
|
|
im[i] = data[i].imag;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convert double array input by initializing internal vectors and assigning values
|
||
|
|
void to_complex(double& in[])
|
||
|
|
{
|
||
|
|
re = im = vector::Zeros(in.Size());
|
||
|
|
re.Assign(in);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Reset vector allocations to zero size
|
||
|
|
void reset(void)
|
||
|
|
{
|
||
|
|
re = vector::Zeros(0);
|
||
|
|
im = vector::Zeros(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
public:
|
||
|
|
vector re; // Holds real parts
|
||
|
|
vector im; // Holds imaginary parts
|
||
|
|
|
||
|
|
// Default Constructor
|
||
|
|
CComplexVector(void)
|
||
|
|
{
|
||
|
|
re = vector::Zeros(0);
|
||
|
|
im = vector::Zeros(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Overloaded Constructors
|
||
|
|
CComplexVector(vectorc& complx) { to_real(complx); }
|
||
|
|
CComplexVector(vector& realv) { to_complex(realv); }
|
||
|
|
CComplexVector(CComplexVector& other)
|
||
|
|
{
|
||
|
|
re = other.re;
|
||
|
|
im = other.im;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Overloaded index operator to retrieve elements as a singular complex structure
|
||
|
|
complex operator[](ulong index)
|
||
|
|
{
|
||
|
|
complex out=0;
|
||
|
|
if(index<re.Size())
|
||
|
|
{
|
||
|
|
out.real = re[index];
|
||
|
|
out.imag = im[index];
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Print(__FUNCTION__, " invalid index ", index, " : container size ", re.Size());
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Assignment Operators
|
||
|
|
void operator=(vectorc& complex_vector) { to_real(complex_vector); }
|
||
|
|
void operator=(vector& real_vector) { to_complex(real_vector); }
|
||
|
|
void operator=(complex& complex_array[]) { to_real(complex_array); }
|
||
|
|
void operator=(double& real_array[]) { to_complex(real_array); }
|
||
|
|
|
||
|
|
// Convert back to native vectorc format
|
||
|
|
vectorc to_vector(void) { return as_complex(re,im); }
|
||
|
|
};
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| struct for complex matrices |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
struct CComplexMatrix
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
// Unpack matrixc structure into separate internal real and imaginary matrices
|
||
|
|
void to_real(matrixc& data)
|
||
|
|
{
|
||
|
|
im = re = matrix::Zeros(data.Rows(),data.Cols());
|
||
|
|
for(ulong i = 0; i<data.Rows(); i++)
|
||
|
|
{
|
||
|
|
for(ulong j = 0; j<data.Cols(); j++)
|
||
|
|
{
|
||
|
|
re[i,j] = data[i][j].real;
|
||
|
|
im[i,j] = data[i][j].imag;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convert purely real matrix input by zeroing out the imaginary matrix
|
||
|
|
void to_complex(matrix& in)
|
||
|
|
{
|
||
|
|
im = matrix::Zeros(in.Rows(),in.Cols());
|
||
|
|
re = in;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Clear memory footprint of internal matrices
|
||
|
|
void reset(void)
|
||
|
|
{
|
||
|
|
re = matrix::Zeros(0,0);
|
||
|
|
im = matrix::Zeros(0,0);
|
||
|
|
}
|
||
|
|
|
||
|
|
public:
|
||
|
|
matrix re; // Holds real matrix space
|
||
|
|
matrix im; // Holds imaginary matrix space
|
||
|
|
|
||
|
|
// Default Constructor
|
||
|
|
CComplexMatrix(void)
|
||
|
|
{
|
||
|
|
re = matrix::Zeros(0,0);
|
||
|
|
im = matrix::Zeros(0,0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Overloaded Constructors
|
||
|
|
CComplexMatrix(matrixc& complx) { to_real(complx); }
|
||
|
|
CComplexMatrix(matrix& realm) { to_complex(realm); }
|
||
|
|
CComplexMatrix(CComplexMatrix& other)
|
||
|
|
{
|
||
|
|
re = other.re;
|
||
|
|
im = other.im;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Safe element retrieval at explicit row/column coordinates
|
||
|
|
complex At(ulong row_index,ulong column_index)
|
||
|
|
{
|
||
|
|
complex out = 0;
|
||
|
|
if(row_index<re.Rows() && column_index<re.Cols())
|
||
|
|
{
|
||
|
|
out.real = re[row_index,column_index];
|
||
|
|
out.imag = im[row_index,column_index];
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Print(__FUNCTION__, " invalid row or column index ", " container rows ", re.Rows(), " container columns ", re.Cols());
|
||
|
|
return complex(0.0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Assignment Operators
|
||
|
|
void operator=(matrixc& complex_matrix) { to_real(complex_matrix); }
|
||
|
|
void operator=(matrix& real_matrix) { to_complex(real_matrix); }
|
||
|
|
|
||
|
|
// Convert back to native matrixc format
|
||
|
|
matrixc to_matrix(void) { return as_complex(re,im); }
|
||
|
|
};
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| power of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
complex c_pow(complex base, complex exponent)
|
||
|
|
{
|
||
|
|
// Calculated via identity: base^exponent = exp(exponent * ln(base))
|
||
|
|
return c_exp(exponent*c_log(base));
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| simple power of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vectorc c_pow(vectorc &vect, complex exponent)
|
||
|
|
{
|
||
|
|
vectorc out(vect.Size());
|
||
|
|
for(ulong i = 0; i<vect.Size(); i++)
|
||
|
|
out[i] = c_pow(vect[i],exponent);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| simple power of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrixc c_pow(matrixc &matrx, complex exponent)
|
||
|
|
{
|
||
|
|
matrixc out(matrx.Rows(),matrx.Cols());
|
||
|
|
// Process column by column using vector-based power calculations
|
||
|
|
for(ulong i = 0; i<out.Cols(); i++)
|
||
|
|
out.Col(c_pow(matrx.Col(i),exponent),i);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| power of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
complex c_pow(complex value, double alpha)
|
||
|
|
{
|
||
|
|
complex out = value;
|
||
|
|
double r = c_abs(value); // Magnitude
|
||
|
|
double theta = atan2(value.imag,value.real); // Phase Angle
|
||
|
|
double n_r = pow(r,alpha); // New Magnitude
|
||
|
|
double n_theta = alpha*theta; // New Phase Angle
|
||
|
|
|
||
|
|
// Convert back from polar form to rectangular form
|
||
|
|
out.real = n_r*cos(n_theta);
|
||
|
|
out.imag = n_r*sin(n_theta);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| simple power of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vectorc c_pow(vectorc &vect, double alpha)
|
||
|
|
{
|
||
|
|
vectorc out(vect.Size());
|
||
|
|
for(ulong i = 0; i<vect.Size(); i++)
|
||
|
|
out[i] = c_pow(vect[i],alpha);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| simple power of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrixc c_pow(matrixc &matrx, double alpha)
|
||
|
|
{
|
||
|
|
matrixc out(matrx.Rows(),matrx.Cols());
|
||
|
|
// Process matrix columns individually
|
||
|
|
for(ulong i = 0; i<out.Cols(); i++)
|
||
|
|
out.Col(c_pow(matrx.Col(i),alpha),i);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Complex Signum Function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
complex signum(complex z)
|
||
|
|
{
|
||
|
|
double magnitude = sqrt((z.real*z.real) + (z.imag*z.imag));
|
||
|
|
if(!magnitude)
|
||
|
|
return 0+0i; // Handle division by zero for origin coordinates
|
||
|
|
|
||
|
|
complex magz;
|
||
|
|
magz.real = magnitude;
|
||
|
|
magz.imag = 0.0;
|
||
|
|
|
||
|
|
// Returns unit vector directed in the same phase angle (z / |z|)
|
||
|
|
return z/magz;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| absolute value of a complex number (magnitude) |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double c_abs(complex z)
|
||
|
|
{
|
||
|
|
return sqrt((z.real*z.real) + (z.imag*z.imag));
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| absolute value of a complex number (magnitude) |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vector c_abs(vectorc &z)
|
||
|
|
{
|
||
|
|
CComplexVector v(z);
|
||
|
|
// Vectorized calculation of Euclidean length
|
||
|
|
return sqrt((v.re*v.re) + (v.im*v.im));
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| absolute value of a complex number (magnitude) |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrix abs(matrixc &z)
|
||
|
|
{
|
||
|
|
CComplexMatrix v(z);
|
||
|
|
// Matrix-wide vectorized calculation of absolute values
|
||
|
|
return sqrt((v.re*v.re) + (v.im*v.im));
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| sqrt of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
complex c_sqrt(complex z)
|
||
|
|
{
|
||
|
|
double mag_z = c_abs(z);
|
||
|
|
mag_z=sqrt(mag_z); // Square root of the magnitude
|
||
|
|
double theta = atan2(z.imag,z.real); // Phase Angle
|
||
|
|
complex out;
|
||
|
|
// Half-angle principles for complex square root calculation
|
||
|
|
out.real = mag_z*cos(theta/2.0);
|
||
|
|
out.imag = mag_z*sin(theta/2.0);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| sqrt of complex vector |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vectorc c_sqrt(vectorc &z)
|
||
|
|
{
|
||
|
|
vectorc out = z;
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
out[i] = c_sqrt(z[i]);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| sqrt of complex vector |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrixc c_sqrt(matrixc &z)
|
||
|
|
{
|
||
|
|
matrixc out = z;
|
||
|
|
for(ulong i = 0; i<out.Cols(); i++)
|
||
|
|
out.Col(c_sqrt(z.Col(i)),i);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| log of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
complex c_log(complex z)
|
||
|
|
{
|
||
|
|
complex out;
|
||
|
|
// Natural logarithm of complex number: ln(z) = ln(|z|) + i*theta
|
||
|
|
out.real = c_abs(z);
|
||
|
|
out.imag = atan2(z.imag,z.real);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| log of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vectorc c_log(vectorc &z)
|
||
|
|
{
|
||
|
|
vectorc out = z;
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
out[i] = c_log(z[i]);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| log of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrixc c_log(matrixc &z)
|
||
|
|
{
|
||
|
|
matrixc out = z;
|
||
|
|
for(ulong i = 0; i<out.Cols(); i++)
|
||
|
|
out.Col(c_log(z.Col(i)),i);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| exp function of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
complex c_exp(complex z)
|
||
|
|
{
|
||
|
|
complex out;
|
||
|
|
// Euler's Formula conversion: exp(x + iy) = exp(x) * (cos(y) + i*sin(y))
|
||
|
|
out.real = exp(z.real)*cos(z.imag);
|
||
|
|
out.imag = exp(z.real)*sin(z.imag);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| exp function of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vectorc c_exp(vectorc &z)
|
||
|
|
{
|
||
|
|
vectorc out = z;
|
||
|
|
for(ulong i = 0; i<out.Size(); i++)
|
||
|
|
out[i] = c_exp(z[i]);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| exp function of complex number |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrixc c_exp(matrixc &z)
|
||
|
|
{
|
||
|
|
matrixc out = z;
|
||
|
|
for(ulong i = 0; i<out.Cols(); i++)
|
||
|
|
out.Col(c_exp(z.Col(i)),i);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+-----------------------------------------------------------------------+
|
||
|
|
//| Generate a complex Vandermonde matrix |
|
||
|
|
//| in : vectorc |
|
||
|
|
//| num_columns : ulong, default: size of in input vector. |
|
||
|
|
//| ascending : bool, (default: false) Order of the powers of the columns.|
|
||
|
|
//| If true, the powers increase |
|
||
|
|
//| from left to right, if false (the default) they are reversed |
|
||
|
|
//+-----------------------------------------------------------------------+
|
||
|
|
matrixc vanderc(vectorc &in, ulong num_columns = 0,bool ascending = false)
|
||
|
|
{
|
||
|
|
ulong n = num_columns?num_columns:in.Size();
|
||
|
|
|
||
|
|
matrixc out(in.Size(),n);
|
||
|
|
|
||
|
|
// Populate columns by geometric power progression rules specified by 'ascending'
|
||
|
|
for(ulong i = 0; i<n; i++)
|
||
|
|
out.Col(c_pow(in,ascending?double(i):double(n-1-i)),i);
|
||
|
|
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//|process vector representing complex numbers in compact form |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
vectorc compact_to_complex(vector& v,vectorc& bp)
|
||
|
|
{
|
||
|
|
vectorc v_out = vectorc::Zeros(v.Size());
|
||
|
|
|
||
|
|
for(ulong i = 0; i<v.Size() && i<bp.Size();)
|
||
|
|
{
|
||
|
|
// If the blueprint tracking parameter has an imaginary element, parse conjugate pairs
|
||
|
|
if(bp[i].imag)
|
||
|
|
{
|
||
|
|
v_out[i].real = v[i];
|
||
|
|
if(i+1 < v.Size())
|
||
|
|
{
|
||
|
|
// Maps the pair out as real + i*imag and real - i*imag sequential indexes
|
||
|
|
v_out[i].imag = v[i+1];
|
||
|
|
v_out[i+1].real = v_out[i].real;
|
||
|
|
v_out[i+1].imag = -1.0*v_out[i].imag; // Conjugate inversion
|
||
|
|
i+=2; // Step over both elements processed
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// Purely real number fallback step
|
||
|
|
v_out[i].real = v[i];
|
||
|
|
i+=1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return v_out;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| process matrix representing complex numbers in compact form |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
matrixc compact_to_complex(matrix& m, vectorc& bp)
|
||
|
|
{
|
||
|
|
matrixc m_out = matrixc::Zeros(m.Rows(), m.Cols());
|
||
|
|
|
||
|
|
// Row-by-row matrix translation leveraging the underlying vector unpacker
|
||
|
|
for(ulong i = 0; i<m.Rows(); i++)
|
||
|
|
{
|
||
|
|
vector row = m.Row(i);
|
||
|
|
vectorc row_c = compact_to_complex(row,bp);
|
||
|
|
m_out.Row(row_c,i);
|
||
|
|
}
|
||
|
|
return m_out;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|