double ReferenceArguments::calculateArgumentDistance( const std::vector<Value*> & vals, const std::vector<double>& arg,
    ReferenceValuePack& myder, const bool& squared ) const {
  double r=0; std::vector<double> arg_ders( vals.size() );
  if( hasmetric ) {
    for(unsigned i=0; i<reference_args.size(); ++i) {
      unsigned ik=arg_der_index[i]; arg_ders[ ik ]=0;
      double dp_i=vals[ik]->difference( reference_args[i], arg[ik] );
      for(unsigned j=0; j<reference_args.size(); ++j) {
        double dp_j;
        unsigned jk=arg_der_index[j];
        if(i==j) dp_j=dp_i;
        else dp_j=vals[jk]->difference( reference_args[j], arg[jk] );

        arg_ders[ ik ]+=2.0*metric(i,j)*dp_j;    // Factor of two for off diagonal terms as you have terms from ij and ji
        r+=dp_i*dp_j*metric(i,j);
      }
    }
  } else {
    for(unsigned i=0; i<reference_args.size(); ++i) {
      unsigned ik=arg_der_index[i];
      double dp_i=vals[ik]->difference( reference_args[i], arg[ik] );
      r+=weights[i]*dp_i*dp_i; arg_ders[ik]=2.0*weights[i]*dp_i;
    }
  }
  if(!squared) {
    r=sqrt(r); double ir=1.0/(2.0*r);
    for(unsigned i=0; i<arg_ders.size(); ++i) myder.setArgumentDerivatives( i, arg_ders[i]*ir );
  } else {
    for(unsigned i=0; i<arg_ders.size(); ++i) myder.setArgumentDerivatives( i, arg_ders[i] );
  }
  return r;
}
double DotProductDistance::calculateArgumentDistance( const std::vector<Value*> & vals, const std::vector<double>& arg,
    ReferenceValuePack& myder, const bool& squared ) const {
  double dot=0.0;
  for (unsigned long i=0; i<vals.size(); ++i) dot+=getReferenceArgument(i)*arg[i];
  for (unsigned long i=0; i<vals.size(); ++i) myder.setArgumentDerivatives( i, -getReferenceArgument(i)/dot );
  return -log(dot);
}
double ReferenceArguments::projectArgDisplacementOnVector( const std::vector<double>& eigv, const std::vector<Value*>& vals, const std::vector<double>& arg, ReferenceValuePack& mypack ) const {
  if( hasmetric ) {
    plumed_error();
  } else {
    double proj=0;
    for(unsigned j=0; j<reference_args.size(); ++j) {
      unsigned jk=arg_der_index[j];
      proj += eigv[j]*sqrtweight[j]*vals[jk]->difference( reference_args[j], arg[jk] );
      mypack.setArgumentDerivatives( jk, eigv[j]*sqrtweight[j] );
    }
    return proj;
  }
}