/* Copyright (C) 1993 by Thomas Glen Smith. All Rights Reserved. */
/* reducecm APL2 V1.0.0 ************************************************
* Called by ireduces and nreduces. *
* Builds the necessary output APLCB for a reduce or scan operation, *
* but expects the caller to perform the reduce or scan. *
***********************************************************************/
#define INCLUDES APLCB+APLMEM
#include "includes.h"
Aplcb reducecm(id,identity,rite,axis,axicnt,botcnt,topcnt,type)
int id; /* 1=reduce, 0=scan */
double *identity; /* identity value */
Aplcb rite; /* operand */
int *axis; /* axis of reduction */
int *axicnt,*botcnt,*topcnt; /* processing variables */
int type; /* data type of output */
{
Axispre; Errinit; Errstop; Getcb; Imax;
extern int indxorg;
int datacnt,*dimin,*dimout,i,j,k,rank;
Aplcb out=NULL;
if (errinit())
return(errstop(0,NULL,rite,NULL));
if (*axis < 0) /* does caller want the default axis? */
*axis = rite->aplrank;
else
*axis += (indxorg == 0);
if (OK!=axispre(rite,*axis,axicnt,botcnt,topcnt))
return(errstop(0,NULL,rite,NULL));
if (id)
datacnt=*topcnt**botcnt; /* reduce */
else
datacnt=rite->aplcount; /* scan */
rank=imax(0,rite->aplrank-id);
if (datacnt && type == APLCHAR && *axicnt > 1) type = APLINT;
out=getcb(NULL,datacnt,type+APLTEMP,rank,NULL);
if (rank > 1) { /* output isn't scalar or vector */
dimout=out->apldim;
dimin=rite->apldim;
for (i=1; i<=rite->aplrank; i++) {
if (!(id && i==*axis))
*dimout++=*dimin;
dimin++;
}
}
if (!datacnt) /* result empty? */
return(out);
/* 1 or more elements of output */
if (rite->aplcount==0 && identity==NULL)
return(errstop(13,NULL,rite,out)); /* no identity */
return(out);
}