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