diff --git a/la_random.h b/la_random.h index 3811497..d6e544c 100644 --- a/la_random.h +++ b/la_random.h @@ -3,23 +3,23 @@ namespace LA { -//RANDOM numbers defaulting to standard library but switchable to user's functions -#ifndef RANDDOUBLE -#define RANDDOUBLE randdouble -#endif - -#ifndef RANDDOUBLESIGNED -#define RANDDOUBLESIGNED randdoublesigned -#endif - -#ifndef RANDINT32 -#define RANDINT32 randint32 -#endif - extern double randdouble(); extern double randdoublesigned(); extern int randint32(); +//RANDOM numbers defaulting to standard library but switchable to user's functions +#ifndef RANDDOUBLE +#define RANDDOUBLE LA::randdouble +#endif + +#ifndef RANDDOUBLESIGNED +#define RANDDOUBLESIGNED LA::randdoublesigned +#endif + +#ifndef RANDINT32 +#define RANDINT32 LA::randint32 +#endif + #ifdef __GNUC__ #define WEAK_SYMBOL __attribute__((weak)) #else diff --git a/la_traits.h b/la_traits.h index dc682b7..5db3801 100644 --- a/la_traits.h +++ b/la_traits.h @@ -68,6 +68,13 @@ extern "C" { } #endif + +//forward declarations +namespace LA_Vecmat3 { +template class Vec3; +template class Mat3; +} + namespace LA { diff --git a/mat.cc b/mat.cc index 798f903..3a58b6a 100644 --- a/mat.cc +++ b/mat.cc @@ -3411,6 +3411,8 @@ for(int j=0; j; template class NRMat >; +//template class NRMat; +//template class NRMat >; template class NRMat; template class NRMat; template class NRMat; diff --git a/mat.h b/mat.h index bc6c967..91d4bfb 100644 --- a/mat.h +++ b/mat.h @@ -22,6 +22,10 @@ #define _LA_MAT_H_ #include "la_traits.h" +using namespace LA_Vecmat3; + +#include "vecmat3.h" + namespace LA { @@ -82,8 +86,9 @@ public: inline NRMat(const T &a, const int n, const int m); //! inlined constructor creating matrix of given size filled with data located at given memory location - NRMat(const T *a, const int n, const int m); - + inline NRMat(const T *a, const int n, const int m); + inline NRMat(const Mat3 &rhs) : NRMat(&rhs(0,0),3,3) {}; + //! inlined constructor creating matrix of given size from an array template inline NRMat(const T (&a)[R][C]); @@ -615,7 +620,6 @@ NRMat::NRMat(const T *a, const int n, const int m) : nn(n), mm(m), count(new cublasSetVector(nm, sizeof(T), a, 1, v, 1); } #endif - } /***************************************************************************//** diff --git a/smat.cc b/smat.cc index dff16ac..4f5e9ef 100644 --- a/smat.cc +++ b/smat.cc @@ -872,7 +872,8 @@ NRSMat > NRSMat >::inverse() {return ******************************************************************************/ template class NRSMat; template class NRSMat >; - +//template class NRSMat; +//template class NRSMat >; template class NRSMat; template class NRSMat; template class NRSMat; diff --git a/t.cc b/t.cc index c37d456..7d22e69 100644 --- a/t.cc +++ b/t.cc @@ -426,7 +426,7 @@ cout < a; cin >>a ; @@ -2784,5 +2784,32 @@ NRSMat adjperm = adj.permuted(p); cout <<"resorted graph = "< a; +a.randomize(10.); +cout< ata = a.transpose()*a; +Mat3 work(ata); +Vec3 w; +Mat3 v; +work.eivec_sym(w,v,true); +cout < aat = a*a.transpose(); +Mat3 work2(aat); +Vec3 w2; +Mat3 v2; +work2.eivec_sym(w2,v2,true); +cout < aa(a); +cout < uu(3,3),vv(3,3); +NRVec ss(3); +singular_decomposition(aa,&uu,ss,&vv,0); +cout < #include "vec.h" #include - +#include "vecmat3.h" namespace LA { @@ -904,6 +904,7 @@ void NRVec::storesubvector(const NRVec &selection, const NRVec &rhs) } + /***************************************************************************//** * forced instantization in the corespoding object file ******************************************************************************/ @@ -1039,6 +1040,8 @@ INSTANTIZE_CONCAT(std::complex) +//template class NRVec; +//template class NRVec >; template class NRVec; template class NRVec >; template class NRVec; diff --git a/vec.h b/vec.h index 28ee8fe..6493b6f 100644 --- a/vec.h +++ b/vec.h @@ -21,8 +21,11 @@ #define _LA_VEC_H_ #include "la_traits.h" +#include "vecmat3.h" #include +using namespace LA_Vecmat3; + namespace LA { /***************************************************************************//** @@ -134,6 +137,7 @@ public: //! inlined constructor creating vector of given size filled with data located at given memory location inline NRVec(const T *a, const int n); + inline NRVec(const Vec3 &rhs) : NRVec(&rhs[0],3) {}; //! inlined constructor creating vector of given size filled with data located at given memory location inline NRVec(T *a, const int n, bool skeleton); diff --git a/vecmat3.cc b/vecmat3.cc index 86d2174..ef30d54 100644 --- a/vecmat3.cc +++ b/vecmat3.cc @@ -17,6 +17,9 @@ */ #include "vecmat3.h" +#ifndef QUAT_NO_RANDOM +#include "la_random.h" +#endif namespace LA_Vecmat3 { @@ -613,6 +616,24 @@ tmp=(q[2][1]+q[1][2])/2; q[2][1]=q[1][2]=tmp; } + +#ifndef QUAT_NO_RANDOM +template <> +void Vec3::randomize(const double x) +{ +for(int i=0;i<3;++i) q[i]=x*RANDDOUBLESIGNED(); +} + + +template <> +void Mat3::randomize(const double x, const bool symmetric) +{ +if(symmetric) for(int i=0;i<3;++i) for(int j=0; j<=i; ++j) q[j][i]=q[i][j]=x*RANDDOUBLESIGNED(); +else for(int i=0;i<3;++i) for(int j=0; j<3; ++j) q[i][j]=x*RANDDOUBLESIGNED(); +} + +#endif + //eigensolver for 3x3 matrix by Joachim Kopp - analytic formula version, //might be unstable for ill-conditioned ones, then use other methods //cf. arxiv physics 0610206v3 @@ -651,7 +672,7 @@ q[2][1]=q[1][2]=tmp; #define SQR(x) ((x)*(x)) // x^2 // template -void Mat3::eival_sym(Vec3 &w) const +void Mat3::eival_sym(Vec3 &w, const bool sortdown) const { T m, c1, c0; @@ -685,10 +706,19 @@ T m, c1, c0; w[0] = w[1] + c; w[1] -= s; +if(sortdown) + { + if(w[0]w[1]) {T tmp=w[0]; w[0]=w[1]; w[1]=tmp;} -if(w[0]>w[2]) {T tmp=w[0]; w[0]=w[2]; w[2]=tmp;} -if(w[1]>w[2]) {T tmp=w[1]; w[1]=w[2]; w[2]=tmp;} + { + if(w[0]>w[1]) {T tmp=w[0]; w[0]=w[1]; w[1]=tmp;} + if(w[0]>w[2]) {T tmp=w[0]; w[0]=w[2]; w[2]=tmp;} + if(w[1]>w[2]) {T tmp=w[1]; w[1]=w[2]; w[2]=tmp;} + } } // Calculates the eigenvalues and normalized eigenvectors of a symmetric 3x3 @@ -717,7 +747,7 @@ if(w[1]>w[2]) {T tmp=w[1]; w[1]=w[2]; w[2]=tmp;} // v1.0: First released version // ---------------------------------------------------------------------------- template -void Mat3::eivec_sym(Vec3 &w, Mat3 &v) const +void Mat3::eivec_sym(Vec3 &w, Mat3 &v, const bool sortdown) const { T norm; // Squared norm or inverse norm of current eigenvector T n0, n1; // Norm of first and second columns of A @@ -729,7 +759,7 @@ void Mat3::eivec_sym(Vec3 &w, Mat3 &v) const int i, j; // Loop counters // Calculate eigenvalues - eival_sym(w); + eival_sym(w,sortdown); Mat3 A(*this); //scratch copy wmax = fabs(w[0]); diff --git a/vecmat3.h b/vecmat3.h index 95f6f4c..acd237e 100644 --- a/vecmat3.h +++ b/vecmat3.h @@ -16,7 +16,7 @@ along with this program. If not, see . */ -//this header defines simple classes for 3-dimensional vectors and matrices to describe rotations etc. +//this header defines simple classes for 3-dimensional REAL-valued vectors and matrices to describe rotations etc. //the class is compatible with functions in quaternion.h used for SO(3) parametrization //it should be compilable separately from LA as well as being a part of LA @@ -62,7 +62,7 @@ public: //compiler generates default copy constructor and assignment operator //formal indexing - inline const T operator[](const int i) const {return q[i];}; + inline const T& operator[](const int i) const {return q[i];}; inline T& operator[](const int i) {return q[i];}; //operations of Vec3s with scalars @@ -89,6 +89,7 @@ public: const Vec3 timesT(const Mat3 &rhs) const; //with transpose Mat3 outer(const Vec3 &rhs) const; //tensor product void inertia(Mat3 &itensor, const T weight) const; //contribution to inertia tensor + void randomize(const T x); //C-style IO int fprintf(FILE *f, const char *format) const {return ::fprintf(f,format,q[0],q[1],q[2]);}; @@ -130,7 +131,7 @@ public: //formal indexing inline const T* operator[](const int i) const {return q[i];}; inline T* operator[](const int i) {return q[i];}; - inline const T operator()(const int i, const int j) const {return q[i][j];}; + inline const T& operator()(const int i, const int j) const {return q[i][j];}; inline T& operator()(const int i, const int j) {return q[i][j];}; @@ -145,6 +146,8 @@ public: const Mat3 operator*(const T rhs) const {return Mat3(*this) *= rhs;}; const Mat3 operator/(const T rhs) const {return Mat3(*this) /= rhs;}; + void randomize(const T x, const bool symmetric=false); + //Mat3 algebra const Mat3 operator-() const {return *this * (T)-1;}; //unary minus Mat3& operator+=(const Mat3 &rhs); @@ -166,8 +169,8 @@ public: int fprintf(FILE *f, const char *format) const {int n= ::fprintf(f,format,q[0][0],q[0][1],q[0][2]); n+=::fprintf(f,format,q[1][0],q[1][1],q[1][2]); n+=::fprintf(f,format,q[2][0],q[2][1],q[2][2]); return n;}; int fscanf(FILE *f, const char *format) const {return ::fscanf(f,format,q[0][0],q[0][1],q[0][2]) + ::fscanf(f,format,q[1][0],q[1][1],q[1][2]) + ::fscanf(f,format,q[2][0],q[2][1],q[2][2]);}; void symmetrize(); //average offdiagonal elements - void eival_sym(Vec3 &w) const; //only for real symmetric matrix, symmetry is not checked - void eivec_sym(Vec3 &w, Mat3 &v) const; //only for real symmetric matrix, symmetry is not checked + void eival_sym(Vec3 &w, const bool sortdown=false) const; //only for real symmetric matrix, symmetry is not checked + void eivec_sym(Vec3 &w, Mat3 &v, const bool sortdown=false) const; //only for real symmetric matrix, symmetry is not checked T norm(const T scalar = 0) const; };