Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid into...
[simgrid.git] / src / smpi / smpi_mpi_dt.c
1 /* smpi_mpi_dt.c -- MPI primitives to handle datatypes                        */
2 /* FIXME: a very incomplete implementation                                    */
3
4 /* Copyright (c) 2009, 2010. The SimGrid Team.
5  * All rights reserved.                                                     */
6
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. */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "private.h"
15 #include "smpi_mpi_dt_private.h"
16
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
18                                 "Logging specific to SMPI (datatype)");
19
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*/             \
24     0,             /* lb */                   \
25     sizeof(type),  /* ub = lb + size */       \
26     DT_FLAG_BASIC,  /* flags */              \
27     NULL           /* pointer on extended struct*/ \
28   };                                          \
29 MPI_Datatype name = &mpi_##name;
30
31 #define CREATE_MPI_DATATYPE_NULL(name)       \
32   static s_smpi_mpi_datatype_t mpi_##name = { \
33     0,  /* size */                 \
34     0,             /*was 1 has_subtype*/             \
35     0,             /* lb */                   \
36     0,  /* ub = lb + size */       \
37     DT_FLAG_BASIC,  /* flags */              \
38     NULL           /* pointer on extended struct*/ \
39   };                                          \
40 MPI_Datatype name = &mpi_##name;
41
42 //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC.
43 typedef struct {
44   float value;
45   int index;
46 } float_int;
47 typedef struct {
48   float value;
49   float index;
50 } float_float;
51 typedef struct {
52   double value;
53   double index;
54 } double_double;
55 typedef struct {
56   long value;
57   int index;
58 } long_int;
59 typedef struct {
60   double value;
61   int index;
62 } double_int;
63 typedef struct {
64   short value;
65   int index;
66 } short_int;
67 typedef struct {
68   int value;
69   int index;
70 } int_int;
71 typedef struct {
72   long double value;
73   int index;
74 } long_double_int;
75
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);
106
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);
114
115 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int);
116
117 CREATE_MPI_DATATYPE_NULL(MPI_UB);
118 CREATE_MPI_DATATYPE_NULL(MPI_LB);
119 CREATE_MPI_DATATYPE_NULL(MPI_PACKED);
120 // Internal use only
121 CREATE_MPI_DATATYPE(MPI_PTR, void*);
122
123
124 size_t smpi_datatype_size(MPI_Datatype datatype)
125 {
126   return datatype->size;
127 }
128
129
130
131 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype)
132 {
133   return datatype->lb;
134 }
135
136 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype)
137 {
138   return datatype->ub;
139 }
140
141 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
142                          MPI_Aint * extent)
143 {
144   *lb = datatype->lb;
145   *extent = datatype->ub - datatype->lb;
146   return MPI_SUCCESS;
147 }
148
149 MPI_Aint smpi_datatype_get_extent(MPI_Datatype datatype){
150   return datatype->ub - datatype->lb;
151 }
152
153 int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype,
154                        void *recvbuf, int recvcount, MPI_Datatype recvtype)
155 {
156   int retval, count;
157
158   /* First check if we really have something to do */
159   if (recvcount == 0) {
160     retval = sendcount == 0 ? MPI_SUCCESS : MPI_ERR_TRUNCATE;
161   } else {
162     /* FIXME: treat packed cases */
163     sendcount *= smpi_datatype_size(sendtype);
164     recvcount *= smpi_datatype_size(recvtype);
165     count = sendcount < recvcount ? sendcount : recvcount;
166
167     if(sendtype->has_subtype == 0 && recvtype->has_subtype == 0) {
168       memcpy(recvbuf, sendbuf, count);
169     }
170     else if (sendtype->has_subtype == 0)
171     {
172       s_smpi_subtype_t *subtype =  recvtype->substruct;
173       subtype->unserialize( sendbuf, recvbuf,1, subtype);
174     }
175     else if (recvtype->has_subtype == 0)
176     {
177       s_smpi_subtype_t *subtype =  sendtype->substruct;
178       subtype->serialize(sendbuf, recvbuf,1, subtype);
179     }else{
180       s_smpi_subtype_t *subtype =  sendtype->substruct;
181
182       s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)sendtype;
183
184       void * buf_tmp = malloc(count * type_c->size_oldtype);
185
186       subtype->serialize( sendbuf, buf_tmp,1, subtype);
187       subtype =  recvtype->substruct;
188       subtype->unserialize(recvbuf, buf_tmp,1, subtype);
189
190       free(buf_tmp);
191     }
192     retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
193   }
194
195   return retval;
196 }
197
198 /*
199  *  Copies noncontiguous data into contiguous memory.
200  *  @param contiguous_vector - output vector
201  *  @param noncontiguous_vector - input vector
202  *  @param type - pointer contening :
203  *      - stride - stride of between noncontiguous data
204  *      - block_length - the width or height of blocked matrix
205  *      - count - the number of rows of matrix
206  */
207 void serialize_vector( const void *noncontiguous_vector,
208                        void *contiguous_vector,
209                        size_t count,
210                        void *type)
211 {
212   s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)type;
213   int i;
214   char* contiguous_vector_char = (char*)contiguous_vector;
215   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
216
217   for (i = 0; i < type_c->block_count * count; i++) {
218       if (type_c->old_type->has_subtype == 0)
219         memcpy(contiguous_vector_char,
220                noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype);
221       else
222         ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_vector_char,
223                                                                      contiguous_vector_char,
224                                                                      type_c->block_length,
225                                                                      type_c->old_type->substruct);
226
227     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
228     noncontiguous_vector_char += type_c->block_stride*smpi_datatype_get_extent(type_c->old_type);
229   }
230 }
231
232 /*
233  *  Copies contiguous data into noncontiguous memory.
234  *  @param noncontiguous_vector - output vector
235  *  @param contiguous_vector - input vector
236  *  @param type - pointer contening :
237  *      - stride - stride of between noncontiguous data
238  *      - block_length - the width or height of blocked matrix
239  *      - count - the number of rows of matrix
240  */
241 void unserialize_vector( const void *contiguous_vector,
242                          void *noncontiguous_vector,
243                          size_t count,
244                          void *type)
245 {
246   s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)type;
247   int i;
248
249   char* contiguous_vector_char = (char*)contiguous_vector;
250   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
251
252   for (i = 0; i < type_c->block_count * count; i++) {
253     if (type_c->old_type->has_subtype == 0)
254       memcpy(noncontiguous_vector_char,
255              contiguous_vector_char, type_c->block_length * type_c->size_oldtype);
256     else
257       ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_vector_char,
258                                                                      noncontiguous_vector_char,
259                                                                      type_c->block_length,
260                                                                      type_c->old_type->substruct);
261     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
262     noncontiguous_vector_char += type_c->block_stride*smpi_datatype_get_extent(type_c->old_type);
263   }
264 }
265
266 /*
267  * Create a Sub type vector to be able to serialize and unserialize it
268  * the structure s_smpi_mpi_vector_t is derived from s_smpi_subtype which
269  * required the functions unserialize and serialize
270  *
271  */
272 s_smpi_mpi_vector_t* smpi_datatype_vector_create( int block_stride,
273                                                   int block_length,
274                                                   int block_count,
275                                                   MPI_Datatype old_type,
276                                                   int size_oldtype){
277   s_smpi_mpi_vector_t *new_t= xbt_new(s_smpi_mpi_vector_t,1);
278   new_t->base.serialize = &serialize_vector;
279   new_t->base.unserialize = &unserialize_vector;
280   new_t->base.subtype_free = &free_vector;
281   new_t->block_stride = block_stride;
282   new_t->block_length = block_length;
283   new_t->block_count = block_count;
284   new_t->old_type = old_type;
285   new_t->size_oldtype = size_oldtype;
286   return new_t;
287 }
288
289 void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int has_subtype,
290                           void *struct_type, int flags){
291   MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1);
292   new_t->size = size;
293   new_t->has_subtype = has_subtype;
294   new_t->lb = lb;
295   new_t->ub = ub;
296   new_t->flags = flags;
297   new_t->substruct = struct_type;
298   *new_type = new_t;
299 }
300
301 void smpi_datatype_free(MPI_Datatype* type){
302   if ((*type)->has_subtype == 1){
303     ((s_smpi_subtype_t *)(*type)->substruct)->subtype_free(type);  
304   }
305   xbt_free(*type);
306 }
307
308 int smpi_datatype_contiguous(int count, MPI_Datatype old_type, MPI_Datatype* new_type)
309 {
310   int retval;
311   if(old_type->has_subtype){
312           //handle this case as a hvector with stride equals to the extent of the datatype
313           return smpi_datatype_hvector(count, 1, smpi_datatype_get_extent(old_type), old_type, new_type);
314   }
315   smpi_datatype_create(new_type,
316                                           count * smpi_datatype_size(old_type),
317                                           0,count * smpi_datatype_size(old_type),
318                                           0,NULL, DT_FLAG_CONTIGUOUS);
319   retval=MPI_SUCCESS;
320   return retval;
321 }
322
323 int smpi_datatype_vector(int count, int blocklen, int stride, MPI_Datatype old_type, MPI_Datatype* new_type)
324 {
325   int retval;
326   if (blocklen<=0) return MPI_ERR_ARG;
327   MPI_Aint lb = 0;
328   MPI_Aint ub = 0;
329   if(count>0){
330     lb=smpi_datatype_lb(old_type);
331     ub=((count-1)*stride+blocklen-1)*smpi_datatype_get_extent(old_type)+smpi_datatype_ub(old_type);
332   }
333   if(old_type->has_subtype || stride != blocklen){
334
335
336     s_smpi_mpi_vector_t* subtype = smpi_datatype_vector_create( stride,
337                                                                 blocklen,
338                                                                 count,
339                                                                 old_type,
340                                                                 smpi_datatype_size(old_type));
341     smpi_datatype_create(new_type,
342                          count * (blocklen) * smpi_datatype_size(old_type), lb,
343                          ub,
344                          1,
345                          subtype,
346                          DT_FLAG_VECTOR);
347     retval=MPI_SUCCESS;
348   }else{
349     /* in this situation the data are contignous thus it's not
350      * required to serialize and unserialize it*/
351     smpi_datatype_create(new_type, count * blocklen *
352                          smpi_datatype_size(old_type), 0, ((count -1) * stride + blocklen)*
353                          smpi_datatype_size(old_type),
354                          0,
355                          NULL,
356                          DT_FLAG_VECTOR|DT_FLAG_CONTIGUOUS);
357     retval=MPI_SUCCESS;
358   }
359   return retval;
360 }
361
362 void free_vector(MPI_Datatype* d){
363 }
364
365 /*
366 Hvector Implementation - Vector with stride in bytes
367 */
368
369
370 /*
371  *  Copies noncontiguous data into contiguous memory.
372  *  @param contiguous_hvector - output hvector
373  *  @param noncontiguous_hvector - input hvector
374  *  @param type - pointer contening :
375  *      - stride - stride of between noncontiguous data, in bytes
376  *      - block_length - the width or height of blocked matrix
377  *      - count - the number of rows of matrix
378  */
379 void serialize_hvector( const void *noncontiguous_hvector,
380                        void *contiguous_hvector,
381                        size_t count,
382                        void *type)
383 {
384   s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type;
385   int i;
386   char* contiguous_vector_char = (char*)contiguous_hvector;
387   char* noncontiguous_vector_char = (char*)noncontiguous_hvector;
388
389   for (i = 0; i < type_c->block_count * count; i++) {
390     if (type_c->old_type->has_subtype == 0)
391       memcpy(contiguous_vector_char,
392            noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype);
393     else
394       ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_vector_char,
395                                                                    contiguous_vector_char,
396                                                                    type_c->block_length,
397                                                                    type_c->old_type->substruct);
398
399     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
400     noncontiguous_vector_char += type_c->block_stride;
401   }
402 }
403 /*
404  *  Copies contiguous data into noncontiguous memory.
405  *  @param noncontiguous_vector - output hvector
406  *  @param contiguous_vector - input hvector
407  *  @param type - pointer contening :
408  *      - stride - stride of between noncontiguous data, in bytes
409  *      - block_length - the width or height of blocked matrix
410  *      - count - the number of rows of matrix
411  */
412 void unserialize_hvector( const void *contiguous_vector,
413                          void *noncontiguous_vector,
414                          size_t count,
415                          void *type)
416 {
417   s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type;
418   int i;
419
420   char* contiguous_vector_char = (char*)contiguous_vector;
421   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
422
423   for (i = 0; i < type_c->block_count * count; i++) {
424     if (type_c->old_type->has_subtype == 0)
425       memcpy(noncontiguous_vector_char,
426            contiguous_vector_char, type_c->block_length * type_c->size_oldtype);
427     else
428       ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_vector_char,
429                                                                      noncontiguous_vector_char,
430                                                                      type_c->block_length,
431                                                                      type_c->old_type->substruct);
432     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
433     noncontiguous_vector_char += type_c->block_stride;
434   }
435 }
436
437 /*
438  * Create a Sub type vector to be able to serialize and unserialize it
439  * the structure s_smpi_mpi_vector_t is derived from s_smpi_subtype which
440  * required the functions unserialize and serialize
441  *
442  */
443 s_smpi_mpi_hvector_t* smpi_datatype_hvector_create( MPI_Aint block_stride,
444                                                   int block_length,
445                                                   int block_count,
446                                                   MPI_Datatype old_type,
447                                                   int size_oldtype){
448   s_smpi_mpi_hvector_t *new_t= xbt_new(s_smpi_mpi_hvector_t,1);
449   new_t->base.serialize = &serialize_hvector;
450   new_t->base.unserialize = &unserialize_hvector;
451   new_t->base.subtype_free = &free_hvector;
452   new_t->block_stride = block_stride;
453   new_t->block_length = block_length;
454   new_t->block_count = block_count;
455   new_t->old_type = old_type;
456   new_t->size_oldtype = size_oldtype;
457   return new_t;
458 }
459
460 //do nothing for vector types
461 void free_hvector(MPI_Datatype* d){
462 }
463
464 int smpi_datatype_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type)
465 {
466   int retval;
467   if (blocklen<=0) return MPI_ERR_ARG;
468   MPI_Aint lb = 0;
469   MPI_Aint ub = 0;
470   if(count>0){
471     lb=smpi_datatype_lb(old_type);
472     ub=((count-1)*stride)+(blocklen-1)*smpi_datatype_get_extent(old_type)+smpi_datatype_ub(old_type);
473   }
474   if(old_type->has_subtype || stride != blocklen*smpi_datatype_get_extent(old_type)){
475     s_smpi_mpi_hvector_t* subtype = smpi_datatype_hvector_create( stride,
476                                                                   blocklen,
477                                                                   count,
478                                                                   old_type,
479                                                                   smpi_datatype_size(old_type));
480
481     smpi_datatype_create(new_type, count * blocklen * smpi_datatype_size(old_type),
482                                                  lb,ub,
483                          1,
484                          subtype,
485                          DT_FLAG_VECTOR);
486     retval=MPI_SUCCESS;
487   }else{
488     smpi_datatype_create(new_type, count * blocklen *
489                                              smpi_datatype_size(old_type),0,count * blocklen *
490                                              smpi_datatype_size(old_type),
491                                             0,
492                                             NULL,
493                                             DT_FLAG_VECTOR|DT_FLAG_CONTIGUOUS);
494     retval=MPI_SUCCESS;
495   }
496   return retval;
497 }
498
499
500 /*
501 Indexed Implementation
502 */
503
504 /*
505  *  Copies noncontiguous data into contiguous memory.
506  *  @param contiguous_indexed - output indexed
507  *  @param noncontiguous_indexed - input indexed
508  *  @param type - pointer contening :
509  *      - block_lengths - the width or height of blocked matrix
510  *      - block_indices - indices of each data, in element
511  *      - count - the number of rows of matrix
512  */
513 void serialize_indexed( const void *noncontiguous_indexed,
514                        void *contiguous_indexed,
515                        size_t count,
516                        void *type)
517 {
518   s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type;
519   int i,j;
520   char* contiguous_indexed_char = (char*)contiguous_indexed;
521   char* noncontiguous_indexed_char = (char*)noncontiguous_indexed;
522   for(j=0; j<count;j++){
523     for (i = 0; i < type_c->block_count; i++) {
524       if (type_c->old_type->has_subtype == 0)
525         memcpy(contiguous_indexed_char,
526                      noncontiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
527       else
528         ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_indexed_char,
529                                                                      contiguous_indexed_char,
530                                                                      type_c->block_lengths[i],
531                                                                      type_c->old_type->substruct);
532
533
534       contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
535       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);
536       else noncontiguous_indexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
537     }
538     noncontiguous_indexed=(void*)noncontiguous_indexed_char;
539   }
540 }
541 /*
542  *  Copies contiguous data into noncontiguous memory.
543  *  @param noncontiguous_indexed - output indexed
544  *  @param contiguous_indexed - input indexed
545  *  @param type - pointer contening :
546  *      - block_lengths - the width or height of blocked matrix
547  *      - block_indices - indices of each data, in element
548  *      - count - the number of rows of matrix
549  */
550 void unserialize_indexed( const void *contiguous_indexed,
551                          void *noncontiguous_indexed,
552                          size_t count,
553                          void *type)
554 {
555   s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type;
556   int i,j;
557
558   char* contiguous_indexed_char = (char*)contiguous_indexed;
559   char* noncontiguous_indexed_char = (char*)noncontiguous_indexed;
560   for(j=0; j<count;j++){
561     for (i = 0; i < type_c->block_count; i++) {
562       if (type_c->old_type->has_subtype == 0)
563         memcpy(noncontiguous_indexed_char,
564              contiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
565       else
566         ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_indexed_char,
567                                                                        noncontiguous_indexed_char,
568                                                                        type_c->block_lengths[i],
569                                                                        type_c->old_type->substruct);
570
571       contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
572       if (i<type_c->block_count-1)
573         noncontiguous_indexed_char = (char*)noncontiguous_indexed + type_c->block_indices[i+1]*smpi_datatype_get_extent(type_c->old_type);
574       else noncontiguous_indexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
575     }
576     noncontiguous_indexed=(void*)noncontiguous_indexed_char;
577   }
578 }
579
580 void free_indexed(MPI_Datatype* type){
581   xbt_free(((s_smpi_mpi_indexed_t *)(*type)->substruct)->block_lengths);
582   xbt_free(((s_smpi_mpi_indexed_t *)(*type)->substruct)->block_indices);
583 }
584
585 /*
586  * Create a Sub type indexed to be able to serialize and unserialize it
587  * the structure s_smpi_mpi_indexed_t is derived from s_smpi_subtype which
588  * required the functions unserialize and serialize
589  */
590 s_smpi_mpi_indexed_t* smpi_datatype_indexed_create( int* block_lengths,
591                                                   int* block_indices,
592                                                   int block_count,
593                                                   MPI_Datatype old_type,
594                                                   int size_oldtype){
595   s_smpi_mpi_indexed_t *new_t= xbt_new(s_smpi_mpi_indexed_t,1);
596   new_t->base.serialize = &serialize_indexed;
597   new_t->base.unserialize = &unserialize_indexed;
598   new_t->base.subtype_free = &free_indexed;
599  //TODO : add a custom function for each time to clean these 
600   new_t->block_lengths= xbt_new(int, block_count);
601   new_t->block_indices= xbt_new(int, block_count);
602   int i;
603   for(i=0;i<block_count;i++){
604     new_t->block_lengths[i]=block_lengths[i];
605     new_t->block_indices[i]=block_indices[i];
606   }
607   new_t->block_count = block_count;
608   new_t->old_type = old_type;
609   new_t->size_oldtype = size_oldtype;
610   return new_t;
611 }
612
613
614 int smpi_datatype_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
615 {
616   int i;
617   int retval;
618   int size = 0;
619   int contiguous=1;
620   MPI_Aint lb = 0;
621   MPI_Aint ub = 0;
622   if(count>0){
623     lb=indices[0]*smpi_datatype_get_extent(old_type);
624     ub=indices[0]*smpi_datatype_get_extent(old_type) + blocklens[0]*smpi_datatype_ub(old_type);
625   }
626
627   for(i=0; i< count; i++){
628     if   (blocklens[i]<=0)
629       return MPI_ERR_ARG;
630     size += blocklens[i];
631
632     if(indices[i]*smpi_datatype_get_extent(old_type)+smpi_datatype_lb(old_type)<lb)
633         lb = indices[i]*smpi_datatype_get_extent(old_type)+smpi_datatype_lb(old_type);
634     if(indices[i]*smpi_datatype_get_extent(old_type)+blocklens[i]*smpi_datatype_ub(old_type)>ub)
635         ub = indices[i]*smpi_datatype_get_extent(old_type)+blocklens[i]*smpi_datatype_ub(old_type);
636
637     if ( (i< count -1) && (indices[i]+blocklens[i] != indices[i+1]) )contiguous=0;
638   }
639   if (old_type->has_subtype == 1)
640     contiguous=0;
641
642   if(!contiguous){
643     s_smpi_mpi_indexed_t* subtype = smpi_datatype_indexed_create( blocklens,
644                                                                   indices,
645                                                                   count,
646                                                                   old_type,
647                                                                   smpi_datatype_size(old_type));
648      smpi_datatype_create(new_type,  size *
649                          smpi_datatype_size(old_type),lb,ub,1, subtype, DT_FLAG_DATA);
650   }else{
651     smpi_datatype_create(new_type,  size *
652                          smpi_datatype_size(old_type),0,size *
653                          smpi_datatype_size(old_type),0, NULL, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
654   }
655   retval=MPI_SUCCESS;
656   return retval;
657 }
658
659
660 /*
661 Hindexed Implementation - Indexed with indices in bytes 
662 */
663
664 /*
665  *  Copies noncontiguous data into contiguous memory.
666  *  @param contiguous_hindexed - output hindexed
667  *  @param noncontiguous_hindexed - input hindexed
668  *  @param type - pointer contening :
669  *      - block_lengths - the width or height of blocked matrix
670  *      - block_indices - indices of each data, in bytes
671  *      - count - the number of rows of matrix
672  */
673 void serialize_hindexed( const void *noncontiguous_hindexed,
674                        void *contiguous_hindexed,
675                        size_t count,
676                        void *type)
677 {
678   s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type;
679   int i,j;
680   char* contiguous_hindexed_char = (char*)contiguous_hindexed;
681   char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed;
682   for(j=0; j<count;j++){
683     for (i = 0; i < type_c->block_count; i++) {
684       if (type_c->old_type->has_subtype == 0)
685         memcpy(contiguous_hindexed_char,
686                      noncontiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
687       else
688         ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_hindexed_char,
689                                                                      contiguous_hindexed_char,
690                                                                      type_c->block_lengths[i],
691                                                                      type_c->old_type->substruct);
692
693       contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
694       if (i<type_c->block_count-1)noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1];
695       else noncontiguous_hindexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
696     }
697     noncontiguous_hindexed=(void*)noncontiguous_hindexed_char;
698   }
699 }
700 /*
701  *  Copies contiguous data into noncontiguous memory.
702  *  @param noncontiguous_hindexed - output hindexed
703  *  @param contiguous_hindexed - input hindexed
704  *  @param type - pointer contening :
705  *      - block_lengths - the width or height of blocked matrix
706  *      - block_indices - indices of each data, in bytes
707  *      - count - the number of rows of matrix
708  */
709 void unserialize_hindexed( const void *contiguous_hindexed,
710                          void *noncontiguous_hindexed,
711                          size_t count,
712                          void *type)
713 {
714   s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type;
715   int i,j;
716
717   char* contiguous_hindexed_char = (char*)contiguous_hindexed;
718   char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed;
719   for(j=0; j<count;j++){
720     for (i = 0; i < type_c->block_count; i++) {
721       if (type_c->old_type->has_subtype == 0)
722         memcpy(noncontiguous_hindexed_char,
723                contiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
724       else
725         ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_hindexed_char,
726                                                                        noncontiguous_hindexed_char,
727                                                                        type_c->block_lengths[i],
728                                                                        type_c->old_type->substruct);
729
730       contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
731       if (i<type_c->block_count-1)noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1];
732       else noncontiguous_hindexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
733     }
734     noncontiguous_hindexed=(void*)noncontiguous_hindexed_char;
735   }
736 }
737
738 void free_hindexed(MPI_Datatype* type){
739   xbt_free(((s_smpi_mpi_hindexed_t *)(*type)->substruct)->block_lengths);
740   xbt_free(((s_smpi_mpi_hindexed_t *)(*type)->substruct)->block_indices);
741 }
742
743 /*
744  * Create a Sub type hindexed to be able to serialize and unserialize it
745  * the structure s_smpi_mpi_hindexed_t is derived from s_smpi_subtype which
746  * required the functions unserialize and serialize
747  */
748 s_smpi_mpi_hindexed_t* smpi_datatype_hindexed_create( int* block_lengths,
749                                                   MPI_Aint* block_indices,
750                                                   int block_count,
751                                                   MPI_Datatype old_type,
752                                                   int size_oldtype){
753   s_smpi_mpi_hindexed_t *new_t= xbt_new(s_smpi_mpi_hindexed_t,1);
754   new_t->base.serialize = &serialize_hindexed;
755   new_t->base.unserialize = &unserialize_hindexed;
756   new_t->base.subtype_free = &free_hindexed;
757  //TODO : add a custom function for each time to clean these 
758   new_t->block_lengths= xbt_new(int, block_count);
759   new_t->block_indices= xbt_new(MPI_Aint, block_count);
760   int i;
761   for(i=0;i<block_count;i++){
762     new_t->block_lengths[i]=block_lengths[i];
763     new_t->block_indices[i]=block_indices[i];
764   }
765   new_t->block_count = block_count;
766   new_t->old_type = old_type;
767   new_t->size_oldtype = size_oldtype;
768   return new_t;
769 }
770
771
772 int smpi_datatype_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
773 {
774   int i;
775   int retval;
776   int size = 0;
777   int contiguous=1;
778   MPI_Aint lb = 0;
779   MPI_Aint ub = 0;
780   if(count>0){
781     lb=indices[0] + smpi_datatype_lb(old_type);
782     ub=indices[0] + blocklens[0]*smpi_datatype_ub(old_type);
783   }
784   for(i=0; i< count; i++){
785     if   (blocklens[i]<=0)
786       return MPI_ERR_ARG;
787     size += blocklens[i];
788
789     if(indices[i]+smpi_datatype_lb(old_type)<lb) lb = indices[i]+smpi_datatype_lb(old_type);
790     if(indices[i]+blocklens[i]*smpi_datatype_ub(old_type)>ub) ub = indices[i]+blocklens[i]*smpi_datatype_ub(old_type);
791
792     if ( (i< count -1) && (indices[i]+blocklens[i]*smpi_datatype_size(old_type) != indices[i+1]) )contiguous=0;
793   }
794   if (old_type->has_subtype == 1 || lb!=0)
795     contiguous=0;
796
797   if(!contiguous){
798     s_smpi_mpi_hindexed_t* subtype = smpi_datatype_hindexed_create( blocklens,
799                                                                   indices,
800                                                                   count,
801                                                                   old_type,
802                                                                   smpi_datatype_size(old_type));
803     smpi_datatype_create(new_type,  size * smpi_datatype_size(old_type),
804                                                  lb,
805                          ub
806                          ,1, subtype, DT_FLAG_DATA);
807   }else{
808     smpi_datatype_create(new_type,  size * smpi_datatype_size(old_type),
809                                              0,size * smpi_datatype_size(old_type),
810                                              0, NULL, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
811   }
812   retval=MPI_SUCCESS;
813   return retval;
814 }
815
816
817 /*
818 struct Implementation - Indexed with indices in bytes 
819 */
820
821 /*
822  *  Copies noncontiguous data into contiguous memory.
823  *  @param contiguous_struct - output struct
824  *  @param noncontiguous_struct - input struct
825  *  @param type - pointer contening :
826  *      - stride - stride of between noncontiguous data
827  *      - block_length - the width or height of blocked matrix
828  *      - count - the number of rows of matrix
829  */
830 void serialize_struct( const void *noncontiguous_struct,
831                        void *contiguous_struct,
832                        size_t count,
833                        void *type)
834 {
835   s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type;
836   int i,j;
837   char* contiguous_struct_char = (char*)contiguous_struct;
838   char* noncontiguous_struct_char = (char*)noncontiguous_struct;
839   for(j=0; j<count;j++){
840     for (i = 0; i < type_c->block_count; i++) {
841       if (type_c->old_types[i]->has_subtype == 0)
842         memcpy(contiguous_struct_char,
843              noncontiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i]));
844       else
845         ((s_smpi_subtype_t*)type_c->old_types[i]->substruct)->serialize( noncontiguous_struct_char,
846                                                                          contiguous_struct_char,
847                                                                          type_c->block_lengths[i],
848                                                                          type_c->old_types[i]->substruct);
849
850
851       contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]);
852       if (i<type_c->block_count-1)noncontiguous_struct_char = (char*)noncontiguous_struct + type_c->block_indices[i+1];
853       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 ?
854     }
855     noncontiguous_struct=(void*)noncontiguous_struct_char;
856   }
857 }
858 /*
859  *  Copies contiguous data into noncontiguous memory.
860  *  @param noncontiguous_struct - output struct
861  *  @param contiguous_struct - input struct
862  *  @param type - pointer contening :
863  *      - stride - stride of between noncontiguous data
864  *      - block_length - the width or height of blocked matrix
865  *      - count - the number of rows of matrix
866  */
867 void unserialize_struct( const void *contiguous_struct,
868                          void *noncontiguous_struct,
869                          size_t count,
870                          void *type)
871 {
872   s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type;
873   int i,j;
874
875   char* contiguous_struct_char = (char*)contiguous_struct;
876   char* noncontiguous_struct_char = (char*)noncontiguous_struct;
877   for(j=0; j<count;j++){
878     for (i = 0; i < type_c->block_count; i++) {
879       if (type_c->old_types[i]->has_subtype == 0)
880         memcpy(noncontiguous_struct_char,
881              contiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i]));
882       else
883         ((s_smpi_subtype_t*)type_c->old_types[i]->substruct)->unserialize( contiguous_struct_char,
884                                                                            noncontiguous_struct_char,
885                                                                            type_c->block_lengths[i],
886                                                                            type_c->old_types[i]->substruct);
887
888       contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]);
889       if (i<type_c->block_count-1)noncontiguous_struct_char =  (char*)noncontiguous_struct + type_c->block_indices[i+1];
890       else noncontiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_types[i]);
891     }
892     noncontiguous_struct=(void*)noncontiguous_struct_char;
893     
894   }
895 }
896
897 void free_struct(MPI_Datatype* type){
898   xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->block_lengths);
899   xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->block_indices);
900   xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->old_types);
901 }
902
903 /*
904  * Create a Sub type struct to be able to serialize and unserialize it
905  * the structure s_smpi_mpi_struct_t is derived from s_smpi_subtype which
906  * required the functions unserialize and serialize
907  */
908 s_smpi_mpi_struct_t* smpi_datatype_struct_create( int* block_lengths,
909                                                   MPI_Aint* block_indices,
910                                                   int block_count,
911                                                   MPI_Datatype* old_types){
912   s_smpi_mpi_struct_t *new_t= xbt_new(s_smpi_mpi_struct_t,1);
913   new_t->base.serialize = &serialize_struct;
914   new_t->base.unserialize = &unserialize_struct;
915   new_t->base.subtype_free = &free_struct;
916  //TODO : add a custom function for each time to clean these 
917   new_t->block_lengths= xbt_new(int, block_count);
918   new_t->block_indices= xbt_new(MPI_Aint, block_count);
919   new_t->old_types=  xbt_new(MPI_Datatype, block_count);
920   int i;
921   for(i=0;i<block_count;i++){
922     new_t->block_lengths[i]=block_lengths[i];
923     new_t->block_indices[i]=block_indices[i];
924     new_t->old_types[i]=old_types[i];
925   }
926   //new_t->block_lengths = block_lengths;
927   //new_t->block_indices = block_indices;
928   new_t->block_count = block_count;
929   //new_t->old_types = old_types;
930   return new_t;
931 }
932
933
934 int smpi_datatype_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type)
935 {
936   int i;
937   size_t size = 0;
938   int contiguous=1;
939   size = 0;
940   MPI_Aint lb = 0;
941   MPI_Aint ub = 0;
942   if(count>0){
943     lb=indices[0] + smpi_datatype_lb(old_types[0]);
944     ub=indices[0] + blocklens[0]*smpi_datatype_ub(old_types[0]);
945   }
946   int forced_lb=0;
947   int forced_ub=0;
948   for(i=0; i< count; i++){
949     if (blocklens[i]<=0)
950       return MPI_ERR_ARG;
951     if (old_types[i]->has_subtype == 1)
952       contiguous=0;
953
954     size += blocklens[i]*smpi_datatype_size(old_types[i]);
955     if (old_types[i]==MPI_LB){
956       lb=indices[i];
957       forced_lb=1;
958     }
959     if (old_types[i]==MPI_UB){
960       ub=indices[i];
961       forced_ub=1;
962     }
963
964     if(!forced_lb && indices[i]+smpi_datatype_lb(old_types[i])<lb) lb = indices[i];
965     if(!forced_ub && indices[i]+blocklens[i]*smpi_datatype_ub(old_types[i])>ub) ub = indices[i]+blocklens[i]*smpi_datatype_ub(old_types[i]);
966
967     if ( (i< count -1) && (indices[i]+blocklens[i]*smpi_datatype_size(old_types[i]) != indices[i+1]) )contiguous=0;
968   }
969
970   if(!contiguous){
971     s_smpi_mpi_struct_t* subtype = smpi_datatype_struct_create( blocklens,
972                                                               indices,
973                                                               count,
974                                                               old_types);
975
976     smpi_datatype_create(new_type,  size, lb, ub,1, subtype, DT_FLAG_DATA);
977   }else{
978     smpi_datatype_create(new_type,  size, lb, ub,0, NULL, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
979   }
980   return MPI_SUCCESS;
981 }
982
983 void smpi_datatype_commit(MPI_Datatype *datatype)
984 {
985   (*datatype)->flags=  ((*datatype)->flags | DT_FLAG_COMMITED);
986 }
987
988 typedef struct s_smpi_mpi_op {
989   MPI_User_function *func;
990 } s_smpi_mpi_op_t;
991
992 #define MAX_OP(a, b)  (b) = (a) < (b) ? (b) : (a)
993 #define MIN_OP(a, b)  (b) = (a) < (b) ? (a) : (b)
994 #define SUM_OP(a, b)  (b) += (a)
995 #define PROD_OP(a, b) (b) *= (a)
996 #define LAND_OP(a, b) (b) = (a) && (b)
997 #define LOR_OP(a, b)  (b) = (a) || (b)
998 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
999 #define BAND_OP(a, b) (b) &= (a)
1000 #define BOR_OP(a, b)  (b) |= (a)
1001 #define BXOR_OP(a, b) (b) ^= (a)
1002 #define MAXLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (b) : (a)
1003 #define MINLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (a) : (b)
1004 //TODO : MINLOC & MAXLOC
1005
1006 #define APPLY_FUNC(a, b, length, type, func) \
1007 {                                          \
1008   int i;                                   \
1009   type* x = (type*)(a);                    \
1010   type* y = (type*)(b);                    \
1011   for(i = 0; i < *(length); i++) {         \
1012     func(x[i], y[i]);                      \
1013   }                                        \
1014 }
1015
1016 static void max_func(void *a, void *b, int *length,
1017                      MPI_Datatype * datatype)
1018 {
1019   if (*datatype == MPI_CHAR) {
1020     APPLY_FUNC(a, b, length, char, MAX_OP);
1021   } else if (*datatype == MPI_SHORT) {
1022     APPLY_FUNC(a, b, length, short, MAX_OP);
1023   } else if (*datatype == MPI_INT) {
1024     APPLY_FUNC(a, b, length, int, MAX_OP);
1025   } else if (*datatype == MPI_LONG) {
1026     APPLY_FUNC(a, b, length, long, MAX_OP);
1027   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1028     APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
1029   } else if (*datatype == MPI_UNSIGNED) {
1030     APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
1031   } else if (*datatype == MPI_UNSIGNED_LONG) {
1032     APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
1033   } else if (*datatype == MPI_FLOAT) {
1034     APPLY_FUNC(a, b, length, float, MAX_OP);
1035   } else if (*datatype == MPI_DOUBLE) {
1036     APPLY_FUNC(a, b, length, double, MAX_OP);
1037   } else if (*datatype == MPI_LONG_DOUBLE) {
1038     APPLY_FUNC(a, b, length, long double, MAX_OP);
1039   }
1040 }
1041
1042 static void min_func(void *a, void *b, int *length,
1043                      MPI_Datatype * datatype)
1044 {
1045   if (*datatype == MPI_CHAR) {
1046     APPLY_FUNC(a, b, length, char, MIN_OP);
1047   } else if (*datatype == MPI_SHORT) {
1048     APPLY_FUNC(a, b, length, short, MIN_OP);
1049   } else if (*datatype == MPI_INT) {
1050     APPLY_FUNC(a, b, length, int, MIN_OP);
1051   } else if (*datatype == MPI_LONG) {
1052     APPLY_FUNC(a, b, length, long, MIN_OP);
1053   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1054     APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
1055   } else if (*datatype == MPI_UNSIGNED) {
1056     APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
1057   } else if (*datatype == MPI_UNSIGNED_LONG) {
1058     APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
1059   } else if (*datatype == MPI_FLOAT) {
1060     APPLY_FUNC(a, b, length, float, MIN_OP);
1061   } else if (*datatype == MPI_DOUBLE) {
1062     APPLY_FUNC(a, b, length, double, MIN_OP);
1063   } else if (*datatype == MPI_LONG_DOUBLE) {
1064     APPLY_FUNC(a, b, length, long double, MIN_OP);
1065   }
1066 }
1067
1068 static void sum_func(void *a, void *b, int *length,
1069                      MPI_Datatype * datatype)
1070 {
1071   if (*datatype == MPI_CHAR) {
1072     APPLY_FUNC(a, b, length, char, SUM_OP);
1073   } else if (*datatype == MPI_SHORT) {
1074     APPLY_FUNC(a, b, length, short, SUM_OP);
1075   } else if (*datatype == MPI_INT) {
1076     APPLY_FUNC(a, b, length, int, SUM_OP);
1077   } else if (*datatype == MPI_LONG) {
1078     APPLY_FUNC(a, b, length, long, SUM_OP);
1079   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1080     APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
1081   } else if (*datatype == MPI_UNSIGNED) {
1082     APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
1083   } else if (*datatype == MPI_UNSIGNED_LONG) {
1084     APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
1085   } else if (*datatype == MPI_FLOAT) {
1086     APPLY_FUNC(a, b, length, float, SUM_OP);
1087   } else if (*datatype == MPI_DOUBLE) {
1088     APPLY_FUNC(a, b, length, double, SUM_OP);
1089   } else if (*datatype == MPI_LONG_DOUBLE) {
1090     APPLY_FUNC(a, b, length, long double, SUM_OP);
1091   } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
1092     APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
1093   } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
1094     APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
1095   } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
1096     APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
1097   }
1098 }
1099
1100 static void prod_func(void *a, void *b, int *length,
1101                       MPI_Datatype * datatype)
1102 {
1103   if (*datatype == MPI_CHAR) {
1104     APPLY_FUNC(a, b, length, char, PROD_OP);
1105   } else if (*datatype == MPI_SHORT) {
1106     APPLY_FUNC(a, b, length, short, PROD_OP);
1107   } else if (*datatype == MPI_INT) {
1108     APPLY_FUNC(a, b, length, int, PROD_OP);
1109   } else if (*datatype == MPI_LONG) {
1110     APPLY_FUNC(a, b, length, long, PROD_OP);
1111   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1112     APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
1113   } else if (*datatype == MPI_UNSIGNED) {
1114     APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
1115   } else if (*datatype == MPI_UNSIGNED_LONG) {
1116     APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
1117   } else if (*datatype == MPI_FLOAT) {
1118     APPLY_FUNC(a, b, length, float, PROD_OP);
1119   } else if (*datatype == MPI_DOUBLE) {
1120     APPLY_FUNC(a, b, length, double, PROD_OP);
1121   } else if (*datatype == MPI_LONG_DOUBLE) {
1122     APPLY_FUNC(a, b, length, long double, PROD_OP);
1123   } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
1124     APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
1125   } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
1126     APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
1127   } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
1128     APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
1129   }
1130 }
1131
1132 static void land_func(void *a, void *b, int *length,
1133                       MPI_Datatype * datatype)
1134 {
1135   if (*datatype == MPI_CHAR) {
1136     APPLY_FUNC(a, b, length, char, LAND_OP);
1137   } else if (*datatype == MPI_SHORT) {
1138     APPLY_FUNC(a, b, length, short, LAND_OP);
1139   } else if (*datatype == MPI_INT) {
1140     APPLY_FUNC(a, b, length, int, LAND_OP);
1141   } else if (*datatype == MPI_LONG) {
1142     APPLY_FUNC(a, b, length, long, LAND_OP);
1143   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1144     APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
1145   } else if (*datatype == MPI_UNSIGNED) {
1146     APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
1147   } else if (*datatype == MPI_UNSIGNED_LONG) {
1148     APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
1149   } else if (*datatype == MPI_C_BOOL) {
1150     APPLY_FUNC(a, b, length, _Bool, LAND_OP);
1151   }
1152 }
1153
1154 static void lor_func(void *a, void *b, int *length,
1155                      MPI_Datatype * datatype)
1156 {
1157   if (*datatype == MPI_CHAR) {
1158     APPLY_FUNC(a, b, length, char, LOR_OP);
1159   } else if (*datatype == MPI_SHORT) {
1160     APPLY_FUNC(a, b, length, short, LOR_OP);
1161   } else if (*datatype == MPI_INT) {
1162     APPLY_FUNC(a, b, length, int, LOR_OP);
1163   } else if (*datatype == MPI_LONG) {
1164     APPLY_FUNC(a, b, length, long, LOR_OP);
1165   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1166     APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
1167   } else if (*datatype == MPI_UNSIGNED) {
1168     APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
1169   } else if (*datatype == MPI_UNSIGNED_LONG) {
1170     APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
1171   } else if (*datatype == MPI_C_BOOL) {
1172     APPLY_FUNC(a, b, length, _Bool, LOR_OP);
1173   }
1174 }
1175
1176 static void lxor_func(void *a, void *b, int *length,
1177                       MPI_Datatype * datatype)
1178 {
1179   if (*datatype == MPI_CHAR) {
1180     APPLY_FUNC(a, b, length, char, LXOR_OP);
1181   } else if (*datatype == MPI_SHORT) {
1182     APPLY_FUNC(a, b, length, short, LXOR_OP);
1183   } else if (*datatype == MPI_INT) {
1184     APPLY_FUNC(a, b, length, int, LXOR_OP);
1185   } else if (*datatype == MPI_LONG) {
1186     APPLY_FUNC(a, b, length, long, LXOR_OP);
1187   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1188     APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
1189   } else if (*datatype == MPI_UNSIGNED) {
1190     APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
1191   } else if (*datatype == MPI_UNSIGNED_LONG) {
1192     APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
1193   } else if (*datatype == MPI_C_BOOL) {
1194     APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
1195   }
1196 }
1197
1198 static void band_func(void *a, void *b, int *length,
1199                       MPI_Datatype * datatype)
1200 {
1201   if (*datatype == MPI_CHAR) {
1202     APPLY_FUNC(a, b, length, char, BAND_OP);
1203   }
1204   if (*datatype == MPI_SHORT) {
1205     APPLY_FUNC(a, b, length, short, BAND_OP);
1206   } else if (*datatype == MPI_INT) {
1207     APPLY_FUNC(a, b, length, int, BAND_OP);
1208   } else if (*datatype == MPI_LONG) {
1209     APPLY_FUNC(a, b, length, long, BAND_OP);
1210   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1211     APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
1212   } else if (*datatype == MPI_UNSIGNED) {
1213     APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
1214   } else if (*datatype == MPI_UNSIGNED_LONG) {
1215     APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
1216   } else if (*datatype == MPI_BYTE) {
1217     APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
1218   }
1219 }
1220
1221 static void bor_func(void *a, void *b, int *length,
1222                      MPI_Datatype * datatype)
1223 {
1224   if (*datatype == MPI_CHAR) {
1225     APPLY_FUNC(a, b, length, char, BOR_OP);
1226   } else if (*datatype == MPI_SHORT) {
1227     APPLY_FUNC(a, b, length, short, BOR_OP);
1228   } else if (*datatype == MPI_INT) {
1229     APPLY_FUNC(a, b, length, int, BOR_OP);
1230   } else if (*datatype == MPI_LONG) {
1231     APPLY_FUNC(a, b, length, long, BOR_OP);
1232   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1233     APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
1234   } else if (*datatype == MPI_UNSIGNED) {
1235     APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
1236   } else if (*datatype == MPI_UNSIGNED_LONG) {
1237     APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
1238   } else if (*datatype == MPI_BYTE) {
1239     APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
1240   }
1241 }
1242
1243 static void bxor_func(void *a, void *b, int *length,
1244                       MPI_Datatype * datatype)
1245 {
1246   if (*datatype == MPI_CHAR) {
1247     APPLY_FUNC(a, b, length, char, BXOR_OP);
1248   } else if (*datatype == MPI_SHORT) {
1249     APPLY_FUNC(a, b, length, short, BXOR_OP);
1250   } else if (*datatype == MPI_INT) {
1251     APPLY_FUNC(a, b, length, int, BXOR_OP);
1252   } else if (*datatype == MPI_LONG) {
1253     APPLY_FUNC(a, b, length, long, BXOR_OP);
1254   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1255     APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
1256   } else if (*datatype == MPI_UNSIGNED) {
1257     APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
1258   } else if (*datatype == MPI_UNSIGNED_LONG) {
1259     APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
1260   } else if (*datatype == MPI_BYTE) {
1261     APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
1262   }
1263 }
1264
1265 static void minloc_func(void *a, void *b, int *length,
1266                         MPI_Datatype * datatype)
1267 {
1268   if (*datatype == MPI_FLOAT_INT) {
1269     APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
1270   } else if (*datatype == MPI_LONG_INT) {
1271     APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
1272   } else if (*datatype == MPI_DOUBLE_INT) {
1273     APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
1274   } else if (*datatype == MPI_SHORT_INT) {
1275     APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
1276   } else if (*datatype == MPI_2INT) {
1277     APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
1278   } else if (*datatype == MPI_LONG_DOUBLE_INT) {
1279     APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
1280   } else if (*datatype == MPI_2FLOAT) {
1281     APPLY_FUNC(a, b, length, float_float, MINLOC_OP);
1282   } else if (*datatype == MPI_2DOUBLE) {
1283     APPLY_FUNC(a, b, length, double_double, MINLOC_OP);
1284   }
1285 }
1286
1287 static void maxloc_func(void *a, void *b, int *length,
1288                         MPI_Datatype * datatype)
1289 {
1290   if (*datatype == MPI_FLOAT_INT) {
1291     APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
1292   } else if (*datatype == MPI_LONG_INT) {
1293     APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
1294   } else if (*datatype == MPI_DOUBLE_INT) {
1295     APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
1296   } else if (*datatype == MPI_SHORT_INT) {
1297     APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
1298   } else if (*datatype == MPI_2INT) {
1299     APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
1300   } else if (*datatype == MPI_LONG_DOUBLE_INT) {
1301     APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
1302   } else if (*datatype == MPI_2FLOAT) {
1303     APPLY_FUNC(a, b, length, float_float, MAXLOC_OP);
1304   } else if (*datatype == MPI_2DOUBLE) {
1305     APPLY_FUNC(a, b, length, double_double, MAXLOC_OP);
1306   }
1307 }
1308
1309
1310 #define CREATE_MPI_OP(name, func)                             \
1311   static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
1312 MPI_Op name = &mpi_##name;
1313
1314 CREATE_MPI_OP(MPI_MAX, max_func);
1315 CREATE_MPI_OP(MPI_MIN, min_func);
1316 CREATE_MPI_OP(MPI_SUM, sum_func);
1317 CREATE_MPI_OP(MPI_PROD, prod_func);
1318 CREATE_MPI_OP(MPI_LAND, land_func);
1319 CREATE_MPI_OP(MPI_LOR, lor_func);
1320 CREATE_MPI_OP(MPI_LXOR, lxor_func);
1321 CREATE_MPI_OP(MPI_BAND, band_func);
1322 CREATE_MPI_OP(MPI_BOR, bor_func);
1323 CREATE_MPI_OP(MPI_BXOR, bxor_func);
1324 CREATE_MPI_OP(MPI_MAXLOC, maxloc_func);
1325 CREATE_MPI_OP(MPI_MINLOC, minloc_func);
1326
1327 MPI_Op smpi_op_new(MPI_User_function * function, int commute)
1328 {
1329   MPI_Op op;
1330
1331   //FIXME: add commute param
1332   op = xbt_new(s_smpi_mpi_op_t, 1);
1333   op->func = function;
1334   return op;
1335 }
1336
1337 void smpi_op_destroy(MPI_Op op)
1338 {
1339   xbt_free(op);
1340 }
1341
1342 void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len,
1343                    MPI_Datatype * datatype)
1344 {
1345   op->func(invec, inoutvec, len, datatype);
1346 }