Logo AND Algorithmique Numérique Distribuée

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