aboutsummaryrefslogtreecommitdiff
path: root/libcilkrts/include/cilk/reducer_opand.h
diff options
context:
space:
mode:
Diffstat (limited to 'libcilkrts/include/cilk/reducer_opand.h')
-rw-r--r--libcilkrts/include/cilk/reducer_opand.h880
1 files changed, 535 insertions, 345 deletions
diff --git a/libcilkrts/include/cilk/reducer_opand.h b/libcilkrts/include/cilk/reducer_opand.h
index 0ee7b9faf57..3b27246d0ea 100644
--- a/libcilkrts/include/cilk/reducer_opand.h
+++ b/libcilkrts/include/cilk/reducer_opand.h
@@ -1,33 +1,41 @@
-/*
- * Copyright (C) 2009-2011
- * Intel Corporation
- *
- * This file is part of the Intel Cilk Plus Library. This library is free
- * software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Under Section 7 of GPL version 3, you are granted additional
- * permissions described in the GCC Runtime Library Exception, version
- * 3.1, as published by the Free Software Foundation.
- *
- * You should have received a copy of the GNU General Public License and
- * a copy of the GCC Runtime Library Exception along with this program;
- * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- * <http://www.gnu.org/licenses/>.
+/* reducer_opand.h -*- C++ -*-
*
+ * @copyright
+ * Copyright (C) 20009-2013
+ * Intel Corporation
+ *
+ * @copyright
+ * This file is part of the Intel Cilk Plus Library. This library is free
+ * software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * @copyright
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * @copyright
+ * Under Section 7 of GPL version 3, you are granted additional
+ * permissions described in the GCC Runtime Library Exception, version
+ * 3.1, as published by the Free Software Foundation.
+ *
+ * @copyright
+ * You should have received a copy of the GNU General Public License and
+ * a copy of the GCC Runtime Library Exception along with this program;
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ * <http://www.gnu.org/licenses/>.
*/
-/*
- * reducer_opand.h
+/** @file reducer_opand.h
+ *
+ * @brief Defines classes for doing parallel bitwise and reductions.
*
- * Purpose: Reducer hyperobject to compute bitwise AND of values
+ * @ingroup ReducersAnd
+ *
+ * @see ReducersAnd
*/
#ifndef REDUCER_OPAND_H_INCLUDED
@@ -35,317 +43,475 @@
#include <cilk/reducer.h>
-#ifdef __cplusplus
-
-/* C++ Interface
- *
- * Purpose: Reducer hyperobject to compute bitwise AND values
- * When bool is passed as 'Type', it computes logical AND
- * operation.
- *
- * Classes: reducer_opand<Type>
- *
- * Description:
- * ============
- * This component provides a reducer-type hyperobject representation
- * that allows conducting bitwise AND operation to a non-local variable
- * using the &=, & operators. A common operation
- * when traversing a data structure is to bit-wise AND values
- * into a non-local numeric variable. When Cilk parallelism is
- * introduced, however, a data race will occur on the variable holding
- * the bit-wise AND result. By replacing the variable with the
- * hyperobject defined in this component, the data race is eliminated.
- *
- * When bool is passed as the 'Type', this reducer conducts logic AND
- * operation.
- *
- * Usage Example:
- * ==============
- * Assume we wish to traverse an array of objects, performing a bit-wise AND
- * operation on each object and accumulating the result of the operation
- * into an integer variable.
- *..
- * unsigned int compute(const X& v);
- *
- * int test()
- * {
- * const std::size_t ARRAY_SIZE = 1000000;
- * extern X myArray[ARRAY_SIZE];
- * // ...
- *
- * unsigned int result = 1;
- * for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
- * {
- * result &= compute(myArray[i]);
- * }
+/** @defgroup ReducersAnd Bitwise And Reducers
*
- * std::cout << "The result is: " << result << std::endl;
+ * Bitwise and reducers allow the computation of the bitwise and of a set of
+ * values in parallel.
*
- * return 0;
- * }
- *..
- * Changing the 'for' to a 'cilk_for' will cause the loop to run in parallel,
- * but doing so will create a data race on the 'result' variable.
- * The race is solved by changing 'result' to a 'reducer_opand' hyperobject:
- *..
- * unsigned int compute(const X& v);
- *
- *
- * int test()
- * {
- * const std::size_t ARRAY_SIZE = 1000000;
- * extern X myArray[ARRAY_SIZE];
- * // ...
- *
- * cilk::reducer_opand<unsigned int> result(1);
- * cilk_for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
- * {
- * *result &= compute(myArray[i]);
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file `reducers.md`, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redopand_usage Usage Example
+ *
+ * cilk::reducer< cilk::op_and<unsigned> > r;
+ * cilk_for (int i = 0; i != N; ++i) {
+ * *r &= a[i];
* }
+ * unsigned result;
+ * r.move_out(result);
*
- * std::cout << "The result is: "
- * << result.get_value() << std::endl;
+ * @section redopand_monoid The Monoid
*
- * return 0;
- * }
- *
+ * @subsection redopand_monoid_values Value Set
+ *
+ * The value set of a bitwise and reducer is the set of values of `Type`,
+ * which is expected to be a builtin integer type which has a representation
+ * as a sequence of bits (or something like it, such as `bool` or
+ * `std::bitset`).
+ *
+ * @subsection redopand_monoid_operator Operator
+ *
+ * The operator of a bitwise and reducer is the bitwise and operator, defined
+ * by the “`&`” binary operator on `Type`.
+ *
+ * @subsection redopand_monoid_identity Identity
*
- * Operations provided:
- * ====================
- * Given 'reducer_opand' objects, x and y, the following are
- * valid statements:
- *..
- * *x &= 5;
- * *x = *x & 5;
- *..
- * The following are not valid expressions and will result in a run-time error
- * in a debug build:
- *..
- * x = y; // Cannot assign one reducer to another
- * *x = *y & 5; // Mixed reducers
- * *x = 5 & *x; // operator& is not necessarily commutative
- *..
- *..
- *
- * Requirements on the 'Type' parameter
- * ====================================
- * The 'Type' parameter used to instantiate the 'reducer_opand' class must
- * provide a &= operator that meets the requirements for an
- * *associative* *mutating* *operator* as defined in the Cilk++ user manual.
- * The identity function of 'Type' in class Monoid must yield a bit-wise
- * AND identity, i.e.,
- * a value (such as true in bool) that, when AND with any other value, yields
- * the other value.
- *
- * When unsigned int or bool is passed as 'Type', the identity function of
- * Monoid returns AND identity.
+ * The identity value of the reducer is the value whose representation
+ * contains all 1-bits. This is expected to be the value of the expression
+ * `~Type()` (i.e., the bitwise negation operator applied to the default value
+ * of the value type).
+ *
+ * @section redopand_operations Operations
+ *
+ * @subsection redopand_constructors Constructors
+ *
+ * reducer() // identity
+ * reducer(const Type& value)
+ * reducer(move_in(Type& variable))
+ *
+ * @subsection redopand_get_set Set and Get
+ *
+ * r.set_value(const Type& value)
+ * const Type& = r.get_value() const
+ * r.move_in(Type& variable)
+ * r.move_out(Type& variable)
+ *
+ * @subsection redopand_initial Initial Values
+ *
+ * If a bitwise and reducer is constructed without an explicit initial value,
+ * then its initial value will be its identity value, as long as `Type`
+ * satisfies the requirements of @ref redopand_types.
+ *
+ * @subsection redopand_view_ops View Operations
+ *
+ * *r &= a
+ * *r = *r & a
+ * *r = *r & a1 & a2 … & an
+ *
+ * @section redopand_types Type and Operator Requirements
+ *
+ * `Type` must be `Copy Constructible`, `Default Constructible`, and
+ * `Assignable`.
+ *
+ * The operator “`&=`” must be defined on `Type`, with `x &= a` having the
+ * same meaning as `x = x & a`.
+ *
+ * The expression `~ Type()` must be a valid expression which yields the
+ * identity value (the value of `Type` whose representation consists of all
+ * 1-bits).
+ *
+ * @section redopand_in_c Bitwise And Reducers in C
+ *
+ * The @ref CILK_C_REDUCER_OPAND and @ref CILK_C_REDUCER_OPAND_TYPE macros can
+ * be used to do bitwise and reductions in C. For example:
+ *
+ * CILK_C_REDUCER_OPAND(r, uint, ~0);
+ * CILK_C_REGISTER_REDUCER(r);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * REDUCER_VIEW(r) &= a[i];
+ * }
+ * CILK_C_UNREGISTER_REDUCER(r);
+ * printf("The bitwise AND of the elements of a is %x\n", REDUCER_VIEW(r));
+ *
+ * See @ref reducers_c_predefined.
*/
-#include <new>
+#ifdef __cplusplus
namespace cilk {
-/**
- * @brief A reducer-type hyperobject representation that allows conducting
- * bitwise AND operation to a non-local variable using the &=, & operators.
+/** The bitwise and reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_and<Type> >`. It holds the accumulator variable
+ * for the reduction, and allows only `and` operations to be performed on it.
+ *
+ * @note The reducer “dereference” operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `&=` operation would be used in an expression like `*r &= a`, where
+ * `r` is an opmod reducer variable.
+ *
+ * @tparam Type The type of the contained accumulator variable. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
*
- * A common operation when traversing a data structure is to bit-wise AND
- * values into a non-local numeric variable. When Cilk parallelism is
- * introduced, however, a data race will occur on the variable holding
- * the bit-wise AND result. By replacing the variable with the
- * hyperobject defined in this component, the data race is eliminated.
+ * @see ReducersAnd
+ * @see op_and
+ *
+ * @ingroup ReducersAnd
*/
-
template <typename Type>
-class reducer_opand
+class op_and_view : public scalar_view<Type>
{
- public:
- /// Definition of data view, operation, and identity for reducer_opand
- class Monoid : public monoid_base<Type>
- {
- public:
- static void reduce(Type* left, Type* right);
-
- /// identity function must provide a value that,
- /// when AND with any other values, yields the other value
- void identity(Type* p) const { new ((void*) p) Type(~0); }
+ typedef scalar_view<Type> base;
+
+public:
+ /** Class to represent the right-hand side of `*reducer = *reducer & value`.
+ *
+ * The only assignment operator for the op_and_view class takes an
+ * rhs_proxy as its operand. This results in the syntactic restriction
+ * that the only expressions that can be assigned to an op_and_view are
+ * ones which generate an rhs_proxy — that is, expressions of the form
+ * `op_and_view & value ... & value`.
+ *
+ * @warning
+ * The lhs and rhs views in such an assignment must be the same;
+ * otherwise, the behavior will be undefined. (I.e., `v1 = v1 & x` is
+ * legal; `v1 = v2 & x` is illegal.) This condition will be checked with
+ * a runtime assertion when compiled in debug mode.
+ *
+ * @see op_and_view
+ */
+ class rhs_proxy {
+ private:
+ friend class op_and_view;
+
+ const op_and_view* m_view;
+ Type m_value;
+
+ // Constructor is invoked only from op_and_view::operator&().
+ //
+ rhs_proxy(const op_and_view* view, const Type& value) : m_view(view), m_value(value) {}
+
+ rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator
+ rhs_proxy(); // Disable default constructor
+
+ public:
+ /** Bitwise and with an additional rhs value. If `v` is an op_and_view
+ * and `a1` is a value, then the expression `v & a1` invokes the
+ * view’s `operator&()` to create an rhs_proxy for `(v, a1)`; then
+ * `v & a1 & a2` invokes the rhs_proxy’s `operator&()` to create a new
+ * rhs_proxy for `(v, a1&a2)`. This allows the right-hand side of an
+ * assignment to be not just `view & value`, but
+ * `view & value & value ... & value`. The effect is that
+ *
+ * v = v & a1 & a2 ... & an;
+ *
+ * is evaluated as
+ *
+ * v = v & (a1 & a2 ... & an);
+ */
+ rhs_proxy& operator&(const Type& x) { m_value &= x; return *this; }
};
- /// "PRIVATE" HELPER CLASS
- class temp_and {
- friend class reducer_opand;
-
- Type* valuePtr_;
-
- // Default copy constructor, no assignment operator
- temp_and& operator=(const temp_and&);
-
- explicit temp_and(Type* valuePtr);
-
- public:
- temp_and& operator&(const Type& x);
- };
-
- public:
-
- /// Construct an 'reducer_opand' object with a value of 'Type()'.
- reducer_opand();
-
- /// Construct an 'reducer_opand' object with the specified initial value.
- explicit reducer_opand(const Type& initial_value);
- /// Return a const reference to the current value of this object.
- ///
- /// @warning If this method is called before the parallel calculation is
- /// complete, the value returned by this method will be a partial result.
- const Type& get_value() const;
-
- /// Set the value of this object.
- ///
- /// @warning Setting the value of a reducer such that it violates the
- /// associative operation algebra will yield results that are likely to
- /// differ from serial execution and may differ from run to run.
- void set_value(const Type& value);
-
- /// AND 'x' to the value of this reducer and produce a temporary and object.
- /// The temporary and can be used for additional bit-wise operations
- /// or assigned back to this reducer.
- temp_and operator&(const Type& x) const;
-
- /// AND 'x' to the value of this object.
- reducer_opand& operator&=(const Type& x);
+ /** Default/identity constructor. This constructor initializes the
+ * contained value to `~ Type()`.
+ */
+ op_and_view() : base(~Type()) {}
+
+ /** Construct with a specified initial value.
+ */
+ explicit op_and_view(const Type& v) : base(v) {}
+
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_and monoid to combine the views
+ * of two strands when the right strand merges with the left one. It
+ * “ands” the value contained in the left-strand view with the value
+ * contained in the right-strand view, and leaves the value in the
+ * right-strand view undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_and monoid to implement the monoid
+ * reduce operation.
+ */
+ void reduce(op_and_view* right) { this->m_value &= right->m_value; }
+
+ /** @name Accumulator variable updates.
+ *
+ * These functions support the various syntaxes for “anding” the
+ * accumulator variable contained in the view with some value.
+ */
+ //@{
+
+ /** And the accumulator variable with @a x.
+ */
+ op_and_view& operator&=(const Type& x) { this->m_value &= x; return *this; }
+
+ /** Create an object representing `*this & x`.
+ *
+ * @see rhs_proxy
+ */
+ rhs_proxy operator&(const Type& x) const { return rhs_proxy(this, x); }
+
+ /** Assign the result of a `view & value` expression to the view. Note that
+ * this is the only assignment operator for this class.
+ *
+ * @see rhs_proxy
+ */
+ op_and_view& operator=(const rhs_proxy& rhs) {
+ __CILKRTS_ASSERT(this == rhs.m_view);
+ this->m_value &= rhs.m_value;
+ return *this;
+ }
+
+ //@}
+};
- /// Merge the result of AND operation into this object. The AND operation
- /// must involve this reducer, i.e., x = x + 5; not x = y + 5;
- reducer_opand& operator=(const temp_and& temp);
+/** Monoid class for bitwise and reductions. Instantiate the cilk::reducer
+ * template class with an op_and monoid to create a bitwise and reducer
+ * class. For example, to compute the bitwise and of a set of `unsigned long`
+ * values:
+ *
+ * cilk::reducer< cilk::op_and<unsigned long> > r;
+ *
+ * @tparam Type The reducer value type.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersAnd
+ * @see op_and_view
+ *
+ * @ingroup ReducersAnd
+ */
+template <typename Type, bool Align = false>
+struct op_and : public monoid_with_view<op_and_view<Type>, Align> {};
+/** Deprecated bitwise and reducer class.
+ *
+ * reducer_opand is the same as @ref reducer<@ref op_and>, except that
+ * reducer_opand is a proxy for the contained view, so that accumulator
+ * variable update operations can be applied directly to the reducer. For
+ * example, a value is anded with a `reducer<%op_and>` with `*r &= a`, but a
+ * value can be anded with a `%reducer_opand` with `r &= a`.
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_opand.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_opand`
+ * and `reducer<%op_and>`. This allows incremental code
+ * conversion: old code that used `%reducer_opand` can pass a
+ * `%reducer_opand` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_and>`, and vice
+ * versa.
+ *
+ * @tparam Type The value type of the reducer.
+ *
+ * @see op_and
+ * @see reducer
+ * @see ReducersAnd
+ *
+ * @ingroup ReducersAnd
+ */
+template <typename Type>
+class reducer_opand : public reducer< op_and<Type, true> >
+{
+ typedef reducer< op_and<Type, true> > base;
+ using base::view;
+
+public:
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view’s rhs proxy type.
+ typedef typename view_type::rhs_proxy rhs_proxy;
+
+ /// The view type for the reducer.
+ typedef view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /** Default constructor.
+ *
+ * Constructs the wrapper with the default initial value of `Type()`
+ * (not the identity value).
+ */
+ reducer_opand() : base(Type()) {}
+
+ /** Value constructor.
+ *
+ * Constructs the wrapper with a specified initial value.
+ */
+ explicit reducer_opand(const Type& initial_value) : base(initial_value) {}
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_and_view. */
+ //@{
+
+ /// @copydoc op_and_view::operator&=(const Type&)
+ reducer_opand& operator&=(const Type& x)
+ {
+ view() &= x;
+ return *this;
+ }
+
+ // The legacy definition of reducer_opand::operator&() has different
+ // behavior and a different return type than this definition. The legacy
+ // version is defined as a member function, so this new version is defined
+ // as a free function to give it a different signature, so that they won’t
+ // end up sharing a single object file entry.
+
+ /// @copydoc op_and_view::operator&(const Type&) const
+ friend rhs_proxy operator&(const reducer_opand& r, const Type& x)
+ {
+ return r.view() & x;
+ }
+
+ /// @copydoc op_and_view::operator=(const rhs_proxy&)
+ reducer_opand& operator=(const rhs_proxy& temp)
+ {
+ view() = temp;
+ return *this;
+ }
+ //@}
+
+ /** @name Dereference
+ * @details Dereferencing a wrapper is a no-op. It simply returns the
+ * wrapper. Combined with the rule that the wrapper forwards view
+ * operations to its contained view, this means that view operations can
+ * be written the same way on reducers and wrappers, which is convenient
+ * for incrementally converting old code using wrappers to use reducers
+ * instead. That is:
+ *
+ * reducer< op_and<int> > r;
+ * *r &= a; // *r returns the view
+ * // operator &= is a view member function
+ *
+ * reducer_opand<int> w;
+ * *w &= a; // *w returns the wrapper
+ * // operator &= is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
reducer_opand& operator*() { return *this; }
reducer_opand const& operator*() const { return *this; }
reducer_opand* operator->() { return this; }
reducer_opand const* operator->() const { return this; }
-
- private:
- friend class temp_and;
-
- // Hyperobject to serve up views
- reducer<Monoid> imp_;
-
- // Not copyable
- reducer_opand(const reducer_opand&);
- reducer_opand& operator=(const reducer_opand&);
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_and<Type, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_and<Type, false> >* >(this);
+ }
+ operator const reducer< op_and<Type, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_and<Type, false> >* >(this);
+ }
+ //@}
};
-/////////////////////////////////////////////////////////////////////////////
-// Implementation of inline and template functions
-/////////////////////////////////////////////////////////////////////////////
-
-// ------------------------------------
-// template class reducer_opand::Monoid
-// ------------------------------------
-
-/**
- * Combines two views of the data.
+/// @cond internal
+/** Metafunction specialization for reducer conversion.
+ *
+ * This specialization of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes the `reducer< op_and<Type> >` class to have an
+ * `operator reducer_opand<Type>& ()` conversion operator that statically
+ * downcasts the `reducer<op_and>` to the corresponding `reducer_opand` type.
+ * (The reverse conversion, from `reducer_opand` to `reducer<op_and>`, is just
+ * an upcast, which is provided for free by the language.)
+ *
+ * @ingroup ReducersAnd
*/
-template <typename Type>
-void
-reducer_opand<Type>::Monoid::reduce(Type* left, Type* right)
-{
- *left &= *right;
-}
-
-// ----------------------------
-// template class reducer_opand
-// ----------------------------
-
-template <typename Type>
-inline
-reducer_opand<Type>::reducer_opand()
- : imp_(Type())
-{
-}
-
-template <typename Type>
-inline
-reducer_opand<Type>::reducer_opand(const Type& initial_value)
- : imp_(initial_value)
-{
-}
-
-template <typename Type>
-inline
-const Type& reducer_opand<Type>::get_value() const
-{
- return imp_.view();
-}
-
-template <typename Type>
-inline
-void reducer_opand<Type>::set_value(const Type& value)
-{
- imp_.view() = value;
-}
-
-template <typename Type>
-inline
-typename reducer_opand<Type>::temp_and
-reducer_opand<Type>::operator&(const Type& x) const
-{
- Type* valuePtr = const_cast<Type*>(&imp_.view());
- *valuePtr = *valuePtr & x;
- return temp_and(valuePtr);
-}
-
-template <typename Type>
-inline
-reducer_opand<Type>& reducer_opand<Type>::operator&=(const Type& x)
-{
- imp_.view() &= x;
- return *this;
-}
-
-template <typename Type>
-inline
-reducer_opand<Type>&
-reducer_opand<Type>::operator=(
- const typename reducer_opand<Type>::temp_and& temp)
+template <typename Type, bool Align>
+struct legacy_reducer_downcast<reducer<op_and<Type, Align> > >
{
- // No-op. Just test that temp was constructed from this.
- __CILKRTS_ASSERT(&imp_.view() == temp.valuePtr_);
- return *this;
-}
-
-// --------------------------------------
-// template class reducer_opand::temp_and
-// --------------------------------------
-
-template <typename Type>
-inline
-reducer_opand<Type>::temp_and::temp_and(Type *valuePtr)
- : valuePtr_(valuePtr)
-{
-}
-
-template <typename Type>
-inline
-typename reducer_opand<Type>::temp_and&
-reducer_opand<Type>::temp_and::operator&(const Type& x)
-{
- *valuePtr_ = *valuePtr_ & x;
- return *this;
-}
+ typedef reducer_opand<Type> type;
+};
+/// @endcond
} // namespace cilk
-#endif /* __cplusplus */
+#endif // __cplusplus
+
-/* C Interface
+/** @ingroup ReducersAdd
*/
+//@{
+/** @name C language reducer macros
+ *
+ * These macros are used to declare and work with op_and reducers in C code.
+ *
+ * @see @ref page_reducers_in_c
+ */
+ //@{
+
__CILKRTS_BEGIN_EXTERN_C
+/** Opand reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the op_and
+ * reducer type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersAnd
+ */
#define CILK_C_REDUCER_OPAND_TYPE(tn) \
__CILKRTS_MKIDENT(cilk_c_reducer_opand_,tn)
+
+/** Declare an op_and reducer object.
+ *
+ * This macro expands into a declaration of an op_and reducer object for a
+ * specified numeric type. For example:
+ *
+ * CILK_C_REDUCER_OPAND(my_reducer, ulong, ~0UL);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ * @param v The initial value for the reducer. (A value which can be
+ * assigned to the numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersAnd
+ */
#define CILK_C_REDUCER_OPAND(obj,tn,v) \
CILK_C_REDUCER_OPAND_TYPE(tn) obj = \
CILK_C_INIT_REDUCER(_Typeof(obj.value), \
@@ -353,57 +519,81 @@ __CILKRTS_BEGIN_EXTERN_C
__CILKRTS_MKIDENT(cilk_c_reducer_opand_identity_,tn), \
__cilkrts_hyperobject_noop_destroy, v)
-/* Declare an instance of the reducer for a specific numeric type */
-#define CILK_C_REDUCER_OPAND_INSTANCE(t,tn) \
- typedef CILK_C_DECLARE_REDUCER(t) \
- __CILKRTS_MKIDENT(cilk_c_reducer_opand_,tn); \
+/// @cond internal
+
+/** Declare the op_and reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which
+ * implement the reducer functionality for the op_and reducer type for a
+ * specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name” identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPAND_DECLARATION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPAND_TYPE(tn); \
__CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opand,tn,l,r); \
- __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opand,tn);
-
-/* Declare an instance of the reducer type for each numeric type */
-CILK_C_REDUCER_OPAND_INSTANCE(char,char);
-CILK_C_REDUCER_OPAND_INSTANCE(unsigned char,uchar);
-CILK_C_REDUCER_OPAND_INSTANCE(signed char,schar);
-CILK_C_REDUCER_OPAND_INSTANCE(wchar_t,wchar_t);
-CILK_C_REDUCER_OPAND_INSTANCE(short,short);
-CILK_C_REDUCER_OPAND_INSTANCE(unsigned short,ushort);
-CILK_C_REDUCER_OPAND_INSTANCE(int,int);
-CILK_C_REDUCER_OPAND_INSTANCE(unsigned int,uint);
-CILK_C_REDUCER_OPAND_INSTANCE(unsigned int,unsigned); /* alternate name */
-CILK_C_REDUCER_OPAND_INSTANCE(long,long);
-CILK_C_REDUCER_OPAND_INSTANCE(unsigned long,ulong);
-CILK_C_REDUCER_OPAND_INSTANCE(long long,longlong);
-CILK_C_REDUCER_OPAND_INSTANCE(unsigned long long,ulonglong);
-CILK_C_REDUCER_OPAND_INSTANCE(float,float);
-CILK_C_REDUCER_OPAND_INSTANCE(double,double);
-CILK_C_REDUCER_OPAND_INSTANCE(long double,longdouble);
-
-/* Declare function bodies for the reducer for a specific numeric type */
-#define CILK_C_REDUCER_OPAND_IMP(t,tn) \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opand,tn);
+
+/** Define the op_and reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement
+ * the reducer functionality for the op_and reducer type for a specified
+ * numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name” identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPAND_DEFINITION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPAND_TYPE(tn); \
__CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opand,tn,l,r) \
{ *(t*)l &= *(t*)r; } \
__CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opand,tn) \
- { *(t*)v = (t)-1; }
-
-/* c_reducers.c contains definitions for all of the monoid functions
- for the C numeric tyeps. The contents of reducer_opand.c are as follows:
-
-CILK_C_REDUCER_OPAND_IMP(char,char)
-CILK_C_REDUCER_OPAND_IMP(unsigned char,uchar)
-CILK_C_REDUCER_OPAND_IMP(signed char,schar)
-CILK_C_REDUCER_OPAND_IMP(wchar_t,wchar_t)
-CILK_C_REDUCER_OPAND_IMP(short,short)
-CILK_C_REDUCER_OPAND_IMP(unsigned short,ushort)
-CILK_C_REDUCER_OPAND_IMP(int,int)
-CILK_C_REDUCER_OPAND_IMP(unsigned int,uint)
-CILK_C_REDUCER_OPAND_IMP(unsigned int,unsigned) // alternate name
-CILK_C_REDUCER_OPAND_IMP(long,long)
-CILK_C_REDUCER_OPAND_IMP(unsigned long,ulong)
-CILK_C_REDUCER_OPAND_IMP(long long,longlong)
-CILK_C_REDUCER_OPAND_IMP(unsigned long long,ulonglong)
-
-*/
+ { *(t*)v = ~((t)0); }
+
+//@{
+/** @def CILK_C_REDUCER_OPAND_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS`
+ * will be defined, and this macro will generate reducer implementation
+ * functions. Everywhere else, `CILK_C_DEFINE_REDUCERS` will be undefined, and
+ * this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_OPAND_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPAND_DEFINITION(t,tn)
+#else
+# define CILK_C_REDUCER_OPAND_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPAND_DECLARATION(t,tn)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for
+ * each numeric type.
+ */
+CILK_C_REDUCER_OPAND_INSTANCE(char, char)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned char, uchar)
+CILK_C_REDUCER_OPAND_INSTANCE(signed char, schar)
+CILK_C_REDUCER_OPAND_INSTANCE(wchar_t, wchar_t)
+CILK_C_REDUCER_OPAND_INSTANCE(short, short)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned short, ushort)
+CILK_C_REDUCER_OPAND_INSTANCE(int, int)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned int, uint)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned int, unsigned) /* alternate name */
+CILK_C_REDUCER_OPAND_INSTANCE(long, long)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned long, ulong)
+CILK_C_REDUCER_OPAND_INSTANCE(long long, longlong)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned long long, ulonglong)
+
+//@endcond
__CILKRTS_END_EXTERN_C
-#endif /* REDUCER_OPAND_H_INCLUDED */
+//@}
+
+//@}
+
+#endif /* REDUCER_OPAND_H_INCLUDED */