Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Added MPI_CHAR to predefined reduce operations (not in the standard, but convenient...
[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 if(sendtype == recvtype) {
116     /* If same datatypes used, just copy. */
117    count = sendcount < recvcount ? sendcount : recvcount;
118    memcpy(recvbuf, sendbuf, smpi_datatype_size(sendtype) * count);
119    retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
120  } else {
121    /* FIXME:  cases
122     * - If receive packed.
123     * - If send packed
124     * to be treated once we have the MPI_Pack things ...
125     **/
126    retval = MPI_SUCCESS;
127  }
128  return retval;
129 }
130
131 typedef struct s_smpi_mpi_op {
132   MPI_User_function* func;
133 } s_smpi_mpi_op_t;
134
135 #define MAX_OP(a, b)  (b) = (a) < (b) ? (b) : (a)
136 #define MIN_OP(a, b)  (b) = (a) < (b) ? (a) : (b)
137 #define SUM_OP(a, b)  (b) += (a)
138 #define PROD_OP(a, b) (b) *= (a)
139 #define LAND_OP(a, b) (b) = (a) && (b)
140 #define LOR_OP(a, b)  (b) = (a) || (b)
141 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
142 #define BAND_OP(a, b) (b) &= (a)
143 #define BOR_OP(a, b)  (b) |= (a)
144 #define BXOR_OP(a, b) (b) ^= (a)
145 #define MAXLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (b) : (a)
146 #define MINLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (a) : (b)
147 //TODO : MINLOC & MAXLOC
148
149 #define APPLY_FUNC(a, b, length, type, func) \
150   {                                          \
151     int i;                                   \
152     type* x = (type*)(a);                    \
153     type* y = (type*)(b);                    \
154     for(i = 0; i < *(length); i++) {         \
155       func(x[i], y[i]);                      \
156     }                                        \
157   }
158
159 static void max_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
160   if(*datatype == MPI_CHAR) {
161     APPLY_FUNC(a, b, length, char, MAX_OP);
162   } else if(*datatype == MPI_SHORT) {
163     APPLY_FUNC(a, b, length, short, MAX_OP);
164   } else if(*datatype == MPI_INT) {
165     APPLY_FUNC(a, b, length, int, MAX_OP);
166   } else if(*datatype == MPI_LONG) {
167     APPLY_FUNC(a, b, length, long, MAX_OP);
168   } else if(*datatype == MPI_UNSIGNED_SHORT) {
169     APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
170   } else if(*datatype == MPI_UNSIGNED) {
171     APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
172   } else if(*datatype == MPI_UNSIGNED_LONG) {
173     APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
174   } else if(*datatype == MPI_FLOAT) {
175     APPLY_FUNC(a, b, length, float, MAX_OP);
176   } else if(*datatype == MPI_DOUBLE) {
177     APPLY_FUNC(a, b, length, double, MAX_OP);
178   } else if(*datatype == MPI_LONG_DOUBLE) {
179     APPLY_FUNC(a, b, length, long double, MAX_OP);
180   }
181 }
182
183 static void min_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
184   if(*datatype == MPI_CHAR) {
185     APPLY_FUNC(a, b, length, char, MIN_OP);
186   } else if(*datatype == MPI_SHORT) {
187     APPLY_FUNC(a, b, length, short, MIN_OP);
188   } else if(*datatype == MPI_INT) {
189     APPLY_FUNC(a, b, length, int, MIN_OP);
190   } else if(*datatype == MPI_LONG) {
191     APPLY_FUNC(a, b, length, long, MIN_OP);
192   } else if(*datatype == MPI_UNSIGNED_SHORT) {
193     APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
194   } else if(*datatype == MPI_UNSIGNED) {
195     APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
196   } else if(*datatype == MPI_UNSIGNED_LONG) {
197     APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
198   } else if(*datatype == MPI_FLOAT) {
199     APPLY_FUNC(a, b, length, float, MIN_OP);
200   } else if(*datatype == MPI_DOUBLE) {
201     APPLY_FUNC(a, b, length, double, MIN_OP);
202   } else if(*datatype == MPI_LONG_DOUBLE) {
203     APPLY_FUNC(a, b, length, long double, MIN_OP);
204   }
205 }
206
207 static void sum_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
208   if(*datatype == MPI_CHAR) {
209     APPLY_FUNC(a, b, length, char, SUM_OP);
210   } else if(*datatype == MPI_SHORT) {
211     APPLY_FUNC(a, b, length, short, SUM_OP);
212   } else if(*datatype == MPI_INT) {
213     APPLY_FUNC(a, b, length, int, SUM_OP);
214   } else if(*datatype == MPI_LONG) {
215     APPLY_FUNC(a, b, length, long, SUM_OP);
216   } else if(*datatype == MPI_UNSIGNED_SHORT) {
217     APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
218   } else if(*datatype == MPI_UNSIGNED) {
219     APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
220   } else if(*datatype == MPI_UNSIGNED_LONG) {
221     APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
222   } else if(*datatype == MPI_FLOAT) {
223     APPLY_FUNC(a, b, length, float, SUM_OP);
224   } else if(*datatype == MPI_DOUBLE) {
225     APPLY_FUNC(a, b, length, double, SUM_OP);
226   } else if(*datatype == MPI_LONG_DOUBLE) {
227     APPLY_FUNC(a, b, length, long double, SUM_OP);
228   } else if(*datatype == MPI_C_FLOAT_COMPLEX) {
229     APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
230   } else if(*datatype == MPI_C_DOUBLE_COMPLEX) {
231     APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
232   } else if(*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
233     APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
234   }
235 }
236
237 static void prod_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
238   if(*datatype == MPI_CHAR) {
239     APPLY_FUNC(a, b, length, char, PROD_OP);
240   } else if(*datatype == MPI_SHORT) {
241     APPLY_FUNC(a, b, length, short, PROD_OP);
242   } else if(*datatype == MPI_INT) {
243     APPLY_FUNC(a, b, length, int, PROD_OP);
244   } else if(*datatype == MPI_LONG) {
245     APPLY_FUNC(a, b, length, long, PROD_OP);
246   } else if(*datatype == MPI_UNSIGNED_SHORT) {
247     APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
248   } else if(*datatype == MPI_UNSIGNED) {
249     APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
250   } else if(*datatype == MPI_UNSIGNED_LONG) {
251     APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
252   } else if(*datatype == MPI_FLOAT) {
253     APPLY_FUNC(a, b, length, float, PROD_OP);
254   } else if(*datatype == MPI_DOUBLE) {
255     APPLY_FUNC(a, b, length, double, PROD_OP);
256   } else if(*datatype == MPI_LONG_DOUBLE) {
257     APPLY_FUNC(a, b, length, long double, PROD_OP);
258   } else if(*datatype == MPI_C_FLOAT_COMPLEX) {
259     APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
260   } else if(*datatype == MPI_C_DOUBLE_COMPLEX) {
261      APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
262   } else if(*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
263     APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
264   }
265 }
266
267 static void land_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
268   if(*datatype == MPI_CHAR) {
269     APPLY_FUNC(a, b, length, char, LAND_OP);
270   } else if(*datatype == MPI_SHORT) {
271     APPLY_FUNC(a, b, length, short, LAND_OP);
272   } else if(*datatype == MPI_INT) {
273     APPLY_FUNC(a, b, length, int, LAND_OP);
274   } else if(*datatype == MPI_LONG) {
275     APPLY_FUNC(a, b, length, long, LAND_OP);
276   } else if(*datatype == MPI_UNSIGNED_SHORT) {
277     APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
278   } else if(*datatype == MPI_UNSIGNED) {
279     APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
280   } else if(*datatype == MPI_UNSIGNED_LONG) {
281     APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
282   } else if(*datatype == MPI_C_BOOL) {
283     APPLY_FUNC(a, b, length, _Bool, LAND_OP);
284   }
285 }
286
287 static void lor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
288   if(*datatype == MPI_CHAR) {
289     APPLY_FUNC(a, b, length, char, LOR_OP);
290   } else if(*datatype == MPI_SHORT) {
291     APPLY_FUNC(a, b, length, short, LOR_OP);
292   } else if(*datatype == MPI_INT) {
293     APPLY_FUNC(a, b, length, int, LOR_OP);
294   } else if(*datatype == MPI_LONG) {
295     APPLY_FUNC(a, b, length, long, LOR_OP);
296   } else if(*datatype == MPI_UNSIGNED_SHORT) {
297     APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
298   } else if(*datatype == MPI_UNSIGNED) {
299     APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
300   } else if(*datatype == MPI_UNSIGNED_LONG) {
301     APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
302   } else if(*datatype == MPI_C_BOOL) {
303     APPLY_FUNC(a, b, length, _Bool, LOR_OP);
304   }
305 }
306
307 static void lxor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
308   if(*datatype == MPI_CHAR) {
309     APPLY_FUNC(a, b, length, char, LXOR_OP);
310   } else if(*datatype == MPI_SHORT) {
311     APPLY_FUNC(a, b, length, short, LXOR_OP);
312   } else if(*datatype == MPI_INT) {
313     APPLY_FUNC(a, b, length, int, LXOR_OP);
314   } else if(*datatype == MPI_LONG) {
315     APPLY_FUNC(a, b, length, long, LXOR_OP);
316   } else if(*datatype == MPI_UNSIGNED_SHORT) {
317     APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
318   } else if(*datatype == MPI_UNSIGNED) {
319     APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
320   } else if(*datatype == MPI_UNSIGNED_LONG) {
321     APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
322   } else if(*datatype == MPI_C_BOOL) {
323     APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
324   }
325 }
326
327 static void band_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
328   if(*datatype == MPI_CHAR) {
329     APPLY_FUNC(a, b, length, char, BAND_OP);
330   } if(*datatype == MPI_SHORT) {
331     APPLY_FUNC(a, b, length, short, BAND_OP);
332   } else if(*datatype == MPI_INT) {
333     APPLY_FUNC(a, b, length, int, BAND_OP);
334   } else if(*datatype == MPI_LONG) {
335     APPLY_FUNC(a, b, length, long, BAND_OP);
336   } else if(*datatype == MPI_UNSIGNED_SHORT) {
337     APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
338   } else if(*datatype == MPI_UNSIGNED) {
339     APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
340   } else if(*datatype == MPI_UNSIGNED_LONG) {
341     APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
342   } else if(*datatype == MPI_BYTE) {
343     APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
344   }
345 }
346
347 static void bor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
348   if(*datatype == MPI_CHAR) {
349     APPLY_FUNC(a, b, length, char, BOR_OP);
350   } else if(*datatype == MPI_SHORT) {
351     APPLY_FUNC(a, b, length, short, BOR_OP);
352   } else if(*datatype == MPI_INT) {
353     APPLY_FUNC(a, b, length, int, BOR_OP);
354   } else if(*datatype == MPI_LONG) {
355     APPLY_FUNC(a, b, length, long, BOR_OP);
356   } else if(*datatype == MPI_UNSIGNED_SHORT) {
357     APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
358   } else if(*datatype == MPI_UNSIGNED) {
359     APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
360   } else if(*datatype == MPI_UNSIGNED_LONG) {
361     APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
362   } else if(*datatype == MPI_BYTE) {
363     APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
364   }
365 }
366
367 static void bxor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
368   if(*datatype == MPI_CHAR) {
369     APPLY_FUNC(a, b, length, char, BXOR_OP);
370   } else if(*datatype == MPI_SHORT) {
371     APPLY_FUNC(a, b, length, short, BXOR_OP);
372   } else if(*datatype == MPI_INT) {
373     APPLY_FUNC(a, b, length, int, BXOR_OP);
374   } else if(*datatype == MPI_LONG) {
375     APPLY_FUNC(a, b, length, long, BXOR_OP);
376   } else if(*datatype == MPI_UNSIGNED_SHORT) {
377     APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
378   } else if(*datatype == MPI_UNSIGNED) {
379     APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
380   } else if(*datatype == MPI_UNSIGNED_LONG) {
381     APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
382   } else if(*datatype == MPI_BYTE) {
383     APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
384   }
385 }
386
387 static void minloc_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
388   if(*datatype == MPI_FLOAT_INT) {
389     APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
390   } else if(*datatype == MPI_LONG_INT) {
391     APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
392   } else if(*datatype == MPI_DOUBLE_INT) {
393     APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
394   } else if(*datatype == MPI_SHORT_INT) {
395     APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
396   } else if(*datatype == MPI_2INT) {
397     APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
398   } else if(*datatype == MPI_LONG_DOUBLE_INT) {
399     APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
400   }
401 }
402
403 static void maxloc_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
404   if(*datatype == MPI_FLOAT_INT) {
405     APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
406   } else if(*datatype == MPI_LONG_INT) {
407     APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
408   } else if(*datatype == MPI_DOUBLE_INT) {
409     APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
410   } else if(*datatype == MPI_SHORT_INT) {
411     APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
412   } else if(*datatype == MPI_2INT) {
413     APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
414   } else if(*datatype == MPI_LONG_DOUBLE_INT) {
415     APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
416   }
417 }
418
419
420 #define CREATE_MPI_OP(name, func)                             \
421   static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
422   MPI_Op name = &mpi_##name;
423
424 CREATE_MPI_OP(MPI_MAX,     max_func);
425 CREATE_MPI_OP(MPI_MIN,     min_func);
426 CREATE_MPI_OP(MPI_SUM,     sum_func);
427 CREATE_MPI_OP(MPI_PROD,    prod_func);
428 CREATE_MPI_OP(MPI_LAND,    land_func);
429 CREATE_MPI_OP(MPI_LOR,     lor_func);
430 CREATE_MPI_OP(MPI_LXOR,    lxor_func);
431 CREATE_MPI_OP(MPI_BAND,    band_func);
432 CREATE_MPI_OP(MPI_BOR,     bor_func);
433 CREATE_MPI_OP(MPI_BXOR,    bxor_func);
434 CREATE_MPI_OP(MPI_MAXLOC,  maxloc_func);
435 CREATE_MPI_OP(MPI_MINLOC,  minloc_func);
436
437 MPI_Op smpi_op_new(MPI_User_function* function, int commute) {
438   MPI_Op op;
439
440   //FIXME: add commute param
441   op = xbt_new(s_smpi_mpi_op_t, 1);
442   op->func = function;
443   return op;
444 }
445
446 void smpi_op_destroy(MPI_Op op) {
447   xbt_free(op);
448 }
449
450 void smpi_op_apply(MPI_Op op, void* invec, void* inoutvec, int* len, MPI_Datatype* datatype) {
451   op->func(invec, inoutvec, len, datatype);
452 }