#include "Bdef.h"

int Smpath_br(ctxt, scope, npaths, rsrc, csrc)
BLACSCONTEXT  *ctxt;
char  scope;
int  npaths;
int  rsrc;
int  csrc;
{
   void Ssend2d00();
   void Srecv2d00();

   int pathlen;		/* the minimal length of each path */
   int mydist;		/* my distance from src */
   int faredge;		/* node at far end of path */
   int lastlong;	/* distance to node on end of last path with extra node */
   int rdest, cdest;    /* row and column coordinates of destination node */
   int nrnodes;         /* number of receiving nodes ( = nnodes-1 ) */
   int Ng, nprow, npcol, myrow, mycol;
   int msgid;
   int info, rbufid;

   Mgridinfo(ctxt, Ng, nprow, npcol, myrow, mycol);
   if (npaths == FULLCON) npaths = Ng;
   scope = Mlowcase(scope);
   switch(scope)
   {
   case 'r':
      msgid = Mrid(ctxt);
      nrnodes = npcol - 1;
      rdest = myrow;
      if (npaths > 0)
      {
         cdest = (mycol+1) % npcol;
         mydist = (npcol + mycol - csrc) % npcol;
      }
      else
      {
	 cdest = (nrnodes+mycol) % npcol;
         mydist = (npcol + csrc - mycol) % npcol;
	 npaths = -npaths;
      }
      break;
   case 'c':
      msgid = Mcid(ctxt);
      nrnodes = nprow - 1;
      if (npaths > 0)
      {
         rdest = (myrow+1) % nprow;
         mydist = (nprow + myrow - rsrc) % nprow;
      }
      else
      {
	 rdest = (nrnodes+myrow) % nprow;
         mydist = (nprow + rsrc - myrow) % nprow;
	 npaths = -npaths;
      }
      cdest = mycol;
      break;
   case 'a':  /* NOTE: faredge temp. holds src and dest in this case */
      msgid = Maid(ctxt);
      nrnodes = Ng - 1;
      faredge = Mvkpnum(ctxt, rsrc, csrc);
      if (npaths > 0)
      {
         mydist = (Ng + ctxt->vIam - faredge) % Ng;
         faredge = (ctxt->vIam+1) % Ng;
      }
      else
      {
         mydist = (Ng + faredge - ctxt->vIam) % Ng;
	 faredge = (nrnodes+ctxt->vIam) % Ng;
	 npaths = -npaths;
      }
      Mvpcoord(ctxt, faredge, rdest, cdest);
      break;
   default:
      return(BADSCP);
   }
/*
 * Make sure npaths is cool
 */
   if (npaths > nrnodes) npaths = nrnodes;

   pathlen = nrnodes / npaths;
   lastlong = (nrnodes%npaths) * (pathlen+1);
   if (lastlong)
   {
      if (mydist <= lastlong) faredge = ((mydist-1)/(pathlen+1)+1)*(pathlen+1);
      else faredge = ((lastlong-1)/(pathlen+1)+1) * (pathlen+1)
		     + ((mydist-lastlong-1)/pathlen + 1) * pathlen;
   }
   else faredge = ((mydist-1)/pathlen + 1) * pathlen;

   Srecv2d00(ctxt, msgid);

   if (mydist < faredge)
   {
/*
    *    Free send buffer, send from receive buff
 */
      rbufid = pvm_getrbuf();
      info = pvm_freebuf(pvm_setsbuf(rbufid));
      Mpvmerror(info, "pvm_freebuf", __LINE__, __FILE__);
      Ssend2d00(ctxt, rdest, cdest, msgid);
      pvm_setrbuf(rbufid);  /* restore buffer state */
   }
   return(0);
}
