//---------------------------------------------------------------------------
#include <stdio.h>  // printf
#include <stdlib.h> // atoi
#include <string.h>
#include <sys\timeb.h>
#include <sys\types.h>
#include <sys\stat.h>

//---------------------------------------------------------------------------

#include "boom.h"
#include "tpfnct.h"
//#include "buffers.h"
#include "tboolfnct.h"

#define POCET_POKUSU_OUTPUT 3
// #define LADICI_HLASENI
#define VYPIS_CHYBEJICICH_TERMU
#define VYPIS_CASU

//---------------------------------------------------------------------------




class THash_Polozka
{
public:
  TPfnct * fnct;                // Budu pouzivat Tpfcnt fyzicky z TBoolfcnt kvuli mistu.
  THash_Polozka * next;
  THash_Polozka();
private:
};

//---------------------------------------------------------------------------

class THash_Seznam_Polozek
{
public:
  THash_Seznam_Polozek* next;
  long index;  // index do Thash_Tabulka->tabulka[]  -- kvuli DeleteTerm. pokud budem mazat prvni, tak abychom mohli zmenit primo tabulka[]
  THash_Seznam_Polozek();
  ~THash_Seznam_Polozek();
};

//---------------------------------------------------------------------------

class THash_Tabulka
{
public:
  long pocet;
  int bitu;
  long polozek;

private:
  THash_Polozka **tabulka;
  void Push(TPfnct * ff,long kam);
  TBoolFnct *parent;
  void AddItemPrivate(TPfnct * ff, int pozice, long kam);
  THash_Seznam_Polozek* Vrat_SeznamPrivate(TPfnct * ff,THash_Seznam_Polozek* pol, int pozice,long kde);  // Vrati ukazatel na seznam kam (by patril)/patri term ff.

public:
  THash_Tabulka(int bits,TBoolFnct *parent);
  ~THash_Tabulka();
  THash_Polozka* VratPolozkuZTabulky(long index);
  void THash_Tabulka::UlozPolozkuDoTabulky(THash_Polozka *pol,long index);
  void DeleteInvalidTerms();   // Takze budu mazat jen pointery bez mazani fyzickeho
  void AddItem(TPfnct * ff);
  THash_Seznam_Polozek* Vrat_Seznam(TPfnct * ff);  // Vrati ukazatel na seznam kam (by patril)/patri term ff.
  void DeleteTerm(TPfnct *ff);
  void Print();
};

//---------------------------------------------------------------------------

class GenerateInfo
{
public:
  int bits;
  char *onmpla;
  char *onminf;
  int iv;
  int ov;
  int t;
  int mask;
  int idc;
  int odc;
  int idt;
  int odt;
  int idf;
  int odf;
  int filt;
  int timeout;
  THash_Tabulka *hashtab;
  TBoolFnct *fn;
  int *tab;   // tabulka s idc,idt,idf,odc,odt,odf pro kazdy term. Pro pocitani granularity.
  void Print();
  void PrintOdchylka(GenerateInfo *gi);
  GenerateInfo(int terms);
  ~GenerateInfo();
};
//---------------------------------------------------------------------------

GenerateInfo::GenerateInfo(int terms)
{
  this->tab = (int *) malloc(sizeof(int) * 6 * terms);  // alokuju pole
}

GenerateInfo::~GenerateInfo()
{
  delete this->tab;
}


void GenerateInfo::Print()
{
  printf("Vstupu: %4d Vystupu: %4d Termu: %4d\n",this->iv,this->ov,this->t);
  printf("Vstupni %% dont-care: %3d Vystupni %% dont-care: %3d\n",this->idc,this->odc);
  printf("Vstupni %% '1':       %3d Vystupni %% '1':       %3d\n",this->idt,this->odt);
  printf("Vstupni %% '0':       %3d Vystupni %% '0':       %3d\n",this->idf,this->odf);
}
void GenerateInfo::PrintOdchylka(GenerateInfo *gi)
{
  printf("Odchylky:\n" );
  printf("Vstupni %% dont-care: %3d Vystupni %% dont-care: %3d\n",this->idc-gi->idc,this->odc-gi->odc);
  printf("Vstupni %% '1':       %3d Vystupni %% '1':       %3d\n",this->idt-gi->idt,this->odt-gi->odt);
  printf("Vstupni %% '0':       %3d Vystupni %% '0':       %3d\n",this->idf-gi->idf,this->odf-gi->odf);
}

//---------------------------------------------------------------------------

THash_Polozka* THash_Tabulka::VratPolozkuZTabulky(long index)
{
  return this->tabulka[index];
}

//---------------------------------------------------------------------------

void THash_Tabulka::UlozPolozkuDoTabulky(THash_Polozka *pol,long index)
{
  this->tabulka[index] = pol;
}

//---------------------------------------------------------------------------

THash_Seznam_Polozek::THash_Seznam_Polozek()
{
 this->next = NULL;
 this->index = 0;
}

//---------------------------------------------------------------------------

THash_Seznam_Polozek::~THash_Seznam_Polozek()
{
  if ( this == NULL ) return;
  if ( this->next != NULL )
  {
    delete this->next;
  }
}

//---------------------------------------------------------------------------

THash_Polozka::THash_Polozka()
{
  this->next = NULL;
  this->fnct = NULL;
}

//---------------------------------------------------------------------------

THash_Tabulka::THash_Tabulka(int bits,TBoolFnct *parent)
{
  long i;
  this->bitu=bits;
  this->parent=parent;
  this->polozek=1 << bits;
  this->pocet=0;
  this->tabulka = (THash_Polozka * *) malloc(sizeof(THash_Polozka *) * polozek);  // alokuju pole
  for (i=0;i<polozek;++i)
  {
    this->tabulka[i]=NULL;
  }
}

//---------------------------------------------------------------------------

THash_Tabulka::~THash_Tabulka()         // Znici jen strukturu THash_Tabulka, fnct zustanou v TBoolfnct
{
  THash_Polozka * pol, * pol2;
  long i;
  if ( this == 0 ) return;
  for (i=0;i<this->polozek;++i)
  {
    pol = this->tabulka[i];
    while ( pol != 0 )
    {
      pol2 = pol->next;
      delete pol;
      pol = pol2;
    }
  }
}

//---------------------------------------------------------------------------

void THash_Tabulka::Push(TPfnct * ff,long kam)
{
	THash_Polozka *novy;
	novy = new THash_Polozka;
	novy->fnct = ff;
	novy->next = this->tabulka[kam];
  this->tabulka[kam]=novy;
  this->pocet++;
}

//---------------------------------------------------------------------------

void THash_Tabulka::AddItem(TPfnct * ff )
{
  this->AddItemPrivate(ff,0,0);
}

//---------------------------------------------------------------------------

void THash_Tabulka::AddItemPrivate(TPfnct * ff, int pozice, long kam)
{
  if ((pozice == this->parent->inpvars ) || (pozice==this->bitu))
  {
    this->Push(ff,kam);
  }
  else
  {
    kam = kam << 1;
    if (ff->iv[pozice]=='-')
    {
      this->AddItemPrivate(ff,pozice+1,kam);
      this->AddItemPrivate(ff,pozice+1,kam+1);
    }
    else if (ff->iv[pozice]=='0') { this->AddItemPrivate(ff,pozice+1,kam); }
    else if (ff->iv[pozice]=='1') { this->AddItemPrivate(ff,pozice+1,kam+1); }
  }
}

//---------------------------------------------------------------------------

THash_Seznam_Polozek* THash_Tabulka::Vrat_Seznam(TPfnct * ff)
{
  THash_Seznam_Polozek* pol;
  pol=NULL;
  pol = this->Vrat_SeznamPrivate(ff,pol,0,0);
  return pol;
}


//---------------------------------------------------------------------------

THash_Seznam_Polozek* THash_Tabulka::Vrat_SeznamPrivate(TPfnct * ff,THash_Seznam_Polozek* pol, int pozice, long kde)
{
  THash_Seznam_Polozek* pol2;
  if ((pozice == this->parent->inpvars) || (pozice==this->bitu))
  {
    pol2 = new THash_Seznam_Polozek;
    pol2->next = pol;
    pol2->index=kde;
    return pol2;
  }
  else
  {
    kde = kde << 1;
    if (ff->iv[pozice]=='-')
    {
      pol = this->Vrat_SeznamPrivate(ff,pol,pozice+1,kde);
      pol = this->Vrat_SeznamPrivate(ff,pol,pozice+1,kde+1);
    }
    else if (ff->iv[pozice]=='0') { pol = this->Vrat_SeznamPrivate(ff,pol,pozice+1,kde); }
    else if (ff->iv[pozice]=='1') { pol = this->Vrat_SeznamPrivate(ff,pol,pozice+1,kde+1); }
  }
  return pol;
}


//---------------------------------------------------------------------------

void THash_Tabulka::DeleteInvalidTerms()  // Smaze jen polozky s pointery na invalid Termy, takze volame pred TBoolFnct->DeleteInvalidTerms
{
  long i;
  THash_Polozka * pol, * pol1, * pol2;

  for (i=0;i<this->polozek;++i)
  {
    pol = this->tabulka[i];
    pol2 = 0;
    while ( pol != NULL )
    {
      if ( pol->fnct->valid == 0 )
      {
        if ( this->tabulka[i] == pol )
        {
          this->tabulka[i] = pol->next;
          pol->next = NULL;
          delete pol;
          pol = this->tabulka[i];
          pol2 = pol;
          this->pocet--;
        }
        else
        {
          pol1 = pol->next;
          pol->next = NULL;
          delete pol;
          pol2->next = pol1;
          pol = pol1;
          this->pocet--;
        }
      }
      else
      {
        pol2 = pol;
        pol = pol->next;
      }
    }
  }
}

//---------------------------------------------------------------------------

void THash_Tabulka::DeleteTerm(TPfnct *ff)

{

    THash_Seznam_Polozek *ff1,*ff1n;

    THash_Polozka *ff2,*ff2n,*ff3,*ff4;
    int brk;

    ff1=NULL;
    ff1n=ff1=this->Vrat_Seznam(ff);
    while (ff1!=NULL)
    {
        ff2n=ff2=this->VratPolozkuZTabulky(ff1->index);
        brk=0;
        while ((ff2!=NULL) && (brk==0))
        {
          if (ff2->fnct == ff)
          {
            brk=1;
            if ( ff2n == ff2 )
            {
              this->tabulka[ff1->index] = ff2->next;
              ff2->next = NULL;
              delete ff2;
              ff2 = this->tabulka[ff1->index];
              ff3 = ff2;
              this->pocet--;
            }
            else
            {
              ff4 = ff2->next;
              ff2->next = NULL;
              delete ff2;
              ff3->next = ff4;
              ff2 = ff4;
              this->pocet--;
            }
          }
          else
          {
            ff3=ff2;
            ff2=ff2->next;
          }
        }
        ff1=ff1->next;
    }
    delete ff1n;
}


//---------------------------------------------------------------------------


void THash_Tabulka::Print()

{
  THash_Polozka * pol;
  int i;
  for (i=0;i<this->polozek;++i)
  {
    pol = this->tabulka[i];
    printf ("%d - ",i);
    while ( pol != 0 )
    {
      printf("%s*%s",pol->fnct->iv,pol->fnct->ov);
      pol = pol->next;
      if (pol) printf(",");
    }
    printf("\n");
  }
  printf("\n");
}



//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

int NewGauge( char * name, int max, int context )
{
  return 0;
}

//---------------------------------------------------------------------------
void CloseGauge()
{
}

//---------------------------------------------------------------------------
int GaugeStep( int val, int context )
{
  return 0;
}

//---------------------------------------------------------------------------
void help()
{
  fprintf( stderr, "syntax: Generate -i n -o n -t n [-idc n] [-odc n] [-NC] [-timeout n] [file_name]\n" );
  fprintf( stderr, "    -i n     Specify the number of inputs\n" );
  fprintf( stderr, "    -o n     Specify the number of outputs\n" );
  fprintf( stderr, "    -t n     Specify the number of defined terms\n" );
  fprintf( stderr, "    -h n     Specify the number of hash bits. 0 is default\n" );
  fprintf( stderr, "    -idc n   Specify the percentage of input don't cares. 0 is default\n" );
  fprintf( stderr, "    -odc n   Specify the percentage of output don't cares. 0 is default\n" );
  fprintf( stderr, "    -idt n   Specify the percentage of input ones. 50 is default\n" );
  fprintf( stderr, "    -odt n   Specify the percentage of output ones. 50 is default\n" );
  fprintf( stderr, "    -timeout n  The timeout limit, in seconds. 1000s is the default\n" );
  fprintf( stderr, "    -NC      The consistency check is not performed \n" );
  fprintf( stderr, "    -IN      Print info about generated terms\n" );
  fprintf( stderr, "    -L       Load PLA from file and print info about it\n" );
}

//---------------------------------------------------------------------------

void RandomFillFnctFrom(THash_Tabulka *htab, TBoolFnct *srcf, TPfnct *ff, int r, int r2, int mask)
{
    int i,j,v;

    j=1;
    while (ff!=NULL) {
        ff->dim=0;
        if ((mask & 1) == 1)
        {
          for (i = 0; i < srcf->inpvars; i++)
          {
            v = random(100);
            if (v < r) {
                ff->iv[i] = '-';
                ff->dim++;
            } else {
                v = random(100);
                if (v<r2) { ff->iv[i] = '1'; }
                else ff->iv[i] = '0';
            }
          }
          htab->AddItem(ff); // Pridavam do hashtabulky

        }
        if ((mask &2) == 2) for (i=0; i<srcf->outvars; i++) {
            v=random(100);
            if (v<r) {
                    ff->ov[i]='~';
            } else {
                v = random(100);
                if (v<r2) { ff->ov[i] = '1'; }
                else ff->ov[i] = '0';
            }
        }
        ff=ff->next;
        j++;
    }
}


//---------------------------------------------------------------------------

int CheckConsistOf(THash_Tabulka *htab, TBoolFnct *fn, TPfnct *ffl)   // 0=OK 1=must be deleted
{
  THash_Seznam_Polozek *ff1,*ffn;
  THash_Polozka* ff2;
  int i,brk,brk2;

  brk2=0;
  ff1=ffn=NULL;
  if (ffl!=NULL)
  {
    ffn=ff1=htab->Vrat_Seznam(ffl);
      while ((ff1!=NULL) && (brk2==0))
      {
        ff2=htab->VratPolozkuZTabulky(ff1->index);
        while ((ff2!=NULL) && (brk2==0))
        {
          if (ff2->fnct->valid==1) {
            brk=0;
            for (i=0; i<fn->inpvars; i++)
            {
                if (ffl->iv[i]!=ff2->fnct->iv[i] && ffl->iv[i]!='-' && ff2->fnct->iv[i]!='-')
                {
                    brk=1;
                    break;
                }
            }
            if (brk==0)
            {
              for (i=0; i<fn->outvars; i++)
              {
                if (ffl->ov[i]!=ff2->fnct->ov[i] && ffl->ov[i]!='~' && ff2->fnct->ov[i]!='~')
                {
                  ffl->valid=0;
                  brk2=1;
                  break;
                }
              }
            }
          }
          ff2=ff2->next;
        }
        ff1=ff1->next;
      }
    delete ffn;
  }
  return brk2;
}

int DeleteInconsist(THash_Tabulka *htab, TBoolFnct *fn)   // 0=nonconsistent, 1=OK, 2=overlapping
{
    TPfnct* ff;
    THash_Seznam_Polozek *ff1,*ffn;
    THash_Polozka* ff2;
    int i,brk;

    ff=fn->fnct;
    ff1=ffn=NULL;
    while (ff!=NULL)
    {
      ffn=ff1=htab->Vrat_Seznam(ff);
      while (ff1!=NULL)
      {
        ff2=htab->VratPolozkuZTabulky(ff1->index);
        while (ff2!=NULL)
        {
          if (ff2->fnct->valid==1)
          {
            brk=0;
            for (i=0; i<fn->inpvars; i++)
            {
                if (ff->iv[i]!=ff2->fnct->iv[i] && ff->iv[i]!='-' && ff2->fnct->iv[i]!='-')
                {
                    brk=1;
                    break;
                }
            }
            if (brk==0)
            {
              for (i=0; i<fn->outvars; i++)
              {
                if (ff->ov[i]!=ff2->fnct->ov[i] && ff->ov[i]!='~' && ff2->fnct->ov[i]!='~')
                {
                  ff2->fnct->valid=0;
                  break;
                }
              }
            }
          }
          ff2=ff2->next;
        }
        ff1=ff1->next;
      }
      do
      {
        ff=ff->next;
      } while ((ff!=NULL) && (!ff->valid));
      delete ffn;
    }
    htab->DeleteInvalidTerms();
    fn->DeleteInvalidTerms();
    return 1;
}

//---------------------------------------------------------------------------

int TrimFnct(TBoolFnct *fn, int v)
{
    int i;
    TPfnct *ff;

    ff=fn->fnct;
    i=0;
    while (i!=v && ff!=NULL) {
        ff=ff->next;
        i++;
    };
    if (ff==NULL) return 0;
    i=0;
    while (ff!=NULL) {
         ff->valid=0;
         i++;
         ff=ff->next;
    }
    fn->DeleteInvalidTerms();
    return i;
}

//---------------------------------------------------------------------------

int RndConFillFnct( GenerateInfo *gi )
//THash_Tabulka * htab,TBoolFnct *fn, int mask, int irnd, int ornd,int idt,int odt, int filt, int to)
/*
    Randomly fills a function fn. Terms must be defined.
    mask: bit 0 == 1 -> fill input
    mask: bit 1 == 1 -> fill output
    irnd: % of input DCs
    ornd: % of input DCs
    filt == 0 -> no checks, just fill it
    filt == 1 -> consistent fill (no inconsistencies)
    to: # of seconds until timeout
    returns true if succeeded
*/
{
    int zbyvajicich=0,brk,k;
    TPfnct *ff, *ff1, *ffl, *ff1l;
    TBoolFnct *fn2;
    struct timeb t2, t1;

    ftime(&t2);

    fn2 = gi->fn->DuplFnct();
    ff1=ff1l=fn2->fnct;
    RandomFillFnctFrom(gi->hashtab, gi->fn, gi->fn->fnct,gi->idc,gi->idt, gi->mask & 1);
    RandomFillFnctFrom(gi->hashtab, gi->fn, gi->fn->fnct,gi->odc,gi->odt, gi->mask & 2);
   #ifdef LADICI_HLASENI
    gi->hashtab->Print();
    gi->fn->Print();
   #endif
    if (gi->filt > 0) {
        DeleteInconsist(gi->hashtab, gi->fn);
        if (gi->mask != 3)
        {
          ff = gi->fn->fnct;
          ff1 = fn2->fnct;
          while (ff != NULL)
          {
            if ((gi->mask & 1) == 0) memcpy(ff->iv, ff1->iv, gi->fn->inpvars);
            if ((gi->mask & 2) == 0) memcpy(ff->ov, ff1->ov, gi->fn->outvars);
            if (ff==gi->fn->last) {ff1l=ff1;}
            ff = ff->next;
            ff1 = ff1->next;
          }
        }
       #ifdef LADICI_HLASENI
        htab->Print();
        fn->Print();
       #endif
        ffl = gi->fn->last;
        ftime(&t1);
        while (gi->fn->terms < gi->t && t1.time-t2.time < gi->timeout)
        {
#ifdef VYPIS_CHYBEJICICH_TERMU
        if (zbyvajicich != gi->t-gi->fn->terms)
        {
          zbyvajicich = gi->t-gi->fn->terms;
          printf("Zbyva %d termu\n",zbyvajicich);
        }
#endif
          ffl = ff = gi->fn->last;
          gi->fn->AddTermToEnd(ff->iv, ff->ov, 0);
          ff = ffl->next;
          ff1 = ff1l->next;
         #ifdef LADICI_HLASENI
          htab->Print();
          fn->Print();
         #endif
          RandomFillFnctFrom(gi->hashtab, gi->fn, ff, gi->idc, gi->idt, gi->mask & 1);
         #ifdef LADICI_HLASENI
          htab->Print();
          fn->Print();
         #endif
          RandomFillFnctFrom(gi->hashtab, gi->fn, ff, gi->odc, gi->odt, gi->mask & 2);
         #ifdef LADICI_HLASENI
          gi->hashtab->Print();
          gi->fn->Print();
         #endif
          if (gi->mask != 3) {
            if (ff != NULL) {
              if ((gi->mask & 1) == 0) memcpy(ff->iv, ff1->iv, gi->fn->inpvars);
              if ((gi->mask & 2) == 0) memcpy(ff->ov, ff1->ov, gi->fn->outvars);
            }
          }
          brk=CheckConsistOf(gi->hashtab, gi->fn, ff); // zkouma validitu termu ff
          k=POCET_POKUSU_OUTPUT;
          while ((brk) && (k>0) && ((gi->mask & 2)==2) ) // pokud mame jeste pokusy a zajima nas output  tak zkousime menit output
          {
            --k;
            RandomFillFnctFrom(gi->hashtab, gi->fn, ff, gi->odc, gi->odt, gi->mask & 2);
           #ifdef LADICI_HLASENI
            gi->hashtab->Print();
            gi->fn->Print();
           #endif
            brk=CheckConsistOf(gi->hashtab, gi->fn, ff); // 0=consistent 1=incosnistent = must be deleted
          }
          if (brk)       // brk1 inconsistent => mazeme
          {
            gi->hashtab->DeleteTerm(ff);  // musi byt volana pred fn.
            gi->fn->DeleteTerm(ff,ffl);
          }
          else
          {
            ff1l = ff1l->next;  // Pokud se term nesmaze tak posuneme.
          }
          ftime(&t1);
        }
        TrimFnct(gi->fn,gi->t);
    }
    return (gi->fn->terms == gi->t);
}

void GetInfo(GenerateInfo *z,TBoolFnct *fn)
{
  long indc,intr,infa,oudc,outr,oufa,inp,out,pom;
  TPfnct *ff;
  int i,j;
  indc=intr=infa=oudc=outr=oufa=inp=out=pom=0;
  z->fn = fn;
  z->iv = fn->inpvars;
  z->ov = fn->outvars;
  z->t = fn->terms;
  ff=fn->fnct;
  j=0;
  while (ff!=NULL)
  {
    for (i=0; i<fn->inpvars; i++)
      if (ff->iv[i]=='0') { infa++; z->tab[j*6]++; }
      else if (ff->iv[i]=='1') { intr++; z->tab[j*6+1]++; }
      else if (ff->iv[i]=='-') { indc++; z->tab[j*6+2]++; }
    for (i=0; i<fn->outvars; i++)
      if (ff->ov[i]=='0') { oufa++; z->tab[j*6+3]++; }
      else if (ff->ov[i]=='1') { outr++; z->tab[j*6+4]++; }
      else if (ff->ov[i]=='~') { oudc++; z->tab[j*6+5]++; }
    ff=ff->next;
  }
  inp = z->iv*z->t;
  out = z->ov*z->t;
  z->idc = 100*indc / inp;
  z->odc = 100*oudc / out;
  pom=inp-indc;
  if (pom)
  {
    z->idt = 100*intr / pom;
    z->idf = 100-z->idt;
  }
  else
  {
    z->idt = -1;
    z->idf = -1;
  }
  pom=out-oudc;
  if (pom)
  {
    z->odt = 100*outr / pom;
    z->odf = 100-z->odt;
  }
  else
  {
    z->odt = -1;
    z->odf = -1;
  }
}

//---------------------------------------------------------------------------
int main( int argc, char * argv[] )
{
  int i;
  int cas,load,info,ready;
  struct timeb t2, t1;
  int fr = 1;

  ftime(&t2);

  Boom * boominst;
  GenerateInfo *gi,*gg;

  boominst = new Boom();
  boominst->gauge.NewGauge = NewGauge;
  boominst->gauge.CloseGauge = CloseGauge;
  boominst->gauge.GaugeStep = GaugeStep;

  srand((unsigned int)time((time_t *)NULL));
  gi = new GenerateInfo(0);
  gi->bits = 0;
  gi->onmpla = 0;
  gi->onminf = 0;
  gi->iv = -1;
  gi->ov = -1;
  gi->t = -1;
  gi->idc = 0;
  gi->odc = 0;
  gi->idt = 50;
  gi->odt = 50;
  gi->filt = 1;
  gi->timeout = 1000;
  gi->mask = 3;

  i = 1;
  load = 0;
  info = 0;
  ready = 0;

  fprintf( stderr, "PLA Generator 2.0, (c) December 2005\n\n" );
  while ( i != argc )
  {
    if ( argv[i] [0] == '-' )
    {
        if ( strcmp(argv[i], "-i") == 0)
            gi->iv = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-fd") == 0)             // NEW!
            fr = 0;
        else if ( strcmp(argv[i], "-o") == 0)
            gi->ov = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-t") == 0)
            gi->t = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-h") == 0)
            gi->bits = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-idc") == 0)
            gi->idc = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-odc") == 0)
            gi->odc = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-idt") == 0)
            gi->idt = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-odt") == 0)
            gi->odt = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-timeout") == 0)
            gi->timeout = atoi( argv[++i] );
        else if ( strcmp(argv[i], "-NC") == 0)
            gi->filt = 0;
        else if ( strcmp(argv[i], "-IN") == 0)
            info = 1;
        else if ( strcmp(argv[i], "-L") == 0) {
            load = 1;
            info = 1; }
        else {
            fprintf( stderr, "Unknown parameter %s\n", argv[i] );
            exit( 1 );
        }
    } else
      gi->onmpla = argv[i];
    i++;
  }

  gi->idf = 100-gi->idt;
  gi->odf = 100-gi->odt;

  if (( gi->iv == -1 || gi->ov == -1 || gi->t == -1 ) && (load==0))help();
  else
  {

    if (load)
    {
      if (gi->fn=gi->fn->LoadFnct(gi->onmpla,boominst->gauge))
      { ready=1; }
      else fprintf(stderr, "Cannot open file \"%s\"",gi->onmpla);
    }
    else
    {
      gi->fn = new TBoolFnct( gi->iv, gi->ov, gi->t, 1 );
      gi->fn->FillEmptyFnct();
      gi->fn->NameVars();
      gi->hashtab = new THash_Tabulka(gi->bits,gi->fn);
      if ( RndConFillFnct( gi ) )
         {
           gi->fn->type = fr;
           gi->fn->SaveFnct( gi->onmpla, boominst->gauge, boominst->go);
           ready=1;
         }
      else fprintf( stderr, "Timeout\n" );

    }
    if (info && ready)
    {
      gg = new GenerateInfo(gi->fn->terms);
      GetInfo(gg,gi->fn);
      gg->Print();
      if (!load) gg->PrintOdchylka(gi);
      delete gg;
    }
    ftime(&t1);
    cas=t1.time*1000+t1.millitm-t2.time*1000-t2.millitm;
   #ifdef VYPIS_CASU
    printf("Program jel %.3f sekund. tj %d:%d.%d\n",(float)cas/1000,cas/60000,(cas/1000)%60,cas%1000);
   #endif

    delete gi->fn;
    delete gi->hashtab;
    delete gi;

  }
  return 0;
}
