Program rieši problém generovania testov prostredníctvom Boolovskej diferencie

Delphi & Pascal (česká wiki)
Přejít na: navigace, hledání
Kategórie:

Program: Prac_ndf.cBooldif.zip
Soubor exe: Booldif.exe
Potřebné: Adresar.cColor.cDerivac.cError.cFunkcie.cHelp.cKey.cLine_edi.cMain.cMenu.cObsluha.cOkno.cPrac_ndf.cSlovnik.cSlov_fon.cStatist.cUtil.cVideo.cVystupy.cAdresar.hColor.hDefine.hError.hFunkcie.hGlob.hKey.hLine_edi.hMbooldif.hMenu.hOkno.hSlov_fon.hUtil.hVideo.h
Příklady: Example.zipBin_10_o.ndfBin_10_o.ndfBin_1and.ndfBin_2rad.ndfBin_3rad.ndfBin_4rad.ndfHard.ndfI_reg_lo.ndfReg_jk.ndfScitac_s.ndfScp_1rad.ndfScp_2rad.ndfScp_2r_1.ndfScp_3rad.ndfScp_4r_2.ndfScp_6r_3.ndfScp_8r_4.ndfSc_1r_pj.ndfSc_1r_sj.ndfSc_1_aoi.ndfSc_2r_4.ndfSc_3r_6.ndfSc_7400n.ndfSc_aon.ndfSimp3_a.ndfSimp3_b.ndfSimp4_a.ndfSimp4_b.ndfSimp4_c.ndfSimp6_a.ndfTest_vod.ndfZle.ndf
Manual: Prirucky.zip

Program rieši problém generovania testov prostredníctvom Boolovskej diferencie. Riešenie vyplýva z metódy matematicej derivácie logických zápisov funkcie v tvare Boolovského zápisu. Vytvára vektory porúch pre daný obvod, pričom zohľadňuje všetky vetviace sa vodiče. Výsledkom je úplný test.
Je implementovaný v programovacom jazyku C pre operačný systém MS-DOS, alebo iný s ním kompatibilným. Program je vhodný pre interaktívny spôsob komunikácie s užívateľom, čo umožňuje pohodlné pracovné prostredie podobné systémom Turbo Vision.

Ako príklad skúste nasledovné.
  • Menu->Voľby->Vstup->Zo Súboru. Vyberte si niektorý z ukážkových súborov.
  • Menu->Činnosť->Boolovské diferencie->Primárne vodiče
  • Menu->Činnosť->Boolovské diferencie->Vnútorné vodiče
  • Menu->Výsledky - môžete si pozrieť výsledky práce programu


POZNÁMKA: Zdrojové kódy ktoré simulujú prostredie Turbo Vision niesu dielom autora.
//************************************************************************//
// PRAC_NDF.C                                                             //
// Sluzi pre standartne operacie s Boolovskymi diferenciami, prevody      //
// nasobicky atd.                                                         //
//                                                                        //
// PS: Pocas toho ako som robil tuto DP (mimochodom druhu, raz som letel  //
// zo statnic) som sa rozisiel s priatelkou, dostal povolavaci rozkaz,    //
// zacal ako prvak na hutnickej a samozrejme vela inych o ktorych by som  //
// mohol napisat, preto ak lustis tieto zdrojaky pomysli na to a nenadavaj//
//                                               dakujem TRSEK 25.8.1997  //
//************************************************************************//
// Nieco v neporiadku napr. strcpy( vysl, "" ); dava do vysl="a" - hahaha //
 
#include <dos.h>
#include <dir.h>
#include "mbooldif.h"
#include "color.h"
#include "glob.h"
#include "okno.h"
#include "key.h"
#include "util.h"
#include "video.h"
#include "menu.h"
#include "error.h"
#include "glob.h"
#include "funkcie.h"
#define v_NDF h_fnc->pNDF[h_fnc->poc_NDF]
#define s_NDF subst_NDF->pNDF[subst_NDF->poc_NDF]
#define pSubst_NDF subst_NDF->pSubst[subst_NDF->poc_NDF]
 
//************************************************************************//
// Vyhrad miesto pre dalsie NDF                                           //
// i: premenna zapis_NDF o:chyba malo pamate                   25.8.1997  //
//************************************************************************//
 
int dalsie_NDF (zapis_NDF *h_fnc, int velkost )
{
int i;
 
 h_fnc->poc_NDF++;
 if ( h_fnc->poc_NDF > max_NDF ) return(12);
 
 if( velkost == 0 ) velkost = h_fnc->pv_NDF;      // taaake velke bude pole
 v_NDF = (char *) farmalloc(velkost + 1 );
 min_mem = min_mem + velkost + 8 ;
 pamet();                                         // ukaz ako si na tom z pametou
 if ( v_NDF == NULL ) return(11);
 for (i=0; i<velkost; i++) v_NDF[i] = nic;        // zapis je vyplneny prazdnymi polozkami
 v_NDF[i]='\0';					  // aby som nieco videl, lebo inac tam boli
						  // take bludy asi Borland Corp atd.
 h_fnc->adept[ h_fnc->poc_NDF ] =0;		  // aj adept na vyhodenie ma nulu
 h_fnc->t_vodic[ h_fnc->poc_NDF ] =0;		  // vzhladom na ktory t (a,b,c) zistujem chybu
 h_fnc->t_chyba[ h_fnc->poc_NDF ] =0;		  // chyba je 0 alebo 1
 
 return(0);
}
 
 
//************************************************************************//
// Prevedie do vnutorneho zapisu s ktorym potom pracujem		  //
// i:zapis_NDF o:chyba malo pamate                             25.8.1997  //
//************************************************************************//
 
int vytvor_formu(zapis_NDF *h_fnc,char vstr[])
{
int i=0,err=0;
 
// prax ma naucila v BC si clovek nieje nicim isty takze zicher je zicher
znuluj(h_fnc,1);
// zisti pocet premennych
for (i=0 ; i<=strlen(vstr) ; i++)
    {
     if ( je_znak( vstr[i], jclen ) == TRUE )	// pre male a..z
	if ( (vstr[i]-'a') >= h_fnc->pv_NDF ) h_fnc->pv_NDF=vstr[i]-'a'+1;
 
     if ( je_znak( vstr[i], nclen ) == TRUE )	// pre velke A..Z
	if ( (vstr[i]-224) >= h_fnc->pv_NDF ) h_fnc->pv_NDF=vstr[i]-224+1;
    }
 
 if ( strlen(vstr) == 0 ) return(0);		// aj to sa stava !?
 // vyhrad miesto pre zapis prveho
 if ( (err=dalsie_NDF(h_fnc,0)) == 1) return(err);
 
 // rozsekaj do vnutorneho zapisu
 i=0;
 while (i < strlen(vstr)) {
 
     // neake nasobenie 0 ma za nasledok zrusenie clena
     if ( vstr[i] == vstup_0[0] ) h_fnc->adept[ h_fnc->poc_NDF ]=1;
 
     if ( je_znak( vstr[i], jclen ) == TRUE ) {         // pre male a..z chyba kontrola na viacnasobny vyskyt jednoho prvku !!!
	 if (( v_NDF[ vstr[i] - 'a' ] == nclen ) && (h_fnc->adept[ h_fnc->poc_NDF ] == 0 ))
               h_fnc->adept[ h_fnc->poc_NDF ] =1;
	    else v_NDF [ vstr[i] - 'a' ] = jclen;
	}
      else {
	if ( je_znak( vstr[i], nclen ) == TRUE ) {      // pre velke A..Z chyba kontrola na viacnasobny vyskyt jednoho prvku !!!
	   if (( v_NDF[ vstr[i] - 224 ] == jclen ) && (h_fnc->adept[ h_fnc->poc_NDF ] == 0 ))
                 h_fnc->adept[ h_fnc->poc_NDF ] =1;
	      else v_NDF[ vstr[i] - 224 ] = nclen;
	   }
	 else
           if( je_znak( vstr[i], nic ) == FALSE )// vyhrad miesto pre zapis prveho
	       if ( (err=dalsie_NDF(h_fnc,0)) == 1) return(err);
	 }
 
     i++;
    }
 return(0);
}
 
 
//************************************************************************//
// Vyhodi vsetky NDF, ktore su adeptami na vyhodenie                      //
//                                                             25.8.1997  //
//************************************************************************//
 
void von_adept(zapis_NDF *h_fnc)
{
int x,y;      // devky
 
 // ak sa nachadza clen 0000000 teda nema ani jclen ani jeho negaciu
 // ale ak sa nachadza nic tak az take nic to nieje ( skus pre f=a )
 for (x=1; x<=h_fnc->poc_NDF; x++)
   // spravit z neho adepta ???
   if( ( h_fnc->adept[x] == 0 ) && ( h_fnc->pv_NDF > 0 ) ) {
       h_fnc->adept[x]=1;
       for (y=0; y<h_fnc->pv_NDF; y++)
           if(( h_fnc->pNDF[x][y] == jclen ) || ( h_fnc->pNDF[x][y] == nclen ))
              h_fnc->adept[x]=0;
      }
 
 for (x=h_fnc->poc_NDF; x>=0; x--)
     if (h_fnc->adept[x] == 1) {
	  strcpy( h_fnc->pNDF[x], v_NDF );
	  h_fnc->adept[x] = h_fnc->adept[ h_fnc->poc_NDF ];
	  h_fnc->adept[ h_fnc->poc_NDF ]=0;
	  farfree (v_NDF);
          v_NDF=NULL;
          pamet();
	  h_fnc->poc_NDF--;
	 }
}
 
 
//************************************************************************//
// Zistuje vsetky pohltenia, ktore sa nachadzaju                          //
// ak ich ma tak oznaci adept[i] na vyhodenie                  25.8.1997  //
//************************************************************************//
 
void pohltenie(zapis_NDF *h_fnc)
{
int i,x,y,adp_i,adp_y;
int n_clen_i,n_clen_y;		// su iba n-cleny ??
 
 for (i=1; i<=h_fnc->poc_NDF-1; i++)
     for (y=i+1; y<=h_fnc->poc_NDF; y++)
	 {
	 adp_i=0;adp_y=0;
         // ci nahodou nieje len zo ziadnych clenov vtedy pohlti akykolvek iny clen
	 n_clen_i=1;n_clen_y=1;
	 for (x=0; x<h_fnc->pv_NDF; x++)
	     {
	     if ( h_fnc->pNDF[i][x] != nic ) n_clen_i=0;
	     if ( h_fnc->pNDF[y][x] != nic ) n_clen_y=0;
	     // zatial pohlcuje
	     if (( h_fnc->pNDF[i] [x] == nic ) && ( h_fnc->pNDF[y] [x] != nic )) adp_y=adp_y | 1 ;
	     if (( h_fnc->pNDF[y] [x] == nic ) && ( h_fnc->pNDF[i] [x] != nic )) adp_i=adp_i | 1 ;
	     // toto uz nie ma rozdielne
	     if ( (( h_fnc->pNDF[i] [x] == nclen ) && ( h_fnc->pNDF[y] [x] == jclen )) ||
		  (( h_fnc->pNDF[y] [x] == nclen ) && ( h_fnc->pNDF[i] [x] == jclen )) )
		 {
		  adp_i=adp_i | 2 ;
		  adp_y=adp_y | 2 ;
		 }
	    }
	  // su navlas podobne
	  if ((n_clen_i == 0) && ( adp_i == 0 ) && ( adp_y == 0 ))
	      h_fnc->adept[i]=1;
	  // je cas vyhodnotit
	  if ((n_clen_i == 0) && ( adp_i == 1 ) && ( adp_y != 1 ))
	      h_fnc->adept[i]=1;
	  if ((n_clen_y == 0) && ( adp_y == 1 ) && ( adp_i != 1 ))
	      h_fnc->adept[y]=1;
	 }
}
 
 
//************************************************************************//
// Filter pre dalsie spracovanie vyrazu                                   //
//                                                             25.8.1997  //
//************************************************************************//
 
int filter( char vstr[] )
{
int i=0,err=0;
 
 while( i < strlen( vstr ) )
     if (vstr[i] == ' ') strdel(vstr,i);
                    else i++;
 
 for (i=0; i<strlen(vstr); i++) {
     if (vstr[i]== '(') err++;
     if (vstr[i]== ')') err--;
    }
 if ( err!=0 ) return(13);
 
 for (i=0; i<strlen(vstr); i++) {
     if( vstr[i] == '1' ) vstr[i] = vstup_1[0];
     if (!( ( je_znak( vstr[i], nic ) == TRUE ) || ( vstr[i] == '+' ) ||
            ( vstr[i] == '(' ) || ( vstr[i] == ')' ) ||
            ( vstr[i] == vstup_0[0] ) || ( vstr[i] == vstup_1[0]) ))
	     err=1;
     if (( vstr[i] == '(' ) && ( vstr[i+1] == '+' )) err=2;
     if (( vstr[i] == '+' ) && ( vstr[i+1] == ')' )) err=2;
    }
 
 if ( err==1 ) return(14);
 if ( err==2 ) return(15);
 
 return(0);
}
 
 
//************************************************************************//
// Ma vobec zatvorky ???                                                  //
// o: 1-ak ma zatvorky                                          2.9.1997  //
//************************************************************************//
 
int ma_zatv ( char vstr[] )
{
int i;
  for (i=0; i<=strlen(vstr); i++)
      if ( vstr[i] == '(' ) return(1);
  return(0);
}
 
 
//************************************************************************//
// Odstrani zatvorky                                                      //
//                                                     27.8.1997 (2.9.97) //
//************************************************************************//
 
int odstran_zatvorky( char vstr[], int alge )
{
int i,ii;
int b_nec,lava;                 // b_nec je to nasobenec ?? lava udava pocet lavych zatvoriek
char nasobitel[ max_ret ];	        // obsah 1 zatvorky
char nasobenec[ max_ret ];	        // obsah 2 zatvorky s cim idem nasobit
char vysl[ max_ret ];		        // vysledny produkt
 
 if ( ma_zatv(vstr) != 1 ) return (0);
 pamet();
 
 do {				// budeme opakovat pokial ziadna zatvorka
  if ( vstr[0] == '(' )		// taka lahodka, teraz mozme zacat
     {				// ta co je posledna je jeho ??? aby to nebolo (a+c)(d+a)
      lava=1;i=1;
      while (( lava>0 ) && ( i < strlen( vstr ) )) {
	    if ( vstr[i] == '(' ) lava++;
	    if ( vstr[i] == ')' ) lava--;
	    i++;
	   }
      if ( i == strlen( vstr )) {
	  strdel( vstr, 0 );
	  strdel( vstr, strlen(vstr)-1 );
	 }
     }
 
   nasobitel[0]='\0';nasobenec[0]='\0';vysl[0]='\0';
   lava=0;b_nec=0;
 
   for (i=0; i<=strlen(vstr); i++)
       {
	if ( vstr[i] == '(') {
	   lava++;       			// odteraz kopirujem do nasobitel
	   if ( nasobitel[0] == '+') {
	      strchar( vysl, '+' );strdel( nasobitel, 0 );
	      }
	   if (( lava == 1 ) && ( strlen(nasobitel) > 0 )) b_nec=1;
	   }
 
	if (( lava == 0 ) && ( b_nec == 1 ) && (( vstr[i] == '+' ) ||
            ( i == strlen( vstr ) )))
	   {
	    odstran_zatvorky( nasobitel, 1 );	// zavola rekurzivne, co ak nieco obsahuje ???
	    odstran_zatvorky( nasobenec, 1 );	// zavola rekurzivne, co ak nieco obsahuje ???
 
            if (( vysl[ strlen( vysl )-1 ] == '+' ) &&
                (( vstr[i] == '+' ) || ( vstr[i] == '\0' )) ||
                (( strlen( nasobenec ) == 0 ) && ( strlen( nasobitel ) == 0 ) ))
                {// kedy nedavat zatvorky, alebo je to zbytocne !!!
                 strcat( vysl, nasob_NDF( nasobitel, nasobenec, alge ) );
                }
               else {
	         strchar( vysl, '(' );
                 strcat( vysl, nasob_NDF( nasobitel, nasobenec, alge ) );
 	         strchar( vysl, ')' );
                }
 
	    nasobitel[0]='\0';nasobenec[0]='\0';
	    b_nec=0;
	   } // end if(lava==0
					       // je to OK daj do vysledku
       if ((( vstr[i] == '+' ) && ( lava == 0 ) && ( b_nec == 0 )) ||
	    ( i == strlen( vstr )))
	  {
	   odstran_zatvorky( nasobitel, 1 );     // zavola rekurzivne
	   for (ii=0; ii<strlen(nasobitel); ii++)
	       strchar( vysl, nasobitel[ii] );
	   nasobitel[0]='\0';
	  }
 
	if ( b_nec == 0 ) strchar( nasobitel, vstr[i] );  // kopiruje do nasobitel pre pripad nasobenia
		     else strchar( nasobenec, vstr[i] );  // do nasobenec to uz je iste nasobenie
 
						// hura idem roznasobovat
	if ( vstr[i] == ')' ) {
	   lava--;
	   if (( lava == 0 ) && ( b_nec == 1 ))
	     {
	      odstran_zatvorky( nasobitel, 1 );	// zavola rekurzivne, co ak nieco obsahuje ???
	      odstran_zatvorky( nasobenec, 1 );	// zavola rekurzivne, co ak nieco obsahuje ???
 
              if (( vysl[ strlen( vysl )-1 ] == '+' ) &&
                  (( vstr[i] == '+' ) || ( vstr[i] == '\0' )) ||
                  (( strlen( nasobenec ) == 0 ) && ( strlen( nasobitel ) == 0 ) ))
                  {// kedy nedavat zatvorky, alebo je to zbytocne !!!
	           strcat( vysl, nasob_NDF( nasobitel, nasobenec, alge ));
                  }
                 else {
	           strchar( vysl, '(' );
	           strcat( vysl, nasob_NDF( nasobitel, nasobenec, alge ));
	           strchar( vysl, ')' );
                  }
 
	      nasobitel[0]='\0';nasobenec[0]='\0';
	      b_nec=0;
	     } // end if(lava==1
					// odteraz kopirujem do nasobitel
					// ked vydim to vstr[i+1] ako keby mi zuby trhalo
	   if (( lava == 0 ) &&
               (( vstr[i+1] != '+' ) || ( strlen( vstr ) <= i+1 ))) b_nec=1;
	  }   // end if(vstr[i]==')'
 
     }   // end for(i=0;
 
   // to von blbosti odstranuje cleny ako aA atd, proste blbosti
   strcpy( vstr, vysl );			// toto je spravny vysledok
   vysl[0]='\0';
  } while ( ma_zatv( vstr ) == 1 );
 
 if( alge == 1 ) strcpy( vstr, von_blbosti( vstr ) );
 return( 0 );
}
 
 
//************************************************************************//
// Roznasobi dva cleny (zatvorky) v NDF strukture                         //
// pozor rusi obsah prveho z nich                               2.9.1997  //
//************************************************************************//
 
char *nasob_NDF( char nc[], char nt[], int alge )
{
char vysln[max_ret];
char pom_v[max_ret];            // pomocna
int pc=0,pt=0;			// pokial roznasobil nc, nt
int ic=0,it=0;			// devky premenne
				// z toho ma tiez boli brucho
 if ( strlen(nc) == 0 ) return(nt);
 if ( strlen(nt) == 0 ) return(nc);
 pom_v[0]='\0';
 vysln[0]='\0';         	// obcas hadzalo vysledky az strach
 				// clovek aby stale na nieco myslel
 
 while ( pc <= strlen(nc) ) {
  pt=0;
  while ( pt <= strlen(nt) ) {
 
    ic=0;
    while (( nc[ pc+ic ] != '+' ) && ( (pc+ic)< strlen(nc))) {
       strchar( pom_v, nc[pc+ic] );
       ic++;
       }
 
    while (( nt[ pt+it ] != '+' ) && ( (pt+it)< strlen(nt))) {
       strchar( pom_v, nt[pt+it] );
       it++;
       }
    pt=pt+it+1;it=0;
 
    if( alge == 1 ) {
      von_blbosti( pom_v );
      if( !(( strlen( pom_v ) == 1 ) && ( pom_v[0] == '0') ))
       {// toto treba co najskor odstranit dava nekorektne vysledky
        if( ( strlen( vysln ) + strlen( pom_v )) < ( max_ret-10 ) ) {
            strcat( vysln, pom_v );
            strchar( vysln,'+');
           }
       }
      }
    pom_v[0]='\0';
 
  }  // end while (pt< strlen(nt)
  pc=pc+ic+1;ic=0;
 }   // end while (pc< strlen(nc)
 
 if( alge == 1 ) von_blbosti( vysln );
 if( strlen( vysln ) == 0 ) strchar( vysln, '0' );
 return ( vysln );
}
 
 
//************************************************************************//
// Prevedie retazec do NDF struktury rozne poupravuje pospekuluje         //
// este ze funguje, vyp_sk ak chcem vnutit iny text             2.9.1997  //
//************************************************************************//
 
void ret_do_NDF(char skus[], zapis_NDF *fnc, char subor[])
{
int err;
FILE *tmp,*fopen();
 
 // da prec medzery a ine nepotrebne + kontrola zapisu operacia =2
 if ( (err=filter(skus)) != 0 )
    {
     chybove_okno(chyba[err] );
     return;
    }
 
 // odstrani zatvorky operacia =3
 if ( (err=odstran_zatvorky(skus,1)) != 0 )
    {
     chybove_okno(chyba[err]);
     return;
    }
 
 // vytvori standart NDF s ktorym budem make-ovat operacia =1
 if ( (err=vytvor_formu(fnc,skus)) !=0 )
    {
     chybove_okno(chyba[err]);
     return;
    }
 
 tmp=fopen( strspoj( temp,subor) ,"wt" );
 if ( tmp==NULL ) {
    chybove_okno( chyba[17] );
    return;
    }
 fprintf( tmp,"\n\r f= %s",ret_f );
 fclose(tmp);
 
 von_adept( fnc );			 // vyhodi adeptov na vyhodenie
 uloz_NDF ( fnc , "\n Po odstr nenĄ z tvoriek\n f= ",subor);
 
 pohltenie( fnc );			 // vyhodi cleny, ktore sa pohlcuju
 uloz_NDF ( fnc , "\n Odstr nen‚ ‡leny, ktor‚ sŁ pohlten‚ (Ź zna‡Ą pohlten‚ ‡leny)\n f= ",subor);
 
 von_adept( fnc );			 // vyhodi adeptov na vyhodenie
 uloz_NDF ( fnc , "\n V˜sledn  funkcia pou‘Ąvan  pre ƒal¨iu pr cu\n f= ",subor);
}
 
 
//************************************************************************//
// Boolovska diferencia podla premennych                                  //
// i:upravena funkcia o:diferencie podla premennych            30.9.1997  //
//************************************************************************//
 
int diferencie( int medzi_v )
{
int i,x,y;			      // devky
int zx,zy;
int prem;                             // aka substituovana premenna sa zhoduje
int a_rezim=0;			      // opustit rezim a prejst do automatickeho ???
int p_chyb=0,p_pokusov=0;	      // pocet chyb, pocet pokusov
char subst[max_ret];		      // ake cleny som substioval
char pom[max_ret];		      // pomocna
char ret_f2[ max_ret ];               // musim zalohovat retazec
zapis_NDF pom_f;                      // pomocna f(NDF)
 
 if ( strcmp(ret_f,"") == 0 ) {
   chybove_okno( chyba[10] );
   return(0);
   }
 
 zx=_stlpcov/2-23;
 zy=_riadkov/2-3;
 if( view_okno(zx,zy,zx+46,zy+5,atributy[20],atributy[21],2,"")==FALSE) {
   chybove_okno( chyba[1] );
   return(0);
   }
 
 p_stat=0; min_mem=0;                           // znulujeme
 zarad_stat( "Prevod do NDF tvaru",0 );         // dame do statistickych udajov
 
 tlac_retazec(zx+1,zy+2,atributy[20],"    Vykon vam deriv cie podŒa premenn˜ch ");
 del_tmp( TmpSubor[2] );			// kto maze ten ide
 del_tmp( TmpSubor[3] );			// ak spustim znova aby neboli duplicitne vysledky
 
 znuluj( &subst_NDF,0 );                        // nech tam niesu haus-numera
 znuluj( &pom_f,0 );                            // nech tam niesu haus-numera
 znuluj( &slovnik,1 );                          // slovnik znulovany
 init_jadro();					// zicher je zicher
 del_tmp( TmpSubor[1] );                        // ak spustim dvkrat, aby kvakrat nebolo zapisane
 
 filter( ret_f );
 subst[0]='\0';
 strcpy( ret_f2, ret_f );			// odzalohujem, lebo nahrad_vetvy
 ret_do_NDF( ret_f2, &h_fnc, TmpSubor[0]);	// retazec do NDF
 zarad_stat( "",1 );
 zac_subst = h_fnc.pv_NDF + 1;                  // od tejto prem zacinaju substitucie
                                                // toto nech je predtym ako ulozi slovnik vzdy !!!
 slovnik.pv_NDF = h_fnc.pv_NDF + 1;		// bude mat tolko premennych ako h_fnc +
						// vystup zapisujem ako dalsiu potrebuje zapis_slovnik
 uloz_NDF( &h_fnc, " Vstupn  funkcia\n f= ",TmpSubor[1]);// zobrazi NDF strukturu
 index[0]=' ';index[1]=' ';
                                                // derivacia podla vstupnych premennych
 // derivacie bez vnutornych vstupov ???
 if( medzi_v ) a_rezim=27;
 
 for ( i=0; i<h_fnc.pv_NDF; i++ ) {             // spravi komplet diferenciu podla i
     index[0] = 'a'+i; index[1] = ' ';
     difer_podla( &h_fnc, i, subst, &p_chyb, &p_pokusov, &a_rezim );
    }
 
 // derivacie bez vnutornych vstupov ???
 if( medzi_v ) a_rezim=27;
          else a_rezim=0;
 tlac_retazec(zx+1,zy+2,atributy[20]," Deriv cie pre vetviace sa prim rne vstupy");
 
 // aby vypisal, ze substioval, lebo testuje ci ret je vecsi ako 1 znak
 dalsie_NDF( &subst_NDF, 1 );
 subst_NDF.pv_NDF=1;
 strcpy( pom, ret_f );
 filter(pom);
 
 for( x=0; x<h_fnc.pv_NDF; x++ )
    // zistim ci ma viac ako jeden vstup (ci sa vobec vetvy)
    if( kolko_vetiev( pom, x ) > 1 ) {
        prem=0;
        for( y=0; y< strlen( pom ); y++ )
           if(( pom[y] == 'a' + x ) || ( pom[y] == 224 + x ))
             { // vetvy od primarneho vstupu
              prem++;
              subst_NDF.t_chyba[ subst_NDF.poc_NDF ] = prem;
              subst_NDF.adept[ subst_NDF.poc_NDF ] = 'a' + x;
              index[0]='a' + x;
              index[1]='0' + subst_NDF.t_chyba[ subst_NDF.poc_NDF ];
              // bude mat nazov ako nasledujuci dalsi
              pom[y] = 'a'+zac_subst -1;
              subst_NDF.pNDF[subst_NDF.poc_NDF ][0] = 'a' + x;
              // to co som substioval
              // az sa pokusis pouzit ret_f2 dobre si to rozmysli !!!
              strcpy( ret_f2, ret_f );
              for( i=strlen(ret_f)+1; i>y+1; i-- ) ret_f[i]=ret_f[i-1];
              ret_f[y+1]='0'+prem;
              // sprav NDF
              ret_do_NDF( pom, &pom_f, TmpSubor[0] );
              // vsetky okrem mojej
              difer_podla( &pom_f, zac_subst-1, subst_NDF.pNDF[subst_NDF.poc_NDF ],
                           &p_chyb, &p_pokusov, &a_rezim );
              // spat ako bolo
              strcpy( ret_f, ret_f2 );
              strcpy( pom, ret_f2 );
             }
      }
 // poriadok v pamati
 znuluj( &pom_f, 1 );
 a_rezim=0;
 
 
 if( medzi_v ) {     // derivacie aj pre vnutorne vstupy ???
 tlac_retazec(zx+1,zy+2,atributy[20],"  Vykon vam deriv cie pre vnŁtorn‚ vodi‡e ");
 
 // teraz hladame pre vnutorne vodice
 strcpy( ret_f2, ret_f );			// obnovy tak ako bol vstup
 znuluj( &subst_NDF, 1 );                       // poriadok robi kamaratov s pamatou
 while ( nahrad_vetvy( ret_f2, subst, &subst_NDF ) > 0 ) ;
 index[0]=' ';index[1]=' ';                     // znuluj index
 
 for( i = 1; i < subst_NDF.poc_NDF; i++ ) {
     // to co tu mam zhoduje sa z niecim ???
     prem = kontr_subst( subst_NDF.pNDF[i], i+1, subst_NDF.poc_NDF );
     // nasiel som vetviaci sa vodic !!!
     if( prem != 0 ) {
       // znamena to, ze nasiel medzivoce
       medzi_v=0;
       // pre tento som nerobil diferenciu
       if( subst_NDF.t_chyba[i] == 0 ) {
           subst_NDF.t_chyba[i] = 1;    // dostane oznacenie 1
           // ma taky index napr. e1, e2
           index[0]= subst_NDF.adept[i];
           index[1]='0' + subst_NDF.t_chyba[i];
           // retazec, ktory vznikol po substitucii do NDF
           strcpy( pom, subst_NDF.pSubst[i] );
           // vsetky okrem mojej
           substitucie( pom, subst_NDF.adept[i] );
           // nech vypisuje co substioval
           strcpy( ret_f2, ret_f );
           strcpy( ret_f, pom );
           ret_do_NDF( pom, &h_fnc, TmpSubor[0] );
           // spravi komplet diferenciu podla substituovaneho
           strcpy( pom, subst_NDF.pNDF[i] );
           difer_podla( &h_fnc, subst_NDF.adept[i] - 'a', pom, &p_chyb, &p_pokusov, &a_rezim );
           strcpy( ret_f, ret_f2 );
          }
 
       // dostane oznacenie +1
       subst_NDF.t_chyba[ prem - zac_subst +1 ] = subst_NDF.t_chyba[i]+1;
       // ma taky index napr. e1, e2
       index[1]='0'+subst_NDF.t_chyba[ prem - zac_subst +1 ];
       // retazec, ktory vznikol po substitucii do NDF
       strcpy( pom, subst_NDF.pSubst[ prem - zac_subst +1 ] );
       // vsetky okrem mojej
       substitucie( pom, subst_NDF.adept[ prem - zac_subst +1 ] );
       // aby spravne zobrazoval potom !!!
       for( y=0; y < strlen(pom); y++ )
          if( pom[y] == subst_NDF.adept[ prem - zac_subst +1 ] )
              pom[y] = subst_NDF.adept[i];
       // dostane meno ako ta s ktorou sa podoba
       subst_NDF.adept[ prem - zac_subst +1 ] = subst_NDF.adept[i];
 
       // nech vypisuje co substioval
       strcpy( ret_f2, ret_f );
       strcpy( ret_f, pom );
 
       ret_do_NDF( pom, &h_fnc, TmpSubor[0] );
       // spravi komplet diferenciu podla substituovaneho
       strcpy( pom, subst_NDF.pNDF[ prem - zac_subst +1 ] );
       difer_podla( &h_fnc, subst_NDF.adept[ i ] - 'a', pom,
                    &p_chyb, &p_pokusov, &a_rezim );
       strcpy( ret_f, ret_f2 );
      } // end if( prem != 0 )
   }
 }      // end if( medzi_v
 
 zatvor_okno();
 // ziadne vnutorne vodice niesu
 if( medzi_v ) hlasky( chyba[27] );
 
 // znuluj( &subst_NDF,1 );
 if ( Rezim == PREV ) result_skusania( p_chyb, p_pokusov );
 index[0]=' ';index[1]=' ';
 if( medzi_v == 0 ) hlasky(chyba[23]);
 return( 0 );
}
 
 
//************************************************************************//
// DIFER_PODLA vykona boolovske diferencie podla premennej                //
//                                                             2.11.1997  //
//************************************************************************//
 
int difer_podla( zapis_NDF *hp_fnc, int podla_p, char subst[], int *p_chyb, int *p_pokusov, int *a_rezim )
// hp_fnc - funkcia, podla_p - podla akej premennej, subst - aky retazec substiujem
// p_chyb p_pokusov - pocet chyb pokusov, a_rezim - automaticky rezim pri demo ???
{
zapis_NDF K0,K1,K;		    // pre potreby derivacie dF/dA
char pom_f[max_ret];                // pre pracu s derivaciami
char pom[256];                      // devka
 
 // pre potreby derivacie dF/dA
 znuluj(&K0,0); znuluj(&K1,0); znuluj(&K,0);
 // dame do statistickych udajov
 if( strlen( subst ) == 0 ) sprintf( pom,"dF/d%s", index );
                       else sprintf( pom,"dF/d%s subst(%s)", index, subst );
 zarad_stat( pom,0 );
 
 sprintf(pom," F = %s\n F(ndf) = ", ret_f );
 // zobrazi NDF strukturu
 uloz_NDF( hp_fnc, pom, TmpSubor[3]);
 
 filter( subst );
 
 if ( derivac_dF( hp_fnc, podla_p, &K, &K0, &K1) == FALSE )
    {
     znuluj(&K0,1); znuluj(&K1,1); znuluj(&K,1);
     // uz nemam cas to inac spravit !!!
     // vypise pre aku premennu nemoze sparvit derivaciu
     chyba[28][0][14]=index[0];
     if ( index[1] != ' ' ) // toto je vetviaci sa vodic
         chyba[28][0][15]=index[1];
     chybove_okno( chyba[28] );		// priprav cleny
     del_tmp(TmpSubor[3]);
     return(1);
    }
 
 strcpy( pom_f, zderivuj_dF( &K, &K0, &K1) );		// vyrob so zatvorkami
 substitucie( pom_f, ' ' );                             // substitucie spat na normalne cleny
 
 // taky akoze test, ci nahodov neodpoveda vzdy 0, alebo I
 jed_odpoved( pom_f );
 // zlom !!! tento riadok je magicky uz sa mi o nom sniva
 ret_do_NDF( pom_f, &deriv_f, TmpSubor[0] );		// uprav do prijatelneho tvaru
 uloz_NDF( &deriv_f, "\n dF = ",TmpSubor[3]);
 
 // ulozi slovnik poruch pre t0( prem), alebo t1 neg( prem )
 uloz_slovnik( pom_f, podla_p, &h_fnc, TmpSubor[3], subst );
 
 // dame do statistickych udajov
 zarad_stat( "",1 );
 
 // je  Preverovaci rezim tak zobrazuj
 if ( (( Rezim == VYUK ) || ( Rezim == PREV )) && ( *a_rezim != ESC ) ) {
    zobraz_tmp5();
    (*p_pokusov)++;					// dalsi pokus
    *a_rezim=prever_uziv( &deriv_f, p_chyb );		// over jeho vedomosti
    zatvor_okno();
   }
 
 if ( ( Rezim == DEMO ) && ( *a_rezim != ESC ) ) {	// ak je DEMO tak zobrazuj
    // po zobrazeni zmaze !!!
    *a_rezim=zobraz_tmp4();
   }
 
 // podla coho derivujem ???
 if( strlen( subst ) == 0 ) sprintf( pom,"\n dF/d%s  = ", index );
                       else sprintf( pom,"\n subst(%s) = %s\n dF/d%s = ", subst, index, index );
 
 // zobrazi NDF strukturu do NDF.TMP
 uloz_NDF( &deriv_f, pom,TmpSubor[1]);
 
 // ulozi do vystupneho suboru
 if ( Vystup == TLC ) {                 // ak tlaciaren
     anti_ascii( TmpSubor[3] , TmpSubor[5] );
     sprintf( pom_f,"type %s%s > prn", temp, TmpSubor[5] );
     system( pom_f );
    }
 
 if ( Vystup == SUB ) {                 // ak ukladat do suboru
     anti_ascii( TmpSubor[3], TmpSubor[5] );
     sprintf( pom_f,"if exist %s%s type %s%s >> %s", temp, TmpSubor[5], temp, TmpSubor[5], TmpSubor[4] );
     system( pom_f );
    }
 
 // ak spustim znova aby neboli duplicitne vysledky
 del_tmp( TmpSubor[3] );
 del_tmp( TmpSubor[2] );
 
 // vycistime pamat
 znuluj(&K0,1); znuluj(&K1,1); znuluj(&K,1);
 // aj toto je na stabilitu, lebo ked je cista pamat aj hlava je cista
 return(0);
}
 
 
//************************************************************************//
// KONTR_SUBST kontrola ci retazec subst sa nachadza v subst_NDF          //
// i:... o: 0-nenasiel som !=0 ako sa vola subst. premenna    30.10.1997  //
// toto este prepracovat !!!
//************************************************************************//
int kontr_subst( char subst[], int odkial, int pokial )
{
int x,y,i;			// devky
int prem=0;                     // toto je premenna, ktora ma dvojca
zapis_NDF NDF1,NDF2;            // nahadzem do NDF1, NDF2 porovnam
char ret_NDF1[ max_ret ], ret_NDF2[ max_ret ];
 
 znuluj( &NDF1, 0 );
 znuluj( &NDF2, 0 );
 strcpy( ret_NDF1, subst );
 ret_do_NDF( ret_NDF1, &NDF1, TmpSubor[5] ); // s tymto porovnavam
 
 for( i=odkial; i <= pokial; i++ )
    {
     for( x=0; x < NDF1.poc_NDF; x++ ) NDF1.t_vodic[x] = 0;
     strcpy( ret_NDF2, subst_NDF.pNDF[i] );
     ret_do_NDF( ret_NDF2, &NDF2, TmpSubor[5] );
 
     // maju aspon rovnaky pocet NDF ?
     if(( NDF1.pv_NDF == NDF2.pv_NDF ) && ( NDF1.poc_NDF == NDF2.poc_NDF ))
       { // grupak, kazdy s kazdym
         for( x=1; x <= NDF1.poc_NDF; x++ )
            for( y=1; y <= NDF2.poc_NDF; y++ )
               if(( strcmp( NDF1.pNDF[x], NDF2.pNDF[y] ) == 0 ) &&
                  ( NDF1.t_vodic[x] == 0 ) && ( NDF2.t_vodic[y] == 0 ))
                  {// sedi rovnaju sa, a este som ich nezlucil
                   NDF1.t_vodic[x] = 1;
                   NDF2.t_vodic[y] = 1;
                  }
 
         // tak je to ona, alebo nie ???
         prem = subst_NDF.adept[i] - 'a' +1 ;
         for( x=1; x <= NDF1.poc_NDF; x++ )
            if( NDF1.t_vodic[x] == 0 ) prem=0;     // nie je to ono
       } // end if(( NDF1.pv_NDF == NDF2.pv_NDF ...
      znuluj( &NDF2, 1 );
      // nasiel som ideme prec
      if( prem != 0 ) {
        znuluj( &NDF1, 1 );
        return( prem );
       }
    } // end for( i=0; i < subst_NDF.poc_NDF; i++ )
 
 // nenasiel som
 znuluj( &NDF1, 1 );
 return(0);
}
 
//************************************************************************//
// Zisti ako by sa mala spravat funkcia ak je vsetko OK                   //
// i:vektor(00I0II) o:vstup_0 "0" vstup_1 "1"                 25.10.1997  //
//************************************************************************//
 
char odpoved_f( char v_vektor[], zapis_NDF *h_fnc )
{
int x,y;		// len tak
char j_ndf,c_ndf=0;	// hodnota jednoho ndf, celej f-cie
 
 for( y=1; y<= h_fnc->poc_NDF; y++ )
    {
     j_ndf=1;
     for( x=0; x< h_fnc->pv_NDF; x++ )
	{
	 if (( h_fnc->pNDF[y][x] == jclen ) &&
	     ( v_vektor[x] == vstup_0[0] )) j_ndf=0;
	 if (( h_fnc->pNDF[y][x] == nclen ) &&
	     ( v_vektor[x] == vstup_1[0] )) j_ndf=0;
	}
     c_ndf=c_ndf+j_ndf;
    }
 
 if ( c_ndf != 0 ) return( vstup_1[0] );
	      else return( vstup_0[0] );
}
 
//************************************************************************//
// NAHRAD_VETVY hlada podobne a nahrdzuje ich inym                        //
// napr. abc+d(abc+de)= f+d(f+de)                                         //
// i:z akeho ret, co som substioval, slovnik substucii                    //
// o:ake ma cislo novo vytvoreny vodic                        30.10.1997  //
//************************************************************************//
 
int nahrad_vetvy( char ret_f[], char subst[], zapis_NDF *subst_NDF )
{
int i,y,err;			        // devky
int lav_z=0,prav_z=0;                   // lava, prava zatvorka pre subst a+b
int ma_subst=0;				// mam uz nejake subst
char vysl[ max_ret ];                   // vysledok
 
 subst[0]='\0';    			// znulujeme
 vysl[0]='\0';
 
 for( i=0; i <= strlen(ret_f); i++ )
    {
     // koncim kopirovanie
     if( ( je_znak( ret_f[i], nic ) == FALSE ) && ( strlen( subst ) > 1 ) &&
         ( ma_subst == 0 ) ) {
         filter( subst );                        // odfiltruj medzery, zatvorky
         if ( (err = dalsie_NDF( subst_NDF, strlen( subst ) ) ) != 0) {
             chybove_okno(chyba[err] );
             return(0);
            }
 
         for( y=0; y < strlen( subst ); y++ ) s_NDF[y] = subst[y];
         // takto sa bude volat nova premenna
         subst_NDF->adept[ subst_NDF->poc_NDF ] = 'a' + zac_subst + subst_NDF->poc_NDF - 2 ;
         // takto to uz dalej nepojde mam malo pismen abecedy na vetvenia
         if( subst_NDF->adept[ subst_NDF->poc_NDF ] >= 'z' )
             {
              chybove_okno(chyba[26] );
              return(0);
             }
	 // vyrobil som novu premennu
	 strchar( vysl, 'a' + zac_subst + subst_NDF->poc_NDF - 2 );
	 subst[0]='\0';                          // bratku nazavadzaj, my uz mame ine zaujmy
         ma_subst=1;                             // uz je to tady !!!
        }
 
     // kopirujem kam treba
     if( je_znak( ret_f[i], nic ) == FALSE ) {
	 strcat ( vysl, subst );
	 strchar( vysl, ret_f[i] );
	 subst[0]='\0';
	}
       else strchar( subst, ret_f[i] );
 
     // nasiel som clen ohraniceny len zatvorkami
     if(( vysl[ strlen(vysl) -3 ] == '(' ) && ( vysl[ strlen(vysl) -1 ] == ')' )) {
	  vysl[ strlen(vysl) -3 ]=' ';	// zatvorky nebudu bratu, (x) je zbytocne
	  vysl[ strlen(vysl) -1 ]=' ';
          filter(vysl);
         }
    }
 
 subst[0]='\0';                         // znulujeme odlozene v subst_NDF
 if( ma_subst )
   {
    strchar( subst, 'a' + zac_subst + subst_NDF->poc_NDF - 2 );
    strcpy( ret_f, vysl );              // tuto je vysledok mojho snazenia
 
    pSubst_NDF = (char *) farmalloc( strlen( vysl ) + 1 );// sprav mu miesto
    min_mem = min_mem + strlen( vysl ) + 8;
    pamet();                            // ukaz ako si na tom z pametou
    if ( pSubst_NDF == NULL ) {         // malo pamete
        chybove_okno(chyba[err] );
        return(0);
       }
    for( y=0; y <= strlen( vysl ); y++ ) pSubst_NDF[y] = vysl[y];
    return( zac_subst + subst_NDF->poc_NDF - 1 ); // poslem aku premennu som vyrobil
   }                                             // pozor ak tu return nebude radikalne meni pointu
 
  //***********************************************************************//
  // teraz taka lahodka premenne budu typu "or" subst (a+b+c) = d          //
  //***********************************************************************//
 
  if( ma_zatv( ret_f ) == 1 ) {
      // hladam najpravejsiu zatvorku
      for( lav_z=strlen( ret_f ); lav_z>0; lav_z-- )
         if( ret_f[lav_z] == ')' ) prav_z=lav_z;
      // k nej lavu zatvorku
      lav_z = prav_z;
      while(( lav_z>0 ) && ( ret_f[lav_z] != '(' )) lav_z--;
 
      subst[0]='\0'; vysl[0]='\0';
      // po lavu zatvorku do vysl
      for( i = 0; i < lav_z; i++ ) strchar( vysl, ret_f[i] );
      // od lavej do pravej do subst
      for( i = lav_z +1 ; i < prav_z; i++ )
           strchar( subst, ret_f[i] );
      strchar( vysl, 'a' + zac_subst + subst_NDF->poc_NDF -1 );	 // vyrobil som novu premennu
      // od pravej do vysl
      for( i = prav_z +1; i < strlen( ret_f ); i++ )
           strchar( vysl, ret_f[i] );
 
      filter( subst );
 
      if ( dalsie_NDF( subst_NDF, strlen( subst ) ) == 1) return(0);
 
      // tak ten clen tam hodim
      for( y=0; y <= strlen( subst ); y++ ) s_NDF[y] = subst[y];
      subst_NDF->adept[ subst_NDF->poc_NDF ] = 'a' + zac_subst + subst_NDF->poc_NDF - 2 ;
      // takto to uz dalej nepojde mam malo pismen abecedy na vetvenia
      if( subst_NDF->adept[ subst_NDF->poc_NDF ] >= 'z' )
        {
         chybove_okno(chyba[26] );
         return(0);
        }
      subst_NDF->t_vodic[ subst_NDF->poc_NDF ] = '+';// znaci, ze je to clen OR
      strcpy( ret_f, vysl );                    // tuto je vysledok mojho snazenia
 
      pSubst_NDF = (char *) farmalloc( strlen( vysl ) + 1 );// sprav mu miesto
      min_mem = min_mem + strlen( vysl ) +8;
      pamet();                            // ukaz ako si na tom z pametou
      if ( pSubst_NDF == NULL ) {         // malo pamete
          chybove_okno(chyba[err] );
          return(0);
         }
      for( y=0; y <= strlen( vysl ); y++ ) pSubst_NDF[y] = vysl[y];
 
      return( zac_subst + subst_NDF->poc_NDF -1 ); // poslem aku premennu som vyrobil
     } // end if( ma_zatv( ret_f ) == 1 )
    else return(0);                               // subtitucie uz dosli
}
 
 
//************************************************************************//
// SUBSTITUCIE nahradzuje cleny substituovane skutocnymi vstupmi          //
// i:slovnik substitucii o: retazec substitucii               30.10.1997  //
//************************************************************************//
int substitucie( char subst[], char okrem )
{
int x,y;	        // devka
char pom[ max_ret ];
char vysl[ max_ret ];
int ma_subst=0;         // neaku substituciu som nahradil
zapis_NDF pom_NDF;
 
 vysl[0]='\0';          // no a co mam robit ???
 
 for( x=0; x< strlen( subst ); x++ )
    {// je to clen zo substituciou
     if(( ( subst[x]-'a'+1 ) >= zac_subst ) && ( je_znak( subst[x],jclen ) == TRUE ) && ( subst[x] != okrem ))
       {
	ma_subst=1;
        pom[0]='\0';
        for( y=0; y < strlen(subst_NDF.pNDF[ subst[x] - 'a' - zac_subst + 2 ] ); y++ )
           strchar( pom, subst_NDF.pNDF[ subst[x] - 'a' - zac_subst + 2 ][y] );
	// aj rekurzivne substitucie
	while ( substitucie( pom, okrem ) );
	strcat( vysl, "(" );                       // co ak je to substitucia (a+b)
        strcat( vysl, pom );
        strcat( vysl, ")" );
       } // end if( subst[x] > f_fnc.pv_NDF )
     else {// a co ak su negovane
     if(( ( subst[x]-224+1 ) >= zac_subst ) && ( je_znak( subst[x],nclen ) == TRUE ) && ( subst[x]-224+'a' != okrem ))
       {
	ma_subst=1;
        pom[0]='\0';
        for( y=0; y < strlen(subst_NDF.pNDF[ subst[x] - 224 - zac_subst + 2 ] ); y++ )
           strchar( pom, subst_NDF.pNDF[ subst[x] - 224 - zac_subst + 2 ][y] );
        znuluj( &pom_NDF, 0 );                     // aby to bolo OK
        vytvor_formu( &pom_NDF, pom );             // ret do mojho zapisu
        strcpy( pom , K_negovane( &pom_NDF ) );    // zneguj
        znuluj( &pom_NDF, 1 );                     // uvolni pamet
 
	// aj rekurzivne substitucie
	while ( substitucie( pom, okrem ) );
	strcat( vysl, "(" );                       // co ak je to substitucia (a+b)
        strcat( vysl, pom );
        strcat( vysl, ")" );
       }
      else strchar( vysl, subst[x] );
     }
    }	// end for( x=0; x< strlen( subst ); x++ )
 
 strcpy( subst, vysl );
 return( ma_subst );
}
 
//************************************************************************//
// KOLKO_VETIEV zistuje na kolko premennych sa deli primarny vstup        //
// i:funkcia o:pocet vetiev                                   22.11.1997  //
//************************************************************************//
int kolko_vetiev( char f_vstup[], int premenna )
{
int i,poc=0;
 
 for( i=0; i< strlen( f_vstup ); i++ )
    if(( f_vstup[i] == 'a' + premenna ) || ( f_vstup[i] == 224 + premenna ))
       poc++;
 return( poc );
}
 
 
/*---------------------------------END--------------------------------------*/