1 /* reducer_opadd.h -*- C++ -*- 2 * 3 * @copyright 4 * Copyright (C) 2009-2013, Intel Corporation 5 * All rights reserved. 6 * 7 * @copyright 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * @copyright 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 30 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 33 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 /** @file reducer_opadd.h 38 * 39 * @brief Defines classes for doing parallel addition reductions. 40 * 41 * @ingroup ReducersAdd 42 * 43 * @see ReducersAdd 44 */ 45 46 #ifndef REDUCER_OPADD_H_INCLUDED 47 #define REDUCER_OPADD_H_INCLUDED 48 49 #include <cilk/reducer.h> 50 51 /** @defgroup ReducersAdd Addition Reducers 52 * 53 * Addition reducers allow the computation of the sum of a set of values in 54 * parallel. 55 * 56 * @ingroup Reducers 57 * 58 * You should be familiar with @ref pagereducers "Cilk reducers", described in 59 * file `reducers.md`, and particularly with @ref reducers_using, before trying 60 * to use the information in this file. 61 * 62 * @section redopadd_usage Usage Example 63 * 64 * cilk::reducer< cilk::op_add<int> > r; 65 * cilk_for (int i = 0; i != N; ++i) { 66 * *r += a[i]; 67 * } 68 * return r.get_value(); 69 * 70 * @section redopadd_monoid The Monoid 71 * 72 * @subsection redopadd_monoid_values Value Set 73 * 74 * The value set of an addition reducer is the set of values of `Type`, which 75 * is expected to be a builtin numeric type (or something like it, such as 76 * `std::complex`). 77 * 78 * @subsection redopadd_monoid_operator Operator 79 * 80 * The operator of an addition reducer is the addition operator, defined by 81 * the “`+`” binary operator on `Type`. 82 * 83 * @subsection redopadd_monoid_identity Identity 84 * 85 * The identity value of the reducer is the numeric value “`0`”. This is 86 * expected to be the value of the default constructor `Type()`. 87 * 88 * @section redopadd_operations Operations 89 * 90 * @subsection redopadd_constructors Constructors 91 * 92 * reducer() // identity 93 * reducer(const Type& value) 94 * reducer(move_in(Type& variable)) 95 * 96 * @subsection redopadd_get_set Set and Get 97 * 98 * r.set_value(const Type& value) 99 * const Type& = r.get_value() const 100 * r.move_in(Type& variable) 101 * r.move_out(Type& variable) 102 * 103 * @subsection redopadd_initial Initial Values 104 * 105 * If an addition reducer is constructed without an explicit initial value, 106 * then its initial value will be its identity value, as long as `Type` 107 * satisfies the requirements of @ref redopadd_types. 108 * 109 * @subsection redopadd_view_ops View Operations 110 * 111 * *r += a 112 * *r -= a 113 * ++*r 114 * --*r 115 * (*r)++ 116 * (*r)-- 117 * *r = *r + a 118 * *r = *r - a 119 * *r = *r ± a1 ± a2 … ± an 120 * 121 * The post-increment and post-decrement operations do not return a value. (If 122 * they did, they would expose the value contained in the view, which is 123 * non-deterministic in the middle of a reduction.) 124 * 125 * Note that subtraction operations are allowed on an addition reducer because 126 * subtraction is equivalent to addition with a negated operand. It is true 127 * that `(x - y) - z` is not equivalent to `x - (y - z)`, but 128 * `(x + (-y)) + (-z)` _is_ equivalent to `x + ((-y) + (-z))`. 129 * 130 * @section redopadd_floating_point Issues with Floating-Point Types 131 * 132 * Because of precision and round-off issues, floating-point addition is not 133 * really associative. For example, `(1e30 + -1e30) + 1 == 1`, but 134 * `1e30 + (-1e30 + 1) == 0`. 135 * 136 * In many cases, this won’t matter, but computations which have been 137 * carefully ordered to control round-off errors may not deal well with 138 * being reassociated. In general, you should be sure to understand the 139 * floating-point behavior of your program before doing any transformation 140 * that will reassociate its computations. 141 * 142 * @section redopadd_types Type and Operator Requirements 143 * 144 * `Type` must be `Copy Constructible`, `Default Constructible`, and 145 * `Assignable`. 146 * 147 * The operator “`+=`” must be defined on `Type`, with `x += a` having the 148 * same meaning as `x = x + a`. In addition, if the code uses the “`-=`”, 149 * pre-increment, post-increment, pre-decrement, or post-decrement operators, 150 * then the corresponding operators must be defined on `Type`. 151 * 152 * The expression `Type()` must be a valid expression which yields the 153 * identity value (the value of `Type` whose numeric value is zero). 154 * 155 * @section redopadd_in_c Addition Reducers in C 156 * 157 * The @ref CILK_C_REDUCER_OPADD and @ref CILK_C_REDUCER_OPADD_TYPE macros can 158 * be used to do addition reductions in C. For example: 159 * 160 * CILK_C_REDUCER_OPADD(r, double, 0); 161 * CILK_C_REGISTER_REDUCER(r); 162 * cilk_for(int i = 0; i != n; ++i) { 163 * REDUCER_VIEW(r) += a[i]; 164 * } 165 * CILK_C_UNREGISTER_REDUCER(r); 166 * printf("The sum of the elements of a is %f\n", REDUCER_VIEW(r)); 167 * 168 * See @ref reducers_c_predefined. 169 */ 170 171 #ifdef __cplusplus 172 173 namespace cilk { 174 175 /** The addition reducer view class. 176 * 177 * This is the view class for reducers created with 178 * `cilk::reducer< cilk::op_add<Type> >`. It holds the accumulator variable 179 * for the reduction, and allows only addition and subtraction operations to 180 * be performed on it. 181 * 182 * @note The reducer “dereference” operation (`reducer::operator *()`) 183 * yields a reference to the view. Thus, for example, the view class’s 184 * `+=` operation would be used in an expression like `*r += a`, where 185 * `r` is an op_add reducer variable. 186 * 187 * @tparam Type The type of the contained accumulator variable. This will 188 * be the value type of a monoid_with_view that is 189 * instantiated with this view. 190 * 191 * @see ReducersAdd 192 * @see op_add 193 * 194 * @ingroup ReducersAdd 195 */ 196 template <typename Type> 197 class op_add_view : public scalar_view<Type> 198 { 199 typedef scalar_view<Type> base; 200 201 public: 202 /** Class to represent the right-hand side of 203 * `*reducer = *reducer ± value`. 204 * 205 * The only assignment operator for the op_add_view class takes an 206 * rhs_proxy as its operand. This results in the syntactic restriction 207 * that the only expressions that can be assigned to an op_add_view are 208 * ones which generate an rhs_proxy — that is, expressions of the form 209 * `op_add_view ± value ... ± value`. 210 * 211 * @warning 212 * The lhs and rhs views in such an assignment must be the same; 213 * otherwise, the behavior will be undefined. (I.e., `v1 = v1 + x` is 214 * legal; `v1 = v2 + x` is illegal.) This condition will be checked with a 215 * runtime assertion when compiled in debug mode. 216 * 217 * @see op_add_view 218 */ 219 class rhs_proxy { 220 friend class op_add_view; 221 222 const op_add_view* m_view; 223 Type m_value; 224 225 // Constructor is invoked only from op_add_view::operator+() and 226 // op_add_view::operator-(). 227 // rhs_proxy(const op_add_view * view,const Type & value)228 rhs_proxy(const op_add_view* view, const Type& value) : 229 m_view(view), m_value(value) {} 230 231 rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator 232 rhs_proxy(); // Disable default constructor 233 234 public: 235 //@{ 236 /** Add or subtract an additional rhs value. If `v` is an op_add_view 237 * and `a1` is a value, then the expression `v + a1` invokes the view’s 238 * `operator+()` to create an rhs_proxy for `(v, a1)`; then 239 * `v + a1 + a2` invokes the rhs_proxy’s `operator+()` to create a new 240 * rhs_proxy for `(v, a1+a2)`. This allows the right-hand side of an 241 * assignment to be not just `view ± value`, but 242 * `view ± value ± value ... ± value`. The effect is that 243 * 244 * v = v ± a1 ± a2 ... ± an; 245 * 246 * is evaluated as 247 * 248 * v = v ± (±a1 ± a2 ... ± an); 249 */ 250 rhs_proxy& operator+(const Type& x) { m_value += x; return *this; } 251 rhs_proxy& operator-(const Type& x) { m_value -= x; return *this; } 252 //@} 253 }; 254 255 256 /** Default/identity constructor. This constructor initializes the 257 * contained value to `Type()`, which is expected to be the identity value 258 * for addition on `Type`. 259 */ op_add_view()260 op_add_view() : base() {} 261 262 /** Construct with a specified initial value. 263 */ op_add_view(const Type & v)264 explicit op_add_view(const Type& v) : base(v) {} 265 266 /** Reduction operation. 267 * 268 * This function is invoked by the @ref op_add monoid to combine the views 269 * of two strands when the right strand merges with the left one. It adds 270 * the value contained in the right-strand view to the value contained in 271 * the left-strand view, and leaves the value in the right-strand view 272 * undefined. 273 * 274 * @param right A pointer to the right-strand view. (`this` points to 275 * the left-strand view.) 276 * 277 * @note Used only by the @ref op_add monoid to implement the monoid 278 * reduce operation. 279 */ reduce(op_add_view * right)280 void reduce(op_add_view* right) { this->m_value += right->m_value; } 281 282 /** @name Accumulator variable updates. 283 * 284 * These functions support the various syntaxes for incrementing or 285 * decrementing the accumulator variable contained in the view. 286 */ 287 //@{ 288 289 /** Increment the accumulator variable by @a x. 290 */ 291 op_add_view& operator+=(const Type& x) { this->m_value += x; return *this; } 292 293 /** Decrement the accumulator variable by @a x. 294 */ 295 op_add_view& operator-=(const Type& x) { this->m_value -= x; return *this; } 296 297 /** Pre-increment. 298 */ 299 op_add_view& operator++() { ++this->m_value; return *this; } 300 301 /** Post-increment. 302 * 303 * @note Conventionally, post-increment operators return the old value 304 * of the incremented variable. However, reducer views do not 305 * expose their contained values, so `view++` does not have a 306 * return value. 307 */ 308 void operator++(int) { this->m_value++; } 309 310 /** Pre-decrement. 311 */ 312 op_add_view& operator--() { --this->m_value; return *this; } 313 314 /** Post-decrement. 315 * 316 * @note Conventionally, post-decrement operators return the old value 317 * of the decremented variable. However, reducer views do not 318 * expose their contained values, so `view--` does not have a 319 * return value. 320 */ 321 void operator--(int) { this->m_value--; } 322 323 /** Create an object representing `*this + x`. 324 * 325 * @see rhs_proxy 326 */ 327 rhs_proxy operator+(const Type& x) const { return rhs_proxy(this, x); } 328 329 /** Create an object representing `*this - x`. 330 * 331 * @see rhs_proxy 332 */ 333 rhs_proxy operator-(const Type& x) const { return rhs_proxy(this, -x); } 334 335 /** Assign the result of a `view ± value` expression to the view. Note that 336 * this is the only assignment operator for this class. 337 * 338 * @see rhs_proxy 339 */ 340 op_add_view& operator=(const rhs_proxy& rhs) { 341 __CILKRTS_ASSERT(this == rhs.m_view); 342 this->m_value += rhs.m_value; 343 return *this; 344 } 345 346 //@} 347 }; 348 349 350 /** Monoid class for addition reductions. Instantiate the cilk::reducer 351 * template class with an op_add monoid to create an addition reducer class. 352 * For example, to compute 353 * the sum of a set of `int` values: 354 * 355 * cilk::reducer< cilk::op_add<int> > r; 356 * 357 * @tparam Type The reducer value type. 358 * @tparam Align If `false` (the default), reducers instantiated on this 359 * monoid will be naturally aligned (the Cilk library 1.0 360 * behavior). If `true`, reducers instantiated on this monoid 361 * will be cache-aligned for binary compatibility with 362 * reducers in Cilk library version 0.9. 363 * 364 * @see ReducersAdd 365 * @see op_add_view 366 * 367 * @ingroup ReducersAdd 368 */ 369 template <typename Type, bool Align = false> 370 struct op_add : public monoid_with_view<op_add_view<Type>, Align> {}; 371 372 /** **Deprecated** addition reducer wrapper class. 373 * 374 * reducer_opadd is the same as @ref reducer<@ref op_add>, except that 375 * reducer_opadd is a proxy for the contained view, so that accumulator 376 * variable update operations can be applied directly to the reducer. For 377 * example, a value is added to a `reducer<%op_add>` with `*r += a`, but a 378 * value can be added to a `%reducer_opadd` with `r += a`. 379 * 380 * @deprecated Users are strongly encouraged to use `reducer<monoid>` 381 * reducers rather than the old wrappers like reducer_opadd. 382 * The `reducer<monoid>` reducers show the reducer/monoid/view 383 * architecture more clearly, are more consistent in their 384 * implementation, and present a simpler model for new 385 * user-implemented reducers. 386 * 387 * @note Implicit conversions are provided between `%reducer_opadd` 388 * and `reducer<%op_add>`. This allows incremental code 389 * conversion: old code that used `%reducer_opadd` can pass a 390 * `%reducer_opadd` to a converted function that now expects a 391 * pointer or reference to a `reducer<%op_add>`, and vice 392 * versa. 393 * 394 * @tparam Type The value type of the reducer. 395 * 396 * @see op_add 397 * @see reducer 398 * @see ReducersAdd 399 * 400 * @ingroup ReducersAdd 401 */ 402 template <typename Type> 403 class reducer_opadd : public reducer< op_add<Type, true> > 404 { 405 typedef reducer< op_add<Type, true> > base; 406 using base::view; 407 408 public: 409 /// The view type for the reducer. 410 typedef typename base::view_type view_type; 411 412 /// The view’s rhs proxy type. 413 typedef typename view_type::rhs_proxy rhs_proxy; 414 415 /// The view type for the reducer. 416 typedef view_type View; 417 418 /// The monoid type for the reducer. 419 typedef typename base::monoid_type Monoid; 420 421 /** @name Constructors 422 */ 423 //@{ 424 425 /** Default (identity) constructor. 426 * 427 * Constructs the wrapper with the default initial value of `Type()`. 428 */ reducer_opadd()429 reducer_opadd() {} 430 431 /** Value constructor. 432 * 433 * Constructs the wrapper with a specified initial value. 434 */ reducer_opadd(const Type & initial_value)435 explicit reducer_opadd(const Type& initial_value) : base(initial_value) {} 436 437 //@} 438 439 /** @name Forwarded functions 440 * @details Functions that update the contained accumulator variable are 441 * simply forwarded to the contained @ref op_add_view. */ 442 //@{ 443 444 /// @copydoc op_add_view::operator+=(const Type&) 445 reducer_opadd& operator+=(const Type& x) { view() += x; return *this; } 446 447 /// @copydoc op_add_view::operator-=(const Type&) 448 reducer_opadd& operator-=(const Type& x) { view() -= x; return *this; } 449 450 /// @copydoc op_add_view::operator++() 451 reducer_opadd& operator++() { ++view(); return *this; } 452 453 /// @copydoc op_add_view::operator++(int) 454 void operator++(int) { view()++; } 455 456 /// @copydoc op_add_view::operator-\-() 457 reducer_opadd& operator--() { --view(); return *this; } 458 459 /// @copydoc op_add_view::operator-\-(int) 460 void operator--(int) { view()--; } 461 462 // The legacy definitions of reducer_opadd::operator+() and 463 // reducer_opadd::operator-() have different behavior and a different 464 // return type than this definition. The legacy version is defined as a 465 // member function, so this new version is defined as a free function to 466 // give it a different signature, so that they won’t end up sharing a 467 // single object file entry. 468 469 /// @copydoc op_add_view::operator+(const Type&) const 470 friend rhs_proxy operator+(const reducer_opadd& r, const Type& x) 471 { 472 return r.view() + x; 473 } 474 /// @copydoc op_add_view::operator-(const Type&) const 475 friend rhs_proxy operator-(const reducer_opadd& r, const Type& x) 476 { 477 return r.view() - x; 478 } 479 /// @copydoc op_add_view::operator=(const rhs_proxy&) 480 reducer_opadd& operator=(const rhs_proxy& temp) 481 { 482 view() = temp; 483 return *this; 484 } 485 //@} 486 487 /** @name Dereference 488 * @details Dereferencing a wrapper is a no-op. It simply returns the 489 * wrapper. Combined with the rule that the wrapper forwards view 490 * operations to its contained view, this means that view operations can 491 * be written the same way on reducers and wrappers, which is convenient 492 * for incrementally converting old code using wrappers to use reducers 493 * instead. That is: 494 * 495 * reducer< op_add<int> > r; 496 * *r += a; // *r returns the view 497 * // operator += is a view member function 498 * 499 * reducer_opadd<int> w; 500 * *w += a; // *w returns the wrapper 501 * // operator += is a wrapper member function that 502 * // calls the corresponding view function 503 */ 504 //@{ 505 reducer_opadd& operator*() { return *this; } 506 reducer_opadd const& operator*() const { return *this; } 507 508 reducer_opadd* operator->() { return this; } 509 reducer_opadd const* operator->() const { return this; } 510 //@} 511 512 /** @name Upcast 513 * @details In Cilk library 0.9, reducers were always cache-aligned. In 514 * library 1.0, reducer cache alignment is optional. By default, reducers 515 * are unaligned (i.e., just naturally aligned), but legacy wrappers 516 * inherit from cache-aligned reducers for binary compatibility. 517 * 518 * This means that a wrapper will automatically be upcast to its aligned 519 * reducer base class. The following conversion operators provide 520 * pseudo-upcasts to the corresponding unaligned reducer class. 521 */ 522 //@{ 523 operator reducer< op_add<Type, false> >& () 524 { 525 return *reinterpret_cast< reducer< op_add<Type, false> >* >(this); 526 } 527 operator const reducer< op_add<Type, false> >& () const 528 { 529 return *reinterpret_cast< const reducer< op_add<Type, false> >* >(this); 530 } 531 //@} 532 }; 533 534 /// @cond internal 535 /** Metafunction specialization for reducer conversion. 536 * 537 * This specialization of the @ref legacy_reducer_downcast template class 538 * defined in reducer.h causes the `reducer< op_add<Type> >` class to have an 539 * `operator reducer_opadd<Type>& ()` conversion operator that statically 540 * downcasts the `reducer<op_add>` to the corresponding `reducer_opadd` type. 541 * (The reverse conversion, from `reducer_opadd` to `reducer<op_add>`, is just 542 * an upcast, which is provided for free by the language.) 543 * 544 * @ingroup ReducersAdd 545 */ 546 template <typename Type, bool Align> 547 struct legacy_reducer_downcast<reducer<op_add<Type, Align> > > 548 { 549 typedef reducer_opadd<Type> type; 550 }; 551 /// @endcond 552 553 } // namespace cilk 554 555 #endif // __cplusplus 556 557 558 /** @ingroup ReducersAdd 559 */ 560 //@{ 561 562 /** @name C Language Reducer Macros 563 * 564 * These macros are used to declare and work with numeric op_add reducers in 565 * C code. 566 * 567 * @see @ref page_reducers_in_c 568 */ 569 //@{ 570 571 __CILKRTS_BEGIN_EXTERN_C 572 573 /** Opadd reducer type name. 574 * 575 * This macro expands into the identifier which is the name of the op_add 576 * reducer type for a specified numeric type. 577 * 578 * @param tn The @ref reducers_c_type_names "numeric type name" specifying 579 * the type of the reducer. 580 * 581 * @see @ref reducers_c_predefined 582 * @see ReducersAdd 583 */ 584 #define CILK_C_REDUCER_OPADD_TYPE(tn) \ 585 __CILKRTS_MKIDENT(cilk_c_reducer_opadd_,tn) 586 587 /** Declare an op_add reducer object. 588 * 589 * This macro expands into a declaration of an op_add reducer object for a 590 * specified numeric type. For example: 591 * 592 * CILK_C_REDUCER_OPADD(my_reducer, double, 0.0); 593 * 594 * @param obj The variable name to be used for the declared reducer object. 595 * @param tn The @ref reducers_c_type_names "numeric type name" specifying 596 * the type of the reducer. 597 * @param v The initial value for the reducer. (A value which can be 598 * assigned to the numeric type represented by @a tn.) 599 * 600 * @see @ref reducers_c_predefined 601 * @see ReducersAdd 602 */ 603 #define CILK_C_REDUCER_OPADD(obj,tn,v) \ 604 CILK_C_REDUCER_OPADD_TYPE(tn) obj = \ 605 CILK_C_INIT_REDUCER(_Typeof(obj.value), \ 606 __CILKRTS_MKIDENT(cilk_c_reducer_opadd_reduce_,tn), \ 607 __CILKRTS_MKIDENT(cilk_c_reducer_opadd_identity_,tn), \ 608 __cilkrts_hyperobject_noop_destroy, v) 609 610 /// @cond internal 611 612 /** Declare the op_add reducer functions for a numeric type. 613 * 614 * This macro expands into external function declarations for functions which 615 * implement the reducer functionality for the op_add reducer type for a 616 * specified numeric type. 617 * 618 * @param t The value type of the reducer. 619 * @param tn The value “type name” identifier, used to construct the reducer 620 * type name, function names, etc. 621 */ 622 #define CILK_C_REDUCER_OPADD_DECLARATION(t,tn) \ 623 typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPADD_TYPE(tn); \ 624 __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opadd,tn,l,r); \ 625 __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opadd,tn); 626 627 /** Define the op_add reducer functions for a numeric type. 628 * 629 * This macro expands into function definitions for functions which implement 630 * the reducer functionality for the op_add reducer type for a specified 631 * numeric type. 632 * 633 * @param t The value type of the reducer. 634 * @param tn The value “type name” identifier, used to construct the reducer 635 * type name, function names, etc. 636 */ 637 #define CILK_C_REDUCER_OPADD_DEFINITION(t,tn) \ 638 typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPADD_TYPE(tn); \ 639 __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opadd,tn,l,r) \ 640 { *(t*)l += *(t*)r; } \ 641 __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opadd,tn) \ 642 { *(t*)v = 0; } 643 644 //@{ 645 /** @def CILK_C_REDUCER_OPADD_INSTANCE 646 * @brief Declare or define implementation functions for a reducer type. 647 * 648 * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS` 649 * will be defined, and this macro will generate reducer implementation 650 * functions. Everywhere else, `CILK_C_DEFINE_REDUCERS` will be undefined, 651 * and this macro will expand into external declarations for the functions. 652 */ 653 #ifdef CILK_C_DEFINE_REDUCERS 654 # define CILK_C_REDUCER_OPADD_INSTANCE(t,tn) \ 655 CILK_C_REDUCER_OPADD_DEFINITION(t,tn) 656 #else 657 # define CILK_C_REDUCER_OPADD_INSTANCE(t,tn) \ 658 CILK_C_REDUCER_OPADD_DECLARATION(t,tn) 659 #endif 660 //@} 661 662 /* Declare or define an instance of the reducer type and its functions for each 663 * numeric type. 664 */ 665 CILK_C_REDUCER_OPADD_INSTANCE(char, char) 666 CILK_C_REDUCER_OPADD_INSTANCE(unsigned char, uchar) 667 CILK_C_REDUCER_OPADD_INSTANCE(signed char, schar) 668 CILK_C_REDUCER_OPADD_INSTANCE(wchar_t, wchar_t) 669 CILK_C_REDUCER_OPADD_INSTANCE(short, short) 670 CILK_C_REDUCER_OPADD_INSTANCE(unsigned short, ushort) 671 CILK_C_REDUCER_OPADD_INSTANCE(int, int) 672 CILK_C_REDUCER_OPADD_INSTANCE(unsigned int, uint) 673 CILK_C_REDUCER_OPADD_INSTANCE(unsigned int, unsigned) /* alternate name */ 674 CILK_C_REDUCER_OPADD_INSTANCE(long, long) 675 CILK_C_REDUCER_OPADD_INSTANCE(unsigned long, ulong) 676 CILK_C_REDUCER_OPADD_INSTANCE(long long, longlong) 677 CILK_C_REDUCER_OPADD_INSTANCE(unsigned long long, ulonglong) 678 CILK_C_REDUCER_OPADD_INSTANCE(float, float) 679 CILK_C_REDUCER_OPADD_INSTANCE(double, double) 680 CILK_C_REDUCER_OPADD_INSTANCE(long double, longdouble) 681 682 //@endcond 683 684 __CILKRTS_END_EXTERN_C 685 686 //@} 687 688 //@} 689 690 #endif /* REDUCER_OPADD_H_INCLUDED */ 691