1 /* smpi_mpi_dt.c -- MPI primitives to handle datatypes */
2 /* FIXME: a very incomplete implementation */
4 /* Copyright (c) 2009, 2010. The SimGrid Team.
5 * All rights reserved. */
7 /* This program is free software; you can redistribute it and/or modify it
8 * under the terms of the license (GNU LGPL) which comes with this package. */
15 #include "smpi_mpi_dt_private.h"
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
18 "Logging specific to SMPI (datatype)");
20 #define CREATE_MPI_DATATYPE(name, type) \
21 static s_smpi_mpi_datatype_t mpi_##name = { \
22 sizeof(type), /* size */ \
23 0, /*was 1 has_subtype*/ \
25 sizeof(type), /* ub = lb + size */ \
26 DT_FLAG_BASIC, /* flags */ \
27 NULL /* pointer on extended struct*/ \
29 MPI_Datatype name = &mpi_##name;
31 #define CREATE_MPI_DATATYPE_NULL(name) \
32 static s_smpi_mpi_datatype_t mpi_##name = { \
34 0, /*was 1 has_subtype*/ \
36 0, /* ub = lb + size */ \
37 DT_FLAG_BASIC, /* flags */ \
38 NULL /* pointer on extended struct*/ \
40 MPI_Datatype name = &mpi_##name;
42 //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC.
76 // Predefined data types
77 CREATE_MPI_DATATYPE(MPI_CHAR, char);
78 CREATE_MPI_DATATYPE(MPI_SHORT, short);
79 CREATE_MPI_DATATYPE(MPI_INT, int);
80 CREATE_MPI_DATATYPE(MPI_LONG, long);
81 CREATE_MPI_DATATYPE(MPI_LONG_LONG, long long);
82 CREATE_MPI_DATATYPE(MPI_SIGNED_CHAR, signed char);
83 CREATE_MPI_DATATYPE(MPI_UNSIGNED_CHAR, unsigned char);
84 CREATE_MPI_DATATYPE(MPI_UNSIGNED_SHORT, unsigned short);
85 CREATE_MPI_DATATYPE(MPI_UNSIGNED, unsigned int);
86 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG, unsigned long);
87 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG, unsigned long long);
88 CREATE_MPI_DATATYPE(MPI_FLOAT, float);
89 CREATE_MPI_DATATYPE(MPI_DOUBLE, double);
90 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE, long double);
91 CREATE_MPI_DATATYPE(MPI_WCHAR, wchar_t);
92 CREATE_MPI_DATATYPE(MPI_C_BOOL, _Bool);
93 CREATE_MPI_DATATYPE(MPI_INT8_T, int8_t);
94 CREATE_MPI_DATATYPE(MPI_INT16_T, int16_t);
95 CREATE_MPI_DATATYPE(MPI_INT32_T, int32_t);
96 CREATE_MPI_DATATYPE(MPI_INT64_T, int64_t);
97 CREATE_MPI_DATATYPE(MPI_UINT8_T, uint8_t);
98 CREATE_MPI_DATATYPE(MPI_UINT16_T, uint16_t);
99 CREATE_MPI_DATATYPE(MPI_UINT32_T, uint32_t);
100 CREATE_MPI_DATATYPE(MPI_UINT64_T, uint64_t);
101 CREATE_MPI_DATATYPE(MPI_C_FLOAT_COMPLEX, float _Complex);
102 CREATE_MPI_DATATYPE(MPI_C_DOUBLE_COMPLEX, double _Complex);
103 CREATE_MPI_DATATYPE(MPI_C_LONG_DOUBLE_COMPLEX, long double _Complex);
104 CREATE_MPI_DATATYPE(MPI_AINT, MPI_Aint);
105 CREATE_MPI_DATATYPE(MPI_OFFSET, MPI_Offset);
107 CREATE_MPI_DATATYPE(MPI_FLOAT_INT, float_int);
108 CREATE_MPI_DATATYPE(MPI_LONG_INT, long_int);
109 CREATE_MPI_DATATYPE(MPI_DOUBLE_INT, double_int);
110 CREATE_MPI_DATATYPE(MPI_SHORT_INT, short_int);
111 CREATE_MPI_DATATYPE(MPI_2INT, int_int);
112 CREATE_MPI_DATATYPE(MPI_2FLOAT, float_float);
113 CREATE_MPI_DATATYPE(MPI_2DOUBLE, double_double);
115 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int);
117 CREATE_MPI_DATATYPE_NULL(MPI_UB);
118 CREATE_MPI_DATATYPE_NULL(MPI_LB);
119 CREATE_MPI_DATATYPE_NULL(MPI_PACKED);
121 CREATE_MPI_DATATYPE(MPI_PTR, void*);
124 size_t smpi_datatype_size(MPI_Datatype datatype)
126 return datatype->size;
131 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype)
136 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype)
141 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
146 // if ((datatype->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
147 // retval = MPI_ERR_TYPE;
150 *extent = datatype->ub - datatype->lb;
151 retval = MPI_SUCCESS;
156 MPI_Aint smpi_datatype_get_extent(MPI_Datatype datatype){
159 smpi_datatype_extent(datatype, &lb, &extent);
163 int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype,
164 void *recvbuf, int recvcount, MPI_Datatype recvtype)
168 /* First check if we really have something to do */
169 if (recvcount == 0) {
170 retval = sendcount == 0 ? MPI_SUCCESS : MPI_ERR_TRUNCATE;
172 /* FIXME: treat packed cases */
173 sendcount *= smpi_datatype_size(sendtype);
174 recvcount *= smpi_datatype_size(recvtype);
175 count = sendcount < recvcount ? sendcount : recvcount;
177 if(sendtype->has_subtype == 0 && recvtype->has_subtype == 0) {
178 memcpy(recvbuf, sendbuf, count);
180 else if (sendtype->has_subtype == 0)
182 s_smpi_subtype_t *subtype = recvtype->substruct;
183 subtype->unserialize( sendbuf, recvbuf,1, subtype);
185 else if (recvtype->has_subtype == 0)
187 s_smpi_subtype_t *subtype = sendtype->substruct;
188 subtype->serialize(sendbuf, recvbuf,1, subtype);
190 s_smpi_subtype_t *subtype = sendtype->substruct;
192 s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)sendtype;
194 void * buf_tmp = malloc(count * type_c->size_oldtype);
196 subtype->serialize( sendbuf, buf_tmp,1, subtype);
197 subtype = recvtype->substruct;
198 subtype->unserialize(recvbuf, buf_tmp,1, subtype);
202 retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
209 * Copies noncontiguous data into contiguous memory.
210 * @param contiguous_vector - output vector
211 * @param noncontiguous_vector - input vector
212 * @param type - pointer contening :
213 * - stride - stride of between noncontiguous data
214 * - block_length - the width or height of blocked matrix
215 * - count - the number of rows of matrix
217 void serialize_vector( const void *noncontiguous_vector,
218 void *contiguous_vector,
222 s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)type;
224 char* contiguous_vector_char = (char*)contiguous_vector;
225 char* noncontiguous_vector_char = (char*)noncontiguous_vector;
227 for (i = 0; i < type_c->block_count * count; i++) {
228 if (type_c->old_type->has_subtype == 0)
229 memcpy(contiguous_vector_char,
230 noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype);
232 ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_vector_char,
233 contiguous_vector_char,
234 type_c->block_length,
235 type_c->old_type->substruct);
237 contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
238 noncontiguous_vector_char += type_c->block_stride*smpi_datatype_get_extent(type_c->old_type);
243 * Copies contiguous data into noncontiguous memory.
244 * @param noncontiguous_vector - output vector
245 * @param contiguous_vector - input vector
246 * @param type - pointer contening :
247 * - stride - stride of between noncontiguous data
248 * - block_length - the width or height of blocked matrix
249 * - count - the number of rows of matrix
251 void unserialize_vector( const void *contiguous_vector,
252 void *noncontiguous_vector,
256 s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)type;
259 char* contiguous_vector_char = (char*)contiguous_vector;
260 char* noncontiguous_vector_char = (char*)noncontiguous_vector;
262 for (i = 0; i < type_c->block_count * count; i++) {
263 if (type_c->old_type->has_subtype == 0)
264 memcpy(noncontiguous_vector_char,
265 contiguous_vector_char, type_c->block_length * type_c->size_oldtype);
267 ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_vector_char,
268 noncontiguous_vector_char,
269 type_c->block_length,
270 type_c->old_type->substruct);
271 contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
272 noncontiguous_vector_char += type_c->block_stride*smpi_datatype_get_extent(type_c->old_type);
277 * Create a Sub type vector to be able to serialize and unserialize it
278 * the structure s_smpi_mpi_vector_t is derived from s_smpi_subtype which
279 * required the functions unserialize and serialize
282 s_smpi_mpi_vector_t* smpi_datatype_vector_create( int block_stride,
285 MPI_Datatype old_type,
287 s_smpi_mpi_vector_t *new_t= xbt_new(s_smpi_mpi_vector_t,1);
288 new_t->base.serialize = &serialize_vector;
289 new_t->base.unserialize = &unserialize_vector;
290 new_t->base.subtype_free = &free_vector;
291 new_t->block_stride = block_stride;
292 new_t->block_length = block_length;
293 new_t->block_count = block_count;
294 new_t->old_type = old_type;
295 new_t->size_oldtype = size_oldtype;
299 void smpi_datatype_create(MPI_Datatype* new_type, int size,int extent, int has_subtype,
300 void *struct_type, int flags){
301 MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1);
303 new_t->has_subtype = has_subtype;
306 new_t->flags = flags;
307 new_t->substruct = struct_type;
311 void smpi_datatype_free(MPI_Datatype* type){
312 if ((*type)->has_subtype == 1){
313 ((s_smpi_subtype_t *)(*type)->substruct)->subtype_free(type);
318 int smpi_datatype_contiguous(int count, MPI_Datatype old_type, MPI_Datatype* new_type)
321 smpi_datatype_create(new_type, count *
322 smpi_datatype_size(old_type),count *
323 smpi_datatype_size(old_type),0,NULL, DT_FLAG_CONTIGUOUS);
328 int smpi_datatype_vector(int count, int blocklen, int stride, MPI_Datatype old_type, MPI_Datatype* new_type)
331 if (blocklen<=0) return MPI_ERR_ARG;
332 if(old_type->has_subtype || stride != blocklen){
333 s_smpi_mpi_vector_t* subtype = smpi_datatype_vector_create( stride,
337 smpi_datatype_size(old_type));
338 smpi_datatype_create(new_type,
339 count * (blocklen) * smpi_datatype_size(old_type),
340 ((count -1) * stride + blocklen) * smpi_datatype_get_extent(old_type),
346 /* in this situation the data are contignous thus it's not
347 * required to serialize and unserialize it*/
348 smpi_datatype_create(new_type, count * blocklen *
349 smpi_datatype_size(old_type), ((count -1) * stride + blocklen)*
350 smpi_datatype_size(old_type),
353 DT_FLAG_VECTOR|DT_FLAG_CONTIGUOUS);
359 void free_vector(MPI_Datatype* d){
363 Hvector Implementation - Vector with stride in bytes
368 * Copies noncontiguous data into contiguous memory.
369 * @param contiguous_hvector - output hvector
370 * @param noncontiguous_hvector - input hvector
371 * @param type - pointer contening :
372 * - stride - stride of between noncontiguous data, in bytes
373 * - block_length - the width or height of blocked matrix
374 * - count - the number of rows of matrix
376 void serialize_hvector( const void *noncontiguous_hvector,
377 void *contiguous_hvector,
381 s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type;
383 char* contiguous_vector_char = (char*)contiguous_hvector;
384 char* noncontiguous_vector_char = (char*)noncontiguous_hvector;
386 for (i = 0; i < type_c->block_count * count; i++) {
387 if (type_c->old_type->has_subtype == 0)
388 memcpy(contiguous_vector_char,
389 noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype);
391 ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_vector_char,
392 contiguous_vector_char,
393 type_c->block_length,
394 type_c->old_type->substruct);
396 contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
397 noncontiguous_vector_char += type_c->block_stride;
401 * Copies contiguous data into noncontiguous memory.
402 * @param noncontiguous_vector - output hvector
403 * @param contiguous_vector - input hvector
404 * @param type - pointer contening :
405 * - stride - stride of between noncontiguous data, in bytes
406 * - block_length - the width or height of blocked matrix
407 * - count - the number of rows of matrix
409 void unserialize_hvector( const void *contiguous_vector,
410 void *noncontiguous_vector,
414 s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type;
417 char* contiguous_vector_char = (char*)contiguous_vector;
418 char* noncontiguous_vector_char = (char*)noncontiguous_vector;
420 for (i = 0; i < type_c->block_count * count; i++) {
421 if (type_c->old_type->has_subtype == 0)
422 memcpy(noncontiguous_vector_char,
423 contiguous_vector_char, type_c->block_length * type_c->size_oldtype);
425 ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_vector_char,
426 noncontiguous_vector_char,
427 type_c->block_length,
428 type_c->old_type->substruct);
429 contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
430 noncontiguous_vector_char += type_c->block_stride;
435 * Create a Sub type vector to be able to serialize and unserialize it
436 * the structure s_smpi_mpi_vector_t is derived from s_smpi_subtype which
437 * required the functions unserialize and serialize
440 s_smpi_mpi_hvector_t* smpi_datatype_hvector_create( MPI_Aint block_stride,
443 MPI_Datatype old_type,
445 s_smpi_mpi_hvector_t *new_t= xbt_new(s_smpi_mpi_hvector_t,1);
446 new_t->base.serialize = &serialize_hvector;
447 new_t->base.unserialize = &unserialize_hvector;
448 new_t->base.subtype_free = &free_hvector;
449 new_t->block_stride = block_stride;
450 new_t->block_length = block_length;
451 new_t->block_count = block_count;
452 new_t->old_type = old_type;
453 new_t->size_oldtype = size_oldtype;
457 //do nothing for vector types
458 void free_hvector(MPI_Datatype* d){
461 int smpi_datatype_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type)
464 if (blocklen<=0) return MPI_ERR_ARG;
465 if(old_type->has_subtype || stride != blocklen*smpi_datatype_get_extent(old_type)){
466 s_smpi_mpi_hvector_t* subtype = smpi_datatype_hvector_create( stride,
470 smpi_datatype_size(old_type));
472 smpi_datatype_create(new_type, count * blocklen *
473 smpi_datatype_size(old_type), (count-1) * stride + blocklen *
474 smpi_datatype_size(old_type),
480 smpi_datatype_create(new_type, count * blocklen *
481 smpi_datatype_size(old_type),count * blocklen *
482 smpi_datatype_size(old_type),
485 DT_FLAG_VECTOR|DT_FLAG_CONTIGUOUS);
493 Indexed Implementation
497 * Copies noncontiguous data into contiguous memory.
498 * @param contiguous_indexed - output indexed
499 * @param noncontiguous_indexed - input indexed
500 * @param type - pointer contening :
501 * - block_lengths - the width or height of blocked matrix
502 * - block_indices - indices of each data, in element
503 * - count - the number of rows of matrix
505 void serialize_indexed( const void *noncontiguous_indexed,
506 void *contiguous_indexed,
510 s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type;
512 char* contiguous_indexed_char = (char*)contiguous_indexed;
513 char* noncontiguous_indexed_char = (char*)noncontiguous_indexed;
514 for(j=0; j<count;j++){
515 for (i = 0; i < type_c->block_count; i++) {
516 if (type_c->old_type->has_subtype == 0)
517 memcpy(contiguous_indexed_char,
518 noncontiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
520 ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_indexed_char,
521 contiguous_indexed_char,
522 type_c->block_lengths[i],
523 type_c->old_type->substruct);
526 contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
527 if (i<type_c->block_count-1)noncontiguous_indexed_char = (char*)noncontiguous_indexed + type_c->block_indices[i+1]*smpi_datatype_get_extent(type_c->old_type);
528 else noncontiguous_indexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
530 noncontiguous_indexed=(void*)noncontiguous_indexed_char;
534 * Copies contiguous data into noncontiguous memory.
535 * @param noncontiguous_indexed - output indexed
536 * @param contiguous_indexed - input indexed
537 * @param type - pointer contening :
538 * - block_lengths - the width or height of blocked matrix
539 * - block_indices - indices of each data, in element
540 * - count - the number of rows of matrix
542 void unserialize_indexed( const void *contiguous_indexed,
543 void *noncontiguous_indexed,
547 s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type;
550 char* contiguous_indexed_char = (char*)contiguous_indexed;
551 char* noncontiguous_indexed_char = (char*)noncontiguous_indexed;
552 for(j=0; j<count;j++){
553 for (i = 0; i < type_c->block_count; i++) {
554 if (type_c->old_type->has_subtype == 0)
555 memcpy(noncontiguous_indexed_char,
556 contiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
558 ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_indexed_char,
559 noncontiguous_indexed_char,
560 type_c->block_lengths[i],
561 type_c->old_type->substruct);
563 contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
564 if (i<type_c->block_count-1)
565 noncontiguous_indexed_char = (char*)noncontiguous_indexed + type_c->block_indices[i+1]*smpi_datatype_get_extent(type_c->old_type);
566 else noncontiguous_indexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
568 noncontiguous_indexed=(void*)noncontiguous_indexed_char;
572 void free_indexed(MPI_Datatype* type){
573 xbt_free(((s_smpi_mpi_indexed_t *)(*type)->substruct)->block_lengths);
574 xbt_free(((s_smpi_mpi_indexed_t *)(*type)->substruct)->block_indices);
578 * Create a Sub type indexed to be able to serialize and unserialize it
579 * the structure s_smpi_mpi_indexed_t is derived from s_smpi_subtype which
580 * required the functions unserialize and serialize
582 s_smpi_mpi_indexed_t* smpi_datatype_indexed_create( int* block_lengths,
585 MPI_Datatype old_type,
587 s_smpi_mpi_indexed_t *new_t= xbt_new(s_smpi_mpi_indexed_t,1);
588 new_t->base.serialize = &serialize_indexed;
589 new_t->base.unserialize = &unserialize_indexed;
590 new_t->base.subtype_free = &free_indexed;
591 //TODO : add a custom function for each time to clean these
592 new_t->block_lengths= xbt_new(int, block_count);
593 new_t->block_indices= xbt_new(int, block_count);
595 for(i=0;i<block_count;i++){
596 new_t->block_lengths[i]=block_lengths[i];
597 new_t->block_indices[i]=block_indices[i];
599 new_t->block_count = block_count;
600 new_t->old_type = old_type;
601 new_t->size_oldtype = size_oldtype;
606 int smpi_datatype_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
612 for(i=0; i< count; i++){
615 size += blocklens[i];
617 if ( (i< count -1) && (indices[i]+blocklens[i] != indices[i+1]) )contiguous=0;
619 if (old_type->has_subtype == 1)
623 s_smpi_mpi_indexed_t* subtype = smpi_datatype_indexed_create( blocklens,
627 smpi_datatype_size(old_type));
628 smpi_datatype_create(new_type, size *
629 smpi_datatype_size(old_type),(indices[count-1]+blocklens[count-1])*smpi_datatype_size(old_type),1, subtype, DT_FLAG_DATA);
631 smpi_datatype_create(new_type, size *
632 smpi_datatype_size(old_type),size *
633 smpi_datatype_size(old_type),0, NULL, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
641 Hindexed Implementation - Indexed with indices in bytes
645 * Copies noncontiguous data into contiguous memory.
646 * @param contiguous_hindexed - output hindexed
647 * @param noncontiguous_hindexed - input hindexed
648 * @param type - pointer contening :
649 * - block_lengths - the width or height of blocked matrix
650 * - block_indices - indices of each data, in bytes
651 * - count - the number of rows of matrix
653 void serialize_hindexed( const void *noncontiguous_hindexed,
654 void *contiguous_hindexed,
658 s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type;
660 char* contiguous_hindexed_char = (char*)contiguous_hindexed;
661 char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed;
662 for(j=0; j<count;j++){
663 for (i = 0; i < type_c->block_count; i++) {
664 if (type_c->old_type->has_subtype == 0)
665 memcpy(contiguous_hindexed_char,
666 noncontiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
668 ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_hindexed_char,
669 contiguous_hindexed_char,
670 type_c->block_lengths[i],
671 type_c->old_type->substruct);
673 contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
674 if (i<type_c->block_count-1)noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1];
675 else noncontiguous_hindexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
677 noncontiguous_hindexed=(void*)noncontiguous_hindexed_char;
681 * Copies contiguous data into noncontiguous memory.
682 * @param noncontiguous_hindexed - output hindexed
683 * @param contiguous_hindexed - input hindexed
684 * @param type - pointer contening :
685 * - block_lengths - the width or height of blocked matrix
686 * - block_indices - indices of each data, in bytes
687 * - count - the number of rows of matrix
689 void unserialize_hindexed( const void *contiguous_hindexed,
690 void *noncontiguous_hindexed,
694 s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type;
697 char* contiguous_hindexed_char = (char*)contiguous_hindexed;
698 char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed;
699 for(j=0; j<count;j++){
700 for (i = 0; i < type_c->block_count; i++) {
701 if (type_c->old_type->has_subtype == 0)
702 memcpy(noncontiguous_hindexed_char,
703 contiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
705 ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_hindexed_char,
706 noncontiguous_hindexed_char,
707 type_c->block_lengths[i],
708 type_c->old_type->substruct);
710 contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
711 if (i<type_c->block_count-1)noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1];
712 else noncontiguous_hindexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
714 noncontiguous_hindexed=(void*)noncontiguous_hindexed_char;
718 void free_hindexed(MPI_Datatype* type){
719 xbt_free(((s_smpi_mpi_hindexed_t *)(*type)->substruct)->block_lengths);
720 xbt_free(((s_smpi_mpi_hindexed_t *)(*type)->substruct)->block_indices);
724 * Create a Sub type hindexed to be able to serialize and unserialize it
725 * the structure s_smpi_mpi_hindexed_t is derived from s_smpi_subtype which
726 * required the functions unserialize and serialize
728 s_smpi_mpi_hindexed_t* smpi_datatype_hindexed_create( int* block_lengths,
729 MPI_Aint* block_indices,
731 MPI_Datatype old_type,
733 s_smpi_mpi_hindexed_t *new_t= xbt_new(s_smpi_mpi_hindexed_t,1);
734 new_t->base.serialize = &serialize_hindexed;
735 new_t->base.unserialize = &unserialize_hindexed;
736 new_t->base.subtype_free = &free_hindexed;
737 //TODO : add a custom function for each time to clean these
738 new_t->block_lengths= xbt_new(int, block_count);
739 new_t->block_indices= xbt_new(MPI_Aint, block_count);
741 for(i=0;i<block_count;i++){
742 new_t->block_lengths[i]=block_lengths[i];
743 new_t->block_indices[i]=block_indices[i];
745 new_t->block_count = block_count;
746 new_t->old_type = old_type;
747 new_t->size_oldtype = size_oldtype;
752 int smpi_datatype_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
758 for(i=0; i< count; i++){
761 size += blocklens[i];
762 if ( (i< count -1) && (indices[i]+blocklens[i]*smpi_datatype_size(old_type) != indices[i+1]) )contiguous=0;
764 if (old_type->has_subtype == 1)
767 s_smpi_mpi_hindexed_t* subtype = smpi_datatype_hindexed_create( blocklens,
771 smpi_datatype_size(old_type));
772 smpi_datatype_create(new_type, size *
773 smpi_datatype_size(old_type),indices[count-1]+blocklens[count-1]*smpi_datatype_size(old_type)
774 ,1, subtype, DT_FLAG_DATA);
776 smpi_datatype_create(new_type, size *
777 smpi_datatype_size(old_type),size *
778 smpi_datatype_size(old_type),0, NULL, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
786 struct Implementation - Indexed with indices in bytes
790 * Copies noncontiguous data into contiguous memory.
791 * @param contiguous_struct - output struct
792 * @param noncontiguous_struct - input struct
793 * @param type - pointer contening :
794 * - stride - stride of between noncontiguous data
795 * - block_length - the width or height of blocked matrix
796 * - count - the number of rows of matrix
798 void serialize_struct( const void *noncontiguous_struct,
799 void *contiguous_struct,
803 s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type;
805 char* contiguous_struct_char = (char*)contiguous_struct;
806 char* noncontiguous_struct_char = (char*)noncontiguous_struct;
807 for(j=0; j<count;j++){
808 for (i = 0; i < type_c->block_count; i++) {
809 if (type_c->old_types[i]->has_subtype == 0)
810 memcpy(contiguous_struct_char,
811 noncontiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i]));
813 ((s_smpi_subtype_t*)type_c->old_types[i]->substruct)->serialize( noncontiguous_struct_char,
814 contiguous_struct_char,
815 type_c->block_lengths[i],
816 type_c->old_types[i]->substruct);
819 contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]);
820 if (i<type_c->block_count-1)noncontiguous_struct_char = (char*)noncontiguous_struct + type_c->block_indices[i+1];
821 else noncontiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_types[i]);//let's hope this is MPI_UB ?
823 noncontiguous_struct=(void*)noncontiguous_struct_char;
827 * Copies contiguous data into noncontiguous memory.
828 * @param noncontiguous_struct - output struct
829 * @param contiguous_struct - input struct
830 * @param type - pointer contening :
831 * - stride - stride of between noncontiguous data
832 * - block_length - the width or height of blocked matrix
833 * - count - the number of rows of matrix
835 void unserialize_struct( const void *contiguous_struct,
836 void *noncontiguous_struct,
840 s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type;
843 char* contiguous_struct_char = (char*)contiguous_struct;
844 char* noncontiguous_struct_char = (char*)noncontiguous_struct;
845 for(j=0; j<count;j++){
846 for (i = 0; i < type_c->block_count; i++) {
847 if (type_c->old_types[i]->has_subtype == 0)
848 memcpy(noncontiguous_struct_char,
849 contiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i]));
851 ((s_smpi_subtype_t*)type_c->old_types[i]->substruct)->unserialize( contiguous_struct_char,
852 noncontiguous_struct_char,
853 type_c->block_lengths[i],
854 type_c->old_types[i]->substruct);
856 contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]);
857 if (i<type_c->block_count-1)noncontiguous_struct_char = (char*)noncontiguous_struct + type_c->block_indices[i+1];
858 else noncontiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_types[i]);
860 noncontiguous_struct=(void*)noncontiguous_struct_char;
865 void free_struct(MPI_Datatype* type){
866 xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->block_lengths);
867 xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->block_indices);
868 xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->old_types);
872 * Create a Sub type struct to be able to serialize and unserialize it
873 * the structure s_smpi_mpi_struct_t is derived from s_smpi_subtype which
874 * required the functions unserialize and serialize
876 s_smpi_mpi_struct_t* smpi_datatype_struct_create( int* block_lengths,
877 MPI_Aint* block_indices,
879 MPI_Datatype* old_types){
880 s_smpi_mpi_struct_t *new_t= xbt_new(s_smpi_mpi_struct_t,1);
881 new_t->base.serialize = &serialize_struct;
882 new_t->base.unserialize = &unserialize_struct;
883 new_t->base.subtype_free = &free_struct;
884 //TODO : add a custom function for each time to clean these
885 new_t->block_lengths= xbt_new(int, block_count);
886 new_t->block_indices= xbt_new(MPI_Aint, block_count);
887 new_t->old_types= xbt_new(MPI_Datatype, block_count);
889 for(i=0;i<block_count;i++){
890 new_t->block_lengths[i]=block_lengths[i];
891 new_t->block_indices[i]=block_indices[i];
892 new_t->old_types[i]=old_types[i];
894 //new_t->block_lengths = block_lengths;
895 //new_t->block_indices = block_indices;
896 new_t->block_count = block_count;
897 //new_t->old_types = old_types;
902 int smpi_datatype_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type)
908 for(i=0; i< count; i++){
911 if (old_types[i]->has_subtype == 1)
913 size += blocklens[i]*smpi_datatype_size(old_types[i]);
915 if ( (i< count -1) && (indices[i]+blocklens[i]*smpi_datatype_size(old_types[i]) != indices[i+1]) )contiguous=0;
919 s_smpi_mpi_struct_t* subtype = smpi_datatype_struct_create( blocklens,
924 smpi_datatype_create(new_type, size, indices[count-1] + blocklens[count-1]*smpi_datatype_size(old_types[count-1]),1, subtype, DT_FLAG_DATA);
926 smpi_datatype_create(new_type, size, indices[count-1] + blocklens[count-1]*smpi_datatype_size(old_types[count-1]),0, NULL, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
931 void smpi_datatype_commit(MPI_Datatype *datatype)
933 (*datatype)->flags= ((*datatype)->flags | DT_FLAG_COMMITED);
936 typedef struct s_smpi_mpi_op {
937 MPI_User_function *func;
940 #define MAX_OP(a, b) (b) = (a) < (b) ? (b) : (a)
941 #define MIN_OP(a, b) (b) = (a) < (b) ? (a) : (b)
942 #define SUM_OP(a, b) (b) += (a)
943 #define PROD_OP(a, b) (b) *= (a)
944 #define LAND_OP(a, b) (b) = (a) && (b)
945 #define LOR_OP(a, b) (b) = (a) || (b)
946 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
947 #define BAND_OP(a, b) (b) &= (a)
948 #define BOR_OP(a, b) (b) |= (a)
949 #define BXOR_OP(a, b) (b) ^= (a)
950 #define MAXLOC_OP(a, b) (b) = (a.value) < (b.value) ? (b) : (a)
951 #define MINLOC_OP(a, b) (b) = (a.value) < (b.value) ? (a) : (b)
952 //TODO : MINLOC & MAXLOC
954 #define APPLY_FUNC(a, b, length, type, func) \
957 type* x = (type*)(a); \
958 type* y = (type*)(b); \
959 for(i = 0; i < *(length); i++) { \
964 static void max_func(void *a, void *b, int *length,
965 MPI_Datatype * datatype)
967 if (*datatype == MPI_CHAR) {
968 APPLY_FUNC(a, b, length, char, MAX_OP);
969 } else if (*datatype == MPI_SHORT) {
970 APPLY_FUNC(a, b, length, short, MAX_OP);
971 } else if (*datatype == MPI_INT) {
972 APPLY_FUNC(a, b, length, int, MAX_OP);
973 } else if (*datatype == MPI_LONG) {
974 APPLY_FUNC(a, b, length, long, MAX_OP);
975 } else if (*datatype == MPI_UNSIGNED_SHORT) {
976 APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
977 } else if (*datatype == MPI_UNSIGNED) {
978 APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
979 } else if (*datatype == MPI_UNSIGNED_LONG) {
980 APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
981 } else if (*datatype == MPI_FLOAT) {
982 APPLY_FUNC(a, b, length, float, MAX_OP);
983 } else if (*datatype == MPI_DOUBLE) {
984 APPLY_FUNC(a, b, length, double, MAX_OP);
985 } else if (*datatype == MPI_LONG_DOUBLE) {
986 APPLY_FUNC(a, b, length, long double, MAX_OP);
990 static void min_func(void *a, void *b, int *length,
991 MPI_Datatype * datatype)
993 if (*datatype == MPI_CHAR) {
994 APPLY_FUNC(a, b, length, char, MIN_OP);
995 } else if (*datatype == MPI_SHORT) {
996 APPLY_FUNC(a, b, length, short, MIN_OP);
997 } else if (*datatype == MPI_INT) {
998 APPLY_FUNC(a, b, length, int, MIN_OP);
999 } else if (*datatype == MPI_LONG) {
1000 APPLY_FUNC(a, b, length, long, MIN_OP);
1001 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1002 APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
1003 } else if (*datatype == MPI_UNSIGNED) {
1004 APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
1005 } else if (*datatype == MPI_UNSIGNED_LONG) {
1006 APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
1007 } else if (*datatype == MPI_FLOAT) {
1008 APPLY_FUNC(a, b, length, float, MIN_OP);
1009 } else if (*datatype == MPI_DOUBLE) {
1010 APPLY_FUNC(a, b, length, double, MIN_OP);
1011 } else if (*datatype == MPI_LONG_DOUBLE) {
1012 APPLY_FUNC(a, b, length, long double, MIN_OP);
1016 static void sum_func(void *a, void *b, int *length,
1017 MPI_Datatype * datatype)
1019 if (*datatype == MPI_CHAR) {
1020 APPLY_FUNC(a, b, length, char, SUM_OP);
1021 } else if (*datatype == MPI_SHORT) {
1022 APPLY_FUNC(a, b, length, short, SUM_OP);
1023 } else if (*datatype == MPI_INT) {
1024 APPLY_FUNC(a, b, length, int, SUM_OP);
1025 } else if (*datatype == MPI_LONG) {
1026 APPLY_FUNC(a, b, length, long, SUM_OP);
1027 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1028 APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
1029 } else if (*datatype == MPI_UNSIGNED) {
1030 APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
1031 } else if (*datatype == MPI_UNSIGNED_LONG) {
1032 APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
1033 } else if (*datatype == MPI_FLOAT) {
1034 APPLY_FUNC(a, b, length, float, SUM_OP);
1035 } else if (*datatype == MPI_DOUBLE) {
1036 APPLY_FUNC(a, b, length, double, SUM_OP);
1037 } else if (*datatype == MPI_LONG_DOUBLE) {
1038 APPLY_FUNC(a, b, length, long double, SUM_OP);
1039 } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
1040 APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
1041 } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
1042 APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
1043 } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
1044 APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
1048 static void prod_func(void *a, void *b, int *length,
1049 MPI_Datatype * datatype)
1051 if (*datatype == MPI_CHAR) {
1052 APPLY_FUNC(a, b, length, char, PROD_OP);
1053 } else if (*datatype == MPI_SHORT) {
1054 APPLY_FUNC(a, b, length, short, PROD_OP);
1055 } else if (*datatype == MPI_INT) {
1056 APPLY_FUNC(a, b, length, int, PROD_OP);
1057 } else if (*datatype == MPI_LONG) {
1058 APPLY_FUNC(a, b, length, long, PROD_OP);
1059 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1060 APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
1061 } else if (*datatype == MPI_UNSIGNED) {
1062 APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
1063 } else if (*datatype == MPI_UNSIGNED_LONG) {
1064 APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
1065 } else if (*datatype == MPI_FLOAT) {
1066 APPLY_FUNC(a, b, length, float, PROD_OP);
1067 } else if (*datatype == MPI_DOUBLE) {
1068 APPLY_FUNC(a, b, length, double, PROD_OP);
1069 } else if (*datatype == MPI_LONG_DOUBLE) {
1070 APPLY_FUNC(a, b, length, long double, PROD_OP);
1071 } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
1072 APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
1073 } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
1074 APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
1075 } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
1076 APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
1080 static void land_func(void *a, void *b, int *length,
1081 MPI_Datatype * datatype)
1083 if (*datatype == MPI_CHAR) {
1084 APPLY_FUNC(a, b, length, char, LAND_OP);
1085 } else if (*datatype == MPI_SHORT) {
1086 APPLY_FUNC(a, b, length, short, LAND_OP);
1087 } else if (*datatype == MPI_INT) {
1088 APPLY_FUNC(a, b, length, int, LAND_OP);
1089 } else if (*datatype == MPI_LONG) {
1090 APPLY_FUNC(a, b, length, long, LAND_OP);
1091 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1092 APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
1093 } else if (*datatype == MPI_UNSIGNED) {
1094 APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
1095 } else if (*datatype == MPI_UNSIGNED_LONG) {
1096 APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
1097 } else if (*datatype == MPI_C_BOOL) {
1098 APPLY_FUNC(a, b, length, _Bool, LAND_OP);
1102 static void lor_func(void *a, void *b, int *length,
1103 MPI_Datatype * datatype)
1105 if (*datatype == MPI_CHAR) {
1106 APPLY_FUNC(a, b, length, char, LOR_OP);
1107 } else if (*datatype == MPI_SHORT) {
1108 APPLY_FUNC(a, b, length, short, LOR_OP);
1109 } else if (*datatype == MPI_INT) {
1110 APPLY_FUNC(a, b, length, int, LOR_OP);
1111 } else if (*datatype == MPI_LONG) {
1112 APPLY_FUNC(a, b, length, long, LOR_OP);
1113 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1114 APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
1115 } else if (*datatype == MPI_UNSIGNED) {
1116 APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
1117 } else if (*datatype == MPI_UNSIGNED_LONG) {
1118 APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
1119 } else if (*datatype == MPI_C_BOOL) {
1120 APPLY_FUNC(a, b, length, _Bool, LOR_OP);
1124 static void lxor_func(void *a, void *b, int *length,
1125 MPI_Datatype * datatype)
1127 if (*datatype == MPI_CHAR) {
1128 APPLY_FUNC(a, b, length, char, LXOR_OP);
1129 } else if (*datatype == MPI_SHORT) {
1130 APPLY_FUNC(a, b, length, short, LXOR_OP);
1131 } else if (*datatype == MPI_INT) {
1132 APPLY_FUNC(a, b, length, int, LXOR_OP);
1133 } else if (*datatype == MPI_LONG) {
1134 APPLY_FUNC(a, b, length, long, LXOR_OP);
1135 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1136 APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
1137 } else if (*datatype == MPI_UNSIGNED) {
1138 APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
1139 } else if (*datatype == MPI_UNSIGNED_LONG) {
1140 APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
1141 } else if (*datatype == MPI_C_BOOL) {
1142 APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
1146 static void band_func(void *a, void *b, int *length,
1147 MPI_Datatype * datatype)
1149 if (*datatype == MPI_CHAR) {
1150 APPLY_FUNC(a, b, length, char, BAND_OP);
1152 if (*datatype == MPI_SHORT) {
1153 APPLY_FUNC(a, b, length, short, BAND_OP);
1154 } else if (*datatype == MPI_INT) {
1155 APPLY_FUNC(a, b, length, int, BAND_OP);
1156 } else if (*datatype == MPI_LONG) {
1157 APPLY_FUNC(a, b, length, long, BAND_OP);
1158 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1159 APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
1160 } else if (*datatype == MPI_UNSIGNED) {
1161 APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
1162 } else if (*datatype == MPI_UNSIGNED_LONG) {
1163 APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
1164 } else if (*datatype == MPI_BYTE) {
1165 APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
1169 static void bor_func(void *a, void *b, int *length,
1170 MPI_Datatype * datatype)
1172 if (*datatype == MPI_CHAR) {
1173 APPLY_FUNC(a, b, length, char, BOR_OP);
1174 } else if (*datatype == MPI_SHORT) {
1175 APPLY_FUNC(a, b, length, short, BOR_OP);
1176 } else if (*datatype == MPI_INT) {
1177 APPLY_FUNC(a, b, length, int, BOR_OP);
1178 } else if (*datatype == MPI_LONG) {
1179 APPLY_FUNC(a, b, length, long, BOR_OP);
1180 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1181 APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
1182 } else if (*datatype == MPI_UNSIGNED) {
1183 APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
1184 } else if (*datatype == MPI_UNSIGNED_LONG) {
1185 APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
1186 } else if (*datatype == MPI_BYTE) {
1187 APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
1191 static void bxor_func(void *a, void *b, int *length,
1192 MPI_Datatype * datatype)
1194 if (*datatype == MPI_CHAR) {
1195 APPLY_FUNC(a, b, length, char, BXOR_OP);
1196 } else if (*datatype == MPI_SHORT) {
1197 APPLY_FUNC(a, b, length, short, BXOR_OP);
1198 } else if (*datatype == MPI_INT) {
1199 APPLY_FUNC(a, b, length, int, BXOR_OP);
1200 } else if (*datatype == MPI_LONG) {
1201 APPLY_FUNC(a, b, length, long, BXOR_OP);
1202 } else if (*datatype == MPI_UNSIGNED_SHORT) {
1203 APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
1204 } else if (*datatype == MPI_UNSIGNED) {
1205 APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
1206 } else if (*datatype == MPI_UNSIGNED_LONG) {
1207 APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
1208 } else if (*datatype == MPI_BYTE) {
1209 APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
1213 static void minloc_func(void *a, void *b, int *length,
1214 MPI_Datatype * datatype)
1216 if (*datatype == MPI_FLOAT_INT) {
1217 APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
1218 } else if (*datatype == MPI_LONG_INT) {
1219 APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
1220 } else if (*datatype == MPI_DOUBLE_INT) {
1221 APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
1222 } else if (*datatype == MPI_SHORT_INT) {
1223 APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
1224 } else if (*datatype == MPI_2INT) {
1225 APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
1226 } else if (*datatype == MPI_LONG_DOUBLE_INT) {
1227 APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
1228 } else if (*datatype == MPI_2FLOAT) {
1229 APPLY_FUNC(a, b, length, float_float, MINLOC_OP);
1230 } else if (*datatype == MPI_2DOUBLE) {
1231 APPLY_FUNC(a, b, length, double_double, MINLOC_OP);
1235 static void maxloc_func(void *a, void *b, int *length,
1236 MPI_Datatype * datatype)
1238 if (*datatype == MPI_FLOAT_INT) {
1239 APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
1240 } else if (*datatype == MPI_LONG_INT) {
1241 APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
1242 } else if (*datatype == MPI_DOUBLE_INT) {
1243 APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
1244 } else if (*datatype == MPI_SHORT_INT) {
1245 APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
1246 } else if (*datatype == MPI_2INT) {
1247 APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
1248 } else if (*datatype == MPI_LONG_DOUBLE_INT) {
1249 APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
1250 } else if (*datatype == MPI_2FLOAT) {
1251 APPLY_FUNC(a, b, length, float_float, MAXLOC_OP);
1252 } else if (*datatype == MPI_2DOUBLE) {
1253 APPLY_FUNC(a, b, length, double_double, MAXLOC_OP);
1258 #define CREATE_MPI_OP(name, func) \
1259 static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
1260 MPI_Op name = &mpi_##name;
1262 CREATE_MPI_OP(MPI_MAX, max_func);
1263 CREATE_MPI_OP(MPI_MIN, min_func);
1264 CREATE_MPI_OP(MPI_SUM, sum_func);
1265 CREATE_MPI_OP(MPI_PROD, prod_func);
1266 CREATE_MPI_OP(MPI_LAND, land_func);
1267 CREATE_MPI_OP(MPI_LOR, lor_func);
1268 CREATE_MPI_OP(MPI_LXOR, lxor_func);
1269 CREATE_MPI_OP(MPI_BAND, band_func);
1270 CREATE_MPI_OP(MPI_BOR, bor_func);
1271 CREATE_MPI_OP(MPI_BXOR, bxor_func);
1272 CREATE_MPI_OP(MPI_MAXLOC, maxloc_func);
1273 CREATE_MPI_OP(MPI_MINLOC, minloc_func);
1275 MPI_Op smpi_op_new(MPI_User_function * function, int commute)
1279 //FIXME: add commute param
1280 op = xbt_new(s_smpi_mpi_op_t, 1);
1281 op->func = function;
1285 void smpi_op_destroy(MPI_Op op)
1290 void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len,
1291 MPI_Datatype * datatype)
1293 op->func(invec, inoutvec, len, datatype);