/* Copyright (c) 1997-2004
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
   http://www.math.tu-berlin.de/polymake,  mailto:polymake@math.tu-berlin.de

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   This program 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 General Public License for more details.
*/

#ifndef _POLYMAKE_CH_CLIENT_H
#define _POLYMAKE_CH_CLIENT_H "$Project: polymake $$Id: ch_client.h 5757 2005-02-02 17:56:46Z gawrilow $"

#include <Poly.h>
#include <Matrix.h>
#include <Vector.h>
#include <linalg_exceptions.h>
#include <stopwatch.h>

namespace polymake { namespace polytope {

template <typename Solver>
void ch_primal(Poly& p, Solver& solver, stopwatch& timer)
{
   typedef typename Solver::coord_type coord_type;
   const Matrix<coord_type> Points=p.give("VERTICES | POINTS");
   timer.start();
   typename Solver::matrix_pair F=solver.enumerate_facets(Points);
   timer.stop();
   p.take("FACETS") << F.first;
   p.take("AFFINE_HULL") << F.second;
}

template <typename Solver>
void count_facets(Poly& p, Solver& solver, stopwatch& timer)
{
   typedef typename Solver::coord_type coord_type;
   const Matrix<coord_type> Points=p.give("VERTICES | POINTS");
   timer.start();
   long n_facets=solver.count_facets(Points);
   timer.stop();
   p.take("N_FACETS") << n_facets;
}

template <typename Solver>
void ch_dual(Poly& p, Solver& solver, stopwatch& timer)
{
   typedef typename Solver::coord_type coord_type;
   const Matrix<coord_type> H=p.give("FACETS | INEQUALITIES"),
                            EQ=p.lookup("AFFINE_HULL | EQUATIONS");
   timer.start();
   try {
      const Matrix<coord_type> V=solver.enumerate_vertices(H,EQ);
      timer.stop();
      p.take("VERTICES") << V;
      p.take("FEASIBLE") << true;
      p.take("POINTED") << true;
   }
   catch (const linalg_error& error) {
      timer.stop();
      p.take("VERTICES") << Poly::undefined();
      p.take("FEASIBLE") << !dynamic_cast<const infeasible*>(&error);
      p.take("POINTED") << false;
   }
}

template <typename Solver>
void count_vertices(Poly& p, Solver& solver, stopwatch& timer, bool only_bounded=false)
{
   typedef typename Solver::coord_type coord_type;
   const Matrix<coord_type> H=p.give("FACETS | INEQUALITIES"),
                            EQ=p.lookup("AFFINE_HULL | EQUATIONS");
   timer.start();
   try {
      std::pair<long,long> n_vertices=solver.count_vertices(H,EQ,only_bounded);
      timer.stop();
      if (!only_bounded) p.take("N_VERTICES") << n_vertices.first;
      p.take("N_BOUNDED_VERTICES") << n_vertices.second;
      p.take("FEASIBLE") << true;
      p.take("POINTED") << true;
   }
   catch (const linalg_error& error) {
      timer.stop();
      if (!only_bounded) p.take("N_VERTICES") << Poly::undefined();
      p.take("N_BOUNDED_VERTICES") << Poly::undefined();
      p.take("FEASIBLE") << !dynamic_cast<const infeasible*>(&error);
      p.take("POINTED") << false;
   }
}

} }

#endif // _POLYMAKE_CH_CLIENT_H

// Local Variables:
// mode:C++
// c-basic-offset:3
// End:
