Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge remote-tracking branch 'origin/master'
[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, 2010. 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
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
18                                 "Logging specific to SMPI (datatype)");
19
20 #define CREATE_MPI_DATATYPE(name, type)       \
21   static s_smpi_mpi_datatype_t mpi_##name = { \
22     sizeof(type),  /* size */                 \
23     0,             /*was 1 has_subtype*/             \
24     0,             /* lb */                   \
25     sizeof(type),  /* ub = lb + size */       \
26     DT_FLAG_BASIC,  /* flags */              \
27     NULL           /* pointer on extended struct*/ \
28   };                                          \
29 MPI_Datatype name = &mpi_##name;
30
31
32 //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC.
33 typedef struct {
34   float value;
35   int index;
36 } float_int;
37 typedef struct {
38   long value;
39   int index;
40 } long_int;
41 typedef struct {
42   double value;
43   int index;
44 } double_int;
45 typedef struct {
46   short value;
47   int index;
48 } short_int;
49 typedef struct {
50   int value;
51   int index;
52 } int_int;
53 typedef struct {
54   long double value;
55   int index;
56 } long_double_int;
57
58 // Predefined data types
59 CREATE_MPI_DATATYPE(MPI_CHAR, char);
60 CREATE_MPI_DATATYPE(MPI_SHORT, short);
61 CREATE_MPI_DATATYPE(MPI_INT, int);
62 CREATE_MPI_DATATYPE(MPI_LONG, long);
63 CREATE_MPI_DATATYPE(MPI_LONG_LONG, long long);
64 CREATE_MPI_DATATYPE(MPI_SIGNED_CHAR, signed char);
65 CREATE_MPI_DATATYPE(MPI_UNSIGNED_CHAR, unsigned char);
66 CREATE_MPI_DATATYPE(MPI_UNSIGNED_SHORT, unsigned short);
67 CREATE_MPI_DATATYPE(MPI_UNSIGNED, unsigned int);
68 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG, unsigned long);
69 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG, unsigned long long);
70 CREATE_MPI_DATATYPE(MPI_FLOAT, float);
71 CREATE_MPI_DATATYPE(MPI_DOUBLE, double);
72 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE, long double);
73 CREATE_MPI_DATATYPE(MPI_WCHAR, wchar_t);
74 CREATE_MPI_DATATYPE(MPI_C_BOOL, _Bool);
75 CREATE_MPI_DATATYPE(MPI_INT8_T, int8_t);
76 CREATE_MPI_DATATYPE(MPI_INT16_T, int16_t);
77 CREATE_MPI_DATATYPE(MPI_INT32_T, int32_t);
78 CREATE_MPI_DATATYPE(MPI_INT64_T, int64_t);
79 CREATE_MPI_DATATYPE(MPI_UINT8_T, uint8_t);
80 CREATE_MPI_DATATYPE(MPI_UINT16_T, uint16_t);
81 CREATE_MPI_DATATYPE(MPI_UINT32_T, uint32_t);
82 CREATE_MPI_DATATYPE(MPI_UINT64_T, uint64_t);
83 CREATE_MPI_DATATYPE(MPI_C_FLOAT_COMPLEX, float _Complex);
84 CREATE_MPI_DATATYPE(MPI_C_DOUBLE_COMPLEX, double _Complex);
85 CREATE_MPI_DATATYPE(MPI_C_LONG_DOUBLE_COMPLEX, long double _Complex);
86 CREATE_MPI_DATATYPE(MPI_AINT, MPI_Aint);
87 CREATE_MPI_DATATYPE(MPI_OFFSET, MPI_Offset);
88
89 CREATE_MPI_DATATYPE(MPI_FLOAT_INT, float_int);
90 CREATE_MPI_DATATYPE(MPI_LONG_INT, long_int);
91 CREATE_MPI_DATATYPE(MPI_DOUBLE_INT, double_int);
92 CREATE_MPI_DATATYPE(MPI_SHORT_INT, short_int);
93 CREATE_MPI_DATATYPE(MPI_2INT, int_int);
94 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int);
95
96 // Internal use only
97 CREATE_MPI_DATATYPE(MPI_PTR, void*);
98
99
100 size_t smpi_datatype_size(MPI_Datatype datatype)
101 {
102   return datatype->size;
103 }
104
105
106
107 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype)
108 {
109   return datatype->lb;
110 }
111
112 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype)
113 {
114   return datatype->ub;
115 }
116
117 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
118                          MPI_Aint * extent)
119 {
120   int retval;
121
122   if ((datatype->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
123     retval = MPI_ERR_TYPE;
124   } else {
125     *lb = datatype->lb;
126     *extent = datatype->ub - datatype->lb;
127     retval = MPI_SUCCESS;
128   }
129   return retval;
130 }
131
132 int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype,
133                        void *recvbuf, int recvcount, MPI_Datatype recvtype)
134 {
135   int retval, count;
136
137   /* First check if we really have something to do */
138   if (recvcount == 0) {
139     retval = sendcount == 0 ? MPI_SUCCESS : MPI_ERR_TRUNCATE;
140   } else {
141     /* FIXME: treat packed cases */
142     sendcount *= smpi_datatype_size(sendtype);
143     recvcount *= smpi_datatype_size(recvtype);
144     count = sendcount < recvcount ? sendcount : recvcount;
145
146     if(sendtype->has_subtype == 0 && recvtype->has_subtype == 0) {
147       memcpy(recvbuf, sendbuf, count);
148     }
149     else if (sendtype->has_subtype == 0)
150     {
151       s_smpi_subtype_t *subtype =  recvtype->substruct;
152       subtype->unserialize( sendbuf, recvbuf,1, subtype);
153     }
154     else if (recvtype->has_subtype == 0)
155     {
156       s_smpi_subtype_t *subtype =  sendtype->substruct;
157       subtype->serialize(sendbuf, recvbuf,1, subtype);
158     }else{
159       s_smpi_subtype_t *subtype =  sendtype->substruct;
160
161       s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)sendtype;
162
163       void * buf_tmp = malloc(count * type_c->size_oldtype);
164
165       subtype->serialize( sendbuf, buf_tmp,1, subtype);
166       subtype =  recvtype->substruct;
167       subtype->unserialize(recvbuf, buf_tmp,1, subtype);
168
169       free(buf_tmp);
170     }
171     retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
172   }
173
174   return retval;
175 }
176
177 /*
178  *  Copies noncontiguous data into contiguous memory.
179  *  @param contiguous_vector - output vector
180  *  @param noncontiguous_vector - input vector
181  *  @param type - pointer contening :
182  *      - stride - stride of between noncontiguous data
183  *      - block_length - the width or height of blocked matrix
184  *      - count - the number of rows of matrix
185  */
186 void serialize_vector( const void *noncontiguous_vector,
187                        void *contiguous_vector,
188                        size_t count,
189                        void *type)
190 {
191   s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)type;
192   int i;
193   char* contiguous_vector_char = (char*)contiguous_vector;
194   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
195
196   for (i = 0; i < type_c->block_count * count; i++) {
197     memcpy(contiguous_vector_char,
198            noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype);
199
200     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
201     noncontiguous_vector_char += type_c->block_stride*type_c->size_oldtype;
202   }
203 }
204
205 /*
206  *  Copies contiguous data into noncontiguous memory.
207  *  @param noncontiguous_vector - output vector
208  *  @param contiguous_vector - input vector
209  *  @param type - pointer contening :
210  *      - stride - stride of between noncontiguous data
211  *      - block_length - the width or height of blocked matrix
212  *      - count - the number of rows of matrix
213  */
214 void unserialize_vector( const void *contiguous_vector,
215                          void *noncontiguous_vector,
216                          size_t count,
217                          void *type)
218 {
219   s_smpi_mpi_vector_t* type_c = (s_smpi_mpi_vector_t*)type;
220   int i;
221
222   char* contiguous_vector_char = (char*)contiguous_vector;
223   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
224
225   for (i = 0; i < type_c->block_count * count; i++) {
226     memcpy(noncontiguous_vector_char,
227            contiguous_vector_char, type_c->block_length * type_c->size_oldtype);
228
229     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
230     noncontiguous_vector_char += type_c->block_stride*type_c->size_oldtype;
231   }
232 }
233
234 /*
235  * Create a Sub type vector to be able to serialize and unserialize it
236  * the structre s_smpi_mpi_vector_t is derived from s_smpi_subtype which
237  * required the functions unserialize and serialize
238  *
239  */
240 s_smpi_mpi_vector_t* smpi_datatype_vector_create( int block_stride,
241                                                   int block_length,
242                                                   int block_count,
243                                                   MPI_Datatype old_type,
244                                                   int size_oldtype){
245   s_smpi_mpi_vector_t *new_t= xbt_new(s_smpi_mpi_vector_t,1);
246   new_t->base.serialize = &serialize_vector;
247   new_t->base.unserialize = &unserialize_vector;
248   new_t->block_stride = block_stride;
249   new_t->block_length = block_length;
250   new_t->block_count = block_count;
251   new_t->old_type = old_type;
252   new_t->size_oldtype = size_oldtype;
253   return new_t;
254 }
255
256 void smpi_datatype_create(MPI_Datatype* new_type, int size, int has_subtype,
257                           void *struct_type, int flags){
258   MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1);
259   new_t->size = size;
260   new_t->has_subtype = has_subtype;
261   new_t->lb = 0;
262   new_t->ub = size;
263   new_t->flags = flags;
264   new_t->substruct = struct_type;
265   *new_type = new_t;
266 }
267
268 void smpi_datatype_free(MPI_Datatype* type){
269   xbt_free(*type);
270 }
271
272 int smpi_datatype_contiguous(int count, MPI_Datatype old_type, MPI_Datatype* new_type)
273 {
274   int retval;
275   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
276     retval = MPI_ERR_TYPE;
277   } else {
278     smpi_datatype_create(new_type, count *
279                          smpi_datatype_size(old_type),1,NULL, DT_FLAG_CONTIGUOUS);
280     retval=MPI_SUCCESS;
281   }
282   return retval;
283 }
284
285 int smpi_datatype_vector(int count, int blocklen, int stride, MPI_Datatype old_type, MPI_Datatype* new_type)
286 {
287   int retval;
288   if (blocklen<=0) return MPI_ERR_ARG;
289   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
290     retval = MPI_ERR_TYPE;
291   } else {
292     if(stride != blocklen){
293       s_smpi_mpi_vector_t* subtype = smpi_datatype_vector_create( stride,
294                                                                   blocklen,
295                                                                   count,
296                                                                   old_type,
297                                                                   smpi_datatype_size(old_type));
298
299       smpi_datatype_create(new_type, count * (blocklen) *
300                            smpi_datatype_size(old_type),
301                            1,
302                            subtype,
303                            DT_FLAG_VECTOR);
304       retval=MPI_SUCCESS;
305     }else{
306       /* in this situation the data are contignous thus it's not
307        * required to serialize and unserialize it*/
308       smpi_datatype_create(new_type, count * blocklen *
309                            smpi_datatype_size(old_type),
310                            0,
311                            NULL,
312                            DT_FLAG_VECTOR);
313       retval=MPI_SUCCESS;
314     }
315   }
316   return retval;
317 }
318
319
320
321 /*
322 Hvector Implementation - Vector with stride in bytes
323 */
324
325
326 /*
327  *  Copies noncontiguous data into contiguous memory.
328  *  @param contiguous_hvector - output hvector
329  *  @param noncontiguous_hvector - input hvector
330  *  @param type - pointer contening :
331  *      - stride - stride of between noncontiguous data, in bytes
332  *      - block_length - the width or height of blocked matrix
333  *      - count - the number of rows of matrix
334  */
335 void serialize_hvector( const void *noncontiguous_hvector,
336                        void *contiguous_hvector,
337                        size_t count,
338                        void *type)
339 {
340   s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type;
341   int i;
342   char* contiguous_vector_char = (char*)contiguous_hvector;
343   char* noncontiguous_vector_char = (char*)noncontiguous_hvector;
344
345   for (i = 0; i < type_c->block_count * count; i++) {
346     memcpy(contiguous_vector_char,
347            noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype);
348
349     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
350     noncontiguous_vector_char += type_c->block_stride;
351   }
352 }
353 /*
354  *  Copies contiguous data into noncontiguous memory.
355  *  @param noncontiguous_vector - output hvector
356  *  @param contiguous_vector - input hvector
357  *  @param type - pointer contening :
358  *      - stride - stride of between noncontiguous data, in bytes
359  *      - block_length - the width or height of blocked matrix
360  *      - count - the number of rows of matrix
361  */
362 void unserialize_hvector( const void *contiguous_vector,
363                          void *noncontiguous_vector,
364                          size_t count,
365                          void *type)
366 {
367   s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type;
368   int i;
369
370   char* contiguous_vector_char = (char*)contiguous_vector;
371   char* noncontiguous_vector_char = (char*)noncontiguous_vector;
372
373   for (i = 0; i < type_c->block_count * count; i++) {
374     memcpy(noncontiguous_vector_char,
375            contiguous_vector_char, type_c->block_length * type_c->size_oldtype);
376
377     contiguous_vector_char += type_c->block_length*type_c->size_oldtype;
378     noncontiguous_vector_char += type_c->block_stride;
379   }
380 }
381
382 /*
383  * Create a Sub type vector to be able to serialize and unserialize it
384  * the structre s_smpi_mpi_vector_t is derived from s_smpi_subtype which
385  * required the functions unserialize and serialize
386  *
387  */
388 s_smpi_mpi_hvector_t* smpi_datatype_hvector_create( MPI_Aint block_stride,
389                                                   int block_length,
390                                                   int block_count,
391                                                   MPI_Datatype old_type,
392                                                   int size_oldtype){
393   s_smpi_mpi_hvector_t *new_t= xbt_new(s_smpi_mpi_hvector_t,1);
394   new_t->base.serialize = &serialize_hvector;
395   new_t->base.unserialize = &unserialize_hvector;
396   new_t->block_stride = block_stride;
397   new_t->block_length = block_length;
398   new_t->block_count = block_count;
399   new_t->old_type = old_type;
400   new_t->size_oldtype = size_oldtype;
401   return new_t;
402 }
403
404 int smpi_datatype_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type)
405 {
406   int retval;
407   if (blocklen<=0) return MPI_ERR_ARG;
408   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
409     retval = MPI_ERR_TYPE;
410   } else {
411     if(stride != blocklen*smpi_datatype_size(old_type)){
412       s_smpi_mpi_hvector_t* subtype = smpi_datatype_hvector_create( stride,
413                                                                     blocklen,
414                                                                     count,
415                                                                     old_type,
416                                                                     smpi_datatype_size(old_type));
417
418       smpi_datatype_create(new_type, count * blocklen *
419                            smpi_datatype_size(old_type),
420                            1,
421                            subtype,
422                            DT_FLAG_VECTOR);
423       retval=MPI_SUCCESS;
424     }else{
425       smpi_datatype_create(new_type, count * blocklen *
426                                                smpi_datatype_size(old_type),
427                                               0,
428                                               NULL,
429                                               DT_FLAG_VECTOR);
430       retval=MPI_SUCCESS;
431     }
432   }
433   return retval;
434 }
435
436
437 /*
438 Indexed Implementation
439 */
440
441 /*
442  *  Copies noncontiguous data into contiguous memory.
443  *  @param contiguous_indexed - output indexed
444  *  @param noncontiguous_indexed - input indexed
445  *  @param type - pointer contening :
446  *      - stride - stride of between noncontiguous data
447  *      - block_length - the width or height of blocked matrix
448  *      - count - the number of rows of matrix
449  */
450 void serialize_indexed( const void *noncontiguous_indexed,
451                        void *contiguous_indexed,
452                        size_t count,
453                        void *type)
454 {
455   s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type;
456   int i;
457   char* contiguous_indexed_char = (char*)contiguous_indexed;
458   char* noncontiguous_indexed_char = (char*)noncontiguous_indexed;
459
460   for (i = 0; i < type_c->block_count * count; i++) {
461     memcpy(contiguous_indexed_char,
462            noncontiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
463
464     contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
465     noncontiguous_indexed_char = (char*)noncontiguous_indexed + type_c->block_indices[i+1]*type_c->size_oldtype;
466   }
467 }
468 /*
469  *  Copies contiguous data into noncontiguous memory.
470  *  @param noncontiguous_indexed - output indexed
471  *  @param contiguous_indexed - input indexed
472  *  @param type - pointer contening :
473  *      - stride - stride of between noncontiguous data
474  *      - block_length - the width or height of blocked matrix
475  *      - count - the number of rows of matrix
476  */
477 void unserialize_indexed( const void *contiguous_indexed,
478                          void *noncontiguous_indexed,
479                          size_t count,
480                          void *type)
481 {
482   s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type;
483   int i;
484
485   char* contiguous_indexed_char = (char*)contiguous_indexed;
486   char* noncontiguous_indexed_char = (char*)noncontiguous_indexed;
487
488   for (i = 0; i < type_c->block_count * count; i++) {
489     memcpy(noncontiguous_indexed_char,
490            contiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
491
492     contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
493     noncontiguous_indexed_char = (char*)noncontiguous_indexed + type_c->block_indices[i+1]*type_c->size_oldtype;
494   }
495 }
496
497 /*
498  * Create a Sub type indexed to be able to serialize and unserialize it
499  * the structre s_smpi_mpi_indexed_t is derived from s_smpi_subtype which
500  * required the functions unserialize and serialize
501  */
502 s_smpi_mpi_indexed_t* smpi_datatype_indexed_create( int* block_lengths,
503                                                   int* block_indices,
504                                                   int block_count,
505                                                   MPI_Datatype old_type,
506                                                   int size_oldtype){
507   s_smpi_mpi_indexed_t *new_t= xbt_new(s_smpi_mpi_indexed_t,1);
508   new_t->base.serialize = &serialize_indexed;
509   new_t->base.unserialize = &unserialize_indexed;
510  //FIXME : copy those or assume they won't be freed ? 
511   new_t->block_lengths = block_lengths;
512   new_t->block_indices = block_indices;
513   new_t->block_count = block_count;
514   new_t->old_type = old_type;
515   new_t->size_oldtype = size_oldtype;
516   return new_t;
517 }
518
519
520 int smpi_datatype_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
521 {
522   int i;
523   int retval;
524   int size = 0;
525   for(i=0; i< count; i++){
526     if   (blocklens[i]<=0)
527       return MPI_ERR_ARG;
528     size += blocklens[i];
529   }
530   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
531     retval = MPI_ERR_TYPE;
532   } else {
533     s_smpi_mpi_indexed_t* subtype = smpi_datatype_indexed_create( blocklens,
534                                                                   indices,
535                                                                   count,
536                                                                   old_type,
537                                                                   smpi_datatype_size(old_type));
538
539     smpi_datatype_create(new_type,  size *
540                          smpi_datatype_size(old_type),1, subtype, DT_FLAG_DATA);
541     retval=MPI_SUCCESS;
542   }
543   return retval;
544 }
545
546
547 /*
548 Hindexed Implementation - Indexed with indices in bytes 
549 */
550
551 /*
552  *  Copies noncontiguous data into contiguous memory.
553  *  @param contiguous_hindexed - output hindexed
554  *  @param noncontiguous_hindexed - input hindexed
555  *  @param type - pointer contening :
556  *      - stride - stride of between noncontiguous data
557  *      - block_length - the width or height of blocked matrix
558  *      - count - the number of rows of matrix
559  */
560 void serialize_hindexed( const void *noncontiguous_hindexed,
561                        void *contiguous_hindexed,
562                        size_t count,
563                        void *type)
564 {
565   s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type;
566   int i;
567   char* contiguous_hindexed_char = (char*)contiguous_hindexed;
568   char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed;
569
570   for (i = 0; i < type_c->block_count * count; i++) {
571     memcpy(contiguous_hindexed_char,
572            noncontiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
573
574     contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
575     noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1];
576   }
577 }
578 /*
579  *  Copies contiguous data into noncontiguous memory.
580  *  @param noncontiguous_hindexed - output hindexed
581  *  @param contiguous_hindexed - input hindexed
582  *  @param type - pointer contening :
583  *      - stride - stride of between noncontiguous data
584  *      - block_length - the width or height of blocked matrix
585  *      - count - the number of rows of matrix
586  */
587 void unserialize_hindexed( const void *contiguous_hindexed,
588                          void *noncontiguous_hindexed,
589                          size_t count,
590                          void *type)
591 {
592   s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type;
593   int i;
594
595   char* contiguous_hindexed_char = (char*)contiguous_hindexed;
596   char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed;
597
598   for (i = 0; i < type_c->block_count * count; i++) {
599     memcpy(noncontiguous_hindexed_char,
600            contiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype);
601
602     contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype;
603     noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1];
604   }
605 }
606
607 /*
608  * Create a Sub type hindexed to be able to serialize and unserialize it
609  * the structre s_smpi_mpi_hindexed_t is derived from s_smpi_subtype which
610  * required the functions unserialize and serialize
611  */
612 s_smpi_mpi_hindexed_t* smpi_datatype_hindexed_create( int* block_lengths,
613                                                   MPI_Aint* block_indices,
614                                                   int block_count,
615                                                   MPI_Datatype old_type,
616                                                   int size_oldtype){
617   s_smpi_mpi_hindexed_t *new_t= xbt_new(s_smpi_mpi_hindexed_t,1);
618   new_t->base.serialize = &serialize_hindexed;
619   new_t->base.unserialize = &unserialize_hindexed;
620  //FIXME : copy those or assume they won't be freed ? 
621   new_t->block_lengths = block_lengths;
622   new_t->block_indices = block_indices;
623   new_t->block_count = block_count;
624   new_t->old_type = old_type;
625   new_t->size_oldtype = size_oldtype;
626   return new_t;
627 }
628
629
630 int smpi_datatype_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
631 {
632   int i;
633   int retval;
634   int size = 0;
635   for(i=0; i< count; i++){
636     if   (blocklens[i]<=0)
637       return MPI_ERR_ARG;
638     size += blocklens[i];
639   }
640   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
641     retval = MPI_ERR_TYPE;
642   } else {
643     s_smpi_mpi_hindexed_t* subtype = smpi_datatype_hindexed_create( blocklens,
644                                                                   indices,
645                                                                   count,
646                                                                   old_type,
647                                                                   smpi_datatype_size(old_type));
648
649     smpi_datatype_create(new_type,  size *
650                          smpi_datatype_size(old_type),1, subtype, DT_FLAG_DATA);
651     retval=MPI_SUCCESS;
652   }
653   return retval;
654 }
655
656
657 /*
658 struct Implementation - Indexed with indices in bytes 
659 */
660
661 /*
662  *  Copies noncontiguous data into contiguous memory.
663  *  @param contiguous_struct - output struct
664  *  @param noncontiguous_struct - input struct
665  *  @param type - pointer contening :
666  *      - stride - stride of between noncontiguous data
667  *      - block_length - the width or height of blocked matrix
668  *      - count - the number of rows of matrix
669  */
670 void serialize_struct( const void *noncontiguous_struct,
671                        void *contiguous_struct,
672                        size_t count,
673                        void *type)
674 {
675   s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type;
676   int i;
677   char* contiguous_struct_char = (char*)contiguous_struct;
678   char* noncontiguous_struct_char = (char*)noncontiguous_struct;
679
680   for (i = 0; i < type_c->block_count * count; i++) {
681     memcpy(contiguous_struct_char,
682            noncontiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i]));
683     contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]);
684     noncontiguous_struct_char = (char*)noncontiguous_struct + type_c->block_indices[i+1];
685   }
686 }
687 /*
688  *  Copies contiguous data into noncontiguous memory.
689  *  @param noncontiguous_struct - output struct
690  *  @param contiguous_struct - input struct
691  *  @param type - pointer contening :
692  *      - stride - stride of between noncontiguous data
693  *      - block_length - the width or height of blocked matrix
694  *      - count - the number of rows of matrix
695  */
696 void unserialize_struct( const void *contiguous_struct,
697                          void *noncontiguous_struct,
698                          size_t count,
699                          void *type)
700 {
701   s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type;
702   int i;
703
704   char* contiguous_struct_char = (char*)contiguous_struct;
705   char* noncontiguous_struct_char = (char*)noncontiguous_struct;
706
707   for (i = 0; i < type_c->block_count * count; i++) {
708     memcpy(noncontiguous_struct_char,
709            contiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i]));
710     contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]);
711     noncontiguous_struct_char = (char*)noncontiguous_struct + type_c->block_indices[i+1];
712   }
713 }
714
715 /*
716  * Create a Sub type struct to be able to serialize and unserialize it
717  * the structre s_smpi_mpi_struct_t is derived from s_smpi_subtype which
718  * required the functions unserialize and serialize
719  */
720 s_smpi_mpi_struct_t* smpi_datatype_struct_create( int* block_lengths,
721                                                   MPI_Aint* block_indices,
722                                                   int block_count,
723                                                   MPI_Datatype* old_types){
724   s_smpi_mpi_struct_t *new_t= xbt_new(s_smpi_mpi_struct_t,1);
725   new_t->base.serialize = &serialize_struct;
726   new_t->base.unserialize = &unserialize_struct;
727  //FIXME : copy those or assume they won't be freed ? 
728   new_t->block_lengths = block_lengths;
729   new_t->block_indices = block_indices;
730   new_t->block_count = block_count;
731   new_t->old_types = old_types;
732   return new_t;
733 }
734
735
736 int smpi_datatype_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type)
737 {
738   int i;
739   size_t size = 0;
740   for(i=0; i< count; i++){
741     if (blocklens[i]<=0)
742       return MPI_ERR_ARG;
743     if ((old_types[i]->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED)
744       return MPI_ERR_TYPE;
745     size += blocklens[i]*smpi_datatype_size(old_types[i]);
746   }
747
748
749   s_smpi_mpi_struct_t* subtype = smpi_datatype_struct_create( blocklens,
750                                                               indices,
751                                                               count,
752                                                               old_types);
753
754   smpi_datatype_create(new_type,  size ,1, subtype, DT_FLAG_DATA);
755
756   return MPI_SUCCESS;
757 }
758
759 void smpi_datatype_commit(MPI_Datatype *datatype)
760 {
761   (*datatype)->flags=  ((*datatype)->flags | DT_FLAG_COMMITED);
762 }
763
764 typedef struct s_smpi_mpi_op {
765   MPI_User_function *func;
766 } s_smpi_mpi_op_t;
767
768 #define MAX_OP(a, b)  (b) = (a) < (b) ? (b) : (a)
769 #define MIN_OP(a, b)  (b) = (a) < (b) ? (a) : (b)
770 #define SUM_OP(a, b)  (b) += (a)
771 #define PROD_OP(a, b) (b) *= (a)
772 #define LAND_OP(a, b) (b) = (a) && (b)
773 #define LOR_OP(a, b)  (b) = (a) || (b)
774 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
775 #define BAND_OP(a, b) (b) &= (a)
776 #define BOR_OP(a, b)  (b) |= (a)
777 #define BXOR_OP(a, b) (b) ^= (a)
778 #define MAXLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (b) : (a)
779 #define MINLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (a) : (b)
780 //TODO : MINLOC & MAXLOC
781
782 #define APPLY_FUNC(a, b, length, type, func) \
783 {                                          \
784   int i;                                   \
785   type* x = (type*)(a);                    \
786   type* y = (type*)(b);                    \
787   for(i = 0; i < *(length); i++) {         \
788     func(x[i], y[i]);                      \
789   }                                        \
790 }
791
792 static void max_func(void *a, void *b, int *length,
793                      MPI_Datatype * datatype)
794 {
795   if (*datatype == MPI_CHAR) {
796     APPLY_FUNC(a, b, length, char, MAX_OP);
797   } else if (*datatype == MPI_SHORT) {
798     APPLY_FUNC(a, b, length, short, MAX_OP);
799   } else if (*datatype == MPI_INT) {
800     APPLY_FUNC(a, b, length, int, MAX_OP);
801   } else if (*datatype == MPI_LONG) {
802     APPLY_FUNC(a, b, length, long, MAX_OP);
803   } else if (*datatype == MPI_UNSIGNED_SHORT) {
804     APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
805   } else if (*datatype == MPI_UNSIGNED) {
806     APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
807   } else if (*datatype == MPI_UNSIGNED_LONG) {
808     APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
809   } else if (*datatype == MPI_FLOAT) {
810     APPLY_FUNC(a, b, length, float, MAX_OP);
811   } else if (*datatype == MPI_DOUBLE) {
812     APPLY_FUNC(a, b, length, double, MAX_OP);
813   } else if (*datatype == MPI_LONG_DOUBLE) {
814     APPLY_FUNC(a, b, length, long double, MAX_OP);
815   }
816 }
817
818 static void min_func(void *a, void *b, int *length,
819                      MPI_Datatype * datatype)
820 {
821   if (*datatype == MPI_CHAR) {
822     APPLY_FUNC(a, b, length, char, MIN_OP);
823   } else if (*datatype == MPI_SHORT) {
824     APPLY_FUNC(a, b, length, short, MIN_OP);
825   } else if (*datatype == MPI_INT) {
826     APPLY_FUNC(a, b, length, int, MIN_OP);
827   } else if (*datatype == MPI_LONG) {
828     APPLY_FUNC(a, b, length, long, MIN_OP);
829   } else if (*datatype == MPI_UNSIGNED_SHORT) {
830     APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
831   } else if (*datatype == MPI_UNSIGNED) {
832     APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
833   } else if (*datatype == MPI_UNSIGNED_LONG) {
834     APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
835   } else if (*datatype == MPI_FLOAT) {
836     APPLY_FUNC(a, b, length, float, MIN_OP);
837   } else if (*datatype == MPI_DOUBLE) {
838     APPLY_FUNC(a, b, length, double, MIN_OP);
839   } else if (*datatype == MPI_LONG_DOUBLE) {
840     APPLY_FUNC(a, b, length, long double, MIN_OP);
841   }
842 }
843
844 static void sum_func(void *a, void *b, int *length,
845                      MPI_Datatype * datatype)
846 {
847   if (*datatype == MPI_CHAR) {
848     APPLY_FUNC(a, b, length, char, SUM_OP);
849   } else if (*datatype == MPI_SHORT) {
850     APPLY_FUNC(a, b, length, short, SUM_OP);
851   } else if (*datatype == MPI_INT) {
852     APPLY_FUNC(a, b, length, int, SUM_OP);
853   } else if (*datatype == MPI_LONG) {
854     APPLY_FUNC(a, b, length, long, SUM_OP);
855   } else if (*datatype == MPI_UNSIGNED_SHORT) {
856     APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
857   } else if (*datatype == MPI_UNSIGNED) {
858     APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
859   } else if (*datatype == MPI_UNSIGNED_LONG) {
860     APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
861   } else if (*datatype == MPI_FLOAT) {
862     APPLY_FUNC(a, b, length, float, SUM_OP);
863   } else if (*datatype == MPI_DOUBLE) {
864     APPLY_FUNC(a, b, length, double, SUM_OP);
865   } else if (*datatype == MPI_LONG_DOUBLE) {
866     APPLY_FUNC(a, b, length, long double, SUM_OP);
867   } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
868     APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
869   } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
870     APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
871   } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
872     APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
873   }
874 }
875
876 static void prod_func(void *a, void *b, int *length,
877                       MPI_Datatype * datatype)
878 {
879   if (*datatype == MPI_CHAR) {
880     APPLY_FUNC(a, b, length, char, PROD_OP);
881   } else if (*datatype == MPI_SHORT) {
882     APPLY_FUNC(a, b, length, short, PROD_OP);
883   } else if (*datatype == MPI_INT) {
884     APPLY_FUNC(a, b, length, int, PROD_OP);
885   } else if (*datatype == MPI_LONG) {
886     APPLY_FUNC(a, b, length, long, PROD_OP);
887   } else if (*datatype == MPI_UNSIGNED_SHORT) {
888     APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
889   } else if (*datatype == MPI_UNSIGNED) {
890     APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
891   } else if (*datatype == MPI_UNSIGNED_LONG) {
892     APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
893   } else if (*datatype == MPI_FLOAT) {
894     APPLY_FUNC(a, b, length, float, PROD_OP);
895   } else if (*datatype == MPI_DOUBLE) {
896     APPLY_FUNC(a, b, length, double, PROD_OP);
897   } else if (*datatype == MPI_LONG_DOUBLE) {
898     APPLY_FUNC(a, b, length, long double, PROD_OP);
899   } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
900     APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
901   } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
902     APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
903   } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
904     APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
905   }
906 }
907
908 static void land_func(void *a, void *b, int *length,
909                       MPI_Datatype * datatype)
910 {
911   if (*datatype == MPI_CHAR) {
912     APPLY_FUNC(a, b, length, char, LAND_OP);
913   } else if (*datatype == MPI_SHORT) {
914     APPLY_FUNC(a, b, length, short, LAND_OP);
915   } else if (*datatype == MPI_INT) {
916     APPLY_FUNC(a, b, length, int, LAND_OP);
917   } else if (*datatype == MPI_LONG) {
918     APPLY_FUNC(a, b, length, long, LAND_OP);
919   } else if (*datatype == MPI_UNSIGNED_SHORT) {
920     APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
921   } else if (*datatype == MPI_UNSIGNED) {
922     APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
923   } else if (*datatype == MPI_UNSIGNED_LONG) {
924     APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
925   } else if (*datatype == MPI_C_BOOL) {
926     APPLY_FUNC(a, b, length, _Bool, LAND_OP);
927   }
928 }
929
930 static void lor_func(void *a, void *b, int *length,
931                      MPI_Datatype * datatype)
932 {
933   if (*datatype == MPI_CHAR) {
934     APPLY_FUNC(a, b, length, char, LOR_OP);
935   } else if (*datatype == MPI_SHORT) {
936     APPLY_FUNC(a, b, length, short, LOR_OP);
937   } else if (*datatype == MPI_INT) {
938     APPLY_FUNC(a, b, length, int, LOR_OP);
939   } else if (*datatype == MPI_LONG) {
940     APPLY_FUNC(a, b, length, long, LOR_OP);
941   } else if (*datatype == MPI_UNSIGNED_SHORT) {
942     APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
943   } else if (*datatype == MPI_UNSIGNED) {
944     APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
945   } else if (*datatype == MPI_UNSIGNED_LONG) {
946     APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
947   } else if (*datatype == MPI_C_BOOL) {
948     APPLY_FUNC(a, b, length, _Bool, LOR_OP);
949   }
950 }
951
952 static void lxor_func(void *a, void *b, int *length,
953                       MPI_Datatype * datatype)
954 {
955   if (*datatype == MPI_CHAR) {
956     APPLY_FUNC(a, b, length, char, LXOR_OP);
957   } else if (*datatype == MPI_SHORT) {
958     APPLY_FUNC(a, b, length, short, LXOR_OP);
959   } else if (*datatype == MPI_INT) {
960     APPLY_FUNC(a, b, length, int, LXOR_OP);
961   } else if (*datatype == MPI_LONG) {
962     APPLY_FUNC(a, b, length, long, LXOR_OP);
963   } else if (*datatype == MPI_UNSIGNED_SHORT) {
964     APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
965   } else if (*datatype == MPI_UNSIGNED) {
966     APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
967   } else if (*datatype == MPI_UNSIGNED_LONG) {
968     APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
969   } else if (*datatype == MPI_C_BOOL) {
970     APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
971   }
972 }
973
974 static void band_func(void *a, void *b, int *length,
975                       MPI_Datatype * datatype)
976 {
977   if (*datatype == MPI_CHAR) {
978     APPLY_FUNC(a, b, length, char, BAND_OP);
979   }
980   if (*datatype == MPI_SHORT) {
981     APPLY_FUNC(a, b, length, short, BAND_OP);
982   } else if (*datatype == MPI_INT) {
983     APPLY_FUNC(a, b, length, int, BAND_OP);
984   } else if (*datatype == MPI_LONG) {
985     APPLY_FUNC(a, b, length, long, BAND_OP);
986   } else if (*datatype == MPI_UNSIGNED_SHORT) {
987     APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
988   } else if (*datatype == MPI_UNSIGNED) {
989     APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
990   } else if (*datatype == MPI_UNSIGNED_LONG) {
991     APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
992   } else if (*datatype == MPI_BYTE) {
993     APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
994   }
995 }
996
997 static void bor_func(void *a, void *b, int *length,
998                      MPI_Datatype * datatype)
999 {
1000   if (*datatype == MPI_CHAR) {
1001     APPLY_FUNC(a, b, length, char, BOR_OP);
1002   } else if (*datatype == MPI_SHORT) {
1003     APPLY_FUNC(a, b, length, short, BOR_OP);
1004   } else if (*datatype == MPI_INT) {
1005     APPLY_FUNC(a, b, length, int, BOR_OP);
1006   } else if (*datatype == MPI_LONG) {
1007     APPLY_FUNC(a, b, length, long, BOR_OP);
1008   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1009     APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
1010   } else if (*datatype == MPI_UNSIGNED) {
1011     APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
1012   } else if (*datatype == MPI_UNSIGNED_LONG) {
1013     APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
1014   } else if (*datatype == MPI_BYTE) {
1015     APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
1016   }
1017 }
1018
1019 static void bxor_func(void *a, void *b, int *length,
1020                       MPI_Datatype * datatype)
1021 {
1022   if (*datatype == MPI_CHAR) {
1023     APPLY_FUNC(a, b, length, char, BXOR_OP);
1024   } else if (*datatype == MPI_SHORT) {
1025     APPLY_FUNC(a, b, length, short, BXOR_OP);
1026   } else if (*datatype == MPI_INT) {
1027     APPLY_FUNC(a, b, length, int, BXOR_OP);
1028   } else if (*datatype == MPI_LONG) {
1029     APPLY_FUNC(a, b, length, long, BXOR_OP);
1030   } else if (*datatype == MPI_UNSIGNED_SHORT) {
1031     APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
1032   } else if (*datatype == MPI_UNSIGNED) {
1033     APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
1034   } else if (*datatype == MPI_UNSIGNED_LONG) {
1035     APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
1036   } else if (*datatype == MPI_BYTE) {
1037     APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
1038   }
1039 }
1040
1041 static void minloc_func(void *a, void *b, int *length,
1042                         MPI_Datatype * datatype)
1043 {
1044   if (*datatype == MPI_FLOAT_INT) {
1045     APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
1046   } else if (*datatype == MPI_LONG_INT) {
1047     APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
1048   } else if (*datatype == MPI_DOUBLE_INT) {
1049     APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
1050   } else if (*datatype == MPI_SHORT_INT) {
1051     APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
1052   } else if (*datatype == MPI_2INT) {
1053     APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
1054   } else if (*datatype == MPI_LONG_DOUBLE_INT) {
1055     APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
1056   }
1057 }
1058
1059 static void maxloc_func(void *a, void *b, int *length,
1060                         MPI_Datatype * datatype)
1061 {
1062   if (*datatype == MPI_FLOAT_INT) {
1063     APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
1064   } else if (*datatype == MPI_LONG_INT) {
1065     APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
1066   } else if (*datatype == MPI_DOUBLE_INT) {
1067     APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
1068   } else if (*datatype == MPI_SHORT_INT) {
1069     APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
1070   } else if (*datatype == MPI_2INT) {
1071     APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
1072   } else if (*datatype == MPI_LONG_DOUBLE_INT) {
1073     APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
1074   }
1075 }
1076
1077
1078 #define CREATE_MPI_OP(name, func)                             \
1079   static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
1080 MPI_Op name = &mpi_##name;
1081
1082 CREATE_MPI_OP(MPI_MAX, max_func);
1083 CREATE_MPI_OP(MPI_MIN, min_func);
1084 CREATE_MPI_OP(MPI_SUM, sum_func);
1085 CREATE_MPI_OP(MPI_PROD, prod_func);
1086 CREATE_MPI_OP(MPI_LAND, land_func);
1087 CREATE_MPI_OP(MPI_LOR, lor_func);
1088 CREATE_MPI_OP(MPI_LXOR, lxor_func);
1089 CREATE_MPI_OP(MPI_BAND, band_func);
1090 CREATE_MPI_OP(MPI_BOR, bor_func);
1091 CREATE_MPI_OP(MPI_BXOR, bxor_func);
1092 CREATE_MPI_OP(MPI_MAXLOC, maxloc_func);
1093 CREATE_MPI_OP(MPI_MINLOC, minloc_func);
1094
1095 MPI_Op smpi_op_new(MPI_User_function * function, int commute)
1096 {
1097   MPI_Op op;
1098
1099   //FIXME: add commute param
1100   op = xbt_new(s_smpi_mpi_op_t, 1);
1101   op->func = function;
1102   return op;
1103 }
1104
1105 void smpi_op_destroy(MPI_Op op)
1106 {
1107   xbt_free(op);
1108 }
1109
1110 void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len,
1111                    MPI_Datatype * datatype)
1112 {
1113   op->func(invec, inoutvec, len, datatype);
1114 }