Metropoli BBS
VIEWER: reduces.h MODE: TEXT (ASCII)
/*Copyright (C) 1993, 1996 by Thomas Glen Smith.  All Rights Reserved.*/
/* reduces.h APL2 V1.0.0 ***********************************************
* The is the heart of both subroutines reducesb.c and ireduces.c.      *
* After using #define for the following values, this code is included  *
* in those subroutines to do both reduce and scan processing for the   *
* two data types integer and real, respectively:                       *
*   SUBRTNE -> Subroutine name.                                        *
*   DATATYPE-> Data type, i.e. int or double.                          *
*   APLTYPE -> APL data type, i.e. APLINT or APLNUMB.                  *
*   CONVERT -> Conversion subroutine, i.e. integer or real.            *
*   COPYSUB -> Copy subroutine, i.e. intcopy or dblcopy.               *
*   DATAPTR -> union name to be used with aplptr, i.e. aplint, apldata.*
***********************************************************************/
struct aplcb *SUBRTNE(id,oper,identity,rite,axis)
int id; /* 1=reduce, 0=scan */
DATATYPE (*oper)(); /* operator */
DATATYPE *identity; /* identity value */
Aplcb rite; /* operand */
int axis; /* axis of reduction */
{
	Errinit; Errstop; Reducecm;
	extern int aplerr;
	Aplcb CONVERT(), out;
	int axicnt,botcnt,topcnt;
	int i,j,k,m,n,p;
	DATATYPE *dataout,*COPYSUB(),*ip,*kp,wrk;

	if (errinit())
		return(errstop(0,NULL,rite,NULL));
	if (!(rite->aplflags & APLTYPE)) {
		rite=CONVERT(rite); /* convert to desired input data type */
		if (aplerr)
			return(NULL);
	}
	out=reducecm(id,identity,rite,&axis,&axicnt,&botcnt,&topcnt,APLTYPE);
	if (aplerr)
		return(NULL);
	n = (id) ? 1 : axicnt; /* n == 1 if reduce, axicnt if scan */
	if (out->aplcount) { /* 1 or more elements of output */
		dataout = out->aplptr.DATAPTR;
		if (0 == rite->aplcount) /* is input empty? */
			dataout=COPYSUB(dataout,identity,out->aplcount,0); 
		else {
			for (i = 0; i < topcnt; i++) {
				ip=rite->aplptr.DATAPTR+(p=i*botcnt*axicnt);
				for (j=0; j<botcnt; j++)
					for (m = n; m > 0; m--) {
						wrk=*(kp=ip+j+(axicnt-m)*botcnt);
						for (k = 1; k < axicnt-m+1; k++)
							wrk=(*oper)(*(kp-=botcnt),wrk);
						if (id) *dataout++=wrk; /* reduce */
						else *(dataout+p+j+(axicnt-m)*botcnt)=wrk;
					}
			}
		}
	}
	return(errstop(0,NULL,rite,out));
}
[ RETURN TO DIRECTORY ]