int
SCOTCH_graphMapCompute (
SCOTCH_Graph * const        grafptr,              /*+ Graph to order     +*/
SCOTCH_Mapping * const      mappptr,              /*+ Mapping to compute +*/
SCOTCH_Strat * const        stratptr)             /*+ Mapping strategy   +*/
{
  Kgraph                mapgrafdat;               /* Effective mapping graph     */
  const Strat *         mapstratptr;              /* Pointer to mapping strategy */
  LibMapping * restrict lmapptr;
  int                   o;

#ifdef SCOTCH_DEBUG_GRAPH2
  if (graphCheck ((Graph *) grafptr) != 0) {
    errorPrint ("SCOTCH_graphMapCompute: invalid input graph");
    return     (1);
  }
#endif /* SCOTCH_DEBUG_GRAPH2 */

  lmapptr = (LibMapping *) mappptr;
  if (*((Strat **) stratptr) == NULL) {           /* Set default mapping strategy if necessary */
    ArchDom             archdomnorg;

    archDomFrst (&lmapptr->m.archdat, &archdomnorg);
    if (archVar (&lmapptr->m.archdat))
      SCOTCH_stratGraphClusterBuild (stratptr, 0, 1, 0.0, 0.05);
    else
      SCOTCH_stratGraphMapBuild (stratptr, 0, archDomSize (&lmapptr->m.archdat, &archdomnorg), 0.05);
  }

  mapstratptr = *((Strat **) stratptr);
  if (mapstratptr->tabl != &kgraphmapststratab) {
    errorPrint ("SCOTCH_graphMapCompute: not a graph mapping strategy");
    return     (1);
  }

  if (kgraphInit (&mapgrafdat, (Graph *) grafptr, &lmapptr->m) != 0)
    return (1);
  o = kgraphMapSt (&mapgrafdat, mapstratptr);     /* Perform mapping */

  lmapptr->m.domnmax = mapgrafdat.m.domnmax;      /* Do not free the mapping, as it has been cloned */
  lmapptr->m.domnnbr = mapgrafdat.m.domnnbr;
  lmapptr->m.domntab = mapgrafdat.m.domntab;      /* Update pointer to domntab in case it has changed */

  mapgrafdat.m.parttax = NULL;                    /* Prevent mapping arrays from being freed by graph */
  mapgrafdat.m.domntab = NULL;
  kgraphExit (&mapgrafdat);

  if (lmapptr->parttax != NULL) {                 /* Propagate mapping data to user partition array */
    Gnum                vertnum;
    Gnum                vertnnd;

    for (vertnum = lmapptr->m.baseval, vertnnd = vertnum + lmapptr->m.vertnbr;
         vertnum < vertnnd; vertnum ++)
      lmapptr->parttax[vertnum] = archDomNum (&lmapptr->m.archdat, &lmapptr->m.domntab[lmapptr->m.parttax[vertnum]]);
  }

  return (o);
}
static
int
graphMapCompute2 (
SCOTCH_Graph * const        grafptr,              /*+ Graph to order                  +*/
SCOTCH_Mapping * const      mappptr,              /*+ Mapping to compute              +*/
SCOTCH_Mapping * const      mapoptr,              /*+ Old mapping                     +*/
const double                emraval,              /*+ Edge migration ratio            +*/ 
const SCOTCH_Num *          vmlotab,              /*+ Vertex migration cost array     +*/
Gnum                        vfixval,              /*+ Equal to 0 if no fixed vertices +*/
SCOTCH_Strat * const        straptr)              /*+ Mapping strategy                +*/
{
  Kgraph                mapgrafdat;               /* Effective mapping graph              */
  const Strat *         mapstraptr;               /* Pointer to mapping strategy          */
  LibMapping * restrict lmapptr;
  LibMapping * restrict lmaoptr;
  Anum *                pfixtax;
  Gnum                  baseval;
  Anum *                parttax;                  /* Partition array                      */
  Anum *                parotax;                  /* Old partition array                  */
  Gnum                  crloval;                  /* Coefficient load for regular edges   */
  Gnum                  cmloval;                  /* Coefficient load for migration edges */
  const Gnum *          vmlotax;                  /* Vertex migration cost array          */
  Gnum                  vertnum;
  Gnum                  vertnnd;
  Gnum                  vertnbr;
  int                   o;

  lmapptr = (LibMapping *) mappptr;
#ifdef SCOTCH_DEBUG_GRAPH2
  if ((Graph *) grafptr != lmapptr->grafptr) {
    errorPrint ("graphMapCompute2: output mapping does not correspond to input graph");
    return     (1);
  }
  if (graphCheck ((Graph *) grafptr) != 0) {      /* Vertex loads can be 0 if we have fixed vertices */
    errorPrint ("graphMapCompute2: invalid input graph");
    return     (1);
  }
#endif /* SCOTCH_DEBUG_GRAPH2 */

  if (*((Strat **) straptr) == NULL) {            /* Set default mapping strategy if necessary */
    ArchDom             archdomnorg;

    archDomFrst (lmapptr->archptr, &archdomnorg);
    SCOTCH_stratGraphMapBuild (straptr, SCOTCH_STRATDEFAULT, archDomSize (lmapptr->archptr, &archdomnorg), 0.01);
  }

  mapstraptr = *((Strat **) straptr);
  if (mapstraptr->tabl != &kgraphmapststratab) {
    errorPrint ("graphMapCompute2: not a graph mapping strategy");
    return     (1);
  }

  baseval = lmapptr->grafptr->baseval;
  vertnbr = lmapptr->grafptr->vertnbr;
  if (mapoptr != NULL) {                          /* We are doing a repartitioning */
    LibMapping *        lmaoptr;
    Gnum                numeval;
    Gnum                denoval;

    lmaoptr = (LibMapping *) mapoptr;
#ifdef SCOTCH_DEBUG_GRAPH2
    if (lmapptr->grafptr != lmaoptr->grafptr) {
      errorPrint ("graphMapCompute2: output and old mapping must correspond to the same graph");
      return     (1);
    }
    if (lmapptr->archptr != lmaoptr->archptr) {
      errorPrint ("graphMapCompute2: output and old mapping must correspond to the same architecture");
      return     (1);
    }
#endif /* SCOTCH_DEBUG_GRAPH2 */

    parotax = lmaoptr->parttab - baseval;
    vmlotax = (vmlotab != NULL) ? vmlotab - baseval : NULL;
    numeval = (INT) ((emraval * 100.0) + 0.5);
    denoval = intGcd (numeval, 100);
    cmloval = numeval / denoval;
    crloval = 100     / denoval;
  }
  else {
    parotax = NULL;
    vmlotax = NULL;
    cmloval =
    crloval = 1;
  }

  parttax = NULL;
  if (vfixval != 0) {                             /* We have fixed vertices */
#ifdef SCOTCH_DEBUG_GRAPH2
    if (lmapptr->parttab == NULL) {               /* We must have fixed vertices information */
      errorPrint ("graphMapCompute2: missing output mapping part array");
      return     (1);
    }
#endif /* SCOTCH_DEBUG_GRAPH2 */
    pfixtax = lmapptr->parttab - baseval;
    if ((parttax = (Anum *) memAlloc (vertnbr * sizeof (Anum))) == NULL) {
      errorPrint ("graphMapCompute2: out of memory (1)");
      return     (1);
    }
    memSet (parttax, 0, vertnbr * sizeof (Anum)); /* All vertices mapped to first domain */
    parttax -= baseval;
  } else {
    pfixtax = NULL;
    if (lmapptr->parttab == NULL) {               /* If user mapping not initialized */
      errorPrint ("graphMapCompute2: invalid user mapping");
      return     (1);
    }
    parttax = lmapptr->parttab - baseval;
  }

  intRandInit ();                                 /* Check that random number generator is initialized */

  if (kgraphInit (&mapgrafdat, (Graph *) grafptr, lmapptr->archptr, NULL, parttax, parotax, crloval, cmloval, vmlotax, pfixtax) != 0)
    return (1);

  o = 0;
  if (mapgrafdat.vfixnbr != mapgrafdat.s.vertnbr) { /* Perform mapping if not all fixed vertices */
    o = kgraphMapSt (&mapgrafdat, mapstraptr);

    lmapptr->parttab -= baseval;
    for (vertnum = baseval, vertnnd = vertnum + lmapptr->grafptr->vertnbr;
        vertnum < vertnnd; vertnum ++)
      lmapptr->parttab[vertnum] = archDomNum (lmapptr->archptr, &mapgrafdat.m.domntab[mapgrafdat.m.parttax[vertnum]]);
    lmapptr->parttab += baseval;
  }

  if (vfixval != 0)                               /* We have fixed vertices */
    memFree (parttax + baseval);

  kgraphExit (&mapgrafdat);

  return (o);
}