HClib  0.3
Documentation for Habanero-C Library API
 All Data Structures Functions Typedefs Enumerations Groups
accumulator.c
1 /* Copyright (c) 2013, Rice University
2 
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions are
5 met:
6 
7 1. Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9 2. Redistributions in binary form must reproduce the above
10  copyright notice, this list of conditions and the following
11  disclaimer in the documentation and/or other materials provided
12  with the distribution.
13 3. Neither the name of Rice University
14  nor the names of its contributors may be used to endorse or
15  promote products derived from this software without specific
16  prior written permission.
17 
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30  */
31 
32 #include "rt-accumulator.h"
33 #include "ddf.h"
34 #include "runtime-hclib.h"
35 
36 #include <stdlib.h>
37 #include <assert.h>
38 #include <stdio.h>
39 
40 //
41 // Data-structure Types Implementation
42 //
43 
44  typedef struct accum_short_t {
45  accum_impl_t impl;
46  short result;
47  void (*open)(struct accum_short_t * accum, short init);
48  void (*put)(struct accum_short_t * accum, short v);
49  short (*get)(struct accum_short_t * accum);
50  void (*op)(short * res, short cur, short new);
51  } accum_short_t;
52 
53 void accum_op_short_max(short * res, short cur, short new) {
54  if(new > cur) {
55  *res = new;
56  }
57 }
58 
59 void accum_op_short_min(short * res, short cur, short new) {
60  if(new < cur) {
61  *res = new;
62  }
63 }
64 
65 void accum_op_short_plus(short * res, short cur, short new) {
66  *res = cur + new;
67 }
68 
69 void accum_op_short_prod(short * res, short cur, short new) {
70  *res = cur * new;
71 }
72 
73 void accum_op_short_land(short * res, short cur, short new) {
74  *res = cur && new;
75 }
76 
77 void accum_op_short_band(short * res, short cur, short new) {
78  *res = cur & new;
79 }
80 
81 void accum_op_short_lor(short * res, short cur, short new) {
82  *res = cur || new;
83 }
84 
85 void accum_op_short_bor(short * res, short cur, short new) {
86  *res = cur | new;
87 }
88 
89 void accum_op_short_lxor(short * res, short cur, short new) {
90  *res = !cur != !new;
91 }
92 
93 void accum_op_short_bxor(short * res, short cur, short new) {
94  *res = cur ^ new;
95 }
96 
97  typedef struct accum_int_t {
98  accum_impl_t impl;
99  int result;
100  void (*open)(struct accum_int_t * accum, int init);
101  void (*put)(struct accum_int_t * accum, int v);
102  int (*get)(struct accum_int_t * accum);
103  void (*op)(int * res, int cur, int new);
104  } accum_int_t;
105 
106 void accum_op_int_max(int * res, int cur, int new) {
107  if(new > cur) {
108  *res = new;
109  }
110 }
111 
112 void accum_op_int_min(int * res, int cur, int new) {
113  if(new < cur) {
114  *res = new;
115  }
116 }
117 
118 void accum_op_int_plus(int * res, int cur, int new) {
119  *res = cur + new;
120 }
121 
122 void accum_op_int_prod(int * res, int cur, int new) {
123  *res = cur * new;
124 }
125 
126 void accum_op_int_land(int * res, int cur, int new) {
127  *res = cur && new;
128 }
129 
130 void accum_op_int_band(int * res, int cur, int new) {
131  *res = cur & new;
132 }
133 
134 void accum_op_int_lor(int * res, int cur, int new) {
135  *res = cur || new;
136 }
137 
138 void accum_op_int_bor(int * res, int cur, int new) {
139  *res = cur | new;
140 }
141 
142 void accum_op_int_lxor(int * res, int cur, int new) {
143  *res = !cur != !new;
144 }
145 
146 void accum_op_int_bxor(int * res, int cur, int new) {
147  *res = cur ^ new;
148 }
149 
150  typedef struct accum_long_t {
151  accum_impl_t impl;
152  long result;
153  void (*open)(struct accum_long_t * accum, long init);
154  void (*put)(struct accum_long_t * accum, long v);
155  long (*get)(struct accum_long_t * accum);
156  void (*op)(long * res, long cur, long new);
157  } accum_long_t;
158 
159 void accum_op_long_max(long * res, long cur, long new) {
160  if(new > cur) {
161  *res = new;
162  }
163 }
164 
165 void accum_op_long_min(long * res, long cur, long new) {
166  if(new < cur) {
167  *res = new;
168  }
169 }
170 
171 void accum_op_long_plus(long * res, long cur, long new) {
172  *res = cur + new;
173 }
174 
175 void accum_op_long_prod(long * res, long cur, long new) {
176  *res = cur * new;
177 }
178 
179 void accum_op_long_land(long * res, long cur, long new) {
180  *res = cur && new;
181 }
182 
183 void accum_op_long_band(long * res, long cur, long new) {
184  *res = cur & new;
185 }
186 
187 void accum_op_long_lor(long * res, long cur, long new) {
188  *res = cur || new;
189 }
190 
191 void accum_op_long_bor(long * res, long cur, long new) {
192  *res = cur | new;
193 }
194 
195 void accum_op_long_lxor(long * res, long cur, long new) {
196  *res = !cur != !new;
197 }
198 
199 void accum_op_long_bxor(long * res, long cur, long new) {
200  *res = cur ^ new;
201 }
202 
203  typedef struct accum_float_t {
204  accum_impl_t impl;
205  float result;
206  void (*open)(struct accum_float_t * accum, float init);
207  void (*put)(struct accum_float_t * accum, float v);
208  float (*get)(struct accum_float_t * accum);
209  void (*op)(float * res, float cur, float new);
210  } accum_float_t;
211 
212 void accum_op_float_max(float * res, float cur, float new) {
213  if(new > cur) {
214  *res = new;
215  }
216 }
217 
218 void accum_op_float_min(float * res, float cur, float new) {
219  if(new < cur) {
220  *res = new;
221  }
222 }
223 
224 void accum_op_float_plus(float * res, float cur, float new) {
225  *res = cur + new;
226 }
227 
228 void accum_op_float_prod(float * res, float cur, float new) {
229  *res = cur * new;
230 }
231 
232  typedef struct accum_double_t {
233  accum_impl_t impl;
234  double result;
235  void (*open)(struct accum_double_t * accum, double init);
236  void (*put)(struct accum_double_t * accum, double v);
237  double (*get)(struct accum_double_t * accum);
238  void (*op)(double * res, double cur, double new);
239  } accum_double_t;
240 
241 void accum_op_double_max(double * res, double cur, double new) {
242  if(new > cur) {
243  *res = new;
244  }
245 }
246 
247 void accum_op_double_min(double * res, double cur, double new) {
248  if(new < cur) {
249  *res = new;
250  }
251 }
252 
253 void accum_op_double_plus(double * res, double cur, double new) {
254  *res = cur + new;
255 }
256 
257 void accum_op_double_prod(double * res, double cur, double new) {
258  *res = cur * new;
259 }
260 
261 //
262 // Lazy Implementation
263 //
264 
265 typedef struct accum_short_lazy_t {
266  accum_short_t base;
267  short * localAccums;
269 
270 
271 void accum_destroy_short_lazy(accum_impl_t * accum) {
272  free(((accum_short_lazy_t *) accum)->localAccums);
273  free(accum);
274 }
275 
276 void accum_close_short_lazy(accum_impl_t * accum) {
277  accum_short_t * accum_short = ((accum_short_t *) accum);
278  short * result = &(accum_short->result);
279  short * localAccums = ((accum_short_lazy_t *) accum)->localAccums;
280  int i = 0;
281  int nb_w = get_nb_workers();
282  // Sequential reduce of local accumulators
283  while (i < nb_w) {
284  accum_short->op(result, *result, localAccums[i]);
285  i++;
286  }
287 }
288 
289 accum_t * accum_transmit_short_lazy(accum_impl_t * accum, void * params, int properties) {
290  // No-op
291  return (accum_t *) accum;
292 }
293 
294 void accum_open_short_lazy(accum_short_t * accum, short init) {
295  accum->result = init;
296  int nb_w = get_nb_workers();
297  // Initialize local accumulators for each worker
298  accum_short_lazy_t * accum_lazy = (accum_short_lazy_t *) accum;
299  short * localAccums = malloc(sizeof(short) * nb_w);
300  int i = 0;
301  while (i < nb_w) {
302  localAccums[i] = init;
303  i++;
304  }
305  accum_lazy->localAccums = localAccums;
306 }
307 
308 void accum_put_short_lazy(accum_short_t * accum, short v) {
309  int wid = get_worker_id_hc();
310  accum_short_lazy_t * accum_lazy = (accum_short_lazy_t *) accum;
311  return accum->op(&(accum_lazy->localAccums[wid]), accum_lazy->localAccums[wid], v);
312 }
313 
314 short accum_get_short_lazy(accum_short_t * accum) {
315  return accum->result;
316 }
317 
318 typedef struct accum_int_lazy_t {
319  accum_int_t base;
320  int * localAccums;
322 
323 
324 void accum_destroy_int_lazy(accum_impl_t * accum) {
325  free(((accum_int_lazy_t *) accum)->localAccums);
326  free(accum);
327 }
328 
329 void accum_close_int_lazy(accum_impl_t * accum) {
330  accum_int_t * accum_int = ((accum_int_t *) accum);
331  int * result = &(accum_int->result);
332  int * localAccums = ((accum_int_lazy_t *) accum)->localAccums;
333  int i = 0;
334  int nb_w = get_nb_workers();
335  // Sequential reduce of local accumulators
336  while (i < nb_w) {
337  accum_int->op(result, *result, localAccums[i]);
338  i++;
339  }
340 }
341 
342 accum_t * accum_transmit_int_lazy(accum_impl_t * accum, void * params, int properties) {
343  // No-op
344  return (accum_t *) accum;
345 }
346 
347 void accum_open_int_lazy(accum_int_t * accum, int init) {
348  accum->result = init;
349  int nb_w = get_nb_workers();
350  // Initialize local accumulators for each worker
351  accum_int_lazy_t * accum_lazy = (accum_int_lazy_t *) accum;
352  int * localAccums = malloc(sizeof(int) * nb_w);
353  int i = 0;
354  while (i < nb_w) {
355  localAccums[i] = init;
356  i++;
357  }
358  accum_lazy->localAccums = localAccums;
359 }
360 
361 void accum_put_int_lazy(accum_int_t * accum, int v) {
362  int wid = get_worker_id_hc();
363  accum_int_lazy_t * accum_lazy = (accum_int_lazy_t *) accum;
364  return accum->op(&(accum_lazy->localAccums[wid]), accum_lazy->localAccums[wid], v);
365 }
366 
367 int accum_get_int_lazy(accum_int_t * accum) {
368  return accum->result;
369 }
370 
371 typedef struct accum_long_lazy_t {
372  accum_long_t base;
373  long * localAccums;
375 
376 
377 void accum_destroy_long_lazy(accum_impl_t * accum) {
378  free(((accum_long_lazy_t *) accum)->localAccums);
379  free(accum);
380 }
381 
382 void accum_close_long_lazy(accum_impl_t * accum) {
383  accum_long_t * accum_long = ((accum_long_t *) accum);
384  long * result = &(accum_long->result);
385  long * localAccums = ((accum_long_lazy_t *) accum)->localAccums;
386  int i = 0;
387  int nb_w = get_nb_workers();
388  // Sequential reduce of local accumulators
389  while (i < nb_w) {
390  accum_long->op(result, *result, localAccums[i]);
391  i++;
392  }
393 }
394 
395 accum_t * accum_transmit_long_lazy(accum_impl_t * accum, void * params, int properties) {
396  // No-op
397  return (accum_t *) accum;
398 }
399 
400 void accum_open_long_lazy(accum_long_t * accum, long init) {
401  accum->result = init;
402  int nb_w = get_nb_workers();
403  // Initialize local accumulators for each worker
404  accum_long_lazy_t * accum_lazy = (accum_long_lazy_t *) accum;
405  long * localAccums = malloc(sizeof(long) * nb_w);
406  int i = 0;
407  while (i < nb_w) {
408  localAccums[i] = init;
409  i++;
410  }
411  accum_lazy->localAccums = localAccums;
412 }
413 
414 void accum_put_long_lazy(accum_long_t * accum, long v) {
415  int wid = get_worker_id_hc();
416  accum_long_lazy_t * accum_lazy = (accum_long_lazy_t *) accum;
417  return accum->op(&(accum_lazy->localAccums[wid]), accum_lazy->localAccums[wid], v);
418 }
419 
420 long accum_get_long_lazy(accum_long_t * accum) {
421  return accum->result;
422 }
423 
424 typedef struct accum_float_lazy_t {
425  accum_float_t base;
426  float * localAccums;
428 
429 
430 void accum_destroy_float_lazy(accum_impl_t * accum) {
431  free(((accum_float_lazy_t *) accum)->localAccums);
432  free(accum);
433 }
434 
435 void accum_close_float_lazy(accum_impl_t * accum) {
436  accum_float_t * accum_float = ((accum_float_t *) accum);
437  float * result = &(accum_float->result);
438  float * localAccums = ((accum_float_lazy_t *) accum)->localAccums;
439  int i = 0;
440  int nb_w = get_nb_workers();
441  // Sequential reduce of local accumulators
442  while (i < nb_w) {
443  accum_float->op(result, *result, localAccums[i]);
444  i++;
445  }
446 }
447 
448 accum_t * accum_transmit_float_lazy(accum_impl_t * accum, void * params, int properties) {
449  // No-op
450  return (accum_t *) accum;
451 }
452 
453 void accum_open_float_lazy(accum_float_t * accum, float init) {
454  accum->result = init;
455  int nb_w = get_nb_workers();
456  // Initialize local accumulators for each worker
457  accum_float_lazy_t * accum_lazy = (accum_float_lazy_t *) accum;
458  float * localAccums = malloc(sizeof(float) * nb_w);
459  int i = 0;
460  while (i < nb_w) {
461  localAccums[i] = init;
462  i++;
463  }
464  accum_lazy->localAccums = localAccums;
465 }
466 
467 void accum_put_float_lazy(accum_float_t * accum, float v) {
468  int wid = get_worker_id_hc();
469  accum_float_lazy_t * accum_lazy = (accum_float_lazy_t *) accum;
470  return accum->op(&(accum_lazy->localAccums[wid]), accum_lazy->localAccums[wid], v);
471 }
472 
473 float accum_get_float_lazy(accum_float_t * accum) {
474  return accum->result;
475 }
476 
477 typedef struct accum_double_lazy_t {
478  accum_double_t base;
479  double * localAccums;
481 
482 
483 void accum_destroy_double_lazy(accum_impl_t * accum) {
484  free(((accum_double_lazy_t *) accum)->localAccums);
485  free(accum);
486 }
487 
488 void accum_close_double_lazy(accum_impl_t * accum) {
489  accum_double_t * accum_double = ((accum_double_t *) accum);
490  double * result = &(accum_double->result);
491  double * localAccums = ((accum_double_lazy_t *) accum)->localAccums;
492  int i = 0;
493  int nb_w = get_nb_workers();
494  // Sequential reduce of local accumulators
495  while (i < nb_w) {
496  accum_double->op(result, *result, localAccums[i]);
497  i++;
498  }
499 }
500 
501 accum_t * accum_transmit_double_lazy(accum_impl_t * accum, void * params, int properties) {
502  // No-op
503  return (accum_t *) accum;
504 }
505 
506 void accum_open_double_lazy(accum_double_t * accum, double init) {
507  accum->result = init;
508  int nb_w = get_nb_workers();
509  // Initialize local accumulators for each worker
510  accum_double_lazy_t * accum_lazy = (accum_double_lazy_t *) accum;
511  double * localAccums = malloc(sizeof(double) * nb_w);
512  int i = 0;
513  while (i < nb_w) {
514  localAccums[i] = init;
515  i++;
516  }
517  accum_lazy->localAccums = localAccums;
518 }
519 
520 void accum_put_double_lazy(accum_double_t * accum, double v) {
521  int wid = get_worker_id_hc();
522  accum_double_lazy_t * accum_lazy = (accum_double_lazy_t *) accum;
523  return accum->op(&(accum_lazy->localAccums[wid]), accum_lazy->localAccums[wid], v);
524 }
525 
526 double accum_get_double_lazy(accum_double_t * accum) {
527  return accum->result;
528 }
529 
530 //
531 // API Implementation
532 //
533 
534 accum_t * accum_create_short(accum_op_t op, accum_mode_t mode, short init) {
535  accum_short_t * accum_short = NULL;
536  if(mode == ACCUM_MODE_SEQ) {
537  assert(0);
538  // accum_short = (accum_short_t *) malloc(sizeof(accum_short_t));
539  // accum_impl_t * accum_impl = (accum_impl_t *) accum_short;
540  // accum_impl->close = accum_close_short_seq;
541  // accum_impl->transmit = accum_transmit_short_seq;
542  // accum_impl->destroy = accum_destroy_short_seq;
543  // accum_short->open = accum_open_short_seq;
544  // accum_short->get = accum_get_short_seq;
545  // accum_short->put = accum_put_short_seq;
546  } else if(mode == ACCUM_MODE_REC) {
547  assert(0);
548  // accum_short_rec_t * accum_rec = malloc(sizeof(accum_short_rec_t));
549  // //TODO parameterize degree and contributors
550  // accum_rec->degree = 2;
551  // accum_rec->children = NULL;
552  // accum_short = (accum_short_t *) accum_rec;
553  // accum_impl_t * accum_impl = (accum_impl_t *) accum_short;
554  // accum_impl->close = accum_close_short_rec;
555  // accum_impl->transmit = accum_transmit_short_rec;
556  // accum_impl->destroy = accum_destroy_short_rec;
557  // accum_short->open = accum_open_short_rec;
558  // accum_short->get = accum_get_short_rec;
559  // accum_short->put = accum_put_short_rec;
560  } else if(mode == ACCUM_MODE_LAZY) {
561  accum_short_lazy_t * accum_lazy = malloc(sizeof(accum_short_lazy_t));
562  //TODO parameterize degree and contributors
563  accum_lazy->localAccums = NULL;
564  accum_short = (accum_short_t *) accum_lazy;
565  accum_impl_t * accum_impl = (accum_impl_t *) accum_short;
566  accum_impl->close = accum_close_short_lazy;
567  accum_impl->transmit = accum_transmit_short_lazy;
568  accum_impl->destroy = accum_destroy_short_lazy;
569  accum_short->open = accum_open_short_lazy;
570  accum_short->get = accum_get_short_lazy;
571  accum_short->put = accum_put_short_lazy;
572  } else {
573  assert(0 && "error: short accumulator mode not implemented");
574  }
575 
576  switch(op) {
577  case ACCUM_OP_NONE:
578  // Used internally
579  break;
580  case ACCUM_OP_MAX:
581  accum_short->op = accum_op_short_max;
582  break;
583  case ACCUM_OP_MIN:
584  accum_short->op = accum_op_short_min;
585  break;
586  case ACCUM_OP_PLUS:
587  accum_short->op = accum_op_short_plus;
588  break;
589  case ACCUM_OP_PROD:
590  accum_short->op = accum_op_short_prod;
591  break;
592  case ACCUM_OP_LAND:
593  accum_short->op = accum_op_short_land;
594  break;
595  case ACCUM_OP_BAND:
596  accum_short->op = accum_op_short_band;
597  break;
598  case ACCUM_OP_LOR:
599  accum_short->op = accum_op_short_lor;
600  break;
601  case ACCUM_OP_BOR:
602  accum_short->op = accum_op_short_bor;
603  break;
604  case ACCUM_OP_LXOR:
605  accum_short->op = accum_op_short_lxor;
606  break;
607  case ACCUM_OP_BXOR:
608  accum_short->op = accum_op_short_bxor;
609  break;
610  default:
611  assert(0 && "error: short accumulator operation not implemented");
612  }
613 
614  // Open the accumulator
615  accum_short->open(accum_short, init);
616  return (accum_t *) accum_short;
617 }
618 
620  accum_int_t * accum_int = NULL;
621  if(mode == ACCUM_MODE_SEQ) {
622  assert(0);
623  // accum_int = (accum_int_t *) malloc(sizeof(accum_int_t));
624  // accum_impl_t * accum_impl = (accum_impl_t *) accum_int;
625  // accum_impl->close = accum_close_int_seq;
626  // accum_impl->transmit = accum_transmit_int_seq;
627  // accum_impl->destroy = accum_destroy_int_seq;
628  // accum_int->open = accum_open_int_seq;
629  // accum_int->get = accum_get_int_seq;
630  // accum_int->put = accum_put_int_seq;
631  } else if(mode == ACCUM_MODE_REC) {
632  assert(0);
633  // accum_int_rec_t * accum_rec = malloc(sizeof(accum_int_rec_t));
634  // //TODO parameterize degree and contributors
635  // accum_rec->degree = 2;
636  // accum_rec->children = NULL;
637  // accum_int = (accum_int_t *) accum_rec;
638  // accum_impl_t * accum_impl = (accum_impl_t *) accum_int;
639  // accum_impl->close = accum_close_int_rec;
640  // accum_impl->transmit = accum_transmit_int_rec;
641  // accum_impl->destroy = accum_destroy_int_rec;
642  // accum_int->open = accum_open_int_rec;
643  // accum_int->get = accum_get_int_rec;
644  // accum_int->put = accum_put_int_rec;
645  } else if(mode == ACCUM_MODE_LAZY) {
646  accum_int_lazy_t * accum_lazy = malloc(sizeof(accum_int_lazy_t));
647  //TODO parameterize degree and contributors
648  accum_lazy->localAccums = NULL;
649  accum_int = (accum_int_t *) accum_lazy;
650  accum_impl_t * accum_impl = (accum_impl_t *) accum_int;
651  accum_impl->close = accum_close_int_lazy;
652  accum_impl->transmit = accum_transmit_int_lazy;
653  accum_impl->destroy = accum_destroy_int_lazy;
654  accum_int->open = accum_open_int_lazy;
655  accum_int->get = accum_get_int_lazy;
656  accum_int->put = accum_put_int_lazy;
657  } else {
658  assert(0 && "error: int accumulator mode not implemented");
659  }
660 
661  switch(op) {
662  case ACCUM_OP_NONE:
663  // Used internally
664  break;
665  case ACCUM_OP_MAX:
666  accum_int->op = accum_op_int_max;
667  break;
668  case ACCUM_OP_MIN:
669  accum_int->op = accum_op_int_min;
670  break;
671  case ACCUM_OP_PLUS:
672  accum_int->op = accum_op_int_plus;
673  break;
674  case ACCUM_OP_PROD:
675  accum_int->op = accum_op_int_prod;
676  break;
677  case ACCUM_OP_LAND:
678  accum_int->op = accum_op_int_land;
679  break;
680  case ACCUM_OP_BAND:
681  accum_int->op = accum_op_int_band;
682  break;
683  case ACCUM_OP_LOR:
684  accum_int->op = accum_op_int_lor;
685  break;
686  case ACCUM_OP_BOR:
687  accum_int->op = accum_op_int_bor;
688  break;
689  case ACCUM_OP_LXOR:
690  accum_int->op = accum_op_int_lxor;
691  break;
692  case ACCUM_OP_BXOR:
693  accum_int->op = accum_op_int_bxor;
694  break;
695  default:
696  assert(0 && "error: int accumulator operation not implemented");
697  }
698 
699  // Open the accumulator
700  accum_int->open(accum_int, init);
701  return (accum_t *) accum_int;
702 }
703 accum_t * accum_create_long(accum_op_t op, accum_mode_t mode, long init) {
704  accum_long_t * accum_long = NULL;
705  if(mode == ACCUM_MODE_SEQ) {
706  assert(0);
707  // accum_long = (accum_long_t *) malloc(sizeof(accum_long_t));
708  // accum_impl_t * accum_impl = (accum_impl_t *) accum_long;
709  // accum_impl->close = accum_close_long_seq;
710  // accum_impl->transmit = accum_transmit_long_seq;
711  // accum_impl->destroy = accum_destroy_long_seq;
712  // accum_long->open = accum_open_long_seq;
713  // accum_long->get = accum_get_long_seq;
714  // accum_long->put = accum_put_long_seq;
715  } else if(mode == ACCUM_MODE_REC) {
716  assert(0);
717  // accum_long_rec_t * accum_rec = malloc(sizeof(accum_long_rec_t));
718  // //TODO parameterize degree and contributors
719  // accum_rec->degree = 2;
720  // accum_rec->children = NULL;
721  // accum_long = (accum_long_t *) accum_rec;
722  // accum_impl_t * accum_impl = (accum_impl_t *) accum_long;
723  // accum_impl->close = accum_close_long_rec;
724  // accum_impl->transmit = accum_transmit_long_rec;
725  // accum_impl->destroy = accum_destroy_long_rec;
726  // accum_long->open = accum_open_long_rec;
727  // accum_long->get = accum_get_long_rec;
728  // accum_long->put = accum_put_long_rec;
729  } else if(mode == ACCUM_MODE_LAZY) {
730  accum_long_lazy_t * accum_lazy = malloc(sizeof(accum_long_lazy_t));
731  //TODO parameterize degree and contributors
732  accum_lazy->localAccums = NULL;
733  accum_long = (accum_long_t *) accum_lazy;
734  accum_impl_t * accum_impl = (accum_impl_t *) accum_long;
735  accum_impl->close = accum_close_long_lazy;
736  accum_impl->transmit = accum_transmit_long_lazy;
737  accum_impl->destroy = accum_destroy_long_lazy;
738  accum_long->open = accum_open_long_lazy;
739  accum_long->get = accum_get_long_lazy;
740  accum_long->put = accum_put_long_lazy;
741  } else {
742  assert(0 && "error: long accumulator mode not implemented");
743  }
744 
745  switch(op) {
746  case ACCUM_OP_NONE:
747  // Used internally
748  break;
749  case ACCUM_OP_MAX:
750  accum_long->op = accum_op_long_max;
751  break;
752  case ACCUM_OP_MIN:
753  accum_long->op = accum_op_long_min;
754  break;
755  case ACCUM_OP_PLUS:
756  accum_long->op = accum_op_long_plus;
757  break;
758  case ACCUM_OP_PROD:
759  accum_long->op = accum_op_long_prod;
760  break;
761  case ACCUM_OP_LAND:
762  accum_long->op = accum_op_long_land;
763  break;
764  case ACCUM_OP_BAND:
765  accum_long->op = accum_op_long_band;
766  break;
767  case ACCUM_OP_LOR:
768  accum_long->op = accum_op_long_lor;
769  break;
770  case ACCUM_OP_BOR:
771  accum_long->op = accum_op_long_bor;
772  break;
773  case ACCUM_OP_LXOR:
774  accum_long->op = accum_op_long_lxor;
775  break;
776  case ACCUM_OP_BXOR:
777  accum_long->op = accum_op_long_bxor;
778  break;
779  default:
780  assert(0 && "error: long accumulator operation not implemented");
781  }
782 
783  // Open the accumulator
784  accum_long->open(accum_long, init);
785  return (accum_t *) accum_long;
786 }
787 accum_t * accum_create_float(accum_op_t op, accum_mode_t mode, float init) {
788  accum_float_t * accum_float = NULL;
789  if(mode == ACCUM_MODE_SEQ) {
790  assert(0);
791  // accum_float = (accum_float_t *) malloc(sizeof(accum_float_t));
792  // accum_impl_t * accum_impl = (accum_impl_t *) accum_float;
793  // accum_impl->close = accum_close_float_seq;
794  // accum_impl->transmit = accum_transmit_float_seq;
795  // accum_impl->destroy = accum_destroy_float_seq;
796  // accum_float->open = accum_open_float_seq;
797  // accum_float->get = accum_get_float_seq;
798  // accum_float->put = accum_put_float_seq;
799  } else if(mode == ACCUM_MODE_REC) {
800  assert(0);
801  // accum_float_rec_t * accum_rec = malloc(sizeof(accum_float_rec_t));
802  // //TODO parameterize degree and contributors
803  // accum_rec->degree = 2;
804  // accum_rec->children = NULL;
805  // accum_float = (accum_float_t *) accum_rec;
806  // accum_impl_t * accum_impl = (accum_impl_t *) accum_float;
807  // accum_impl->close = accum_close_float_rec;
808  // accum_impl->transmit = accum_transmit_float_rec;
809  // accum_impl->destroy = accum_destroy_float_rec;
810  // accum_float->open = accum_open_float_rec;
811  // accum_float->get = accum_get_float_rec;
812  // accum_float->put = accum_put_float_rec;
813  } else if(mode == ACCUM_MODE_LAZY) {
814  accum_float_lazy_t * accum_lazy = malloc(sizeof(accum_float_lazy_t));
815  //TODO parameterize degree and contributors
816  accum_lazy->localAccums = NULL;
817  accum_float = (accum_float_t *) accum_lazy;
818  accum_impl_t * accum_impl = (accum_impl_t *) accum_float;
819  accum_impl->close = accum_close_float_lazy;
820  accum_impl->transmit = accum_transmit_float_lazy;
821  accum_impl->destroy = accum_destroy_float_lazy;
822  accum_float->open = accum_open_float_lazy;
823  accum_float->get = accum_get_float_lazy;
824  accum_float->put = accum_put_float_lazy;
825  } else {
826  assert(0 && "error: float accumulator mode not implemented");
827  }
828 
829  switch(op) {
830  case ACCUM_OP_NONE:
831  // Used internally
832  break;
833  case ACCUM_OP_MAX:
834  accum_float->op = accum_op_float_max;
835  break;
836  case ACCUM_OP_MIN:
837  accum_float->op = accum_op_float_min;
838  break;
839  case ACCUM_OP_PLUS:
840  accum_float->op = accum_op_float_plus;
841  break;
842  case ACCUM_OP_PROD:
843  accum_float->op = accum_op_float_prod;
844  break;
845  default:
846  assert(0 && "error: float accumulator operation not implemented");
847  }
848 
849  // Open the accumulator
850  accum_float->open(accum_float, init);
851  return (accum_t *) accum_float;
852 }
854  accum_double_t * accum_double = NULL;
855  if(mode == ACCUM_MODE_SEQ) {
856  assert(0);
857  // accum_double = (accum_double_t *) malloc(sizeof(accum_double_t));
858  // accum_impl_t * accum_impl = (accum_impl_t *) accum_double;
859  // accum_impl->close = accum_close_double_seq;
860  // accum_impl->transmit = accum_transmit_double_seq;
861  // accum_impl->destroy = accum_destroy_double_seq;
862  // accum_double->open = accum_open_double_seq;
863  // accum_double->get = accum_get_double_seq;
864  // accum_double->put = accum_put_double_seq;
865  } else if(mode == ACCUM_MODE_REC) {
866  assert(0);
867  // accum_double_rec_t * accum_rec = malloc(sizeof(accum_double_rec_t));
868  // //TODO parameterize degree and contributors
869  // accum_rec->degree = 2;
870  // accum_rec->children = NULL;
871  // accum_double = (accum_double_t *) accum_rec;
872  // accum_impl_t * accum_impl = (accum_impl_t *) accum_double;
873  // accum_impl->close = accum_close_double_rec;
874  // accum_impl->transmit = accum_transmit_double_rec;
875  // accum_impl->destroy = accum_destroy_double_rec;
876  // accum_double->open = accum_open_double_rec;
877  // accum_double->get = accum_get_double_rec;
878  // accum_double->put = accum_put_double_rec;
879  } else if(mode == ACCUM_MODE_LAZY) {
880  accum_double_lazy_t * accum_lazy = malloc(sizeof(accum_double_lazy_t));
881  //TODO parameterize degree and contributors
882  accum_lazy->localAccums = NULL;
883  accum_double = (accum_double_t *) accum_lazy;
884  accum_impl_t * accum_impl = (accum_impl_t *) accum_double;
885  accum_impl->close = accum_close_double_lazy;
886  accum_impl->transmit = accum_transmit_double_lazy;
887  accum_impl->destroy = accum_destroy_double_lazy;
888  accum_double->open = accum_open_double_lazy;
889  accum_double->get = accum_get_double_lazy;
890  accum_double->put = accum_put_double_lazy;
891  } else {
892  assert(0 && "error: double accumulator mode not implemented");
893  }
894 
895  switch(op) {
896  case ACCUM_OP_NONE:
897  // Used internally
898  break;
899  case ACCUM_OP_MAX:
900  accum_double->op = accum_op_double_max;
901  break;
902  case ACCUM_OP_MIN:
903  accum_double->op = accum_op_double_min;
904  break;
905  case ACCUM_OP_PLUS:
906  accum_double->op = accum_op_double_plus;
907  break;
908  case ACCUM_OP_PROD:
909  accum_double->op = accum_op_double_prod;
910  break;
911  default:
912  assert(0 && "error: double accumulator operation not implemented");
913  }
914 
915  // Open the accumulator
916  accum_double->open(accum_double, init);
917  return (accum_t *) accum_double;
918 }
919 //
920 // User API Interface Implementation
921 //
922 
923 short accum_get_short(accum_t * acc) {
924  accum_short_t * acc_short = (accum_short_t *) acc;
925  return acc_short->get(acc_short);
926 }
927 
928 void accum_put_short(accum_t * acc, short v) {
929  accum_short_t * acc_short = (accum_short_t *) acc;
930  return acc_short->put(acc_short, v);
931 }
932 
933 int accum_get_int(accum_t * acc) {
934  accum_int_t * acc_int = (accum_int_t *) acc;
935  return acc_int->get(acc_int);
936 }
937 
938 void accum_put_int(accum_t * acc, int v) {
939  accum_int_t * acc_int = (accum_int_t *) acc;
940  return acc_int->put(acc_int, v);
941 }
942 
943 long accum_get_long(accum_t * acc) {
944  accum_long_t * acc_long = (accum_long_t *) acc;
945  return acc_long->get(acc_long);
946 }
947 
948 void accum_put_long(accum_t * acc, long v) {
949  accum_long_t * acc_long = (accum_long_t *) acc;
950  return acc_long->put(acc_long, v);
951 }
952 
953 float accum_get_float(accum_t * acc) {
954  accum_float_t * acc_float = (accum_float_t *) acc;
955  return acc_float->get(acc_float);
956 }
957 
958 void accum_put_float(accum_t * acc, float v) {
959  accum_float_t * acc_float = (accum_float_t *) acc;
960  return acc_float->put(acc_float, v);
961 }
962 
963 double accum_get_double(accum_t * acc) {
964  accum_double_t * acc_double = (accum_double_t *) acc;
965  return acc_double->get(acc_double);
966 }
967 
968 void accum_put_double(accum_t * acc, double v) {
969  accum_double_t * acc_double = (accum_double_t *) acc;
970  return acc_double->put(acc_double, v);
971 }
972 
973 void accum_register(accum_t ** accs, int n) {
974  int i = 0;
975  finish_t * finish = get_current_finish();
976  //TODO this goes away when we switch to static registration in start_finish
977  assert((finish->accumulators == NULL) && "error: overwritting registered accumulators");
978  accum_t ** accumulators = (accum_t **) malloc(sizeof(accum_t*) * (n+1));
979  while (i < n) {
980  accumulators[i] = accs[i];
981  i++;
982  }
983  accumulators[i] = NULL;
984  finish->accumulators = accumulators;
985 }
986 
987 void accum_destroy(accum_t * acc) {
988  accum_impl_t * acc_impl = (accum_impl_t *) acc;
989  return acc_impl->destroy(acc_impl);
990 }