Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Update doc for asynchronous comm and pthread_mutexes of pthread_conds.
[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 typedef struct s_smpi_mpi_datatype {
21   size_t size;
22   MPI_Aint lb;
23   MPI_Aint ub;
24   int flags;
25 } s_smpi_mpi_datatype_t;
26
27 #define CREATE_MPI_DATATYPE(name, type)       \
28   static s_smpi_mpi_datatype_t mpi_##name = { \
29     sizeof(type),  /* size */                 \
30     0,             /* lb */                   \
31     sizeof(type),  /* ub = lb + size */       \
32     DT_FLAG_BASIC  /* flags */                \
33   };                                          \
34   MPI_Datatype name = &mpi_##name;
35
36
37 //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC.
38 typedef struct { float       value; int index;} float_int;
39 typedef struct { long        value; int index;} long_int ;
40 typedef struct { double      value; int index;} double_int;
41 typedef struct { short       value; int index;} short_int;
42 typedef struct { int         value; int index;} int_int;
43 typedef struct { long double value; int index;} long_double_int;
44
45 // Predefined data types
46 CREATE_MPI_DATATYPE(MPI_CHAR,                  char);
47 CREATE_MPI_DATATYPE(MPI_SHORT,                 short);
48 CREATE_MPI_DATATYPE(MPI_INT,                   int);
49 CREATE_MPI_DATATYPE(MPI_LONG,                  long);
50 CREATE_MPI_DATATYPE(MPI_LONG_LONG,             long long);
51 CREATE_MPI_DATATYPE(MPI_SIGNED_CHAR,           signed char);
52 CREATE_MPI_DATATYPE(MPI_UNSIGNED_CHAR,         unsigned char);
53 CREATE_MPI_DATATYPE(MPI_UNSIGNED_SHORT,        unsigned short);
54 CREATE_MPI_DATATYPE(MPI_UNSIGNED,              unsigned int);
55 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG,         unsigned long);
56 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG,    unsigned long long);
57 CREATE_MPI_DATATYPE(MPI_FLOAT,                 float);
58 CREATE_MPI_DATATYPE(MPI_DOUBLE,                double);
59 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE,           long double);
60 CREATE_MPI_DATATYPE(MPI_WCHAR,                 wchar_t);
61 CREATE_MPI_DATATYPE(MPI_C_BOOL,                _Bool);
62 CREATE_MPI_DATATYPE(MPI_INT8_T,                int8_t);
63 CREATE_MPI_DATATYPE(MPI_INT16_T,               int16_t);
64 CREATE_MPI_DATATYPE(MPI_INT32_T,               int32_t);
65 CREATE_MPI_DATATYPE(MPI_INT64_T,               int64_t);
66 CREATE_MPI_DATATYPE(MPI_UINT8_T,               uint8_t);
67 CREATE_MPI_DATATYPE(MPI_UINT16_T,              uint16_t);
68 CREATE_MPI_DATATYPE(MPI_UINT32_T,              uint32_t);
69 CREATE_MPI_DATATYPE(MPI_UINT64_T,              uint64_t);
70 CREATE_MPI_DATATYPE(MPI_C_FLOAT_COMPLEX,       float _Complex);
71 CREATE_MPI_DATATYPE(MPI_C_DOUBLE_COMPLEX,      double _Complex);
72 CREATE_MPI_DATATYPE(MPI_C_LONG_DOUBLE_COMPLEX, long double _Complex);
73 CREATE_MPI_DATATYPE(MPI_AINT,                  MPI_Aint);
74 CREATE_MPI_DATATYPE(MPI_OFFSET,                MPI_Offset);
75
76 CREATE_MPI_DATATYPE(MPI_FLOAT_INT,             float_int);
77 CREATE_MPI_DATATYPE(MPI_LONG_INT,              long_int);
78 CREATE_MPI_DATATYPE(MPI_DOUBLE_INT,            double_int);
79 CREATE_MPI_DATATYPE(MPI_SHORT_INT,             short_int);
80 CREATE_MPI_DATATYPE(MPI_2INT,                  int_int);
81 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT,       long_double_int);
82
83
84 size_t smpi_datatype_size(MPI_Datatype datatype) {
85   return datatype->size;
86 }
87
88 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype) {
89   return datatype->lb;
90 }
91
92 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype) {
93   return datatype->ub;
94 }
95
96 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint* lb, MPI_Aint * extent) {
97   int retval;
98
99   if((datatype->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
100     retval = MPI_ERR_TYPE;
101   } else {
102     *lb =  datatype->lb;
103     *extent =  datatype->ub - datatype->lb;
104     retval = MPI_SUCCESS;
105   }
106   return MPI_SUCCESS;
107 }
108
109 int smpi_datatype_copy(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype) {
110   int retval, count;
111
112   /* First check if we really have something to do */
113   if(recvcount == 0) {
114     retval = sendcount == 0 ? MPI_SUCCESS : MPI_ERR_TRUNCATE;
115   } else {
116      /* FIXME: treat packed cases */
117      sendcount *= smpi_datatype_size(sendtype);
118      recvcount *= smpi_datatype_size(recvtype);
119      count = sendcount < recvcount ? sendcount : recvcount;
120      memcpy(recvbuf, sendbuf, count);
121      retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
122   }
123   return retval;
124 }
125
126 typedef struct s_smpi_mpi_op {
127   MPI_User_function* func;
128 } s_smpi_mpi_op_t;
129
130 #define MAX_OP(a, b)  (b) = (a) < (b) ? (b) : (a)
131 #define MIN_OP(a, b)  (b) = (a) < (b) ? (a) : (b)
132 #define SUM_OP(a, b)  (b) += (a)
133 #define PROD_OP(a, b) (b) *= (a)
134 #define LAND_OP(a, b) (b) = (a) && (b)
135 #define LOR_OP(a, b)  (b) = (a) || (b)
136 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
137 #define BAND_OP(a, b) (b) &= (a)
138 #define BOR_OP(a, b)  (b) |= (a)
139 #define BXOR_OP(a, b) (b) ^= (a)
140 #define MAXLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (b) : (a)
141 #define MINLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (a) : (b)
142 //TODO : MINLOC & MAXLOC
143
144 #define APPLY_FUNC(a, b, length, type, func) \
145   {                                          \
146     int i;                                   \
147     type* x = (type*)(a);                    \
148     type* y = (type*)(b);                    \
149     for(i = 0; i < *(length); i++) {         \
150       func(x[i], y[i]);                      \
151     }                                        \
152   }
153
154 static void max_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
155   if(*datatype == MPI_CHAR) {
156     APPLY_FUNC(a, b, length, char, MAX_OP);
157   } else if(*datatype == MPI_SHORT) {
158     APPLY_FUNC(a, b, length, short, MAX_OP);
159   } else if(*datatype == MPI_INT) {
160     APPLY_FUNC(a, b, length, int, MAX_OP);
161   } else if(*datatype == MPI_LONG) {
162     APPLY_FUNC(a, b, length, long, MAX_OP);
163   } else if(*datatype == MPI_UNSIGNED_SHORT) {
164     APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
165   } else if(*datatype == MPI_UNSIGNED) {
166     APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
167   } else if(*datatype == MPI_UNSIGNED_LONG) {
168     APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
169   } else if(*datatype == MPI_FLOAT) {
170     APPLY_FUNC(a, b, length, float, MAX_OP);
171   } else if(*datatype == MPI_DOUBLE) {
172     APPLY_FUNC(a, b, length, double, MAX_OP);
173   } else if(*datatype == MPI_LONG_DOUBLE) {
174     APPLY_FUNC(a, b, length, long double, MAX_OP);
175   }
176 }
177
178 static void min_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
179   if(*datatype == MPI_CHAR) {
180     APPLY_FUNC(a, b, length, char, MIN_OP);
181   } else if(*datatype == MPI_SHORT) {
182     APPLY_FUNC(a, b, length, short, MIN_OP);
183   } else if(*datatype == MPI_INT) {
184     APPLY_FUNC(a, b, length, int, MIN_OP);
185   } else if(*datatype == MPI_LONG) {
186     APPLY_FUNC(a, b, length, long, MIN_OP);
187   } else if(*datatype == MPI_UNSIGNED_SHORT) {
188     APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
189   } else if(*datatype == MPI_UNSIGNED) {
190     APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
191   } else if(*datatype == MPI_UNSIGNED_LONG) {
192     APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
193   } else if(*datatype == MPI_FLOAT) {
194     APPLY_FUNC(a, b, length, float, MIN_OP);
195   } else if(*datatype == MPI_DOUBLE) {
196     APPLY_FUNC(a, b, length, double, MIN_OP);
197   } else if(*datatype == MPI_LONG_DOUBLE) {
198     APPLY_FUNC(a, b, length, long double, MIN_OP);
199   }
200 }
201
202 static void sum_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
203   if(*datatype == MPI_CHAR) {
204     APPLY_FUNC(a, b, length, char, SUM_OP);
205   } else if(*datatype == MPI_SHORT) {
206     APPLY_FUNC(a, b, length, short, SUM_OP);
207   } else if(*datatype == MPI_INT) {
208     APPLY_FUNC(a, b, length, int, SUM_OP);
209   } else if(*datatype == MPI_LONG) {
210     APPLY_FUNC(a, b, length, long, SUM_OP);
211   } else if(*datatype == MPI_UNSIGNED_SHORT) {
212     APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
213   } else if(*datatype == MPI_UNSIGNED) {
214     APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
215   } else if(*datatype == MPI_UNSIGNED_LONG) {
216     APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
217   } else if(*datatype == MPI_FLOAT) {
218     APPLY_FUNC(a, b, length, float, SUM_OP);
219   } else if(*datatype == MPI_DOUBLE) {
220     APPLY_FUNC(a, b, length, double, SUM_OP);
221   } else if(*datatype == MPI_LONG_DOUBLE) {
222     APPLY_FUNC(a, b, length, long double, SUM_OP);
223   } else if(*datatype == MPI_C_FLOAT_COMPLEX) {
224     APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
225   } else if(*datatype == MPI_C_DOUBLE_COMPLEX) {
226     APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
227   } else if(*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
228     APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
229   }
230 }
231
232 static void prod_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
233   if(*datatype == MPI_CHAR) {
234     APPLY_FUNC(a, b, length, char, PROD_OP);
235   } else if(*datatype == MPI_SHORT) {
236     APPLY_FUNC(a, b, length, short, PROD_OP);
237   } else if(*datatype == MPI_INT) {
238     APPLY_FUNC(a, b, length, int, PROD_OP);
239   } else if(*datatype == MPI_LONG) {
240     APPLY_FUNC(a, b, length, long, PROD_OP);
241   } else if(*datatype == MPI_UNSIGNED_SHORT) {
242     APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
243   } else if(*datatype == MPI_UNSIGNED) {
244     APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
245   } else if(*datatype == MPI_UNSIGNED_LONG) {
246     APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
247   } else if(*datatype == MPI_FLOAT) {
248     APPLY_FUNC(a, b, length, float, PROD_OP);
249   } else if(*datatype == MPI_DOUBLE) {
250     APPLY_FUNC(a, b, length, double, PROD_OP);
251   } else if(*datatype == MPI_LONG_DOUBLE) {
252     APPLY_FUNC(a, b, length, long double, PROD_OP);
253   } else if(*datatype == MPI_C_FLOAT_COMPLEX) {
254     APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
255   } else if(*datatype == MPI_C_DOUBLE_COMPLEX) {
256      APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
257   } else if(*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
258     APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
259   }
260 }
261
262 static void land_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
263   if(*datatype == MPI_CHAR) {
264     APPLY_FUNC(a, b, length, char, LAND_OP);
265   } else if(*datatype == MPI_SHORT) {
266     APPLY_FUNC(a, b, length, short, LAND_OP);
267   } else if(*datatype == MPI_INT) {
268     APPLY_FUNC(a, b, length, int, LAND_OP);
269   } else if(*datatype == MPI_LONG) {
270     APPLY_FUNC(a, b, length, long, LAND_OP);
271   } else if(*datatype == MPI_UNSIGNED_SHORT) {
272     APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
273   } else if(*datatype == MPI_UNSIGNED) {
274     APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
275   } else if(*datatype == MPI_UNSIGNED_LONG) {
276     APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
277   } else if(*datatype == MPI_C_BOOL) {
278     APPLY_FUNC(a, b, length, _Bool, LAND_OP);
279   }
280 }
281
282 static void lor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
283   if(*datatype == MPI_CHAR) {
284     APPLY_FUNC(a, b, length, char, LOR_OP);
285   } else if(*datatype == MPI_SHORT) {
286     APPLY_FUNC(a, b, length, short, LOR_OP);
287   } else if(*datatype == MPI_INT) {
288     APPLY_FUNC(a, b, length, int, LOR_OP);
289   } else if(*datatype == MPI_LONG) {
290     APPLY_FUNC(a, b, length, long, LOR_OP);
291   } else if(*datatype == MPI_UNSIGNED_SHORT) {
292     APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
293   } else if(*datatype == MPI_UNSIGNED) {
294     APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
295   } else if(*datatype == MPI_UNSIGNED_LONG) {
296     APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
297   } else if(*datatype == MPI_C_BOOL) {
298     APPLY_FUNC(a, b, length, _Bool, LOR_OP);
299   }
300 }
301
302 static void lxor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
303   if(*datatype == MPI_CHAR) {
304     APPLY_FUNC(a, b, length, char, LXOR_OP);
305   } else if(*datatype == MPI_SHORT) {
306     APPLY_FUNC(a, b, length, short, LXOR_OP);
307   } else if(*datatype == MPI_INT) {
308     APPLY_FUNC(a, b, length, int, LXOR_OP);
309   } else if(*datatype == MPI_LONG) {
310     APPLY_FUNC(a, b, length, long, LXOR_OP);
311   } else if(*datatype == MPI_UNSIGNED_SHORT) {
312     APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
313   } else if(*datatype == MPI_UNSIGNED) {
314     APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
315   } else if(*datatype == MPI_UNSIGNED_LONG) {
316     APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
317   } else if(*datatype == MPI_C_BOOL) {
318     APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
319   }
320 }
321
322 static void band_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
323   if(*datatype == MPI_CHAR) {
324     APPLY_FUNC(a, b, length, char, BAND_OP);
325   } if(*datatype == MPI_SHORT) {
326     APPLY_FUNC(a, b, length, short, BAND_OP);
327   } else if(*datatype == MPI_INT) {
328     APPLY_FUNC(a, b, length, int, BAND_OP);
329   } else if(*datatype == MPI_LONG) {
330     APPLY_FUNC(a, b, length, long, BAND_OP);
331   } else if(*datatype == MPI_UNSIGNED_SHORT) {
332     APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
333   } else if(*datatype == MPI_UNSIGNED) {
334     APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
335   } else if(*datatype == MPI_UNSIGNED_LONG) {
336     APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
337   } else if(*datatype == MPI_BYTE) {
338     APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
339   }
340 }
341
342 static void bor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
343   if(*datatype == MPI_CHAR) {
344     APPLY_FUNC(a, b, length, char, BOR_OP);
345   } else if(*datatype == MPI_SHORT) {
346     APPLY_FUNC(a, b, length, short, BOR_OP);
347   } else if(*datatype == MPI_INT) {
348     APPLY_FUNC(a, b, length, int, BOR_OP);
349   } else if(*datatype == MPI_LONG) {
350     APPLY_FUNC(a, b, length, long, BOR_OP);
351   } else if(*datatype == MPI_UNSIGNED_SHORT) {
352     APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
353   } else if(*datatype == MPI_UNSIGNED) {
354     APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
355   } else if(*datatype == MPI_UNSIGNED_LONG) {
356     APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
357   } else if(*datatype == MPI_BYTE) {
358     APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
359   }
360 }
361
362 static void bxor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
363   if(*datatype == MPI_CHAR) {
364     APPLY_FUNC(a, b, length, char, BXOR_OP);
365   } else if(*datatype == MPI_SHORT) {
366     APPLY_FUNC(a, b, length, short, BXOR_OP);
367   } else if(*datatype == MPI_INT) {
368     APPLY_FUNC(a, b, length, int, BXOR_OP);
369   } else if(*datatype == MPI_LONG) {
370     APPLY_FUNC(a, b, length, long, BXOR_OP);
371   } else if(*datatype == MPI_UNSIGNED_SHORT) {
372     APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
373   } else if(*datatype == MPI_UNSIGNED) {
374     APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
375   } else if(*datatype == MPI_UNSIGNED_LONG) {
376     APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
377   } else if(*datatype == MPI_BYTE) {
378     APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
379   }
380 }
381
382 static void minloc_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
383   if(*datatype == MPI_FLOAT_INT) {
384     APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
385   } else if(*datatype == MPI_LONG_INT) {
386     APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
387   } else if(*datatype == MPI_DOUBLE_INT) {
388     APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
389   } else if(*datatype == MPI_SHORT_INT) {
390     APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
391   } else if(*datatype == MPI_2INT) {
392     APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
393   } else if(*datatype == MPI_LONG_DOUBLE_INT) {
394     APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
395   }
396 }
397
398 static void maxloc_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
399   if(*datatype == MPI_FLOAT_INT) {
400     APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
401   } else if(*datatype == MPI_LONG_INT) {
402     APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
403   } else if(*datatype == MPI_DOUBLE_INT) {
404     APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
405   } else if(*datatype == MPI_SHORT_INT) {
406     APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
407   } else if(*datatype == MPI_2INT) {
408     APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
409   } else if(*datatype == MPI_LONG_DOUBLE_INT) {
410     APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
411   }
412 }
413
414
415 #define CREATE_MPI_OP(name, func)                             \
416   static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
417   MPI_Op name = &mpi_##name;
418
419 CREATE_MPI_OP(MPI_MAX,     max_func);
420 CREATE_MPI_OP(MPI_MIN,     min_func);
421 CREATE_MPI_OP(MPI_SUM,     sum_func);
422 CREATE_MPI_OP(MPI_PROD,    prod_func);
423 CREATE_MPI_OP(MPI_LAND,    land_func);
424 CREATE_MPI_OP(MPI_LOR,     lor_func);
425 CREATE_MPI_OP(MPI_LXOR,    lxor_func);
426 CREATE_MPI_OP(MPI_BAND,    band_func);
427 CREATE_MPI_OP(MPI_BOR,     bor_func);
428 CREATE_MPI_OP(MPI_BXOR,    bxor_func);
429 CREATE_MPI_OP(MPI_MAXLOC,  maxloc_func);
430 CREATE_MPI_OP(MPI_MINLOC,  minloc_func);
431
432 MPI_Op smpi_op_new(MPI_User_function* function, int commute) {
433   MPI_Op op;
434
435   //FIXME: add commute param
436   op = xbt_new(s_smpi_mpi_op_t, 1);
437   op->func = function;
438   return op;
439 }
440
441 void smpi_op_destroy(MPI_Op op) {
442   xbt_free(op);
443 }
444
445 void smpi_op_apply(MPI_Op op, void* invec, void* inoutvec, int* len, MPI_Datatype* datatype) {
446   op->func(invec, inoutvec, len, datatype);
447 }