/* 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: k-cyclic.cc,v 1.8 2005/07/28 18:03:50 gawrilow Exp $"

#include <cmath>
#include <Poly.h>
#include <Matrix.h>
#include <Array.h>
#include <Rational.h>

namespace polymake { namespace polytope {

void k_cyclic(Poly& p, const Array<double>& s, int n)
{
   const int k=s.size();
   p.take("AMBIENT_DIM") << 2*k;
   p.take("DIM") << 2*k;
   p.take("N_VERTICES") << n;

   const double pi = M_PI;

   Matrix<double> vertices(n,2*k+1);
   double* v=concat_rows(vertices).begin();

   for (int i = 0; i < n; ++i) {
      *v++ = 1;
      for (int j = 0; j < k; ++j) {
	 *v++ = cos(2*pi*s[j]*double(i)/double(n));
	 *v++ = sin(2*pi*s[j]*double(i)/double(n));
      }
   }
   p.take("VERTICES") << vertices;
   p.take("BOUNDED") << true;
}

} }

using namespace polymake;

/** @file k_cyclic
 *
 *  Produce a (rounded) $2*k$-dimensional $k$-cyclic polytope with $n$ points.
 *  Special cases are the bicyclic ($k=2$) and tricyclic ($k=3$) polytopes.
 *  Only possible in even dimensions.
 *
 *  The parameters $s_i$ can be specified as integer, floating-point, or rational numbers.
 *  The coordinates of the $i$-th point are taken as follows:
 *
 *  $cos(s_1 * 2&pi;i/n)$,
 *  $sin(s_1 * 2&pi;i/n)$,
 *     ...
 *  $cos(s_k * 2&pi;i/n)$,
 *  $sin(s_k * 2&pi;i/n)$
 *
 *  Warning: Some of the $k$-cyclic polytopes are not simplicial. 
 *           Since the components are rounded, this client might
 *           output a polytope which is not a $k$-cyclic polytope!
 *
 *  More information can be found in the following references:
 *
 *  P. Schuchert: "Matroid-Polytope und Einbettungen kombinatorischer Mannigfaltigkeiten",
 *                 PhD thesis, TU Darmstadt, 1995.
 * 
 *  Z. Smilansky: "Bi-cyclic $4$-polytopes",
 *                 Isr. J. Math. 70, 1990, 82-92
 *
 *  @synopsis k_cyclic <file> <k> <n> <s_1> ... <s_k>
 *
 *  @writing  AMBIENT_DIM, DIM, N_VERTICES, VERTICES, BOUNDED
 *
 *  @index clients Producing from scratch
 */

int main(int argc, const char *argv[]) {
   if (argc < 5) {
      cerr << "usage: " << argv[0] << " <file> <k> <n> <s_1> ... <s_k>" << endl;
      cerr << "Produces k-cyclic polytopes with n points" << endl;
      return 1;
   }
   try {
      int i;

      const int k = atoi(argv[2]);   // type of polytope
      const int n = atoi(argv[3]);   // number of points

      if (argc != 4+k) {
	 cerr << argv[0] << ": need " << k << " parameters" << endl;
	 return 1;
      }
      if (k%2 || k < 1 || k >= n) {
	 cerr << argv[0] << ": need an even k: 1 <= k < n" << endl;
	 return 1;
      }

      Array<double> s(k);  // to store the parameters

      for (i=0; i < k; ++i)
	 if (strchr(argv[4+i], '/'))
	    s[i]=double(Rational(argv[4+i]));
	 else
	    s[i]=atof(argv[4+i]);

      Poly p(argv[1], ios::out | ios::trunc);
      polytope::k_cyclic(p, s, n);
   }
   catch (const std::exception& e) {
      cerr << e.what() << endl;
      return 1;
   }
   return 0;
}
