/* Copyright (c) 1997-2010
   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: rational_integer.cc 9991 2010-12-12 23:36:28Z gawrilow $
*/

#include "polymake/client.h"
#include "polymake/Rational.h"
#include "polymake/Matrix.h"
#include "polymake/Vector.h"
#include "polymake/linalg.h"

namespace polymake { namespace common {
namespace {

template <typename DstIterator, typename SrcIterator> inline
void store_lcm(DstIterator dst, SrcIterator src, const Integer& LCM, pm::False)
{
   for (; !src.at_end(); ++src, ++dst)
      *dst=div_exact(LCM,denominator(*src))*numerator(*src);
}

template <typename DstIterator, typename SrcIterator> inline
void store_lcm(DstIterator dst, SrcIterator src, const Integer& LCM, pm::True)
{
   for (; !src.at_end(); ++src)
      dst[src.index()]=div_exact(LCM,denominator(*src))*numerator(*src);
}

template <typename DstIterator, typename Vector> inline
void store_lcm(DstIterator dst, const GenericVector<Vector>& v, const Integer& LCM)
{
   store_lcm(dst, entire(v.top()), LCM, bool2type<pm::check_container_feature<Vector,pm::sparse>::value>());
}

}

template <typename _Vector> inline
Vector<Integer> eliminate_denominators(const GenericVector<_Vector,Rational>& V)
{
   Vector<Integer> result(V.dim());
   if (V.dim()) store_lcm(result.begin(), V, common_denominator(V));
   return result;
}

template <typename _Matrix> inline
Matrix<Integer> eliminate_denominators(const GenericMatrix<_Matrix,Rational>& M)
{
   Matrix<Integer> result(M.rows(), M.cols());
   if (M.rows() && M.cols()) {
      Rows< Matrix<Integer> >::iterator d=rows(result).begin();
      for (typename Entire< Rows<_Matrix> >::const_iterator s=entire(rows(M)); !s.at_end(); ++s, ++d)
         store_lcm(d->begin(), *s, common_denominator(*s));
   }
   return result;
}

template <typename Vector> inline
bool is_integral(const GenericVector<Vector,Rational>& V)
{
   for (typename Entire<Vector>::const_iterator x=entire(V.top()); !x.at_end(); ++x)
      if (denominator(*x)!=1) return false;
   return true;
}

template <typename Matrix> inline
bool is_integral(const GenericMatrix<Matrix,Rational>& M)
{
   return is_integral(concat_rows(M));
}

FunctionTemplate4perl("eliminate_denominators(Vector<Rational>)");
FunctionTemplate4perl("eliminate_denominators(Matrix<Rational>)");
FunctionTemplate4perl("is_integral(Vector<Rational>)");
FunctionTemplate4perl("is_integral(Matrix<Rational>)");

} }

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