diff --git a/matlab.h b/matlab.h new file mode 100644 index 0000000000000000000000000000000000000000..27d163c6a99d83a3f11d77eae03367db11824da2 --- /dev/null +++ b/matlab.h @@ -0,0 +1,241 @@ +#pragma once + +#include <random> +#include <iostream> +#include <fstream> +#include "../types.h" +#include <complex> +/* + * Code translated from Matlab base functions + * matlab translation guide : https://eigen.tuxfamily.org/dox/AsciiQuickReference.txt + */ + +//------------------------------------------------------------------------------------------------- +// VARIOUS + +const number pi = M_PI; + +// squares a number +template<typename T> inline T squared(const T& x) +{ + return x*x; +} + +//------------------------------------------------------------------------------------------------- +// ALGEBRA + +// build a vector with values in the given interval +Vector make_vector(const int fromValue, const int toValue, const int by = 1) +{ + int size = 1 + (toValue - fromValue) / by; + Vector result(size); + + int currentValue = fromValue; + for(int i = 0; i < size; i++) + { + result(i) = currentValue; + currentValue += by; + } + + return result; +} + +// repeats a column vector n times in order to build a matrix +Matrix repmat(const Vector& v, const int colNumber) +{ + Matrix result(v.size(), colNumber); + + for(int col = 0; col < colNumber; col++) + { + result.col(col) = v; + } + + return result; +} + +// solves m = m1 \ m2 +inline ComplexMatrix mldivide(const ComplexMatrix& m1, const ComplexMatrix& m2) +{ + //return m1.colPivHouseholderQr().solve(m2); + return m1.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(m2); // you can use JacobiSVD for improved precision +} + +// returns an hermitian matrix where v is the first row and conj(v) the first column +Matrix toeplitz(const Vector& v) +{ + auto size = v.size(); + Matrix result(size, size); + + for(int row=0; row<size; row++) + { + for(int col=0; col<size; col++) + { + // complex + /*number value = v(std::abs(row - col)); + if(row > col) + { + value = Sstd::conj(value); + } + result(row,col) = value;*/ + + // real + result(row,col) = v(std::abs(row - col)); + } + } + + return result; +} + +// flip the column and rows +inline Matrix flip(Matrix mat) +{ + Matrix matflipr = mat.rowwise().reverse(); // fliplr + Matrix matflipc = matflipr.colwise().reverse(); // flipud + return matflipc; +} + +//------------------------------------------------------------------------------------------------- +// POLYNOMIAL + +/* + * evaluates a polynomial on the given data + * use Horner's scheme + * NOTE: one could use a more numerically stable algorithm + */ +Vector polyval(const Polynomial& pol, const Vector& x) +{ + Vector result = Vector::Zero(x.size()); + + for(const auto& coef : pol) + { + result = result.binaryExpr(x, [coef](const number& result, const number& x){return result*x + coef;}); + } + + return result; +} + +//------------------------------------------------------------------------------------------------- + +// RANDOM HELPING FUNCTION + +const unsigned int n = 65535;//0xFFFF; +const unsigned int m = 16807; +const unsigned int b = 0; +static long seed = 43690;//0xAAAA; +// generate an uniformaly distributed random number sampled from [0;0x7FFFFFFF] +long uniform() { + long unsigned int hi = m * (seed & n); + long unsigned int lo = m * (seed >> 16); + + lo+= (hi & 32767) << 16; + lo+= hi >> 15; + + if (lo > 2147483647) //0x7FFFFFFF) + lo -= 2147483647; //0x7FFFFFFF; + seed=(long) lo; + return seed ; +} + + +//-------------------------------------------------------------------------------------------------- + +// RANDOM + +// generate an uniformaly distributed random number sampled from [-1;1] +inline number randu() +{ + //on le veut entre -1 et 1 / pour l'instant on l'a entre 0 et 1 + number result = uniform()/2147483647; //(double)0x7FFFFFFF; + // number result = (uniform() - (number)3xFFFFFFF.8)/(number)3xFFFFFFF.8); + return result; + // throw std::logic_error("Function not yet implemented."); +} + +// generates a vector of the given size, the entries of the vector are all complex number +// their real and imaginary parts are uniformaly distributed random number sampled from [-1;1] +ComplexVector randu(int size) +{ + ComplexVector complexVector(size); + std::complex<number> mycomplex; + for(int i = 0; i < size; i++) + { + std::complex<number> mycomplex(randu(), randu()); + complexVector(i) = mycomplex; + } + return complexVector; + + //throw std::logic_error("Function not yet implemented."); +} + +// generate a normally distributed random number +// sampled from a distribution with mean 0 and std 1 +inline number randn() +{ + + number res; + number U0 = uniform()/2147483647;//(double)0x7FFFFFFF; + number U1 = uniform()/2147483647;//(double)0x7FFFFFFF; + res = sqrt(-2 * log(U0)) * cos(2 * M_PI * U1); + + return res; + + // throw std::logic_error("Function not yet implemented."); +} + +// generates a vector of the given size, the entries of the vector are all complex number +// their real and imaginary parts are sampled from a normal distribution with mean 0 and std 1 +ComplexVector randn(int size) +{ + // NOTE: this can be built on the previous function + ComplexVector complexVector(size); + std::complex<number> mycomplex; + for(int i = 0; i < size; i++) + { + std::complex<number> mycomplex(randn(), randn()); + complexVector(i) = mycomplex; + } + return complexVector; + //throw std::logic_error("Function not yet implemented."); +} + + + +//------------------------------------------------------------------------------------------------- +// IMPORT + +/// import a vector of reals from a file +Vector loadRealVector(const std::string& file) +{ + std::vector<number> result; + std::ifstream input(file); + + number x; + while (input >> x) + { + result.push_back(x); + } + + Vector output = Eigen::Map<Vector, Eigen::Unaligned>(result.data(), result.size()); + return output; +} + +/// import a vector of complex from a file +ComplexVector loadComplexVector(const std::string& file) +{ + std::vector<complexNumber> result; + std::ifstream input(file); + + number r; + number i; + while (input >> r) + { + input >> i; + complexNumber x(r,i); + result.push_back(x); + } + + ComplexVector output = Eigen::Map<ComplexVector, Eigen::Unaligned>(result.data(), result.size()); + return output; +} + +//-------------------------------------------------------------------------------------------------