MatrixXd MultivariateFNormalSufficient::get_PW() const
{
    if (!flag_PW_)
    {
        ////PW
        timer_.start(SOLVE);
        MatrixXd PW(M_,M_);
        if (N_==1)
        {
            IMP_LOG(TERSE, "MVN:   W=0 => PW=0" << std::endl);
            PW.setZero();
        } else {
            IMP_LOG(TERSE, "MVN:   solving for PW" << std::endl);
            if (use_cg_)
            {
                if (first_PW_)
                {
                    PW = compute_PW_direct();
                    (*const_cast<bool *>(&first_PW_))=false;
                } else {
                    PW = compute_PW_cg();
                }
            } else {
                PW = compute_PW_direct();
            }
        }
        const_cast<MultivariateFNormalSufficient *>(this)->set_PW(PW);
        timer_.stop(SOLVE);
    }
    return PW_;
}
MatrixXd MultivariateFNormalSufficient::compute_PW_cg() const
{
    //compute PW using CG. Preconditionner is Sigma^-1 and initial guess
    //is previous value of PW. Do M steps (theoretically sufficient) and if the
    //residuals are too big do the inversion.
    //
    timer_.start(PW_CG_SUCCESS);
    //static unsigned numtries=0;
    //static unsigned numfail=0;
    cg_->set_A(get_Sigma());
    cg_->set_B(get_W());
    cg_->set_X0(PW_);
    cg_->set_tol(cg_tol_);
    MatrixXd PW(cg_->optimize(precond_, M_));
    if (cg_->info()>0) timer_.stop(PW_CG_SUCCESS);
    double resid = (get_Sigma()*PW-get_W()).norm();
    if (resid > cg_tol_)
    {
        //numfail++;
        PW = compute_PW_direct();
    }
    //numtries++;
    //std::cout << "CG: numtries="<<numtries<<" numfail="<<numfail<<std::endl;
    return PW;
}
MatrixXd MultivariateFNormalSufficient::get_PW() const
{
    if (!flag_PW_)
    {
        ////PW
        MatrixXd PW(M_,M_);
        if (N_==1)
        {
            LOG( "MVN:   W=0 => PW=0" << std::endl);
            PW.setZero();
        } else {
            LOG( "MVN:   solving for PW" << std::endl);
            PW = compute_PW_direct();
        }
        const_cast<MultivariateFNormalSufficient *>(this)->set_PW(PW);
    }
    return PW_;
}