Initiate
This commit is contained in:
@@ -0,0 +1,965 @@
|
||||
/*****************************************************************
|
||||
|
||||
This software is part of Jean-Sébastien Caux's Abacus toolsuite.
|
||||
|
||||
Copyright © Jean-Sébastien Caux.
|
||||
|
||||
*****************************************************************/
|
||||
|
||||
|
||||
export module matrix;
|
||||
|
||||
|
||||
import std;
|
||||
|
||||
|
||||
import conveniences;
|
||||
|
||||
|
||||
// version using flattened vector
|
||||
|
||||
////////////////////
|
||||
// ↓ Class Matrix //
|
||||
////////////////////
|
||||
|
||||
export template <class T>
|
||||
class Matrix {
|
||||
|
||||
private:
|
||||
std::size_t dim_;
|
||||
std::vector<T> element_;
|
||||
|
||||
public:
|
||||
Matrix (std::size_t dim);
|
||||
|
||||
inline std::size_t size() const { return dim_; };
|
||||
|
||||
inline T operator() (IndexU i, IndexU j) const { return element_[i*dim_ + j]; };
|
||||
inline T& operator() (IndexU i, IndexU j) { return element_[i*dim_ + j]; };
|
||||
|
||||
void setZero();
|
||||
|
||||
Matrix<T>& operator*= (const T& a);
|
||||
Matrix<T>& operator/= (const T& a);
|
||||
|
||||
void ludcmp (std::vector<IndexU>& indx, T& d);
|
||||
void lubksb (std::vector<IndexU>& indx, std::vector<T>& b);
|
||||
std::complex<long double> lndet_LU_destroy ();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
Matrix<T>::Matrix (std::size_t dim)
|
||||
: dim_(dim)
|
||||
, element_(std::vector<T>(dim_*dim_))
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
void Matrix<T>::setZero ()
|
||||
{
|
||||
std::fill(element_.begin(), element_.end(), T(0));
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
Matrix<T>& Matrix<T>::operator*= (const T& a)
|
||||
{
|
||||
std::transform(element_.begin(), element_.end(), element_.begin(), [a](T el) { return el * a; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Matrix<T>& Matrix<T>::operator/= (const T& a)
|
||||
{
|
||||
T oneovera = T(1)/a;
|
||||
std::transform(element_.begin(), element_.end(), element_.begin(), [oneovera](T el) { return el * oneovera; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
void Matrix<T>::ludcmp (std::vector<IndexU>& indx, T& d)
|
||||
{
|
||||
IndexU i, j, k;
|
||||
IndexU imax { 0 };
|
||||
IndexU idim_, jdim_, imaxdim_;
|
||||
T big, dum, sum, temp;
|
||||
|
||||
IndexU n { size() };
|
||||
|
||||
std::vector<T> vv(n);
|
||||
d = T(1);
|
||||
for (i = 0; i < n; i++) {
|
||||
big = T(0);
|
||||
idim_ = i*dim_;
|
||||
for (j = 0; j < n; j++) {
|
||||
if ((std::fabs(temp = element_[idim_ + j])) > std::fabs(big)) big = temp;
|
||||
}
|
||||
if (big == T(0)) throw;
|
||||
vv[i] = T(1)/big;
|
||||
}
|
||||
|
||||
for (j = 0; j < n; j++) {
|
||||
for (i = 0; i < j; i++) {
|
||||
idim_ = i*dim_;
|
||||
sum = element_[idim_ + j];
|
||||
for (k = 0; k < i; k++) sum -= element_[idim_ + k] * element_[k*dim_ + j];
|
||||
element_[idim_ + j] = sum;
|
||||
}
|
||||
big = T(0);
|
||||
for (i = j; i < n; i++) {
|
||||
idim_ = i*dim_;
|
||||
sum = element_[idim_ + j];
|
||||
for (k = 0; k < j; k++) sum -= element_[idim_ + k] * element_[k*dim_ + j];
|
||||
element_[idim_ + j] = sum;
|
||||
if ((std::fabs(dum = vv[i]*sum)) >= std::fabs(big)) {
|
||||
big = dum;
|
||||
imax = i;
|
||||
}
|
||||
}
|
||||
jdim_ = j*dim_;
|
||||
if (j != imax) {
|
||||
imaxdim_ = imax*dim_;
|
||||
for (k = 0; k < n; k++) {
|
||||
dum = element_[imaxdim_ + k];
|
||||
element_[imaxdim_ + k] = element_[jdim_ + k];
|
||||
element_[jdim_ + k] = dum;
|
||||
}
|
||||
d = -d;
|
||||
vv[imax] = vv[j];
|
||||
}
|
||||
indx[j] = imax;
|
||||
if (j !=n-1) {
|
||||
dum = T(1)/(element_[jdim_ + j]);
|
||||
for (i = j + 1; i < n; i++) element_[i*dim_ + j] *= dum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Matrix<T>::lubksb (std::vector<IndexU>& indx, std::vector<T>& b)
|
||||
{
|
||||
// int i, ip, j;
|
||||
// int ii { 0 };
|
||||
// int idim_;
|
||||
// T sum;
|
||||
|
||||
// int n { int(size()) };
|
||||
// for (i = 0; i < n; i++) {
|
||||
// ip = indx[i];
|
||||
// sum = b[ip];
|
||||
// b[ip] = b[i];
|
||||
// idim_ = i*dim_;
|
||||
// if (ii != 0)
|
||||
// for (j = ii-1; j < i; j++) sum -= element_[idim_ + j] * b[j];
|
||||
// else if (sum != T(0))
|
||||
// ii = i + 1;
|
||||
// b[i] = sum;
|
||||
// }
|
||||
// for (i = n - 1; i >= 0; i--) {
|
||||
// sum = b[i];
|
||||
// idim_ = i*dim_;
|
||||
// for (j = i + 1; j < n; j++) sum -= element_[idim_ + j] * b[j];
|
||||
// b[i] = sum/element_[idim_ + i];
|
||||
// }
|
||||
|
||||
std::size_t i, ip, j;
|
||||
std::size_t ii { 0 };
|
||||
std::size_t idim_;
|
||||
T sum;
|
||||
std::size_t n { size() };
|
||||
for (i = 0; i < n; i++) {
|
||||
ip = indx[i];
|
||||
sum = b[ip];
|
||||
b[ip] = b[i];
|
||||
idim_ = i*dim_;
|
||||
if (ii != 0)
|
||||
for (j = ii-1; j < i; j++) sum -= element_[idim_ + j] * b[j];
|
||||
else if (sum != T(0))
|
||||
ii = i + 1;
|
||||
b[i] = sum;
|
||||
}
|
||||
for (i = n; i--;) {
|
||||
sum = b[i];
|
||||
idim_ = i*dim_;
|
||||
for (j = i + 1; j < n; j++) sum -= element_[idim_ + j] * b[j];
|
||||
b[i] = sum/element_[idim_ + i];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::complex<long double> Matrix<T>::lndet_LU_destroy ()
|
||||
{
|
||||
std::vector<IndexU> indx(size());
|
||||
T d;
|
||||
std::complex<long double> lndet { 0 };
|
||||
|
||||
(*this).ludcmp(indx, d);
|
||||
|
||||
lndet = log(std::complex<long double>(d));
|
||||
|
||||
for (IndexU j { 0 }; j < size(); j++) {
|
||||
lndet += log(std::complex<long double>(element_[j*dim_ + j]));
|
||||
}
|
||||
|
||||
return lndet;
|
||||
}
|
||||
|
||||
|
||||
export template <class T>
|
||||
std::ostream& operator<< (std::ostream& s, const Matrix<T>& M)
|
||||
{
|
||||
for (IndexU i { 0 }; i < M.size(); ++i) {
|
||||
for (IndexU j { 0 }; j < M.size(); ++j) s << M(i,j) << "\t";
|
||||
s << std::endl;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// ↑ Class Matrix //
|
||||
////////////////////
|
||||
|
||||
|
||||
|
||||
// Additional utilities
|
||||
|
||||
|
||||
inline Real SIGN (const Real& a, const Real& b)
|
||||
{
|
||||
return b >= Real(0) ? (a >= Real(0) ? a : -a) : (a >= Real(0) ? -a : a);
|
||||
}
|
||||
|
||||
Real pythag(const Real a, const Real b)
|
||||
{
|
||||
Real absa, absb;
|
||||
absa = std::abs(a);
|
||||
absb = std::abs(b);
|
||||
if (absa > absb) return absa * std::sqrt(Real(1) + (absb/absa)*(absb/absa));
|
||||
else return absb * std::sqrt(Real(1) + (absa/absb)*(absa/absb));
|
||||
}
|
||||
|
||||
|
||||
// Singular value decomposition
|
||||
// Numerical Recipes section 2.6
|
||||
// Restricted to square matrix due to use of Matrix class
|
||||
export void svdcmp(Matrix<Real>& a, std::vector<Real>& w, Matrix<Real>& v)
|
||||
{
|
||||
bool flag;
|
||||
int i, its, j, jj, k, l, nm;
|
||||
Real anorm, c, f, g, h, s, scale, x, y, z;
|
||||
|
||||
int m { int(a.size()) };
|
||||
int n { int(a.size()) };
|
||||
|
||||
std::vector<Real> rv1(n);
|
||||
g = Real(0); scale = Real(0); anorm = Real(0);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
l = i+2;
|
||||
rv1[i] = scale*g;
|
||||
g = Real(0); s = Real(0); scale = Real(0);
|
||||
if (i < m) {
|
||||
for (k = i; k < m; k++) scale += std::abs(a(k,i));
|
||||
if (scale != Real(0)) {
|
||||
for (k = i; k < m; k++) {
|
||||
a(k,i) /= scale;
|
||||
s += a(k,i) * a(k,i);
|
||||
}
|
||||
f = a(i,i);
|
||||
g = -SIGN(std::sqrt(s), f);
|
||||
h = f*g-s;
|
||||
a(i,i) = f-g;
|
||||
for (j = l-1; j < n; j++) {
|
||||
for (s=Real(0), k=i; k < m; k++) s += a(k,i)*a(k,j);
|
||||
f=s/h;
|
||||
for (k=i; k < m; k++) a(k,j) += f*a(k,i);
|
||||
}
|
||||
for (k=i; k < m; k++) a(k,i) *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
w[i] = scale*g;
|
||||
g = Real(0); s = Real(0); scale = Real(0);
|
||||
|
||||
if (i+1 <= m && i != n) {
|
||||
for (k = l-1; k < n; k++) scale += std::abs(a(i,k));
|
||||
if (scale != Real(0)) {
|
||||
for (k=l-1; k < n; k++) {
|
||||
a(i,k) /= scale;
|
||||
s += a(i,k)*a(i,k);
|
||||
}
|
||||
f = a(i, l-1);
|
||||
g = -SIGN(std::sqrt(s), f);
|
||||
h = f*g - s;
|
||||
a(i, l-1) = f-g;
|
||||
for (k=l-1; k < n; k++) rv1[k] = a(i,k)/h;
|
||||
for (j = l-1; j < m; j++) {
|
||||
for (s=Real(0), k=l-1; k < n; k++) s += a(j,k)*a(i,k);
|
||||
for (k=l-1; k < n; k++) a(j,k) += s*rv1[k];
|
||||
}
|
||||
for (k=l-1; k < n; k++) a(i,k) *= scale;
|
||||
}
|
||||
}
|
||||
anorm = std::max(anorm, std::abs(w[i]) + std::abs(rv1[i]));
|
||||
}
|
||||
|
||||
for (i = n-1; i >= 0; i--) { // accumulation of right-hand transforms
|
||||
if (i < n-1) {
|
||||
if (g != Real(0)) {
|
||||
for (j = l; j < n; j++) v(j,i) = (a(i,j)/a(i,l))/g;
|
||||
for (j=l; j < n; j++) {
|
||||
for (s=Real(0), k=l; k < n; k++) s += a(i,k)*v(k,j);
|
||||
for (k=l; k < n; k++) v(k,j) += s*v(k,i);
|
||||
}
|
||||
}
|
||||
for (j=l; j < n; j++) {
|
||||
v(i,j) = Real(0);
|
||||
v(j,i) = Real(0);
|
||||
}
|
||||
}
|
||||
v(i,i) = Real(1);
|
||||
g = rv1[i];
|
||||
l = i;
|
||||
}
|
||||
|
||||
for (i = std::min(m,n) -1; i >= 0; i--) { // accumulation of left-hand transforms
|
||||
l = i+1;
|
||||
g = w[i];
|
||||
for (j=l; j < n; j++) a(i,j) = Real(0);
|
||||
if (g != Real(0)) {
|
||||
g = Real(1)/g;
|
||||
for (j=l; j < n; j++) {
|
||||
for (s=Real(0), k=l; k < m; k++) s += a(k,i) * a(k,j);
|
||||
f = (s/a(i,i))*g;
|
||||
for (k=i; k < m; k++) a(k,j) += f*a(k,i);
|
||||
}
|
||||
for (j=i; j < m; j++) a(j,i) *= g;
|
||||
}
|
||||
else for (j=i; j < m; j++) a(j,i) = Real(0);
|
||||
++a(i,i);
|
||||
}
|
||||
|
||||
for (k=n-1; k >= 0; k--) {
|
||||
for (its=0; its < 30; its++) {
|
||||
flag = true;
|
||||
for (l=k; l >= 0; l--) {
|
||||
nm = l-1;
|
||||
if (std::abs(rv1[l]) + anorm == anorm) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
if (std::abs(w[nm]) + anorm == anorm) break;
|
||||
}
|
||||
if (flag) {
|
||||
c = Real(0);
|
||||
s = Real(1);
|
||||
for (i=l-1; i < k+1; i++) {
|
||||
f = s*rv1[i];
|
||||
rv1[i] = c*rv1[i];
|
||||
if (std::abs(f) + anorm == anorm) break;
|
||||
g = w[i];
|
||||
h = pythag(f,g);
|
||||
w[i] = h;
|
||||
h = Real(1)/h;
|
||||
c = g*h;
|
||||
s = -f*h;
|
||||
for (j=0; j < m; j++) {
|
||||
y = a(j, nm);
|
||||
z = a(j,i);
|
||||
a(j, nm) = y*c + z*s;
|
||||
a(j,i) = z*c - y*s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
z = w[k];
|
||||
if (l == k) {
|
||||
if (z < Real(0)) {
|
||||
w[k] = -z;
|
||||
for (j=0; j < n; j++) v(j,k) = -v(j,k);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (its == 29) throw AbacusException("No convergence in 30 svdmp iterations");
|
||||
x = w[l];
|
||||
nm = k-1;
|
||||
y = w[nm];
|
||||
g = rv1[nm];
|
||||
h = rv1[k];
|
||||
f = ((y-z) * (y+z) + (g-h) * (g+h))/(2*h*y);
|
||||
g = pythag(f, Real(1));
|
||||
f = ((x-z)*(x+z) + h*((y/(f+SIGN(g,f)))-h))/x;
|
||||
c = Real(1); s = Real(1); // Next QR transformation
|
||||
for (j=l; j <= nm; j++) {
|
||||
i = j+1;
|
||||
g = rv1[i];
|
||||
y = w[i];
|
||||
h = s*g;
|
||||
g = c*g;
|
||||
z = pythag(f,h);
|
||||
rv1[j] = z;
|
||||
c = f/z;
|
||||
s = h/z;
|
||||
f = x*c + g*s;
|
||||
g = g*c - x*s;
|
||||
h = y*s;
|
||||
y *= c;
|
||||
for (jj = 0; jj < n; jj++) {
|
||||
x = v(jj, j);
|
||||
z = v(jj, i);
|
||||
v(jj, j) = x*c + z*s;
|
||||
v(jj, i) = z*c - x*s;
|
||||
}
|
||||
z = pythag(f,h);
|
||||
w[j] = z;
|
||||
if (z) {
|
||||
z = Real(1)/z;
|
||||
c = f*z;
|
||||
s = h*z;
|
||||
}
|
||||
f = c*g + s*y;
|
||||
x = c*y - s*g;
|
||||
for (jj=0; jj < m; jj++) {
|
||||
y = a(jj, j);
|
||||
z = a(jj, i);
|
||||
a(jj, j) = y*c + z*s;
|
||||
a(jj, i) = z*c - y*s;
|
||||
}
|
||||
}
|
||||
rv1[l] = Real(0);
|
||||
rv1[k] = f;
|
||||
w[k] = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Householder reduction of a real symmetric matrix
|
||||
// NR section 11.2
|
||||
export void tred2 (Matrix<Real>& a, std::vector<Real>& d, std::vector<Real>& e)
|
||||
{
|
||||
int l, k, j, i;
|
||||
Real scale, hh, h, g, f;
|
||||
|
||||
int n { int(a.size()) };
|
||||
for (i = n-1; i > 0; i--) {
|
||||
l = i - 1;
|
||||
h = scale = Real(0);
|
||||
if (l > 0) {
|
||||
for (k = 0; k < l + 1; k++) scale += std::abs(a(i,k));
|
||||
if (scale == Real(0)) e[i] = a(i,l);
|
||||
else {
|
||||
for (k = 0; k < l + 1; k++) {
|
||||
a(i,k) /= scale;
|
||||
h += a(i,k) * a(i,k);
|
||||
}
|
||||
f = a(i,l);
|
||||
g = (f >= Real(0) ? -std::sqrt(h) : std::sqrt(h));
|
||||
e[i] = scale * g;
|
||||
h -= f * g;
|
||||
a(i,l) = f - g;
|
||||
f = Real(0);
|
||||
for (j = 0; j < l + 1; j++) {
|
||||
a(j,i) = a(i,j)/h;
|
||||
g = Real(0);
|
||||
for (k = 0; k < j + 1; k++) g += a(j,k) * a(i,k);
|
||||
for (k = j + 1; k < l + 1; k++) g += a(k,j) * a(i,k);
|
||||
e[j] = g/h;
|
||||
f += e[j] * a(i,j);
|
||||
}
|
||||
hh = f/(h +h);
|
||||
for (j = 0; j < l + 1; j++) {
|
||||
f = a(i,j);
|
||||
e[j] = g = e[j] - hh * f;
|
||||
for (k = 0; k < j + 1; k++) a(j,k) -= (f * e[k] + g * a(i,k));
|
||||
}
|
||||
}
|
||||
}
|
||||
else e[i] = a(i,l);
|
||||
d[i] = h;
|
||||
}
|
||||
d[0] = Real(0);
|
||||
e[0] = Real(0);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
l = i;
|
||||
if (d[i] != Real(0)) {
|
||||
for (j = 0; j < l; j++) {
|
||||
g = Real(0);
|
||||
for (k = 0; k < l; k++) g += a(i,k) * a(k,j);
|
||||
for (k = 0; k < l; k++) a(k,j) -= g * a(k,i);
|
||||
}
|
||||
}
|
||||
d[i] = a(i,i);
|
||||
a(i,i) = Real(1);
|
||||
for (j = 0; j < l; j++) a(j,i) = a(i,j) = Real(0);
|
||||
}
|
||||
} // tred2
|
||||
|
||||
|
||||
|
||||
// QL algorithm with implicit shifts
|
||||
// NR section 11.3
|
||||
export void tqli (std::vector<Real>& d, std::vector<Real>& e, Matrix<Real>& z)
|
||||
{
|
||||
int m, l, iter, i, k;
|
||||
Real s, r, p, g, f, dd, c, b;
|
||||
|
||||
int n { int(d.size()) };
|
||||
for (i = 1; i < n; i++) e[i-1] = e[i];
|
||||
e[n-1] = Real(0);
|
||||
for (l = 0; l < n; l++) {
|
||||
iter = 0;
|
||||
do {
|
||||
for (m = l; m < n-1; m++) {
|
||||
dd = std::abs(d[m]) + std::abs(d[m+1]);
|
||||
if (std::abs(e[m]) + dd == dd) break;
|
||||
}
|
||||
if (m != l) {
|
||||
if (iter++ == 30) {
|
||||
std::cout << "Too many iterations in tqli" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
g = (d[l + 1] - d[l])/(2 * e[l]);
|
||||
r = pythag(g, Real(1));
|
||||
g = d[m] - d[l] + e[l]/(g + SIGN(r, g));
|
||||
s = c = Real(1);
|
||||
p = Real(0);
|
||||
for (i = m - 1; i >= l; i--) {
|
||||
f = s * e[i];
|
||||
b = c * e[i];
|
||||
e[i + 1] = (r = pythag(f,g));
|
||||
if (r == Real(0)) {
|
||||
d[i + 1] -= p;
|
||||
e[m] = Real(0);
|
||||
break;
|
||||
}
|
||||
s = f/r;
|
||||
c = g/r;
|
||||
g = d[i + 1] - p;
|
||||
r = (d[i] - g) * s + 2 * c * b;
|
||||
d[i + 1] = g + (p = s * r);
|
||||
g = c * r - b;
|
||||
for (k = 0; k < n; k++) {
|
||||
f = z(k, i + 1);
|
||||
z(k, i + 1) = s * z(k, i) + c * f;
|
||||
z(k, i) = c * z(k, i) - s * f;
|
||||
}
|
||||
}
|
||||
if (r == Real(0) && i >= l) continue;
|
||||
d[l] -= p;
|
||||
e[l] = g;
|
||||
e[m] = Real(0);
|
||||
}
|
||||
} while (m != l);
|
||||
}
|
||||
} // tqli
|
||||
|
||||
|
||||
|
||||
|
||||
// Failed version using T**
|
||||
//
|
||||
// ////////////////////
|
||||
// // ↓ Class Matrix //
|
||||
// ////////////////////
|
||||
|
||||
// export template <class T>
|
||||
// class Matrix {
|
||||
|
||||
// private:
|
||||
// std::size_t dim_;
|
||||
// T** element_;
|
||||
|
||||
// public:
|
||||
// Matrix (std::size_t dim);
|
||||
// // ~Matrix () = default;
|
||||
// ~Matrix ();
|
||||
|
||||
// inline std::size_t size() { return dim_; };
|
||||
|
||||
// // inline T* operator[] (const IndexU i);
|
||||
// // inline const T* operator[] (const IndexU i) const;
|
||||
|
||||
// inline T operator() (IndexU i, IndexU j) const { return element_[i][j]; };
|
||||
// inline T& operator() (IndexU i, IndexU j) { return element_[i][j]; };
|
||||
|
||||
// void setZero();
|
||||
|
||||
// // Matrix& operator= (const Matrix& rhs);
|
||||
|
||||
// Matrix<T>& operator*= (const T& a);
|
||||
// Matrix<T>& operator/= (const T& a);
|
||||
|
||||
// void ludcmp (std::vector<IndexU>& indx, T& d);
|
||||
// void lubksb (std::vector<IndexU>& indx, std::vector<T>& b);
|
||||
// std::complex<long double> lndet_LU_destroy ();
|
||||
// };
|
||||
|
||||
// template <class T>
|
||||
// Matrix<T>::Matrix (std::size_t dim)
|
||||
// : dim_(dim)
|
||||
// , element_(new T*[dim])
|
||||
// {
|
||||
// // element_[0] = new T[dim_*dim_];
|
||||
// // for (IndexU i { 0 }; i + 1 < dim_; i++) element_[i+1] = element_[i] + dim_;
|
||||
// for (IndexU i { 0 }; i < dim_; ++i) element_[i] = new T[dim];
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// Matrix<T>::~Matrix()
|
||||
// {
|
||||
// // if (element_ != 0) {
|
||||
// // delete[] (element_[0]);
|
||||
// // delete[] (element_);
|
||||
// // }
|
||||
// for (IndexU i { 0 }; i < dim_; ++i) delete[] element_[i];
|
||||
// delete[] element_;
|
||||
// }
|
||||
|
||||
// // template <class T>
|
||||
// // inline T* Matrix<T>::operator[] (const IndexU i)
|
||||
// // {
|
||||
// // return element_[i];
|
||||
// // }
|
||||
|
||||
// // template <class T>
|
||||
// // inline const T* Matrix<T>::operator[] (const IndexU i) const
|
||||
// // {
|
||||
// // return element_[i];
|
||||
// // }
|
||||
|
||||
// template <class T>
|
||||
// void Matrix<T>::setZero ()
|
||||
// {
|
||||
// for (IndexU i { 0 }; i < dim_; ++i)
|
||||
// for (IndexU j { 0 }; j < dim_; ++j) element_[i][j] = T(0);
|
||||
// }
|
||||
|
||||
// // template <class T>
|
||||
// // Matrix<T>& Matrix<T>::operator= (const Matrix<T>& rhs)
|
||||
// // {
|
||||
// // if (this != &rhs) {
|
||||
// // if (dim_ != rhs.dim_) {
|
||||
// // throw;
|
||||
// // }
|
||||
|
||||
// // for (int i = 0; i < dim_; ++i)
|
||||
// // for (int j = 0; j < dim_; ++j) element_[i][j] = rhs.element_[i][j];
|
||||
// // }
|
||||
// // return *this;
|
||||
// // }
|
||||
|
||||
|
||||
|
||||
// template <class T>
|
||||
// Matrix<T>& Matrix<T>::operator*= (const T& a)
|
||||
// {
|
||||
// for (IndexU i { 0 }; i < dim_; ++i)
|
||||
// for (IndexU j { 0 }; j < dim_; ++j) element_[i][j] *= a;
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// Matrix<T>& Matrix<T>::operator/= (const T& a)
|
||||
// {
|
||||
// T oneovera = T(1)/a;
|
||||
// for (IndexU i { 0 }; i < dim_; ++i)
|
||||
// for (IndexU j { 0 }; j < dim_; ++j) element_[i][j] *= oneovera;
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
|
||||
// template <class T>
|
||||
// void Matrix<T>::ludcmp (std::vector<IndexU>& indx, T& d)
|
||||
// {
|
||||
// IndexU i, j, k;
|
||||
// IndexU imax { 0 };
|
||||
// T big, dum, sum, temp;
|
||||
|
||||
// IndexU n { size() };
|
||||
|
||||
// std::vector<T> vv(n);
|
||||
// d = T(1);
|
||||
// for (i = 0; i < n; i++) {
|
||||
// big = T(0);
|
||||
// for (j = 0; j < n; j++) {
|
||||
// if ((std::fabs(temp = element_[i][j])) > std::fabs(big)) big = temp;
|
||||
// }
|
||||
// if (big == T(0)) throw;
|
||||
// vv[i] = T(1)/big;
|
||||
// }
|
||||
|
||||
// for (j = 0; j < n; j++) {
|
||||
// for (i = 0; i < j; i++) {
|
||||
// sum = element_[i][j];
|
||||
// for (k = 0; k < i; k++) sum -= element_[i][k] * element_[k][j];
|
||||
// element_[i][j] = sum;
|
||||
// }
|
||||
// big = T(0);
|
||||
// for (i = j; i < n; i++) {
|
||||
// sum = element_[i][j];
|
||||
// for (k = 0; k < j; k++) sum -= element_[i][k] * element_[k][j];
|
||||
// element_[i][j] = sum;
|
||||
// if ((std::fabs(dum = vv[i]*sum)) >= std::fabs(big)) {
|
||||
// big = dum;
|
||||
// imax = i;
|
||||
// }
|
||||
// }
|
||||
// if (j != imax) {
|
||||
// for (k = 0; k < n; k++) {
|
||||
// dum = element_[imax][k];
|
||||
// element_[imax][k] = element_[j][k];
|
||||
// element_[j][k] = dum;
|
||||
// }
|
||||
// d = -d;
|
||||
// vv[imax] = vv[j];
|
||||
// }
|
||||
// indx[j] = imax;
|
||||
// if (j !=n-1) {
|
||||
// dum = T(1)/(element_[j][j]);
|
||||
// for (i = j + 1; i < n; i++) element_[i][j] *= dum;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// void Matrix<T>::lubksb (std::vector<IndexU>& indx, std::vector<T>& b)
|
||||
// {
|
||||
// int i, ip, j;
|
||||
// int ii { 0 };
|
||||
// T sum;
|
||||
|
||||
// int n { int(size()) };
|
||||
// for (i = 0; i < n; i++) {
|
||||
// ip = indx[i];
|
||||
// sum = b[ip];
|
||||
// b[ip] = b[i];
|
||||
// if (ii != 0)
|
||||
// for (j = ii-1; j < i; j++) sum -= element_[i][j] * b[j];
|
||||
// else if (sum != T(0))
|
||||
// ii = i + 1;
|
||||
// b[i] = sum;
|
||||
// }
|
||||
// for (i = n - 1; i >= 0; i--) {
|
||||
// sum = b[i];
|
||||
// for (j = i + 1; j < n; j++) sum -= element_[i][j] * b[j];
|
||||
// b[i] = sum/element_[i][i];
|
||||
// }
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// std::complex<long double> Matrix<T>::lndet_LU_destroy ()
|
||||
// {
|
||||
// std::vector<IndexU> indx(size());
|
||||
// T d;
|
||||
// std::complex<long double> lndet { 0 };
|
||||
|
||||
// (*this).ludcmp(indx, d);
|
||||
|
||||
// lndet = log(std::complex<long double>(d));
|
||||
|
||||
// for (IndexU j { 0 }; j < size(); j++) {
|
||||
// lndet += log(std::complex<long double>(element_[j][j]));
|
||||
// }
|
||||
|
||||
// return lndet;
|
||||
// }
|
||||
|
||||
|
||||
// template <class T>
|
||||
// std::ostream& operator<< (std::ostream& s, const Matrix<T>& M)
|
||||
// {
|
||||
// for (IndexU i { 0 }; i < M.dim(); ++i) {
|
||||
// for (IndexU j { 0 }; j < M.dim(); ++j) s << M[i][j] << "\t";
|
||||
// s << std::endl;
|
||||
// }
|
||||
// return s;
|
||||
// }
|
||||
|
||||
// ////////////////////
|
||||
// // ↑ Class Matrix //
|
||||
// ////////////////////
|
||||
|
||||
|
||||
|
||||
// // Version using vector of vector (not working)
|
||||
|
||||
// ////////////////////
|
||||
// // ↓ Class Matrix //
|
||||
// ////////////////////
|
||||
|
||||
// export template <class T>
|
||||
// class Matrix {
|
||||
|
||||
// private:
|
||||
// std::size_t dim_;
|
||||
// std::vector<std::vector<T>> element_;
|
||||
|
||||
// public:
|
||||
// Matrix (std::size_t dim);
|
||||
// ~Matrix () = default;
|
||||
|
||||
// inline std::size_t size() { return dim_; };
|
||||
// inline std::vector<std::vector<T>> rows () const { return element_; };
|
||||
// inline std::vector<T>& operator[] (const std::size_t i);
|
||||
// inline T operator() (IndexU i, IndexU j) const { return element_[i][j]; };
|
||||
// inline T& operator() (IndexU i, IndexU j) { return element_[i][j]; };
|
||||
|
||||
// void setZero();
|
||||
|
||||
// Matrix<T>& operator*= (const T& a);
|
||||
// Matrix<T>& operator/= (const T& a);
|
||||
|
||||
// void ludcmp (std::vector<IndexU>& indx, T& d);
|
||||
// void lubksb (std::vector<IndexU>& indx, std::vector<T>& b);
|
||||
// std::complex<long double> lndet_LU_destroy ();
|
||||
// };
|
||||
|
||||
// template <class T>
|
||||
// inline std::vector<T>& Matrix<T>::operator[] (const std::size_t i)
|
||||
// {
|
||||
// return element_[i];
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// Matrix<T>::Matrix (std::size_t dim)
|
||||
// : dim_(dim)
|
||||
// , element_(std::vector<std::vector<T>>(dim_, std::vector<T>(dim_)))
|
||||
// {
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// Matrix<T>& Matrix<T>::operator*= (const T& a)
|
||||
// {
|
||||
// for (auto &row : element_)
|
||||
// for (auto &col : row) col *= a;
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// Matrix<T>& Matrix<T>::operator/= (const T& a)
|
||||
// {
|
||||
// for (auto &row : element_)
|
||||
// for (auto &col : row) col /= a;
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// void Matrix<T>::setZero ()
|
||||
// {
|
||||
// for (auto &row : element_)
|
||||
// for (auto &col : row) col = T(0);
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// void Matrix<T>::ludcmp (std::vector<IndexU>& indx, T& d)
|
||||
// {
|
||||
// IndexU i, j, k;
|
||||
// IndexU imax { 0 };
|
||||
// T big, dum, sum, temp;
|
||||
|
||||
// IndexU n { size() };
|
||||
|
||||
// std::vector<T> vv(n);
|
||||
// d = T(1);
|
||||
// for (i = 0; i < n; i++) {
|
||||
// big = T(0);
|
||||
// for (j = 0; j < n; j++) {
|
||||
// if ((std::fabs(temp = element_[i][j])) > std::fabs(big)) big = temp;
|
||||
// }
|
||||
// if (big == T(0)) throw;
|
||||
// vv[i] = T(1)/big;
|
||||
// }
|
||||
|
||||
// for (j = 0; j < n; j++) {
|
||||
// for (i = 0; i < j; i++) {
|
||||
// sum = element_[i][j];
|
||||
// for (k = 0; k < i; k++) sum -= element_[i][k] * element_[k][j];
|
||||
// element_[i][j] = sum;
|
||||
// }
|
||||
// big = T(0);
|
||||
// for (i = j; i < n; i++) {
|
||||
// sum = element_[i][j];
|
||||
// for (k = 0; k < j; k++) sum -= element_[i][k] * element_[k][j];
|
||||
// element_[i][j] = sum;
|
||||
// if ((std::fabs(dum = vv[i]*sum)) >= std::fabs(big)) {
|
||||
// big = dum;
|
||||
// imax = i;
|
||||
// }
|
||||
// }
|
||||
// if (j != imax) {
|
||||
// for (k = 0; k < n; k++) {
|
||||
// dum = element_[imax][k];
|
||||
// element_[imax][k] = element_[j][k];
|
||||
// element_[j][k] = dum;
|
||||
// }
|
||||
// d = -d;
|
||||
// vv[imax] = vv[j];
|
||||
// }
|
||||
// indx[j] = imax;
|
||||
// if (j !=n-1) {
|
||||
// dum = T(1)/(element_[j][j]);
|
||||
// for (i = j + 1; i < n; i++) element_[i][j] *= dum;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// void Matrix<T>::lubksb (std::vector<IndexU>& indx, std::vector<T>& b)
|
||||
// {
|
||||
// int i, ip, j;
|
||||
// int ii { 0 };
|
||||
// T sum;
|
||||
|
||||
// int n { int(size()) };
|
||||
// for (i = 0; i < n; i++) {
|
||||
// ip = indx[i];
|
||||
// sum = b[ip];
|
||||
// b[ip] = b[i];
|
||||
// if (ii != 0)
|
||||
// for (j = ii-1; j < i; j++) sum -= element_[i][j] * b[j];
|
||||
// else if (sum != T(0))
|
||||
// ii = i + 1;
|
||||
// b[i] = sum;
|
||||
// }
|
||||
// for (i = n - 1; i >= 0; i--) {
|
||||
// sum = b[i];
|
||||
// for (j = i + 1; j < n; j++) sum -= element_[i][j] * b[j];
|
||||
// b[i] = sum/element_[i][i];
|
||||
// }
|
||||
// }
|
||||
|
||||
// template <class T>
|
||||
// std::complex<long double> Matrix<T>::lndet_LU_destroy ()
|
||||
// {
|
||||
// std::vector<IndexU> indx(size());
|
||||
// T d;
|
||||
// std::complex<long double> lndet { 0 };
|
||||
|
||||
// (*this).ludcmp(indx, d);
|
||||
|
||||
// lndet = log(std::complex<long double>(d));
|
||||
|
||||
// for (IndexU j { 0 }; j < size(); j++) {
|
||||
// lndet += log(std::complex<long double>(element_[j][j]));
|
||||
// }
|
||||
|
||||
// return lndet;
|
||||
// }
|
||||
|
||||
|
||||
// template <class T>
|
||||
// std::ostream& operator<< (std::ostream& s, const Matrix<T>& M)
|
||||
// {
|
||||
// for (auto row : M.rows()) {
|
||||
// for (auto col : row) s << col << "\t";
|
||||
// s << std::endl;
|
||||
// }
|
||||
// return s;
|
||||
// }
|
||||
|
||||
// ////////////////////
|
||||
// // ↑ Class Matrix //
|
||||
// ////////////////////
|
||||
Reference in New Issue
Block a user