This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[PATCH][libstdc++-v3 parallel mode] PR 33488 improved
- From: Johannes Singler <singler at ira dot uka dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>, gcc-patches at gcc dot gnu dot org
- Date: Fri, 28 Sep 2007 19:29:29 +0200
- Subject: [PATCH][libstdc++-v3 parallel mode] PR 33488 improved
This should fix PR 33488, and a similar problem for inner_product, also
adding corresponding test cases.
Improved patch thanks to Sylvain Pion.
No regressions.
Please approve.
Also, we would like to get some comments/votes on
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33490
-- Johannes
* include/parallel/base.h: Added plus and multiplies functor
for differently typed objects
* include/parallel/numeric: Used the above
* include/parallel/for_each_selectors.h: Allowed different types
* include/parallel/partial_sum.h: Fixed return value
* testsuite/26_numerics/accumulate/1.cc: Tests for accumulate
* testsuite/26_numerics/inner_product/1.cc: Tests for inner_product
Index: include/parallel/base.h
===================================================================
--- include/parallel/base.h (revision 128848)
+++ include/parallel/base.h (working copy)
@@ -112,14 +112,6 @@
};
- /** @brief Similar to std::equal_to, but allows two different types. */
- template<typename T1, typename T2>
- struct equal_to : std::binary_function<T1, T2, bool>
- {
- bool operator()(const T1& t1, const T2& t2) const
- { return t1 == t2; }
- };
-
/** @brief Similar to std::binder1st, but giving the argument types explicitly. */
template<typename _Predicate, typename argument_type>
class unary_negate
@@ -190,6 +182,14 @@
{ return op(__x, value); }
};
+ /** @brief Similar to std::equal_to, but allows two different types. */
+ template<typename T1, typename T2>
+ struct equal_to : std::binary_function<T1, T2, bool>
+ {
+ bool operator()(const T1& t1, const T2& t2) const
+ { return t1 == t2; }
+ };
+
/** @brief Similar to std::less, but allows two different types. */
template<typename T1, typename T2>
struct less : std::binary_function<T1, T2, bool>
@@ -212,6 +212,53 @@
{ return __x < __y; }
};
+
+ /** @brief Similar to std::plus, but allows two different types. */
+ template<typename _Tp1, typename _Tp2>
+ struct plus : public std::binary_function<_Tp1, _Tp2, _Tp1>
+ {
+ typedef typeof(*static_cast<_Tp1*>(NULL) + *static_cast<_Tp2*>(NULL)) result;
+
+ result
+ operator()(const _Tp1& __x, const _Tp2& __y) const
+ { return __x + __y; }
+ };
+
+ // Partial specialization for one type. Same as std::plus.
+ template<typename _Tp>
+ struct plus<_Tp, _Tp> : public std::binary_function<_Tp, _Tp, _Tp>
+ {
+ typedef typeof(*static_cast<_Tp*>(NULL) + *static_cast<_Tp*>(NULL)) result;
+
+ result
+ operator()(const _Tp& __x, const _Tp& __y) const
+ { return __x + __y; }
+ };
+
+
+ /** @brief Similar to std::multiplies, but allows two different types. */
+ template<typename _Tp1, typename _Tp2>
+ struct multiplies : public std::binary_function<_Tp1, _Tp2, _Tp1>
+ {
+ typedef typeof(*static_cast<_Tp1*>(NULL) * *static_cast<_Tp2*>(NULL)) result;
+
+ result
+ operator()(const _Tp1& __x, const _Tp2& __y) const
+ { return __x * __y; }
+ };
+
+ // Partial specialization for one type. Same as std::multiplies.
+ template<typename _Tp>
+ struct multiplies<_Tp, _Tp> : public std::binary_function<_Tp, _Tp, _Tp>
+ {
+ typedef typeof(*static_cast<_Tp*>(NULL) * *static_cast<_Tp*>(NULL)) result;
+
+ result
+ operator()(const _Tp& __x, const _Tp& __y) const
+ { return __x * __y; }
+ };
+
+
template<typename T, typename _DifferenceTp>
class pseudo_sequence;
Index: include/parallel/numeric
===================================================================
--- include/parallel/numeric (revision 128848)
+++ include/parallel/numeric (working copy)
@@ -80,7 +80,8 @@
inline T
accumulate(InputIterator begin, InputIterator end, T init, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced)
{
- return accumulate_switch(begin, end, init, std::plus<typename std::iterator_traits<InputIterator>::value_type>(), typename std::iterator_traits<InputIterator>::iterator_category(), parallelism_tag);
+ return accumulate_switch(begin, end, init,
+ __gnu_parallel::plus<T, typename std::iterator_traits<InputIterator>::value_type>(), typename std::iterator_traits<InputIterator>::iterator_category(), parallelism_tag);
}
// Sequential fallback for input iterator case.
@@ -173,11 +174,16 @@
inline T
inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced)
{
- typedef iterator_traits<InputIterator1> traits_type;
- typedef typename traits_type::value_type value_type;
-
- return inner_product(first1, last1, first2, init, std::plus<value_type>(),
- std::multiplies<value_type>(), parallelism_tag);
+ return inner_product(first1, last1, first2, init,
+ __gnu_parallel::plus<
+ T,
+ typename iterator_traits<InputIterator1>::value_type
+ >(),
+ __gnu_parallel::multiplies<
+ typename iterator_traits<InputIterator1>::value_type,
+ typename iterator_traits<InputIterator2>::value_type
+ >(),
+ parallelism_tag);
}
// Sequential fallback.
Index: include/parallel/for_each_selectors.h
===================================================================
--- include/parallel/for_each_selectors.h (revision 128848)
+++ include/parallel/for_each_selectors.h (working copy)
@@ -335,8 +335,8 @@
explicit accumulate_binop_reduct(BinOp& b) : binop(b) {}
- template<typename T>
- inline T operator()(T x, T y) { return binop(x, y); }
+ template<typename Result, typename Addend>
+ Result operator()(const Result& x, const Addend& y) { return binop(x, y); }
};
}
Index: include/parallel/partial_sum.h
===================================================================
--- include/parallel/partial_sum.h (revision 128848)
+++ include/parallel/partial_sum.h (working copy)
@@ -182,7 +182,7 @@
default:
// Partial_sum algorithm not implemented.
_GLIBCXX_PARALLEL_ASSERT(0);
- return end;
+ return result + n;
}
}
}
Index: testsuite/26_numerics/accumulate/1.cc
===================================================================
--- testsuite/26_numerics/accumulate/1.cc (revision 0)
+++ testsuite/26_numerics/accumulate/1.cc (revision 0)
@@ -0,0 +1,54 @@
+// Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 26.4.1 [lib.accumulate]
+
+#include <numeric>
+#include <testsuite_hooks.h>
+
+int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+const int NA = sizeof(A) / sizeof(int);
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ int res = std::accumulate(A, A + NA, 11);
+ VERIFY( res == 66 );
+}
+
+bool B[] = {true, false, true, true, false, true, false, true, true, false};
+const int NB = sizeof(B) / sizeof(bool);
+
+void
+test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ int res = std::accumulate(B, B + NB, 100);
+ VERIFY( res == 106 );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/26_numerics/inner_product/1.cc
===================================================================
--- testsuite/26_numerics/inner_product/1.cc (revision 0)
+++ testsuite/26_numerics/inner_product/1.cc (revision 0)
@@ -0,0 +1,56 @@
+// Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 26.4.2 [lib.inner_product]
+
+#include <numeric>
+#include <testsuite_hooks.h>
+
+int A1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+int A2[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
+const int NA = sizeof(A1) / sizeof(int);
+
+bool B1[] = {false, true, true, false, true, false, true, true, false, true};
+bool B2[] = {true, false, true, true, false, true, false, true, true, false};
+const int NB = sizeof(B1) / sizeof(bool);
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ int res = std::inner_product(A1, A1 + NA, A2, 31);
+ VERIFY( res == 983 );
+}
+
+void
+test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ int res = std::inner_product(B1, B1 + NB, B2, 100);
+ VERIFY( res == 102 );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ return 0;
+}