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