// Copyright (C) 2004, 2006 International Business Machines and others.
// All Rights Reserved.
// This code is published under the Common Public License.
//
// $Id: IpMatrix.cpp 841 2007-02-27 17:30:26Z andreasw $
//
// Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13

#include "IpMatrix.hpp"

namespace Ipopt
{
  void Matrix::AddMSinvZ(Number alpha, const Vector& S, const Vector& Z,
                         Vector& X) const
  {
    AddMSinvZImpl(alpha, S, Z, X);
  }

  void Matrix::SinvBlrmZMTdBr(Number alpha, const Vector& S,
                              const Vector& R, const Vector& Z,
                              const Vector& D, Vector& X) const
  {
    SinvBlrmZMTdBrImpl(alpha, S, R, Z, D, X);
  }

  // Prototype for specialize methods (can and should be overloaded)
  void Matrix::AddMSinvZImpl(Number alpha, const Vector& S, const Vector& Z,
                             Vector& X) const
  {
    SmartPtr<Vector> tmp = S.MakeNew();
    tmp->AddVectorQuotient(1., Z, S, 0.);
    MultVector(alpha, *tmp, 1., X);
  }

  void Matrix::SinvBlrmZMTdBrImpl(Number alpha, const Vector& S,
                                  const Vector& R, const Vector& Z,
                                  const Vector& D, Vector& X) const
  {
    TransMultVector(alpha, D, 0., X);
    X.ElementWiseMultiply(Z);
    X.Axpy(1., R);
    X.ElementWiseDivide(S);
  }

  bool Matrix::HasValidNumbers() const
  {
    if (valid_cache_tag_ != GetTag()) {
      cached_valid_ = HasValidNumbersImpl();
      valid_cache_tag_ = GetTag();
    }
    return cached_valid_;
  }

  void Matrix::Print(SmartPtr<const Journalist> jnlst,
                     EJournalLevel level,
                     EJournalCategory category,
                     const std::string& name,
                     Index indent,
                     const std::string& prefix) const
  {
    if (IsValid(jnlst) && jnlst->ProduceOutput(level, category)) {
      PrintImpl(*jnlst, level, category, name, indent, prefix);
    }
  }

  void Matrix::Print(const Journalist& jnlst,
                     EJournalLevel level,
                     EJournalCategory category,
                     const std::string& name,
                     Index indent,
                     const std::string& prefix) const
  {
    if (jnlst.ProduceOutput(level, category)) {
      PrintImpl(jnlst, level, category, name, indent, prefix);
    }
  }

} // namespace Ipopt
