ECF 1.5
Algebra.cpp
1/*
2Algebra.cpp
3Written by Walter O. Krawec
4
5Copyright (c) 2016 Walter O. Krawec
6
7Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
9The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12*/
13
14#include "Algebra.h"
15
16extern "C"
17{
18#include <cblas.h>
19#include <lapacke.h>
20}
21
22
23namespace algebra
24{
25void mat::random_unitary(const std::vector <double>& phi_v, const std::vector <double>& psi_v, const std::vector <double>& chi_v, double alpha)
26{
27 int dim = chi_v.size();//getRows();
28 if(dim != getRows())
29 create(dim);
30 algebra::mat E, temp, temp2;
31 temp.create(dim);
32 int index = 0;
33 Complex z;
34 ident();
35 for(int j=1; j<=dim-1; ++j)
36 {
37 E.create(dim);
38 E.ident();
39 for(int i=j; i>=1; --i)
40 {
41 int I2 = i;
42 int J = j+1;
43 double psi, phi, chi;
44 psi = psi_v[index];
45 phi = phi_v[index];
46 //std::cout << i << ", " << j << " = " << index << "\n";
47 if(I2 == 1)
48 chi = chi_v[i-1];
49 else
50 chi = 0;
51
52 //psi = 0;
53 //chi = 0;
54 //phi = 0;
55 //if((i%2)==0) phi = 0;
56
57 ++index;
58 temp.ident();
59 z = algebra::ComplexHelper::construct(psi);
60 z *= cos(phi);
61 temp(I2-1, I2-1) = z;
62
63 z = algebra::ComplexHelper::construct(chi);
64 z *= sin(phi);
65 temp(I2-1, J-1) = z;
66
67 z = algebra::ComplexHelper::construct(-chi);
68 z *= -sin(phi);
69 temp(J-1, I2-1) = z;
70
71 z = algebra::ComplexHelper::construct(-psi);
72 z *= cos(phi);
73 temp(J-1, J-1) = z;
74
75 //if(j == dim-1 || (I-1 < dim/2 && J-1 == I-1+dim/2)){
76 E.multiply(temp, temp2);
77 E = temp2;
78 //}
79 }
80 //if(j==dim/3||j==dim/3*2||j == dim-1){
81 //if(j==dim-1){
82 multiply(E, temp2);
83 *this = temp2;
84 //}
85 }
86
87 Complex c = cos(alpha) + I*sin(alpha);
88 multiplyScalar(c);
89}
90
91bool matrix::eigenValues(std::vector <double>& values)
92{
93 int n, lda, info, lwork, lrwork, liwork;
94 n = getRows();
95 lda = n;
96 int iwkopt;
97 int* iwork;
98 double rwkopt;
99 double* rwork;
100 Complex wkopt, *work;
101
102 double *w = new double[n];
103
104 matrix a;
105 a.create(n);
106 for(int r=0; r<n; ++r)
107 {
108 for(int c=0; c<n; ++c)
109 {
110 a(r,c) = 0;
111
112 if(c >= r)
113 a(r,c) = (*this)(r,c);
114 }
115 }
116 //a.print(std::cout);
117
118 lwork = -1;
119 lrwork = -1;
120 liwork = -1;
121
122 LAPACK_zheevd("N", "Upper", &n, a.getElements(), &lda, w, &wkopt, &lwork, &rwkopt, &lrwork, &iwkopt, &liwork, &info);
123 lwork = (int)creal(wkopt);
124 work = new Complex[lwork];
125 lrwork = (int)rwkopt;
126 rwork = new double[lrwork];
127 liwork = iwkopt;
128 iwork = new int[liwork];
129
130 LAPACK_zheevd("N", "Upper", &n, a.getElements(), &lda, w, work, &lwork, rwork, &lwork, iwork, &liwork, &info);
131
132 if(info == 0)
133 {
134 values.clear();
135 for(int i=0; i<n; ++i)
136 values.push_back(w[i]);
137 }
138
139 delete[] w;
140 delete[] work;
141 delete[] rwork;
142 delete[] iwork;
143
144 return (info==0);
145}
146
147void matrix::tensor(matrix* B, matrix* output)
148{
149 if(!B || !output)
150 return;
151
152 output->create(getRows()*B->getRows(), getCols()*B->getCols());
153
154 for(int r=0; r<output->getRows(); ++r)
155 {
156 for(int c=0; c<output->getCols(); ++c)
157 {
158 int aRow = r / B->getRows();
159 int aCol = c / B->getCols();
160 int bRow = r % B->getRows();
161 int bCol = c % B->getCols();
162
163 output->setDirect(r, c, getDirect(aRow, aCol)* B->getDirect(bRow, bCol));
164 }
165 }
166}
167
168bool matrix::multiply(matrix& B, matrix& output, char TRANSB)
169{
170 if(TRANSB != 'N')
171 std::cout << "Warning: matrix transpose not implemented in multiply function; result will be wrong\n";
172
173 output.create(getRows(), B.getCols());
174 Complex sum;
175 for(int row=0; row<output.getRows(); ++row)
176 {
177 for(int col=0; col<output.getCols(); ++col){
178 sum = 0;
179 for(int k=0; k<getCols(); ++k)
180 sum = sum + ( (*this)(row,k) * B(k,col) );
181
182 output(row, col) = sum;
183 }
184 }
185 return true;
186}
187
188}