/* Copyright (c) 1997-2009
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Darmstadt, Germany)
   http://www.polymake.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.
--------------------------------------------------------------------------------
   $Project: polymake $$Id: cdd_lp_client.cc 9298 2009-09-02 23:10:56Z gawrilow $
*/

#include <cdd_interface.h>

namespace polymake { namespace polytope {

   template <typename Scalar>
   void cdd_solve_lp(perl::Object p, perl::Object lp, bool maximize)
   {
      typedef cdd_interface::solver<Scalar> Solver;
      const Matrix<Scalar> H=p.give("FACETS | INEQUALITIES"),
                           E=p.lookup("AFFINE_HULL | EQUATIONS");
      const Vector<Scalar> Obj=lp.give("LINEAR_OBJECTIVE");

      try {
	 Solver solver;
	 typename Solver::lp_solution S=solver.solve_lp(H, E, Obj, maximize);
	 lp.take(maximize ? "MAXIMAL_VALUE" : "MINIMAL_VALUE") << S.first;
	 lp.take(maximize ? "MAXIMAL_VERTEX" : "MINIMAL_VERTEX") << S.second;
	 p.take("FEASIBLE") << true;
      }
      catch (unbounded) {
	 if (maximize)
	    lp.take("MAXIMAL_VALUE") << std::numeric_limits<Scalar>::infinity();
	 else
	    lp.take("MINIMAL_VALUE") << -std::numeric_limits<Scalar>::infinity();
	 lp.take(maximize ? "MAXIMAL_VERTEX" : "MINIMAL_VERTEX") << perl::undefined();
	 p.take("FEASIBLE") << true;
      }
      catch (infeasible) {
	 lp.take(maximize ? "MAXIMAL_VALUE" : "MINIMAL_VALUE") << perl::undefined();
	 lp.take(maximize ? "MAXIMAL_VERTEX" : "MINIMAL_VERTEX") << perl::undefined();
	 p.take("FEASIBLE") << false;
      }
   }

   FunctionTemplate4perl("cdd_solve_lp<Scalar> (Polytope<Scalar>, LinearProgram<Scalar>, $) : void");
} }
