Logo AND Algorithmique Numérique Distribuée

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