00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <sys/types.h>
00012 
00013 #include "./dataloop.h"
00014 
00015 
00016 
00017 #ifdef HAVE_ANY_INT64_T_ALIGNEMENT
00018 #define MPIR_ALIGN8_TEST(p1,p2)
00019 #else
00020 #define MPIR_ALIGN8_TEST(p1,p2) && ((((MPI_Aint)p1 | (MPI_Aint)p2) & 0x7) == 0)
00021 #endif
00022 
00023 #ifdef HAVE_ANY_INT32_T_ALIGNEMENT
00024 #define MPIR_ALIGN4_TEST(p1,p2)
00025 #else
00026 #define MPIR_ALIGN4_TEST(p1,p2) && ((((MPI_Aint)p1 | (MPI_Aint)p2) & 0x3) == 0)
00027 #endif
00028 
00029 #define MPIDI_COPY_FROM_VEC(src,dest,stride,type,nelms,count)   \
00030 {                               \
00031     type * l_src = (type *)src, * l_dest = (type *)dest;    \
00032     int i, j;                           \
00033     const int l_stride = stride;                \
00034     if (nelms == 1) {                       \
00035         for (i=count;i!=0;i--) {                \
00036             *l_dest++ = *l_src;                 \
00037             l_src = (type *) ((char *) l_src + l_stride);   \
00038         }                           \
00039     }                               \
00040     else {                          \
00041         for (i=count; i!=0; i--) {              \
00042             for (j=0; j<nelms; j++) {               \
00043                 *l_dest++ = l_src[j];               \
00044         }                           \
00045             l_src = (type *) ((char *) l_src + l_stride);   \
00046         }                           \
00047     }                               \
00048     dest = (char *) l_dest;                 \
00049     src  = (char *) l_src;                                      \
00050 }
00051 
00052 #define MPIDI_COPY_TO_VEC(src,dest,stride,type,nelms,count) \
00053 {                               \
00054     type * l_src = (type *)src, * l_dest = (type *)dest;    \
00055     int i, j;                           \
00056     const int l_stride = stride;                \
00057     if (nelms == 1) {                       \
00058         for (i=count;i!=0;i--) {                \
00059             *l_dest = *l_src++;                 \
00060             l_dest = (type *) ((char *) l_dest + l_stride); \
00061         }                           \
00062     }                               \
00063     else {                          \
00064         for (i=count; i!=0; i--) {              \
00065             for (j=0; j<nelms; j++) {               \
00066                 l_dest[j] = *l_src++;               \
00067         }                           \
00068             l_dest = (type *) ((char *) l_dest + l_stride); \
00069         }                           \
00070     }                               \
00071     dest = (char *) l_dest;                 \
00072     src  = (char *) l_src;                                      \
00073 }
00074 
00075 
00076 
00077 int PREPEND_PREFIX(Segment_contig_m2m)(DLOOP_Offset *blocks_p,
00078                        DLOOP_Type    el_type,
00079                        DLOOP_Offset  rel_off,
00080                        DLOOP_Buffer  unused,
00081                        void         *v_paramp)
00082 {
00083     DLOOP_Offset el_size; 
00084     DLOOP_Offset size;
00085     struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp;
00086 
00087     DLOOP_Handle_get_size_macro(el_type, el_size);
00088     size = *blocks_p * el_size;
00089 
00090 #ifdef MPID_SU_VERBOSE
00091     dbg_printf("\t[contig unpack: do=%d, dp=%x, bp=%x, sz=%d, blksz=%d]\n",
00092            rel_off, 
00093            (unsigned) bufp,
00094            (unsigned) paramp->u.unpack.unpack_buffer,
00095            el_size,
00096            (int) *blocks_p);
00097 #endif
00098 
00099     if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
00100     memcpy((char *) (paramp->userbuf + rel_off), paramp->streambuf, size);
00101     }
00102     else {
00103     memcpy(paramp->streambuf, (char *) (paramp->userbuf + rel_off), size);
00104     }
00105     paramp->streambuf += size;
00106     return 0;
00107 }
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
00117                        DLOOP_Count   unused,
00118                        DLOOP_Count   blksz,
00119                        DLOOP_Offset  stride,
00120                        DLOOP_Type    el_type,
00121                        DLOOP_Offset  rel_off, 
00122                        DLOOP_Buffer  unused2,
00123                        void         *v_paramp)
00124 {
00125     DLOOP_Count i, blocks_left, whole_count;
00126     DLOOP_Offset el_size;
00127     struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp;
00128     char *cbufp;
00129 
00130     cbufp = paramp->userbuf + rel_off;
00131     DLOOP_Handle_get_size_macro(el_type, el_size);
00132 
00133     whole_count = (blksz > 0) ? (*blocks_p / blksz) : 0;
00134     blocks_left = (blksz > 0) ? (*blocks_p % blksz) : 0;
00135 
00136     if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
00137     if (el_size == 8 
00138         MPIR_ALIGN8_TEST(paramp->streambuf,cbufp))
00139     {
00140         MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, stride,
00141                   int64_t, blksz, whole_count);
00142         MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0,
00143                   int64_t, blocks_left, 1);
00144     }
00145     else if (el_size == 4
00146          MPIR_ALIGN4_TEST(paramp->streambuf,cbufp))
00147     {
00148         MPIDI_COPY_TO_VEC((paramp->streambuf), cbufp, stride,
00149                   int32_t, blksz, whole_count);
00150         MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0,
00151                   int32_t, blocks_left, 1);
00152     }
00153     else if (el_size == 2) {
00154         MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, stride,
00155                   int16_t, blksz, whole_count);
00156         MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0,
00157                   int16_t, blocks_left, 1);
00158     }
00159     else {
00160         for (i=0; i < whole_count; i++) {
00161         memcpy(cbufp, paramp->streambuf, blksz * el_size);
00162         paramp->streambuf += blksz * el_size;
00163         cbufp += stride;
00164         }
00165         if (blocks_left) {
00166         memcpy(cbufp, paramp->streambuf, blocks_left * el_size);
00167         paramp->streambuf += blocks_left * el_size;
00168         }
00169     }
00170     }
00171     else  {
00172     if (el_size == 8 
00173         MPIR_ALIGN8_TEST(cbufp,paramp->streambuf))
00174     {
00175         MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride,
00176                 int64_t, blksz, whole_count);
00177         MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0,
00178                 int64_t, blocks_left, 1);
00179     }
00180     else if (el_size == 4
00181          MPIR_ALIGN4_TEST(cbufp,paramp->streambuf))
00182     {
00183         MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride,
00184                 int32_t, blksz, whole_count);
00185         MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0,
00186                 int32_t, blocks_left, 1);
00187     }
00188     else if (el_size == 2) {
00189         MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride,
00190                 int16_t, blksz, whole_count);
00191         MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0,
00192                 int16_t, blocks_left, 1);
00193     }
00194     else {
00195         for (i=0; i < whole_count; i++) {
00196         memcpy(paramp->streambuf, cbufp, blksz * el_size);
00197         paramp->streambuf += blksz * el_size;
00198         cbufp += stride;
00199         }
00200         if (blocks_left) {
00201         memcpy(paramp->streambuf, cbufp, blocks_left * el_size);
00202         paramp->streambuf += blocks_left * el_size;
00203         }
00204     }
00205     }
00206 
00207     return 0;
00208 }
00209 
00210 
00211 
00212 int PREPEND_PREFIX(Segment_blkidx_m2m)(DLOOP_Offset *blocks_p,
00213                        DLOOP_Count   count,
00214                        DLOOP_Count   blocklen,
00215                        DLOOP_Offset *offsetarray,
00216                        DLOOP_Type    el_type,
00217                        DLOOP_Offset  rel_off,
00218                        DLOOP_Buffer  unused,
00219                        void         *v_paramp)
00220 {
00221     DLOOP_Count curblock = 0;
00222     DLOOP_Offset el_size;
00223     DLOOP_Offset blocks_left = *blocks_p;
00224     char *cbufp;
00225     struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp;
00226 
00227     DLOOP_Handle_get_size_macro(el_type, el_size);
00228 
00229     while (blocks_left) {
00230     char *src, *dest;
00231 
00232     DLOOP_Assert(curblock < count);
00233 
00234     cbufp = paramp->userbuf + rel_off + offsetarray[curblock];
00235 
00236     if (blocklen > blocks_left) blocklen = blocks_left;
00237 
00238     if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
00239         src  = paramp->streambuf;
00240         dest = cbufp;
00241     }
00242     else {
00243         src  = cbufp;
00244         dest = paramp->streambuf;
00245     }
00246 
00247     
00248     if (el_size == 8
00249         MPIR_ALIGN8_TEST(src, dest))
00250     {
00251         MPIDI_COPY_FROM_VEC(src, dest, 0, int64_t, blocklen, 1);
00252     }
00253     else if (el_size == 4
00254          MPIR_ALIGN4_TEST(src,dest))
00255     {
00256         MPIDI_COPY_FROM_VEC(src, dest, 0, int32_t, blocklen, 1);
00257     }
00258     else if (el_size == 2) {
00259         MPIDI_COPY_FROM_VEC(src, dest, 0, int16_t, blocklen, 1);
00260     }
00261     else {
00262         memcpy(dest, src, blocklen * el_size);
00263     }
00264 
00265     paramp->streambuf += blocklen * el_size;
00266     blocks_left -= blocklen;
00267     curblock++;
00268     }
00269 
00270     return 0;
00271 }
00272 
00273 
00274 
00275 int PREPEND_PREFIX(Segment_index_m2m)(DLOOP_Offset *blocks_p,
00276                       DLOOP_Count   count,
00277                       DLOOP_Count  *blockarray,
00278                       DLOOP_Offset *offsetarray,
00279                       DLOOP_Type    el_type,
00280                       DLOOP_Offset  rel_off,
00281                       DLOOP_Buffer  unused,
00282                       void         *v_paramp)
00283 {
00284     int curblock = 0;
00285     DLOOP_Offset el_size;
00286     DLOOP_Offset cur_block_sz, blocks_left = *blocks_p;
00287     char *cbufp;
00288     struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp;
00289 
00290     DLOOP_Handle_get_size_macro(el_type, el_size);
00291 
00292     while (blocks_left) {
00293     char *src, *dest;
00294 
00295     DLOOP_Assert(curblock < count);
00296     cur_block_sz = blockarray[curblock];
00297 
00298     cbufp = paramp->userbuf + rel_off + offsetarray[curblock];
00299 
00300     if (cur_block_sz > blocks_left) cur_block_sz = blocks_left;
00301 
00302     if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
00303         src  = paramp->streambuf;
00304         dest = cbufp;
00305     }
00306     else {
00307         src  = cbufp;
00308         dest = paramp->streambuf;
00309     }
00310 
00311     
00312     if (el_size == 8
00313         MPIR_ALIGN8_TEST(src, dest))
00314     {
00315         MPIDI_COPY_FROM_VEC(src, dest, 0, int64_t, cur_block_sz, 1);
00316     }
00317     else if (el_size == 4
00318          MPIR_ALIGN4_TEST(src,dest))
00319     {
00320         MPIDI_COPY_FROM_VEC(src, dest, 0, int32_t, cur_block_sz, 1);
00321     }
00322     else if (el_size == 2) {
00323         MPIDI_COPY_FROM_VEC(src, dest, 0, int16_t, cur_block_sz, 1);
00324     }
00325     else {
00326         memcpy(dest, src, cur_block_sz * el_size);
00327     }
00328 
00329     paramp->streambuf += cur_block_sz * el_size;
00330     blocks_left -= cur_block_sz;
00331     curblock++;
00332     }
00333 
00334     return 0;
00335 }
00336 
00337 void PREPEND_PREFIX(Segment_pack)(DLOOP_Segment *segp,
00338                   DLOOP_Offset   first,
00339                   DLOOP_Offset  *lastp,
00340                   void          *streambuf)
00341 {
00342     struct PREPEND_PREFIX(m2m_params) params;
00343 
00344     
00345 
00346 
00347 
00348     params.userbuf   = segp->ptr;
00349     params.streambuf = streambuf;
00350     params.direction = DLOOP_M2M_FROM_USERBUF;
00351 
00352     PREPEND_PREFIX(Segment_manipulate)(segp, first, lastp,
00353                        PREPEND_PREFIX(Segment_contig_m2m),
00354                        PREPEND_PREFIX(Segment_vector_m2m),
00355                        PREPEND_PREFIX(Segment_blkidx_m2m),
00356                        PREPEND_PREFIX(Segment_index_m2m),
00357                        NULL, 
00358                        ¶ms);
00359     return;
00360 }
00361 
00362 void PREPEND_PREFIX(Segment_unpack)(DLOOP_Segment *segp,
00363                     DLOOP_Offset   first,
00364                     DLOOP_Offset  *lastp,
00365                     void *streambuf)
00366 {
00367     struct PREPEND_PREFIX(m2m_params) params;
00368 
00369     params.userbuf   = segp->ptr;
00370     params.streambuf = streambuf;
00371     params.direction = DLOOP_M2M_TO_USERBUF;
00372 
00373     PREPEND_PREFIX(Segment_manipulate)(segp, first, lastp,
00374                        PREPEND_PREFIX(Segment_contig_m2m),
00375                        PREPEND_PREFIX(Segment_vector_m2m),
00376                        PREPEND_PREFIX(Segment_blkidx_m2m),
00377                        PREPEND_PREFIX(Segment_index_m2m),
00378                        NULL, 
00379                        ¶ms);
00380     return;
00381 }
00382 
00383 struct PREPEND_PREFIX(contig_blocks_params) {
00384     DLOOP_Count  count;
00385     DLOOP_Offset last_loc;
00386 };
00387 
00388 
00389 
00390 
00391 
00392 
00393 static int DLOOP_Segment_contig_count_block(DLOOP_Offset *blocks_p,
00394                         DLOOP_Type    el_type,
00395                         DLOOP_Offset  rel_off,
00396                         DLOOP_Buffer  unused,
00397                         void         *v_paramp)
00398 {
00399     DLOOP_Offset size, el_size;
00400     struct PREPEND_PREFIX(contig_blocks_params) *paramp = v_paramp;
00401 
00402     DLOOP_Assert(*blocks_p > 0);
00403 
00404     DLOOP_Handle_get_size_macro(el_type, el_size);
00405     size = *blocks_p * el_size;
00406 
00407 #ifdef MPID_SP_VERBOSE
00408     MPIU_dbg_printf("contig count block: count = %d, buf+off = %d, lastloc = %d\n",
00409             (int) paramp->count,
00410             (int) ((char *) bufp + rel_off),
00411             (int) paramp->last_loc);
00412 #endif
00413 
00414     if (paramp->count > 0 && rel_off == paramp->last_loc)
00415     {
00416     
00417     paramp->last_loc += size;
00418     }
00419     else {
00420     
00421     paramp->last_loc = rel_off + size;
00422     paramp->count++;
00423     }
00424     return 0;
00425 }
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 static int DLOOP_Segment_vector_count_block(DLOOP_Offset *blocks_p,
00441                         DLOOP_Count   count,
00442                         DLOOP_Count   blksz,
00443                         DLOOP_Offset  stride,
00444                         DLOOP_Type    el_type,
00445                         DLOOP_Offset  rel_off, 
00446                         DLOOP_Buffer  unused,
00447                         void         *v_paramp)
00448 {
00449     DLOOP_Count new_blk_count;
00450     DLOOP_Offset size, el_size;
00451     struct PREPEND_PREFIX(contig_blocks_params) *paramp = v_paramp;
00452 
00453     DLOOP_Assert(count > 0 && blksz > 0 && *blocks_p > 0);
00454 
00455     DLOOP_Handle_get_size_macro(el_type, el_size);
00456     size = el_size * blksz;
00457     new_blk_count = count;
00458 
00459     
00460     if (size == stride) new_blk_count = 1;
00461 
00462     if (paramp->count > 0 && rel_off == paramp->last_loc)
00463     {
00464     
00465     new_blk_count--;
00466     }
00467 
00468     paramp->last_loc = rel_off + (count-1) * stride + size;
00469     paramp->count += new_blk_count;
00470     return 0;
00471 }
00472 
00473 
00474 
00475 
00476 
00477 
00478 static int DLOOP_Segment_blkidx_count_block(DLOOP_Offset *blocks_p,
00479                         DLOOP_Count   count,
00480                         DLOOP_Count   blksz,
00481                         DLOOP_Offset *offsetarray,
00482                         DLOOP_Type    el_type,
00483                         DLOOP_Offset  rel_off,
00484                         DLOOP_Buffer  unused,
00485                         void         *v_paramp)
00486 {
00487     DLOOP_Count i, new_blk_count;
00488     DLOOP_Offset size, el_size, last_loc;
00489     struct PREPEND_PREFIX(contig_blocks_params) *paramp = v_paramp;
00490 
00491     DLOOP_Assert(count > 0 && blksz > 0 && *blocks_p > 0);
00492 
00493     DLOOP_Handle_get_size_macro(el_type, el_size);
00494     size = el_size * blksz;
00495     new_blk_count = count;
00496 
00497     if (paramp->count > 0 && rel_off == paramp->last_loc)
00498     {
00499     
00500     new_blk_count--;
00501     }
00502 
00503     last_loc = rel_off + offsetarray[0] + size;
00504     for (i=1; i < count; i++) {
00505     if (last_loc == rel_off + offsetarray[i]) new_blk_count--;
00506 
00507     last_loc = rel_off + offsetarray[i] + size;
00508     }
00509 
00510     paramp->last_loc = last_loc;
00511     paramp->count += new_blk_count;
00512     return 0;
00513 }
00514 
00515 
00516 
00517 
00518 
00519 
00520 static int DLOOP_Segment_index_count_block(DLOOP_Offset *blocks_p,
00521                        DLOOP_Count   count,
00522                        DLOOP_Count  *blockarray,
00523                        DLOOP_Offset *offsetarray,
00524                        DLOOP_Type    el_type,
00525                        DLOOP_Offset  rel_off,
00526                        DLOOP_Buffer  unused,
00527                        void         *v_paramp)
00528 {
00529     DLOOP_Count new_blk_count;
00530     DLOOP_Offset el_size, last_loc;
00531     struct PREPEND_PREFIX(contig_blocks_params) *paramp = v_paramp;
00532 
00533     DLOOP_Assert(count > 0 && *blocks_p > 0);
00534 
00535     DLOOP_Handle_get_size_macro(el_type, el_size);
00536     new_blk_count = count;
00537 
00538     if (paramp->count > 0 && rel_off == paramp->last_loc)
00539     {
00540     
00541     new_blk_count--;
00542     }
00543 
00544     
00545 
00546 
00547 
00548 
00549 
00550 
00551     last_loc = rel_off + offsetarray[count-1] + blockarray[count-1] * el_size;
00552 
00553     paramp->last_loc = last_loc;
00554     paramp->count += new_blk_count;
00555     return 0;
00556 }
00557 
00558 
00559 
00560 
00561 
00562 void PREPEND_PREFIX(Segment_count_contig_blocks)(DLOOP_Segment *segp,
00563                          DLOOP_Offset   first,
00564                          DLOOP_Offset  *lastp,
00565                          DLOOP_Count   *countp)
00566 {
00567     struct PREPEND_PREFIX(contig_blocks_params) params;
00568 
00569     params.count    = 0;
00570     params.last_loc = 0;
00571 
00572     PREPEND_PREFIX(Segment_manipulate)(segp,
00573                        first,
00574                        lastp,
00575                        DLOOP_Segment_contig_count_block,
00576                        DLOOP_Segment_vector_count_block,
00577                        DLOOP_Segment_blkidx_count_block,
00578                        DLOOP_Segment_index_count_block,
00579                        NULL, 
00580                        (void *) ¶ms);
00581 
00582     *countp = params.count;
00583     return;
00584 }
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 struct PREPEND_PREFIX(mpi_flatten_params) {
00600     int       index, length;
00601     MPI_Aint  last_end;
00602     int      *blklens;
00603     MPI_Aint *disps;
00604 };
00605 
00606 
00607 
00608 
00609 static int DLOOP_Segment_contig_mpi_flatten(DLOOP_Offset *blocks_p,
00610                         DLOOP_Type    el_type,
00611                         DLOOP_Offset  rel_off,
00612                         DLOOP_Buffer  bufp,
00613                         void         *v_paramp)
00614 {
00615     int last_idx, size;
00616     DLOOP_Offset el_size;
00617     char *last_end = NULL;
00618     struct PREPEND_PREFIX(mpi_flatten_params) *paramp = v_paramp;
00619 
00620     DLOOP_Handle_get_size_macro(el_type, el_size);
00621     size = *blocks_p * (int) el_size;
00622     
00623     last_idx = paramp->index - 1;
00624     if (last_idx >= 0) {
00625     last_end = ((char *) paramp->disps[last_idx]) +
00626         paramp->blklens[last_idx];
00627     }
00628 
00629     if ((last_idx == paramp->length-1) &&
00630     (last_end != ((char *) bufp + rel_off)))
00631     {
00632     
00633 
00634 
00635 
00636     *blocks_p = 0;
00637     return 1;
00638     }
00639     else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off)))
00640     {
00641     
00642     paramp->blklens[last_idx] += size;
00643     }
00644     else {
00645     paramp->disps[last_idx+1]   = (MPI_Aint) ((char *) bufp + rel_off);
00646     paramp->blklens[last_idx+1] = size;
00647     paramp->index++;
00648     }
00649     return 0;
00650 }
00651 
00652 
00653 
00654 
00655 
00656 
00657 
00658 
00659 
00660 
00661 
00662 
00663 
00664 
00665 
00666 
00667 
00668 static int DLOOP_Segment_vector_mpi_flatten(DLOOP_Offset *blocks_p,
00669                         DLOOP_Count   count,
00670                         DLOOP_Count   blksz,
00671                         DLOOP_Offset  stride,
00672                         DLOOP_Type    el_type,
00673                         DLOOP_Offset  rel_off, 
00674                         DLOOP_Buffer  bufp, 
00675                         void         *v_paramp)
00676 {
00677     int i, size, blocks_left;
00678     DLOOP_Offset el_size;
00679     struct PREPEND_PREFIX(mpi_flatten_params) *paramp = v_paramp;
00680 
00681     DLOOP_Handle_get_size_macro(el_type, el_size);
00682     blocks_left = *blocks_p;
00683 
00684     for (i=0; i < count && blocks_left > 0; i++) {
00685     int last_idx;
00686     char *last_end = NULL;
00687 
00688     if (blocks_left > blksz) {
00689         size = blksz * (int) el_size;
00690         blocks_left -= blksz;
00691     }
00692     else {
00693         
00694         size = blocks_left * (int) el_size;
00695         blocks_left = 0;
00696     }
00697 
00698     last_idx = paramp->index - 1;
00699     if (last_idx >= 0) {
00700         last_end = ((char *) paramp->disps[last_idx]) +
00701         paramp->blklens[last_idx];
00702     }
00703 
00704     if ((last_idx == paramp->length-1) &&
00705         (last_end != ((char *) bufp + rel_off)))
00706     {
00707         
00708 
00709 
00710         *blocks_p -= (blocks_left + (size / (int) el_size));
00711 #ifdef MPID_SP_VERBOSE
00712         MPIU_dbg_printf("\t[vector to vec exiting (1): next ind = %d, %d blocks processed.\n",
00713                 paramp->u.pack_vector.index,
00714                 (int) *blocks_p);
00715 #endif
00716         return 1;
00717     }
00718     else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off)))
00719     {
00720         
00721         paramp->blklens[last_idx] += size;
00722     }
00723     else {
00724         paramp->disps[last_idx+1]   = (MPI_Aint) ((char *) bufp + rel_off);
00725         paramp->blklens[last_idx+1] = size;
00726         paramp->index++;
00727     }
00728 
00729     rel_off += stride;
00730     }
00731 
00732 #ifdef MPID_SP_VERBOSE
00733     MPIU_dbg_printf("\t[vector to vec exiting (2): next ind = %d, %d blocks processed.\n",
00734             paramp->u.pack_vector.index,
00735             (int) *blocks_p);
00736 #endif
00737 
00738     
00739 
00740 
00741 
00742     DLOOP_Assert(blocks_left == 0);
00743     return 0;
00744 }
00745 
00746 
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 
00756 
00757 
00758 
00759 void PREPEND_PREFIX(Segment_mpi_flatten)(DLOOP_Segment *segp,
00760                      DLOOP_Offset   first,
00761                      DLOOP_Offset  *lastp,
00762                      int           *blklens,
00763                      MPI_Aint      *disps,
00764                      int           *lengthp)
00765 {
00766     struct PREPEND_PREFIX(mpi_flatten_params) params;
00767 
00768     DLOOP_Assert(*lengthp > 0);
00769 
00770     params.index   = 0;
00771     params.length  = *lengthp;
00772     params.blklens = blklens;
00773     params.disps   = disps;
00774 
00775     PREPEND_PREFIX(Segment_manipulate)(segp,
00776                        first,
00777                        lastp, 
00778                        DLOOP_Segment_contig_mpi_flatten, 
00779                        DLOOP_Segment_vector_mpi_flatten,
00780                        NULL, 
00781                        NULL, 
00782                        NULL,
00783                        ¶ms);
00784 
00785     
00786     *lengthp = params.index;
00787     return;
00788 }
00789 
00790 
00791 
00792 
00793 
00794