25#define Complex double _Complex 
   33      static Complex one() {Complex out; out = 1.0 + 0*I; 
return out; }
 
   34      static Complex zero() {Complex out; out = 0 + 0*I; 
return out;}
 
   36        static void sq(Complex& v)
 
   38          Complex v2 = creal(v) - cimag(v)*I;
 
   41        static Complex construct(
double theta)
 
   43          Complex out = cos(theta) + sin(theta)*I;
 
   47        static Complex power(Complex& base, 
int e)
 
   51            double real = log( sqrt( creal(base)*creal(base)* + cimag(base)*cimag(base)));
 
   52            double imag = atan2(cimag(base), creal(base));
 
   59            Complex result = construct(cimag(a));
 
   62            Complex r2 = creal(result)*exp(real) + cimag(result)*real*I;
 
   67        static Complex add(Complex& a, Complex& b)
 
   71        static Complex subtract(Complex& a, Complex& b)
 
   76        static Complex mult(Complex& a, Complex& b)
 
   81        static Complex invert(Complex& a)
 
   84            double d = creal(a)*creal(a) + cimag(a)*cimag(a);
 
   86            out = creal(a) / d - cimag(a)/d *I;
 
  110            varName = std::string(_name);
 
  119            if(r == 0 || c == 0 || !m.elements)
 
  122            elements = 
new Complex[n];
 
  126            for(
int i=0; i<n; ++i)
 
  127                elements[i] = m.elements[i];
 
  131        void saveToFile(
const std::string& filename);
 
  132        void saveToFile(std::ofstream& f);
 
  134        bool loadFromFile(
const std::string& filename);
 
  135        bool loadFromFile(std::ifstream& f);
 
  139            if(!elements || r != m.r || c != m.c)
 
  146                if(r == 0 || c == 0 || !m.elements)
 
  148                    throw std::string(
"operator= error.\n");
 
  152                elements = 
new Complex[n];
 
  157                throw std::string(
"operator= error 2.\n");
 
  161            for(
int i=0; i<n; ++i)
 
  162                elements[i] = m.elements[i];
 
  171            if(elements && !noCleanup)
 
  186            for(
int i=0; i<n; ++i)
 
  188              elements[i] = 0.0+0.0*I;
 
  199            if(getCols() < getRows())
 
  202            Complex one = 1.0+0.0*I;
 
  204            for(
int i=0; i<dim; ++i)
 
  205                this->setDirect(i,i,one);
 
  210            Complex c = 0.0 + 0.0*I;
 
  211            for(
int i=0; i<getRows(); ++i)
 
  213              c = c + (*this)(i,i);
 
  218        void clear(Complex value)
 
  222            for(
int i=0; i<n; ++i)
 
  226        bool create(
int _r, 
int _c, Complex* _elements)
 
  233            elements = _elements;
 
  237        bool create(
int _r, 
int _c)
 
  239            if(_r <= 0 || _c <= 0)
 
  241            if(elements && r == _r && c == _c)
 
  249            elements = 
new Complex[r*c];
 
  258            return create(_r, _r);
 
  261        Complex& operator() (
int row, 
int col)
 
  265            if(!elements || _r >= r || _c >= c || _r < 0 || _c < 0)
 
  267                std::cout << 
"Error 5 (" << elements << 
", " << _r << 
", " << r << 
", " << _c << 
", " << c << 
")\n";
 
  268                std::cout << 
"Name = " << varName << 
"\n";
 
  269                throw(std::string(
"Algebra Error 5.1"));
 
  274            return elements[_c*r + _r];
 
  277        void random_unitary(
const std::vector <double>& phi_v, 
const std::vector <double>& psi_v, 
const std::vector <double>& chi_v, 
double alpha);
 
  278        bool eigenValues(std::vector <double>& values);
 
  279        double safeLog(
double x)
 
  283          return log(x)/log(2.0);
 
  287          std::vector<double> ev;
 
  292          for(
int i=0; i < ev.size(); ++i)
 
  294              sum = sum - ev[i] * safeLog(ev[i]);
 
  301        Complex getDirect(
int row, 
int col)
 
  305            if(!elements || _r >= r || _c >= c || _r < 0 || _c < 0)
 
  307                std::cout << 
"Error 5 (" << elements << 
", " << _r << 
", " << r << 
", " << _c << 
", " << c << 
")\n";
 
  308                throw(std::string(
"Algebra Error 5.2"));
 
  313            return elements[_c*r + _r];
 
  316        void setDirect(
int _n, Complex data)
 
  318            if(!elements || _n >= n)
 
  321                throw(std::string(
"Algebra Error 5.3"));
 
  329        void setDirect(
int row, 
int col, Complex data)
 
  333            if(!elements || _r >= r || _c >= c || _r < 0 || _c < 0)
 
  335                std::cout << 
"Error 5 (" << elements << 
", " << _r << 
", " << r << 
", " << _c << 
", " << c << 
")\n";
 
  336                throw(std::string(
"Algebra Error 5.4"));
 
  341            elements[_c*r + _r] = data;
 
  344        void setDirect(
int row, 
int col, 
double re, 
double im)
 
  348            if(!elements || _r >= r || _c >= c || _r < 0 || _c < 0)
 
  350                std::cout << 
"Error 5 (" << elements << 
", " << _r << 
", " << r << 
", " << _c << 
", " << c << 
")\n";
 
  351                throw(std::string(
"Algebra Error 5.4"));
 
  356            elements[_c*r + _r] = re + im*I;
 
  360            if(!elements || _n >= n)
 
  362                std::cout << 
"Error 2 (" << elements << 
", " << _n << 
", " << n << 
")\n";
 
  369        Complex* getElements()
 
  374        void print(std::ostream& f, 
bool printAll=
false)
 
  378            int rStart = 0, cStart=0;
 
  384            int rows = alg_min(10, r);
 
  385            int cols = alg_min(10, c);
 
  392            for(
int _r=rStart; _r < rows; ++_r)
 
  394                for(
int _c=cStart; _c<cols; ++_c)
 
  396                  f << creal((*
this)(_r,_c)) << 
"+" << cimag((*
this)(_r,_c)) << 
"i\t";
 
  404        void multiplyScalar(Complex& c)
 
  409            for(
int i=0; i<n; ++i)
 
  411                elements[i] = ComplexHelper::mult(elements[i], c);
 
  417            if(!elements || c != r)
 
  419                throw(std::string(
"Algebra error 1.2"));
 
  424            for(
long row=0; row<r; ++row)
 
  426                for(
long col=row; col<c; ++col)
 
  430                    temp = getDirect(row,col);
 
  431                    setDirect(row,col, getDirect(col,row));
 
  432                    setDirect(col,row, temp);
 
  442            for(
int _r=0; _r<r; ++_r)
 
  444                for(
int _c=0; _c<c; ++_c)
 
  446                  Complex c = (*this)(_r, _c);
 
  447                  B(_c, _r) = creal(c) - cimag(c)*I;
 
  453        void subtract(Complex& c)
 
  458            for(
int i=0; i<n; ++i)
 
  460              elements[i] = elements[i] = c;
 
  469            if(!elements || !B->getElements() || getRows() != B->getRows() || getCols() != B->getCols())
 
  471                throw std::string(
"Error - cannot subtract matrix\n");
 
  475            output->create(getRows(), getCols());
 
  477            for(
int i=0; i<n; ++i)
 
  479              output->elements[i] = elements[i] - B->getElements()[i];
 
  488            if(!elements || !B->getElements() || getRows() != B->getRows() || getCols() != B->getCols())
 
  490                throw std::string(
"Error - cannot add matrix\n");
 
  494            output->create(getRows(), getCols());
 
  496            for(
int i=0; i<n; ++i)
 
  498              output->elements[i] = elements[i] + B->getElements()[i];
 
  502        void random(
double smallValue, 
double largeValue);
 
  509            if(!elements || !B->getElements() || getRows() != B->getRows() || getCols() != B->getCols())
 
  511                throw std::string(
"Error - cannot add matrix\n");
 
  517            for(
int i=0; i<n; ++i)
 
  519              output->elements[i] = elements[i] + B->getElements()[i];
 
  523        void dot(
matrix* B, Complex& output);   
 
  525        bool multiply(
matrix& B, 
matrix& output, 
char TRANSB=
'N');
 
  542        int alg_min(
int a, 
int b)
 
  544            return (a < b) ? a : b;
 
  546        int alg_max(
int a, 
int b)
 
  548            return (a > b) ? a : b;