Logo AND Algorithmique Numérique Distribuée

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