From 5512fb24f238a49f05c5263338073fa24a64c0e5 Mon Sep 17 00:00:00 2001
From: Giovanni Bussi <giovanni.bussi@gmail.com>
Date: Sun, 17 Feb 2013 16:44:31 -0500
Subject: [PATCH] Another small optimization in RMSD

---
 src/tools/RMSD.cpp | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/tools/RMSD.cpp b/src/tools/RMSD.cpp
index 79c30bc43..98af7de08 100644
--- a/src/tools/RMSD.cpp
+++ b/src/tools/RMSD.cpp
@@ -243,10 +243,9 @@ double RMSD::optimalAlignment(const  std::vector<double>  & align,
   double dist(0);
   double norm(0);
   const unsigned n=reference.size();
-// for these tensors I directly accumulate the trace:
+// This is the trace of positions*positions + reference*reference
   double sum00w(0);
-  double sum11w(0);
-// for these
+// This is positions*reference
   Tensor sum01w;
 
   derivatives.resize(n);
@@ -261,26 +260,27 @@ double RMSD::optimalAlignment(const  std::vector<double>  & align,
     cpositions+=positions[iat]*w;
     creference+=reference[iat]*w;
   }
-  cpositions/=norm;
-  creference/=norm;
+  double invnorm=1.0/norm;
+
+  cpositions*=invnorm;
+  creference*=invnorm;
   
 // second expensive loop: compute second moments wrt centers
   for(unsigned iat=0;iat<n;iat++){
     double w=align[iat];
-    sum00w+=dotProduct(positions[iat]-cpositions,positions[iat]-cpositions)*w;
+    sum00w+=(dotProduct(positions[iat]-cpositions,positions[iat]-cpositions)
+            +dotProduct(reference[iat]-creference,reference[iat]-creference))*w;
     sum01w+=Tensor(positions[iat]-cpositions,reference[iat]-creference)*w;
-    sum11w+=dotProduct(reference[iat]-creference,reference[iat]-creference)*w;
   }
 
-  double rr00=sum00w/norm;
-  Tensor rr01=sum01w/norm;
-  double rr11=sum11w/norm;
+  double rr00=sum00w*invnorm;
+  Tensor rr01=sum01w*invnorm;
 
   Matrix<double> m=Matrix<double>(4,4);
-  m[0][0]=rr00+rr11+2.0*(-rr01[0][0]-rr01[1][1]-rr01[2][2]);
-  m[1][1]=rr00+rr11+2.0*(-rr01[0][0]+rr01[1][1]+rr01[2][2]);
-  m[2][2]=rr00+rr11+2.0*(+rr01[0][0]-rr01[1][1]+rr01[2][2]);
-  m[3][3]=rr00+rr11+2.0*(+rr01[0][0]+rr01[1][1]-rr01[2][2]);
+  m[0][0]=rr00+2.0*(-rr01[0][0]-rr01[1][1]-rr01[2][2]);
+  m[1][1]=rr00+2.0*(-rr01[0][0]+rr01[1][1]+rr01[2][2]);
+  m[2][2]=rr00+2.0*(+rr01[0][0]-rr01[1][1]+rr01[2][2]);
+  m[3][3]=rr00+2.0*(+rr01[0][0]+rr01[1][1]-rr01[2][2]);
   m[0][1]=2.0*(-rr01[1][2]+rr01[2][1]);
   m[0][2]=2.0*(+rr01[0][2]-rr01[2][0]);
   m[0][3]=2.0*(-rr01[0][1]+rr01[1][0]);
@@ -325,7 +325,6 @@ double RMSD::optimalAlignment(const  std::vector<double>  & align,
   rotation[2][0]=2*(+q[0]*q[2]+q[1]*q[3]);
   rotation[2][1]=2*(-q[0]*q[1]+q[2]*q[3]);
 
-  double invnorm=1.0/norm;
   double prefactor=2.0*invnorm;
   Vector shift=cpositions-matmul(rotation,creference);
 
@@ -342,8 +341,9 @@ double RMSD::optimalAlignment(const  std::vector<double>  & align,
   for(unsigned iat=0;iat<n;iat++){
 // there is no need for derivatives of rotation and shift here as it is by construction zero
 // (similar to Hellman-Feynman forces)
-    derivatives[iat]= prefactor*align[iat]*(positions[iat]-shift - matmul(rotation,reference[iat]));
-    if(safe) dist+=align[iat]*invnorm*modulo2(positions[iat]-shift - matmul(rotation,reference[iat]));
+    Vector d(positions[iat]-shift - matmul(rotation,reference[iat]));
+    derivatives[iat]= prefactor*align[iat]*d;
+    if(safe) dist+=align[iat]*invnorm*modulo2(d);
   }
 
   if(!squared) dist=sqrt(dist);
-- 
GitLab