Metropoli BBS
VIEWER: finda.c MODE: TEXT (ASCII)
/* Copyright (C) 1993 by Thomas Glen Smith.	All Rights Reserved. */
/* finda APL2 V1.0.0 ***************************************************
* Called from find to finish processing after initial checks.		 *
***********************************************************************/
#define INCLUDES APLCB
#include "includes.h"
void finda(left,rite,out,d)
Aplcb left,rite;	/* Arguments, already matched by data type. */
Aplcb out;		/* Output. */
int d;			/* Difference between ranks of left and rite. */
{
	Endoper; Getcb; Intcopy;
     void findb(Aplcb, Aplcb, Aplcb, Aplcb, Aplcb, Aplcb, Aplcb,
     	int, int, int);
	extern int aplerr;
	Aplcb dimcb=NULL,ixcb=NULL,lccb=NULL,rccb=NULL;
	int datatyp,i,j,k,*iip,*jip,*oip;

	for (;;) { /* lets me use break */
		datatyp = left->aplflags & (APLMASK + APLAPL);
		dimcb = getcb(NULL, out->aplrank, APLTEMP + APLINT, 1, NULL);
			/* Pseudo-dimensions: The first d dimensions of rite will  */
			/* match the first d items in dimcb.  Remaining items will */
			/* be the difference between right-most dimensions of rite */
			/* and the dimensions of left.					    */
		ixcb  = getcb(NULL, out->aplrank, APLTEMP + APLINT, 1, NULL);
			/* Indices to rite and out, bumped by calls to indices.    */
			/* Used for two things:							    */
			/* 1.  Select elements in out which can be 1.		    */
			/* 2.  Select the upper left corner element in rite for    */
			/*	  comparison against left.					    */
		lccb  = getcb(NULL, left->aplrank, APLTEMP + APLINT, 1, NULL);
		rccb  = getcb(NULL, rite->aplrank, APLTEMP + APLINT, 1, NULL);
			/* Lccb and rccb will be used to make the comparison on    */
			/* sub-array in rite against left to determine if the	    */
			/* current output item should be 1 or 0.			    */
		if (aplerr) break;
		i = -1; /* Set ixcb array to -1 (required by indices rtne). */
		oip = intcopy(ixcb->aplptr.aplint, &i, ixcb->aplcount, 0);
		/* Now compare the rightmost (Rleft) dimensions of rite to	   */
		/* rite to dimensions of left.  If a dimension of rite is less */
		/* than left, all output of find must be all zeros. Also	   */
		/* derive k = #items in out that can be 1.				   */
		for(k = 1, i = d, oip = dimcb->aplptr.aplint,
			iip = out->apldim; i; i--) k *= *oip++ = *iip++;
		for( i = j = out->aplrank - d, iip = out->apldim + d,
			jip = left->apldim; i && j > -1; i--)
			k *= *oip++ = 1 + (j = *iip++ - *jip++);
		if (j < 0) break; /* Done: Dimension of rite < left */
          findb(left,rite,out,dimcb,ixcb,lccb,rccb,k,datatyp,d);
		break; /* final break out of for (;;) */
	}
	endoper(dimcb);
	endoper(ixcb);
	endoper(lccb);
	endoper(rccb);
}
[ RETURN TO DIRECTORY ]