1 // -*- C++ -*- 2 3 // Copyright (C) 2007-2013 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the terms 7 // of the GNU General Public License as published by the Free Software 8 // Foundation; either version 3, or (at your option) any later 9 // version. 10 11 // This library is distributed in the hope that it will be useful, but 12 // WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 // General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file parallel/base.h 26 * @brief Sequential helper functions. 27 * This file is a GNU parallel extension to the Standard C++ Library. 28 */ 29 30 // Written by Johannes Singler. 31 32 #ifndef _GLIBCXX_PARALLEL_BASE_H 33 #define _GLIBCXX_PARALLEL_BASE_H 1 34 35 #include <bits/c++config.h> 36 #include <bits/stl_function.h> 37 #include <omp.h> 38 #include <parallel/features.h> 39 #include <parallel/basic_iterator.h> 40 #include <parallel/parallel.h> 41 42 // Parallel mode namespaces. 43 44 /** 45 * @namespace std::__parallel 46 * @brief GNU parallel code, replaces standard behavior with parallel behavior. 47 */ 48 namespace std _GLIBCXX_VISIBILITY(default) 49 { 50 namespace __parallel { } 51 } 52 53 /** 54 * @namespace __gnu_parallel 55 * @brief GNU parallel code for public use. 56 */ 57 namespace __gnu_parallel 58 { 59 // Import all the parallel versions of components in namespace std. 60 using namespace std::__parallel; 61 } 62 63 /** 64 * @namespace __gnu_sequential 65 * @brief GNU sequential classes for public use. 66 */ 67 namespace __gnu_sequential 68 { 69 // Import whatever is the serial version. 70 #ifdef _GLIBCXX_PARALLEL 71 using namespace std::_GLIBCXX_STD_A; 72 #else 73 using namespace std; 74 #endif 75 } 76 77 78 namespace __gnu_parallel 79 { 80 // NB: Including this file cannot produce (unresolved) symbols from 81 // the OpenMP runtime unless the parallel mode is actually invoked 82 // and active, which imples that the OpenMP runtime is actually 83 // going to be linked in. 84 inline _ThreadIndex 85 __get_max_threads() 86 { 87 _ThreadIndex __i = omp_get_max_threads(); 88 return __i > 1 ? __i : 1; 89 } 90 91 92 inline bool 93 __is_parallel(const _Parallelism __p) { return __p != sequential; } 94 95 96 /** @brief Calculates the rounded-down logarithm of @c __n for base 2. 97 * @param __n Argument. 98 * @return Returns 0 for any argument <1. 99 */ 100 template<typename _Size> 101 inline _Size 102 __rd_log2(_Size __n) 103 { 104 _Size __k; 105 for (__k = 0; __n > 1; __n >>= 1) 106 ++__k; 107 return __k; 108 } 109 110 /** @brief Encode two integers into one gnu_parallel::_CASable. 111 * @param __a First integer, to be encoded in the most-significant @c 112 * _CASable_bits/2 bits. 113 * @param __b Second integer, to be encoded in the least-significant 114 * @c _CASable_bits/2 bits. 115 * @return value encoding @c __a and @c __b. 116 * @see __decode2 117 */ 118 inline _CASable 119 __encode2(int __a, int __b) //must all be non-negative, actually 120 { 121 return (((_CASable)__a) << (_CASable_bits / 2)) | (((_CASable)__b) << 0); 122 } 123 124 /** @brief Decode two integers from one gnu_parallel::_CASable. 125 * @param __x __gnu_parallel::_CASable to decode integers from. 126 * @param __a First integer, to be decoded from the most-significant 127 * @c _CASable_bits/2 bits of @c __x. 128 * @param __b Second integer, to be encoded in the least-significant 129 * @c _CASable_bits/2 bits of @c __x. 130 * @see __encode2 131 */ 132 inline void 133 __decode2(_CASable __x, int& __a, int& __b) 134 { 135 __a = (int)((__x >> (_CASable_bits / 2)) & _CASable_mask); 136 __b = (int)((__x >> 0 ) & _CASable_mask); 137 } 138 139 //needed for parallel "numeric", even if "algorithm" not included 140 141 /** @brief Equivalent to std::min. */ 142 template<typename _Tp> 143 inline const _Tp& 144 min(const _Tp& __a, const _Tp& __b) 145 { return (__a < __b) ? __a : __b; } 146 147 /** @brief Equivalent to std::max. */ 148 template<typename _Tp> 149 inline const _Tp& 150 max(const _Tp& __a, const _Tp& __b) 151 { return (__a > __b) ? __a : __b; } 152 153 /** @brief Constructs predicate for equality from strict weak 154 * ordering predicate 155 */ 156 template<typename _T1, typename _T2, typename _Compare> 157 class _EqualFromLess : public std::binary_function<_T1, _T2, bool> 158 { 159 private: 160 _Compare& _M_comp; 161 162 public: 163 _EqualFromLess(_Compare& __comp) : _M_comp(__comp) { } 164 165 bool operator()(const _T1& __a, const _T2& __b) 166 { return !_M_comp(__a, __b) && !_M_comp(__b, __a); } 167 }; 168 169 170 /** @brief Similar to std::unary_negate, 171 * but giving the argument types explicitly. */ 172 template<typename _Predicate, typename argument_type> 173 class __unary_negate 174 : public std::unary_function<argument_type, bool> 175 { 176 protected: 177 _Predicate _M_pred; 178 179 public: 180 explicit 181 __unary_negate(const _Predicate& __x) : _M_pred(__x) { } 182 183 bool 184 operator()(const argument_type& __x) 185 { return !_M_pred(__x); } 186 }; 187 188 /** @brief Similar to std::binder1st, 189 * but giving the argument types explicitly. */ 190 template<typename _Operation, typename _FirstArgumentType, 191 typename _SecondArgumentType, typename _ResultType> 192 class __binder1st 193 : public std::unary_function<_SecondArgumentType, _ResultType> 194 { 195 protected: 196 _Operation _M_op; 197 _FirstArgumentType _M_value; 198 199 public: 200 __binder1st(const _Operation& __x, const _FirstArgumentType& __y) 201 : _M_op(__x), _M_value(__y) { } 202 203 _ResultType 204 operator()(const _SecondArgumentType& __x) 205 { return _M_op(_M_value, __x); } 206 207 // _GLIBCXX_RESOLVE_LIB_DEFECTS 208 // 109. Missing binders for non-const sequence elements 209 _ResultType 210 operator()(_SecondArgumentType& __x) const 211 { return _M_op(_M_value, __x); } 212 }; 213 214 /** 215 * @brief Similar to std::binder2nd, but giving the argument types 216 * explicitly. 217 */ 218 template<typename _Operation, typename _FirstArgumentType, 219 typename _SecondArgumentType, typename _ResultType> 220 class __binder2nd 221 : public std::unary_function<_FirstArgumentType, _ResultType> 222 { 223 protected: 224 _Operation _M_op; 225 _SecondArgumentType _M_value; 226 227 public: 228 __binder2nd(const _Operation& __x, const _SecondArgumentType& __y) 229 : _M_op(__x), _M_value(__y) { } 230 231 _ResultType 232 operator()(const _FirstArgumentType& __x) const 233 { return _M_op(__x, _M_value); } 234 235 // _GLIBCXX_RESOLVE_LIB_DEFECTS 236 // 109. Missing binders for non-const sequence elements 237 _ResultType 238 operator()(_FirstArgumentType& __x) 239 { return _M_op(__x, _M_value); } 240 }; 241 242 /** @brief Similar to std::equal_to, but allows two different types. */ 243 template<typename _T1, typename _T2> 244 struct _EqualTo : std::binary_function<_T1, _T2, bool> 245 { 246 bool operator()(const _T1& __t1, const _T2& __t2) const 247 { return __t1 == __t2; } 248 }; 249 250 /** @brief Similar to std::less, but allows two different types. */ 251 template<typename _T1, typename _T2> 252 struct _Less : std::binary_function<_T1, _T2, bool> 253 { 254 bool 255 operator()(const _T1& __t1, const _T2& __t2) const 256 { return __t1 < __t2; } 257 258 bool 259 operator()(const _T2& __t2, const _T1& __t1) const 260 { return __t2 < __t1; } 261 }; 262 263 // Partial specialization for one type. Same as std::less. 264 template<typename _Tp> 265 struct _Less<_Tp, _Tp> 266 : public std::less<_Tp> { }; 267 268 /** @brief Similar to std::plus, but allows two different types. */ 269 template<typename _Tp1, typename _Tp2, typename _Result 270 = __typeof__(*static_cast<_Tp1*>(0) 271 + *static_cast<_Tp2*>(0))> 272 struct _Plus : public std::binary_function<_Tp1, _Tp2, _Result> 273 { 274 _Result 275 operator()(const _Tp1& __x, const _Tp2& __y) const 276 { return __x + __y; } 277 }; 278 279 // Partial specialization for one type. Same as std::plus. 280 template<typename _Tp> 281 struct _Plus<_Tp, _Tp, _Tp> 282 : public std::plus<_Tp> { }; 283 284 /** @brief Similar to std::multiplies, but allows two different types. */ 285 template<typename _Tp1, typename _Tp2, typename _Result 286 = __typeof__(*static_cast<_Tp1*>(0) 287 * *static_cast<_Tp2*>(0))> 288 struct _Multiplies : public std::binary_function<_Tp1, _Tp2, _Result> 289 { 290 _Result 291 operator()(const _Tp1& __x, const _Tp2& __y) const 292 { return __x * __y; } 293 }; 294 295 // Partial specialization for one type. Same as std::multiplies. 296 template<typename _Tp> 297 struct _Multiplies<_Tp, _Tp, _Tp> 298 : public std::multiplies<_Tp> { }; 299 300 /** @brief _Iterator associated with __gnu_parallel::_PseudoSequence. 301 * If features the usual random-access iterator functionality. 302 * @param _Tp Sequence _M_value type. 303 * @param _DifferenceTp Sequence difference type. 304 */ 305 template<typename _Tp, typename _DifferenceTp> 306 class _PseudoSequenceIterator 307 { 308 public: 309 typedef _DifferenceTp _DifferenceType; 310 311 _PseudoSequenceIterator(const _Tp& __val, _DifferenceType __pos) 312 : _M_val(__val), _M_pos(__pos) { } 313 314 // Pre-increment operator. 315 _PseudoSequenceIterator& 316 operator++() 317 { 318 ++_M_pos; 319 return *this; 320 } 321 322 // Post-increment operator. 323 _PseudoSequenceIterator 324 operator++(int) 325 { return _PseudoSequenceIterator(_M_pos++); } 326 327 const _Tp& 328 operator*() const 329 { return _M_val; } 330 331 const _Tp& 332 operator[](_DifferenceType) const 333 { return _M_val; } 334 335 bool 336 operator==(const _PseudoSequenceIterator& __i2) 337 { return _M_pos == __i2._M_pos; } 338 339 bool 340 operator!=(const _PseudoSequenceIterator& __i2) 341 { return _M_pos != __i2._M_pos; } 342 343 _DifferenceType 344 operator-(const _PseudoSequenceIterator& __i2) 345 { return _M_pos - __i2._M_pos; } 346 347 private: 348 const _Tp& _M_val; 349 _DifferenceType _M_pos; 350 }; 351 352 /** @brief Sequence that conceptually consists of multiple copies of 353 the same element. 354 * The copies are not stored explicitly, of course. 355 * @param _Tp Sequence _M_value type. 356 * @param _DifferenceTp Sequence difference type. 357 */ 358 template<typename _Tp, typename _DifferenceTp> 359 class _PseudoSequence 360 { 361 public: 362 typedef _DifferenceTp _DifferenceType; 363 364 // Better cast down to uint64_t, than up to _DifferenceTp. 365 typedef _PseudoSequenceIterator<_Tp, uint64_t> iterator; 366 367 /** @brief Constructor. 368 * @param __val Element of the sequence. 369 * @param __count Number of (virtual) copies. 370 */ 371 _PseudoSequence(const _Tp& __val, _DifferenceType __count) 372 : _M_val(__val), _M_count(__count) { } 373 374 /** @brief Begin iterator. */ 375 iterator 376 begin() const 377 { return iterator(_M_val, 0); } 378 379 /** @brief End iterator. */ 380 iterator 381 end() const 382 { return iterator(_M_val, _M_count); } 383 384 private: 385 const _Tp& _M_val; 386 _DifferenceType _M_count; 387 }; 388 389 /** @brief Compute the median of three referenced elements, 390 according to @c __comp. 391 * @param __a First iterator. 392 * @param __b Second iterator. 393 * @param __c Third iterator. 394 * @param __comp Comparator. 395 */ 396 template<typename _RAIter, typename _Compare> 397 _RAIter 398 __median_of_three_iterators(_RAIter __a, _RAIter __b, 399 _RAIter __c, _Compare __comp) 400 { 401 if (__comp(*__a, *__b)) 402 if (__comp(*__b, *__c)) 403 return __b; 404 else 405 if (__comp(*__a, *__c)) 406 return __c; 407 else 408 return __a; 409 else 410 { 411 // Just swap __a and __b. 412 if (__comp(*__a, *__c)) 413 return __a; 414 else 415 if (__comp(*__b, *__c)) 416 return __c; 417 else 418 return __b; 419 } 420 } 421 422 #define _GLIBCXX_PARALLEL_ASSERT(_Condition) __glibcxx_assert(_Condition) 423 424 } //namespace __gnu_parallel 425 426 #endif /* _GLIBCXX_PARALLEL_BASE_H */ 427