MatrixXd MultivariateFNormalSufficient::evaluate_second_derivative_Sigma_Sigma(
        unsigned m, unsigned n) const
  {
      CHECK(N_==1, "not implemented when N>1");
      MatrixXd P(get_P());
      VectorXd Peps(get_Peps());
      MatrixXd tmp(P.col(m)*Peps.transpose());
      MatrixXd ret(0.5*(-P.col(n)*P.row(m)
                        +Peps(n)*(tmp+tmp.transpose())));
      return ret/SQUARE(factor_);
  }
MatrixXd MultivariateFNormalSufficient::evaluate_second_derivative_Sigma_Sigma(
        unsigned m, unsigned n) const
  {
      if (N_!=1) IMP_THROW("not implemented when N>1", ModelException);
      MatrixXd P(get_P());
      VectorXd Peps(get_Peps());
      MatrixXd tmp(P.col(m)*Peps.transpose());
      MatrixXd ret(0.5*(-P.col(n)*P.row(m)
                        +Peps(n)*(tmp+tmp.transpose())));
      return ret/IMP::square(factor_);
  }
 MatrixXd MultivariateFNormalSufficient::evaluate_second_derivative_FM_Sigma(
         unsigned k) const
 {
     CHECK(N_==1, "not implemented when N>1");
     MatrixXd P(get_P());
     VectorXd Peps(get_Peps());
     MatrixXd ret(P.transpose().col(k)*Peps.transpose());
     return ret/SQUARE(factor_);
 }
 MatrixXd MultivariateFNormalSufficient::evaluate_second_derivative_FM_Sigma(
         unsigned k) const
 {
     if (N_!=1) IMP_THROW("not implemented when N>1", ModelException);
     MatrixXd P(get_P());
     VectorXd Peps(get_Peps());
     MatrixXd ret(P.transpose().col(k)*Peps.transpose());
     return ret/IMP::square(factor_);
 }
  double MultivariateFNormalSufficient::get_mean_square_residuals() const
{
    //std::cout << "P " << std::endl << P_ << std::endl;
    //std::cout << "epsilon " << std::endl << get_epsilon() << std::endl;
    VectorXd Peps(get_Peps());
    VectorXd epsilon(get_epsilon());
    double dist = epsilon.transpose()*Peps;
    LOG( "MVN:   get_mean_square_residuals = " << dist << std::endl);
    return dist;
}