// Copyright (C) 2003-2009 Marc Duruflé
//
// This file is part of the linear-algebra library Seldon,
// http://seldon.sourceforge.net/.
//
// Seldon is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your option)
// any later version.
//
// Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Seldon. If not, see http://www.gnu.org/licenses/.


#ifndef SELDON_FILE_PRECOND_SSOR_CXX

namespace Seldon
{
  template <class T>
  class SorPreconditioner
  {
  protected :
    bool symmetric_precond; //!< true for Symmetric relaxation
    int nb_iter; //!< number of iterations
    T omega; //!< relaxation parameter
    
  public :
    SorPreconditioner();
    ~SorPreconditioner(){}
    
    void InitSymmetricPreconditioning() { symmetric_precond = true; }
    void InitUnSymmetricPreconditioning() { symmetric_precond = false; }
    void SetParameterRelaxation(const T& param) { omega = param; }
    void SetNumberIterations(int nb_iterations) { nb_iter = nb_iterations; }
    
    template<class Vector, class Matrix>
    void Solve(const Matrix& A, const Vector& r, Vector& z,
	       bool init_guess_null = true);
    
    template<class Vector, class Matrix>
    void TransSolve(const Matrix& A, const Vector& r, Vector& z,
		    bool init_guess_null = true);
    
  };
  
  
  //! Default constructor
  template<class T>
  SorPreconditioner<T>::SorPreconditioner()
  {
    nb_iter = 1; omega = T(1);
    symmetric_precond = true;
  }
  
  
  //! Solves M z = r
  template<class T>
  template<class Vector, class Matrix>
  void SorPreconditioner<T>::
  Solve(const Matrix& A, const Vector& r, Vector& z, bool init_guess_null)
  {
    if (init_guess_null)
      z.Zero();
    
    if (symmetric_precond)
      Seldon::SOR(A, z, r, omega, nb_iter, 0);
    else
      Seldon::SOR(A, z, r, omega, nb_iter, 2);
  }
  
  
  //! Solves M^t z = r
  template<class T>
  template<class Vector, class Matrix>
  void SorPreconditioner<T>::
  TransSolve(const Matrix& A, const Vector& r, Vector& z, bool init_guess_null)
  {
    if (init_guess_null)
      z.Zero();
    
    if (symmetric_precond)
      Seldon::SOR(A, z, r, omega, nb_iter, 0);
    else
      Seldon::SOR(A, z, r, omega, nb_iter, 3);
  }
  
}

#define SELDON_FILE_PRECOND_SSOR_CXX
#endif