Skip to content

Commit d74a0ef

Browse files
authored
Typed vector and tensor (plumed#1092)
* templatized runtime fastpow * templatized the type of LoopUnroller * templatized the type of Vector * templatized the type of Tensor * constexpr everithing! * solving some cpp checks * rounded a few compatibilities between the new Vector and View * Updating Vector and Tensor with conversion and types interactions * added and checked the possibility of using ssyevr * lowestEigenpairSym typing * Changing the precision in rt-make-4 * adressed codecheck uninitialized return variable --------- Co-authored-by: Daniele Rapetti <5535617+Iximiel@users.noreply.github.com>
1 parent 13d0f4d commit d74a0ef

File tree

18 files changed

+1821
-710
lines changed

18 files changed

+1821
-710
lines changed

regtest/basic/rt-lowest-eigenpair/eigenValues_float.reference

Lines changed: 405 additions & 0 deletions
Large diffs are not rendered by default.

regtest/basic/rt-lowest-eigenpair/eigenVectors_float.reference

Lines changed: 405 additions & 0 deletions
Large diffs are not rendered by default.

regtest/basic/rt-lowest-eigenpair/main.cpp

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ using namespace PLMD;
1616

1717
namespace {
1818

19-
static Tensor4d makeMatrix(const Tensor & rr01) {
20-
Tensor4d m;
19+
template<typename precision>
20+
static auto makeMatrix(const TensorT<precision> & rr01) {
21+
TensorTyped<precision,4,4> m;
2122
m[0][0]= +rr01[0][0]+rr01[1][1]+rr01[2][2];
2223
m[1][1]= +rr01[0][0]-rr01[1][1]-rr01[2][2];
2324
m[2][2]= -rr01[0][0]+rr01[1][1]-rr01[2][2];
@@ -51,9 +52,9 @@ inline void DoNotOptimize(T& value) {
5152
}
5253

5354

54-
55-
PLMD::Tensor randomRMSDmat(rng & gen, const double referencedistance=1.0) {
56-
PLMD::Tensor toret;
55+
template <typename precision>
56+
auto randomRMSDmat(rng & gen, const double referencedistance=1.0) {
57+
TensorT<precision> toret;
5758
constexpr size_t n=30;
5859

5960
std::vector<double> align(n);
@@ -86,16 +87,17 @@ PLMD::Tensor randomRMSDmat(rng & gen, const double referencedistance=1.0) {
8687
// second expensive loop: compute second moments wrt centers
8788
for(unsigned iat=0; iat<n; iat++) {
8889
double w=align[iat];
89-
toret+=Tensor(positions[iat]-cpositions,reference[iat])*w;
90+
PLMD::LoopUnroller<9>::_add(toret.data(),
91+
(Tensor(positions[iat]-cpositions,reference[iat])*w).data());
9092
}
9193
return toret;
9294
}
9395

94-
95-
int main() {
96+
template <typename T>
97+
void doTest(std::string suffix="") {
9698
std::cerr <<std::setprecision(9) << std::fixed;
9799

98-
std::vector<PLMD::Tensor> tests= {
100+
std::vector<PLMD::TensorT<T>> tests= {
99101
// {1,1,1,1,1,1,1,1,1}, // 'wrong' eigenvector selected (due to the degeneracy)
100102
// {1,2,3,4,5,6,7,8,9}, // 'wrong' eigenvector selected (due to the degeneracy)
101103
{0,1,1,1,1,1,1,1,1},
@@ -125,14 +127,14 @@ int main() {
125127
gen.setSeed(123456789);
126128
double error=100.0;
127129
for(int i=0; i<400; i++) {
128-
tests.push_back(randomRMSDmat(gen,error));
130+
tests.push_back(randomRMSDmat<T>(gen,error));
129131
if(i%50) {
130132
error/=10.0;
131133
}
132134
}
133-
std::ofstream matOut ("matrices");
134-
std::ofstream out ("eigenValues");
135-
std::ofstream outv ("eigenVectors");
135+
std::ofstream matOut ("matrices"+suffix);
136+
std::ofstream out ("eigenValues"+suffix);
137+
std::ofstream outv ("eigenVectors"+suffix);
136138
// setting up an header for clarity
137139

138140
matOut<<"# id:";
@@ -162,12 +164,12 @@ int main() {
162164
const auto& mat = tests[index];
163165
auto m=makeMatrix(mat);
164166

165-
Vector1d eigenval_ref;
166-
TensorGeneric<1,4> eigenvec_ref;
167+
VectorTyped<T,1> eigenval_ref;
168+
TensorTyped<T,1,4> eigenvec_ref;
167169
diagMatSym(m, eigenval_ref, eigenvec_ref );
168170

169-
double eigenval;
170-
Vector4d eigenvec;
171+
T eigenval;
172+
PLMD::VectorTyped<T,4> eigenvec;
171173
eigenval=lowestEigenpairSym(m,eigenvec);
172174

173175
matOut <<std::setw(4)<<index <<":";
@@ -178,7 +180,12 @@ int main() {
178180
matOut<<"\n";
179181

180182
out <<std::setw(4)<<index <<":";
181-
out<<" "<<std::setw(10) <<eigenval_ref[0] - eigenval;
183+
if constexpr (std::is_same_v<T,double>) {
184+
out<<" "<<std::setw(10) <<eigenval_ref[0] - eigenval;
185+
} else {
186+
auto tmp = eigenval_ref[0] - eigenval;
187+
out<<" "<<std::setw(10) <<((std::fabs(tmp) < 1e-4) ? T(0.0): tmp);
188+
}
182189
out<<"\n";
183190

184191
double modulo2_ref=0.0;
@@ -198,7 +205,7 @@ int main() {
198205

199206
//Timings
200207
{
201-
std::vector<PLMD::Tensor4d> matrices(tests.size());
208+
std::vector<PLMD::TensorTyped<T,4,4>> matrices(tests.size());
202209
for(size_t i=0; i< tests.size(); ++i) {
203210
matrices[i] = makeMatrix(tests[i]);
204211
}
@@ -210,8 +217,8 @@ int main() {
210217
for (const auto & mat : matrices) {
211218
auto sww = sw.startStop("diagMatSym");
212219

213-
Vector1d eigenvals;
214-
TensorGeneric<1,4> eigenvecs;
220+
VectorTyped<T,1> eigenvals;
221+
TensorTyped<T,1,4> eigenvecs;
215222

216223
diagMatSym(mat, eigenvals, eigenvecs );
217224
DoNotOptimize(eigenvals);
@@ -224,16 +231,21 @@ int main() {
224231
for (const auto & mat : matrices) {
225232
auto sww = sw.startStop("compute_quaternion_from_K");
226233

227-
double eigenvals;
228-
Vector4d eigenvecs;
234+
VectorTyped<T,4> eigenvecs;
229235

230-
eigenvals=lowestEigenpairSym(mat, eigenvecs);
236+
auto eigenvals=lowestEigenpairSym(mat, eigenvecs);
231237
DoNotOptimize(eigenvals);
232238
DoNotOptimize(eigenvecs);
233239
}
234240
}
235241
}
236242
std::cerr<<sw;
237243
}
244+
}
245+
int main () {
246+
doTest<double>();
247+
std::cerr << "\n\nFloating point\n\n";
248+
doTest<float>("_float");
249+
238250
return 0;
239251
}

regtest/basic/rt-make-0/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
type=make
2+
#should we rename this to something meaningful? like "rt-VectorTensor"?

regtest/basic/rt-make-4/main.cpp

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,60 @@
22
#include "plumed/tools/Matrix.h"
33
#include "plumed/tools/Tensor.h"
44

5-
int main () {
5+
template <typename precision>
6+
void matrixTest (PLMD::OFile& out, const std::string& fmt) {
67

78
// Define symmetric matrix
8-
PLMD::Matrix<double> mat1(3,3); PLMD::OFile out; out.open("output");
9-
mat1(0,0)=1.0; mat1(0,1)=0.2; mat1(0,2)=0.3;
10-
mat1(1,0)=0.2; mat1(1,1)=0.2; mat1(1,2)=0.6;
11-
mat1(2,0)=0.3; mat1(2,1)=0.6; mat1(2,2)=0.4;
9+
PLMD::Matrix<precision> mat1(3,3);
10+
mat1(0,0)=1.0;
11+
mat1(0,1)=0.2;
12+
mat1(0,2)=0.3;
13+
mat1(1,0)=0.2;
14+
mat1(1,1)=0.2;
15+
mat1(1,2)=0.6;
16+
mat1(2,0)=0.3;
17+
mat1(2,1)=0.6;
18+
mat1(2,2)=0.4;
1219

1320
// Test diagonalize
14-
std::vector<double> eigval(3); PLMD::Matrix<double> eigvec(3,3);
15-
diagMat( mat1, eigval, eigvec );
16-
out<<"Eigenvalues "<<eigval[0]<<" "<<eigval[1]<<" "<<eigval[2]<<"\n";
21+
std::vector<precision> eigval(3);
22+
PLMD::Matrix<precision> eigvec(3,3);
23+
diagMat( mat1, eigval, eigvec );
24+
out.printf(("Eigenvalues "+fmt+" "+fmt+" "+fmt+"\n").c_str(),
25+
eigval[0],eigval[1],eigval[2]);
1726
out<<"Eigenvectors : \n";
18-
for(unsigned i=0;i<3;++i){
19-
out<<eigvec(i,0)<<" "<<eigvec(i,1)<<" "<<eigvec(i,2)<<"\n";
27+
for(unsigned i=0; i<3; ++i) {
28+
out.printf((fmt+" "+fmt+" "+fmt+"\n").c_str(),
29+
eigvec(i,0), eigvec(i,1), eigvec(i,2));
2030
}
2131

2232
// Test inverse
2333
out<<"Inverse : \n";
24-
PLMD::Matrix<double> inverse(3,3); Invert( mat1, inverse );
25-
for(unsigned i=0;i<3;++i){
26-
for(unsigned j=0;j<3;++j) out<<inverse(i,j)<<" ";
27-
out<<"\n";
34+
PLMD::Matrix<precision> inverse(3,3);
35+
Invert( mat1, inverse );
36+
for(unsigned i=0; i<3; ++i) {
37+
for(unsigned j=0; j<3; ++j) {
38+
out.printf((" "+fmt).c_str(),inverse(i,j));
39+
}
40+
out<<"\n";
2841
}
2942

30-
// Test pseudoinverse
43+
// Test pseudoinverse
3144
out<<"Pseudoinverse : \n";
32-
PLMD::Matrix<double> mat(3,2);
33-
mat(0,0)=0.1; mat(0,1)=0.2;
34-
mat(1,0)=0.3; mat(1,1)=0.5;
35-
mat(2,0)=0.4; mat(2,1)=0.6;
36-
PLMD::Matrix<double> pseu(2,3);
45+
PLMD::Matrix<precision> mat(3,2);
46+
mat(0,0)=0.1;
47+
mat(0,1)=0.2;
48+
mat(1,0)=0.3;
49+
mat(1,1)=0.5;
50+
mat(2,0)=0.4;
51+
mat(2,1)=0.6;
52+
PLMD::Matrix<precision> pseu(2,3);
3753
pseudoInvert( mat, pseu );
38-
for(unsigned i=0;i<pseu.nrows();++i){
39-
for(unsigned j=0;j<pseu.ncols();++j) out<<" "<<pseu(i,j);
40-
out<<"\n";
54+
for(unsigned i=0; i<pseu.nrows(); ++i) {
55+
for(unsigned j=0; j<pseu.ncols(); ++j) {
56+
out.printf((" "+fmt).c_str(),pseu(i,j));
57+
}
58+
out<<"\n";
4159
}
4260

4361

@@ -47,11 +65,13 @@ int main () {
4765
/// This would trigger an error before fix
4866
/// f1da0a9b3a13f904bd97d6f92a2fb5e1b6479ac0
4967
{
50-
PLMD::TensorGeneric<4,4> mat;
51-
PLMD::TensorGeneric<1,4> evec;
52-
PLMD::VectorGeneric<4> eval_underlying;
68+
PLMD::TensorTyped<precision,4,4> mat;
69+
PLMD::TensorTyped<precision,1,4> evec;
70+
PLMD::VectorTyped<precision,4> eval_underlying;
5371

54-
auto eval = new(&eval_underlying[0]) PLMD::VectorGeneric<1>;
72+
//The both of the two following lines are scary, but on my machine are equivalent
73+
//PLMD::Vector1d* eval=reinterpret_cast<PLMD::Vector1d*>(eval_underlying.data());
74+
auto eval = new(&eval_underlying[0]) PLMD::VectorTyped<precision,1>;
5575

5676
mat[1][0]=mat[0][1]=3.0;
5777
mat[1][1]=5.0;
@@ -61,16 +81,16 @@ int main () {
6181

6282
out<<"Test diagmat (identical eigenvalues)\n";
6383
/// Also eval_underlying[1] will be modified
64-
out<<eval_underlying[0]<<" "<<eval_underlying[1];
65-
out<<"\n";
84+
out.printf((fmt+" "+fmt+"\n").c_str(),
85+
eval_underlying[0], eval_underlying[1]);
6686
}
6787

6888
{
69-
PLMD::TensorGeneric<4,4> mat;
70-
PLMD::TensorGeneric<1,4> evec;
71-
PLMD::VectorGeneric<4> eval_underlying;
89+
PLMD::TensorTyped<precision,4,4> mat;
90+
PLMD::TensorTyped<precision,1,4> evec;
91+
PLMD::VectorTyped<precision,4> eval_underlying;
7292

73-
auto eval = new(&eval_underlying[0]) PLMD::VectorGeneric<1>;
93+
auto eval = new(&eval_underlying[0]) PLMD::VectorTyped<precision,1>;
7494

7595
mat[1][0]=mat[0][1]=3.0;
7696
mat[1][1]=5.0;
@@ -79,18 +99,18 @@ int main () {
7999
PLMD::diagMatSym(mat,*eval,evec);
80100

81101
out<<"Test diagmat (different eigenvalues)\n";
82-
out<<eval_underlying[0]<<" "<<eval_underlying[1];
83-
out<<"\n";
102+
out.printf((fmt+" "+fmt+"\n").c_str(),
103+
eval_underlying[0], eval_underlying[1]);
84104
}
85105

86106
/// The following is to test the fact that
87107
/// dsyevr actually modifies the diagonalized matrix
88108
/// This would trigger an error before fix
89109
/// f1da0a9b3a13f904bd97d6f92a2fb5e1b6479ac0
90110
{
91-
PLMD::TensorGeneric<4,4> mat;
92-
PLMD::TensorGeneric<4,4> evec;
93-
PLMD::VectorGeneric<4> eval;
111+
PLMD::TensorTyped<precision,4,4> mat;
112+
PLMD::TensorTyped<precision,4,4> evec;
113+
PLMD::VectorTyped<precision,4> eval;
94114

95115
mat[1][0]=mat[0][1]=3.0;
96116
mat[1][1]=5.0;
@@ -100,19 +120,32 @@ int main () {
100120

101121
out<<"Test diagmat (is matrix modified)\n";
102122
out<<"Before:\n";
103-
for(unsigned i=0;i<4;i++) {
104-
for(unsigned j=0;j<4;j++) out<<" "<<mat[i][j];
123+
for(unsigned i=0; i<4; i++) {
124+
for(unsigned j=0; j<4; j++) {
125+
out.printf((" "+fmt).c_str(),mat[i][j]);
126+
}
105127
out<<"\n";
106128
}
107129

108130
PLMD::diagMatSym(mat,eval,evec);
109131

110132
out<<"After:\n";
111-
for(unsigned i=0;i<4;i++) {
112-
for(unsigned j=0;j<4;j++) out<<" "<<mat[i][j];
133+
for(unsigned i=0; i<4; i++) {
134+
for(unsigned j=0; j<4; j++) {
135+
out.printf((" "+fmt).c_str(),mat[i][j]);
136+
}
113137
out<<"\n";
114138
}
115139
}
140+
}
141+
int main () {
142+
PLMD::OFile out;
143+
out.open("output");
144+
matrixTest<double>(out,"%8.6f");
116145
out.close();
146+
PLMD::OFile out_float;
147+
out_float.open("output_float");
148+
matrixTest<float>(out_float,"%8.4f");
149+
out_float.close();
117150
return 0;
118151
}
Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
Eigenvalues -0.309693 0.593857 1.31584
1+
Eigenvalues -0.309693 0.593857 1.315836
22
Eigenvectors :
3-
0.0342772 0.756017 -0.653654
3+
0.034277 0.756017 -0.653654
44
0.659404 -0.508584 -0.553651
55
0.751007 0.412044 0.515953
66
Inverse :
7-
1.15702 -0.413223 -0.247934
8-
-0.413223 -1.28099 2.2314
9-
-0.247934 2.2314 -0.661157
7+
1.157025 -0.413223 -0.247934
8+
-0.413223 -1.280992 2.231405
9+
-0.247934 2.231405 -0.661157
1010
Pseudoinverse :
11-
-18.8889 -11.1111 15.5556
12-
12.2222 7.77778 -8.88889
11+
-18.888889 -11.111111 15.555556
12+
12.222222 7.777778 -8.888889
1313
Test diagmat (identical eigenvalues)
14-
-1.40512 0
14+
-1.405125 0.000000
1515
Test diagmat (different eigenvalues)
16-
-1.40512 0
16+
-1.405125 0.000000
1717
Test diagmat (is matrix modified)
1818
Before:
19-
0 3 0 -1
20-
3 5 0 0
21-
0 0 0 3
22-
-1 0 3 6
19+
0.000000 3.000000 0.000000 -1.000000
20+
3.000000 5.000000 0.000000 0.000000
21+
0.000000 0.000000 0.000000 3.000000
22+
-1.000000 0.000000 3.000000 6.000000
2323
After:
24-
0 3 0 -1
25-
3 5 0 0
26-
0 0 0 3
27-
-1 0 3 6
24+
0.000000 3.000000 0.000000 -1.000000
25+
3.000000 5.000000 0.000000 0.000000
26+
0.000000 0.000000 0.000000 3.000000
27+
-1.000000 0.000000 3.000000 6.000000

0 commit comments

Comments
 (0)