1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #ifndef MPIR_DATATYPE_H_INCLUDED
7 #define MPIR_DATATYPE_H_INCLUDED
8 
9 /* This value should be set to greatest value used as the type index suffix in
10  * the predefined handles.  That is, look at the last two hex digits of all
11  * predefined datatype handles, take the greatest one, and convert it to decimal
12  * here. */
13 /* FIXME: I will fix this by refactor the current datatype code out-of configure.ac */
14 #define MPIR_DATATYPE_N_BUILTIN 71
15 #define MPIR_DATATYPE_PAIRTYPE 5
16 #define MPIR_DATATYPE_N_PREDEFINED (MPIR_DATATYPE_N_BUILTIN + MPIR_DATATYPE_PAIRTYPE)
17 
18 #ifndef MPIR_DATATYPE_PREALLOC
19 #define MPIR_DATATYPE_PREALLOC 8
20 #endif /* MPIR_DATATYPE_PREALLOC */
21 
22 /*S
23   MPIR_Datatype_contents - Holds envelope and contents data for a given
24                            datatype
25 
26   Notes:
27   Space is allocated beyond the structure itself in order to hold the
28   arrays of types, ints, and aints, in that order.
29 
30   S*/
31 typedef struct MPIR_Datatype_contents {
32     int combiner;
33     int nr_ints;
34     int nr_aints;
35     int nr_types;
36     /* space allocated beyond structure used to store the types[],
37      * ints[], and aints[], in that order.
38      */
39 } MPIR_Datatype_contents;
40 
41 /* Datatype Structure */
42 /*S
43   MPIR_Datatype - Description of the MPID Datatype structure
44 
45   Notes:
46   The 'ref_count' is needed for nonblocking operations such as
47 .vb
48    MPI_Type_struct(... , &newtype);
49    MPI_Irecv(buf, 1000, newtype, ..., &request);
50    MPI_Type_free(&newtype);
51    ...
52    MPI_Wait(&request, &status);
53 .ve
54 
55   Module:
56   Datatype-DS
57 
58   Notes:
59 
60   Alternatives:
61   The following alternatives for the layout of this structure were considered.
62   Most were not chosen because any benefit in performance or memory
63   efficiency was outweighed by the added complexity of the implementation.
64 
65   A number of fields contain only boolean inforation ('is_contig',
66   'is_committed').  These
67   could be combined and stored in a single bit vector.
68 
69   'MPI_Type_dup' could be implemented with a shallow copy, where most of the
70   data fields, would not be copied into the new object created by
71   'MPI_Type_dup'; instead, the new object could point to the data fields in
72   the old object.  However, this requires more code to make sure that fields
73   are found in the correct objects and that deleting the old object doesn't
74   invalidate the dup'ed datatype.
75 
76   Originally we attempted to keep contents/envelope data in a non-optimized
77   typerep.  The subarray and darray types were particularly problematic,
78   and eventually we decided it would be simpler to just keep contents/
79   envelope data in arrays separately.
80 
81   Earlier versions of the ADI used a single API to change the 'ref_count',
82   with each MPI object type having a separate routine.  Since reference
83   count changes are always up or down one, and since all MPI objects
84   are defined to have the 'ref_count' field in the same place, the current
85   ADI3 API uses two routines, 'MPIR_Object_add_ref' and
86   'MPIR_Object_release_ref', to increment and decrement the reference count.
87 
88   S*/
89 struct MPIR_Datatype {
90     /* handle and ref_count are filled in by MPIR_Handle_obj_alloc() */
91     MPIR_OBJECT_HEADER;         /* adds handle and ref_count fields */
92 
93     /* user-visible parameters */
94     MPI_Aint size;              /* MPI_Count could be 128 bits, so use MPI_Aint */
95     MPI_Aint extent, ub, lb, true_ub, true_lb;
96     struct MPIR_Attribute *attributes;
97     char name[MPI_MAX_OBJECT_NAME];
98 
99 
100     /* private fields */
101     /* chars affecting subsequent datatype processing and creation */
102     MPI_Aint alignsize;
103     int is_committed;
104 
105     /* element information; used for accumulate and get elements
106      * basic_type: describes basic type (predefined type). If the
107      *             type is composed of the same basic type, it is
108      *             set to that type, otherwise it is set to MPI_DATATYPE_NULL.
109      * n_builtin_elements: refers to the number of builtin type elements.
110      * builtin_element_size: refers to the size of builtin type. If the
111      *                       type is composed of the same builtin type,
112      *                       it is set to size of that type, otherwise it
113      *                       is set to -1.
114      */
115     int basic_type;
116     MPI_Aint n_builtin_elements;
117     MPI_Aint builtin_element_size;
118 
119     /* information on contiguity of type, for processing shortcuts.
120      *
121      * is_contig is non-zero only if N instances of the type would be
122      * contiguous.
123      */
124     int is_contig;
125 
126     /* pointer to contents and envelope data for the datatype */
127     MPIR_Datatype_contents *contents;
128 
129     /* flattened representation */
130     void *flattened;
131     int flattened_sz;
132 
133     /* handle to the backend datatype engine + some content that we
134      * query from it and cache over here for performance reasons */
135     struct {
136         void *handle;
137         MPI_Aint num_contig_blocks;     /* contig blocks in one datatype element */
138     } typerep;
139 
140     /* Other, device-specific information */
141 #ifdef MPID_DEV_DATATYPE_DECL
142      MPID_DEV_DATATYPE_DECL
143 #endif
144 };
145 
146 extern MPIR_Datatype MPIR_Datatype_builtin[MPIR_DATATYPE_N_BUILTIN];
147 extern MPIR_Datatype MPIR_Datatype_direct[];
148 extern MPIR_Object_alloc_t MPIR_Datatype_mem;
149 extern MPI_Datatype MPIR_Datatype_index_to_predefined[MPIR_DATATYPE_N_PREDEFINED];
150 
151 void MPIR_Datatype_free(MPIR_Datatype * ptr);
152 void MPIR_Datatype_get_flattened(MPI_Datatype type, void **flattened, int *flattened_sz);
153 
154 #define MPIR_Datatype_ptr_add_ref(datatype_ptr) MPIR_Object_add_ref((datatype_ptr))
155 
156 /* to be used only after MPIR_Datatype_valid_ptr(); the check on
157  * err == MPI_SUCCESS ensures that we won't try to dereference the
158  * pointer if something has already been detected as wrong.
159  */
160 #define MPIR_Datatype_committed_ptr(ptr,err) do {               \
161     if ((err == MPI_SUCCESS) && !((ptr)->is_committed))         \
162         err = MPIR_Err_create_code(MPI_SUCCESS,                 \
163                                    MPIR_ERR_RECOVERABLE,        \
164                                    __func__,                      \
165                                    __LINE__,                    \
166                                    MPI_ERR_TYPE,                \
167                                    "**dtypecommit",             \
168                                    0);                          \
169 } while (0)
170 
171 #define MPIR_Datatype_get_basic_size(a) (((a)&0x0000ff00)>>8)
172 
173 #define MPIR_Datatype_get_basic_type(a,basic_type_) do {            \
174     void *ptr;                                                      \
175     switch (HANDLE_GET_KIND(a)) {                                   \
176         case HANDLE_KIND_DIRECT:                                    \
177             MPIR_Assert(HANDLE_INDEX(a) < MPIR_DATATYPE_PREALLOC);  \
178             ptr = MPIR_Datatype_direct+HANDLE_INDEX(a);             \
179             basic_type_ = ((MPIR_Datatype *) ptr)->basic_type;      \
180             break;                                                  \
181         case HANDLE_KIND_INDIRECT:                                  \
182             ptr = ((MPIR_Datatype *)                                \
183              MPIR_Handle_get_ptr_indirect(a,&MPIR_Datatype_mem));   \
184             basic_type_ = ((MPIR_Datatype *) ptr)->basic_type;      \
185             break;                                                  \
186         case HANDLE_KIND_BUILTIN:                                   \
187             basic_type_ = a;                                        \
188             break;                                                  \
189         case HANDLE_KIND_INVALID:                                   \
190         default:                                                    \
191          basic_type_ = 0;                                           \
192          break;                                                     \
193                                                                     \
194     }                                                               \
195     /* This macro returns the builtin type, if 'basic_type' is not  \
196      * a builtin type, it must be a pair type composed of different \
197      * builtin types, so we return MPI_DATATYPE_NULL here.          \
198      */                                                             \
199     if (!HANDLE_IS_BUILTIN((basic_type_)))                          \
200         basic_type_ = MPI_DATATYPE_NULL;                            \
201  } while (0)
202 
203 #define MPIR_Datatype_get_ptr(a,ptr)   MPIR_Getb_ptr(Datatype,DATATYPE,a,0x000000ff,ptr)
204 
205 /* Note: Probably there is some clever way to build all of these from a macro.
206  */
207 #define MPIR_Datatype_get_size_macro(a,size_) do {                     \
208     void *ptr;                                                          \
209     switch (HANDLE_GET_KIND(a)) {                                       \
210         case HANDLE_KIND_DIRECT:                                        \
211             MPIR_Assert(HANDLE_INDEX(a) < MPIR_DATATYPE_PREALLOC);      \
212             ptr = MPIR_Datatype_direct+HANDLE_INDEX(a);                 \
213             size_ = ((MPIR_Datatype *) ptr)->size;                      \
214             break;                                                      \
215         case HANDLE_KIND_INDIRECT:                                      \
216             ptr = ((MPIR_Datatype *)                                    \
217              MPIR_Handle_get_ptr_indirect(a,&MPIR_Datatype_mem));       \
218             MPIR_Assert(ptr != NULL);                                   \
219             size_ = ((MPIR_Datatype *) ptr)->size;                      \
220             break;                                                      \
221         case HANDLE_KIND_BUILTIN:                                       \
222             size_ = MPIR_Datatype_get_basic_size(a);                    \
223             break;                                                      \
224         case HANDLE_KIND_INVALID:                                       \
225         default:                                                        \
226          size_ = 0;                                                     \
227          break;                                                         \
228                                                                         \
229     }                                                                   \
230 } while (0)
231 
232 #define MPIR_Datatype_get_extent_macro(a,extent_) do {                  \
233     void *ptr;                                                          \
234     switch (HANDLE_GET_KIND(a)) {                                       \
235         case HANDLE_KIND_DIRECT:                                        \
236             MPIR_Assert(HANDLE_INDEX(a) < MPIR_DATATYPE_PREALLOC);      \
237             ptr = MPIR_Datatype_direct+HANDLE_INDEX(a);                 \
238             extent_ = ((MPIR_Datatype *) ptr)->extent;                  \
239             break;                                                      \
240         case HANDLE_KIND_INDIRECT:                                      \
241             ptr = ((MPIR_Datatype *)                                    \
242              MPIR_Handle_get_ptr_indirect(a,&MPIR_Datatype_mem));       \
243             MPIR_Assert(ptr != NULL);                                   \
244             extent_ = ((MPIR_Datatype *) ptr)->extent;                  \
245             break;                                                      \
246         case HANDLE_KIND_INVALID:                                       \
247         case HANDLE_KIND_BUILTIN:                                       \
248         default:                                                        \
249             extent_ = MPIR_Datatype_get_basic_size(a);  /* same as size */  \
250             break;                                                      \
251     }                                                                   \
252 } while (0)
253 
254 /* helper macro: takes an MPI_Datatype handle value and returns TRUE in
255  * (*is_config_) if the type is contiguous */
256 #define MPIR_Datatype_is_contig(dtype_, is_contig_)                            \
257     do {                                                                       \
258         if (HANDLE_IS_BUILTIN((dtype_))) {                                     \
259             *(is_contig_) = TRUE;                                              \
260         }                                                                      \
261         else {                                                                 \
262             MPIR_Datatype *dtp_ = NULL;                                        \
263             MPIR_Datatype_get_ptr((dtype_), dtp_);                             \
264             MPIR_Assert(dtp_ != NULL);                                         \
265             *(is_contig_) = dtp_->is_contig;                                   \
266         }                                                                      \
267     } while (0)
268 
269 #define MPIR_Datatype_get_density(datatype_, density_)          \
270     do {                                                        \
271         int is_contig_;                                         \
272         MPIR_Datatype_is_contig((datatype_), &is_contig_);      \
273         if (is_contig_) {                                       \
274             (density_) = INT_MAX;                               \
275         } else {                                                \
276             MPIR_Datatype *dt_ptr_;                             \
277             MPIR_Datatype_get_ptr((datatype_), dt_ptr_);        \
278             MPI_Aint size_;                                     \
279             MPIR_Datatype_get_size_macro((datatype_), size_);   \
280             (density_) = size_ / dt_ptr_->typerep.num_contig_blocks;    \
281         }                                                       \
282     } while (0)
283 
284 /* MPIR_Datatype_ptr_release decrements the reference count on the MPIR_Datatype
285  * and, if the refct is then zero, frees the MPIR_Datatype and associated
286  * structures.
287  */
288 #define MPIR_Datatype_ptr_release(datatype_ptr) do {                            \
289     int inuse_;                                                             \
290                                                                             \
291     MPIR_Object_release_ref((datatype_ptr),&inuse_);                        \
292     if (!inuse_) {                                                          \
293         int lmpi_errno = MPI_SUCCESS;                                       \
294      if (MPIR_Process.attr_free && datatype_ptr->attributes) {              \
295          lmpi_errno = MPIR_Process.attr_free(datatype_ptr->handle,         \
296                                &datatype_ptr->attributes);                 \
297      }                                                                      \
298      /* LEAVE THIS COMMENTED OUT UNTIL WE HAVE SOME USE FOR THE FREE_FN     \
299      if (datatype_ptr->free_fn) {                                           \
300          mpi_errno = (datatype_ptr->free_fn)(datatype_ptr);               \
301           if (mpi_errno) {                                                  \
302            MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_TYPE_FREE);                  \
303            return MPIR_Err_return_comm(0, __func__, mpi_errno);             \
304           }                                                                 \
305      } */                                                                   \
306         if (lmpi_errno == MPI_SUCCESS) {                                    \
307          MPIR_Datatype_free(datatype_ptr);                                 \
308         }                                                                   \
309     }                                                                       \
310 } while (0)
311 
312 /* helper macro: takes an MPI_Datatype handle value and returns true_lb in
313  * (*true_lb_) */
314 #define MPIR_Datatype_get_true_lb(dtype_, true_lb_)                            \
315     do {                                                                       \
316         if (HANDLE_IS_BUILTIN((dtype_))) {                                     \
317             *(true_lb_) = 0;                                                   \
318         }                                                                      \
319         else {                                                                 \
320             MPIR_Datatype *dtp_ = NULL;                                        \
321             MPIR_Datatype_get_ptr((dtype_), dtp_);                             \
322             *(true_lb_) = dtp_->true_lb;                                       \
323         }                                                                      \
324     } while (0)
325 
326 #define MPIR_Datatype_valid_ptr(ptr,err) MPIR_Valid_ptr_class(Datatype,ptr,MPI_ERR_TYPE,err)
327 
328 /* we pessimistically assume that MPI_DATATYPE_NULL may be passed as a "valid" type
329  * for send/recv when MPI_PROC_NULL is the destination/src */
330 #define MPIR_Datatype_add_ref_if_not_builtin(datatype_)             \
331     do {                                                            \
332     if ((datatype_) != MPI_DATATYPE_NULL &&                         \
333         !MPIR_DATATYPE_IS_PREDEFINED((datatype_)))                  \
334     {                                                               \
335         MPIR_Datatype *dtp_ = NULL;                                 \
336         MPIR_Datatype_get_ptr((datatype_), dtp_);                   \
337         MPIR_Assert(dtp_ != NULL);                                  \
338         MPIR_Datatype_ptr_add_ref(dtp_);                            \
339     }                                                               \
340     } while (0)
341 
342 #define MPIR_Datatype_release_if_not_builtin(datatype_)             \
343     do {                                                            \
344     if ((datatype_) != MPI_DATATYPE_NULL &&                         \
345         !MPIR_DATATYPE_IS_PREDEFINED((datatype_)))                  \
346     {                                                               \
347         MPIR_Datatype *dtp_ = NULL;                                 \
348         MPIR_Datatype_get_ptr((datatype_), dtp_);                   \
349         MPIR_Assert(dtp_ != NULL);                                  \
350         MPIR_Datatype_ptr_release(dtp_);                            \
351     }                                                               \
352     } while (0)
353 
MPIR_Datatype_free_contents(MPIR_Datatype * dtp)354 static inline void MPIR_Datatype_free_contents(MPIR_Datatype * dtp)
355 {
356     int i, struct_sz = sizeof(MPIR_Datatype_contents);
357     int epsilon;
358     MPIR_Datatype *old_dtp;
359     MPI_Datatype *array_of_types;
360 
361     if ((epsilon = struct_sz % MAX_ALIGNMENT)) {
362         struct_sz += MAX_ALIGNMENT - epsilon;
363     }
364 
365     /* note: relies on types being first after structure */
366     array_of_types = (MPI_Datatype *) ((char *) dtp->contents + struct_sz);
367 
368     for (i = 0; i < dtp->contents->nr_types; i++) {
369         if (!HANDLE_IS_BUILTIN(array_of_types[i])) {
370             MPIR_Datatype_get_ptr(array_of_types[i], old_dtp);
371             MPIR_Datatype_ptr_release(old_dtp);
372         }
373     }
374 
375     MPL_free(dtp->contents);
376     dtp->contents = NULL;
377 }
378 
379 /*@
380   MPIR_Datatype_set_contents - store contents information for use in
381   MPI_Type_get_contents.
382 
383   Returns MPI_SUCCESS on success, MPI error code on error.
384   @*/
MPIR_Datatype_set_contents(MPIR_Datatype * new_dtp,int combiner,int nr_ints,int nr_aints,int nr_types,int array_of_ints[],const MPI_Aint array_of_aints[],const MPI_Datatype array_of_types[])385 static inline int MPIR_Datatype_set_contents(MPIR_Datatype * new_dtp,
386                                              int combiner,
387                                              int nr_ints,
388                                              int nr_aints,
389                                              int nr_types,
390                                              int array_of_ints[],
391                                              const MPI_Aint array_of_aints[],
392                                              const MPI_Datatype array_of_types[])
393 {
394     int i, contents_size, epsilon, mpi_errno;
395     int struct_sz, ints_sz, aints_sz, types_sz;
396     MPIR_Datatype_contents *cp;
397     MPIR_Datatype *old_dtp;
398     char *ptr;
399 
400     struct_sz = sizeof(MPIR_Datatype_contents);
401     types_sz = nr_types * sizeof(MPI_Datatype);
402     ints_sz = nr_ints * sizeof(int);
403     aints_sz = nr_aints * sizeof(MPI_Aint);
404 
405     /* pad the struct, types, and ints before we allocate.
406      *
407      * note: it's not necessary that we pad the aints,
408      *       because they are last in the region.
409      */
410     if ((epsilon = struct_sz % MAX_ALIGNMENT)) {
411         struct_sz += MAX_ALIGNMENT - epsilon;
412     }
413     if ((epsilon = types_sz % MAX_ALIGNMENT)) {
414         types_sz += MAX_ALIGNMENT - epsilon;
415     }
416     if ((epsilon = ints_sz % MAX_ALIGNMENT)) {
417         ints_sz += MAX_ALIGNMENT - epsilon;
418     }
419 
420     contents_size = struct_sz + types_sz + ints_sz + aints_sz;
421 
422     cp = (MPIR_Datatype_contents *) MPL_malloc(contents_size, MPL_MEM_DATATYPE);
423     /* --BEGIN ERROR HANDLING-- */
424     if (cp == NULL) {
425         mpi_errno = MPIR_Err_create_code(MPI_SUCCESS,
426                                          MPIR_ERR_RECOVERABLE,
427                                          "MPIR_Datatype_set_contents",
428                                          __LINE__, MPI_ERR_OTHER, "**nomem", 0);
429         return mpi_errno;
430     }
431     /* --END ERROR HANDLING-- */
432 
433     cp->combiner = combiner;
434     cp->nr_ints = nr_ints;
435     cp->nr_aints = nr_aints;
436     cp->nr_types = nr_types;
437 
438     /* arrays are stored in the following order: types, ints, aints,
439      * following the structure itself.
440      */
441     ptr = ((char *) cp) + struct_sz;
442     /* Fortran90 combiner types do not have a "base" type */
443     if (nr_types > 0) {
444         MPIR_Memcpy(ptr, array_of_types, nr_types * sizeof(MPI_Datatype));
445     }
446 
447     ptr = ((char *) cp) + struct_sz + types_sz;
448     if (nr_ints > 0) {
449         MPIR_Memcpy(ptr, array_of_ints, nr_ints * sizeof(int));
450     }
451 
452     ptr = ((char *) cp) + struct_sz + types_sz + ints_sz;
453     if (nr_aints > 0) {
454         MPIR_Memcpy(ptr, array_of_aints, nr_aints * sizeof(MPI_Aint));
455     }
456     new_dtp->contents = cp;
457     new_dtp->flattened = NULL;
458 
459     /* increment reference counts on all the derived types used here */
460     for (i = 0; i < nr_types; i++) {
461         if (!HANDLE_IS_BUILTIN(array_of_types[i])) {
462             MPIR_Datatype_get_ptr(array_of_types[i], old_dtp);
463             MPIR_Datatype_ptr_add_ref(old_dtp);
464         }
465     }
466 
467     return MPI_SUCCESS;
468 }
469 
MPIR_Datatype_predefined_get_type(uint32_t index)470 MPL_STATIC_INLINE_PREFIX MPI_Datatype MPIR_Datatype_predefined_get_type(uint32_t index)
471 {
472     MPIR_Assert(index < MPIR_DATATYPE_N_PREDEFINED);
473     return MPIR_Datatype_index_to_predefined[index];
474 }
475 
MPIR_Datatype_predefined_get_index(MPI_Datatype datatype)476 MPL_STATIC_INLINE_PREFIX int MPIR_Datatype_predefined_get_index(MPI_Datatype datatype)
477 {
478     int dtype_index = 0;
479     switch (HANDLE_GET_KIND(datatype)) {
480         case HANDLE_KIND_BUILTIN:
481             /* Predefined builtin index mask for dtype. See MPIR_Datatype_get_ptr. */
482             dtype_index = datatype & 0x000000ff;
483             MPIR_Assert(dtype_index < MPIR_DATATYPE_N_BUILTIN);
484             break;
485         case HANDLE_KIND_DIRECT:
486             /* pairtype */
487             dtype_index = HANDLE_INDEX(datatype) + MPIR_DATATYPE_N_BUILTIN;
488             MPIR_Assert(dtype_index < MPIR_DATATYPE_N_BUILTIN + MPIR_DATATYPE_N_BUILTIN);
489             break;
490         default:
491             /* should be called only by builtin or pairtype */
492             MPIR_Assert(HANDLE_GET_KIND(datatype) == HANDLE_KIND_BUILTIN ||
493                         HANDLE_GET_KIND(datatype) == HANDLE_KIND_DIRECT);
494             break;
495     }
496     return dtype_index;
497 }
498 
499 /* contents accessor functions */
500 void MPIR_Type_access_contents(MPI_Datatype type, int **ints_p, MPI_Aint ** aints_p,
501                                MPI_Datatype ** types_p);
502 void MPIR_Type_release_contents(MPI_Datatype type, int **ints_p, MPI_Aint ** aints_p,
503                                 MPI_Datatype ** types_p);
504 
505 /* This routine is used to install an attribute free routine for datatypes
506    at finalize-time */
507 void MPII_Datatype_attr_finalize(void);
508 int MPII_Type_zerolen(MPI_Datatype * newtype);
509 
510 #define MPIR_DATATYPE_IS_PREDEFINED(type) \
511     ((HANDLE_IS_BUILTIN((type))) || \
512      (type == MPI_FLOAT_INT) || (type == MPI_DOUBLE_INT) || \
513      (type == MPI_LONG_INT) || (type == MPI_SHORT_INT) || \
514      (type == MPI_LONG_DOUBLE_INT))
515 
516 int MPIR_Get_elements_x_impl(MPI_Count * bytes, MPI_Datatype datatype, MPI_Count * elements);
517 int MPIR_Status_set_elements_x_impl(MPI_Status * status, MPI_Datatype datatype, MPI_Count count);
518 void MPIR_Type_get_extent_x_impl(MPI_Datatype datatype, MPI_Count * lb, MPI_Count * extent);
519 void MPIR_Type_get_true_extent_x_impl(MPI_Datatype datatype, MPI_Count * true_lb,
520                                       MPI_Count * true_extent);
521 int MPIR_Type_size_x_impl(MPI_Datatype datatype, MPI_Count * size);
522 
523 void MPIR_Get_count_impl(const MPI_Status * status, MPI_Datatype datatype, MPI_Aint * count);
524 int MPIR_Type_commit_impl(MPI_Datatype * datatype);
525 int MPIR_Type_create_struct_impl(int count,
526                                  const int array_of_blocklengths[],
527                                  const MPI_Aint array_of_displacements[],
528                                  const MPI_Datatype array_of_types[], MPI_Datatype * newtype);
529 int MPIR_Type_create_indexed_block_impl(int count,
530                                         int blocklength,
531                                         const int array_of_displacements[],
532                                         MPI_Datatype oldtype, MPI_Datatype * newtype);
533 int MPIR_Type_create_hindexed_block_impl(int count, int blocklength,
534                                          const MPI_Aint array_of_displacements[],
535                                          MPI_Datatype oldtype, MPI_Datatype * newtype);
536 int MPIR_Type_contiguous_impl(int count, MPI_Datatype old_type, MPI_Datatype * new_type_p);
537 int MPIR_Type_contiguous_x_impl(MPI_Count count, MPI_Datatype old_type, MPI_Datatype * new_type_p);
538 void MPIR_Type_get_extent_impl(MPI_Datatype datatype, MPI_Aint * lb, MPI_Aint * extent);
539 void MPIR_Type_get_true_extent_impl(MPI_Datatype datatype, MPI_Aint * true_lb,
540                                     MPI_Aint * true_extent);
541 void MPIR_Type_get_envelope(MPI_Datatype datatype, int *num_integers, int *num_addresses,
542                             int *num_datatypes, int *combiner);
543 int MPIR_Type_hvector_impl(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type,
544                            MPI_Datatype * newtype_p);
545 int MPIR_Type_indexed_impl(int count, const int blocklens[], const int indices[],
546                            MPI_Datatype old_type, MPI_Datatype * newtype);
547 void MPIR_Type_free_impl(MPI_Datatype * datatype);
548 int MPIR_Type_vector_impl(int count, int blocklength, int stride, MPI_Datatype old_type,
549                           MPI_Datatype * newtype_p);
550 int MPIR_Type_struct_impl(int count, const int blocklens[], const MPI_Aint indices[],
551                           const MPI_Datatype old_types[], MPI_Datatype * newtype);
552 void MPIR_Pack_size_impl(int incount, MPI_Datatype datatype, MPI_Aint * size);
553 void MPIR_Type_lb_impl(MPI_Datatype datatype, MPI_Aint * displacement);
554 
555 /* Datatype functions */
556 int MPIR_Type_dup(MPI_Datatype oldtype, MPI_Datatype * newtype);
557 int MPIR_Type_struct(int count, const int *blocklength_array, const MPI_Aint * displacement_array,
558                      const MPI_Datatype * oldtype_array, MPI_Datatype * newtype);
559 int MPIR_Type_indexed(int count, const int *blocklength_array, const void *displacement_array,
560                       int dispinbytes, MPI_Datatype oldtype, MPI_Datatype * newtype);
561 int MPIR_Type_vector(int count, int blocklength, MPI_Aint stride, int strideinbytes,
562                      MPI_Datatype oldtype, MPI_Datatype * newtype);
563 int MPIR_Type_contiguous(int count, MPI_Datatype oldtype, MPI_Datatype * newtype);
564 int MPIR_Type_blockindexed(int count,
565                            int blocklength,
566                            const void *displacement_array,
567                            int dispinbytes, MPI_Datatype oldtype, MPI_Datatype * newtype);
568 
569 int MPIR_Type_commit(MPI_Datatype * type);
570 int MPII_Type_zerolen(MPI_Datatype * newtype);
571 int MPIR_Type_create_resized(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint extent,
572                              MPI_Datatype * newtype);
573 int MPIR_Type_get_contents(MPI_Datatype datatype, int max_integers, int max_addresses,
574                            int max_datatypes, int array_of_integers[],
575                            MPI_Aint array_of_addresses[], MPI_Datatype array_of_datatypes[]);
576 int MPIR_Type_create_pairtype(MPI_Datatype datatype, MPIR_Datatype * new_dtp);
577 
578 /* debugging helper functions */
579 char *MPIR_Datatype_builtin_to_string(MPI_Datatype type);
580 char *MPIR_Datatype_combiner_to_string(int combiner);
581 void MPIR_Datatype_debug(MPI_Datatype type, int array_ct);
582 
583 MPI_Aint MPII_Datatype_indexed_count_contig(MPI_Aint count,
584                                             const MPI_Aint * blocklength_array,
585                                             const void *displacement_array,
586                                             int dispinbytes, MPI_Aint old_extent);
587 
588 MPI_Aint MPII_Datatype_blockindexed_count_contig(MPI_Aint count,
589                                                  MPI_Aint blklen,
590                                                  const void *disp_array,
591                                                  int dispinbytes, MPI_Aint old_extent);
592 
593 #endif /* MPIR_DATATYPE_H_INCLUDED */
594