////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014 The Regents of the University of California
//
// This file is part of Qbox
//
// Qbox is distributed under the terms of the GNU General Public License
// as published by the Free Software Foundation, either version 2 of
// the License, or (at your option) any later version.
// See the file COPYING in the root directory of this distribution
// or .
//
////////////////////////////////////////////////////////////////////////////////
//
// D3tensor.h
//
// double 3x3 tensor
//
////////////////////////////////////////////////////////////////////////////////
#ifndef D3TENSOR_H
#define D3TENSOR_H
#include
#include
#include
#include
#include "blas.h"
#include "D3vector.h"
using namespace std;
class D3tensor
{
public:
double a_[9];
double* a(void) { return &a_[0]; }
const double* a(void) const { return &a_[0]; }
explicit D3tensor(void) { clear(); }
explicit D3tensor(double xx, double yy, double zz)
{ a_[0]=xx; a_[4]=yy; a_[8]=zz; }
explicit D3tensor(double xx, double yy, double zz,
double xy, double yz, double xz, char& uplo)
{
a_[0] = xx;
a_[4] = yy;
a_[8] = zz;
if ( uplo == 'l' )
{
a_[1] = xy;
a_[2] = xz;
a_[5] = yz;
}
else if ( uplo == 'u' )
{
a_[3] = xy;
a_[6] = xz;
a_[7] = yz;
}
else if ( uplo == 's' )
{
a_[1] = xy;
a_[2] = xz;
a_[5] = yz;
a_[3] = xy;
a_[6] = xz;
a_[7] = yz;
}
else
assert(false);
}
explicit D3tensor(const D3vector& diag, const D3vector& offdiag)
{
a_[0] = diag[0];
a_[4] = diag[1];
a_[8] = diag[2];
a_[1] = offdiag[0];
a_[5] = offdiag[1];
a_[2] = offdiag[2];
a_[3] = offdiag[0];
a_[7] = offdiag[1];
a_[6] = offdiag[2];
}
explicit D3tensor(const double* a)
{
for ( int i = 0; i < 9; i++ ) a_[i] = a[i];
}
double& operator[](int i)
{
assert(i>=0 && i < 9);
return a_[i];
}
double operator[](int i) const
{
assert(i>=0 && i < 9);
return a_[i];
}
void setdiag(int i, double b)
{
assert(i>=0 && i<3);
a_[i*4] = b;
}
void setdiag(const D3vector& b)
{
for ( int i = 0; i < 3; i++ )
a_[i*4] = b[i];
}
void setoffdiag(int i, double b)
{
assert(i>=0 && i<3);
if ( i == 0 )
{
a_[1] = b;
a_[3] = b;
}
else if ( i == 2 )
{
a_[2] = b;
a_[6] = b;
}
else
{
a_[5] = b;
a_[7] = b;
}
}
void setoffdiag(const D3vector& b)
{
a_[1] = b[0];
a_[3] = b[0];
a_[5] = b[1];
a_[7] = b[1];
a_[2] = b[2];
a_[6] = b[2];
}
bool operator==(const D3tensor &rhs) const
{
bool eq = true;
for ( int i = 0; i < 9; i++ )
{
if ( rhs[i] != a_[i] )
{
eq &= false;
}
}
return eq;
}
bool operator!=(const D3tensor &rhs) const
{
bool neq = false;
for ( int i = 0; i < 9; i++ )
{
if ( rhs[i] != a_[i] )
{
neq |= true;
}
}
return neq;
}
D3tensor& operator+=(const D3tensor& rhs)
{
for ( int i = 0; i < 9; i++ )
a_[i] += rhs[i];
return *this;
}
D3tensor& operator-=(const D3tensor& rhs)
{
for ( int i = 0; i < 9; i++ )
a_[i] -= rhs[i];
return *this;
}
D3tensor& operator*=(const double& rhs)
{
for ( int i = 0; i < 9; i++ )
a_[i] *= rhs;
return *this;
}
D3tensor& operator/=(const double& rhs)
{
for ( int i = 0; i < 9; i++ )
a_[i] /= rhs;
return *this;
}
friend const D3tensor operator+(const D3tensor& lhs, const D3tensor& rhs)
{
return D3tensor(lhs) += rhs;
}
friend const D3tensor operator-(const D3tensor& a, const D3tensor& b)
{
return D3tensor(a) -= b;
}
friend D3tensor operator*(double a, const D3tensor& b)
{
return D3tensor(b) *= a;
}
friend D3tensor operator*(const D3tensor& a, double b)
{
return D3tensor(a) *= b;
}
friend D3tensor operator/(const D3tensor& a, double b)
{
return D3tensor(a) /= b;
}
friend D3tensor operator*(D3tensor& a, D3tensor& b)
{
D3tensor c;
int ithree = 3;
double one = 1.0, zero = 0.0;
char t = 'n';
dgemm ( &t, &t, &ithree, &ithree, &ithree, &one, &a[0], &ithree,
&b[0], &ithree, &zero, &c[0], &ithree );
return c;
}
friend D3tensor operator-(const D3tensor& a) // unary minus
{
return D3tensor()-a;
}
double norm2(const D3tensor& a) const
{
return a[0]*a[0] + a[1]*a[1] + a[2]*a[2] +
a[3]*a[3] + a[4]*a[4] + a[5]*a[5] +
a[6]*a[6] + a[7]*a[7] + a[8]*a[8];
}
double norm(const D3tensor& a) const
{
return sqrt(norm2(a));
}
double trace(void) const
{
return a_[0]+a_[4]+a_[8];
}
void traceless(void)
{
double b = trace() / 3;
a_[0] -= b;
a_[4] -= b;
a_[8] -= b;
}
void clear(void)
{
for ( int i = 0; i < 9; i++ )
a_[i] = 0.0;
}
void identity(void)
{
clear();
a_[0] = 1.0;
a_[4] = 1.0;
a_[8] = 1.0;
}
friend std::ostream& operator<<(std::ostream& os, const D3tensor& rhs)
{
const double * const v = rhs.a();
os.setf(ios::fixed,ios::floatfield);
os.setf(ios::right,ios::adjustfield);
os.precision(8);
os << setw(14) << v[0] << " " << setw(14) << v[3] << " " << setw(14) << v[6]
<< "\n"
<< setw(14) << v[1] << " " << setw(14) << v[4] << " " << setw(14) << v[7]
<< "\n"
<< setw(14) << v[2] << " " << setw(14) << v[5] << " " << setw(14) << v[8]
<< "\n";
return os;
}
void syev(char uplo, D3vector& eigval, D3tensor& eigvec)
{
double w[3];
int info;
char jobz = 'V';
int lwork=-1;
double tmplwork;
int n = 3;
dsyev(&jobz, &uplo, &n, eigvec.a(), &n, &w[0], &tmplwork, &lwork, &info);
lwork = (int) tmplwork + 1;
double* work = new double[lwork];
eigvec = *this;
dsyev(&jobz, &uplo, &n, eigvec.a(), &n, &w[0], work, &lwork, &info);
delete[] work;
eigval = D3vector(&w[0]);
}
};
#endif