//---------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef BC
  #include <algorithm.h>
#endif
#include <sys/timeb.h>
#include <time.h>
#include <limits.h>
//---------------------------------------------------------------------------
#include "main.h"
#include "conf.h"
#include "tpfnct.h"
#include "bufferstruct.h"
#include "algs.h"
#include "implcheck.h"
#include "tboolfnct.h"
//---------------------------------------------------------------------------
TBoolFnct::TBoolFnct( int iv, int ov, int vct, int tp )
{
  int i;
  this->terms = vct;
  this->inpvars = iv;
  this->outvars = ov;
  this->type = tp;
  this->fnct = 0;
  this->last = 0;
  this->inames = 0;
  this->onames = 0;
  this->parent = 0;
  this->parent = 0;
  this->split = 0;
  this->inames = new char * [iv];
  for ( i = 0; i < iv; i++ ) this->inames[i] = 0;
  this->onames = new char * [ov];
  for ( i = 0; i < ov; i++ ) this->onames[i] = 0;
  this->decomp = 0;
  this->index = 0;
}
//---------------------------------------------------------------------------

TBoolFnct& TBoolFnct::operator=(TBoolFnct &_fn)
{
  this->terms = _fn.terms;
  this->inpvars = _fn.inpvars;
  this->outvars = _fn.outvars;
  this->type = _fn.type;
  this->info = _fn.info;
  this->firstpass = _fn.firstpass;
  this->hits = _fn.hits;
  this->tries = _fn.tries;
  this->parent = _fn.parent;
  this->last = 0;
  TPfnct *pointer = _fn.fnct;
  while ( pointer != 0 )
  {
    TPfnct *temp = new TPfnct();
    temp->operator=(*pointer);
    if ( this->last != 0 ) this->last->next = temp;
    this->last = temp;
    if ( this->fnct == 0 ) this->fnct = temp;
    this->terms++;
    pointer = pointer->next;
  }
  return *this;
}
//---------------------------------------------------------------------------
TBoolFnct::~TBoolFnct()
{
  TPfnct * fnct2;
  int i;
  if ( this == 0 ) return;
  while ( this->fnct != 0 )
  {
    delete[] this->fnct->iv;
    delete[] this->fnct->ov;
    this->fnct->DeleteCovs();
    fnct2 = this->fnct->next;
    delete this->fnct;
    this->fnct = fnct2;
  }
  if ( this->parent == 0 )
  {
    this->DeleteNames();
 //   DestroyDecompAss( this );
    //delete []fn->ffbinds;
  }
  if ( this->split == 1 ) this->DeleteSplit();

  if ( this->index != 0 ) delete[] this->index;
  //    delete this;
}
//---------------------------------------------------------------------------
void TBoolFnct::NameIVars()
{
  int i;
  if ( this->inames != 0 )
    for ( i = 0; i < this->inpvars; i++ )
    {
      this->inames[i] = new char[7];
      sprintf( this->inames[i], "x%i", i );
    }
}
//---------------------------------------------------------------------------
void TBoolFnct::NameOVars()
{
  int i;

  if ( this->onames != 0 )
    for ( i = 0; i < this->outvars; i++ )
    {
      this->onames[i] = new char[7];
      sprintf( this->onames[i], "y%i", i );
    }
}
//---------------------------------------------------------------------------
TBoolFnct * TBoolFnct::CreateChildFnct()
{
  TBoolFnct * fnc = new TBoolFnct( this->inpvars, this->outvars, 0, this->type );
  delete[] fnc->inames;
  delete[] fnc->onames;
  fnc->inames = this->inames;
  fnc->onames = this->onames;
  fnc->parent = this;
  fnc->split = 0;
  fnc->decomp = this->decomp;
  return fnc;
}
//---------------------------------------------------------------------------
TPfnct * TBoolFnct::AddEmptyTermToEnd()
{
  TPfnct * t = new TPfnct();
  if ( this->last != 0 ) this->last->next = t;
  this->last = t;
  if ( this->fnct == 0 ) this->fnct = t;
  this->terms++;
  return t;
}
//---------------------------------------------------------------------------
TPfnct * TBoolFnct::AddTermToBeginning( char * ivr, char * ovr, int tdim )
{
  TPfnct * t = new TPfnct(this,ivr,ovr,tdim);
  t->next = this->fnct;
  this->fnct = t;
  this->terms++;
  return t;
}
//---------------------------------------------------------------------------
TPfnct * TBoolFnct::AddTermToEnd( char * ivr, char * ovr, int tdim )
{
  TPfnct * t = new TPfnct(this,ivr,ovr,tdim);
  t->next = 0;
  if ( this->last != 0 ) this->last->next = t;
  this->last = t;
  if ( this->fnct == 0 ) this->fnct = t;
  this->terms++;
  return t;
}
//---------------------------------------------------------------------------
void TBoolFnct::JoinFnct( TBoolFnct * src )
{
  TPfnct *tempFnct = 0;
  TPfnct *prev = 0;
  TPfnct *pointer = src->fnct;
  while ( pointer != 0 )
  {
  TPfnct *temp = new TPfnct();
  temp->operator=(*pointer);
  if ( prev != 0 ) prev->next = temp;
  prev = temp;
  if ( tempFnct == 0 ) tempFnct = temp;
  pointer = pointer->next;
  }

  if ( this->fnct == 0 )
  {
    this->fnct = tempFnct;
    this->last = prev;
  }
  else
  {
    this->last->next = tempFnct;
    if ( src->last != 0 ) this->last = prev;
  }
  this->terms = this->terms + src->terms;
  if ( src->parent == 0 )
  {
    src->DeleteNames();
 //   DestroyDecompAss( this );
  }
  if ( src->split == 1 ) src->DeleteSplit();
 // if ( src->index != 0 ) delete[] src->index;
  this->Reindex();  
  delete src;
}
//---------------------------------------------------------------------------

TBoolFnct * TBoolFnct::LoadFnct( char * filn, TGauge gauge )
{
  FILE * f;
  int i, j;
  char s[65000];
  TBoolFnct * fn = 0;
  int dend;
  char s1[65000], s2[65000];
  int iv = 0, ov = 0, tp = 0;
  char * * inames = 0, * * onames = 0;

  gauge.NewGauge( "Loading PLA file", 0, 1 );
  if ( ( f = fopen( filn, "rt" ) ) == 0 ) return 0;
  dend = 0;
  while ( !feof( f ) && dend == 0 )
  {
    fscanf( f, "%s", s );
    if ( strcmpi( s, ".i" ) == 0 )
    {
      fscanf( f, "%s", s );
      iv = atoi( s );
    }
    else if ( strcmpi( s, ".o" ) == 0 )
    {
      fscanf( f, "%s", s );
      ov = atoi( s );
    }
    else if ( strcmpi( s, ".type" ) == 0 )
    {
      fscanf( f, "%s", s );
      if ( strcmpi( s, "fr" ) == 0 ) tp = 1;
    }
    else if ( strcmpi( s, ".ilb" ) == 0 )
    {
      inames = new char * [iv];
      for ( i = 0; i < iv; i++ )
      {
        fscanf( f, "%s", s );
        inames[i] = new( char[strlen( s ) + 1] );
        strcpy( inames[i], s );
      }
    }
    else if ( strcmpi( s, ".ob" ) == 0 )
    {
      onames = new char * [ov];
      for ( i = 0; i < ov; i++ )
      {
        fscanf( f, "%s", s );
        onames[i] = new( char[strlen( s ) + 1] );
        strcpy( onames[i], s );
      }
    }
    else if ( strncmpi( s, ".e", 2 ) == 0 ) dend = 1;
    else if ( s[0] == '.' )
    {
      do fscanf( f, "%c", s );
      while ( s[0] != 10 && s[0] != 13 );
    }
    else if ( s[0] == '0' || s[0] == '1' || s[0] == '2' || s[0] == '3' || s[0] == '4' || s[0] == '-' || s[0] == '~' )
    {
      if ( fn == 0 )
      {
        fn = new TBoolFnct( iv, ov, 0, tp );
        if ( inames != 0 )
        {
          delete[] fn->inames;
          fn->inames = inames;
        }
        else
          fn->NameIVars();
        if ( onames != 0 )
        {
          delete[] fn->onames;
          fn->onames = onames;
        }
        else
          fn->NameOVars();
      }
      i = 0;
      j = 0;
      while ( i != iv && !feof( f ) )
      {
        if ( ( unsigned )j == strlen( s ) )
        {
          fscanf( f, "%s", s );
          j = 0;
        }
        if ( s[j] == '0' || s[j] == '1' || s[j] == '-' || s[j] == '~' )
          s1[i++] = s[j];
        else if ( s[j] == '2' )
          s1[i++] = '-';
        else if ( s[j] == '3' )
          s1[i++] = '~';
        else if ( s[j] == '4' )
          s1[i++] = '1';
        j++;
      }
      if ( feof( f ) ) break;
      s1[i] = 0;
      i = 0;
      j++;
      while ( i != ov && !feof( f ) )
      {
        if ( ( unsigned )j >= strlen( s ) )
        {
          fscanf( f, "%s", s );
          j = 0;
        }
        if ( s[j] == '0' || s[j] == '1' || s[j] == '-' || s[j] == '~' )
          s2[i++] = s[j];
        else if ( s[j] == '2' )
          s2[i++] = '-';
        else if ( s[j] == '3' )
          s2[i++] = '~';
        else if ( s[j] == '4' )
          s2[i++] = '1';
        j++;
      }
      s2[i] = 0;
      fn->AddTermToEnd( s1, s2, fn->GetDim( s1 ) );
    }
  }
  fclose( f );
  fn->NullFFBinds();
  gauge.CloseGauge();
  return fn;
}
//---------------------------------------------------------------------------
int TBoolFnct::SaveFnct( char * filn, TGauge gauge, bool savevarnames )
{
  FILE * f;
  TPfnct * ff;
  int i;

  gauge.NewGauge( "Saving PLA", this->terms, 1 );
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;
  fprintf( f, ".i %i\n", this->inpvars );
  fprintf( f, ".o %i\n", this->outvars );
  fprintf( f, ".p %i\n", this->terms );
  if ( this->inames != 0 && savevarnames )
  {
    fprintf( f, ".ilb" );
    for ( i = 0; i < this->inpvars; i++ ) fprintf( f, " %s", this->inames[i] );
    fprintf( f, "\n" );
  }
  if ( this->onames != 0 && savevarnames )
  {
    fprintf( f, ".ob" );
    for ( i = 0; i < this->outvars; i++ ) fprintf( f, " %s", this->onames[i] );
    fprintf( f, "\n" );
  }
  fprintf( f, ".type " );
  switch ( this->type )
  {
    case 0:
      fprintf( f, "fd\n" );
    break;
    case 1:
      fprintf( f, "fr\n" );
  }
  ff = this->fnct;
  i = 0;
  while ( ff != 0 )
  {
    ff->iv[this->inpvars] = 0;
    ff->ov[this->outvars] = 0;
    fprintf( f, "%s %s\n", ff->iv, ff->ov );
    ff = ff->next;
    if ( gauge.GaugeStep( i++, 0 ) != 0 ) break;
  }
  fprintf( f, ".e\n" );
  fclose( f );
  gauge.CloseGauge();
  return 1;
}
//---------------------------------------------------------------------------
void TBoolFnct::FillEmptyFnct()
{
  int i, j;
  TPfnct * fnct2;
  for ( j = 1; j <= this->terms; j++ )
  {
    fnct2 = new TPfnct;
    fnct2->valid = 1;
    fnct2->prime = 0;
    fnct2->origin = 0;
    fnct2->cov = 0;
    fnct2->covfield = 0;
    fnct2->next = this->fnct;
    if ( this->fnct == 0 ) this->last = fnct2;
    this->fnct = fnct2;
    this->fnct->iv = new( char[this->inpvars + 1] );
    for ( i = 0; i < this->inpvars; i++ ) this->fnct->iv[i] = '-';
    this->fnct->iv[i] = 0;
    this->fnct->ov = new( char[this->outvars + 1] );
    for ( i = 0; i < this->outvars; i++ ) this->fnct->ov[i] = '~';
    this->fnct->ov[i] = 0;
  }
}
//---------------------------------------------------------------------------
void TBoolFnct::GetInfo()
{
  TPfnct * ff;
  int i, j, c;
  int d;
  char * o1;

  o1 = new char[this->outvars];
  setmem( o1, this->outvars, 0 );
  this->info.liters = 0;
  this->info.ON_terms = 0;
  this->info.OFF_terms = 0;
  this->info.DC_terms = 0;
  this->info.groupterms = this->terms;
  this->info.selterms = this->terms;
  this->info.primes = 0;
  this->info.GEs = 0;
  this->info.gates = 0;
  ff = this->fnct;
  while ( ff != 0 )
  {
    d = 0;
    for ( i = 0; i < this->inpvars; i++ )
      if ( ff->iv[i] == '0' || ff->iv[i] == '1' ) d++;
    ff->dim = this->inpvars - d;
    this->info.liters += d;
    this->info.gates += max( d - 1, 0 );
    if ( d > 1 ) this->info.GEs += d;
    for ( i = 0; i < this->outvars; i++ )
      switch ( ff->ov[i] )
      {
        case '0':
          this->info.OFF_terms++;
        break;
        case '1':
          this->info.ON_terms++;
          o1[i] ++;
        break;
        case '-':
          this->info.DC_terms++;
      }
    if ( ff->valid == 0 ) this->info.selterms--;
    if ( ff->prime == 1 ) this->info.primes++;
    ff = ff->next;
  }
  this->info.gates += this->info.ON_terms - this->outvars;
  if ( this->info.gates < 0 ) this->info.gates = 0;
  this->info.GEs += this->info.ON_terms;
  for ( i = 0; i < this->outvars; i++ )
    if ( o1[i] == 1 ) this->info.GEs--;
  delete[] o1;
}
//---------------------------------------------------------------------------

char * TBoolFnct::FunctToSymbols( int ovr, Notation notation )
{
  TPfnct * ff;
  int i;
  char s[65000];
  int frst, frst2;
  char * s1;
  int tautflg, kontrflg;

  ff = this->fnct;
  strcpy( s, this->onames[ovr] );
  strcat( s, "=" );
  frst = 1;
  kontrflg = 1;
  while ( ff != 0 )
  {
    if ( ff->ov[ovr] == '1' )
    {
      kontrflg = 0;
      if ( frst == 0 ) strcat( s, notation.NOT_add );
      frst = 0;
      frst2 = 1;
      tautflg = 1;
      for ( i = 0; i < this->inpvars; i++ )
      {
        if ( ff->iv[i] != '-' )
        {
          tautflg = 0;
          if ( frst2 == 0 ) strcat( s, notation.NOT_multiply );
          frst2 = 0;
          if ( ff->iv[i] == '0' && notation.NOT_postneg == 0 ) strcat( s, notation.NOT_neg );
          strcat( s, this->inames[i] );
          if ( ff->iv[i] == '0' && notation.NOT_postneg == 1 ) strcat( s, notation.NOT_neg );
        }
      }
      if ( tautflg == 1 ) strcat( s, "1" );
    }
    ff = ff->next;
  }
  if ( kontrflg == 1 ) strcat( s, "0" );
  s1 = new char[strlen( s ) + 1];
  strcpy( s1, s );
  return s1;
}
//---------------------------------------------------------------------------
void TBoolFnct::DeleteInvalidTerms()
{
  TPfnct * ff, * ff1, * ff2;

  ff = this->fnct;
  ff2 = 0;
  while ( ff != 0 )
  {
    if ( ff->valid == 0 )
    {
      if ( this->fnct == ff )
      {
        this->fnct = ff->next;
        if ( this->fnct == 0 ) this->last = 0;
        delete[] ff->iv;
        delete[] ff->ov;
        ff->DeleteCovs();
        delete ff;
        ff = this->fnct;
        ff2 = ff;
        this->terms--;
      }
      else
      {
        ff1 = ff->next;
        delete[] ff->iv;
        delete[] ff->ov;
        ff->DeleteCovs();
        if ( this->last == ff ) this->last = ff2;
        delete ff;
        ff2->next = ff1;
        ff = ff1;
        this->terms--;
      }
    }
    else
    {
      ff2 = ff;
      ff = ff->next;
    }
  }
}
//---------------------------------------------------------------------------
void TBoolFnct::SplitFnct()
{
  TPfnct * ff, * sf;
  int i;

  if ( this->split == 1 ) return;
  this->onterms = new( int[this->outvars] );
  this->offterms = new( int[this->outvars] );
  this->dcterms = new( int[this->outvars] );
  this->onset = new( TPfnct * [this->outvars] );
  this->offset = new( TPfnct * [this->outvars] );
  this->dcset = new( TPfnct * [this->outvars] );
  this->maxonterms = 0;
  for ( i = 0; i < this->outvars; i++ )
  {
    this->onterms[i] = 0;
    this->offterms[i] = 0;
    this->dcterms[i] = 0;
    this->onset[i] = 0;
    this->offset[i] = 0;
    this->dcset[i] = 0;
  }
  ff = this->fnct;
  while ( ff != 0 )
  {
    for ( i = 0; i < this->outvars; i++ )
    {
      if ( ff->ov[i] == '1' )
      {
        sf = new TPfnct;
        sf->cov = 0;
        sf->covfield = 0;
        sf->next = this->onset[i];
        this->onset[i] = sf;
        sf->iv = new char[this->inpvars + 1];
        sf->ov = 0;
        memcpy( sf->iv, ff->iv, this->inpvars );
        sf->iv[this->inpvars] = 0;
        sf->dim = ff->dim;
        sf->cvd = 0;
        this->onterms[i] ++;
        if ( this->maxonterms < this->onterms[i] ) this->maxonterms = this->onterms[i];
      }
      else if ( ff->ov[i] == '0' && this->type == 1 )
      {
        sf = new TPfnct;
        sf->cov = 0;
        sf->covfield = 0;
        sf->next = this->offset[i];
        this->offset[i] = sf;
        sf->iv = new char[this->inpvars + 1];
        sf->ov = 0;
        memcpy( sf->iv, ff->iv, this->inpvars );
        sf->iv[this->inpvars] = 0;
        sf->dim = ff->dim;
        sf->cvd = 0;
        this->offterms[i] ++;
      }
      else if ( ff->ov[i] == '-' && this->type == 0 )
      {
        sf = new TPfnct;
        sf->cov = 0;
        sf->covfield = 0;
        sf->next = this->dcset[i];
        this->dcset[i] = sf;
        sf->iv = new char[this->inpvars + 1];
        sf->ov = 0;
        memcpy( sf->iv, ff->iv, this->inpvars );
        sf->iv[this->inpvars] = 0;
        sf->dim = ff->dim;
        sf->cvd = 0;
        this->dcterms[i] ++;
      }
    }
    ff = ff->next;
  }
  this->split = 1;
}
//---------------------------------------------------------------------------
TPfnct * TBoolFnct::DeleteTerm( TPfnct * ff, TPfnct * pff )
{
  TPfnct * nff;

  nff = ff->next;
  if ( this->fnct == ff ) this->fnct = nff;
  else pff->next = nff;
  ff->DeleteCovs();
  delete[] ff->iv;
  delete[] ff->ov;
  if ( this->last == ff ) this->last = pff;
  delete ff;
  this->terms--;
  return nff;
}
//---------------------------------------------------------------------------
void TBoolFnct::DeleteTerm( int t ) /* Deletes term # t */
{
  TPfnct * ff, * ff1;
  int i;

  if ( this == 0 ) return;
  if ( t == 0 )
  {
    delete[] this->fnct->iv;
    delete[] this->fnct->ov;
    this->fnct->DeleteCovs();
    ff = this->fnct->next;
    delete this->fnct;
    this->fnct = ff;
  }
  else
  {
    ff = this->fnct;
    i = 0;
    while ( ff != 0 && i != t - 1 )
    {
      ff = ff->next;
      i++;
    }
    if ( ff == 0 ) return;
    delete[] ff->next->iv;
    delete[] ff->next->ov;
    ff->next->DeleteCovs();
    ff1 = ff->next->next;
    delete ff->next;
    ff->next = ff1;
    if ( ff1 == 0 ) this->last = ff;
  }
  this->terms--;
}
//---------------------------------------------------------------------------
int TBoolFnct::GetDim( char * ivr )
{
  int i, j;
  j = 0;
  for ( i = 0; i < this->inpvars; i++ )
    if ( ivr[i] == '-' ) j++;
  return j;
}
//---------------------------------------------------------------------------
void TBoolFnct::NullFFBinds()
{
  int i;
  if ( this != 0 )
  {
    this->ffbinds = new int[this->outvars];
    for ( i = 0; i < this->outvars; i++ ) this->ffbinds[i] = -1;
  }
}
//---------------------------------------------------------------------------
void TBoolFnct::SaveFnctAsSymbols( char * filn, TGauge gauge, Notation notation )
{
  FILE * f;
  int i;

  gauge.NewGauge( "Saving function as text", this->outvars, 1 );
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;
  for ( i = 0; i < this->outvars; i++ )
  {
    fprintf( f, "%s\n", this->FunctToSymbols( i, notation ) );
    if ( gauge.GaugeStep( i, 0 ) != 0 ) break;
  }
  fclose( f );
  gauge.CloseGauge();
}
//---------------------------------------------------------------------------
void TBoolFnct::SaveFnctAsVHDL( char * filn, TGauge gauge )
{
  FILE * f;
  int i, j, fl;
  char n[255];
  char * np;

  gauge.NewGauge( "Saving function as VHDL", 0, 1 );
  this->Reindex();
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;
  strcpy( n, filn );
  np = strrchr( n, '\\' );
  if (np == 0) np = n; else np++;
  if (strchr( np, '.' ) != 0) strchr( np, '.') [0] = 0;
  fprintf( f, "library IEEE;\n" );
  fprintf( f, "use IEEE.std_logic_1164.all;\n\n" );
  fprintf( f, "entity %s is\n", np );
  fprintf( f, "   port(" );
  for ( i = 0; i < this->inpvars; i++ )
    if ( i == 0 ) fprintf( f, "%s", this->inames[i] );
    else
      fprintf( f, ", %s", this->inames[i] );
  fprintf( f, " : in std_logic;\n" );
  fprintf( f, "      " );
  for ( i = 0; i < this->outvars; i++ )
    if ( i == 0 ) fprintf( f, "%s", this->onames[i] );
    else
      fprintf( f, ", %s", this->onames[i] );
  fprintf( f, " : out std_logic);\n" );
  fprintf( f, "end %s;\n", np );
  fprintf( f, "\n" );
  fprintf( f, "architecture %s_arch of %s is\n", np, np );
  fprintf( f, "   signal " );
  for ( i = 0; i < this->terms; i++ )
    if ( i == 0 ) fprintf( f, "t%i", i );
    else
      fprintf( f, ", t%i", i );
  fprintf( f, " : std_logic;\n" );
  fprintf( f, "   signal " );
  for ( i = 0; i < this->inpvars; i++ )
    if ( i == 0 ) fprintf( f, "n_%s", this->inames[i] );
    else
      fprintf( f, ", n_%s", this->inames[i] );
  fprintf( f, " : std_logic;\n" );
  fprintf( f, "\n" );
  fprintf( f, "begin\n" );
  for ( i = 0; i < this->inpvars; i++ )
    fprintf( f, "   n_%s <= not %s;\n", this->inames[i], this->inames[i] );
  fprintf( f, "\n" );
  for ( i = 0; i < this->terms; i++ )
  {
    fprintf( f, "   t%i <= ", i );
    fl = 0;
    for ( j = 0; j < this->inpvars; j++ )
      if ( this->index[i]->iv[j] != '-' )
      {
        if ( fl != 0 ) fprintf( f, " and " );
        if ( this->index[i]->iv[j] == '0' ) fprintf( f, "n_" );
        fl = 1;
        fprintf( f, "%s", this->inames[j] );
      }
    fprintf( f, ";\n" );
  }
  fprintf( f, "\n" );
  for ( i = 0; i < this->outvars; i++ )
  {
    fprintf( f, "   %s <= ", this->onames[i] );
    fl = 0;
    for ( j = 0; j < this->terms; j++ )
      if ( this->index[j]->ov[i] == '1' )
      {
        if ( fl != 0 ) fprintf( f, " or " );
        fprintf( f, "t%i", j );
        fl = 1;
      }
    if ( fl == 0 ) fprintf( f, "0" );
    fprintf( f, ";\n" );
  }
  fprintf( f, "end %s_arch;\n", np );

  fclose( f );
  gauge.CloseGauge();
}

void TBoolFnct::SaveFnctAsVHDL2( char * filn, TGauge gauge )
{
  FILE * f;
  int i, j, fl;
  char n[255];
  char * np;

  gauge.NewGauge( "Saving function as VHDL", 0, 1 );
  this->Reindex();
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;
  strcpy( n, filn );
  np = strrchr( n, '\\' );
  if (np == 0) np = n; else np++;
  if (strchr( np, '.' ) != 0) strchr( np, '.') [0] = 0;
  fprintf( f, "library IEEE;\n" );
  fprintf( f, "use IEEE.std_logic_1164.all;\n\n" );
  fprintf( f, "entity %s is\n", np );
  fprintf( f, "   port(\n" );
  fprintf( f, "        INPUT : in std_logic_vector(%i downto 0);\n", this->inpvars-1);
  fprintf( f, "        OUTPUT : out std_logic_vector(%i downto 0)\n", this->outvars-1);
  fprintf( f, "       );\n" );
  fprintf( f, "end %s;\n\n", np );
  fprintf( f, "architecture %s_arch of %s is\n", np, np );
  fprintf( f, "   signal " );
  for ( i = 0; i < this->terms; i++ )
    if ( i == 0 ) fprintf( f, "t%i", i );
    else
      fprintf( f, ", t%i", i );
  fprintf( f, " : std_logic;\n" );
  fprintf( f, "   signal n_INPUT : std_logic_vector(%i downto 0);\n", this->inpvars-1);
  fprintf( f, "\n" );
  fprintf( f, "begin\n" );
  fprintf( f, "  neg:\n" );
  fprintf( f, "    for i in %i downto 0 generate\n", this->inpvars-1 );
  fprintf( f, "      gen:\n" );
  fprintf( f, "        n_INPUT(i) <= not(INPUT(i));\n" );
  fprintf( f, "    end generate;\n\n" );

  for ( i = 0; i < this->terms; i++ )
  {
    fprintf( f, "   t%i <= ", i );
    fl = 0;
    for ( j = 0; j < this->inpvars; j++ )
      if ( this->index[i]->iv[j] != '-' )
      {
        if ( fl != 0 ) fprintf( f, " and " );
        if ( this->index[i]->iv[j] == '0' ) fprintf( f, "n_" );
        fl = 1;
        fprintf( f, "INPUT(%i)", j );
      }
    fprintf( f, ";\n" );
  }
  fprintf( f, "\n" );
  for ( i = 0; i < this->outvars; i++ )
  {
    fprintf( f, "   OUTPUT(%i) <= ", i );
    fl = 0;
    for ( j = 0; j < this->terms; j++ )
      if ( this->index[j]->ov[i] == '1' )
      {
        if ( fl != 0 ) fprintf( f, " or " );
        fprintf( f, "t%i", j );
        fl = 1;
      }
    if ( fl == 0 ) fprintf( f, "0" );
    fprintf( f, ";\n" );
  }
  fprintf( f, "end %s_arch;\n", np );

  fclose( f );
  gauge.CloseGauge();
}

//---------------------------------------------------------------------------
void TBoolFnct::SaveFnctAsVerilog( char * filn, TGauge gauge )
{
  FILE * f;
  int i, j, fl;
  char n[255];
  char * np;

  gauge.NewGauge( "Saving function as Verilog", 0, 1 );
  this->Reindex();
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;
  strcpy( n, filn );
  np = strrchr( n, '\\' );
  if (np == 0) np = n; else np++;
  if (strchr( np, '.' ) != 0) strchr( np, '.') [0] = 0;
  fprintf( f, "module %s (", np );
  for ( i = 0; i < this->inpvars; i++ )
  {
    if ( i != 0 ) fprintf( f, ", " );
    fprintf( f, "%s", this->inames[i] );
  }
  for ( i = 0; i < this->outvars; i++ ) fprintf( f, ", %s", this->onames[i] );
  fprintf( f, ");\n" );
  fprintf( f, "input " );
  for ( i = 0; i < this->inpvars; i++ )
  {
    if ( i != 0 ) fprintf( f, ", " );
    fprintf( f, "%s", this->inames[i] );
  }
  fprintf( f, ";\n" );
  fprintf( f, "output " );
  for ( i = 0; i < this->outvars; i++ )
  {
    if ( i != 0 ) fprintf( f, ", " );
    fprintf( f, "%s", this->onames[i] );
  }
  fprintf( f, ";\n" );
  fprintf( f, "wire " );
  for ( i = 0; i < this->terms; i++ )
  {
    if ( i != 0 ) fprintf( f, ", " );
    fprintf( f, "t%i", i );
  }
  fprintf( f, ";\n\n" );

  fprintf( f, "assign\n" );
  for ( i = 0; i < this->terms; i++ )
  {
    fprintf( f, "   t%i = ", i );
    fl = 0;
    for ( j = 0; j < this->inpvars; j++ )
      if ( this->index[i]->iv[j] != '-' )
      {
        if ( fl != 0 ) fprintf( f, " & " );
        fl = 1;
        if ( this->index[i]->iv[j] == '0' ) fprintf( f, "~" );
        fprintf( f, "%s", this->inames[j] );
      }
    if ( i != this->terms ) fprintf( f, ",\n" );
    else fprintf( f, ";\n" );
  }
  fprintf( f, "\n" );
  for ( i = 0; i < this->outvars; i++ )
  {
    fprintf( f, "   %s = ", this->onames[i] );
    fl = 0;
    for ( j = 0; j < this->terms; j++ )
      if ( this->index[j]->ov[i] == '1' )
      {
        if ( fl != 0 ) fprintf( f, " | " );
        fl = 1;
        fprintf( f, "t%i", j );
      }
    if ( fl == 0 ) fprintf( f, "0" );
    if ( i != this->outvars - 1 ) fprintf( f, ",\n" );
    else fprintf( f, ";\n" );
  }
  fprintf( f, "endmodule\n" );


  fclose( f );
  gauge.CloseGauge();
}
//---------------------------------------------------------------------------
void TBoolFnct::SaveFnctAsVerilog2( char * filn, TGauge gauge ) /* Doesn't take into account group terms - just equations */
{
  FILE * f;
  int i, j, k, fl, fl2;
  char n[255];
  char * np;

  gauge.NewGauge( "Saving function as Verilog", 0, 1 );
  this->Reindex();
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;
  strcpy( n, filn );
  np = strrchr( n, '\\' ) + 1;
  strchr( np, '.' ) [0] = 0;

  fprintf( f, "module %s (", np );
  for ( i = 0; i < this->inpvars; i++ )
  {
    if ( i != 0 ) fprintf( f, ", " );
    fprintf( f, "%s", this->inames[i] );
  }
  for ( i = 0; i < this->outvars; i++ ) fprintf( f, ", %s", this->onames[i] );
  fprintf( f, ");\n" );
  fprintf( f, "input " );
  for ( i = 0; i < this->inpvars; i++ )
  {
    if ( i != 0 ) fprintf( f, ", " );
    fprintf( f, "%s", this->inames[i] );
  }
  fprintf( f, ";\n" );
  fprintf( f, "output " );
  for ( i = 0; i < this->outvars; i++ )
  {
    if ( i != 0 ) fprintf( f, ", " );
    fprintf( f, "%s", this->onames[i] );
  }
  fprintf( f, ";\n\n" );
  fprintf( f, "assign\n" );

  for ( i = 0; i < this->outvars; i++ )
  {
    fprintf( f, "   %s = ", this->onames[i] );
    fl = 0;
    for ( j = 0; j < this->terms; j++ )
      if ( this->index[j]->ov[i] == '1' )
      {
        if ( fl != 0 ) fprintf( f, " | " );
        fl = 1;
        fprintf( f, "(" );
        fl2 = 0;
        for ( k = 0; k < this->inpvars; k++ )
          if ( this->index[j]->iv[k] != '-' )
          {
            if ( fl2 != 0 ) fprintf( f, " & " );
            fl2 = 1;
            if ( this->index[j]->iv[k] == '0' ) fprintf( f, "~" );
            fprintf( f, "%s", this->inames[k] );
          }
        fprintf( f, ")" );
      }
    if ( fl == 0 ) fprintf( f, "0" );
    if ( i != this->outvars - 1 ) fprintf( f, ",\n" );
    else fprintf( f, ";\n" );
  }
  fprintf( f, "endmodule\n" );
  fclose( f );
  gauge.CloseGauge();
}

//---------------------------------------------------------------------------
void TBoolFnct::SaveFnctAsHTML( char * filn, TGauge gauge )
{
  FILE * f;
  int i;
  TPfnct * ff;

  gauge.NewGauge( "Saving functin as HTML", this->outvars, 1 );
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;
  fprintf( f, "<html>\n" );
  fprintf( f, "<head>\n" );
  fprintf( f, "<meta http-equiv=""Content-Type"" content=""text/html; charset=iso-8859-1"">\n" );
  fprintf( f, "<body>\n" );
  fprintf( f, "<table border=1>\n" );
  fprintf( f, "<tr>\n" );
  for ( i = 0; i < this->inpvars; i++ )
    fprintf( f, "  <td>%s</td>\n", this->inames[i] );
  for ( i = 0; i < this->outvars; i++ )
    fprintf( f, "  <td bgcolor=""cyan"">%s</td>\n", this->onames[i] );
  fprintf( f, "</tr>\n" );
  ff = this->fnct;
  i = 0;
  while ( ff != 0 )
  {
    fprintf( f, "<tr>\n" );
    for ( i = 0; i < this->inpvars; i++ )
      fprintf( f, "  <td>%c</td>\n", ff->iv[i] );
    for ( i = 0; i < this->outvars; i++ )
      fprintf( f, "  <td bgcolor=""cyan"">%c</td>\n", ff->ov[i] );
    fprintf( f, "</tr>\n" );
    if ( gauge.GaugeStep( i++, 0 ) != 0 ) break;
    ff = ff->next;
  }
  fprintf( f, "</body>\n" );
  fprintf( f, "</html>\n" );
  fclose( f );
  gauge.CloseGauge();
}
//---------------------------------------------------------------------------

void TBoolFnct::SaveFnctAsBLIF( char * filn, TGauge gauge )
{
  FILE * f;
  int i, j, k, l;
  TPfnct * ff;

  gauge.NewGauge( "Saving functin as BLIF", this->terms + this->outvars, 1 );
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;

  fprintf( f, ".model new\n\n");
  fprintf( f, ".inputs");
  for ( i = 0; i < this->inpvars; i++ )
    fprintf( f, " %s", this->inames[i] );
  fprintf( f, "\n");
  fprintf( f, ".outputs");
  for ( i = 0; i < this->outvars; i++ )
    fprintf( f, " %s", this->onames[i] );
  fprintf( f, "\n\n");

  ff = this->fnct;
  i = 0;
  while (ff != 0) {
    fprintf( f, ".names");
    for (j = 0; j < this->inpvars; j++)
        if (ff->iv[j] != '-') fprintf(f, " %s", this->inames[j]);
    fprintf( f, " term_%i\n", i++);
    for (j = 0; j < this->inpvars; j++)
        if (ff->iv[j] != '-') fprintf(f, "%c", ff->iv[j]);
    fprintf( f, " 1\n");
    ff = ff->next;
    if ( gauge.GaugeStep( i, 0 ) != 0 ) break;
  }
  fprintf( f, "\n");

  for (i = 0; i < this->outvars; i++) {
    fprintf( f, ".names");
    ff = this->fnct;
    j = 0;
    k = 0;
    while (ff != 0) {
        if (ff->ov[i] == '1') {
           fprintf(f, " term_%i", j);
           k++;
        }
        j++;
        ff = ff->next;
    }
    fprintf(f, " %s\n", this->onames[i]);
    for (j = 0; j < k; j++) {
        for (l = 0; l < k; l++)
            if (j != l) fprintf(f, "-");
            else fprintf(f, "1");
        fprintf(f, " 1\n");
    }
    if ( gauge.GaugeStep( this->terms + i, 0 ) != 0 ) break;
  }
  fprintf(f, ".end\n");

  fclose( f );
  gauge.CloseGauge();
}

void TBoolFnct::SaveFnctAsBLIF_POS( char * filn, TGauge gauge )
{
  FILE * f;
  int i, j, k, l;
  TPfnct * ff;
  char *compinp;

  compinp = new char[this->inpvars];

  gauge.NewGauge( "Saving functin as BLIF", this->terms + this->outvars, 1 );
  if ( filn != 0 ) f = fopen( filn, "wt" );
  else f = stdout;

  fprintf( f, ".model new\n\n");
  fprintf( f, ".inputs");
  for ( i = 0; i < this->inpvars; i++ )
    fprintf( f, " %s", this->inames[i] );
  fprintf( f, "\n");
  fprintf( f, ".outputs");
  for ( i = 0; i < this->outvars; i++ )
    fprintf( f, " %s", this->onames[i] );
  fprintf( f, "\n\n");

  ff = this->fnct;
  i = 0;
  while (ff != 0) {
    fprintf( f, ".names");
    k = 0;
    for (j = 0; j < this->inpvars; j++) {
        if (ff->iv[j] != '-') {
            fprintf(f, " %s", this->inames[j]);
            compinp[k++] = ff->iv[j];
        }
    }
    fprintf( f, " term_%i\n", i++);
    for (j = 0; j < k; j++) {
        for (l = 0; l < k; l++)
           if (j != l) fprintf(f, "-");
           else fprintf(f, "%c", ('1'-compinp[j])+'0');
        fprintf( f, " 1\n");
    }
    ff = ff->next;
    if ( gauge.GaugeStep( i, 0 ) != 0 ) break;
  }
  fprintf( f, "\n");

  for (i = 0; i < this->outvars; i++) {
    fprintf( f, ".names");
    ff = this->fnct;
    j = 0;
    k = 0;
    while (ff != 0) {
        if (ff->ov[i] == '1') {
           fprintf(f, " term_%i", j);
           k++;
        }
        j++;
        ff = ff->next;
    }
    fprintf(f, " %s\n", this->onames[i]);
    for (j = 0; j < k; j++)
        fprintf(f, "1");
    fprintf(f, " 1\n");
    if ( gauge.GaugeStep( this->terms + i, 0 ) != 0 ) break;
  }
  fprintf(f, ".end\n");

  fclose( f );
  delete[] compinp;
  gauge.CloseGauge();

}

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

void TBoolFnct::DuplNames()
{
  int i;
  char * * n;

  n = this->parent->inames;
  this->inames = new char * [this->inpvars];
  for ( i = 0; i < this->inpvars; i++ )
  {
    this->inames[i] = new char[strlen( n[i] ) + 1];
    strcpy( this->inames[i], n[i] );
  }
  n = this->parent->onames;
  this->onames = new char * [this->outvars];
  for ( i = 0; i < this->outvars; i++ )
  {
    this->onames[i] = new char[strlen( n[i] ) + 1];
    strcpy( this->onames[i], n[i] );
  }
}
//---------------------------------------------------------------------------
void TBoolFnct::DeleteInpVariable( int v )
{
  TPfnct * ff;
  int i;

  if ( this == 0 ) return;
  if ( v >= this->inpvars ) return;
  ff = this->fnct;
  while ( ff != 0 )
  {
    memcpy( ff->iv + v, ff->iv + v + 1, this->inpvars - v );
    ff->iv[this->inpvars - 1] = 0;
    ff = ff->next;
  }
  delete[] this->inames[v];
  for ( i = v; i < this->inpvars - 1; i++ )
    this->inames[i] = this->inames[i + 1];
  this->inpvars--;
}
//---------------------------------------------------------------------------
void TBoolFnct::DeleteOutVariable( int v )
{
  TPfnct * ff;
  int i;

  if ( this == 0 ) return;
  if ( v >= this->outvars ) return;
  ff = this->fnct;
  while ( ff != 0 )
  {
    memcpy( ff->ov + v, ff->ov + v + 1, this->outvars - v );
    ff->ov[this->outvars - 1] = 0;
    ff = ff->next;
  }
  delete[] this->onames[v];
  for ( i = v; i < this->outvars - 1; i++ )
    this->onames[i] = this->onames[i + 1];
  this->outvars--;
}
//---------------------------------------------------------------------------
void TBoolFnct::InsertTerm( int t )
{
  TPfnct * ff, * ff1;
  int i;

  if ( this == 0 ) return;

  ff = new TPfnct;
  ff->valid = 1;
  ff->cov = 0;
  ff->covfield = 0;
  ff->dim = 0;
  ff->prime = 0;
  ff->origin = 0;
  ff->iv = new char[this->inpvars + 1];
  setmem( ff->iv, this->inpvars, '-' );
  ff->iv[this->inpvars] = 0;
  ff->ov = new char[this->outvars + 1];
  setmem( ff->ov, this->outvars, '~' );
  ff->ov[this->outvars] = 0;
  if ( t == 0 )
  {
    ff->next = this->fnct;
    this->fnct = ff;
  }
  else
  {
    ff1 = this->fnct;
    i = 0;
    while ( ff1 != 0 && i != t - 1 )
    {
      ff1 = ff1->next;
      i++;
    }
    ff->next = ff1->next;
    ff1->next = ff;
  }
  this->terms++;
}
//---------------------------------------------------------------------------
void TBoolFnct::InsertInpVariable( int v )
{
  TPfnct * ff;
  int i;
  char * iv;
  char * * in;

  if ( this == 0 ) return;
  if ( v >= this->inpvars ) return;
  ff = this->fnct;
  while ( ff != 0 )
  {
    iv = new char[this->inpvars + 2];
    memcpy( iv, ff->iv, v );
    iv[v] = '-';
    memcpy( iv + v + 1, ff->iv + v, this->inpvars - v );
    iv[this->inpvars + 1] = 0;
    delete[] ff->iv;
    ff->iv = iv;
    ff = ff->next;
  }
  in = new char * [this->inpvars + 2];
  for ( i = 0; i < v; i++ )
    in[i] = this->inames[i];
  for ( i = v; i < this->inpvars; i++ )
    in[i + 1] = this->inames[i];
  in[v] = new char[255];
  strcpy( in[v], "new" );
  delete[] this->inames;
  this->inames = in;
  this->inpvars++;
}
//---------------------------------------------------------------------------
void TBoolFnct::InsertOutVariable( int v )
{
  TPfnct * ff;
  int i;
  char * ov;
  char * * on;

  if ( this == 0 ) return;
  if ( v >= this->outvars ) return;
  ff = this->fnct;
  while ( ff != 0 )
  {
    ov = new char[this->outvars + 2];
    memcpy( ov, ff->ov, v );
    ov[v] = '~';
    memcpy( ov + v + 1, ff->ov + v, this->outvars - v );
    ov[this->outvars + 1] = 0;
    delete[] ff->ov;
    ff->ov = ov;
    ff = ff->next;
  }
  on = new char * [this->outvars + 2];
  for ( i = 0; i < v; i++ )
    on[i] = this->onames[i];
  for ( i = v; i < this->outvars; i++ )
    on[i + 1] = this->onames[i];
  on[v] = new char[255];
  strcpy( on[v], "new" );
  delete[] this->onames;
  this->onames = on;
  this->outvars++;
}
//---------------------------------------------------------------------------
int TBoolFnct::CountFnctHamming( char * c )
{
  int d, h;
  TPfnct * ff;

  d = INT_MAX;
  ff = this->fnct;
  while ( ff != 0 && d > 0 )
  {
    h = CountHamming( ff->iv, c, this->inpvars );
    d = min( d, h );
    ff = ff->next;
  }
  return d;
}
//---------------------------------------------------------------------------
void TBoolFnct::GetOptVal( int crit ) // extracts optimization value
{
  switch ( crit )
  {
    case 0:
      this->optval = this->info.groupterms;
    break;
    case 1:
      this->optval = this->info.liters;
    break;
    case 2:
      this->optval = this->info.ON_terms;
    break;
    case 3:
      this->optval = this->info.liters + this->info.ON_terms;
    break;
    case 4:
      this->optval = this->info.gates;
    break;
    case 5:
      this->optval = this->info.GEs;
    break;
      /* case 6: info.inf.inpsum; break; case 7: inf.conesum; break; */
  }
}
//---------------------------------------------------------------------------
void TBoolFnct::Reindex()
{
  TPfnct * ff;
  int i;

  delete[] this->index;
  this->index = new TPfnct * [this->terms];
  ff = this->fnct;
  i = 0;
  while ( ff != 0 )
  {
    this->index[i] = ff;
    ff->index = i;
    ff = ff->next;
    i++;
  }
}
//---------------------------------------------------------------------------
TBoolFnct * TBoolFnct::DuplFnct() /* Creates a duplicate of function. */
{
  TBoolFnct * ofn;
  TPfnct * ff, * ff2;

  ofn = new TBoolFnct( this->inpvars, this->outvars, 0, this->type );
  ff = this->fnct;
  while ( ff != 0 )
  {
    ff2 = ofn->AddTermToEnd( ff->iv, ff->ov, ff->dim );
    ff2->cov = DuplCov( ff->cov );
    ff2->covlen = ff->covlen;
    if ( ff->covfield != 0 )
    {
      ff2->covfield = new int[ff->covlen];
      memcpy( ff2->covfield, ff->covfield, ff->covlen * sizeof( int ) );
    }
    ff = ff->next;
  }
  ofn->parent = this->parent;
  return ofn;
}
//---------------------------------------------------------------------------
void TBoolFnct::SubstOutDCs() /* Substitues output DCs with "0"s */
{
  int i;
  TPfnct * ff;

  ff = this->fnct;
  while ( ff != 0 )
  {
    for ( i = 0; i < this->outvars; i++ )
      if ( ff->ov[i] == '-' ) ff->ov[i] = '0';
    ff = ff->next;
  }
}
//---------------------------------------------------------------------------
char * TBoolFnct::IsPrime( TPfnct * ff, int IC_memory, int IC_type,  TermTree ** imp_test, TermTree ** offtree ) /* Checks if ff is a PI of any output function. srcf = parent function
returns 0 of not, or a pointer to field[ovr] filed[i] = '1' if it is a PI of i output part of ff must be valid */
{
  int i, j;
  char * ispi;
  int ipi;
  char tmp;
  int t;

  ispi = new char[this->outvars];
  setmem( ispi, this->outvars, '1' );
  ipi = 0;

  for ( i = 0; i < this->outvars; i++ )
    if ( ff->ov[i] == '1' )
    {
      for ( j = 0; j < this->inpvars; j++ )
        if ( ff->iv[j] != '-' )
        {
          tmp = ff->iv[j];
          ff->iv[j] = '-';
          t = ImplCheck( this, ff, i, IC_memory, IC_type, imp_test[i], offtree[i] );
          ff->iv[j] = tmp;
          if ( t )
          {
            ispi[j] = '0';
            break;
          }
        }
      if ( j == this->inpvars ) ipi = 1;
    }
  if ( !ipi )
  {
    delete[] ispi;
    ispi = 0;
  }
  return ispi;
}
//---------------------------------------------------------------------------
int TBoolFnct::AdvCountPrimes( int mask, int IC_memory, int IC_type,  TermTree ** imp_test, TermTree ** offtree ) /* counts PI in fn, for a given origin mask */
{
  int i;
  TPfnct * ff;
  char * p;

  i = 0;
  ff = this->fnct;
  while ( ff != 0 )
  {
    if ( ( ff->origin & mask ) == mask )
    {
      p = this->parent->IsPrime( ff, IC_memory, IC_type, imp_test, offtree );
      if ( p != 0 )
      {
        delete[] p;
        i++;
      }
    }
    ff = ff->next;
  }
  return i;
}
//---------------------------------------------------------------------------
void TBoolFnct::DeleteNames() /* Deletes names of the function */
{
  int i;
  if ( this->inames != 0 )
  {
    for ( i = 0; i < this->inpvars; i++ ) delete[] this->inames[i];
    delete[] this->inames;
  }
  if ( this->onames != 0 )
  {
    for ( i = 0; i < this->outvars; i++ ) delete[] this->onames[i];
    delete[] this->onames;
  }
  this->inames = 0;
  this->onames = 0;
}
//---------------------------------------------------------------------------
void TBoolFnct::DeleteSplit() /* Destroys function split info. */
{
  int i;
  TPfnct * fnct2;

  if ( !this->split ) return;

  for ( i = 0; i < this->outvars; i++ )
  {
    while ( this->onset[i] != 0 )
    {
      delete[] this->onset[i]->iv;
      fnct2 = this->onset[i]->next;
      delete this->onset[i];
      this->onset[i] = fnct2;
    }
    while ( this->offset[i] != 0 )
    {
      delete[] this->offset[i]->iv;
      fnct2 = this->offset[i]->next;
      delete this->offset[i];
      this->offset[i] = fnct2;
    }
    while ( this->dcset[i] != 0 )
    {
      delete[] this->dcset[i]->iv;
      fnct2 = this->dcset[i]->next;
      delete this->dcset[i];
      this->dcset[i] = fnct2;
    }
  }
  delete[] this->onset;
  delete[] this->offset;
  delete[] this->dcset;
  delete[] this->onterms;
  delete[] this->offterms;
  delete[] this->dcterms;
  this->split = 0;
}
//---------------------------------------------------------------------------
TBoolFnct * TBoolFnct::DumpOnset( TBoolFnct * e_buffer )
{
  TBoolFnct * ofn;
  TPfnct * aktterm;
  TPfnct * sf;
  int j;
  int ovr;

  ofn = this->CreateChildFnct();
  ofn->type = 0;

  for ( ovr = 0; ovr < this->outvars; ovr++ )
  {
    sf = this->onset[ovr];
    while ( sf != 0 )
    {
      aktterm = ofn->AddEmptyTermToEnd();
      aktterm->iv = new char[ofn->inpvars + 1];
      memcpy( aktterm->iv, sf->iv, this->inpvars );
      aktterm->iv[this->inpvars] = 0;
      aktterm->dim = sf->dim;
      aktterm->ov = new char[ofn->outvars + 1];
      aktterm->ov[ofn->outvars] = 0;
      aktterm->dvar = ovr;
      AddToHistory( e_buffer, aktterm );
      for ( j = 0; j < this->inpvars; j++ ) e_buffer->last->ov[j] = '0';
      e_buffer->last->ov[j] = 0;
      sf = sf->next;
    }
  }
  return ofn;
}
//------------------------------------------------------------------------------

void TBoolFnct::SwapOnOff()
{
    TPfnct *ff;
    int i;
    TPfnct * * tmp;
    int *tmp2;

    ff = this->fnct;

    while (ff != NULL) {
        for (i = 0; i < this->outvars; i++)
            if (ff->ov[i] == '0') ff->ov[i] = '1';
            else if (ff->ov[i] == '1') ff->ov[i] = '0';
        ff = ff->next;
    }
    if (this->split) {
        tmp = this->onset;
        this->onset = this->offset;
        this->offset = tmp;
        tmp2 = this->onterms;
        this->onterms = this->offterms;
        this->offterms = tmp2;
        this->maxonterms = 0;
        for (i = 0; i < this->outvars; i++)
            if (this->onterms[i] > this->maxonterms) this->maxonterms = this->onterms[i];
    }
    if (this->index != 0) this->Reindex();
}


