// loop-ps.c
//      Copyright 1994, Center for Computer Vision and Visualization,
//      University of Florida.  All rights reserved.
//   Create a point set, where each point represents the possible
//   values of indices in nested for loops.
//   We assume that the nested loops have the following properties:
//
//   An over all range from:           start..end
//   The outmost loop starts at value: start
//   The inmost loop stops at value:   end
//   Each inner loop begins at a value 1 > the next most outer loop.
//   Each inner loop ends at a value   1 < the next most inner loop.
//

#include "loop-ps.h"


// This kludge allows me to pass information into the loops_ps_func
//   otherwise, it would be necessary to define an IA_Closure<IP,IP>
//   just to define the function we need here.

static int *lpsf_start, *lpsf_end;


static
int
loops_ps_func( const IA_Point<int> & ip ) {
    // This hack requires the services of static variables
    // defined above to pass parameters we use.

    // First check that the point is within bounds
    for (int d=0; d< ip.dim(); d++) {
	int ipd = ip[d];
	if (ipd < lpsf_start[d])  return 0;
	if (ipd > lpsf_end[d])    return 0;
    }

    // Now check then the point coords are strictly increasing
    for (d=1; d<ip.dim(); d++) {
	if (ip[d-1] >= ip[d])     return 0;
    }
    return 1;
}


IA_Set<IA_Point<int> >
loop_ps( unsigned int d_loops, int start, int end ) {

    int
	d, i,       // loop counters
	* dStart = new int[d_loops], // Start values for each dimen
	* dEnd   = new int[d_loops]; // End values for each dimen


    for (i=start, d=0; d<d_loops; d++, i++) {
	dStart[d] = i;
    }
    IA_Point<int>
	start_ip(dStart, d_loops);  // vector constructor


    for (i=end, d=d_loops-1; d>=0; d--, i--) {
	dEnd[d] = i;
    }
    IA_Point<int>
	end_ip(dEnd, d_loops);     // vector constructor


    // First cut will do this by building the largest point set
    // possible and then cutting away at it until we have the result

    IA_Set<IA_Point<int> >
	ps( start_ip, end_ip );

    // Now create a point set defined by a function that we
    // define locally, and return the intersection.

    // Point the static data pointers to someting of interest.
    lpsf_start = dStart;
    lpsf_end   = dEnd;

    IA_Set<IA_Point<int> >
	funcps( d_loops, loops_ps_func );

    return ps & funcps;  // The result is the intersection of these two
}
