Logo AND Algorithmique Numérique Distribuée

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