// 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"); }