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