/* energy (score) functions, aka -log(p).
   * O(M) if Sigma is up to date
   * O(M^3) if Sigma has changed (Cholesky decomp.) */
double MultivariateFNormalSufficient::evaluate() const
  {
      double e = get_norms()[1] + get_minus_log_jacobian();
      if (N_==1)
      {
          e += 0.5*get_mean_square_residuals()/SQUARE(factor_) ;
          /*std::cout << "mvn"
              << " " << e
              << " " << get_norms()[0]
              << " " << get_norms()[1]
              << " " << get_minus_log_jacobian()
              << " " << get_mean_square_residuals()/SQUARE(factor_)
              <<std::endl; */
      } else {
          e += 0.5*( trace_WP()
                + double(N_)*get_mean_square_residuals())/SQUARE(factor_) ;
      }
      //if log(norm) is -inf, make the score bad, e.g. +inf.
      //should check if epsilon==0 in which case we should return -inf
      //to mimic the Dirac distribution, but this case has undefined derivatives
      if (std::abs(e) > std::numeric_limits<double>::max())
          e=std::numeric_limits<double>::infinity();
      LOG( "MVN: evaluate() = " << e << std::endl);
      return e;
  }
  /* energy (score) functions, aka -log(p).
   * O(M) if Sigma is up to date
   * O(M^3) if Sigma has changed (Cholesky decomp.) */
double MultivariateFNormalSufficient::evaluate() const
  {
      timer_.start(EVAL);
      double e;
      if (N_==1)
      {
          e = get_norms()[1] + get_minus_log_jacobian()
          + 0.5*get_mean_square_residuals()/IMP::square(factor_) ;
          /*std::cout << "mvn"
              << " " << e
              << " " << get_norms()[0]
              << " " << get_norms()[1]
              << " " << get_minus_log_jacobian()
              << " " << get_mean_square_residuals()/IMP::square(factor_)
              <<std::endl; */
      } else {
          e = get_norms()[1] + get_minus_log_jacobian()
          + 0.5*( trace_WP()
                + double(N_)*get_mean_square_residuals())/IMP::square(factor_) ;
      }
      IMP_LOG(TERSE, "MVN: evaluate() = " << e << std::endl);
      timer_.stop(EVAL);
      return e;
  }
double MultivariateFNormalSufficient::get_minus_log_normalization() const
{
    double e = get_norms()[1] + get_minus_log_jacobian();
    return e;
}