/*****************************************************
* Unit:    stacks           release 0.6              *
* purpose: test of functionality of unit stack       *
* Licency: GPL                                       *
* Copyright: (c) 2005-2024 Jaroslav Fojtik           *
******************************************************/
#ifdef _MSC_VER
    #include <windows.h>
#endif
#include <stdio.h>
//#include <stdlib.h>
#include <math.h>
#include <string.h>

#ifdef __BORLANDC__
 #include <alloc.h>
#else
 #define heapcheck() 1
#endif

#define CurrentDir

#ifdef Streams
 #ifdef IOSTREAM_H_ONLY
  #include<iostream.h>
 #else
  #include <iostream>
  using namespace std;
 #endif
#endif

#include "stacks.h"


#ifdef ERROR_HANDLER
 void RaiseError(int ErrNo, const void *Instance)
     {
     fprintf(stderr,"Stack::Error %d (%p)\n",ErrNo,Instance);
     }
#endif

void Benchmark(void);


const int TestArray[10]={1,2,3,5,7, 9,257,1025,16384,4096};


int main(int argc, char *argv[])
{
stack st0,st1;
int i,j;
int Ops;

//CheckCompiler();
 puts("");
 puts("<<<stack>>> (c)2005-2024 Jaroslav Fojtik");
 puts("                 This program tests the stack unit");

 if(argc>1)
    {
    Ops=0;
    for(i=1; i<argc; i++)
      {
      if(!strcmp(argv[i],"-bench")) Ops|=3;
      if(!strcmp(argv[i],"-demo")) Ops|=4;
      if(!strcmp(argv[i],"-test")) Ops|=1;
      }
    }
 else Ops=3;


if(Ops & 1)
{
 //////////////////////////////////
 puts(" pop & push commands");

if(!EmptyCheck(st0))
  {
#ifdef Streams
  cout << "New stack contains something";
#endif
  i = -10;
  goto Abnormal_End;
  }
if(Card(st0)!=0)
  {
#ifdef Streams
  cout<<"Wrong cardinality of empty stack Card="<<Card(st0);
#endif
  i = -11;
  goto Abnormal_End;
  }


for(i=0;i<10;i++)
  {
  st0.push(TestArray[i]);
  //cout << "contents:" << st0;

  if(check(st0))
    {
#ifdef Streams
    cout<<"Stack become corrupted during push";
#endif
    i=-12;
    goto Abnormal_End;
    }

  if(EmptyCheck(st0))
    {
#ifdef Streams
    cout<<"Filled stack is reported to be empty "<<st0;
#endif
    i=-13;
    goto Abnormal_End;
    }

  if(Card(st0) != i+1)
    {
#ifdef Streams
    cout<<"Wrong stack cardinality Card="<<Card(st0)<<" expected:"<<i+1;
#endif
    i=-14;
    goto Abnormal_End;
    }
  }

for(i=9;i>=0;i--)
  {
  if((j=st0.pop())!=TestArray[i])
    {
#ifdef Streams
    cout<<"Stack should not contain:"<<j<<" expected value:"<<TestArray[i];
#endif
    i=-15;
    goto Abnormal_End;
    }

  if(check(st0))
    {
#ifdef Streams
    cout<<"Stack become corrupted during pop";
#endif
    i=-16;
    goto Abnormal_End;
    }
  }

if(!EmptyCheck(st0))
  {
#ifdef Streams
  cout<<"Stack should be empty";
#endif
  i=-17;
  goto Abnormal_End;
  }


//////////////////////////////////
puts(" constructors & copy operator =");

for(i=0;i<10;i++)
  st0.push(TestArray[i]);

st1 = st0;

while(!EmptyCheck(st0))
  {
  j = st0.pop();
  if(j!=st1.pop())
    {
#ifdef Streams
    cout<<"Stack should not contain:"<<j;
#endif
    i = -21;
    goto Abnormal_End;
    }
  }

}

/////Now execute benchmarks/////
if(Ops & 2) Benchmark();

///////////End of tests/////////
i=0;
Abnormal_End:
if(heapcheck()<=0)
         {
	 printf("Bad allocation %d",heapcheck());
         return(-1);
         }
if(i!=0) {
	 printf("Unit Error %d",i);
         return(-1);
         }
puts(" .............. Test passed OK ..............");
return(0);
}



#include "../test/bench.h"


void PopPush(long i)
{
stack st;
while(i-->0)
  {
  st.push(1); st.push(2); st.push(3);
  st.push(5); st.push(7); st.push(9);

  st.pop();   st.pop();   st.pop();
  st.pop();   st.pop();   st.pop();
  }
}

void BigPopPush(long i)
{
stack st;
while(i-->0)
  {
  if(i & 256)
    {st.push(i); st.push(i); st.push(i);}
  else
    {st.pop(); st.pop(); st.pop();}
  }
}


void Benchmark(void)
{
float f;

puts(" .............. Benchmarks ..............");


f=AutoMeasure(PopPush);
printf(" Pop and push: %fus\n",f);

f=AutoMeasure(BigPopPush);
printf(" Big pop and push: %fus\n",f);

}
