#include <typedef.h>
#include <getput.h>
#include <matrix.h>
#include <base.h>

#include <gmp.h>

int INFO_LEVEL;
extern int SFLAG;


main(int argc,char **argv){

  bravais_TYP *G;

  matrix_TYP **base,
             **K;

  MP_INT Order;

  int i,
      j,
      l,
      siz,
      anz,
      factors[100],
      order;

  char comment[1000];


  read_header(argc,argv);

  if ((is_option('h') && optionnumber('h')==0) || (FILEANZ < 1)){
     printf("Usage: %s 'file1' [-M] [-N]\n",argv[0]);
     printf("\n");
     printf("file1: bravais_TYP.\n");
     printf("\n");
     printf("Decides whether the given INTEGRAL matrix group is finite.\n");
     printf("If it is so, it will echo the order of the group.\n");
     printf("\n");
     printf("Options:\n");
     printf(" -M   : Output generators for the Minkowski kernel (i.e the \n");
     printf("        subgroup of all matrices congruent I mod 2) of\n");
     printf("        the group. WARNING: these generators will be\n");
     printf("        correct iff the group was finite. Otherwise\n");
     printf("        the program terminates immediatly if it has calculated\n");
     printf("        enough element of the kernel to prove the group to\n");
     printf("        be infinite.\n");
     printf(" -N   : Assume the group to be generated by G->gen,G->normal\n");
     printf("        and G->cen.\n");
     printf(" -o   : just output the order in a way that can be appended to\n");
     printf("        a bravais_TYP.\n");
     printf("\n");
     printf("Cf. Order.\n");
     if (is_option('h')){
        exit(0);
     }
     else{
        exit(31);
     }
  }

  INFO_LEVEL = optionnumber('h');

  if (INFO_LEVEL & 12){
     SFLAG = 1;
  }

  G = get_bravais(FILENAMES[0]);

  base = get_base(G);

  mpz_init_set_si(&Order,0);

  if (is_option('N')){
     G->gen = (matrix_TYP **) realloc(G->gen,(G->gen_no+G->cen_no+G->normal_no)
                                      *sizeof(matrix_TYP*));
     for (i=0;i<G->cen_no;i++)
        G->gen[i+G->gen_no] = G->cen[i];

     for (i=0;i<G->normal_no;i++)
        G->gen[i+G->gen_no+G->cen_no] = G->normal[i];

     G->gen_no += (G->cen_no + G->normal_no);

     if (G->cen != NULL && G->cen_no > 0) free(G->cen);
     if (G->normal != NULL && G->normal_no > 0) free(G->normal);
     G->cen_no = 0;
     G->normal_no = 0;
     G->cen = NULL;
     G->normal = NULL;
  }

  siz = strong_generators_2(base,G,&K,&anz,&Order);

  if (siz != FALSE){
     if (is_option('o')){
        order = mpz_get_si(&Order);
        factorize_new(order,factors);
        fput_order(stdout,factors,order);
     }

     fprintf(stderr,"The order of the group is: ");
     mpz_out_str(stderr,10,&Order);
     fprintf(stderr,"\n");
  }
  else{
     fprintf(stderr,"The group infinite!\n");
  }

  if (is_option('M')){
     printf("#%d\n",anz);
     for (i=0;i<anz;i++){
        sprintf(comment,"%dth-generator for the kernel of the Minkowski hom",
                i+1);
        put_mat(K[i],NULL,comment,2);
     }
  }

  mpz_clear(&Order);
  for (i=0;i<anz;i++) free_mat(K[i]);
  free(K);
  for (i=0;i<G->dim;i++) free_mat(base[i]);
  free_bravais(G);
  free(base);

  if (INFO_LEVEL & 12){
     pointer_statistics(0,0);
  }
  exit(0);

} /* main */
