/* reducer_min_max.h -*- C++ -*- * * @copyright * Copyright (C) 2009-2013, Intel Corporation * All rights reserved. * * @copyright * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * @copyright * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** @file reducer_min_max.h * * @brief Defines classes for doing parallel minimum and maximum reductions. * * @ingroup ReducersMinMax * * @see ReducersMinMax */ #ifndef REDUCER_MIN_MAX_H_INCLUDED #define REDUCER_MIN_MAX_H_INCLUDED #include #ifdef __cplusplus #include #include /** @defgroup ReducersMinMax Minimum and Maximum Reducers * * Minimum and maximum reducers allow the computation of the minimum or * maximum of a set of values in parallel. * * @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 redminmax_usage Usage Examples * * cilk::reducer< cilk::op_max > rm; * cilk_for (int i = 0; i < ARRAY_SIZE; ++i) * { * rm->calc_max(a[i]); // or *rm = cilk::max_of(*max, a[i]) * } * std::cout << "maximum value is " << rm.get_value() << std::endl; * * and * * cilk::reducer< cilk::op_min_index > rmi; * cilk_for (int i = 0; i < ARRAY_SIZE; ++i) * { * rmi->calc_min(i, a[i]) // or *rmi = cilk::min_of(*rmi, i, a[i]); * } * std::cout << "minimum value a[" << rmi.get_value().first << "] = " * << rmi.get_value().second << std::endl; * * @section redminmax_monoid The Monoid * * @subsection redminmax_monoid_values Value Set * * The value set of a minimum or maximum reducer is the set of values of * `Type`, possibly augmented with a special identity value which is greater * than (less than) any value of `Type`. * * @subsection redminmax_monoid_operator Operator * * In the most common case, the operator of a minimum reducer is defined as * * x MIN y == (x < y) ? x : y * * Thus, `a1 MIN a2 MIN … an` is the first `ai` which is not greater than any * other `ai`. * * The operator of a maximum reducer is defined as * * x MAX y == (x > y) ? x : y * * Thus, `a1 MAX a2 MAX … an` is the first `ai` which is not less than any * other `ai`. * * @subsection redminmax_monoid_comparators Comparators * * Min/max reducers are not limited to finding the minimum or maximum value * determined by the `<` or `>` operator. In fact, all min/max reducers use a * _comparator_, which is either a function or an object of a function class * that defines a [strict weak ordering] * (http://en.wikipedia.org/wiki/Strict_weak_ordering#Strict_weak_orderings) * on a set of values. (This is exactly the same as the requirement for the * comparison predicate for STL associative containers and sorting * algorithms.) * * Just as with STL algorithms and containers, the comparator type parameter * for min/max reducers is optional. If it is omitted, it defaults to * `std::less`, which gives the behavior described in the previous section. * Using non-default comparators (anything other than `std::less`) with * min/max reducers is just like using them with STL containers and * algorithms. * * Taking comparator objects into account, the reduction operation `MIN` for a * minimum reducer is defined as * * x MIN y == compare(x, y) ? x : y * * where `compare()` is the reducer’s comparator. Similarly, the reduction * operation MAX for a maximum reducer is defined as * * x MAX y == compare(y, x) ? x : y * * (If `compare(x, y) == x < y`, then `compare(y, x) == x > y`.) * * @subsection redminmax_monoid_identity Identity * * The identity value of the reducer is the value which is greater than (less * than) any other value in the value set of the reducer. This is the * [“special identity value”](#redminmax_monoid_values) if the reducer has * one, or the largest (smallest) value in the value set otherwise. * * @section redminmax_index Value and Index Reducers * * Min/max reducers come in two families. The _value_ reducers, using `op_min` * and `op_max` monoids, simply find the smallest or largest value from a set * of values. The _index_ reducers, using `op_min_index` and `op_max_index` * monoids, also record an index value associated with the first occurrence of * the smallest or largest value. * * In the `%op_min_index` usage example [above](#redminmax_usage), the values * are taken from an array, and the index of a value is the index of the array * element it comes from. More generally, though, an index can be any sort of * key which identifies a particular value in a collection of values. For * example, if the values were taken from the nodes of a tree, then the * “index” of a value might be a pointer to the node containing that value. * * A min/max index reducer is essentially the same as a min/max value reducer * whose value type is an (index, value) pair, and whose comparator ignores * the index part of the pair. (index, value) pairs are represented by * `std::pair` objects. This has the consequence that wherever * the interface of a min/max value reducer has a `Type`, the interface of the * corresponding min/max index reducer has a `std::pair`. (There * are convenience variants of the `reducer(Type)` constructor and the * `calc_min()`, `calc_max()`, `%min_of()`, and `%max_of()` functions that * take an index argument and a value argument instead of an index/value * pair.) * * @section redminmax_operations Operations * * @subsection redminmax_constructors Constructors * * @subsubsection redminmax_constructors_value Min/Max Value Reducers * * reducer() // identity * reducer(const Compare& compare) // identity * reducer(const Type& value) * reducer(move_in(Type& variable)) * reducer(const Type& value, const Compare& compare) * reducer(move_in(Type& variable), const Compare& compare) * * @subsubsection redminmax_constructors_index Min/Max Index Reducers * * reducer() // identity * reducer(const Compare& compare) // identity * reducer(const std::pair& pair) * reducer(const Index& index, const Type& value) * reducer(move_in(std::pair& variable)) * reducer(const std::pair& pair, const Compare& compare) * reducer(const Index& index, const Type& value, const Compare& compare) * reducer(move_in(std::pair& variable), const Compare& compare) * * @subsection redminmax_get_set Set and Get * * r.set_value(const Type& value) * Type = r.get_value() const * r.move_in(Type& variable) * r.move_out(Type& variable) * * Note that for an index reducer, the `Type` in these operations is actually a * `std::pair`. (See @ref redminmax_index.) There is _not_ a * `set_value(value, index)` operation. * * @subsection redminmax_initial Initial Values and is_set() * * A minimum or maximum reducer without a specified initial value, before any * MIN or MAX operation has been performed on it, represents the [identity * value](#redminmax_monoid_identity) of its monoid. For value reducers with a * numeric type and default comparator (`std::less`), this will be a well * defined value. For example, * * reducer< op_max > r1; * // r1.get_value() == 0 * * reducer< op_min > r2; * // r2.get_value() == std::numeric_limits::infinity * * In other cases, though (index reducers, non-numeric types, or non-default * comparators), the actual identity value for the monoid may be unknown, or * it may not even be a value of the reducer’s type. For example, there is no * “largest string” to serve as the initial value for a * `reducer< op_min >`. In these cases, the result of calling * `get_value()` is undefined. * * To avoid calling `get_value()` when its result is undefined, you can call * the view’s `is_set()` function, which will return true if the reducer * has a well-defined value — either because a MIN or MAX operation has been * performed, or because it had a well-defined initial value: * * reducer< op_max > r1; * // r1->is_set() == true * // r1.get_value() == 0 * * reducer< op_min > r2; * // r2->is_set() == false * // r2.get_value() is undefined * r2->calc_min("xyzzy"); * // r2->is_set() == true * // r2.get_value() == "xyzzy" * * > Note: For an index reducer without a specified initial value, the * > initial value of the index is the default value of the `Index` type. * * @subsection redminmax_view_ops View Operations * * The basic reduction operation is `x = x MIN a` for a minimum reducer, or * `x = x MAX a` for a maximum reducer. The basic syntax for these operations * uses the `calc_min()` and `calc_max()` member functions of the view class. * An assignment syntax is also provided, using the %cilk::min_of() and * %cilk::max_of() global functions: * * Class | Modifier | Assignment * ---------------|---------------------|----------- * `op_min` | `r->calc_min(x)` | `*r = min_of(*r, x)` or `*r = min_of(x, *r)` * `op_max` | `r->calc_max(x)` | `*r = max_of(*r, x)` or `*r = max_of(x, *r)` * `op_min_index` | `r->calc_min(i, x)` | `*r = min_of(*r, i, x)` or `*r = min_of(i, x, *r)` * `op_max_index` | `r->calc_max(i, x)` | `*r = max_of(*r, i, x)` or `*r = max_of(i, x, *r)` * * Wherever an “`i`, `x`” argument pair is shown in the table above, a single * pair argument may be passed instead. For example: * * Index index; * Type value; * std::pair ind_val(index, value); * // The following statements are all equivalent. * r->calc_min(index, value); * r->calc_min(ind_val); * *r = min_of(*r, index, value); * *r = min_of(*r, ind_val); * * The `calc_min()` and `calc_max()` member functions return a reference to * the view, so they can be chained: * * r->calc_max(x).calc_max(y).calc_max(z); * * In a `%min_of()` or `%max_of()` assignment, the view on the left-hand side * of the assignment must be the same as the view argument in the call. * Otherwise, the behavior is undefined (but an assertion error will occur if * the code is compiled with debugging enabled). * * *r = max_of(*r, x); // OK * *r1 = max_of(*r2, y); // ERROR * * `%min_of()` and `%max_of()` calls can be nested: * * *r = max_of(max_of(max_of(*r, x), y), z); * *r = min_of(i, a[i], min_of(j, a[j], min_of(k, a[k], *r))); * * @section redminmax_compatibility Compatibility Issues * * Most Cilk library reducers provide * * Binary compatibility between `reducer_KIND` reducers compiled with Cilk * library version 0.9 (distributed with Intel® C++ Composer XE version * 13.0 and earlier) and the same reducers compiled with Cilk library * version 1.0 and later. * * Transparent casting between references to `reducer` and * `reducer_KIND`. * * This compatibility is not available in all cases for min/max reducers. * There are two areas of incompatibility. * * @subsection redminmax_compatibility_stateful Non-empty Comparators * * There is no way to provide binary compatibility between the 0.9 and 1.0 * definitions of min/max reducers that use a non-empty comparator class or a * comparator function. (Empty comparator classes like `std::less` are not a * problem.) * * To avoid run-time surprises, the legacy `reducer_{min|max}[_index]` classes * have been coded in the 1.0 library so that they will not even compile when * instantiated with a non-empty comparator class. * * @subsection redminmax_compatibility_optimized Numeric Optimization * * Min/max reducers with a numeric value type and the default comparator can * be implemented slightly more efficiently than other min/max reducers. * However, the optimization is incompatible with the 0.9 library * implementation of min/max reducers. * * The default min/max reducers implementation in the 1.0 library uses this * numeric optimization. Code using legacy reducers compiled with the 1.0 * library can be safely used in the same program as code compiled with the * 0.9 library, but classes compiled with the different Cilk libraries will be * defined in different namespaces. * * The simplest solution is just to recompile the code that was compiled with * the older version of Cilk. However, if this is impossible, you can define * the `CILK_LIBRARY_0_9_REDUCER_MINMAX` macro (on the compiler command line, * or in your source code before including `reducer_min_max.h`) when compiling * with the new library. This will cause it to generate numeric reducers that * will be less efficient, but will be fully compatible with previously * compiled code. (Note that this macro has no effect on [the non-empty * comparator incompatibility] (redminmax_compatibility_stateful).) * * @section redminmax_types Type Requirements * * `Type` and `Index` must be `Copy Constructible`, `Default Constructible`, * and `Assignable`. * * `Compare` must be `Copy Constructible` if the reducer is constructed with a * `compare` argument, and `Default Constructible` otherwise. * * The `Compare` function must induce a strict weak ordering on the elements * of `Type`. * * @section redminmax_in_c Minimum and Maximum Reducers in C * * These macros can be used to do minimum and maximum reductions in C: * * Declaration | Type | Operation * -----------------------------|-----------------------------------|---------- * @ref CILK_C_REDUCER_MIN |@ref CILK_C_REDUCER_MIN_TYPE |@ref CILK_C_REDUCER_MIN_CALC * @ref CILK_C_REDUCER_MAX |@ref CILK_C_REDUCER_MAX_TYPE |@ref CILK_C_REDUCER_MAX_CALC * @ref CILK_C_REDUCER_MIN_INDEX |@ref CILK_C_REDUCER_MIN_INDEX_TYPE |@ref CILK_C_REDUCER_MIN_INDEX_CALC * @ref CILK_C_REDUCER_MAX_INDEX |@ref CILK_C_REDUCER_MAX_INDEX_TYPE |@ref CILK_C_REDUCER_MAX_INDEX_CALC * * For example: * * CILK_C_REDUCER_MIN(r, int, INT_MAX); * CILK_C_REGISTER_REDUCER(r); * cilk_for(int i = 0; i != n; ++i) { * CILK_C_REDUCER_MIN_CALC(r, a[i]); * } * CILK_C_UNREGISTER_REDUCER(r); * printf("The smallest value in a is %d\n", REDUCER_VIEW(r)); * * * CILK_C_REDUCER_MAX_INDEX(r, uint, 0); * CILK_C_REGISTER_REDUCER(r); * cilk_for(int i = 0; i != n; ++i) { * CILK_C_REDUCER_MAX_INDEX_CALC(r, i, a[i]); * } * CILK_C_UNREGISTER_REDUCER(r); * printf("The largest value in a is %u at %d\n", * REDUCER_VIEW (r).value, REDUCER_VIEW(r).index); * * See @ref reducers_c_predefined. */ namespace cilk { /** @defgroup ReducersMinMaxBinComp Binary compatibility * * If the macro CILK_LIBRARY_0_9_REDUCER_MINMAX is defined, then we generate * reducer code and data structures which are binary-compatible with code that * was compiled with the old min/max wrapper definitions, so we want the * mangled names of the legacy min/max reducer wrapper classes to be the * same as the names produced by the old definitions. * * Conversely, if the macro is not defined, then we generate binary- * incompatible code, so we want different mangled names, to make sure that * the linker does not allow new and old compiled legacy wrappers to be passed * to one another. (Global variables are a different, and probably insoluble, * problem.) * * Similarly, min/max classes compiled with and without * CILK_LIBRARY_0_9_REDUCER_MINMAX are binary-incompatible, and must get * different mangled names. * * The trick is, when compiling in normal (non-compatibility) mode, wrap * everything in an extra namespace, and then `use` it into the top-level cilk * namespace. Then * * * Classes and functions compiled in normal mode will be in * different namespaces from the same classes and functions compiled in * compatibility mode. * * The legacy wrapper classes and functions will be in the same namespace * as the same classes and functions compiled with the0.9 library if and * only if the are compiled in compatibility mode. * * @ingroup ReducersMinMax */ #ifndef CILK_LIBRARY_0_9_REDUCER_MINMAX /** Namespace to wrap min/max reducer definitions when not compiling in “binary * compatibility” mode. * * By default, all of the min/max reducer definitions are defined in this * namespace and then imported into namespace ::cilk, so that they do not * clash with the legacy definitions with the same names. However, if the * macro `CILK_LIBRARY_0_9_REDUCER_MINMAX` is defined, then the min/max * definitions go directly into namespace ::cilk, so that, for example, * cilk::reducer_max defined with the 1.0 library is equivalent (to the * linker) to cilk::reducer_max defined with the 0.9 library. * * @ingroup ReducersMinMaxBinComp * @ingroup ReducersMinMax */ namespace cilk_lib_1_0 { #endif /** Namespace containing internal implementation classes and functions for * min/max reducers. * * @ingroup ReducersMinMax */ namespace min_max_internal { using ::cilk::internal::binary_functor; using ::cilk::internal::typed_indirect_binary_function; using ::cilk::internal::class_is_empty; /** @defgroup ReducersMinMaxIsSet The “is_set optimization” * * The obvious definition of the identity value for a max or min reducer is as * the smallest (or largest) value of the value type. However, for an * arbitrary comparator and/or an arbitrary value type, the largest / smallest * value may not be known. It may not even be defined — what is the largest * string? * * Therefore, min/max reducers represent their value internally as a pair * `(value, is_set)`. When `is_set` is true, the pair represents the known * value `value`; when `is_set` is false, the pair represents the identity * value. * * This is an effective solution, but the most common use of min/max reducers * is probably with numeric types and the default definition of minimum or * maximum (using `std::less`), in which case there are well-defined, knowable * smallest and largest values. Testing `is_set` for every comparison is then * unnecessary and wasteful. * * The “is_set optimization” just means generating code that doesn’t use * `is_set` when it isn’t needed. It is implemented using two metaprogramming * classes: * * - do_is_set_optimization tests whether the optimization is applicable. * - identity_value gets the appropriate identity value for a type. * * The is_set optimization is the reason that min/max reducers compiled with * Cilk library 1.0 are binary-incompatible with the same reducers compiled * with library 0.9, and therefore the optimization is suppressed when * compiling in * ReducersMinMaxBinComp "binary compatibility mode". * * @ingroup ReducersMinMax */ /** Test whether the ReducersMinMaxIsSet "is_set optimization" is * applicable. * * The @ref do_is_set_optimization class is used to test whether the is_set * optimization should be applied for a particular reducer. It is instantiated * with a value type and a comparator, and defines a boolean constant, * `value`. Then `%do_is_set_optimization::%value` can be used as * a boolean template parameter to control the specialization of another * class. * * In ReducersMinMaxBinComp "binary compatibility mode", when the * `CILK_LIBRARY_0_9_REDUCER_MINMAX` macro is defined, `value` will always * be false. * * @tparam Type The value type for the reducer. * @tparam Compare The comparator type for the reducer. * * @result The `value` data member will be `true` if @a Type is a numeric * type, @a Compare is `std::less`, and * `CILK_LIBRARY_0_9_REDUCER_MINMAX` is not defined. * * @see ReducersMinMaxIsSet * @see @ref view_content * * @ingroup ReducersMinMaxIsSet */ template < typename Type, typename Compare > struct do_is_set_optimization { /// `True` if the is_set optimization should be applied to min/max reducers /// with this value type and comparator; `false` otherwise. static const bool value = false; }; #ifndef CILK_LIBRARY_0_9_REDUCER_MINMAX /// @cond template struct do_is_set_optimization > { /// True in the special case where optimization is possible. static const bool value = std::numeric_limits::is_specialized; }; /// @endcond #endif /** Get the identity value when using the ReducersMinMaxIsSet * "is_set optimization". * * This class defines a function which assigns the appropriate identity value * to a variable when the is_set optimization is applicable. * * @tparam Type The value type for the reducer. * @tparam Compare The comparator type for the reducer. * @tparam ForMax `true` to get the identity value for a max reducer (i.e., * the smallest value of @a Type), `false` to get the identity * value for a min reducer (i.e., the largest value of * @a Type). * * @result If @a Type and @a Compare qualify for the is_set optimization, the * `set_identity()' function will set its argument variable to the * smallest or largest value of @a Type, depending on @a ForMax. * Otherwise, `set_identity()` will be a no-op. * * @see ReducersMinMaxIsSet * * @ingroup ReducersMinMaxIsSet * @see @ref view_content */ template < typename Type, typename Compare, bool ForMax, bool = std::numeric_limits::is_specialized, bool = std::numeric_limits::has_infinity > struct identity_value { /// Assign the identity value to the reference parameter. static void set_identity(Type&) {} }; /// @cond template struct identity_value, true, true, true> { /// Floating max identity is negative infinity. static void set_identity(Type& id) { id = -std::numeric_limits::infinity(); } }; template struct identity_value, true, true, false> { /// Integer max identity is minimum value of type. static void set_identity(Type& id) { id = std::numeric_limits::min(); } }; template struct identity_value, false, true, true> { /// Floating min identity is positive infinity. static void set_identity(Type& id) { id = std::numeric_limits::infinity(); } }; template struct identity_value, false, true, false> { /// Integer min identity is maximum value of type. static void set_identity(Type& id) { id = std::numeric_limits::max(); } }; /// @endcond /** Adapter class to reverse the arguments of a predicate. * * Observe that: * * (x < y) == (y > x) * max(x, y) == (x < y) ? y : x * min(x, y) == (y < x) ? y : x == (x > y) ? y : x * * More generally, if `c` is a predicate defining a `Strict Weak Ordering`, * and `c*(x, y) == c(y, x)`, then * * max(x, y, c) == c(x, y) ? y : x * min(x, y, c) == c(y, x) ? y : x == c*(x, y) ? y : x == max(x, y, c*) * * For any predicate `C` with argument type `T`, the template class * `%reverse_predicate` defines a predicate which is identical to `C`, * except that its arguments are reversed. Thus, for example, we could * implement `%op_min_view` as * `%op_max_view >`. * (Actually, op_min_view and op_max_view are both implemented as subclasses * of a common base class, view_base.) * * @note If `C` is an empty functor class, then `reverse_predicate(C)` will * also be an empty functor class. * * @tparam Predicate The predicate whose arguments are to be reversed. * @tparam Argument @a Predicate’s argument type. * * @ingroup ReducersMinMax */ template class reverse_predicate : private binary_functor::type { typedef typename binary_functor::type base; public: /// Default constructor reverse_predicate() : base() {} /// Constructor with predicate object reverse_predicate(const Predicate& p) : base(p) {} /// The reversed predicate operation bool operator()(const Argument& x, const Argument& y) const { return base::operator()(y, x); } }; /** Class to represent the comparator for a min/max view class. * * This class is intended to accomplish two objectives in the implementation * of min/max views. * * 1. To minimize data bloat, when we have a reducer with a non-stateless * comparator, we want to keep a single instance of the comparator object * in the monoid, and just call it from the views. * 2. In ReducersMinMaxBinComp "binary compatibility mode", views for * reducers with a stateless comparator must have the same content as in * Cilk library 0.9 — that is, they must contain only `value` and * `is_set` data members. * * To achieve the first objective, we use the * @ref internal::typed_indirect_binary_function class defined in * metaprogramming.h to wrap a pointer to the actual comparator. If no * pointer is needed because the actual comparator is stateless, the * `typed_indirect_binary_function` class will be empty, too. * * To achieve the second objective, we make the * `typed_indirect_binary_function` class a base class of the view rather than * a data member, so the “empty base class” rule will ensure no that no * additional space is allocated in the view unless it is needed. * * We could simply use typed_indirect_binary_function as the base class of the * view, but this would mean writing comparisons as `(*this)(x, y)`, which is * just weird. So, instead, we comparator_base as a subclass of * typed_indirect_binary_function which provides function `compare()` * as a synonym for `operator()`. * * @tparam Type The value type of the comparator class. * @tparam Compare A predicate class. * * @see internal::typed_indirect_binary_function * * @ingroup ReducersMinMax */ template class comparator_base : private typed_indirect_binary_function { typedef typed_indirect_binary_function base; protected: comparator_base(const Compare* f) : base(f) {} ///< Constructor. /// Comparison function. bool compare(const Type& a, const Type& b) const { return base::operator()(a, b); } /// Get the comparator pointer. const Compare* compare_pointer() const { return base::pointer(); } }; /** @defgroup ReducersMinMaxViewContent Content classes for min/max views * * @ingroup ReducersMinMax * * Minimum and maximum reducer view classes inherit from a “view content” * class. The content class defines the actual data members for the view, * and provides typedefs and member functions for accessing the data members * as needed to support the view functionality. * * There are two content classes, which encapsulate the differences between * simple min/max reducers and min/max with index reducers: * * - view_content * - index_view_content * * @note An obvious, and arguably simpler, encapsulation strategy would be * to just let the `Type` of a min/max view be an (index, value) pair * structure for min_index and max_index reducers. Then all views * would just have a `Type` data member and an `is_set` data member, * and the comparator for min_index and max_index views could be * customized to consider only the value component of the (index, * value) `Type` pair. Unfortunately, this would break binary * compatibility with reducer_max_index and reducer_min_index in * Cilk library 0.9, because the memory layout of an (index, value) * pair followed by a `bool` is different from the memory layout of an * index data member followed by a value data member followed by a * `bool` data member. The content class is designed to exactly * replicate the layout of the views in library 0.9 reducers. * * A content class `C`, and its objects `c`, must define the following: * * Definition | Meaning * ------------------------------------|-------- * `C::value_type` | A typedef for `Type` of the view. (A `std::pair` for min_index and max_index views). * `C::comp_value_type` | A typedef for the type of value compared by the view’s `compare()` function. * `C()` | Constructs the content with the identity value. * `C(const value_type&)` | Constructs the content with a specified value. * `c.is_set()` | Returns true if the content has a known value. * `c.value()` | Returns the content’s value. * `c.set_value(const value_type&)` | Sets the content’s value. (The value becomes known.) * `c.comp_value()` | Returns a const reference to the value or component of the value that is to be compared by the view’s comparator. * `C::comp_value(const value_type&)` | Returns a const reference to a value or component of a value that is to be compared by the view’s comparator. * * @see view_base */ /** Content class for op_min_view and op_max_view. * * @tparam Type The value type of the op_min_view or op_max_view. * @tparam Compare The comparator class specified for the op_min_view or * op_max_view. (_Not_ the derived comparator class actually * used by the view_base. For example, the view_content of an * `op_min_view` will have `Compare = std::less`, * but its comparator_base will have * `Compare = reverse_predicate< std::less >`.) * @tparam ForMax `true` if this is the content class for an op_max_view, * `false` if it is for an op_min_view. * * @note The general implementation of view_content uses an `is_set` data * member. There is also a specialization which implements the * ReducersMinMaxIsSet "is_set optimization". View classes that * inherit from view_content do not need to know anything about the * difference, though; the details are abstracted away in the * view_content interface. * * @see ReducersMinMaxViewContent * * @ingroup ReducersMinMaxViewContent * @ingroup ReducersMinMax */ template < typename Type , typename Compare , bool ForMax , bool = do_is_set_optimization::value > class view_content { Type m_value; bool m_is_set; public: /// The value type of the view. typedef Type value_type; /// The type compared by the view’s `compare()` function (which is the same /// as the value type for view_content). typedef Type comp_value_type; /// Construct with the identity value. view_content() : m_value(), m_is_set(false) {} /// Construct with a defined value. view_content(const value_type& value) : m_value(value), m_is_set(true) {} /// Get the value. value_type value() const { return m_value; } /// Set the value. void set_value(const value_type& value) { m_value = value; m_is_set = true; } /// Get the comparison value (which is the same as the value for /// view_content). const comp_value_type& comp_value() const { return m_value; } /// Given an arbitrary value, get the corresponding comparison value (which /// is the same as the value for view_content). static const comp_value_type& comp_value(const value_type& value) { return value; } /// Get a const reference to value part of the value (which is the same as /// the value for view_content). const Type& get_reference() const { return m_value; } /// Get a const reference to the index part of the value (which is /// meaningless for non-index reducers, but required for view_base. const Type& get_index_reference() const { return m_value; } /// Test if the value is defined. bool is_set() const { return m_is_set; } }; /// @cond /* This is the specialization of the view_content class for cases where * `AssumeIsSet` is true (i.e., where the is_set optimization is applicable). */ template < typename Type , typename Compare , bool ForMax > class view_content { typedef identity_value Identity; Type m_value; public: typedef Type value_type; typedef Type comp_value_type; /// Construct with identity value. view_content() { Identity::set_identity(m_value); } view_content(const value_type& value) : m_value(value) {} value_type value() const { return m_value; } void set_value(const value_type& value) { m_value = value; } const comp_value_type& comp_value() const { return m_value; } static const comp_value_type& comp_value(const value_type& value) { return value; } const Type& get_reference() const { return m_value; } const Type& get_index_reference() const { return m_value; } /// Test if the value is defined. bool is_set() const { return true; } }; /// @endcond /** Content class for op_min_index_view and op_max_index_view. * * @tparam Index The index type of the op_min_index_view or op_max_index_view. * @tparam Type The value type of the op_min_view or op_max_view. (_Not_ * the value type of the view, which will be * `std::pair`.) * @tparam Compare The comparator class specified for the op_min_index_view or * op_max_index_view. (_Not_ the derived comparator class * actually used by the view_base. For example, the * index_view_content of an `op_min_index_view` will have * `Compare = std::less`, but its comparator_base will * have `Compare = reverse_predicate< std::less >`.) * @tparam ForMax `true` if this is the content class for an * op_max_index_view, `false` if it is for an * op_min_index_view. * * @see ReducersMinMaxViewContent * * @ingroup ReducersMinMaxViewContent * @ingroup ReducersMinMax */ template < typename Index , typename Type , typename Compare , bool ForMax > class index_view_content { typedef identity_value Identity; Index m_index; Type m_value; bool m_is_set; public: /// The value type of the view (which is an pair for /// index_view_content). typedef std::pair value_type; /// The type compared by the view’s `compare()` function (which is the data /// value type for index_view_content). typedef Type comp_value_type; /// Construct with the identity value. index_view_content() : m_index(), m_value(), m_is_set(false) {} /// Construct with an index/value pair. index_view_content(const value_type& value) : m_index(value.first), m_value(value.second), m_is_set(true) {} /// Construct with an index and a value. index_view_content(const Index& index, const Type& value) : m_index(index), m_value(value), m_is_set(true) {} /// Construct with just an index. index_view_content(const Index& index) : m_index(index), m_value(), m_is_set(false) {} /// Get the value. value_type value() const { return value_type(m_index, m_value); } /// Set value. void set_value(const value_type& value) { m_index = value.first; m_value = value.second; m_is_set = true; } /// Get the comparison value (which is the value component of the /// index/value pair for index_view_content). const comp_value_type& comp_value() const { return m_value; } /// Given an arbitrary value (i.e., index/value pair), get the /// corresponding comparison value (which is the value component of the /// index/value pair for index_view_content). static const comp_value_type& comp_value(const value_type& value) { return value.second; } /// Get a const reference to value part of the value. const Type& get_reference() const { return m_value; } /// Get a const reference to the index part of the value. const Index& get_index_reference() const { return m_index; } /// Test if the value is defined. bool is_set() const { return m_is_set; } }; template class rhs_proxy; /** Create an rhs_proxy. */ template inline rhs_proxy make_proxy(const typename View::value_type& value, const View& view); template class view_base; /** Class to represent the right-hand side of * `*reducer = {min|max}_of(*reducer, value)`. * * The only assignment operator for a min/max view class takes a rhs_proxy as * its operand. This results in the syntactic restriction that the only * expressions that can be assigned to a min/max view are ones which generate * an rhs_proxy — that is, expressions of the form `max_of(view, value)` and * `min_of(view, value)`. * * @warning * The lhs and rhs views in such an assignment must be the same; otherwise, * the behavior will be undefined. (I.e., `*r1 = min_of(*r1, x)` is legal; * `*r1 = min_of(*r2, x)` is illegal.) This condition will be checked with a * runtime assertion when compiled in debug mode. * * @tparam View The view class (op_{min|max}[_index]_view) that this proxy * was created from. * * @see view_base * * @ingroup ReducersMinMax */ template class rhs_proxy { typedef typename View::less_type less_type; typedef typename View::compare_type compare_type; typedef typename View::value_type value_type; typedef typename View::content_type content_type; typedef typename content_type::comp_value_type comp_value_type; friend class view_base; friend rhs_proxy make_proxy( const typename View::value_type& value, const View& view); typed_indirect_binary_function< compare_type, comp_value_type, comp_value_type, bool> m_comp; const View* m_view; value_type m_value; rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator rhs_proxy(); // Disable default constructor // Constructor (called from view_base::make_proxy). rhs_proxy(const View* view, const value_type& value, const compare_type* compare) : m_view(view), m_value(value), m_comp(compare) {} // Check matching view, then return value (called from view_base::assign). value_type value(const typename View::base* view) const { __CILKRTS_ASSERT(view == m_view); return m_value; } public: /** Support max_of(max_of(view, value), value) and the like. */ rhs_proxy calc(const value_type& x) const { return rhs_proxy( m_view, m_comp( content_type::comp_value(m_value), content_type::comp_value(x) ) ? x : m_value, m_comp.pointer()); } }; template inline rhs_proxy make_proxy(const typename View::value_type& value, const View& view) { return rhs_proxy(&view, value, view.compare_pointer()); } //@} /** Base class for min and max view classes. * * This class accumulates the minimum or maximum of a set of values which have * occurred as arguments to the `calc()` function, as determined by a * comparator. The accumulated value will be the first `calc()` argument value * `x` such that `compare(x, y)` is false for every `calc()` argument value * `y`. * * If the comparator is `std::less`, then the accumulated value is the first * argument value which is not less than any other argument value, i.e., the * maximum. Similarly, if the comparator is `reverse_predicate`, * which is equivalent to `std::greater`, then the accumulated value is the * first argument value which is not greater than any other argument value, * i.e., the minimum. * * @note This class provides the definitions that are required for a class * that will be used as the parameter of a * min_max_internal::monoid_base specialization. * * @tparam Content A content class that provides the value types and data * members for the view. * @tparam Less A “less than” binary predicate that defines the min or * max function. * @tparam Compare A binary predicate to be used to compare the values. * (The same as @a Less for max reducers; its reversal for * min reducers.) * * @see ReducersMinMaxViewContent * @see op_max_view * @see op_min_view * @see op_max_index_view * @see op_min_index_view * @see monoid_base * * @ingroup ReducersMinMax */ template class view_base : // comparator_base comes first to ensure that it will get empty base class // treatment private comparator_base, private Content { typedef comparator_base base; using base::compare; using Content::value; using Content::set_value; using Content::comp_value; typedef Content content_type; template friend class rhs_proxy; template friend rhs_proxy make_proxy(const typename View::value_type& value, const View& view); public: /** @name Monoid support. */ //@{ /** Value type. Required by @ref monoid_with_view. */ typedef typename Content::value_type value_type; /** The type of the comparator specified by the user, that defines the * ordering on @a Type. Required by min_max::monoid_base. */ typedef Less less_type; /** The type of the comparator actually used by the view. Required by * min_max::monoid_base. (This is the same as the @ref less_type for a * max reducer, or `reverse_predicate` for a min reducer.) */ typedef Compare compare_type; /** Reduce operation. Required by @ref monoid_with_view. */ void reduce(view_base* other) { if ( other->is_set() && ( !this->is_set() || compare(this->comp_value(), other->comp_value()) ) ) { this->set_value(other->value()); } } //@} /** Default constructor. Initializes to identity value. */ explicit view_base(const compare_type* compare) : base(compare), Content() {} /** Value constructor. */ template view_base(const T1& x1, const compare_type* compare) : base(compare), Content(x1) {} /** Value constructor. */ template view_base(const T1& x1, const T2& x2, const compare_type* compare) : base(compare), Content(x1, x2) {} /** Move-in constructor. */ explicit view_base(move_in_wrapper w, const compare_type* compare) : base(compare), Content(w.value()) {} /** @name Reducer support. */ //@{ void view_move_in(value_type& v) { set_value(v); } void view_move_out(value_type& v) { v = value(); } void view_set_value(const value_type& v) { set_value(v); } value_type view_get_value() const { return value(); } // view_get_reference() NOT SUPPORTED //@} /** Is the value defined? */ using Content::is_set; /** Reference to contained value data member. * @deprecated For legacy reducers only. */ using Content::get_reference; /** Reference to contained index data member. * (Meaningless for non-index reducers.) * @deprecated For legacy reducers only. */ using Content::get_index_reference; protected: /** Update the min/max value. */ void calc(const value_type& x) { if (!is_set() || compare(comp_value(), comp_value(x))) set_value(x); } /** Assign the result of a `{min|max}_of(view, value)` expression to the * view. * * @see rhs_proxy */ template void assign(const rhs_proxy& rhs) { calc(rhs.value(this)); } }; /** Base class for min and max monoid classes. * * The unique characteristic of minimum and maximum reducers is that they * incorporate a comparator functor that defines what “minimum” or “maximum” * means. The monoid for a reducer contains the comparator that will be used * for the reduction. If the comparator is a function or a class with state, * then each view will have a pointer to the comparator. * * This means that the `construct()` functions first construct the monoid * (possibly with an explicit comparator argument), and then construct the * view with a pointer to the monoid’s comparator. * * @tparam View The view class. * @tparam Align If true, reducers instantiated on this monoid will be * aligned. By default, library reducers (unlike legacy * library reducer _wrappers_) are unaligned. * * @see view_base * * @ingroup ReducersMinMax */ template class monoid_base : public monoid_with_view { typedef typename View::compare_type compare_type; typedef typename View::less_type less_type; const compare_type m_compare; const compare_type* compare_pointer() const { return &m_compare; } using cilk::monoid_base::provisional; public: /** Default constructor uses default comparator. */ monoid_base() : m_compare() {} /** Constructor. * * @param compare The comparator to use. */ monoid_base(const compare_type& compare) : m_compare(compare) {} /** Create an identity view. * * List view identity constructors take the list allocator as an argument. * * @param v The address of the uninitialized memory in which the view * will be constructed. */ void identity(View *v) const { ::new((void*) v) View(compare_pointer()); } /** @name construct functions * * Min/max monoid `construct()` functions optionally take one or two value * arguments, a @ref move_in argument, and/or a comparator argument. */ //@{ template static void construct(Monoid* monoid, View* view) { provisional( new ((void*)monoid) Monoid() ).confirm_if( new ((void*)view) View(monoid->compare_pointer()) ); } template static void construct(Monoid* monoid, View* view, const T1& x1) { provisional( new ((void*)monoid) Monoid() ).confirm_if( new ((void*)view) View(x1, monoid->compare_pointer()) ); } template static void construct(Monoid* monoid, View* view, const T1& x1, const T2& x2) { provisional( new ((void*)monoid) Monoid() ).confirm_if( new ((void*)view) View(x1, x2, monoid->compare_pointer()) ); } template static void construct(Monoid* monoid, View* view, const less_type& compare) { provisional( new ((void*)monoid) Monoid(compare) ).confirm_if( new ((void*)view) View(monoid->compare_pointer()) ); } template static void construct(Monoid* monoid, View* view, const T1& x1, const less_type& compare) { provisional( new ((void*)monoid) Monoid(compare) ).confirm_if( new ((void*)view) View(x1, monoid->compare_pointer()) ); } template static void construct(Monoid* monoid, View* view, const T1& x1, const T2& x2, const less_type& compare) { provisional( new ((void*)monoid) Monoid(compare) ).confirm_if( new ((void*)view) View(x1, x2, monoid->compare_pointer()) ); } //@} }; } //namespace min_max_internal /** @defgroup ReducersMinMaxMaxValue Maximum reducers (value only) * * These reducers will find the largest value from a set of values. * * @ingroup ReducersMinMax */ //@{ /** The maximum reducer view class. * * This is the view class for reducers created with * `cilk::reducer< cilk::op_max >`. It accumulates the maximum, * as determined by a comparator, of a set of values which have occurred as * arguments to the `calc_max()` function. The accumulated value will be the * first argument `x` such that `compare(x, y)` is false for every argument * `y`. * * If the comparator is `std::less`, then the accumulated value is the first * argument value which is not less than any other argument value, i.e., the * maximum. * * @note The reducer “dereference” operation (`reducer::operator *()`) * yields a reference to the view. Thus, for example, the view class’s * `calc_max()` function would be used in an expression like * `r->calc_max(a)` where `r` is an op_max reducer variable. * * @tparam Type The type of the values compared by the reducer. This will * be the value type of a monoid_with_view that is * instantiated with this view. * @tparam Compare A `Strict Weak Ordering` whose argument type is @a Type. It * defines the “less than” relation used to compute the * maximum. * * @see ReducersMinMax * @see op_max */ template class op_max_view : public min_max_internal::view_base< min_max_internal::view_content, Compare, Compare> { typedef min_max_internal::view_base< min_max_internal::view_content, Compare, Compare> base; using base::calc; using base::assign; friend class min_max_internal::rhs_proxy; public: /** @name Constructors. * * All op_max_view constructors simply pass their arguments on to the * @ref view_base base class. */ //@{ op_max_view() : base() {} template op_max_view(const T1& x1) : base(x1) {} template op_max_view(const T1& x1, const T2& x2) : base(x1, x2) {} //@} /** @name View modifier operations. */ //@{ /** Maximize with a value. * * If @a x is greater than the current value of the view (as defined by * the reducer’s comparator), or if the view was created without an * initial value and its value has never been updated (with `calc_max()` * or `= max_of()`), then the value of the view is set to @a x. * * @param x The value to maximize the view’s value with. * * @return A reference to the view. (Allows chaining * `view.comp_max(a).comp_max(b)…`.) */ op_max_view& calc_max(const Type& x) { calc(x); return *this; } /** Assign the result of a `max_of(view, value)` expression to the view. * * @param rhs An rhs_proxy value created by a `max_of(view, value)` * expression. * * @return A reference to the view. * * @see min_max_internal::view_base::rhs_proxy */ op_max_view& operator=(const min_max_internal::rhs_proxy& rhs) { assign(rhs); return *this; } //@} }; /** Compute the maximum of the value in an op_max_view and another value. * * The result of this computation can only be assigned back to the original * view or used in another max_of() call. For example, * * *reducer = max_of(*reducer, x); * *reducer = max_of(x, *reducer); * * @see min_max_internal::rhs_proxy */ template inline min_max_internal::rhs_proxy< op_max_view > max_of(const op_max_view& view, const Type& value) { return min_max_internal::make_proxy(value, view); } /// @copydoc max_of(const op_max_view&, const Type&) template inline min_max_internal::rhs_proxy< op_max_view > max_of(const Type& value, const op_max_view& view) { return min_max_internal::make_proxy(value, view); } /** Nested maximum computation. * * Compute the maximum of the result of a max_of() call and another value. * * The result of this computation can only be assigned back to the original * view or wrapper, or used in another max_of() call. For example, * * *reducer = max_of(x, max_of(y, *reducer)); * wrapper = max_of(max_of(wrapper, x), y); * * @see min_max_internal::rhs_proxy */ template inline min_max_internal::rhs_proxy< op_max_view > max_of(const min_max_internal::rhs_proxy< op_max_view >& proxy, const Type& value) { return proxy.calc(value); } /// @copydoc max_of(const min_max_internal::rhs_proxy< op_max_view >&, const Type&) template inline min_max_internal::rhs_proxy< op_max_view > max_of(const Type& value, const min_max_internal::rhs_proxy< op_max_view >& proxy) { return proxy.calc(value); } /** Monoid class for maximum reductions. Instantiate the cilk::reducer template * class with an op_max monoid to create a maximum reducer class. For example, * to compute the maximum of a set of `int` values: * * cilk::reducer< cilk::op_max > r; * * @see ReducersMinMax * @see op_max_view */ template , bool Align = false> class op_max : public min_max_internal::monoid_base, Align> { typedef min_max_internal::monoid_base, Align> base; public: /// Construct with default comparator. op_max() {} /// Construct with specified comparator. op_max(const Compare& compare) : base(compare) {} }; //@} /** @defgroup ReducersMinMaxMinValue Minimum reducers (value only) * * These reducers will find the smallest value from a set of values. * * @ingroup ReducersMinMax */ //@{ /** The minimum reducer view class. * * This is the view class for reducers created with * `cilk::reducer< cilk::op_min >`. It accumulates the minimum, * as determined by a comparator, of a set of values which have occurred as * arguments to the `calc_min()` function. The accumulated value will be the * first argument `x` such that `compare(y, x)` is false for every argument * `y`. * * If the comparator is `std::less`, then the accumulated value is the first * argument value which no other argument value is less than, i.e., the * minimum. * * @note The reducer “dereference” operation (`reducer::operator *()`) * yields a reference to the view. Thus, for example, the view class’s * `calc_min()` function would be used in an expression like * `r->calc_min(a)` where `r` is an op_min reducer variable. * * @tparam Type The type of the values compared by the reducer. This will * be the value type of a monoid_with_view that is * instantiated with this view. * @tparam Compare A `Strict Weak Ordering` whose argument type is @a Type. It * defines the “less than” relation used to compute the * minimum. * * @see ReducersMinMax * @see op_min */ template class op_min_view : public min_max_internal::view_base< min_max_internal::view_content, Compare, min_max_internal::reverse_predicate > { typedef min_max_internal::view_base< min_max_internal::view_content, Compare, min_max_internal::reverse_predicate > base; using base::calc; using base::assign; friend class min_max_internal::rhs_proxy; public: /** @name Constructors. * * All op_min_view constructors simply pass their arguments on to the * @ref view_base base class. */ //@{ op_min_view() : base() {} template op_min_view(const T1& x1) : base(x1) {} template op_min_view(const T1& x1, const T2& x2) : base(x1, x2) {} //@} /** @name View modifier operations. */ //@{ /** Minimize with a value. * * If @a x is less than the current value of the view (as defined by the * reducer’s comparator), or if the view was created without an initial * value and its value has never been updated (with `calc_min()` or * `= min_of()`), then the value of the view is set to @a x. * * @param x The value to minimize the view’s value with. * * @return A reference to the view. (Allows chaining * `view.comp_min(a).comp_min(b)…`.) */ op_min_view& calc_min(const Type& x) { calc(x); return *this; } /** Assign the result of a `min_of(view, value)` expression to the view. * * @param rhs An rhs_proxy value created by a `min_of(view, value)` * expression. * * @return A reference to the view. * * @see min_max_internal::view_base::rhs_proxy */ op_min_view& operator=(const min_max_internal::rhs_proxy& rhs) { assign(rhs); return *this; } }; /** Compute the minimum of the value in a view and another value. * * The result of this computation can only be assigned back to the original * view or used in another min_of() call. For example, * * *reducer = min_of(*reducer, x); * *reducer = min_of(x, *reducer); * * @see min_max_internal::view_base::rhs_proxy */ template inline min_max_internal::rhs_proxy< op_min_view > min_of(const op_min_view& view, const Type& value) { return min_max_internal::make_proxy(value, view); } /// @copydoc min_of(const op_min_view&, const Type&) template inline min_max_internal::rhs_proxy< op_min_view > min_of(const Type& value, const op_min_view& view) { return min_max_internal::make_proxy(value, view); } /** Nested minimum computation. * * Compute the minimum of the result of a min_of() call and another value. * * The result of this computation can only be assigned back to the original * view or wrapper, or used in another min_of() call. For example, * * *reducer = min_of(x, min_of(y, *reducer)); * wrapper = min_of(min_of(wrapper, x), y); * * @see min_max_internal::rhs_proxy */ template inline min_max_internal::rhs_proxy< op_min_view > min_of(const min_max_internal::rhs_proxy< op_min_view >& proxy, const Type& value) { return proxy.calc(value); } /// @copydoc min_of(const min_max_internal::rhs_proxy< op_min_view >&, const Type&) template inline min_max_internal::rhs_proxy< op_min_view > min_of(const Type& value, const min_max_internal::rhs_proxy< op_min_view >& proxy) { return proxy.calc(value); } /** Monoid class for minimum reductions. Instantiate the cilk::reducer template * class with an op_min monoid to create a minimum reducer class. For example, * to compute the minimum of a set of `int` values: * * cilk::reducer< cilk::op_min > r; * * @see ReducersMinMax * @see op_min_view */ template , bool Align = false> class op_min : public min_max_internal::monoid_base, Align> { typedef min_max_internal::monoid_base, Align> base; public: /// Construct with default comparator. op_min() {} /// Construct with specified comparator. op_min(const Compare& compare) : base(compare) {} }; //@} /** @defgroup ReducersMinMaxMaxIndex Maximum reducers (value and index) * * These reducers will find the largest value from a set of values, and its * index in the set. * * @ingroup ReducersMinMax */ //@{ /** The maximum index reducer view class. * * This is the view class for reducers created with * `cilk::reducer< cilk::op_max_index >`. It accumulates * the maximum, as determined by a comparator, of a set of values which have * occurred as arguments to the `calc_max()` function, and records the index * of the maximum value. The accumulated value will be the first argument `x` * such that `compare(x, y)` is false for every argument `y`. * * If the comparator is `std::less`, then the accumulated value is the first * argument value which is not less than any other argument value, i.e., the * maximum. * * @note The reducer “dereference” operation (`reducer::operator *()`) * yields a reference to the view. Thus, for example, the view class’s * `calc_max()` function would be used in an expression like * `r->calc_max(i, a)`where `r` is an op_max_index reducer * variable. * * @note The word “index” suggests an integer index into an array, but there * is no restriction on the index type or how it should be used. In * general, it may be convenient to use it for any kind of key that * can be used to locate the maximum value in the collection that it * came from — for example: * - An index into an array. * - A key into an STL map. * - An iterator into any STL container. * * @note A max_index reducer is essentially a max reducer whose value type * is a `std::pair`. This fact is camouflaged in the view * `calc_max` function, the global `max_of` functions, and the reducer * value constructor, which can all take an index argument and a value * argument as an alternative to a single `std::pair` argument. * However, the reducer `set_value()`, `get_value()`, `move_in()`, and * `move_out()` functions work only with pairs, not with individual * value and/or index arguments. * * @tparam Index The type of the indices associated with the values. * @tparam Type The type of the values compared by the reducer. This will * be the value type of a monoid_with_view that is * instantiated with this view. * @tparam Compare Used to compare the values. It must be a binary predicate. * If it is omitted, then the view computes the conventional * arithmetic maximum. * * @see ReducersMinMax * @see op_max_index */ template class op_max_index_view : public min_max_internal::view_base< min_max_internal::index_view_content, Compare, Compare> { typedef min_max_internal::view_base< min_max_internal::index_view_content, Compare, Compare> base; using base::calc; using base::assign; typedef std::pair pair_type; friend class min_max_internal::rhs_proxy; public: /** @name Constructors. * * All op_max_index_view constructors simply pass their arguments on to the * @ref view_base base class, except for the `(index, value [, compare])` * constructors, which create a `std::pair` containing the index and value. */ //@{ op_max_index_view() : base() {} template op_max_index_view(const T1& x1) : base(x1) {} template op_max_index_view(const T1& x1, const T2& x2) : base(x1, x2) {} template op_max_index_view(const T1& x1, const T2& x2, const T3& x3) : base(x1, x2, x3) {} op_max_index_view(const Index& i, const Type& v) : base(pair_type(i, v)) {} op_max_index_view(const Index& i, const Type& v, const typename base::compare_type* c) : base(pair_type(i, v), c) {} //@} /** Maximize with a value and index. * * If @a x is greater than the current value of the view (as defined by * the reducer’s comparator), or if the view was created without an * initial value and its value has never been updated (with `calc_max()` * or `= max_of()`), then the value of the view is set to @a x, and the * index is set to @a i.. * * @param i The index of the value @a x. * @param x The value to maximize the view’s value with. * * @return A reference to the view. (Allows * `view.comp_max(i, a).comp_max(j, b)…`.) */ op_max_index_view& calc_max(const Index& i, const Type& x) { calc(pair_type(i, x)); return *this; } /** Maximize with an index/value pair. * * If @a pair.second is greater than the current value of the view (as * defined by the reducer’s comparator), or if the view was created * without an initial value and its value has never been updated (with * `calc_max()` or `= max_of()`), then the value of the view is set to * @a pair.second, and the index is set to @a pair.first. * * @param pair A pair containing a value to maximize the view’s value * with and its associated index. * * @return A reference to the view. (Allows * `view.comp_max(p1).comp_max(p2)…`.) */ op_max_index_view& calc_max(const pair_type& pair) { calc(pair); return *this; } /** Assign the result of a `max_of(view, index, value)` expression to the * view. * * @param rhs An rhs_proxy value created by a `max_of(view, index, value)` * expression. * * @return A reference to the view. * * @see min_max_internal::view_base::rhs_proxy */ op_max_index_view& operator=(const min_max_internal::rhs_proxy& rhs) { assign(rhs); return *this; } }; /** Compute the maximum of the value in a view and another value. * * The result of this computation can only be assigned back to the original * view or used in another max_of() call. For example, * * *reducer = max_of(*reducer, i, x); * *reducer = max_of(i, x, *reducer); * * @see min_max_internal::rhs_proxy */ template inline min_max_internal::rhs_proxy< op_max_index_view > max_of(const op_max_index_view& view, const Index& index, const Type& value) { return min_max_internal::make_proxy(std::pair(index, value), view); } /// @copydoc max_of(const op_max_index_view&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_max_index_view > max_of(const Index& index, const Type& value, const op_max_index_view& view) { return min_max_internal::make_proxy(std::pair(index, value), view); } /// @copydoc max_of(const op_max_index_view&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_max_index_view > max_of(const op_max_index_view& view, const std::pair& pair) { return min_max_internal::make_proxy(pair, view); } /// @copydoc max_of(const op_max_index_view&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_max_index_view > max_of(const std::pair& pair, const op_max_index_view& view) { return min_max_internal::make_proxy(pair, view); } /** Nested computation of the maximum of the value in a view and other values. * * Compute the maximum of the result of a max_of() call and another value. * * The result of this computation can only be assigned back to the original * view or used in another max_of() call. For example, * * *reducer = max_of(x, max_of(y, *reducer)); * *reducer = max_of(max_of(*reducer, x), y); * * @see min_max_internal::rhs_proxy */ template inline min_max_internal::rhs_proxy< op_max_index_view > max_of(const min_max_internal::rhs_proxy< op_max_index_view >& proxy, const Index& index, const Type& value) { return proxy.calc(std::pair(index, value)); } /// @copydoc max_of(const min_max_internal::rhs_proxy< op_max_index_view >&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_max_index_view > max_of(const Index& index, const Type& value, const min_max_internal::rhs_proxy< op_max_index_view >& proxy) { return proxy.calc(std::pair(index, value)); } /// @copydoc max_of(const min_max_internal::rhs_proxy< op_max_index_view >&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_max_index_view > max_of(const min_max_internal::rhs_proxy< op_max_index_view >& proxy, const std::pair& pair) { return proxy.calc(pair); } /// @copydoc max_of(const min_max_internal::rhs_proxy< op_max_index_view >&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_max_index_view > max_of(const std::pair& pair, const min_max_internal::rhs_proxy< op_max_index_view >& proxy) { return proxy.calc(pair); } /** Monoid class for maximum reductions with index. Instantiate the * cilk::reducer template class with an op_max_index monoid to create a * max_index reducer class. For example, to compute the maximum of an array of * `double` values and the array index of the max value: * * cilk::reducer< cilk::op_max_index > r; * * @see ReducersMinMax * @see op_max_index_view */ template < typename Index , typename Type , typename Compare=std::less , bool Align = false > class op_max_index : public min_max_internal::monoid_base, Align> { typedef min_max_internal::monoid_base< op_max_index_view, Align> base; public: /// Construct with default comparator. op_max_index() {} /// Construct with specified comparator. op_max_index(const Compare& compare) : base(compare) {} }; //@} /** @defgroup ReducersMinMaxMinIndex Minimum reducers (value and index) * * These reducers will find the smallest value from a set of values, and its * index in the set. * * @ingroup ReducersMinMax */ //@{ /** The minimum index reducer view class. * * This is the view class for reducers created with * `cilk::reducer >`. It accumulates * the minimum, as determined by a comparator, of a set of values which have * occurred as arguments to the `calc_min()` function, and records the index * of the minimum value. The accumulated value will be the first argument `x` * such that `compare(y, x)` is false for every argument `y`. * * If the comparator is `std::less`, then the accumulated value is the first * argument value which no other argument value is less than, i.e., the * minimum. * * @note The reducer “dereference” operation (`reducer::operator *()`) * yields a reference to the view. Thus, for example, the view class’s * `calc_min()` function would be * used in an expression like `r->calc_min(i, a)`where `r` is an * op_min_index reducer variable. * * @note The word “index” suggests an integer index into an array, but there * is no restriction on the index type or how it should be used. In * general, it may be convenient to use it for any kind of key that * can be used to locate the minimum value in the collection that it * came from — for example: * - An index into an array. * - A key into an STL map. * - An iterator into any STL container. * * @note A min_index reducer is essentially a min reducer whose value type * is a `std::pair`. This fact is camouflaged in the view * `calc_min` function, the global `min_of` functions, and the reducer * value constructor, which can all take an index argument and a value * argument as an alternative to a single `std::pair` argument. * However, the reducer `set_value()`, `get_value()`, `move_in()`, and * `move_out()` functions work only with pairs, not with individual * value and/or index arguments. * * @tparam Index The type of the indices associated with the values. * @tparam Type The type of the values compared by the reducer. This will * be the value type of a monoid_with_view that is * instantiated with this view. * @tparam Compare Used to compare the values. It must be a binary predicate. * If it is omitted, then the view computes the conventional * arithmetic minimum. * * @see ReducersMinMax * @see op_min_index */ template class op_min_index_view : public min_max_internal::view_base< min_max_internal::index_view_content, Compare, min_max_internal::reverse_predicate > { typedef min_max_internal::view_base< min_max_internal::index_view_content, Compare, min_max_internal::reverse_predicate > base; using base::calc; using base::assign; typedef std::pair pair_type; friend class min_max_internal::rhs_proxy; public: /** @name Constructors. * * All op_min_index_view constructors simply pass their arguments on to the * @ref view_base base class, except for the `(index, value [, compare])` * constructors, which create a `std::pair` containing the index and value. */ //@{ op_min_index_view() : base() {} template op_min_index_view(const T1& x1) : base(x1) {} template op_min_index_view(const T1& x1, const T2& x2) : base(x1, x2) {} template op_min_index_view(const T1& x1, const T2& x2, const T3& x3) : base(x1, x2, x3) {} op_min_index_view(const Index& i, const Type& v) : base(pair_type(i, v)) {} op_min_index_view(const Index& i, const Type& v, const typename base::compare_type* c) : base(pair_type(i, v), c) {} //@} /** Minimize with a value and index. * * If @a x is greater than the current value of the view (as defined by * the reducer’s comparator), or if the view was created without an * initial value and its value has never been updated (with `calc_min()` * or `= min_of()`), then the value of the view is set to @a x, and the * index is set to @a i.. * * @param i The index of the value @a x. * @param x The value to minimize the view’s value with. * * @return A reference to the view. (Allows * `view.comp_min(i, a).comp_min(j, b)…`.) */ op_min_index_view& calc_min(const Index& i, const Type& x) { calc(pair_type(i, x)); return *this; } /** Maximize with an index/value pair. * * If @a pair.second is less than the current value of the view (as * defined by the reducer’s comparator), or if the view was created * without an initial value and its value has never been updated (with * `calc_min()` or `= min_of()`), then the value of the view is set to * @a pair.second, and the index is set to @a pair.first. * * @param pair A pair containing a value to minimize the view’s value * with and its associated index. * * @return A reference to the view. (Allows * `view.comp_min(p1).comp_min(p2)…`.) */ op_min_index_view& calc_min(const pair_type& pair) { calc(pair); return *this; } /** Assign the result of a `min_of(view, index, value)` expression to the * view. * * @param rhs An rhs_proxy value created by a `min_of(view, index, value)` * expression. * * @return A reference to the view. * * @see min_max_internal::view_base::rhs_proxy */ op_min_index_view& operator=(const min_max_internal::rhs_proxy& rhs) { assign(rhs); return *this; } }; /** Compute the minimum of the value in a view and another value. * * The result of this computation can only be assigned back to the original * view or used in another min_of() call. For example, * * *reducer = min_of(*reducer, i, x); * *reducer = min_of(i, x, *reducer); * * @see min_max_internal::min_min_view_base::rhs_proxy */ template inline min_max_internal::rhs_proxy< op_min_index_view > min_of(const op_min_index_view& view, const Index& index, const Type& value) { return min_max_internal::make_proxy(std::pair(index, value), view); } /// @copydoc min_of(const op_min_index_view&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_min_index_view > min_of(const Index& index, const Type& value, const op_min_index_view& view) { return min_max_internal::make_proxy(std::pair(index, value), view); } /// @copydoc min_of(const op_min_index_view&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_min_index_view > min_of(const op_min_index_view& view, const std::pair& pair) { return min_max_internal::make_proxy(pair, view); } /// @copydoc min_of(const op_min_index_view&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_min_index_view > min_of(const std::pair& pair, const op_min_index_view& view) { return min_max_internal::make_proxy(pair, view); } /** Nested computation of the minimum of the value in a view and other values. * * Compute the minimum of the result of a min_of() call and another value. * * The result of this computation can only be assigned back to the original * view or used in another min_of() call. For example, * * *reducer = min_of(x, min_of(y, *reducer)); * *reducer = min_of(min_of(*reducer, x), y); * * @see min_max_internal::min_min_view_base::rhs_proxy */ template inline min_max_internal::rhs_proxy< op_min_index_view > min_of(const min_max_internal::rhs_proxy< op_min_index_view >& proxy, const Index& index, const Type& value) { return proxy.calc(std::pair(index, value)); } /// @copydoc min_of(const min_max_internal::rhs_proxy< op_min_index_view >&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_min_index_view > min_of(const Index& index, const Type& value, const min_max_internal::rhs_proxy< op_min_index_view >& proxy) { return proxy.calc(std::pair(index, value)); } /// @copydoc min_of(const min_max_internal::rhs_proxy< op_min_index_view >&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_min_index_view > min_of(const min_max_internal::rhs_proxy< op_min_index_view >& proxy, const std::pair& pair) { return proxy.calc(pair); } /// @copydoc min_of(const min_max_internal::rhs_proxy< op_min_index_view >&, const Index&, const Type&) template inline min_max_internal::rhs_proxy< op_min_index_view > min_of(const std::pair& pair, const min_max_internal::rhs_proxy< op_min_index_view >& proxy) { return proxy.calc(pair); } /** Monoid class for minimum reductions with index. Instantiate the * cilk::reducer template class with an op_min_index monoid to create a * min_index reducer class. For example, to compute the minimum of an array of * `double` values and the array index of the min value: * * cilk::reducer< cilk::op_min_index > r; * * @see ReducersMinMax * @see op_min_index_view */ template < typename Index , typename Type , typename Compare=std::less , bool Align = false > class op_min_index : public min_max_internal::monoid_base, Align> { typedef min_max_internal::monoid_base< op_min_index_view, Align> base; public: /// Construct with default comparator. op_min_index() {} /// Construct with specified comparator. op_min_index(const Compare& compare) : base(compare) {} }; //@} /** Deprecated maximum reducer wrapper class. * * reducer_max is the same as @ref reducer<@ref op_max>, except that * reducer_max 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 maximized with a `reducer<%op_max>` with * `r->calc_max(a)`, but a value can be maximized with a `%reducer_max` with * `r.calc_max(a)`. * * * @deprecated Users are strongly encouraged to use `reducer` * reducers rather than the old wrappers like reducer_max. * The `reducer` 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_max` * and `reducer<%op_max>`. This allows incremental code * conversion: old code that used `%reducer_max` can pass a * `%reducer_max` to a converted function that now expects a * pointer or reference to a `reducer<%op_max>`, and vice * versa. **But see @ref redminmax_compatibility.** * * @tparam Type The value type of the reducer. * @tparam Compare The “less than” comparator type for the reducer. * * @see op_max * @see op_max_view * @see reducer * @see ReducersMinMax * @ingroup ReducersMinMaxMaxValue */ template > class reducer_max : public reducer< op_max > { __CILKRTS_STATIC_ASSERT( ::cilk::internal::class_is_empty< typename ::cilk::internal::binary_functor::type >::value, "cilk::reducer_max only works with " "an empty Compare class"); typedef reducer< op_max > base; public: /// Type of data in a reducer_max. typedef Type basic_value_type; /// The view type for the reducer. typedef typename base::view_type view_type; /// The view type for the reducer. typedef typename base::view_type View; /// The monoid type for the reducer. typedef typename base::monoid_type monoid_type; /// The monoid type for the reducer. typedef typename base::monoid_type Monoid; /// The view’s rhs proxy type. typedef min_max_internal::rhs_proxy rhs_proxy; using base::view; /** @name Constructors */ //@{ /// Construct the wrapper in its identity state (either `!is_set()`, or /// `value() == identity value`). reducer_max() : base() {} /// Construct the wrapper with a specified initial value. explicit reducer_max(const Type& initial_value) : base(initial_value) {} /// Construct the wrapper in its identity state with a specified /// comparator. explicit reducer_max(const Compare& comp) : base(comp) {} /// Construct the wrapper with a specified initial value and a specified /// comparator. reducer_max(const Type& initial_value, const Compare& comp) : base(initial_value, comp) {} //@} /** @name Forwarded functions * @details Functions that update the contained accumulator variable are * simply forwarded to the contained @ref op_max_view. */ //@{ /// @copydoc cilk_lib_1_0::min_max_internal::view_content::is_set() const bool is_set() const { return view().is_set(); } /// @copydoc op_max_view::calc_max(const Type&) reducer_max& calc_max(const Type& x) { view().calc_max(x); return *this; } /// @copydoc op_max_view::operator=(const min_max_internal::rhs_proxy&) reducer_max& operator=(const rhs_proxy& rhs) { view() = rhs; return *this; } //@} /** Allow read-only access to the value within the current view. * * @returns A const reference to the value within the current view. */ const Type& get_reference() const { return view().get_reference(); } /// @name Dereference /** Dereferencing a wrapper is a no-op. It simply returns the wrapper. * Combined with the rule that a wrapper forwards view operations to the * view, this means that view operations can be written the same way on * reducers and wrappers, which is convenient for incrementally * converting code using wrappers to code using reducers. That is: * * reducer< op_max > r; * r->calc_max(a); // *r returns the view * // calc_max is a view member function * * reducer_max w; * w->calc_max(a); // *w returns the wrapper * // calc_max is a wrapper member function that * // calls the corresponding view function */ //@{ reducer_max& operator*() { return *this; } reducer_max const& operator*() const { return *this; } reducer_max* operator->() { return this; } reducer_max const* operator->() const { return this; } //@} /** @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_max >& () { return *reinterpret_cast< reducer< op_max >* >(this); } operator const reducer< op_max >& () const { return *reinterpret_cast< const reducer< op_max >* >(this); } //@} }; /// @cond internal // The legacy definition of max_of(reducer_max, value) has different // behavior and a different return type than this definition. We add an // unused third argument to this version of the function to give it a different // signature, so that they won’t end up sharing a single object file entry. struct max_of_1_0_t {}; const max_of_1_0_t max_of_1_0 = {}; /// @endcond /** Compute the maximum of the value in a reducer_max and another value. * * @deprecated Because reducer_max is deprecated. * * The result of this computation can only be assigned back to the original * reducer or used in another max_of() call. For example, * * reducer = max_of(reducer, x); * reducer = max_of(x, reducer); * * @see min_max_internal::rhs_proxy * * @ingroup ReducersMinMaxMaxValue */ template inline min_max_internal::rhs_proxy< op_max_view > max_of(const reducer_max& r, const Type& value, const max_of_1_0_t& = max_of_1_0) { return min_max_internal::make_proxy(value, r.view()); } /// @copydoc max_of(const reducer_max&, const Type&, const max_of_1_0_t&) /// @ingroup ReducersMinMaxMaxValue template inline min_max_internal::rhs_proxy< op_max_view > max_of(const Type& value, const reducer_max& r, const max_of_1_0_t& = max_of_1_0) { return min_max_internal::make_proxy(value, r.view()); } /** Deprecated minimum reducer wrapper class. * * reducer_min is the same as @ref reducer<@ref op_min>, except that * reducer_min 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 minimized with a `reducer<%op_min>` with * `r->calc_min(a)`, but a value can be minimized with a `%reducer_min` with * `r.calc_min(a)`. * * * @deprecated Users are strongly encouraged to use `reducer` * reducers rather than the old wrappers like reducer_min. * The `reducer` 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_min` * and `reducer<%op_min>`. This allows incremental code * conversion: old code that used `%reducer_min` can pass a * `%reducer_min` to a converted function that now expects a * pointer or reference to a `reducer<%op_min>`, and vice * versa. **But see @ref redminmax_compatibility.** * * @tparam Type The value type of the reducer. * @tparam Compare The “less than” comparator type for the reducer. * * @see op_min * @see op_min_view * @see reducer * @see ReducersMinMax * @ingroup ReducersMinMaxMinValue */ template > class reducer_min : public reducer< op_min > { __CILKRTS_STATIC_ASSERT( ::cilk::internal::class_is_empty< typename ::cilk::internal::binary_functor::type >::value, "cilk::reducer_min only works with " "an empty Compare class"); typedef reducer< op_min > base; public: /// Type of data in a reducer_min. typedef Type basic_value_type; /// The view type for the reducer. typedef typename base::view_type view_type; /// The view type for the reducer. typedef typename base::view_type View; /// The monoid type for the reducer. typedef typename base::monoid_type monoid_type; /// The monoid type for the reducer. typedef typename base::monoid_type Monoid; /// The view’s rhs proxy type. typedef min_max_internal::rhs_proxy rhs_proxy; using base::view; /** @name Constructors */ //@{ /// Construct the wrapper in its identity state (either `!is_set()`, or /// `value() == identity value`). reducer_min() : base() {} /// Construct the wrapper with a specified initial value. explicit reducer_min(const Type& initial_value) : base(initial_value) {} /// Construct the wrapper in its identity state with a specified /// comparator. explicit reducer_min(const Compare& comp) : base(comp) {} /// Construct the wrapper with a specified initial value and a specified /// comparator. reducer_min(const Type& initial_value, const Compare& comp) : base(initial_value, comp) {} //@} /** @name Forwarded functions * @details Functions that update the contained accumulator variable are * simply forwarded to the contained @ref op_min_view. */ //@{ /// @copydoc cilk_lib_1_0::min_max_internal::view_content::is_set() const bool is_set() const { return view().is_set(); } /// @copydoc op_min_view::calc_min(const Type&) reducer_min& calc_min(const Type& x) { view().calc_min(x); return *this; } /// @copydoc op_min_view::operator=(const min_max_internal::rhs_proxy&) reducer_min& operator=(const rhs_proxy& rhs) { view() = rhs; return *this; } //@} /** Allow read-only access to the value within the current view. * * @returns A const reference to the value within the current view. */ const Type& get_reference() const { return view().get_reference(); } /// @name Dereference /** Dereferencing a wrapper is a no-op. It simply returns the wrapper. * Combined with the rule that a wrapper forwards view operations to the * view, this means that view operations can be written the same way on * reducers and wrappers, which is convenient for incrementally * converting code using wrappers to code using reducers. That is: * * reducer< op_min > r; * r->calc_min(a); // *r returns the view * // calc_min is a view member function * * reducer_min w; * w->calc_min(a); // *w returns the wrapper * // calc_min is a wrapper member function that * // calls the corresponding view function */ //@{ reducer_min& operator*() { return *this; } reducer_min const& operator*() const { return *this; } reducer_min* operator->() { return this; } reducer_min const* operator->() const { return this; } //@} /** @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_min >& () { return *reinterpret_cast< reducer< op_min >* >(this); } operator const reducer< op_min >& () const { return *reinterpret_cast< const reducer< op_min >* >(this); } //@} }; /** Compute the minimum of a reducer and a value. * * @deprecated Because reducer_min is deprecated. */ //@{ // The legacy definition of min_of(reducer_min, value) has different // behavior and a different return type than this definition. We add an // unused third argument to this version of the function to give it a different // signature, so that they won’t end up sharing a single object file entry. struct min_of_1_0_t {}; const min_of_1_0_t min_of_1_0 = {}; template inline min_max_internal::rhs_proxy< op_min_view > min_of(const reducer_min& r, const Type& value, const min_of_1_0_t& = min_of_1_0) { return min_max_internal::make_proxy(value, r.view()); } template inline min_max_internal::rhs_proxy< op_min_view > min_of(const Type& value, const reducer_min& r, const min_of_1_0_t& = min_of_1_0) { return min_max_internal::make_proxy(value, r.view()); } //@} /** Deprecated maximum with index reducer wrapper class. * * reducer_max_index is the same as @ref reducer<@ref op_max_index>, except * that reducer_max_index 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 maximized with a `reducer<%op_max_index>` * with `r->calc_max(i, a)`, but a value can be maximized with a * `%reducer_max` with `r.calc_max(i, aa)`. * * * @deprecated Users are strongly encouraged to use `reducer` * reducers rather than the old wrappers like reducer_max. * The `reducer` 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_max_index` * and `reducer<%op_max_index>`. This allows incremental code * conversion: old code that used `%reducer_max_index` can pass a * `%reducer_max_index` to a converted function that now expects a * pointer or reference to a `reducer<%op_max_index>`, and vice * versa. **But see @ref redminmax_compatibility.** * * @tparam Index The index type of the reducer. * @tparam Type The value type of the reducer. * @tparam Compare The “less than” comparator type for the reducer. * * @see op_max_index * @see op_max_index_view * @see reducer * @see ReducersMinMax * @ingroup ReducersMinMaxMaxIndex */ template < typename Index , typename Type , typename Compare = std::less > class reducer_max_index : public reducer< op_max_index > { __CILKRTS_STATIC_ASSERT( ::cilk::internal::class_is_empty< typename ::cilk::internal::binary_functor::type >::value, "cilk::reducer_max_index only works with " "an empty Compare class"); typedef reducer< op_max_index > base; public: /// Type of data in a reducer_max_index. typedef Type basic_value_type; /// The view type for the reducer. typedef typename base::view_type view_type; /// The view type for the reducer. typedef typename base::view_type View; /// The monoid type for the reducer. typedef typename base::monoid_type monoid_type; /// The monoid type for the reducer. typedef typename base::monoid_type Monoid; /// The view’s rhs proxy type. typedef min_max_internal::rhs_proxy rhs_proxy; using base::view; /** @name Constructors */ //@{ /// Construct the wrapper in its identity state (`!is_set()`). reducer_max_index() : base() {} /// Construct with a specified initial index and value. reducer_max_index(const Index& initial_index, const Type& initial_value) : base(initial_index, initial_value) {} /// Construct the wrapper with a specified comparator. explicit reducer_max_index(const Compare& comp) : base(comp) {} /// Construct the wrapper with a specified initial index, value, /// and comparator. reducer_max_index(const Index& initial_index, const Type& initial_value, const Compare& comp) : base(initial_index, initial_value, comp) {} //@} /** @name Set / Get */ //@{ /// Set the index and value of this object. void set_value(const Index& index, const Type& value) { base::set_value(std::make_pair(index, value)); } /// Return the maximum value. const Type& get_value() const { return view().get_reference(); } /// Return the maximum index. const Index& get_index() const { return view().get_index_reference(); } /// Return a const reference to value data member in the view. const Type& get_reference() const { return view().get_reference(); } /// Return a const reference to index data member in the view. const Index& get_index_reference() const { return view().get_index_reference(); } //@} /** @name Forwarded functions * @details Functions that update the contained accumulator variable are * simply forwarded to the contained @ref op_max_view. */ //@{ /// @copydoc cilk_lib_1_0::min_max_internal::view_content::is_set() const bool is_set() const { return view().is_set(); } /// @copydoc op_max_index_view::calc_max(const Index&, const Type&) reducer_max_index& calc_max(const Index& i, const Type& x) { view().calc_max(i, x); return *this; } /// @copydoc op_max_view::operator=(const min_max_internal::rhs_proxy&) reducer_max_index& operator=(const rhs_proxy& rhs) { view() = rhs; return *this; } //@} /// @name Dereference /** Dereferencing a wrapper is a no-op. It simply returns the wrapper. * Combined with the rule that a wrapper forwards view operations to the * view, this means that view operations can be written the same way on * reducers and wrappers, which is convenient for incrementally * converting code using wrappers to code using reducers. That is: * * reducer< op_max_index > r; * r->calc_max(i, a); // *r returns the view * // calc_max is a view member function * * reducer_max_index w; * w->calc_max(i, a); // *w returns the wrapper * // calc_max is a wrapper member function that * // calls the corresponding view function */ //@{ reducer_max_index& operator*() { return *this; } reducer_max_index const& operator*() const { return *this; } reducer_max_index* operator->() { return this; } reducer_max_index const* operator->() const { return this; } //@} /** @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_max_index >& () { return *reinterpret_cast< reducer< op_max_index >* >(this); } operator const reducer< op_max_index >& () const { return *reinterpret_cast< const reducer< op_max_index >* >(this); } //@} }; /** Deprecated minimum with index reducer wrapper class. * * reducer_min_index is the same as @ref reducer<@ref op_min_index>, except * that reducer_min_index 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 minimized with a `reducer<%op_min_index>` * with `r->calc_min(i, a)`, but a value can be minimized with a * `%reducer_min` with `r.calc_min(i, aa)`. * * * @deprecated Users are strongly encouraged to use `reducer` * reducers rather than the old wrappers like reducer_min. * The `reducer` 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_min_index` * and `reducer<%op_min_index>`. This allows incremental code * conversion: old code that used `%reducer_min_index` can pass a * `%reducer_min_index` to a converted function that now expects a * pointer or reference to a `reducer<%op_min_index>`, and vice * versa. **But see @ref redminmax_compatibility.** * * @tparam Index The index type of the reducer. * @tparam Type The value type of the reducer. * @tparam Compare The “less than” comparator type for the reducer. * * @see op_min_index * @see op_min_index_view * @see reducer * @see ReducersMinMax * @ingroup ReducersMinMaxMinIndex */ template < typename Index , typename Type , typename Compare = std::less > class reducer_min_index : public reducer< op_min_index > { __CILKRTS_STATIC_ASSERT( ::cilk::internal::class_is_empty< typename ::cilk::internal::binary_functor::type >::value, "cilk::reducer_min_index only works with " "an empty Compare class"); typedef reducer< op_min_index > base; public: /// Type of data in a reducer_min_index. typedef Type basic_value_type; /// The view type for the reducer. typedef typename base::view_type view_type; /// The view type for the reducer. typedef typename base::view_type View; /// The monoid type for the reducer. typedef typename base::monoid_type monoid_type; /// The monoid type for the reducer. typedef typename base::monoid_type Monoid; /// The view’s rhs proxy type. typedef min_max_internal::rhs_proxy rhs_proxy; using base::view; /** @name Constructors */ //@{ /// Construct the wrapper in its identity state (`!is_set()`). reducer_min_index() : base() {} /// Construct with a specified initial index and value. reducer_min_index(const Index& initial_index, const Type& initial_value) : base(initial_index, initial_value) {} /// Construct the wrapper with a specified comparator. explicit reducer_min_index(const Compare& comp) : base(comp) {} /// Construct the wrapper with a specified initial index, value, /// and comparator. reducer_min_index(const Index& initial_index, const Type& initial_value, const Compare& comp) : base(initial_index, initial_value, comp) {} //@} /** @name Set / Get */ //@{ /// Set the index and value of this object. void set_value(const Index& index, const Type& value) { base::set_value(std::make_pair(index, value)); } /// Return the minimum value. const Type& get_value() const { return view().get_reference(); } /// Return the minimum index. const Index& get_index() const { return view().get_index_reference(); } /// Return a const reference to value data member in the view. const Type& get_reference() const { return view().get_reference(); } /// Return a const reference to index data member in the view. const Index& get_index_reference() const { return view().get_index_reference(); } //@} /** @name Forwarded functions * @details Functions that update the contained accumulator variable are * simply forwarded to the contained @ref op_min_view. */ //@{ /// @copydoc cilk_lib_1_0::min_max_internal::view_content::is_set() const bool is_set() const { return view().is_set(); } /// @copydoc op_min_index_view::calc_min(const Index&, const Type&) reducer_min_index& calc_min(const Index& i, const Type& x) { view().calc_min(i, x); return *this; } /// @copydoc op_min_view::operator=(const min_max_internal::rhs_proxy&) reducer_min_index& operator=(const rhs_proxy& rhs) { view() = rhs; return *this; } //@} /// @name Dereference /** Dereferencing a wrapper is a no-op. It simply returns the wrapper. * Combined with the rule that a wrapper forwards view operations to the * view, this means that view operations can be written the same way on * reducers and wrappers, which is convenient for incrementally * converting code using wrappers to code using reducers. That is: * * reducer< op_min_index > r; * r->calc_min(i, a); // *r returns the view * // calc_min is a view member function * * reducer_min_index w; * w->calc_min(i, a); // *w returns the wrapper * // calc_min is a wrapper member function that * // calls the corresponding view function */ //@{ reducer_min_index& operator*() { return *this; } reducer_min_index const& operator*() const { return *this; } reducer_min_index* operator->() { return this; } reducer_min_index const* operator->() const { return this; } //@} /** @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_min_index >& () { return *reinterpret_cast< reducer< op_min_index >* >(this); } operator const reducer< op_min_index >& () const { return *reinterpret_cast< const reducer< op_min_index >* >(this); } //@} }; #ifndef CILK_LIBRARY_0_9_REDUCER_MINMAX } // namespace cilk_lib_1_0 using namespace cilk_lib_1_0; #endif /// @cond internal /** Metafunction specialization for reducer conversion. * * These specializations of the @ref legacy_reducer_downcast template class * defined in reducer.h causes each `reducer< op_xxxx >` classes to have * an `operator reducer_xxxx& ()` conversion operator that statically * downcasts the `reducer` to the corresponding `reducer_xxxx` type. * (The reverse conversion, from `reducer_xxxx` to `reducer`, is just * an upcast, which is provided for free by the language.) */ template struct legacy_reducer_downcast< reducer< op_max > > { typedef reducer_max type; }; template struct legacy_reducer_downcast< reducer< op_min > > { typedef reducer_min type; }; template struct legacy_reducer_downcast< reducer< op_max_index > > { typedef reducer_max_index type; }; template struct legacy_reducer_downcast< reducer< op_min_index > > { typedef reducer_min_index type; }; /// @endcond } // namespace cilk #endif // __cplusplus /** @name C language reducer macros * * These macros are used to declare and work with numeric minimum and maximum reducers in C * code. * * @see @ref page_reducers_in_c */ //@{ #ifdef CILK_C_DEFINE_REDUCERS /* Integer min/max constants */ #include /* Wchar_t min/max constants */ #if defined(_MSC_VER) || defined(ANDROID) # include #else # include #endif /* Floating-point min/max constants */ #include #ifndef HUGE_VALF static const unsigned int __huge_valf[] = {0x7f800000}; # define HUGE_VALF (*((const float *)__huge_valf)) #endif #ifndef HUGE_VALL static const unsigned int __huge_vall[] = {0, 0, 0x00007f80, 0}; # define HUGE_VALL (*((const long double *)__huge_vall)) #endif #endif /** Max reducer type name. * * This macro expands into the identifier which is the name of the max 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 */ #define CILK_C_REDUCER_MAX_TYPE(tn) \ __CILKRTS_MKIDENT(cilk_c_reducer_max_,tn) /** Declare a max reducer object. * * This macro expands into a declaration of a max reducer object for a specified numeric * type. For example: * * CILK_C_REDUCER_MAX(my_reducer, double, -DBL_MAX); * * @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 */ #define CILK_C_REDUCER_MAX(obj,tn,v) \ CILK_C_REDUCER_MAX_TYPE(tn) obj = \ CILK_C_INIT_REDUCER(_Typeof(obj.value), \ __CILKRTS_MKIDENT(cilk_c_reducer_max_reduce_,tn), \ __CILKRTS_MKIDENT(cilk_c_reducer_max_identity_,tn), \ __cilkrts_hyperobject_noop_destroy, v) /** Maximize with a value. * * `CILK_C_REDUCER_MAX_CALC(reducer, v)` sets the current view of the * reducer to the max of its previous value and a specified new value. * This is equivalent to * * REDUCER_VIEW(reducer) = max(REDUCER_VIEW(reducer), v) * * @param reducer The reducer whose contained value is to be updated. * @param v The value that it is to be maximized with. */ #define CILK_C_REDUCER_MAX_CALC(reducer, v) do { \ _Typeof((reducer).value)* view = &(REDUCER_VIEW(reducer)); \ _Typeof(v) __value = (v); \ if (*view < __value) { \ *view = __value; \ } } while (0) /// @cond internal /** Declare the max reducer functions for a numeric type. * * This macro expands into external function declarations for functions which implement * the reducer functionality for the max 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_MAX_DECLARATION(t,tn,id) \ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_MAX_TYPE(tn); \ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_max,tn,l,r); \ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_max,tn); /** Define the max reducer functions for a numeric type. * * This macro expands into function definitions for functions which implement the * reducer functionality for the max 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_MAX_DEFINITION(t,tn,id) \ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_MAX_TYPE(tn); \ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_max,tn,l,r) \ { if (*(t*)l < *(t*)r) *(t*)l = *(t*)r; } \ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_max,tn) \ { *(t*)v = id; } //@{ /** @def CILK_C_REDUCER_MAX_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_MAX_INSTANCE(t,tn,id) \ CILK_C_REDUCER_MAX_DEFINITION(t,tn,id) #else # define CILK_C_REDUCER_MAX_INSTANCE(t,tn,id) \ CILK_C_REDUCER_MAX_DECLARATION(t,tn,id) #endif //@} /* Declare or define an instance of the reducer type and its functions for each * numeric type. */ __CILKRTS_BEGIN_EXTERN_C CILK_C_REDUCER_MAX_INSTANCE(char, char, CHAR_MIN) CILK_C_REDUCER_MAX_INSTANCE(unsigned char, uchar, 0) CILK_C_REDUCER_MAX_INSTANCE(signed char, schar, SCHAR_MIN) CILK_C_REDUCER_MAX_INSTANCE(wchar_t, wchar_t, WCHAR_MIN) CILK_C_REDUCER_MAX_INSTANCE(short, short, SHRT_MIN) CILK_C_REDUCER_MAX_INSTANCE(unsigned short, ushort, 0) CILK_C_REDUCER_MAX_INSTANCE(int, int, INT_MIN) CILK_C_REDUCER_MAX_INSTANCE(unsigned int, uint, 0) CILK_C_REDUCER_MAX_INSTANCE(unsigned int, unsigned, 0) // alternate name CILK_C_REDUCER_MAX_INSTANCE(long, long, LONG_MIN) CILK_C_REDUCER_MAX_INSTANCE(unsigned long, ulong, 0) CILK_C_REDUCER_MAX_INSTANCE(long long, longlong, LLONG_MIN) CILK_C_REDUCER_MAX_INSTANCE(unsigned long long, ulonglong, 0) CILK_C_REDUCER_MAX_INSTANCE(float, float, -HUGE_VALF) CILK_C_REDUCER_MAX_INSTANCE(double, double, -HUGE_VAL) CILK_C_REDUCER_MAX_INSTANCE(long double, longdouble, -HUGE_VALL) __CILKRTS_END_EXTERN_C /// @endcond /** Max_index reducer type name. * * This macro expands into the identifier which is the name of the max_index 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 */ #define CILK_C_REDUCER_MAX_INDEX_TYPE(tn) \ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_,tn) /** Declare an op_max_index reducer object. * * This macro expands into a declaration of a max_index reducer object for a specified * numeric type. For example: * * CILK_C_REDUCER_MAX_INDEX(my_reducer, double, -DBL_MAX_INDEX); * * @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 */ #define CILK_C_REDUCER_MAX_INDEX(obj,tn,v) \ CILK_C_REDUCER_MAX_INDEX_TYPE(tn) obj = \ CILK_C_INIT_REDUCER(_Typeof(obj.value), \ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_reduce_,tn), \ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_identity_,tn), \ __cilkrts_hyperobject_noop_destroy, {0, v}) /** Maximize with a value. * * `CILK_C_REDUCER_MAX_INDEX_CALC(reducer, i, v)` sets the current view of the * reducer to the max of its previous value and a specified new value. * This is equivalent to * * REDUCER_VIEW(reducer) = max_index(REDUCER_VIEW(reducer), v) * * If the value of the reducer is changed to @a v, then the index of the reducer is * changed to @a i. * * @param reducer The reducer whose contained value and index are to be updated. * @param i The index associated with the new value. * @param v The value that it is to be maximized with. */ #define CILK_C_REDUCER_MAX_INDEX_CALC(reducer, i, v) do { \ _Typeof((reducer).value)* view = &(REDUCER_VIEW(reducer)); \ _Typeof(v) __value = (v); \ if (view->value < __value) { \ view->index = (i); \ view->value = __value; \ } } while (0) /// @cond internal /** Declare the max_index view type. * * The view of a max_index reducer is a structure containing both the * maximum value for the reducer and the index that was associated with * that value in the sequence of input values. */ #define CILK_C_REDUCER_MAX_INDEX_VIEW(t,tn) \ typedef struct { \ __STDNS ptrdiff_t index; \ t value; \ } __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn) /** Declare the max_index reducer functions for a numeric type. * * This macro expands into external function declarations for functions which implement * the reducer functionality for the max_index 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_MAX_INDEX_DECLARATION(t,tn,id) \ CILK_C_REDUCER_MAX_INDEX_VIEW(t,tn); \ typedef CILK_C_DECLARE_REDUCER( \ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn)) \ CILK_C_REDUCER_MAX_INDEX_TYPE(tn); \ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_max_index,tn,l,r); \ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_max_index,tn); /** Define the max_index reducer functions for a numeric type. * * This macro expands into function definitions for functions which implement the * reducer functionality for the max_index 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_MAX_INDEX_DEFINITION(t,tn,id) \ CILK_C_REDUCER_MAX_INDEX_VIEW(t,tn); \ typedef CILK_C_DECLARE_REDUCER( \ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn)) \ CILK_C_REDUCER_MAX_INDEX_TYPE(tn); \ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_max_index,tn,l,r) \ { typedef __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn) view_t; \ if (((view_t*)l)->value < ((view_t*)r)->value) \ *(view_t*)l = *(view_t*)r; } \ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_max_index,tn) \ { typedef __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn) view_t; \ ((view_t*)v)->index = 0; ((view_t*)v)->value = id; } //@{ /** @def CILK_C_REDUCER_MAX_INDEX_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_MAX_INDEX_INSTANCE(t,tn,id) \ CILK_C_REDUCER_MAX_INDEX_DEFINITION(t,tn,id) #else # define CILK_C_REDUCER_MAX_INDEX_INSTANCE(t,tn,id) \ CILK_C_REDUCER_MAX_INDEX_DECLARATION(t,tn,id) #endif //@} /* Declare or define an instance of the reducer type and its functions for each * numeric type. */ __CILKRTS_BEGIN_EXTERN_C CILK_C_REDUCER_MAX_INDEX_INSTANCE(char, char, CHAR_MIN) CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned char, uchar, 0) CILK_C_REDUCER_MAX_INDEX_INSTANCE(signed char, schar, SCHAR_MIN) CILK_C_REDUCER_MAX_INDEX_INSTANCE(wchar_t, wchar_t, WCHAR_MIN) CILK_C_REDUCER_MAX_INDEX_INSTANCE(short, short, SHRT_MIN) CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned short, ushort, 0) CILK_C_REDUCER_MAX_INDEX_INSTANCE(int, int, INT_MIN) CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned int, uint, 0) CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned int, unsigned, 0) // alternate name CILK_C_REDUCER_MAX_INDEX_INSTANCE(long, long, LONG_MIN) CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned long, ulong, 0) CILK_C_REDUCER_MAX_INDEX_INSTANCE(long long, longlong, LLONG_MIN) CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned long long, ulonglong, 0) CILK_C_REDUCER_MAX_INDEX_INSTANCE(float, float, -HUGE_VALF) CILK_C_REDUCER_MAX_INDEX_INSTANCE(double, double, -HUGE_VAL) CILK_C_REDUCER_MAX_INDEX_INSTANCE(long double, longdouble, -HUGE_VALL) __CILKRTS_END_EXTERN_C /// @endcond /** Min reducer type name. * * This macro expands into the identifier which is the name of the min 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 */ #define CILK_C_REDUCER_MIN_TYPE(tn) \ __CILKRTS_MKIDENT(cilk_c_reducer_min_,tn) /** Declare a min reducer object. * * This macro expands into a declaration of a min reducer object for a specified numeric * type. For example: * * CILK_C_REDUCER_MIN(my_reducer, double, DBL_MAX); * * @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 */ #define CILK_C_REDUCER_MIN(obj,tn,v) \ CILK_C_REDUCER_MIN_TYPE(tn) obj = \ CILK_C_INIT_REDUCER(_Typeof(obj.value), \ __CILKRTS_MKIDENT(cilk_c_reducer_min_reduce_,tn), \ __CILKRTS_MKIDENT(cilk_c_reducer_min_identity_,tn), \ __cilkrts_hyperobject_noop_destroy, v) /** Minimize with a value. * * `CILK_C_REDUCER_MIN_CALC(reducer, v)` sets the current view of the * reducer to the min of its previous value and a specified new value. * This is equivalent to * * REDUCER_VIEW(reducer) = min(REDUCER_VIEW(reducer), v) * * @param reducer The reducer whose contained value is to be updated. * @param v The value that it is to be minimized with. */ #define CILK_C_REDUCER_MIN_CALC(reducer, v) do { \ _Typeof((reducer).value)* view = &(REDUCER_VIEW(reducer)); \ _Typeof(v) __value = (v); \ if (*view > __value) { \ *view = __value; \ } } while (0) /// @cond internal /** Declare the min reducer functions for a numeric type. * * This macro expands into external function declarations for functions which implement * the reducer functionality for the min 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_MIN_DECLARATION(t,tn,id) \ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_MIN_TYPE(tn); \ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_min,tn,l,r); \ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_min,tn); /** Define the min reducer functions for a numeric type. * * This macro expands into function definitions for functions which implement the * reducer functionality for the min 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_MIN_DEFINITION(t,tn,id) \ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_MIN_TYPE(tn); \ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_min,tn,l,r) \ { if (*(t*)l > *(t*)r) *(t*)l = *(t*)r; } \ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_min,tn) \ { *(t*)v = id; } //@{ /** @def CILK_C_REDUCER_MIN_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_MIN_INSTANCE(t,tn,id) \ CILK_C_REDUCER_MIN_DEFINITION(t,tn,id) #else # define CILK_C_REDUCER_MIN_INSTANCE(t,tn,id) \ CILK_C_REDUCER_MIN_DECLARATION(t,tn,id) #endif //@} /* Declare or define an instance of the reducer type and its functions for each * numeric type. */ __CILKRTS_BEGIN_EXTERN_C CILK_C_REDUCER_MIN_INSTANCE(char, char, CHAR_MAX) CILK_C_REDUCER_MIN_INSTANCE(unsigned char, uchar, CHAR_MAX) CILK_C_REDUCER_MIN_INSTANCE(signed char, schar, SCHAR_MAX) CILK_C_REDUCER_MIN_INSTANCE(wchar_t, wchar_t, WCHAR_MAX) CILK_C_REDUCER_MIN_INSTANCE(short, short, SHRT_MAX) CILK_C_REDUCER_MIN_INSTANCE(unsigned short, ushort, USHRT_MAX) CILK_C_REDUCER_MIN_INSTANCE(int, int, INT_MAX) CILK_C_REDUCER_MIN_INSTANCE(unsigned int, uint, UINT_MAX) CILK_C_REDUCER_MIN_INSTANCE(unsigned int, unsigned, UINT_MAX) // alternate name CILK_C_REDUCER_MIN_INSTANCE(long, long, LONG_MAX) CILK_C_REDUCER_MIN_INSTANCE(unsigned long, ulong, ULONG_MAX) CILK_C_REDUCER_MIN_INSTANCE(long long, longlong, LLONG_MAX) CILK_C_REDUCER_MIN_INSTANCE(unsigned long long, ulonglong, ULLONG_MAX) CILK_C_REDUCER_MIN_INSTANCE(float, float, HUGE_VALF) CILK_C_REDUCER_MIN_INSTANCE(double, double, HUGE_VAL) CILK_C_REDUCER_MIN_INSTANCE(long double, longdouble, HUGE_VALL) __CILKRTS_END_EXTERN_C /// @endcond /** Min_index reducer type name. * * This macro expands into the identifier which is the name of the min_index 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 */ #define CILK_C_REDUCER_MIN_INDEX_TYPE(tn) \ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_,tn) /** Declare an op_min_index reducer object. * * This macro expands into a declaration of a min_index reducer object for a specified * numeric type. For example: * * CILK_C_REDUCER_MIN_INDEX(my_reducer, double, -DBL_MIN_INDEX); * * @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 */ #define CILK_C_REDUCER_MIN_INDEX(obj,tn,v) \ CILK_C_REDUCER_MIN_INDEX_TYPE(tn) obj = \ CILK_C_INIT_REDUCER(_Typeof(obj.value), \ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_reduce_,tn), \ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_identity_,tn), \ __cilkrts_hyperobject_noop_destroy, {0, v}) /** Minimize with a value. * * `CILK_C_REDUCER_MIN_INDEX_CALC(reducer, i, v)` sets the current view of the * reducer to the min of its previous value and a specified new value. * This is equivalent to * * REDUCER_VIEW(reducer) = min_index(REDUCER_VIEW(reducer), v) * * If the value of the reducer is changed to @a v, then the index of the reducer is * changed to @a i. * * @param reducer The reducer whose contained value and index are to be updated. * @param i The index associated with the new value. * @param v The value that it is to be minimized with. */ #define CILK_C_REDUCER_MIN_INDEX_CALC(reducer, i, v) do { \ _Typeof((reducer).value)* view = &(REDUCER_VIEW(reducer)); \ _Typeof(v) __value = (v); \ if (view->value > __value) { \ view->index = (i); \ view->value = __value; \ } } while (0) /// @cond internal /** Declare the min_index view type. * * The view of a min_index reducer is a structure containing both the * minimum value for the reducer and the index that was associated with * that value in the sequence of input values. */ #define CILK_C_REDUCER_MIN_INDEX_VIEW(t,tn) \ typedef struct { \ __STDNS ptrdiff_t index; \ t value; \ } __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn) /** Declare the min_index reducer functions for a numeric type. * * This macro expands into external function declarations for functions which implement * the reducer functionality for the min_index 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_MIN_INDEX_DECLARATION(t,tn,id) \ CILK_C_REDUCER_MIN_INDEX_VIEW(t,tn); \ typedef CILK_C_DECLARE_REDUCER( \ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn)) \ CILK_C_REDUCER_MIN_INDEX_TYPE(tn); \ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_min_index,tn,l,r); \ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_min_index,tn); /** Define the min_index reducer functions for a numeric type. * * This macro expands into function definitions for functions which implement the * reducer functionality for the min_index 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_MIN_INDEX_DEFINITION(t,tn,id) \ CILK_C_REDUCER_MIN_INDEX_VIEW(t,tn); \ typedef CILK_C_DECLARE_REDUCER( \ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn)) \ CILK_C_REDUCER_MIN_INDEX_TYPE(tn); \ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_min_index,tn,l,r) \ { typedef __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn) view_t; \ if (((view_t*)l)->value > ((view_t*)r)->value) \ *(view_t*)l = *(view_t*)r; } \ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_min_index,tn) \ { typedef __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn) view_t; \ ((view_t*)v)->index = 0; ((view_t*)v)->value = id; } //@{ /** @def CILK_C_REDUCER_MIN_INDEX_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_MIN_INDEX_INSTANCE(t,tn,id) \ CILK_C_REDUCER_MIN_INDEX_DEFINITION(t,tn,id) #else # define CILK_C_REDUCER_MIN_INDEX_INSTANCE(t,tn,id) \ CILK_C_REDUCER_MIN_INDEX_DECLARATION(t,tn,id) #endif //@} /* Declare or define an instance of the reducer type and its functions for each * numeric type. */ __CILKRTS_BEGIN_EXTERN_C CILK_C_REDUCER_MIN_INDEX_INSTANCE(char, char, CHAR_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned char, uchar, CHAR_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(signed char, schar, SCHAR_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(wchar_t, wchar_t, WCHAR_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(short, short, SHRT_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned short, ushort, USHRT_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(int, int, INT_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned int, uint, UINT_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned int, unsigned, UINT_MAX) // alternate name CILK_C_REDUCER_MIN_INDEX_INSTANCE(long, long, LONG_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned long, ulong, ULONG_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(long long, longlong, LLONG_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned long long, ulonglong, ULLONG_MAX) CILK_C_REDUCER_MIN_INDEX_INSTANCE(float, float, HUGE_VALF) CILK_C_REDUCER_MIN_INDEX_INSTANCE(double, double, HUGE_VAL) CILK_C_REDUCER_MIN_INDEX_INSTANCE(long double, longdouble, HUGE_VALL) __CILKRTS_END_EXTERN_C /// @endcond //@} #endif // defined REDUCER_MAX_H_INCLUDED