Logo AND Algorithmique Numérique Distribuée

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