-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpid/common/datatype/mpid_segment.c
        -:    0:Graph:mpid_segment.gcno
        -:    0:Data:mpid_segment.gcda
        -:    0:Runs:3459
        -:    0:Programs:899
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:
        -:    3:/*
        -:    4:*  (C) 2001 by Argonne National Laboratory.
        -:    5:*      See COPYRIGHT in top-level directory.
        -:    6:*/
        -:    7:
        -:    8:#include <stdio.h>
        -:    9:#include <stdlib.h>
        -:   10:
        -:   11:#include <mpiimpl.h>
        -:   12:#include <mpid_dataloop.h>
        -:   13:
        -:   14:/*
        -:   15: * Define these two names to enable debugging output.
        -:   16: */
        -:   17:#undef MPID_SP_VERBOSE
        -:   18:#undef MPID_SU_VERBOSE
        -:   19:
        -:   20:/* MPID_Segment_piece_params
        -:   21:*
        -:   22:* This structure is used to pass function-specific parameters into our
        -:   23:* segment processing function.  This allows us to get additional parameters
        -:   24:* to the functions it calls without changing the prototype.
        -:   25:*/
        -:   26:struct MPID_Segment_piece_params {
        -:   27:    union {
        -:   28:	struct {
        -:   29:	    char *pack_buffer;
        -:   30:	} pack;
        -:   31:	struct {
        -:   32:	    DLOOP_VECTOR *vectorp;
        -:   33:	    int index;
        -:   34:	    int length;
        -:   35:	} pack_vector;
        -:   36:	struct {
        -:   37:	    int64_t *offp;
        -:   38:	    int *sizep; /* see notes in Segment_flatten header */
        -:   39:	    int index;
        -:   40:	    int length;
        -:   41:	} flatten;
        -:   42:	struct {
        -:   43:	    char *last_loc;
        -:   44:	    int count;
        -:   45:	} contig_blocks;
        -:   46:	struct {
        -:   47:	    char *unpack_buffer;
        -:   48:	} unpack;
        -:   49:	struct {
        -:   50:	    int stream_off;
        -:   51:	} print;
        -:   52:    } u;
        -:   53:};
        -:   54:
        -:   55:/* prototypes of internal functions */
        -:   56:static int MPID_Segment_vector_pack_to_iov(DLOOP_Offset *blocks_p,
        -:   57:				       int count,
        -:   58:				       int blksz,
        -:   59:				       DLOOP_Offset stride,
        -:   60:				       DLOOP_Type el_type,
        -:   61:				       DLOOP_Offset rel_off,
        -:   62:				       void *bufp,
        -:   63:				       void *v_paramp);
        -:   64:
        -:   65:static int MPID_Segment_contig_pack_to_iov(DLOOP_Offset *blocks_p,
        -:   66:                                           DLOOP_Type el_type,
        -:   67:					   DLOOP_Offset rel_off,
        -:   68:					   void *bufp,
        -:   69:					   void *v_paramp);
        -:   70:
        -:   71:static int MPID_Segment_contig_flatten(DLOOP_Offset *blocks_p,
        -:   72:				   DLOOP_Type el_type,
        -:   73:				   DLOOP_Offset rel_off,
        -:   74:				   void *bufp,
        -:   75:				   void *v_paramp);
        -:   76:
        -:   77:static int MPID_Segment_vector_flatten(DLOOP_Offset *blocks_p,
        -:   78:				   int count,
        -:   79:				   int blksz,
        -:   80:				   DLOOP_Offset stride,
        -:   81:				   DLOOP_Type el_type,
        -:   82:				   DLOOP_Offset rel_off, /* offset into buffer */
        -:   83:				   void *bufp, /* start of buffer */
        -:   84:				   void *v_paramp);
        -:   85:
        -:   86:/********** EXTERNALLY VISIBLE FUNCTIONS FOR TYPE MANIPULATION **********/
        -:   87:
        -:   88:#undef FUNCNAME
        -:   89:#define FUNCNAME MPID_Segment_pack_vector
        -:   90:#undef FCNAME
        -:   91:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:   92:/* MPID_Segment_pack_vector
        -:   93:*
        -:   94:* Parameters:
        -:   95:* segp    - pointer to segment structure
        -:   96:* first   - first byte in segment to pack
        -:   97:* lastp   - in/out parameter describing last byte to pack (and afterwards
        -:   98:*           the last byte _actually_ packed)
        -:   99:*           NOTE: actually returns index of byte _after_ last one packed
        -:  100:* vectorp - pointer to (off, len) pairs to fill in
        -:  101:* lengthp - in/out parameter describing length of array (and afterwards
        -:  102:*           the amount of the array that has actual data)
        -:  103:*/
        -:  104:void MPID_Segment_pack_vector(struct DLOOP_Segment *segp,
        -:  105:			  DLOOP_Offset first,
        -:  106:			  DLOOP_Offset *lastp,
        -:  107:			  DLOOP_VECTOR *vectorp,
        -:  108:			  int *lengthp)
   521420:  109:{
        -:  110:struct MPID_Segment_piece_params packvec_params;
        -:  111:MPIDI_STATE_DECL(MPID_STATE_MPID_SEGMENT_PACK_VECTOR);
        -:  112:
        -:  113:MPIDI_FUNC_ENTER(MPID_STATE_MPID_SEGMENT_PACK_VECTOR);
        -:  114:
   521420:  115:packvec_params.u.pack_vector.vectorp = vectorp;
   521420:  116:packvec_params.u.pack_vector.index   = 0;
   521420:  117:packvec_params.u.pack_vector.length  = *lengthp;
        -:  118:
   521420:  119:MPIU_Assert(*lengthp > 0);
        -:  120:
   521420:  121:MPID_Segment_manipulate(segp,
        -:  122:			first,
        -:  123:			lastp,
        -:  124:			MPID_Segment_contig_pack_to_iov,
        -:  125:			MPID_Segment_vector_pack_to_iov,
        -:  126:			NULL, /* blkidx fn */
        -:  127:			NULL, /* index fn */
        -:  128:			NULL,
        -:  129:			&packvec_params);
        -:  130:
        -:  131:/* last value already handled by MPID_Segment_manipulate */
   521420:  132:*lengthp = packvec_params.u.pack_vector.index;
        -:  133:MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_PACK_VECTOR);
        -:  134:return;
        -:  135:}
        -:  136:
        -:  137:/* MPID_Segment_unpack_vector
        -:  138:*
        -:  139:* Q: Should this be any different from pack vector?
        -:  140:*/
        -:  141:#undef FUNCNAME
        -:  142:#define FUNCNAME MPID_Segment_unpack_vector
        -:  143:#undef FCNAME
        -:  144:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  145:void MPID_Segment_unpack_vector(struct DLOOP_Segment *segp,
        -:  146:			    DLOOP_Offset first,
        -:  147:			    DLOOP_Offset *lastp,
        -:  148:			    DLOOP_VECTOR *vectorp,
        -:  149:			    int *lengthp)
   132251:  150:{
        -:  151:MPIDI_STATE_DECL(MPID_STATE_MPID_SEGMENT_UNPACK_VECTOR);
        -:  152:MPIDI_FUNC_ENTER(MPID_STATE_MPID_SEGMENT_UNPACK_VECTOR);
   132251:  153:MPID_Segment_pack_vector(segp, first, lastp, vectorp, lengthp);
        -:  154:MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_UNPACK_VECTOR);
        -:  155:return;
        -:  156:}
        -:  157:
        -:  158:#undef FUNCNAME
        -:  159:#define FUNCNAME MPID_Segment_flatten
        -:  160:#undef FCNAME
        -:  161:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  162:/* MPID_Segment_flatten
        -:  163:*
        -:  164:* offp    - pointer to array to fill in with offsets
        -:  165:* sizep   - pointer to array to fill in with sizes
        -:  166:* lengthp - pointer to value holding size of arrays; # used is returned
        -:  167:*
        -:  168:* Internally, index is used to store the index of next array value to fill in.
        -:  169:*
        -:  170:* TODO: MAKE SIZES Aints IN ROMIO, CHANGE THIS TO USE INTS TOO.
        -:  171:*/
        -:  172:void MPID_Segment_flatten(struct DLOOP_Segment *segp,
        -:  173:		      DLOOP_Offset first,
        -:  174:		      DLOOP_Offset *lastp,
        -:  175:		      DLOOP_Offset *offp,
        -:  176:		      int *sizep,
        -:  177:		      DLOOP_Offset *lengthp)
    #####:  178:{
        -:  179:struct MPID_Segment_piece_params packvec_params;
        -:  180:MPIDI_STATE_DECL(MPID_STATE_MPID_SEGMENT_FLATTEN);
        -:  181:
        -:  182:MPIDI_FUNC_ENTER(MPID_STATE_MPID_SEGMENT_FLATTEN);
        -:  183:
    #####:  184:packvec_params.u.flatten.offp = (int64_t *) offp;
    #####:  185:packvec_params.u.flatten.sizep = sizep;
    #####:  186:packvec_params.u.flatten.index   = 0;
    #####:  187:packvec_params.u.flatten.length  = *lengthp;
        -:  188:
    #####:  189:MPIU_Assert(*lengthp > 0);
        -:  190:
    #####:  191:MPID_Segment_manipulate(segp,
        -:  192:			first,
        -:  193:			lastp,
        -:  194:			MPID_Segment_contig_flatten,
        -:  195:			MPID_Segment_vector_flatten,
        -:  196:			NULL, /* blkidx fn */
        -:  197:			NULL,
        -:  198:			NULL,
        -:  199:			&packvec_params);
        -:  200:
        -:  201:/* last value already handled by MPID_Segment_manipulate */
    #####:  202:*lengthp = packvec_params.u.flatten.index;
        -:  203:MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_FLATTEN);
        -:  204:return;
        -:  205:}
        -:  206:
        -:  207:
        -:  208:/*
        -:  209:* EVERYTHING BELOW HERE IS USED ONLY WITHIN THIS FILE
        -:  210:*/
        -:  211:
        -:  212:/********** FUNCTIONS FOR CREATING AN IOV DESCRIBING BUFFER **********/
        -:  213:
        -:  214:#undef FUNCNAME
        -:  215:#define FUNCNAME MPID_Segment_contig_pack_to_iov
        -:  216:#undef FCNAME
        -:  217:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  218:/* MPID_Segment_contig_pack_to_iov
        -:  219:*/
        -:  220:static int MPID_Segment_contig_pack_to_iov(DLOOP_Offset *blocks_p,
        -:  221:                                           DLOOP_Type el_type,
        -:  222:					   DLOOP_Offset rel_off,
        -:  223:					   void *bufp,
        -:  224:					   void *v_paramp)
   212904:  225:{
        -:  226:    int el_size, last_idx;
        -:  227:    DLOOP_Offset size;
   212904:  228:    char *last_end = NULL;
   212904:  229:    struct MPID_Segment_piece_params *paramp = v_paramp;
        -:  230:    MPIDI_STATE_DECL(MPID_STATE_MPID_SEGMENT_CONTIG_PACK_TO_IOV);
        -:  231:
        -:  232:    MPIDI_FUNC_ENTER(MPID_STATE_MPID_SEGMENT_CONTIG_PACK_TO_IOV);
        -:  233:
   212904:  234:    el_size = MPID_Datatype_get_basic_size(el_type);
   212904:  235:    size = *blocks_p * (DLOOP_Offset) el_size;
        -:  236:
        -:  237:    MPIU_DBG_MSG_FMT(DATATYPE,VERBOSE,(MPIU_DBG_FDEST,
        -:  238:             "\t[contig to vec: do=" MPI_AINT_FMT_DEC_SPEC ", dp=%p, ind=%d, sz=%d, blksz=" MPI_AINT_FMT_DEC_SPEC "]\n",
        -:  239:		    (MPI_Aint) rel_off,
        -:  240:		    bufp,
        -:  241:		    paramp->u.pack_vector.index,
        -:  242:		    el_size,
        -:  243:		    (MPI_Aint) *blocks_p));
        -:  244:
   212904:  245:    last_idx = paramp->u.pack_vector.index - 1;
   212904:  246:    if (last_idx >= 0) {
   180165:  247:	last_end = ((char *) paramp->u.pack_vector.vectorp[last_idx].DLOOP_VECTOR_BUF) +
        -:  248:	    paramp->u.pack_vector.vectorp[last_idx].DLOOP_VECTOR_LEN;
        -:  249:    }
        -:  250:
        -:  251:    MPID_Ensure_Aint_fits_in_pointer((MPI_VOID_PTR_CAST_TO_MPI_AINT (bufp)) + rel_off);
   212904:  252:    if ((last_idx == paramp->u.pack_vector.length-1) &&
        -:  253:	(last_end != ((char *) bufp + rel_off)))
        -:  254:    {
        -:  255:	/* we have used up all our entries, and this region doesn't fit on
        -:  256:	 * the end of the last one.  setting blocks to 0 tells manipulation
        -:  257:	 * function that we are done (and that we didn't process any blocks).
        -:  258:	 */
     8346:  259:	*blocks_p = 0;
        -:  260:	MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_CONTIG_PACK_TO_IOV);
     8346:  261:	return 1;
        -:  262:    }
   230731:  263:    else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off)))
        -:  264:    {
        -:  265:	/* add this size to the last vector rather than using up another one */
    26173:  266:	paramp->u.pack_vector.vectorp[last_idx].DLOOP_VECTOR_LEN += size;
        -:  267:    }
        -:  268:    else {
   178385:  269:	paramp->u.pack_vector.vectorp[last_idx+1].DLOOP_VECTOR_BUF = (char *) bufp + rel_off;
   178385:  270:	paramp->u.pack_vector.vectorp[last_idx+1].DLOOP_VECTOR_LEN = size;
   178385:  271:	paramp->u.pack_vector.index++;
        -:  272:    }
        -:  273:    MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_CONTIG_PACK_TO_IOV);
   204558:  274:    return 0;
        -:  275:}
        -:  276:
        -:  277:#undef FUNCNAME
        -:  278:#define FUNCNAME MPID_Segment_vector_pack_to_iov
        -:  279:#undef FCNAME
        -:  280:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  281:/* MPID_Segment_vector_pack_to_iov
        -:  282: *
        -:  283: * Input Parameters:
        -:  284: * blocks_p - [inout] pointer to a count of blocks (total, for all noncontiguous pieces)
        -:  285: * count    - # of noncontiguous regions
        -:  286: * blksz    - size of each noncontiguous region
        -:  287: * stride   - distance in bytes from start of one region to start of next
        -:  288: * el_type - elemental type (e.g. MPI_INT)
        -:  289: * ...
        -:  290: *
        -:  291: * Note: this is only called when the starting position is at the beginning
        -:  292: * of a whole block in a vector type.
        -:  293: */
        -:  294:static int MPID_Segment_vector_pack_to_iov(DLOOP_Offset *blocks_p,
        -:  295:					   int count,
        -:  296:					   int blksz,
        -:  297:					   DLOOP_Offset stride,
        -:  298:					   DLOOP_Type el_type,
        -:  299:					   DLOOP_Offset rel_off, /* offset into buffer */
        -:  300:					   void *bufp, /* start of buffer */
        -:  301:					   void *v_paramp)
   490023:  302:{
        -:  303:    int i;
        -:  304:    DLOOP_Offset size, blocks_left, basic_size;
   490023:  305:    struct MPID_Segment_piece_params *paramp = v_paramp;
        -:  306:    MPIDI_STATE_DECL(MPID_STATE_MPID_SEGMENT_VECTOR_PACK_TO_IOV);
        -:  307:
        -:  308:    MPIDI_FUNC_ENTER(MPID_STATE_MPID_SEGMENT_VECTOR_PACK_TO_IOV);
        -:  309:
   490023:  310:    basic_size = (DLOOP_Offset) MPID_Datatype_get_basic_size(el_type);
   490023:  311:    blocks_left = *blocks_p;
        -:  312:
        -:  313:    MPIU_DBG_MSG_FMT(DATATYPE,VERBOSE,(MPIU_DBG_FDEST,
        -:  314:             "\t[vector to vec: do=" MPI_AINT_FMT_DEC_SPEC
        -:  315:             ", dp=%p"
        -:  316:             ", len=%d, ind=%d, ct=%d, blksz=%d"
        -:  317:             ", str=" MPI_AINT_FMT_DEC_SPEC
        -:  318:             ", blks=" MPI_AINT_FMT_DEC_SPEC
        -:  319:             "]\n",
        -:  320:		    (MPI_Aint) rel_off,
        -:  321:		    bufp,
        -:  322:		    paramp->u.pack_vector.length,
        -:  323:		    paramp->u.pack_vector.index,
        -:  324:		    count,
        -:  325:		    blksz,
        -:  326:		    (MPI_Aint) stride,
        -:  327:		    (MPI_Aint) *blocks_p));
        -:  328:
  6198481:  329:    for (i=0; i < count && blocks_left > 0; i++) {
        -:  330:	int last_idx;
  5951645:  331:	char *last_end = NULL;
        -:  332:
  5951645:  333:	if (blocks_left > (DLOOP_Offset) blksz) {
  5680646:  334:	    size = ((DLOOP_Offset) blksz) * basic_size;
  5680646:  335:	    blocks_left -= (DLOOP_Offset) blksz;
        -:  336:	}
        -:  337:	else {
        -:  338:	    /* last pass */
   270999:  339:	    size = blocks_left * basic_size;
   270999:  340:	    blocks_left = 0;
        -:  341:	}
        -:  342:
  5951645:  343:	last_idx = paramp->u.pack_vector.index - 1;
  5951645:  344:	if (last_idx >= 0) {
  5462965:  345:	    last_end = ((char *) paramp->u.pack_vector.vectorp[last_idx].DLOOP_VECTOR_BUF) +
        -:  346:		paramp->u.pack_vector.vectorp[last_idx].DLOOP_VECTOR_LEN;
        -:  347:	}
        -:  348:
        -:  349:	MPID_Ensure_Aint_fits_in_pointer((MPI_VOID_PTR_CAST_TO_MPI_AINT (bufp)) + rel_off);
  5951645:  350:	if ((last_idx == paramp->u.pack_vector.length-1) &&
        -:  351:	    (last_end != ((char *) bufp + rel_off)))
        -:  352:	{
        -:  353:	    /* we have used up all our entries, and this one doesn't fit on
        -:  354:	     * the end of the last one.
        -:  355:	     */
   243187:  356:	    *blocks_p -= (blocks_left + (size / basic_size));
        -:  357:#if 0
        -:  358:	    paramp->u.pack_vector.index++;
        -:  359:#endif
        -:  360:#ifdef MPID_SP_VERBOSE
        -:  361:	    MPIU_dbg_printf("\t[vector to vec exiting (1): next ind = %d, " MPI_AINT_FMT_DEC_SPEC " blocks processed.\n",
        -:  362:			    paramp->u.pack_vector.index,
        -:  363:			    (MPI_Aint) *blocks_p);
        -:  364:#endif
        -:  365:	    MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_VECTOR_PACK_TO_IOV);
   243187:  366:	    return 1;
        -:  367:	}
  5708653:  368:	else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off)))
        -:  369:	{
        -:  370:	    /* add this size to the last vector rather than using up new one */
      195:  371:	    paramp->u.pack_vector.vectorp[last_idx].DLOOP_VECTOR_LEN += size;
        -:  372:	}
        -:  373:	else {
  5708263:  374:	    paramp->u.pack_vector.vectorp[last_idx+1].DLOOP_VECTOR_BUF =
        -:  375:		(char *) bufp + rel_off;
  5708263:  376:	    paramp->u.pack_vector.vectorp[last_idx+1].DLOOP_VECTOR_LEN = size;
  5708263:  377:	    paramp->u.pack_vector.index++;
        -:  378:	}
        -:  379:
  5708458:  380:	rel_off += stride;
        -:  381:
        -:  382:    }
        -:  383:
        -:  384:#ifdef MPID_SP_VERBOSE
        -:  385:    MPIU_dbg_printf("\t[vector to vec exiting (2): next ind = %d, " MPI_AINT_FMT_DEC_SPEC " blocks processed.\n",
        -:  386:		    paramp->u.pack_vector.index,
        -:  387:		    (MPI_Aint) *blocks_p);
        -:  388:#endif
        -:  389:
        -:  390:    /* if we get here then we processed ALL the blocks; don't need to update
        -:  391:     * blocks_p
        -:  392:     */
   246836:  393:    MPIU_Assert(blocks_left == 0);
        -:  394:    MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_VECTOR_PACK_TO_IOV);
   246836:  395:    return 0;
        -:  396:}
        -:  397:
        -:  398:/********** FUNCTIONS FOR FLATTENING A TYPE **********/
        -:  399:
        -:  400:#undef FUNCNAME
        -:  401:#define FUNCNAME MPID_Segment_contig_flatten
        -:  402:#undef FCNAME
        -:  403:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  404:/* MPID_Segment_contig_flatten
        -:  405: */
        -:  406:static int MPID_Segment_contig_flatten(DLOOP_Offset *blocks_p,
        -:  407:				       DLOOP_Type el_type,
        -:  408:				       DLOOP_Offset rel_off,
        -:  409:				       void *bufp,
        -:  410:				       void *v_paramp)
    #####:  411:{
        -:  412:    int index, el_size;
        -:  413:    DLOOP_Offset size;
    #####:  414:    struct MPID_Segment_piece_params *paramp = v_paramp;
        -:  415:    MPIDI_STATE_DECL(MPID_STATE_MPID_SEGMENT_CONTIG_FLATTEN);
        -:  416:
        -:  417:    MPIDI_FUNC_ENTER(MPID_STATE_MPID_SEGMENT_CONTIG_FLATTEN);
        -:  418:
    #####:  419:    el_size = MPID_Datatype_get_basic_size(el_type);
    #####:  420:    size = *blocks_p * (DLOOP_Offset) el_size;
    #####:  421:    index = paramp->u.flatten.index;
        -:  422:
        -:  423:#ifdef MPID_SP_VERBOSE
        -:  424:    MPIU_dbg_printf("\t[contig flatten: index = %d, loc = (" MPI_AINT_FMT_HEX_SPEC " + " MPI_AINT_FMT_HEX_SPEC ") = " MPI_AINT_FMT_HEX_SPEC ", size = " MPI_AINT_FMT_DEC_SPEC "]\n",
        -:  425:		    index,
        -:  426:		    MPI_VOID_PTR_CAST_TO_MPI_AINT bufp,
        -:  427:		    (MPI_Aint) rel_off,
        -:  428:		    MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off,
        -:  429:		    (MPI_Aint) size);
        -:  430:#endif
        -:  431:
    #####:  432:    if (index > 0 && ((DLOOP_Offset) MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off) ==
        -:  433:	((paramp->u.flatten.offp[index - 1]) +
        -:  434:	 (DLOOP_Offset) paramp->u.flatten.sizep[index - 1]))
        -:  435:    {
        -:  436:	/* add this size to the last vector rather than using up another one */
    #####:  437:	paramp->u.flatten.sizep[index - 1] += size;
        -:  438:    }
        -:  439:    else {
    #####:  440:	paramp->u.flatten.offp[index] =  ((int64_t) MPI_VOID_PTR_CAST_TO_MPI_AINT bufp) + (int64_t) rel_off;
    #####:  441:	paramp->u.flatten.sizep[index] = size;
        -:  442:
    #####:  443:	paramp->u.flatten.index++;
        -:  444:	/* check to see if we have used our entire vector buffer, and if so
        -:  445:	 * return 1 to stop processing
        -:  446:	 */
    #####:  447:	if (paramp->u.flatten.index == paramp->u.flatten.length)
        -:  448:	{
        -:  449:	    MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_CONTIG_FLATTEN);
    #####:  450:	    return 1;
        -:  451:	}
        -:  452:    }
        -:  453:    MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_CONTIG_FLATTEN);
    #####:  454:    return 0;
        -:  455:}
        -:  456:
        -:  457:#undef FUNCNAME
        -:  458:#define FUNCNAME MPID_Segment_vector_flatten
        -:  459:#undef FCNAME
        -:  460:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  461:/* MPID_Segment_vector_flatten
        -:  462: *
        -:  463: * Notes:
        -:  464: * - this is only called when the starting position is at the beginning
        -:  465: *   of a whole block in a vector type.
        -:  466: * - this was a virtual copy of MPID_Segment_pack_to_iov; now it has improvements
        -:  467: *   that MPID_Segment_pack_to_iov needs.
        -:  468: * - we return the number of blocks that we did process in region pointed to by
        -:  469: *   blocks_p.
        -:  470: */
        -:  471:static int MPID_Segment_vector_flatten(DLOOP_Offset *blocks_p,
        -:  472:				       int count,
        -:  473:				       int blksz,
        -:  474:				       DLOOP_Offset stride,
        -:  475:				       DLOOP_Type el_type,
        -:  476:				       DLOOP_Offset rel_off, /* offset into buffer */
        -:  477:				       void *bufp, /* start of buffer */
        -:  478:				       void *v_paramp)
    #####:  479:{
        -:  480:    int i;
        -:  481:    DLOOP_Offset size, blocks_left, basic_size;
    #####:  482:    struct MPID_Segment_piece_params *paramp = v_paramp;
        -:  483:    MPIDI_STATE_DECL(MPID_STATE_MPID_SEGMENT_VECTOR_FLATTEN);
        -:  484:
        -:  485:    MPIDI_FUNC_ENTER(MPID_STATE_MPID_SEGMENT_VECTOR_FLATTEN);
        -:  486:
    #####:  487:    basic_size = (DLOOP_Offset) MPID_Datatype_get_basic_size(el_type);
    #####:  488:    blocks_left = *blocks_p;
        -:  489:
    #####:  490:    for (i=0; i < count && blocks_left > 0; i++) {
    #####:  491:	int index = paramp->u.flatten.index;
        -:  492:
    #####:  493:	if (blocks_left > (DLOOP_Offset) blksz) {
    #####:  494:	    size = ((DLOOP_Offset) blksz) * basic_size;
    #####:  495:	    blocks_left -= (DLOOP_Offset) blksz;
        -:  496:	}
        -:  497:	else {
        -:  498:	    /* last pass */
    #####:  499:	    size = blocks_left * basic_size;
    #####:  500:	    blocks_left = 0;
        -:  501:	}
        -:  502:
    #####:  503:	if (index > 0 && ((DLOOP_Offset) MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off) ==
        -:  504:	    ((paramp->u.flatten.offp[index - 1]) + (DLOOP_Offset) paramp->u.flatten.sizep[index - 1]))
        -:  505:	{
        -:  506:	    /* add this size to the last region rather than using up another one */
    #####:  507:	    paramp->u.flatten.sizep[index - 1] += size;
        -:  508:	}
    #####:  509:	else if (index < paramp->u.flatten.length) {
        -:  510:	    /* take up another region */
    #####:  511:	    paramp->u.flatten.offp[index]  = (DLOOP_Offset) MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off;
    #####:  512:	    paramp->u.flatten.sizep[index] = size;
    #####:  513:	    paramp->u.flatten.index++;
        -:  514:	}
        -:  515:	else {
        -:  516:	    /* we tried to add to the end of the last region and failed; add blocks back in */
    #####:  517:	    *blocks_p = *blocks_p - blocks_left + (size / basic_size);
        -:  518:	    MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_VECTOR_FLATTEN);
    #####:  519:	    return 1;
        -:  520:	}
    #####:  521:	rel_off += stride;
        -:  522:
        -:  523:    }
        -:  524:    /* --BEGIN ERROR HANDLING-- */
    #####:  525:    MPIU_Assert(blocks_left == 0);
        -:  526:    /* --END ERROR HANDLING-- */
        -:  527:    MPIDI_FUNC_EXIT(MPID_STATE_MPID_SEGMENT_VECTOR_FLATTEN);
    #####:  528:    return 0;
        -:  529:}