// Copyright (C) 2006 Fokko Beekhof // Email contact: Fokko.Beekhof@cui.unige.ch // The OMPTL library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef OMPTL_NUMERIC_H #define OMPTL_NUMERIC_H 1 #include #include #include #include "omptl_algorithm" #include "omptl_tools.h" namespace omptl { template struct _Accumulate { template static T accumulate(InputIterator first, InputIterator last, T init, T par_init, BinaryFunction binary_op, const unsigned P) { assert(P > 0u); if (_linear_serial_is_faster(first, last, P)) return ::std::accumulate(first, last, init, binary_op); assert(2*(int)P <= std::distance(first, last)); ::std::vector< ::std::pair > partitions(P); ::omptl::_partition_range(first, last, partitions, P); ::std::vector results(P); #pragma omp parallel for for (int t = 0; t < int(P); ++t) results[t] = ::std::accumulate( partitions[t].first, partitions[t].second, par_init, binary_op); return ::std::accumulate(results.begin(), results.end(), init, binary_op); } }; template <> struct _Accumulate< ::std::input_iterator_tag > { template static T accumulate(InputIterator first, InputIterator last, T init, T par_init, BinaryFunction binary_op, const unsigned P) { return ::std::accumulate(first, last, init, binary_op); } }; template struct _AccumulateOp { template static T accumulate(InputIterator first, InputIterator last, T init, BinaryFunction binary_op, const unsigned P) { assert(P > 0u); return ::std::accumulate(first, last, init, binary_op); } }; template struct _AccumulateOp::value_type> > { typedef ::std::plus::value_type> BinaryFunction; template static T accumulate(InputIterator first, InputIterator last, T init, BinaryFunction binary_op, const unsigned P) { assert(P > 0u); return ::omptl::_Accumulate< typename ::std::iterator_traits::iterator_category>:: accumulate(first, last, init, T(0), binary_op, P); } }; template struct _AccumulateOp::value_type> > { typedef ::std::multiplies::value_type> BinaryFunction; template static T accumulate(InputIterator first, InputIterator last, T init, BinaryFunction binary_op, const unsigned P) { assert(P > 0u); return ::omptl::_Accumulate::iterator_category>:: accumulate(first, last, init, T(1), binary_op, P); } }; template T accumulate(InputIterator first, InputIterator last, T init, BinaryFunction binary_op, const unsigned P) { assert(P > 0u); return ::omptl::_AccumulateOp:: accumulate(first, last, init, binary_op, P); } template T accumulate(InputIterator first, InputIterator last, T init, const unsigned P) { assert(P > 0u); typedef typename std::iterator_traits::value_type VT; return ::omptl::accumulate(first, last, init, std::plus(), P); } template OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryFunction binary_op, const unsigned P) { return ::std::adjacent_difference(first, last, result, binary_op); } template OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, const unsigned P) { // ::std::minus::value_type>() return ::std::adjacent_difference(first, last, result); } template struct _InnerProduct { template static T inner_product( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, const unsigned P) { return ::std::inner_product(first1, last1, first2, init, binary_op1, binary_op2); } template static T inner_product(Iterator1 first1, Iterator1 last1, Iterator2 first2, T init, ::std::plus binary_op1, BinaryFunction2 binary_op2, const unsigned P) { assert(P > 0u); if (_linear_serial_is_faster(first1, last1, P)) return ::std::inner_product(first1, last1, first2, init, binary_op1, binary_op2); assert(2*(int)P <= std::distance(first1, last1)); ::std::vector< ::std::pair > partitions1(P); ::omptl::_partition_range(first1, last1, partitions1, P); ::std::vector partitions2(P); ::omptl::_copy_partitions(partitions1, first2, partitions2, P); #pragma omp parallel for reduction(+:init) for (int t = 0; t < int(P); ++t) init += ::std::inner_product( partitions1[t].first, partitions1[t].second, partitions2[t], T(0.0), binary_op1, binary_op2); return init; } }; template struct _InnerProduct< ::std::input_iterator_tag, Iterator2Tag> { template static T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, const unsigned P) { return ::std::inner_product(first1, last1, first2, init, binary_op1, binary_op2); } }; template struct _InnerProduct { template static T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, const unsigned P) { return ::std::inner_product(first1, last1, first2, init, binary_op1, binary_op2); } }; template <> struct _InnerProduct< ::std::input_iterator_tag, ::std::input_iterator_tag > { template static T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, const unsigned P) { return ::std::inner_product(first1, last1, first2, init, binary_op1, binary_op2); } }; template T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, const unsigned P) { return _InnerProduct< typename ::std::iterator_traits::iterator_category, typename ::std::iterator_traits::iterator_category> ::inner_product(first1, last1, first2, init, binary_op1, binary_op2, P); } template T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, const unsigned P) { return ::omptl::inner_product(first1, last1, first2, init, ::std::plus(), ::std::multiplies(), P); } template OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, const unsigned P) { return ::std::partial_sum(first, last, result, binary_op); } template OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, const unsigned P) { // ::std::plus::value_type>(), return ::std::partial_sum(first, last, result); } } // namespace omptl #endif /* OMPTL_NUMERIC_H */