Metropoli BBS
VIEWER: indexm.c MODE: TEXT (ASCII)
/*Copyright (C) 1993, 1994 by Thomas Glen Smith.  All Rights Reserved.*/
/* indexm APL2 V1.0.0 **************************************************
* Called by enclosf and squadix.                                       *
* Left points to an APL variable from, and perhaps to, which values    *
* are to be indexed.  Indices identifies the index values to be used,  *
* and determines the shape of the output.  If rite isn't NULL, it      *
* contains values to be stored in the indexed elements of left.        *
* Indexm differs from indexv in that left may be of any shape, and     *
* the output may have rank other than 1.  Indexm is the true           *
* implementation of the APL indexing function.                         *
***********************************************************************/
#define INCLUDES APLCB+APLMEM+INDEXMI
#include "includes.h"
Aplcb indexm(left, indices, rite)
Aplcb left, indices, rite;
{
	Errinit; Errstop; Getcb; Indexma; Indexmb; Intcopy; Ireduce; Itimes;
     Matchok; Perm; Temp;
     extern int aplerr; extern int indxorg;
     int  datacnt,i,*ip,itimesid,j,k,*op,rank,tempsave;
	struct ix p;
	Aplcb dimcb, x, *xcb;

	if (errinit()) return(errstop(0,left,indices,rite));
	if ((rite != NULL ) && (!matchok(&left,&rite,APLMASK+APLAPL)))
			return(errstop(0,NULL,indices,NULL));
	if (left->aplrank != indices->aplcount)
			return(errstop(53,left,indices,rite));
	p.siz = left->aplsize;
	p.l = left; p.r = rite; p.x = indices;
	p.o = (void *) p.z = (void *) p.datarite = p.dataout= NULL;
	dimcb = indexma(&p); /* go get output dimensions */
	if (dimcb != NULL) {
		itimesid = 1; /* identity */
		datacnt = ivalue(ireduce(itimes,&itimesid,perm(dimcb),indxorg));
		p.dtyp = left->aplflags & (APLMASK + APLAPL);
		if (0 == (rank = dimcb->aplcount) && p.dtyp == APLCHAR) 
			rank++; /* character types can't be scalars */
		if (rite != NULL) {
			p.datarite = rite->aplptr.aplchar;
			if (0 != (p.inc = (1 == rite->aplcount) ? 0 : p.siz)
			  && rite->aplcount != datacnt) aplerr = 112;
		}
		if (aplerr == 0)
			p.o = getcb(NULL,datacnt,p.dtyp + APLTEMP,rank,NULL);
		if (aplerr == 0 && rank > 1)
			ip = intcopy(p.o->apldim,dimcb->aplptr.aplint,rank,1);
		endoper(temp(dimcb));
		if (aplerr == 0) {
			p.dataout = p.o->aplptr.aplchar;
			if (p.o->aplcount) {
				x = *(xcb = indices->aplptr.aplapl); /* 1st index */
				ip = indexmb(0,&p,xcb,0,x->aplptr.aplint,
					left->aplptr.aplchar);
	}	}	}
	if (p.z != NULL) free(p.z);
	endoper(indices); return(errstop(0,left,rite,p.o));
}
[ RETURN TO DIRECTORY ]