Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add support for various MPI_Type functions, to handle creation of new MPI types
[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 {
39   float value;
40   int index;
41 } float_int;
42 typedef struct {
43   long value;
44   int index;
45 } long_int;
46 typedef struct {
47   double value;
48   int index;
49 } double_int;
50 typedef struct {
51   short value;
52   int index;
53 } short_int;
54 typedef struct {
55   int value;
56   int index;
57 } int_int;
58 typedef struct {
59   long double value;
60   int index;
61 } long_double_int;
62
63 // Predefined data types
64 CREATE_MPI_DATATYPE(MPI_CHAR, char);
65 CREATE_MPI_DATATYPE(MPI_SHORT, short);
66 CREATE_MPI_DATATYPE(MPI_INT, int);
67 CREATE_MPI_DATATYPE(MPI_LONG, long);
68 CREATE_MPI_DATATYPE(MPI_LONG_LONG, long long);
69 CREATE_MPI_DATATYPE(MPI_SIGNED_CHAR, signed char);
70 CREATE_MPI_DATATYPE(MPI_UNSIGNED_CHAR, unsigned char);
71 CREATE_MPI_DATATYPE(MPI_UNSIGNED_SHORT, unsigned short);
72 CREATE_MPI_DATATYPE(MPI_UNSIGNED, unsigned int);
73 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG, unsigned long);
74 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG, unsigned long long);
75 CREATE_MPI_DATATYPE(MPI_FLOAT, float);
76 CREATE_MPI_DATATYPE(MPI_DOUBLE, double);
77 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE, long double);
78 CREATE_MPI_DATATYPE(MPI_WCHAR, wchar_t);
79 CREATE_MPI_DATATYPE(MPI_C_BOOL, _Bool);
80 CREATE_MPI_DATATYPE(MPI_INT8_T, int8_t);
81 CREATE_MPI_DATATYPE(MPI_INT16_T, int16_t);
82 CREATE_MPI_DATATYPE(MPI_INT32_T, int32_t);
83 CREATE_MPI_DATATYPE(MPI_INT64_T, int64_t);
84 CREATE_MPI_DATATYPE(MPI_UINT8_T, uint8_t);
85 CREATE_MPI_DATATYPE(MPI_UINT16_T, uint16_t);
86 CREATE_MPI_DATATYPE(MPI_UINT32_T, uint32_t);
87 CREATE_MPI_DATATYPE(MPI_UINT64_T, uint64_t);
88 CREATE_MPI_DATATYPE(MPI_C_FLOAT_COMPLEX, float _Complex);
89 CREATE_MPI_DATATYPE(MPI_C_DOUBLE_COMPLEX, double _Complex);
90 CREATE_MPI_DATATYPE(MPI_C_LONG_DOUBLE_COMPLEX, long double _Complex);
91 CREATE_MPI_DATATYPE(MPI_AINT, MPI_Aint);
92 CREATE_MPI_DATATYPE(MPI_OFFSET, MPI_Offset);
93
94 CREATE_MPI_DATATYPE(MPI_FLOAT_INT, float_int);
95 CREATE_MPI_DATATYPE(MPI_LONG_INT, long_int);
96 CREATE_MPI_DATATYPE(MPI_DOUBLE_INT, double_int);
97 CREATE_MPI_DATATYPE(MPI_SHORT_INT, short_int);
98 CREATE_MPI_DATATYPE(MPI_2INT, int_int);
99 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int);
100
101 // Internal use only
102 CREATE_MPI_DATATYPE(MPI_PTR, void*);
103
104
105 size_t smpi_datatype_size(MPI_Datatype datatype)
106 {
107   return datatype->size;
108 }
109
110 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype)
111 {
112   return datatype->lb;
113 }
114
115 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype)
116 {
117   return datatype->ub;
118 }
119
120 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
121                          MPI_Aint * extent)
122 {
123   int retval;
124
125   if ((datatype->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
126     retval = MPI_ERR_TYPE;
127   } else {
128     *lb = datatype->lb;
129     *extent = datatype->ub - datatype->lb;
130     retval = MPI_SUCCESS;
131   }
132   return retval;
133 }
134
135 int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype,
136                        void *recvbuf, int recvcount, MPI_Datatype recvtype)
137 {
138   int retval, count;
139
140   /* First check if we really have something to do */
141   if (recvcount == 0) {
142     retval = sendcount == 0 ? MPI_SUCCESS : MPI_ERR_TRUNCATE;
143   } else {
144     /* FIXME: treat packed cases */
145     sendcount *= smpi_datatype_size(sendtype);
146     recvcount *= smpi_datatype_size(recvtype);
147     count = sendcount < recvcount ? sendcount : recvcount;
148     memcpy(recvbuf, sendbuf, count);
149     retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
150   }
151   return retval;
152 }
153
154 void smpi_datatype_create(MPI_Datatype* new_type, int size, int flags){
155   MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1);
156   new_t->size=size;
157   new_t->lb=0;
158   new_t->ub=size;
159   new_t->flags=flags;
160   *new_type = new_t;
161 }
162
163 void smpi_datatype_free(MPI_Datatype* type){
164   xbt_free(*type);
165 }
166
167 int smpi_datatype_contiguous(int count, MPI_Datatype old_type, MPI_Datatype* new_type)
168 {
169   int retval;
170   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
171      retval = MPI_ERR_TYPE;
172   } else {
173     smpi_datatype_create(new_type, count * smpi_datatype_size(old_type), DT_FLAG_CONTIGUOUS);
174     retval=MPI_SUCCESS;
175   }
176   return retval;
177 }
178
179 int smpi_datatype_vector(int count, int blocklen, int stride, MPI_Datatype old_type, MPI_Datatype* new_type)
180 {
181   int retval;
182   if (blocklen<=0)return MPI_ERR_ARG;
183   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
184      retval = MPI_ERR_TYPE;
185   } else {
186     smpi_datatype_create(new_type, count * (blocklen+stride) * smpi_datatype_size(old_type), DT_FLAG_VECTOR);
187     retval=MPI_SUCCESS;
188   }
189   return retval;
190 }
191
192 int smpi_datatype_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type)
193 {
194   int retval;
195   if (blocklen<=0)return MPI_ERR_ARG;
196   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
197      retval = MPI_ERR_TYPE;
198   } else {
199     smpi_datatype_create(new_type, count * ((blocklen * smpi_datatype_size(old_type))+stride), DT_FLAG_VECTOR);
200     retval=MPI_SUCCESS;
201   }
202   return retval;
203 }
204
205
206 int smpi_datatype_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
207 {
208   int i;
209   int retval;
210   for(i=0; i< count; i++){
211     if   (blocklens[i]<=0)
212       return MPI_ERR_ARG;
213   }
214   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
215      retval = MPI_ERR_TYPE;
216   } else {
217     smpi_datatype_create(new_type,  (blocklens[count-1] + indices[count-1]) * smpi_datatype_size(old_type), DT_FLAG_DATA);
218     retval=MPI_SUCCESS;
219   }
220   return retval;
221 }
222
223 int smpi_datatype_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
224 {
225   int i;
226   int retval;
227   for(i=0; i< count; i++){
228     if   (blocklens[i]<=0)
229       return MPI_ERR_ARG;
230   }
231   if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
232      retval = MPI_ERR_TYPE;
233   } else {
234     smpi_datatype_create(new_type,indices[count-1] + (blocklens[count-1]  * smpi_datatype_size(old_type)), DT_FLAG_DATA);
235     retval=MPI_SUCCESS;
236   }
237   return retval;
238 }
239
240 int smpi_datatype_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type)
241 {
242   int i;
243   for(i=0; i< count; i++){
244     if (blocklens[i]<=0)
245       return MPI_ERR_ARG;
246     if ((old_types[i]->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED)
247       return MPI_ERR_TYPE;
248   }
249   smpi_datatype_create(new_type,indices[count-1] + (blocklens[count-1]  * smpi_datatype_size(old_types[count-1])), DT_FLAG_DATA);
250   return MPI_SUCCESS;
251 }
252
253 void smpi_datatype_commit(MPI_Datatype* datatype)
254 {
255   (*datatype)->flags= ( (*datatype)->flags | DT_FLAG_COMMITED);
256 }
257
258 typedef struct s_smpi_mpi_op {
259   MPI_User_function *func;
260 } s_smpi_mpi_op_t;
261
262 #define MAX_OP(a, b)  (b) = (a) < (b) ? (b) : (a)
263 #define MIN_OP(a, b)  (b) = (a) < (b) ? (a) : (b)
264 #define SUM_OP(a, b)  (b) += (a)
265 #define PROD_OP(a, b) (b) *= (a)
266 #define LAND_OP(a, b) (b) = (a) && (b)
267 #define LOR_OP(a, b)  (b) = (a) || (b)
268 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
269 #define BAND_OP(a, b) (b) &= (a)
270 #define BOR_OP(a, b)  (b) |= (a)
271 #define BXOR_OP(a, b) (b) ^= (a)
272 #define MAXLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (b) : (a)
273 #define MINLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (a) : (b)
274 //TODO : MINLOC & MAXLOC
275
276 #define APPLY_FUNC(a, b, length, type, func) \
277   {                                          \
278     int i;                                   \
279     type* x = (type*)(a);                    \
280     type* y = (type*)(b);                    \
281     for(i = 0; i < *(length); i++) {         \
282       func(x[i], y[i]);                      \
283     }                                        \
284   }
285
286 static void max_func(void *a, void *b, int *length,
287                      MPI_Datatype * datatype)
288 {
289   if (*datatype == MPI_CHAR) {
290     APPLY_FUNC(a, b, length, char, MAX_OP);
291   } else if (*datatype == MPI_SHORT) {
292     APPLY_FUNC(a, b, length, short, MAX_OP);
293   } else if (*datatype == MPI_INT) {
294     APPLY_FUNC(a, b, length, int, MAX_OP);
295   } else if (*datatype == MPI_LONG) {
296     APPLY_FUNC(a, b, length, long, MAX_OP);
297   } else if (*datatype == MPI_UNSIGNED_SHORT) {
298     APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
299   } else if (*datatype == MPI_UNSIGNED) {
300     APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
301   } else if (*datatype == MPI_UNSIGNED_LONG) {
302     APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
303   } else if (*datatype == MPI_FLOAT) {
304     APPLY_FUNC(a, b, length, float, MAX_OP);
305   } else if (*datatype == MPI_DOUBLE) {
306     APPLY_FUNC(a, b, length, double, MAX_OP);
307   } else if (*datatype == MPI_LONG_DOUBLE) {
308     APPLY_FUNC(a, b, length, long double, MAX_OP);
309   }
310 }
311
312 static void min_func(void *a, void *b, int *length,
313                      MPI_Datatype * datatype)
314 {
315   if (*datatype == MPI_CHAR) {
316     APPLY_FUNC(a, b, length, char, MIN_OP);
317   } else if (*datatype == MPI_SHORT) {
318     APPLY_FUNC(a, b, length, short, MIN_OP);
319   } else if (*datatype == MPI_INT) {
320     APPLY_FUNC(a, b, length, int, MIN_OP);
321   } else if (*datatype == MPI_LONG) {
322     APPLY_FUNC(a, b, length, long, MIN_OP);
323   } else if (*datatype == MPI_UNSIGNED_SHORT) {
324     APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
325   } else if (*datatype == MPI_UNSIGNED) {
326     APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
327   } else if (*datatype == MPI_UNSIGNED_LONG) {
328     APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
329   } else if (*datatype == MPI_FLOAT) {
330     APPLY_FUNC(a, b, length, float, MIN_OP);
331   } else if (*datatype == MPI_DOUBLE) {
332     APPLY_FUNC(a, b, length, double, MIN_OP);
333   } else if (*datatype == MPI_LONG_DOUBLE) {
334     APPLY_FUNC(a, b, length, long double, MIN_OP);
335   }
336 }
337
338 static void sum_func(void *a, void *b, int *length,
339                      MPI_Datatype * datatype)
340 {
341   if (*datatype == MPI_CHAR) {
342     APPLY_FUNC(a, b, length, char, SUM_OP);
343   } else if (*datatype == MPI_SHORT) {
344     APPLY_FUNC(a, b, length, short, SUM_OP);
345   } else if (*datatype == MPI_INT) {
346     APPLY_FUNC(a, b, length, int, SUM_OP);
347   } else if (*datatype == MPI_LONG) {
348     APPLY_FUNC(a, b, length, long, SUM_OP);
349   } else if (*datatype == MPI_UNSIGNED_SHORT) {
350     APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
351   } else if (*datatype == MPI_UNSIGNED) {
352     APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
353   } else if (*datatype == MPI_UNSIGNED_LONG) {
354     APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
355   } else if (*datatype == MPI_FLOAT) {
356     APPLY_FUNC(a, b, length, float, SUM_OP);
357   } else if (*datatype == MPI_DOUBLE) {
358     APPLY_FUNC(a, b, length, double, SUM_OP);
359   } else if (*datatype == MPI_LONG_DOUBLE) {
360     APPLY_FUNC(a, b, length, long double, SUM_OP);
361   } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
362     APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
363   } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
364     APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
365   } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
366     APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
367   }
368 }
369
370 static void prod_func(void *a, void *b, int *length,
371                       MPI_Datatype * datatype)
372 {
373   if (*datatype == MPI_CHAR) {
374     APPLY_FUNC(a, b, length, char, PROD_OP);
375   } else if (*datatype == MPI_SHORT) {
376     APPLY_FUNC(a, b, length, short, PROD_OP);
377   } else if (*datatype == MPI_INT) {
378     APPLY_FUNC(a, b, length, int, PROD_OP);
379   } else if (*datatype == MPI_LONG) {
380     APPLY_FUNC(a, b, length, long, PROD_OP);
381   } else if (*datatype == MPI_UNSIGNED_SHORT) {
382     APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
383   } else if (*datatype == MPI_UNSIGNED) {
384     APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
385   } else if (*datatype == MPI_UNSIGNED_LONG) {
386     APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
387   } else if (*datatype == MPI_FLOAT) {
388     APPLY_FUNC(a, b, length, float, PROD_OP);
389   } else if (*datatype == MPI_DOUBLE) {
390     APPLY_FUNC(a, b, length, double, PROD_OP);
391   } else if (*datatype == MPI_LONG_DOUBLE) {
392     APPLY_FUNC(a, b, length, long double, PROD_OP);
393   } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
394     APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
395   } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
396     APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
397   } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
398     APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
399   }
400 }
401
402 static void land_func(void *a, void *b, int *length,
403                       MPI_Datatype * datatype)
404 {
405   if (*datatype == MPI_CHAR) {
406     APPLY_FUNC(a, b, length, char, LAND_OP);
407   } else if (*datatype == MPI_SHORT) {
408     APPLY_FUNC(a, b, length, short, LAND_OP);
409   } else if (*datatype == MPI_INT) {
410     APPLY_FUNC(a, b, length, int, LAND_OP);
411   } else if (*datatype == MPI_LONG) {
412     APPLY_FUNC(a, b, length, long, LAND_OP);
413   } else if (*datatype == MPI_UNSIGNED_SHORT) {
414     APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
415   } else if (*datatype == MPI_UNSIGNED) {
416     APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
417   } else if (*datatype == MPI_UNSIGNED_LONG) {
418     APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
419   } else if (*datatype == MPI_C_BOOL) {
420     APPLY_FUNC(a, b, length, _Bool, LAND_OP);
421   }
422 }
423
424 static void lor_func(void *a, void *b, int *length,
425                      MPI_Datatype * datatype)
426 {
427   if (*datatype == MPI_CHAR) {
428     APPLY_FUNC(a, b, length, char, LOR_OP);
429   } else if (*datatype == MPI_SHORT) {
430     APPLY_FUNC(a, b, length, short, LOR_OP);
431   } else if (*datatype == MPI_INT) {
432     APPLY_FUNC(a, b, length, int, LOR_OP);
433   } else if (*datatype == MPI_LONG) {
434     APPLY_FUNC(a, b, length, long, LOR_OP);
435   } else if (*datatype == MPI_UNSIGNED_SHORT) {
436     APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
437   } else if (*datatype == MPI_UNSIGNED) {
438     APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
439   } else if (*datatype == MPI_UNSIGNED_LONG) {
440     APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
441   } else if (*datatype == MPI_C_BOOL) {
442     APPLY_FUNC(a, b, length, _Bool, LOR_OP);
443   }
444 }
445
446 static void lxor_func(void *a, void *b, int *length,
447                       MPI_Datatype * datatype)
448 {
449   if (*datatype == MPI_CHAR) {
450     APPLY_FUNC(a, b, length, char, LXOR_OP);
451   } else if (*datatype == MPI_SHORT) {
452     APPLY_FUNC(a, b, length, short, LXOR_OP);
453   } else if (*datatype == MPI_INT) {
454     APPLY_FUNC(a, b, length, int, LXOR_OP);
455   } else if (*datatype == MPI_LONG) {
456     APPLY_FUNC(a, b, length, long, LXOR_OP);
457   } else if (*datatype == MPI_UNSIGNED_SHORT) {
458     APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
459   } else if (*datatype == MPI_UNSIGNED) {
460     APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
461   } else if (*datatype == MPI_UNSIGNED_LONG) {
462     APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
463   } else if (*datatype == MPI_C_BOOL) {
464     APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
465   }
466 }
467
468 static void band_func(void *a, void *b, int *length,
469                       MPI_Datatype * datatype)
470 {
471   if (*datatype == MPI_CHAR) {
472     APPLY_FUNC(a, b, length, char, BAND_OP);
473   }
474   if (*datatype == MPI_SHORT) {
475     APPLY_FUNC(a, b, length, short, BAND_OP);
476   } else if (*datatype == MPI_INT) {
477     APPLY_FUNC(a, b, length, int, BAND_OP);
478   } else if (*datatype == MPI_LONG) {
479     APPLY_FUNC(a, b, length, long, BAND_OP);
480   } else if (*datatype == MPI_UNSIGNED_SHORT) {
481     APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
482   } else if (*datatype == MPI_UNSIGNED) {
483     APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
484   } else if (*datatype == MPI_UNSIGNED_LONG) {
485     APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
486   } else if (*datatype == MPI_BYTE) {
487     APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
488   }
489 }
490
491 static void bor_func(void *a, void *b, int *length,
492                      MPI_Datatype * datatype)
493 {
494   if (*datatype == MPI_CHAR) {
495     APPLY_FUNC(a, b, length, char, BOR_OP);
496   } else if (*datatype == MPI_SHORT) {
497     APPLY_FUNC(a, b, length, short, BOR_OP);
498   } else if (*datatype == MPI_INT) {
499     APPLY_FUNC(a, b, length, int, BOR_OP);
500   } else if (*datatype == MPI_LONG) {
501     APPLY_FUNC(a, b, length, long, BOR_OP);
502   } else if (*datatype == MPI_UNSIGNED_SHORT) {
503     APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
504   } else if (*datatype == MPI_UNSIGNED) {
505     APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
506   } else if (*datatype == MPI_UNSIGNED_LONG) {
507     APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
508   } else if (*datatype == MPI_BYTE) {
509     APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
510   }
511 }
512
513 static void bxor_func(void *a, void *b, int *length,
514                       MPI_Datatype * datatype)
515 {
516   if (*datatype == MPI_CHAR) {
517     APPLY_FUNC(a, b, length, char, BXOR_OP);
518   } else if (*datatype == MPI_SHORT) {
519     APPLY_FUNC(a, b, length, short, BXOR_OP);
520   } else if (*datatype == MPI_INT) {
521     APPLY_FUNC(a, b, length, int, BXOR_OP);
522   } else if (*datatype == MPI_LONG) {
523     APPLY_FUNC(a, b, length, long, BXOR_OP);
524   } else if (*datatype == MPI_UNSIGNED_SHORT) {
525     APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
526   } else if (*datatype == MPI_UNSIGNED) {
527     APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
528   } else if (*datatype == MPI_UNSIGNED_LONG) {
529     APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
530   } else if (*datatype == MPI_BYTE) {
531     APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
532   }
533 }
534
535 static void minloc_func(void *a, void *b, int *length,
536                         MPI_Datatype * datatype)
537 {
538   if (*datatype == MPI_FLOAT_INT) {
539     APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
540   } else if (*datatype == MPI_LONG_INT) {
541     APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
542   } else if (*datatype == MPI_DOUBLE_INT) {
543     APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
544   } else if (*datatype == MPI_SHORT_INT) {
545     APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
546   } else if (*datatype == MPI_2INT) {
547     APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
548   } else if (*datatype == MPI_LONG_DOUBLE_INT) {
549     APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
550   }
551 }
552
553 static void maxloc_func(void *a, void *b, int *length,
554                         MPI_Datatype * datatype)
555 {
556   if (*datatype == MPI_FLOAT_INT) {
557     APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
558   } else if (*datatype == MPI_LONG_INT) {
559     APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
560   } else if (*datatype == MPI_DOUBLE_INT) {
561     APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
562   } else if (*datatype == MPI_SHORT_INT) {
563     APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
564   } else if (*datatype == MPI_2INT) {
565     APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
566   } else if (*datatype == MPI_LONG_DOUBLE_INT) {
567     APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
568   }
569 }
570
571
572 #define CREATE_MPI_OP(name, func)                             \
573   static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
574   MPI_Op name = &mpi_##name;
575
576 CREATE_MPI_OP(MPI_MAX, max_func);
577 CREATE_MPI_OP(MPI_MIN, min_func);
578 CREATE_MPI_OP(MPI_SUM, sum_func);
579 CREATE_MPI_OP(MPI_PROD, prod_func);
580 CREATE_MPI_OP(MPI_LAND, land_func);
581 CREATE_MPI_OP(MPI_LOR, lor_func);
582 CREATE_MPI_OP(MPI_LXOR, lxor_func);
583 CREATE_MPI_OP(MPI_BAND, band_func);
584 CREATE_MPI_OP(MPI_BOR, bor_func);
585 CREATE_MPI_OP(MPI_BXOR, bxor_func);
586 CREATE_MPI_OP(MPI_MAXLOC, maxloc_func);
587 CREATE_MPI_OP(MPI_MINLOC, minloc_func);
588
589 MPI_Op smpi_op_new(MPI_User_function * function, int commute)
590 {
591   MPI_Op op;
592
593   //FIXME: add commute param
594   op = xbt_new(s_smpi_mpi_op_t, 1);
595   op->func = function;
596   return op;
597 }
598
599 void smpi_op_destroy(MPI_Op op)
600 {
601   xbt_free(op);
602 }
603
604 void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len,
605                    MPI_Datatype * datatype)
606 {
607   op->func(invec, inoutvec, len, datatype);
608 }