// STACK.C
// Stack functions
// © 2021 Peter J. Meyer
#include "iss.h"
static short int *stack_ptr;
static short int *end_of_stack;
static short int *max_stack_ptr;
static unsigned int stack_limit_reached;
static unsigned int stack_limit_reached_overflow;
static unsigned long total_stack_pushes;
extern int max_num_items_in_queue;
extern unsigned int queue_limit_reached;
extern unsigned int queue_limit_reached_overflow;
extern unsigned long total_queue_pushes;
// stack_size is a global variable.
/*--------------------------------*/
void allocate_memory_for_stack(void)
{
int err_flag;
// stack_size = number of short ints, not number of bytes.
if ( !stack_size )
{
printf("\nAttempt to allocate stack of zero size.\n");
exit(1);
}
stack = (A1(short int))array_alloc(&err_flag, sizeof(short int), NULL, 1, stack_size);
/* stack = ((short int *))array_alloc(&err_flag, sizeof(short int), NULL, 1, stack_size); */
if ( err_flag )
{
printf("\nError %d when attempting to allocate an array of %d short ints for stack.\n",
err_flag,stack_size);
exit(1);
}
// Initialize stack variables.
end_of_stack = stack + stack_size; // These are pointers to short ints.
max_stack_ptr = stack;
stack_limit_reached = 0;
stack_limit_reached_overflow = false;
total_stack_pushes = 0;
// Initialize queue variables also.
max_num_items_in_queue = 0;
queue_limit_reached = 0;
queue_limit_reached_overflow = false;
total_queue_pushes = 0;
}
/*------------------*/
void clear_stack(void)
{
if ( !stack_size )
{
printf("\nStack not allocated!\n");
exit(1);
}
stack_ptr = stack;
}
/*-----------------*/
int stack_empty(void)
{
return ( stack_ptr == stack );
}
/*-------------------------------------*/
void check_stack_is_empty(char *location)
{
if ( !stack_empty() )
{
printf("\nStack not empty (in %s).\n",location);
exit(1);
}
}
/*----------------------------------------------*/
int push_onto_stack(short int i, short int j, ...)
{
// int k, l;
if ( stack_ptr + dimensionality > end_of_stack )
{
if ( stack_limit_reached + 1 == 0 )
stack_limit_reached_overflow = true;
else
stack_limit_reached++;
return ( false );
}
total_stack_pushes++;
*(stack_ptr++) = i;
*(stack_ptr++) = j;
switch ( dimensionality )
{
case 3:
// k = *(((int *)(&j))+1);
*(stack_ptr++) = *(((int *)(&j))+1);
break;
case 4:
// k = *(((int *)(&j))+1);
// l = *(((int *)(&j))+2);
*(stack_ptr++) = *(((int *)(&j))+1);
*(stack_ptr++) = *(((int *)(&j))+2);
break;
}
if ( stack_ptr > max_stack_ptr )
max_stack_ptr = stack_ptr;
return ( true );
}
/*-----------------------------------------------------*/
int pop_from_stack(short int *iptr, short int *jptr, ...)
{
short int *kptr, *lptr;
if ( stack_ptr < stack + dimensionality )
return ( false );
// Must decrement stack pointer *before* popping stack value.
switch ( dimensionality )
{
case 3:
kptr = *(((short int **)(&jptr))+1);
*kptr = *(--stack_ptr);
break;
case 4:
kptr = *(((short int **)(&jptr))+1);
lptr = *(((short int **)(&jptr))+2);
*lptr = *(--stack_ptr);
*kptr = *(--stack_ptr);
break;
}
*jptr = *(--stack_ptr);
*iptr = *(--stack_ptr);
return ( true );
}
// The following two functions are called in WOLFF.C.
// Same as the push/pop functions above, with an extra parameter.
/*------------------------------------------------------------------*/
int push_onto_stack_with_r(short int r, short int i, short int j, ...)
{
// int k, l;
if ( stack_ptr + dimensionality + 1 > end_of_stack )
{
if ( stack_limit_reached + 1 == 0 )
stack_limit_reached_overflow = true;
else
stack_limit_reached++;
return ( false );
}
total_stack_pushes++;
*(stack_ptr++) = r;
*(stack_ptr++) = i;
*(stack_ptr++) = j;
switch ( dimensionality )
{
case 3:
// k = *(((int *)(&j))+1);
*(stack_ptr++) = *(((int *)(&j))+1);
break;
case 4:
// k = *(((int *)(&j))+1);
// l = *(((int *)(&j))+2);
*(stack_ptr++) = *(((int *)(&j))+1);
*(stack_ptr++) = *(((int *)(&j))+2);
break;
}
if ( stack_ptr > max_stack_ptr )
max_stack_ptr = stack_ptr;
return ( true );
}
/*-----------------------------------------------------------------------------*/
int pop_from_stack_with_r(short int *rptr, short int *iptr, short int *jptr, ...)
{
short int *kptr, *lptr;
if ( stack_ptr < stack + dimensionality + 1 )
return ( false );
// Must decrement stack pointer *before* popping stack value.
switch ( dimensionality )
{
case 3:
kptr = *(((short int **)(&jptr))+1);
*kptr = *(--stack_ptr);
break;
case 4:
kptr = *(((short int **)(&jptr))+1);
lptr = *(((short int **)(&jptr))+2);
*lptr = *(--stack_ptr);
*kptr = *(--stack_ptr);
break;
}
*jptr = *(--stack_ptr);
*iptr = *(--stack_ptr);
*rptr = *(--stack_ptr);
return ( true );
}
// This assumes that we are writing to a file already.
/*---------------------------*/
void write_stack_data(FILE *of)
{
int max_num_short_ints_on_stack = max_stack_ptr - stack;
int stack_size_in_bytes = stack_size*sizeof(short int);
int short_ints_per_stack_push;
fprintf(of,"\n\nTotal number of stack pushes = %s",ultoa_commas(total_stack_pushes,temp));
short_ints_per_stack_push = ( dynamics_is_swendsen_wang ?
SHORT_INTS_PER_SWENDSEN_WANG_STACK_PUSH : SHORT_INTS_PER_WOLFF_STACK_PUSH );
fprintf(of,"\nMaximum consecutive stack pushes = %s",
ultoa_commas(max_num_short_ints_on_stack/short_ints_per_stack_push,temp1));
fprintf(of,"\n%.2f%% of the stack was used (stack size = ",
((double)max_num_short_ints_on_stack*100)/stack_size);
if ( stack_size_in_bytes < 10000 )
fprintf(of,"%d bytes).",stack_size_in_bytes);
else
{
ultoa_commas(stack_size_in_bytes/1024,temp);
fprintf(of,"%s KB).",temp);
}
if ( stack_limit_reached )
{
fprintf(of,"\nStack limit was reached ");
if ( stack_limit_reached_overflow )
fprintf(of,"more than ");
fprintf(of,"%s time%s.\n",ultoa_commas(stack_limit_reached,temp),
(stack_limit_reached==1 ? "" : "s" ));
}
fprintf(of,"\n");
}