Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
rename a struct to obey the C++ One Definition Rule (and please gcc6)
[simgrid.git] / src / smpi / smpi_mpi_dt.cpp
1 /* smpi_mpi_dt.c -- MPI primitives to handle datatypes                        */
2 /* FIXME: a very incomplete implementation                                    */
3
4 /* Copyright (c) 2009-2015. 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 #include <limits.h>
14 #include "private.h"
15 #include "smpi_mpi_dt_private.h"
16 #include "mc/mc.h"
17 #include "xbt/replay.h"
18 #include "simgrid/modelchecker.h"
19
20 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
21                                 "Logging specific to SMPI (datatype)");
22
23 xbt_dict_t smpi_type_keyvals = NULL;
24 int type_keyval_id=0;//avoid collisions
25
26 #define CREATE_MPI_DATATYPE(name, type)               \
27   static s_smpi_mpi_datatype_t mpi_##name = {         \
28     (char*) # name,                                   \
29     sizeof(type),   /* size */                        \
30     0,              /*was 1 has_subtype*/             \
31     0,              /* lb */                          \
32     sizeof(type),   /* ub = lb + size */              \
33     DT_FLAG_BASIC,  /* flags */                       \
34     NULL,           /* attributes */                  \
35     NULL,           /* pointer on extended struct*/   \
36     0               /* in_use counter */              \
37   };                                                  \
38 const MPI_Datatype name = &mpi_##name;
39
40 #define CREATE_MPI_DATATYPE_NULL(name)                \
41   static s_smpi_mpi_datatype_t mpi_##name = {         \
42     (char*) # name,                                   \
43     0,              /* size */                        \
44     0,              /* was 1 has_subtype*/            \
45     0,              /* lb */                          \
46     0,              /* ub = lb + size */              \
47     DT_FLAG_BASIC,  /* flags */                       \
48     NULL,           /* attributes */                  \
49     NULL,           /* pointer on extended struct*/   \
50     0               /* in_use counter */              \
51   };                                                  \
52 const MPI_Datatype name = &mpi_##name;
53
54 //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC.
55 typedef struct {
56   float value;
57   int index;
58 } float_int;
59 typedef struct {
60   float value;
61   float index;
62 } float_float;
63 typedef struct {
64   long value;
65   long index;
66 } long_long;
67 typedef struct {
68   double value;
69   double index;
70 } double_double;
71 typedef struct {
72   long value;
73   int index;
74 } long_int;
75 typedef struct {
76   double value;
77   int index;
78 } double_int;
79 typedef struct {
80   short value;
81   int index;
82 } short_int;
83 typedef struct {
84   int value;
85   int index;
86 } int_int;
87 typedef struct {
88   long double value;
89   int index;
90 } long_double_int;
91 typedef struct {
92   int64_t value;
93   int64_t index;
94 } integer128_t;
95 // Predefined data types
96 CREATE_MPI_DATATYPE(MPI_CHAR, char);
97 CREATE_MPI_DATATYPE(MPI_SHORT, short);
98 CREATE_MPI_DATATYPE(MPI_INT, int);
99 CREATE_MPI_DATATYPE(MPI_LONG, long);
100 CREATE_MPI_DATATYPE(MPI_LONG_LONG, long long);
101 CREATE_MPI_DATATYPE(MPI_SIGNED_CHAR, signed char);
102 CREATE_MPI_DATATYPE(MPI_UNSIGNED_CHAR, unsigned char);
103 CREATE_MPI_DATATYPE(MPI_UNSIGNED_SHORT, unsigned short);
104 CREATE_MPI_DATATYPE(MPI_UNSIGNED, unsigned int);
105 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG, unsigned long);
106 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG, unsigned long long);
107 CREATE_MPI_DATATYPE(MPI_FLOAT, float);
108 CREATE_MPI_DATATYPE(MPI_DOUBLE, double);
109 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE, long double);
110 CREATE_MPI_DATATYPE(MPI_WCHAR, wchar_t);
111 CREATE_MPI_DATATYPE(MPI_C_BOOL, bool);
112 CREATE_MPI_DATATYPE(MPI_BYTE, int8_t);
113 CREATE_MPI_DATATYPE(MPI_INT8_T, int8_t);
114 CREATE_MPI_DATATYPE(MPI_INT16_T, int16_t);
115 CREATE_MPI_DATATYPE(MPI_INT32_T, int32_t);
116 CREATE_MPI_DATATYPE(MPI_INT64_T, int64_t);
117 CREATE_MPI_DATATYPE(MPI_UINT8_T, uint8_t);
118 CREATE_MPI_DATATYPE(MPI_UINT16_T, uint16_t);
119 CREATE_MPI_DATATYPE(MPI_UINT32_T, uint32_t);
120 CREATE_MPI_DATATYPE(MPI_UINT64_T, uint64_t);
121 CREATE_MPI_DATATYPE(MPI_C_FLOAT_COMPLEX, float _Complex);
122 CREATE_MPI_DATATYPE(MPI_C_DOUBLE_COMPLEX, double _Complex);
123 CREATE_MPI_DATATYPE(MPI_C_LONG_DOUBLE_COMPLEX, long double _Complex);
124 CREATE_MPI_DATATYPE(MPI_AINT, MPI_Aint);
125 CREATE_MPI_DATATYPE(MPI_OFFSET, MPI_Offset);
126
127 CREATE_MPI_DATATYPE(MPI_FLOAT_INT, float_int);
128 CREATE_MPI_DATATYPE(MPI_LONG_INT, long_int);
129 CREATE_MPI_DATATYPE(MPI_DOUBLE_INT, double_int);
130 CREATE_MPI_DATATYPE(MPI_SHORT_INT, short_int);
131 CREATE_MPI_DATATYPE(MPI_2INT, int_int);
132 CREATE_MPI_DATATYPE(MPI_2FLOAT, float_float);
133 CREATE_MPI_DATATYPE(MPI_2DOUBLE, double_double);
134 CREATE_MPI_DATATYPE(MPI_2LONG, long_long);
135
136 CREATE_MPI_DATATYPE(MPI_REAL, float);
137 CREATE_MPI_DATATYPE(MPI_REAL4, float);
138 CREATE_MPI_DATATYPE(MPI_REAL8, float);
139 CREATE_MPI_DATATYPE(MPI_REAL16, double);
140 CREATE_MPI_DATATYPE_NULL(MPI_COMPLEX8);
141 CREATE_MPI_DATATYPE_NULL(MPI_COMPLEX16);
142 CREATE_MPI_DATATYPE_NULL(MPI_COMPLEX32);
143 CREATE_MPI_DATATYPE(MPI_INTEGER1, int);
144 CREATE_MPI_DATATYPE(MPI_INTEGER2, int16_t);
145 CREATE_MPI_DATATYPE(MPI_INTEGER4, int32_t);
146 CREATE_MPI_DATATYPE(MPI_INTEGER8, int64_t);
147 CREATE_MPI_DATATYPE(MPI_INTEGER16, integer128_t);
148
149 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int);
150
151 CREATE_MPI_DATATYPE_NULL(MPI_UB);
152 CREATE_MPI_DATATYPE_NULL(MPI_LB);
153 CREATE_MPI_DATATYPE(MPI_PACKED, char);
154 // Internal use only
155 CREATE_MPI_DATATYPE(MPI_PTR, void*);
156
157 /** Check if the datatype is usable for communications
158  */
159 int is_datatype_valid(MPI_Datatype datatype) {
160     return datatype != MPI_DATATYPE_NULL
161         && (datatype->flags & DT_FLAG_COMMITED);
162 }
163
164 size_t smpi_datatype_size(MPI_Datatype datatype)
165 {
166   return datatype->size;
167 }
168
169 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype)
170 {
171   return datatype->lb;
172 }
173
174 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype)
175 {
176   return datatype->ub;
177 }
178
179 int smpi_datatype_dup(MPI_Datatype datatype, MPI_Datatype* new_t)
180 {
181   int ret=MPI_SUCCESS;
182   *new_t= xbt_new(s_smpi_mpi_datatype_t,1);
183   memcpy(*new_t, datatype, sizeof(s_smpi_mpi_datatype_t));
184   if (datatype->has_subtype){
185     //FIXME: may copy too much information.
186     (*new_t)->substruct=xbt_new(s_smpi_mpi_struct_t,1);
187     memcpy((*new_t)->substruct, datatype->substruct, sizeof(s_smpi_mpi_struct_t));
188   }
189   if(datatype->name)
190     (*new_t)->name = xbt_strdup(datatype->name);
191   if(datatype->attributes !=NULL){
192       (*new_t)->attributes=xbt_dict_new();
193       xbt_dict_cursor_t cursor = NULL;
194       int *key;
195       int flag;
196       void* value_in;
197       void* value_out;
198       xbt_dict_foreach(datatype->attributes, cursor, key, value_in){
199         smpi_type_key_elem elem = static_cast<smpi_type_key_elem>(xbt_dict_get_or_null_ext(smpi_type_keyvals,  (const char*)key, sizeof(int)));
200         if(elem && elem->copy_fn!=MPI_NULL_COPY_FN){
201           ret = elem->copy_fn(datatype, *key, NULL, value_in, &value_out, &flag );
202           if(ret!=MPI_SUCCESS){
203             *new_t=MPI_DATATYPE_NULL;
204             return ret;
205           }
206           if(flag)
207             xbt_dict_set_ext((*new_t)->attributes, (const char*)key, sizeof(int),value_out, NULL);
208         }
209       }
210     }
211   return ret;
212 }
213
214 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
215                          MPI_Aint * extent)
216 {
217   if(datatype == MPI_DATATYPE_NULL){
218     *lb=0;
219     *extent=0;
220     return MPI_SUCCESS;
221   }
222   *lb = datatype->lb;
223   *extent = datatype->ub - datatype->lb;
224   return MPI_SUCCESS;
225 }
226
227 MPI_Aint smpi_datatype_get_extent(MPI_Datatype datatype){
228   if(datatype == MPI_DATATYPE_NULL){
229     return 0;
230   }
231   return datatype->ub - datatype->lb;
232 }
233
234 void smpi_datatype_get_name(MPI_Datatype datatype, char* name, int* length){
235   *length = strlen(datatype->name);
236   strcpy(name, datatype->name);
237 }
238
239 void smpi_datatype_set_name(MPI_Datatype datatype, char* name){
240   datatype->name = xbt_strdup(name);;
241 }
242
243 int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype,
244                        void *recvbuf, int recvcount, MPI_Datatype recvtype)
245 {
246   int count;
247   if(smpi_privatize_global_variables){
248     smpi_switch_data_segment(smpi_process_index());
249   }
250   /* First check if we really have something to do */
251   if (recvcount > 0 && recvbuf != sendbuf) {
252     /* FIXME: treat packed cases */
253     sendcount *= smpi_datatype_size(sendtype);
254     recvcount *= smpi_datatype_size(recvtype);
255     count = sendcount < recvcount ? sendcount : recvcount;
256
257     if(sendtype->has_subtype == 0 && recvtype->has_subtype == 0) {
258       if(!smpi_process_get_replaying()) memcpy(recvbuf, sendbuf, count);
259     }
260     else if (sendtype->has_subtype == 0)
261     {
262       s_smpi_subtype_t *subtype =  static_cast<s_smpi_subtype_t*>(recvtype->substruct);
263       subtype->unserialize( sendbuf, recvbuf, recvcount/smpi_datatype_size(recvtype), subtype, MPI_REPLACE);
264     }
265     else if (recvtype->has_subtype == 0)
266     {
267       s_smpi_subtype_t *subtype =  static_cast<s_smpi_subtype_t*>(sendtype->substruct);
268       subtype->serialize(sendbuf, recvbuf, sendcount/smpi_datatype_size(sendtype), subtype);
269     }else{
270       s_smpi_subtype_t *subtype =  static_cast<s_smpi_subtype_t*>(sendtype->substruct);
271
272
273       void * buf_tmp = xbt_malloc(count);
274
275       subtype->serialize( sendbuf, buf_tmp,count/smpi_datatype_size(sendtype), subtype);
276       subtype =  static_cast<s_smpi_subtype_t*>(recvtype->substruct);
277       subtype->unserialize( buf_tmp, recvbuf,count/smpi_datatype_size(recvtype), subtype, MPI_REPLACE);
278
279       free(buf_tmp);
280     }
281   }
282
283   return sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
284 }
285
286 /*
287  *  Copies noncontiguous data into contiguous memory.
288  *  @param contiguous_vector - output vector
289  *  @param noncontiguous_vector - input vector
290  *  @param type - pointer contening :
291  *      - stride - stride of between noncontiguous data
292  *      - block_length - the width or height of blocked matrix
293  *      - count - the number of rows of matrix
294  */
295 void serialize_vector( const void *noncontiguous_vector,
296                        void *contiguous_vector,
297                        int count,
298                        void *type)
299 {
300   s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)type;
301   int i;
302   char* contiguous_vector_char = (char*)contiguous_vector;
303   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
304
305   for (i = 0; i < type_c->block_count * count; i++) {
306       if (type_c->old_type->has_subtype == 0)
307         memcpy(contiguous_vector_char,
308                noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype);
309       else
310         ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_vector_char,
311                                                                      contiguous_vector_char,
312                                                                      type_c->block_length,
313                                                                      type_c->old_type->substruct);
314
315     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
316     if((i+1)%type_c->block_count ==0)
317     noncontiguous_vector_char += type_c->block_length*smpi_datatype_get_extent(type_c->old_type);
318     else
319     noncontiguous_vector_char += type_c->block_stride*smpi_datatype_get_extent(type_c->old_type);
320   }
321 }
322
323 /*
324  *  Copies contiguous data into noncontiguous memory.
325  *  @param noncontiguous_vector - output vector
326  *  @param contiguous_vector - input vector
327  *  @param type - pointer contening :
328  *      - stride - stride of between noncontiguous data
329  *      - block_length - the width or height of blocked matrix
330  *      - count - the number of rows of matrix
331  */
332 void unserialize_vector( const void *contiguous_vector,
333                          void *noncontiguous_vector,
334                          int count,
335                          void *type,
336                          MPI_Op op)
337 {
338   s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)type;
339   int i;
340
341   char* contiguous_vector_char = (char*)contiguous_vector;
342   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
343
344   for (i = 0; i < type_c->block_count * count; i++) {
345     if (type_c->old_type->has_subtype == 0)
346       smpi_op_apply(op, contiguous_vector_char, noncontiguous_vector_char, &type_c->block_length,
347           &type_c->old_type);
348      /* memcpy(noncontiguous_vector_char,
349              contiguous_vector_char, type_c->block_length * type_c->size_oldtype);*/
350     else
351       ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_vector_char,
352                                                                      noncontiguous_vector_char,
353                                                                      type_c->block_length,
354                                                                      type_c->old_type->substruct,
355                                                                      op);
356     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
357     if((i+1)%type_c->block_count ==0)
358     noncontiguous_vector_char += type_c->block_length*smpi_datatype_get_extent(type_c->old_type);
359     else
360     noncontiguous_vector_char += type_c->block_stride*smpi_datatype_get_extent(type_c->old_type);
361   }
362 }
363
364 /*
365  * Create a Sub type vector to be able to serialize and unserialize it
366  * the structure s_smpi_mpi_vector_t is derived from s_smpi_subtype which
367  * required the functions unserialize and serialize
368  *
369  */
370 s_smpi_mpi_vector_t* smpi_datatype_vector_create( int block_stride,
371                                                   int block_length,
372                                                   int block_count,
373                                                   MPI_Datatype old_type,
374                                                   int size_oldtype){
375   s_smpi_mpi_vector_t *new_t= xbt_new(s_smpi_mpi_vector_t,1);
376   new_t->base.serialize = &serialize_vector;
377   new_t->base.unserialize = &unserialize_vector;
378   new_t->base.subtype_free = &free_vector;
379   new_t->block_stride = block_stride;
380   new_t->block_length = block_length;
381   new_t->block_count = block_count;
382   smpi_datatype_use(old_type);
383   new_t->old_type = old_type;
384   new_t->size_oldtype = size_oldtype;
385   return new_t;
386 }
387
388 void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int has_subtype,
389     void *struct_type, int flags){
390   MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1);
391   new_t->name = NULL;
392   new_t->size = size;
393   new_t->has_subtype = size>0? has_subtype:0;
394   new_t->lb = lb;
395   new_t->ub = ub;
396   new_t->flags = flags;
397   new_t->substruct = struct_type;
398   new_t->in_use=0;
399   new_t->attributes=NULL;
400   *new_type = new_t;
401
402 #ifdef HAVE_MC
403   if(MC_is_active())
404     MC_ignore(&(new_t->in_use), sizeof(new_t->in_use));
405 #endif
406 }
407
408 void smpi_datatype_free(MPI_Datatype* type){
409   xbt_assert((*type)->in_use >= 0);
410   if((*type)->attributes !=NULL){
411       xbt_dict_cursor_t cursor = NULL;
412       int* key;
413       void * value;
414       int flag;
415       xbt_dict_foreach((*type)->attributes, cursor, key, value){
416         smpi_type_key_elem elem = static_cast<smpi_type_key_elem>(xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)key, sizeof(int)));
417         if(elem &&  elem->delete_fn)
418           elem->delete_fn(*type,*key, value, &flag);
419       }
420   }
421
422   if((*type)->flags & DT_FLAG_PREDEFINED)return;
423
424   //if still used, mark for deletion
425   if((*type)->in_use!=0){
426       (*type)->flags |=DT_FLAG_DESTROYED;
427       return;
428   }
429
430   if ((*type)->has_subtype == 1){
431     ((s_smpi_subtype_t *)(*type)->substruct)->subtype_free(type);  
432     xbt_free((*type)->substruct);
433   }
434   if ((*type)->name != NULL){
435     xbt_free((*type)->name);
436   }
437   xbt_free(*type);
438   *type = MPI_DATATYPE_NULL;
439 }
440
441 void smpi_datatype_use(MPI_Datatype type){
442   if(type)type->in_use++;
443
444 #ifdef HAVE_MC
445   if(MC_is_active())
446     MC_ignore(&(type->in_use), sizeof(type->in_use));
447 #endif
448 }
449
450
451 void smpi_datatype_unuse(MPI_Datatype type){
452   if (type->in_use > 0)
453     type->in_use--;
454
455   if(type && type->in_use == 0 && (type->flags & DT_FLAG_DESTROYED))
456     smpi_datatype_free(&type);
457
458 #ifdef HAVE_MC
459   if(MC_is_active())
460     MC_ignore(&(type->in_use), sizeof(type->in_use));
461 #endif
462 }
463
464
465
466
467 /*
468 Contiguous Implementation
469 */
470
471
472 /*
473  *  Copies noncontiguous data into contiguous memory.
474  *  @param contiguous_hvector - output hvector
475  *  @param noncontiguous_hvector - input hvector
476  *  @param type - pointer contening :
477  *      - stride - stride of between noncontiguous data, in bytes
478  *      - block_length - the width or height of blocked matrix
479  *      - count - the number of rows of matrix
480  */
481 void serialize_contiguous( const void *noncontiguous_hvector,
482                        void *contiguous_hvector,
483                        int count,
484                        void *type)
485 {
486   s_smpi_mpi_contiguous_t* type_c = (s_smpi_mpi_contiguous_t*)type;
487   char* contiguous_vector_char = (char*)contiguous_hvector;
488   char* noncontiguous_vector_char = (char*)noncontiguous_hvector+type_c->lb;
489   memcpy(contiguous_vector_char,
490            noncontiguous_vector_char, count* type_c->block_count * type_c->size_oldtype);
491 }
492 /*
493  *  Copies contiguous data into noncontiguous memory.
494  *  @param noncontiguous_vector - output hvector
495  *  @param contiguous_vector - input hvector
496  *  @param type - pointer contening :
497  *      - stride - stride of between noncontiguous data, in bytes
498  *      - block_length - the width or height of blocked matrix
499  *      - count - the number of rows of matrix
500  */
501 void unserialize_contiguous( const void *contiguous_vector,
502                          void *noncontiguous_vector,
503                          int count,
504                          void *type,
505                          MPI_Op op)
506 {
507   s_smpi_mpi_contiguous_t* type_c = (s_smpi_mpi_contiguous_t*)type;
508   char* contiguous_vector_char = (char*)contiguous_vector;
509   char* noncontiguous_vector_char = (char*)noncontiguous_vector+type_c->lb;
510   int n= count* type_c->block_count;
511   smpi_op_apply(op, contiguous_vector_char, noncontiguous_vector_char, &n,
512             &type_c->old_type);
513        /*memcpy(noncontiguous_vector_char,
514            contiguous_vector_char, count*  type_c->block_count * type_c->size_oldtype);*/
515 }
516
517 void free_contiguous(MPI_Datatype* d){
518   smpi_datatype_unuse(((s_smpi_mpi_indexed_t *)(*d)->substruct)->old_type);
519 }
520
521 /*
522  * Create a Sub type contiguous to be able to serialize and unserialize it
523  * the structure s_smpi_mpi_contiguous_t is derived from s_smpi_subtype which
524  * required the functions unserialize and serialize
525  *
526  */
527 s_smpi_mpi_contiguous_t* smpi_datatype_contiguous_create( MPI_Aint lb,
528                                                   int block_count,
529                                                   MPI_Datatype old_type,
530                                                   int size_oldtype){
531   s_smpi_mpi_contiguous_t *new_t= xbt_new(s_smpi_mpi_contiguous_t,1);
532   new_t->base.serialize = &serialize_contiguous;
533   new_t->base.unserialize = &unserialize_contiguous;
534   new_t->base.subtype_free = &free_contiguous;
535   new_t->lb = lb;
536   new_t->block_count = block_count;
537   new_t->old_type = old_type;
538   new_t->size_oldtype = size_oldtype;
539   smpi_datatype_use(old_type);
540   return new_t;
541 }
542
543
544
545
546 int smpi_datatype_contiguous(int count, MPI_Datatype old_type, MPI_Datatype* new_type, MPI_Aint lb)
547 {
548   int retval;
549   if(old_type->has_subtype){
550     //handle this case as a hvector with stride equals to the extent of the datatype
551     return smpi_datatype_hvector(count, 1, smpi_datatype_get_extent(old_type), old_type, new_type);
552   }
553   
554   s_smpi_mpi_contiguous_t* subtype = smpi_datatype_contiguous_create( lb,
555                                                                 count,
556                                                                 old_type,
557                                                                 smpi_datatype_size(old_type));
558                                                                 
559   smpi_datatype_create(new_type,
560             count * smpi_datatype_size(old_type),
561             lb,lb + count * smpi_datatype_size(old_type),
562             1,subtype, DT_FLAG_CONTIGUOUS);
563   retval=MPI_SUCCESS;
564   return retval;
565 }
566
567 int smpi_datatype_vector(int count, int blocklen, int stride, MPI_Datatype old_type, MPI_Datatype* new_type)
568 {
569   int retval;
570   if (blocklen<0) return MPI_ERR_ARG;
571   MPI_Aint lb = 0;
572   MPI_Aint ub = 0;
573   if(count>0){
574     lb=smpi_datatype_lb(old_type);
575     ub=((count-1)*stride+blocklen-1)*smpi_datatype_get_extent(old_type)+smpi_datatype_ub(old_type);
576   }
577   if(old_type->has_subtype || stride != blocklen){
578
579
580     s_smpi_mpi_vector_t* subtype = smpi_datatype_vector_create( stride,
581                                                                 blocklen,
582                                                                 count,
583                                                                 old_type,
584                                                                 smpi_datatype_size(old_type));
585     smpi_datatype_create(new_type,
586                          count * (blocklen) * smpi_datatype_size(old_type), lb,
587                          ub,
588                          1,
589                          subtype,
590                          DT_FLAG_VECTOR);
591     retval=MPI_SUCCESS;
592   }else{
593     /* in this situation the data are contignous thus it's not
594      * required to serialize and unserialize it*/
595     smpi_datatype_create(new_type, count * blocklen *
596                          smpi_datatype_size(old_type), 0, ((count -1) * stride + blocklen)*
597                          smpi_datatype_size(old_type),
598                          0,
599                          NULL,
600                          DT_FLAG_VECTOR|DT_FLAG_CONTIGUOUS);
601     retval=MPI_SUCCESS;
602   }
603   return retval;
604 }
605
606 void free_vector(MPI_Datatype* d){
607   smpi_datatype_unuse(((s_smpi_mpi_indexed_t *)(*d)->substruct)->old_type);
608 }
609
610 /*
611 Hvector Implementation - Vector with stride in bytes
612 */
613
614
615 /*
616  *  Copies noncontiguous data into contiguous memory.
617  *  @param contiguous_hvector - output hvector
618  *  @param noncontiguous_hvector - input hvector
619  *  @param type - pointer contening :
620  *      - stride - stride of between noncontiguous data, in bytes
621  *      - block_length - the width or height of blocked matrix
622  *      - count - the number of rows of matrix
623  */
624 void serialize_hvector( const void *noncontiguous_hvector,
625                        void *contiguous_hvector,
626                        int count,
627                        void *type)
628 {
629   s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type;
630   int i;
631   char* contiguous_vector_char = (char*)contiguous_hvector;
632   char* noncontiguous_vector_char = (char*)noncontiguous_hvector;
633
634   for (i = 0; i < type_c->block_count * count; i++) {
635     if (type_c->old_type->has_subtype == 0)
636       memcpy(contiguous_vector_char,
637            noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype);
638     else
639       ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_vector_char,
640                                                                    contiguous_vector_char,
641                                                                    type_c->block_length,
642                                                                    type_c->old_type->substruct);
643
644     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
645     if((i+1)%type_c->block_count ==0)
646     noncontiguous_vector_char += type_c->block_length*type_c->size_oldtype;
647     else
648     noncontiguous_vector_char += type_c->block_stride;
649   }
650 }
651 /*
652  *  Copies contiguous data into noncontiguous memory.
653  *  @param noncontiguous_vector - output hvector
654  *  @param contiguous_vector - input hvector
655  *  @param type - pointer contening :
656  *      - stride - stride of between noncontiguous data, in bytes
657  *      - block_length - the width or height of blocked matrix
658  *      - count - the number of rows of matrix
659  */
660 void unserialize_hvector( const void *contiguous_vector,
661                          void *noncontiguous_vector,
662                          int count,
663                          void *type,
664                          MPI_Op op)
665 {
666   s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type;
667   int i;
668
669   char* contiguous_vector_char = (char*)contiguous_vector;
670   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
671
672   for (i = 0; i < type_c->block_count * count; i++) {
673     if (type_c->old_type->has_subtype == 0)
674       smpi_op_apply(op, contiguous_vector_char, noncontiguous_vector_char, &type_c->block_length,
675                   &type_c->old_type);
676              /*memcpy(noncontiguous_vector_char,
677            contiguous_vector_char, type_c->block_length * type_c->size_oldtype);*/
678     else
679       ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_vector_char,
680                                                                      noncontiguous_vector_char,
681                                                                      type_c->block_length,
682                                                                      type_c->old_type->substruct,
683                                                                      op);
684     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
685     if((i+1)%type_c->block_count ==0)
686     noncontiguous_vector_char += type_c->block_length*type_c->size_oldtype;
687     else
688     noncontiguous_vector_char += type_c->block_stride;
689   }
690 }
691
692 /*
693  * Create a Sub type vector to be able to serialize and unserialize it
694  * the structure s_smpi_mpi_vector_t is derived from s_smpi_subtype which
695  * required the functions unserialize and serialize
696  *
697  */
698 s_smpi_mpi_hvector_t* smpi_datatype_hvector_create( MPI_Aint block_stride,
699                                                   int block_length,
700                                                   int block_count,
701                                                   MPI_Datatype old_type,
702                                                   int size_oldtype){
703   s_smpi_mpi_hvector_t *new_t= xbt_new(s_smpi_mpi_hvector_t,1);
704   new_t->base.serialize = &serialize_hvector;
705   new_t->base.unserialize = &unserialize_hvector;
706   new_t->base.subtype_free = &free_hvector;
707   new_t->block_stride = block_stride;
708   new_t->block_length = block_length;
709   new_t->block_count = block_count;
710   new_t->old_type = old_type;
711   new_t->size_oldtype = size_oldtype;
712   smpi_datatype_use(old_type);
713   return new_t;
714 }
715
716 //do nothing for vector types
717 void free_hvector(MPI_Datatype* d){
718   smpi_datatype_unuse(((s_smpi_mpi_indexed_t *)(*d)->substruct)->old_type);
719 }
720
721 int smpi_datatype_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type)
722 {
723   int retval;
724   if (blocklen<0) return MPI_ERR_ARG;
725   MPI_Aint lb = 0;
726   MPI_Aint ub = 0;
727   if(count>0){
728     lb=smpi_datatype_lb(old_type);
729     ub=((count-1)*stride)+(blocklen-1)*smpi_datatype_get_extent(old_type)+smpi_datatype_ub(old_type);
730   }
731   if(old_type->has_subtype || stride != blocklen*smpi_datatype_get_extent(old_type)){
732     s_smpi_mpi_hvector_t* subtype = smpi_datatype_hvector_create( stride,
733                                                                   blocklen,
734                                                                   count,
735                                                                   old_type,
736                                                                   smpi_datatype_size(old_type));
737
738     smpi_datatype_create(new_type, count * blocklen * smpi_datatype_size(old_type),
739              lb,ub,
740                          1,
741                          subtype,
742                          DT_FLAG_VECTOR);
743     retval=MPI_SUCCESS;
744   }else{
745     smpi_datatype_create(new_type, count * blocklen *
746                                              smpi_datatype_size(old_type),0,count * blocklen *
747                                              smpi_datatype_size(old_type),
748                                             0,
749                                             NULL,
750                                             DT_FLAG_VECTOR|DT_FLAG_CONTIGUOUS);
751     retval=MPI_SUCCESS;
752   }
753   return retval;
754 }
755
756
757 /*
758 Indexed Implementation
759 */
760
761 /*
762  *  Copies noncontiguous data into contiguous memory.
763  *  @param contiguous_indexed - output indexed
764  *  @param noncontiguous_indexed - input indexed
765  *  @param type - pointer contening :
766  *      - block_lengths - the width or height of blocked matrix
767  *      - block_indices - indices of each data, in element
768  *      - count - the number of rows of matrix
769  */
770 void serialize_indexed( const void *noncontiguous_indexed,
771                        void *contiguous_indexed,
772                        int count,
773                        void *type)
774 {
775   s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type;
776   int i,j;
777   char* contiguous_indexed_char = (char*)contiguous_indexed;
778   char* noncontiguous_indexed_char = (char*)noncontiguous_indexed+type_c->block_indices[0] * type_c->size_oldtype;
779   for(j=0; j<count;j++){
780     for (i = 0; i < type_c->block_count; i++) {
781       if (type_c->old_type->has_subtype == 0)
782         memcpy(contiguous_indexed_char,
783                      noncontiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
784       else
785         ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_indexed_char,
786                                                                      contiguous_indexed_char,
787                                                                      type_c->block_lengths[i],
788                                                                      type_c->old_type->substruct);
789
790
791       contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
792       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);
793       else noncontiguous_indexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
794     }
795     noncontiguous_indexed=(void*)noncontiguous_indexed_char;
796   }
797 }
798 /*
799  *  Copies contiguous data into noncontiguous memory.
800  *  @param noncontiguous_indexed - output indexed
801  *  @param contiguous_indexed - input indexed
802  *  @param type - pointer contening :
803  *      - block_lengths - the width or height of blocked matrix
804  *      - block_indices - indices of each data, in element
805  *      - count - the number of rows of matrix
806  */
807 void unserialize_indexed( const void *contiguous_indexed,
808                          void *noncontiguous_indexed,
809                          int count,
810                          void *type,
811                          MPI_Op op)
812 {
813
814   s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type;
815   int i,j;
816   char* contiguous_indexed_char = (char*)contiguous_indexed;
817   char* noncontiguous_indexed_char = (char*)noncontiguous_indexed+type_c->block_indices[0]*smpi_datatype_get_extent(type_c->old_type);
818   for(j=0; j<count;j++){
819     for (i = 0; i < type_c->block_count; i++) {
820       if (type_c->old_type->has_subtype == 0)
821         smpi_op_apply(op, contiguous_indexed_char, noncontiguous_indexed_char, &type_c->block_lengths[i],
822                     &type_c->old_type);
823                /*memcpy(noncontiguous_indexed_char ,
824              contiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype);*/
825       else
826         ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_indexed_char,
827                                                                        noncontiguous_indexed_char,
828                                                                        type_c->block_lengths[i],
829                                                                        type_c->old_type->substruct,
830                                                                        op);
831
832       contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
833       if (i<type_c->block_count-1)
834         noncontiguous_indexed_char = (char*)noncontiguous_indexed + type_c->block_indices[i+1]*smpi_datatype_get_extent(type_c->old_type);
835       else noncontiguous_indexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
836     }
837     noncontiguous_indexed=(void*)noncontiguous_indexed_char;
838   }
839 }
840
841 void free_indexed(MPI_Datatype* type){
842   xbt_free(((s_smpi_mpi_indexed_t *)(*type)->substruct)->block_lengths);
843   xbt_free(((s_smpi_mpi_indexed_t *)(*type)->substruct)->block_indices);
844   smpi_datatype_unuse(((s_smpi_mpi_indexed_t *)(*type)->substruct)->old_type);
845 }
846
847 /*
848  * Create a Sub type indexed to be able to serialize and unserialize it
849  * the structure s_smpi_mpi_indexed_t is derived from s_smpi_subtype which
850  * required the functions unserialize and serialize
851  */
852 s_smpi_mpi_indexed_t* smpi_datatype_indexed_create( int* block_lengths,
853                                                   int* block_indices,
854                                                   int block_count,
855                                                   MPI_Datatype old_type,
856                                                   int size_oldtype){
857   s_smpi_mpi_indexed_t *new_t= xbt_new(s_smpi_mpi_indexed_t,1);
858   new_t->base.serialize = &serialize_indexed;
859   new_t->base.unserialize = &unserialize_indexed;
860   new_t->base.subtype_free = &free_indexed;
861  //TODO : add a custom function for each time to clean these 
862   new_t->block_lengths= xbt_new(int, block_count);
863   new_t->block_indices= xbt_new(int, block_count);
864   int i;
865   for(i=0;i<block_count;i++){
866     new_t->block_lengths[i]=block_lengths[i];
867     new_t->block_indices[i]=block_indices[i];
868   }
869   new_t->block_count = block_count;
870   smpi_datatype_use(old_type);
871   new_t->old_type = old_type;
872   new_t->size_oldtype = size_oldtype;
873   return new_t;
874 }
875
876
877 int smpi_datatype_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
878 {
879   int i;
880   int retval;
881   int size = 0;
882   int contiguous=1;
883   MPI_Aint lb = 0;
884   MPI_Aint ub = 0;
885   if(count>0){
886     lb=indices[0]*smpi_datatype_get_extent(old_type);
887     ub=indices[0]*smpi_datatype_get_extent(old_type) + blocklens[0]*smpi_datatype_ub(old_type);
888   }
889
890   for(i=0; i< count; i++){
891     if   (blocklens[i]<0)
892       return MPI_ERR_ARG;
893     size += blocklens[i];
894
895     if(indices[i]*smpi_datatype_get_extent(old_type)+smpi_datatype_lb(old_type)<lb)
896       lb = indices[i]*smpi_datatype_get_extent(old_type)+smpi_datatype_lb(old_type);
897     if(indices[i]*smpi_datatype_get_extent(old_type)+blocklens[i]*smpi_datatype_ub(old_type)>ub)
898       ub = indices[i]*smpi_datatype_get_extent(old_type)+blocklens[i]*smpi_datatype_ub(old_type);
899
900     if ( (i< count -1) && (indices[i]+blocklens[i] != indices[i+1]) )contiguous=0;
901   }
902   if (old_type->has_subtype == 1)
903     contiguous=0;
904
905   if(!contiguous){
906     s_smpi_mpi_indexed_t* subtype = smpi_datatype_indexed_create( blocklens,
907                                                                   indices,
908                                                                   count,
909                                                                   old_type,
910                                                                   smpi_datatype_size(old_type));
911      smpi_datatype_create(new_type,  size *
912                          smpi_datatype_size(old_type),lb,ub,1, subtype, DT_FLAG_DATA);
913   }else{
914     s_smpi_mpi_contiguous_t* subtype = smpi_datatype_contiguous_create( lb,
915                                                                   size,
916                                                                   old_type,
917                                                                   smpi_datatype_size(old_type));
918     smpi_datatype_create(new_type,  size *
919                          smpi_datatype_size(old_type),lb,ub,1, subtype, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
920   }
921   retval=MPI_SUCCESS;
922   return retval;
923 }
924
925
926 /*
927 Hindexed Implementation - Indexed with indices in bytes 
928 */
929
930 /*
931  *  Copies noncontiguous data into contiguous memory.
932  *  @param contiguous_hindexed - output hindexed
933  *  @param noncontiguous_hindexed - input hindexed
934  *  @param type - pointer contening :
935  *      - block_lengths - the width or height of blocked matrix
936  *      - block_indices - indices of each data, in bytes
937  *      - count - the number of rows of matrix
938  */
939 void serialize_hindexed( const void *noncontiguous_hindexed,
940                        void *contiguous_hindexed,
941                        int count,
942                        void *type)
943 {
944   s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type;
945   int i,j;
946   char* contiguous_hindexed_char = (char*)contiguous_hindexed;
947   char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed+ type_c->block_indices[0];
948   for(j=0; j<count;j++){
949     for (i = 0; i < type_c->block_count; i++) {
950       if (type_c->old_type->has_subtype == 0)
951         memcpy(contiguous_hindexed_char,
952                      noncontiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
953       else
954         ((s_smpi_subtype_t*)type_c->old_type->substruct)->serialize( noncontiguous_hindexed_char,
955                                                                      contiguous_hindexed_char,
956                                                                      type_c->block_lengths[i],
957                                                                      type_c->old_type->substruct);
958
959       contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
960       if (i<type_c->block_count-1)noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1];
961       else noncontiguous_hindexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
962     }
963     noncontiguous_hindexed=(void*)noncontiguous_hindexed_char;
964   }
965 }
966 /*
967  *  Copies contiguous data into noncontiguous memory.
968  *  @param noncontiguous_hindexed - output hindexed
969  *  @param contiguous_hindexed - input hindexed
970  *  @param type - pointer contening :
971  *      - block_lengths - the width or height of blocked matrix
972  *      - block_indices - indices of each data, in bytes
973  *      - count - the number of rows of matrix
974  */
975 void unserialize_hindexed( const void *contiguous_hindexed,
976                          void *noncontiguous_hindexed,
977                          int count,
978                          void *type,
979                          MPI_Op op)
980 {
981   s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type;
982   int i,j;
983
984   char* contiguous_hindexed_char = (char*)contiguous_hindexed;
985   char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed+ type_c->block_indices[0];
986   for(j=0; j<count;j++){
987     for (i = 0; i < type_c->block_count; i++) {
988       if (type_c->old_type->has_subtype == 0)
989         smpi_op_apply(op, contiguous_hindexed_char, noncontiguous_hindexed_char, &type_c->block_lengths[i],
990                             &type_c->old_type);
991                        /*memcpy(noncontiguous_hindexed_char,
992                contiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype);*/
993       else
994         ((s_smpi_subtype_t*)type_c->old_type->substruct)->unserialize( contiguous_hindexed_char,
995                                                                        noncontiguous_hindexed_char,
996                                                                        type_c->block_lengths[i],
997                                                                        type_c->old_type->substruct,
998                                                                        op);
999
1000       contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
1001       if (i<type_c->block_count-1)noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1];
1002       else noncontiguous_hindexed_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_type);
1003     }
1004     noncontiguous_hindexed=(void*)noncontiguous_hindexed_char;
1005   }
1006 }
1007
1008 void free_hindexed(MPI_Datatype* type){
1009   xbt_free(((s_smpi_mpi_hindexed_t *)(*type)->substruct)->block_lengths);
1010   xbt_free(((s_smpi_mpi_hindexed_t *)(*type)->substruct)->block_indices);
1011   smpi_datatype_unuse(((s_smpi_mpi_indexed_t *)(*type)->substruct)->old_type);
1012 }
1013
1014 /*
1015  * Create a Sub type hindexed to be able to serialize and unserialize it
1016  * the structure s_smpi_mpi_hindexed_t is derived from s_smpi_subtype which
1017  * required the functions unserialize and serialize
1018  */
1019 s_smpi_mpi_hindexed_t* smpi_datatype_hindexed_create( int* block_lengths,
1020                                                   MPI_Aint* block_indices,
1021                                                   int block_count,
1022                                                   MPI_Datatype old_type,
1023                                                   int size_oldtype){
1024   s_smpi_mpi_hindexed_t *new_t= xbt_new(s_smpi_mpi_hindexed_t,1);
1025   new_t->base.serialize = &serialize_hindexed;
1026   new_t->base.unserialize = &unserialize_hindexed;
1027   new_t->base.subtype_free = &free_hindexed;
1028  //TODO : add a custom function for each time to clean these 
1029   new_t->block_lengths= xbt_new(int, block_count);
1030   new_t->block_indices= xbt_new(MPI_Aint, block_count);
1031   int i;
1032   for(i=0;i<block_count;i++){
1033     new_t->block_lengths[i]=block_lengths[i];
1034     new_t->block_indices[i]=block_indices[i];
1035   }
1036   new_t->block_count = block_count;
1037   new_t->old_type = old_type;
1038   new_t->size_oldtype = size_oldtype;
1039   return new_t;
1040 }
1041
1042
1043 int smpi_datatype_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
1044 {
1045   int i;
1046   int retval;
1047   int size = 0;
1048   int contiguous=1;
1049   MPI_Aint lb = 0;
1050   MPI_Aint ub = 0;
1051   if(count>0){
1052     lb=indices[0] + smpi_datatype_lb(old_type);
1053     ub=indices[0] + blocklens[0]*smpi_datatype_ub(old_type);
1054   }
1055   for(i=0; i< count; i++){
1056     if   (blocklens[i]<0)
1057       return MPI_ERR_ARG;
1058     size += blocklens[i];
1059
1060     if(indices[i]+smpi_datatype_lb(old_type)<lb) lb = indices[i]+smpi_datatype_lb(old_type);
1061     if(indices[i]+blocklens[i]*smpi_datatype_ub(old_type)>ub) ub = indices[i]+blocklens[i]*smpi_datatype_ub(old_type);
1062
1063     if ( (i< count -1) && (indices[i]+blocklens[i]*static_cast<int>(smpi_datatype_size(old_type)) != indices[i+1]) )
1064       contiguous=0;
1065   }
1066   if (old_type->has_subtype == 1 || lb!=0)
1067     contiguous=0;
1068
1069   if(!contiguous){
1070     s_smpi_mpi_hindexed_t* subtype = smpi_datatype_hindexed_create( blocklens,
1071                                                                   indices,
1072                                                                   count,
1073                                                                   old_type,
1074                                                                   smpi_datatype_size(old_type));
1075     smpi_datatype_create(new_type,  size * smpi_datatype_size(old_type),
1076              lb,
1077                          ub
1078                          ,1, subtype, DT_FLAG_DATA);
1079   }else{
1080     s_smpi_mpi_contiguous_t* subtype = smpi_datatype_contiguous_create( lb,
1081                                                                   size,
1082                                                                   old_type,
1083                                                                   smpi_datatype_size(old_type));
1084     smpi_datatype_create(new_type,  size * smpi_datatype_size(old_type),
1085                0,size * smpi_datatype_size(old_type),
1086                1, subtype, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
1087   }
1088   retval=MPI_SUCCESS;
1089   return retval;
1090 }
1091
1092
1093 /*
1094 struct Implementation - Indexed with indices in bytes 
1095 */
1096
1097 /*
1098  *  Copies noncontiguous data into contiguous memory.
1099  *  @param contiguous_struct - output struct
1100  *  @param noncontiguous_struct - input struct
1101  *  @param type - pointer contening :
1102  *      - stride - stride of between noncontiguous data
1103  *      - block_length - the width or height of blocked matrix
1104  *      - count - the number of rows of matrix
1105  */
1106 void serialize_struct( const void *noncontiguous_struct,
1107                        void *contiguous_struct,
1108                        int count,
1109                        void *type)
1110 {
1111   s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type;
1112   int i,j;
1113   char* contiguous_struct_char = (char*)contiguous_struct;
1114   char* noncontiguous_struct_char = (char*)noncontiguous_struct+ type_c->block_indices[0];
1115   for(j=0; j<count;j++){
1116     for (i = 0; i < type_c->block_count; i++) {
1117       if (type_c->old_types[i]->has_subtype == 0)
1118         memcpy(contiguous_struct_char,
1119              noncontiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i]));
1120       else
1121         ((s_smpi_subtype_t*)type_c->old_types[i]->substruct)->serialize( noncontiguous_struct_char,
1122                                                                          contiguous_struct_char,
1123                                                                          type_c->block_lengths[i],
1124                                                                          type_c->old_types[i]->substruct);
1125
1126
1127       contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]);
1128       if (i<type_c->block_count-1)noncontiguous_struct_char = (char*)noncontiguous_struct + type_c->block_indices[i+1];
1129       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 ?
1130     }
1131     noncontiguous_struct=(void*)noncontiguous_struct_char;
1132   }
1133 }
1134 /*
1135  *  Copies contiguous data into noncontiguous memory.
1136  *  @param noncontiguous_struct - output struct
1137  *  @param contiguous_struct - input struct
1138  *  @param type - pointer contening :
1139  *      - stride - stride of between noncontiguous data
1140  *      - block_length - the width or height of blocked matrix
1141  *      - count - the number of rows of matrix
1142  */
1143 void unserialize_struct( const void *contiguous_struct,
1144                          void *noncontiguous_struct,
1145                          int count,
1146                          void *type,
1147                          MPI_Op op)
1148 {
1149   s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type;
1150   int i,j;
1151
1152   char* contiguous_struct_char = (char*)contiguous_struct;
1153   char* noncontiguous_struct_char = (char*)noncontiguous_struct+ type_c->block_indices[0];
1154   for(j=0; j<count;j++){
1155     for (i = 0; i < type_c->block_count; i++) {
1156       if (type_c->old_types[i]->has_subtype == 0)
1157         smpi_op_apply(op, contiguous_struct_char, noncontiguous_struct_char, &type_c->block_lengths[i],
1158            & type_c->old_types[i]);
1159                        /*memcpy(noncontiguous_struct_char,
1160              contiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i]));*/
1161       else
1162         ((s_smpi_subtype_t*)type_c->old_types[i]->substruct)->unserialize( contiguous_struct_char,
1163                                                                            noncontiguous_struct_char,
1164                                                                            type_c->block_lengths[i],
1165                                                                            type_c->old_types[i]->substruct,
1166                                                                            op);
1167
1168       contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]);
1169       if (i<type_c->block_count-1)noncontiguous_struct_char =  (char*)noncontiguous_struct + type_c->block_indices[i+1];
1170       else noncontiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_get_extent(type_c->old_types[i]);
1171     }
1172     noncontiguous_struct=(void*)noncontiguous_struct_char;
1173     
1174   }
1175 }
1176
1177 void free_struct(MPI_Datatype* type){
1178   xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->block_lengths);
1179   xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->block_indices);
1180   int i=0;
1181   for (i = 0; i < ((s_smpi_mpi_struct_t *)(*type)->substruct)->block_count; i++)
1182     smpi_datatype_unuse(((s_smpi_mpi_struct_t *)(*type)->substruct)->old_types[i]);
1183   xbt_free(((s_smpi_mpi_struct_t *)(*type)->substruct)->old_types);
1184 }
1185
1186 /*
1187  * Create a Sub type struct to be able to serialize and unserialize it
1188  * the structure s_smpi_mpi_struct_t is derived from s_smpi_subtype which
1189  * required the functions unserialize and serialize
1190  */
1191 s_smpi_mpi_struct_t* smpi_datatype_struct_create( int* block_lengths,
1192                                                   MPI_Aint* block_indices,
1193                                                   int block_count,
1194                                                   MPI_Datatype* old_types){
1195   s_smpi_mpi_struct_t *new_t= xbt_new(s_smpi_mpi_struct_t,1);
1196   new_t->base.serialize = &serialize_struct;
1197   new_t->base.unserialize = &unserialize_struct;
1198   new_t->base.subtype_free = &free_struct;
1199  //TODO : add a custom function for each time to clean these 
1200   new_t->block_lengths= xbt_new(int, block_count);
1201   new_t->block_indices= xbt_new(MPI_Aint, block_count);
1202   new_t->old_types=  xbt_new(MPI_Datatype, block_count);
1203   int i;
1204   for(i=0;i<block_count;i++){
1205     new_t->block_lengths[i]=block_lengths[i];
1206     new_t->block_indices[i]=block_indices[i];
1207     new_t->old_types[i]=old_types[i];
1208     smpi_datatype_use(new_t->old_types[i]);
1209   }
1210   //new_t->block_lengths = block_lengths;
1211   //new_t->block_indices = block_indices;
1212   new_t->block_count = block_count;
1213   //new_t->old_types = old_types;
1214   return new_t;
1215 }
1216
1217
1218 int smpi_datatype_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type)
1219 {
1220   int i;
1221   size_t size = 0;
1222   int contiguous=1;
1223   size = 0;
1224   MPI_Aint lb = 0;
1225   MPI_Aint ub = 0;
1226   if(count>0){
1227     lb=indices[0] + smpi_datatype_lb(old_types[0]);
1228     ub=indices[0] + blocklens[0]*smpi_datatype_ub(old_types[0]);
1229   }
1230   int forced_lb=0;
1231   int forced_ub=0;
1232   for(i=0; i< count; i++){
1233     if (blocklens[i]<0)
1234       return MPI_ERR_ARG;
1235     if (old_types[i]->has_subtype == 1)
1236       contiguous=0;
1237
1238     size += blocklens[i]*smpi_datatype_size(old_types[i]);
1239     if (old_types[i]==MPI_LB){
1240       lb=indices[i];
1241       forced_lb=1;
1242     }
1243     if (old_types[i]==MPI_UB){
1244       ub=indices[i];
1245       forced_ub=1;
1246     }
1247
1248     if(!forced_lb && indices[i]+smpi_datatype_lb(old_types[i])<lb) lb = indices[i];
1249     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]);
1250
1251     if ( (i< count -1) && (indices[i]+blocklens[i]*static_cast<int>(smpi_datatype_size(old_types[i])) != indices[i+1]) )
1252       contiguous=0;
1253   }
1254
1255   if(!contiguous){
1256     s_smpi_mpi_struct_t* subtype = smpi_datatype_struct_create( blocklens,
1257                                                               indices,
1258                                                               count,
1259                                                               old_types);
1260
1261     smpi_datatype_create(new_type,  size, lb, ub,1, subtype, DT_FLAG_DATA);
1262   }else{
1263     s_smpi_mpi_contiguous_t* subtype = smpi_datatype_contiguous_create( lb,
1264                                                                   size,
1265                                                                   MPI_CHAR,
1266                                                                   1);
1267     smpi_datatype_create(new_type,  size, lb, ub,1, subtype, DT_FLAG_DATA|DT_FLAG_CONTIGUOUS);
1268   }
1269   return MPI_SUCCESS;
1270 }
1271
1272 void smpi_datatype_commit(MPI_Datatype *datatype)
1273 {
1274   (*datatype)->flags=  ((*datatype)->flags | DT_FLAG_COMMITED);
1275 }
1276
1277 typedef struct s_smpi_mpi_op {
1278   MPI_User_function *func;
1279   int is_commute;
1280 } s_smpi_mpi_op_t;
1281
1282 #define MAX_OP(a, b)  (b) = (a) < (b) ? (b) : (a)
1283 #define MIN_OP(a, b)  (b) = (a) < (b) ? (a) : (b)
1284 #define SUM_OP(a, b)  (b) += (a)
1285 #define PROD_OP(a, b) (b) *= (a)
1286 #define LAND_OP(a, b) (b) = (a) && (b)
1287 #define LOR_OP(a, b)  (b) = (a) || (b)
1288 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
1289 #define BAND_OP(a, b) (b) &= (a)
1290 #define BOR_OP(a, b)  (b) |= (a)
1291 #define BXOR_OP(a, b) (b) ^= (a)
1292 #define MAXLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (b) : (a)
1293 #define MINLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (a) : (b)
1294
1295 #define APPLY_FUNC(a, b, length, type, func) \
1296 {                                          \
1297   int i;                                   \
1298   type* x = (type*)(a);                    \
1299   type* y = (type*)(b);                    \
1300   for(i = 0; i < *(length); i++) {         \
1301     func(x[i], y[i]);                      \
1302   }                                        \
1303 }
1304
1305 static void max_func(void *a, void *b, int *length,
1306                      MPI_Datatype * datatype)
1307 {
1308   if (*datatype == MPI_CHAR) {
1309     APPLY_FUNC(a, b, length, char, MAX_OP);
1310   } else if (*datatype == MPI_SHORT) {
1311     APPLY_FUNC(a, b, length, short, MAX_OP);
1312   } else if (*datatype == MPI_INT) {
1313     APPLY_FUNC(a, b, length, int, MAX_OP);
1314   } else if (*datatype == MPI_LONG) {
1315     APPLY_FUNC(a, b, length, long, MAX_OP);
1316   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1317     APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
1318   } else if (*datatype == MPI_UNSIGNED) {
1319     APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
1320   } else if (*datatype == MPI_UNSIGNED_LONG) {
1321     APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
1322   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1323     APPLY_FUNC(a, b, length, unsigned char, MAX_OP);
1324   } else if (*datatype == MPI_FLOAT) {
1325     APPLY_FUNC(a, b, length, float, MAX_OP);
1326   } else if (*datatype == MPI_DOUBLE) {
1327     APPLY_FUNC(a, b, length, double, MAX_OP);
1328   } else if (*datatype == MPI_LONG_DOUBLE) {
1329     APPLY_FUNC(a, b, length, long double, MAX_OP);
1330   }
1331 }
1332
1333 static void min_func(void *a, void *b, int *length,
1334                      MPI_Datatype * datatype)
1335 {
1336   if (*datatype == MPI_CHAR) {
1337     APPLY_FUNC(a, b, length, char, MIN_OP);
1338   } else if (*datatype == MPI_SHORT) {
1339     APPLY_FUNC(a, b, length, short, MIN_OP);
1340   } else if (*datatype == MPI_INT) {
1341     APPLY_FUNC(a, b, length, int, MIN_OP);
1342   } else if (*datatype == MPI_LONG) {
1343     APPLY_FUNC(a, b, length, long, MIN_OP);
1344   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1345     APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
1346   } else if (*datatype == MPI_UNSIGNED) {
1347     APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
1348   } else if (*datatype == MPI_UNSIGNED_LONG) {
1349     APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
1350   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1351     APPLY_FUNC(a, b, length, unsigned char, MIN_OP);
1352   } else if (*datatype == MPI_FLOAT) {
1353     APPLY_FUNC(a, b, length, float, MIN_OP);
1354   } else if (*datatype == MPI_DOUBLE) {
1355     APPLY_FUNC(a, b, length, double, MIN_OP);
1356   } else if (*datatype == MPI_LONG_DOUBLE) {
1357     APPLY_FUNC(a, b, length, long double, MIN_OP);
1358   }
1359 }
1360
1361 static void sum_func(void *a, void *b, int *length,
1362                      MPI_Datatype * datatype)
1363 {
1364   if (*datatype == MPI_CHAR) {
1365     APPLY_FUNC(a, b, length, char, SUM_OP);
1366   } else if (*datatype == MPI_SHORT) {
1367     APPLY_FUNC(a, b, length, short, SUM_OP);
1368   } else if (*datatype == MPI_INT) {
1369     APPLY_FUNC(a, b, length, int, SUM_OP);
1370   } else if (*datatype == MPI_LONG) {
1371     APPLY_FUNC(a, b, length, long, SUM_OP);
1372   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1373     APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
1374   } else if (*datatype == MPI_UNSIGNED) {
1375     APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
1376   } else if (*datatype == MPI_UNSIGNED_LONG) {
1377     APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
1378   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1379     APPLY_FUNC(a, b, length, unsigned char, SUM_OP);
1380   } else if (*datatype == MPI_FLOAT) {
1381     APPLY_FUNC(a, b, length, float, SUM_OP);
1382   } else if (*datatype == MPI_DOUBLE) {
1383     APPLY_FUNC(a, b, length, double, SUM_OP);
1384   } else if (*datatype == MPI_LONG_DOUBLE) {
1385     APPLY_FUNC(a, b, length, long double, SUM_OP);
1386   } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
1387     APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
1388   } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
1389     APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
1390   } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
1391     APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
1392   }
1393 }
1394
1395 static void prod_func(void *a, void *b, int *length,
1396                       MPI_Datatype * datatype)
1397 {
1398   if (*datatype == MPI_CHAR) {
1399     APPLY_FUNC(a, b, length, char, PROD_OP);
1400   } else if (*datatype == MPI_SHORT) {
1401     APPLY_FUNC(a, b, length, short, PROD_OP);
1402   } else if (*datatype == MPI_INT) {
1403     APPLY_FUNC(a, b, length, int, PROD_OP);
1404   } else if (*datatype == MPI_LONG) {
1405     APPLY_FUNC(a, b, length, long, PROD_OP);
1406   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1407     APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
1408   } else if (*datatype == MPI_UNSIGNED) {
1409     APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
1410   } else if (*datatype == MPI_UNSIGNED_LONG) {
1411     APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
1412   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1413     APPLY_FUNC(a, b, length, unsigned char, PROD_OP);
1414   } else if (*datatype == MPI_FLOAT) {
1415     APPLY_FUNC(a, b, length, float, PROD_OP);
1416   } else if (*datatype == MPI_DOUBLE) {
1417     APPLY_FUNC(a, b, length, double, PROD_OP);
1418   } else if (*datatype == MPI_LONG_DOUBLE) {
1419     APPLY_FUNC(a, b, length, long double, PROD_OP);
1420   } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
1421     APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
1422   } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
1423     APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
1424   } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
1425     APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
1426   }
1427 }
1428
1429 static void land_func(void *a, void *b, int *length,
1430                       MPI_Datatype * datatype)
1431 {
1432   if (*datatype == MPI_CHAR) {
1433     APPLY_FUNC(a, b, length, char, LAND_OP);
1434   } else if (*datatype == MPI_SHORT) {
1435     APPLY_FUNC(a, b, length, short, LAND_OP);
1436   } else if (*datatype == MPI_INT) {
1437     APPLY_FUNC(a, b, length, int, LAND_OP);
1438   } else if (*datatype == MPI_LONG) {
1439     APPLY_FUNC(a, b, length, long, LAND_OP);
1440   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1441     APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
1442   } else if (*datatype == MPI_UNSIGNED) {
1443     APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
1444   } else if (*datatype == MPI_UNSIGNED_LONG) {
1445     APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
1446   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1447     APPLY_FUNC(a, b, length, unsigned char, LAND_OP);
1448   } else if (*datatype == MPI_C_BOOL) {
1449     APPLY_FUNC(a, b, length, bool, LAND_OP);
1450   }
1451 }
1452
1453 static void lor_func(void *a, void *b, int *length,
1454                      MPI_Datatype * datatype)
1455 {
1456   if (*datatype == MPI_CHAR) {
1457     APPLY_FUNC(a, b, length, char, LOR_OP);
1458   } else if (*datatype == MPI_SHORT) {
1459     APPLY_FUNC(a, b, length, short, LOR_OP);
1460   } else if (*datatype == MPI_INT) {
1461     APPLY_FUNC(a, b, length, int, LOR_OP);
1462   } else if (*datatype == MPI_LONG) {
1463     APPLY_FUNC(a, b, length, long, LOR_OP);
1464   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1465     APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
1466   } else if (*datatype == MPI_UNSIGNED) {
1467     APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
1468   } else if (*datatype == MPI_UNSIGNED_LONG) {
1469     APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
1470   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1471     APPLY_FUNC(a, b, length, unsigned char, LOR_OP);
1472   } else if (*datatype == MPI_C_BOOL) {
1473     APPLY_FUNC(a, b, length, bool, LOR_OP);
1474   }
1475 }
1476
1477 static void lxor_func(void *a, void *b, int *length,
1478                       MPI_Datatype * datatype)
1479 {
1480   if (*datatype == MPI_CHAR) {
1481     APPLY_FUNC(a, b, length, char, LXOR_OP);
1482   } else if (*datatype == MPI_SHORT) {
1483     APPLY_FUNC(a, b, length, short, LXOR_OP);
1484   } else if (*datatype == MPI_INT) {
1485     APPLY_FUNC(a, b, length, int, LXOR_OP);
1486   } else if (*datatype == MPI_LONG) {
1487     APPLY_FUNC(a, b, length, long, LXOR_OP);
1488   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1489     APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
1490   } else if (*datatype == MPI_UNSIGNED) {
1491     APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
1492   } else if (*datatype == MPI_UNSIGNED_LONG) {
1493     APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
1494   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1495     APPLY_FUNC(a, b, length, unsigned char, LXOR_OP);
1496   } else if (*datatype == MPI_C_BOOL) {
1497     APPLY_FUNC(a, b, length, bool, LXOR_OP);
1498   }
1499 }
1500
1501 static void band_func(void *a, void *b, int *length,
1502                       MPI_Datatype * datatype)
1503 {
1504   if (*datatype == MPI_CHAR) {
1505     APPLY_FUNC(a, b, length, char, BAND_OP);
1506   }else if (*datatype == MPI_SHORT) {
1507     APPLY_FUNC(a, b, length, short, BAND_OP);
1508   } else if (*datatype == MPI_INT) {
1509     APPLY_FUNC(a, b, length, int, BAND_OP);
1510   } else if (*datatype == MPI_LONG) {
1511     APPLY_FUNC(a, b, length, long, BAND_OP);
1512   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1513     APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
1514   } else if (*datatype == MPI_UNSIGNED) {
1515     APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
1516   } else if (*datatype == MPI_UNSIGNED_LONG) {
1517     APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
1518   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1519     APPLY_FUNC(a, b, length, unsigned char, BAND_OP);
1520   } else if (*datatype == MPI_BYTE) {
1521     APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
1522   }
1523 }
1524
1525 static void bor_func(void *a, void *b, int *length,
1526                      MPI_Datatype * datatype)
1527 {
1528   if (*datatype == MPI_CHAR) {
1529     APPLY_FUNC(a, b, length, char, BOR_OP);
1530   } else if (*datatype == MPI_SHORT) {
1531     APPLY_FUNC(a, b, length, short, BOR_OP);
1532   } else if (*datatype == MPI_INT) {
1533     APPLY_FUNC(a, b, length, int, BOR_OP);
1534   } else if (*datatype == MPI_LONG) {
1535     APPLY_FUNC(a, b, length, long, BOR_OP);
1536   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1537     APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
1538   } else if (*datatype == MPI_UNSIGNED) {
1539     APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
1540   } else if (*datatype == MPI_UNSIGNED_LONG) {
1541     APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
1542   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1543     APPLY_FUNC(a, b, length, unsigned char, BOR_OP);
1544   } else if (*datatype == MPI_BYTE) {
1545     APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
1546   }
1547 }
1548
1549 static void bxor_func(void *a, void *b, int *length,
1550                       MPI_Datatype * datatype)
1551 {
1552   if (*datatype == MPI_CHAR) {
1553     APPLY_FUNC(a, b, length, char, BXOR_OP);
1554   } else if (*datatype == MPI_SHORT) {
1555     APPLY_FUNC(a, b, length, short, BXOR_OP);
1556   } else if (*datatype == MPI_INT) {
1557     APPLY_FUNC(a, b, length, int, BXOR_OP);
1558   } else if (*datatype == MPI_LONG) {
1559     APPLY_FUNC(a, b, length, long, BXOR_OP);
1560   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1561     APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
1562   } else if (*datatype == MPI_UNSIGNED) {
1563     APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
1564   } else if (*datatype == MPI_UNSIGNED_LONG) {
1565     APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
1566   } else if (*datatype == MPI_UNSIGNED_CHAR) {
1567     APPLY_FUNC(a, b, length, unsigned char, BXOR_OP);
1568   } else if (*datatype == MPI_BYTE) {
1569     APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
1570   }
1571 }
1572
1573 static void minloc_func(void *a, void *b, int *length,
1574                         MPI_Datatype * datatype)
1575 {
1576   if (*datatype == MPI_FLOAT_INT) {
1577     APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
1578   } else if (*datatype == MPI_LONG_INT) {
1579     APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
1580   } else if (*datatype == MPI_DOUBLE_INT) {
1581     APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
1582   } else if (*datatype == MPI_SHORT_INT) {
1583     APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
1584   } else if (*datatype == MPI_2LONG) {
1585     APPLY_FUNC(a, b, length, long_long, MINLOC_OP);
1586   } else if (*datatype == MPI_2INT) {
1587     APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
1588   } else if (*datatype == MPI_LONG_DOUBLE_INT) {
1589     APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
1590   } else if (*datatype == MPI_2FLOAT) {
1591     APPLY_FUNC(a, b, length, float_float, MINLOC_OP);
1592   } else if (*datatype == MPI_2DOUBLE) {
1593     APPLY_FUNC(a, b, length, double_double, MINLOC_OP);
1594   }
1595 }
1596
1597 static void maxloc_func(void *a, void *b, int *length,
1598                         MPI_Datatype * datatype)
1599 {
1600   if (*datatype == MPI_FLOAT_INT) {
1601     APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
1602   } else if (*datatype == MPI_LONG_INT) {
1603     APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
1604   } else if (*datatype == MPI_DOUBLE_INT) {
1605     APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
1606   } else if (*datatype == MPI_SHORT_INT) {
1607     APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
1608   } else if (*datatype == MPI_2LONG) {
1609     APPLY_FUNC(a, b, length, long_long, MAXLOC_OP);
1610   } else if (*datatype == MPI_2INT) {
1611     APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
1612   } else if (*datatype == MPI_LONG_DOUBLE_INT) {
1613     APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
1614   } else if (*datatype == MPI_2FLOAT) {
1615     APPLY_FUNC(a, b, length, float_float, MAXLOC_OP);
1616   } else if (*datatype == MPI_2DOUBLE) {
1617     APPLY_FUNC(a, b, length, double_double, MAXLOC_OP);
1618   }
1619 }
1620
1621 static void replace_func(void *a, void *b, int *length,
1622                         MPI_Datatype * datatype)
1623 {
1624   memcpy(b, a, *length * smpi_datatype_size(*datatype));
1625 }
1626
1627 #define CREATE_MPI_OP(name, func)                             \
1628   static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */, TRUE }; \
1629 MPI_Op name = &mpi_##name;
1630
1631 CREATE_MPI_OP(MPI_MAX, max_func);
1632 CREATE_MPI_OP(MPI_MIN, min_func);
1633 CREATE_MPI_OP(MPI_SUM, sum_func);
1634 CREATE_MPI_OP(MPI_PROD, prod_func);
1635 CREATE_MPI_OP(MPI_LAND, land_func);
1636 CREATE_MPI_OP(MPI_LOR, lor_func);
1637 CREATE_MPI_OP(MPI_LXOR, lxor_func);
1638 CREATE_MPI_OP(MPI_BAND, band_func);
1639 CREATE_MPI_OP(MPI_BOR, bor_func);
1640 CREATE_MPI_OP(MPI_BXOR, bxor_func);
1641 CREATE_MPI_OP(MPI_MAXLOC, maxloc_func);
1642 CREATE_MPI_OP(MPI_MINLOC, minloc_func);
1643 CREATE_MPI_OP(MPI_REPLACE, replace_func);
1644
1645
1646 MPI_Op smpi_op_new(MPI_User_function * function, int commute)
1647 {
1648   MPI_Op op;
1649   op = xbt_new(s_smpi_mpi_op_t, 1);
1650   op->func = function;
1651   op-> is_commute = commute;
1652   return op;
1653 }
1654
1655 int smpi_op_is_commute(MPI_Op op)
1656 {
1657   return (op==MPI_OP_NULL) ? 1 : op-> is_commute;
1658 }
1659
1660 void smpi_op_destroy(MPI_Op op)
1661 {
1662   xbt_free(op);
1663 }
1664
1665 void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len,
1666                    MPI_Datatype * datatype)
1667 {
1668   if(op==MPI_OP_NULL)
1669     return;
1670
1671   if(smpi_privatize_global_variables){ //we need to switch here, as the called function may silently touch global variables
1672     XBT_DEBUG("Applying operation, switch to the right data frame ");
1673     smpi_switch_data_segment(smpi_process_index());
1674   }
1675
1676   if(!smpi_process_get_replaying())
1677   op->func(invec, inoutvec, len, datatype);
1678 }
1679
1680 int smpi_type_attr_delete(MPI_Datatype type, int keyval){
1681   smpi_type_key_elem elem = static_cast<smpi_type_key_elem>(xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)));
1682   if(!elem)
1683     return MPI_ERR_ARG;
1684   if(elem->delete_fn!=MPI_NULL_DELETE_FN){
1685     void * value;
1686     int flag;
1687     if(smpi_type_attr_get(type, keyval, &value, &flag)==MPI_SUCCESS){
1688       int ret = elem->delete_fn(type, keyval, value, &flag);
1689       if(ret!=MPI_SUCCESS) return ret;
1690     }
1691   }  
1692   if(type->attributes==NULL)
1693     return MPI_ERR_ARG;
1694
1695   xbt_dict_remove_ext(type->attributes, (const char*)&keyval, sizeof(int));
1696   return MPI_SUCCESS;
1697 }
1698
1699 int smpi_type_attr_get(MPI_Datatype type, int keyval, void* attr_value, int* flag){
1700   smpi_type_key_elem elem = static_cast<smpi_type_key_elem>(xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)));
1701   if(!elem)
1702     return MPI_ERR_ARG;
1703   xbt_ex_t ex;
1704   if(type->attributes==NULL){
1705     *flag=0;
1706     return MPI_SUCCESS;
1707   }
1708   TRY {
1709     *(void**)attr_value = xbt_dict_get_ext(type->attributes, (const char*)&keyval, sizeof(int));
1710     *flag=1;
1711   }
1712   CATCH(ex) {
1713     *flag=0;
1714     xbt_ex_free(ex);
1715   }
1716   return MPI_SUCCESS;
1717 }
1718
1719 int smpi_type_attr_put(MPI_Datatype type, int keyval, void* attr_value){
1720   if(!smpi_type_keyvals)
1721   smpi_type_keyvals = xbt_dict_new();
1722   smpi_type_key_elem elem = static_cast<smpi_type_key_elem>(xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)));
1723   if(!elem )
1724     return MPI_ERR_ARG;
1725   int flag;
1726   void* value;
1727   smpi_type_attr_get(type, keyval, &value, &flag);
1728   if(flag && elem->delete_fn!=MPI_NULL_DELETE_FN){
1729     int ret = elem->delete_fn(type, keyval, value, &flag);
1730     if(ret!=MPI_SUCCESS) return ret;
1731   }
1732   if(type->attributes==NULL)
1733     type->attributes=xbt_dict_new();
1734
1735   xbt_dict_set_ext(type->attributes, (const char*)&keyval, sizeof(int), attr_value, NULL);
1736   return MPI_SUCCESS;
1737 }
1738
1739 int smpi_type_keyval_create(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval, void* extra_state){
1740
1741   if(!smpi_type_keyvals)
1742   smpi_type_keyvals = xbt_dict_new();
1743   
1744   smpi_type_key_elem value = (smpi_type_key_elem) xbt_new0(s_smpi_mpi_type_key_elem_t,1);
1745   
1746   value->copy_fn=copy_fn;
1747   value->delete_fn=delete_fn;
1748   
1749   *keyval = type_keyval_id;
1750   xbt_dict_set_ext(smpi_type_keyvals,(const char*)keyval, sizeof(int),(void*)value, NULL);
1751   type_keyval_id++;
1752   return MPI_SUCCESS;
1753 }
1754
1755 int smpi_type_keyval_free(int* keyval){
1756   smpi_type_key_elem elem = static_cast<smpi_type_key_elem>(xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)keyval, sizeof(int)));
1757   if(!elem){
1758     return MPI_ERR_ARG;
1759   }
1760   xbt_dict_remove_ext(smpi_type_keyvals, (const char*)keyval, sizeof(int));
1761   xbt_free(elem);
1762   return MPI_SUCCESS;
1763 }
1764
1765 int smpi_mpi_pack(void* inbuf, int incount, MPI_Datatype type, void* outbuf, int outcount, int* position, MPI_Comm comm){
1766   size_t size = smpi_datatype_size(type);
1767   if (outcount - *position < incount*static_cast<int>(size))
1768     return MPI_ERR_BUFFER;
1769   smpi_datatype_copy(inbuf, incount, type,
1770                    (char*)outbuf + *position, outcount, MPI_CHAR);
1771   *position += incount * size;
1772   return MPI_SUCCESS;
1773 }
1774
1775 int smpi_mpi_unpack(void* inbuf, int insize, int* position, void* outbuf, int outcount, MPI_Datatype type, MPI_Comm comm){
1776   int size = static_cast<int>(smpi_datatype_size(type));
1777   if (outcount*size> insize)
1778     return MPI_ERR_BUFFER;
1779   smpi_datatype_copy((char*)inbuf + *position, insize, MPI_CHAR,
1780                    outbuf, outcount, type);
1781   *position += outcount * size;
1782   return MPI_SUCCESS;
1783 }