/* 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.
*/

#ident "$Project: polymake $$Id: product-coord.cc,v 1.3 2004/06/22 16:23:09 gawrilow Exp $"

/* The only reason for extracting this portion code in a separate file is
   the exorbitant memory consumption by gcc. When it becomes more economical one nice day,
   this file should be merged back into product.cc */

#include <Rational.h>
#include <Matrix.h>
#include <Set.h>

namespace polymake { namespace polytope {

Matrix<Rational>
product_coord(const Matrix<Rational>& V1, const Matrix<Rational>& V2,
	      int& n_vertices1, int& n_vertices2, int& n_vertices_out, int n_rays,
	      const Set<int>& rays1, const Set<int>& rays2)
{
   if (!n_vertices_out)
      n_vertices1=V1.rows(), n_vertices2=V2.rows(),
      n_vertices_out=(n_vertices1 - rays1.size()) * (n_vertices2 - rays2.size()) + n_rays;
   const int dim=V1.cols()+V2.cols()-1;

   Matrix<Rational> V_out(n_vertices_out, dim);
   if (n_rays==0) {
      std::copy(entire(product(rows(V1), rows(V2.minor(All,range(1,V2.cols()-1))), operations::concat())),
		rows(V_out).begin());
   } else {
      // affine vertices
      std::copy(entire(product(rows(V1.minor(~rays1,All)), rows(V2.minor(~rays2,range(1,V2.cols()-1))), operations::concat())),
		rows(V_out).begin());
      // rays from P1
      V_out.minor(sequence(n_vertices_out-n_rays, rays1.size()), sequence(0,V1.cols())) =
	 V1.minor(rays1,All);
      // rays from P2
      V_out.minor(sequence(n_vertices_out-rays2.size(), rays2.size()), sequence(V1.cols()-1, V2.cols())) =
	 V2.minor(rays2,All);
   }
   return V_out;
}

} }
