Metropoli BBS
VIEWER: transpot.c MODE: TEXT (ASCII)
/*Copyright (C) 1992, 1996 by Thomas Glen Smith.  All Rights Reserved.*/
/* transpot APL2 V1.0.0 ************************************************
* Called by transpos to complete the operation after the initial       *
* environment has been established.                                    *
***********************************************************************/
#define INCLUDES APLCB
#include "includes.h"
Aplcb transpot(left,rite)
Aplcb left,rite;
{
	Errstop;Getcb;Getfact;Idyadic;Ieq;Imax;Imonadic;Indexv;Indxsub;Inot;
	Intcopy;Ior;Iplus;Ireduce;Iscalar;Iscan;Ivalue;Perm;Reshape;Shape;
	Temp;Transpou;Vectin;
     extern int indxorg, aplerr;
	Aplcb dimcb,testcb,factor;
	int axis,*dp,i,iorid=0,*ip,iplusid=0,j,k,m,n,outrank,riterank;
	static int minus_one=-1;
	char *icp,*ocp;

     riterank = rite->aplrank > 1 ? rite->aplrank : 1;
	if (NULL == left) /* monadic form? */
		left = perm(indxsub(-riterank)); /* left = rank, rank-1, etc. */
	else {
		if (left->aplcount != riterank)
			return(errstop(32,left,rite,NULL)); /* bad left length */
		if (NULL == (left = vectin(left))) /* left w/b permanent */
			return(errstop(0,left,rite,NULL)); /* error */
	}
	testcb = perm(reshape(shape(left),iscalar(1))); /* vector of ones */
	endoper(indexv(testcb,left,iscalar(0))); /* 0s = indices used */
	if (aplerr) return(errstop(0,temp(left),temp(testcb),rite));
	if (left->aplcount != ivalue(		/* left m/b a vector equal in  */
		ireduce(iplus,&iplusid,		/* length to the rank of rite, */
			idyadic(ieq,			/* and m/b complete in that if */
				testcb,			/* its items include any int-  */
				iscan(ior,&iorid,	/* eger N, it also includes all*/
					testcb,		/* positive integers less than */
					indxorg)),	/* N.					 */
			indxorg)))
		return(errstop(33,temp(left),temp(testcb),rite));
	outrank = ivalue(ireduce(iplus,&iplusid,
		imonadic(inot,temp(testcb)),indxorg));
	dimcb = getcb(NULL,outrank,APLINT,1,NULL); /* to store new dims. */
	if (dimcb == NULL) return(errstop(0,left,rite,NULL));
	intcopy(dimcb->aplptr.aplint,&minus_one,outrank,0);
	if (rite->aplrank) /* loop only if rite not scalar */
		for (i = 0; i < riterank; i++) {
			m = *(rite->apldim+i); /* Selected dim. of rite. */
			j = *(left->aplptr.aplint + i) - indxorg;
				/* j == index (rel 0) to selected dim. of output. */
			n = *(dimcb->aplptr.aplint + j);
			*(dimcb->aplptr.aplint + j) = (n == -1 || m < n) ? m : n;
				/* If two or more dimensions of rite are mapped into */
				/* the same dimension of output, use the smaller.    */
				/* Generally, dimcb{left{i}}=shape(rite){i} */
		}
	factor = getfact(shape(rite));
	return(transpou(left,rite,dimcb,factor,outrank));
}
[ RETURN TO DIRECTORY ]