]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/parallel/random_shuffle.h
Licensing changes to GPLv3 resp. GPLv3 with GCC Runtime Exception.
[thirdparty/gcc.git] / libstdc++-v3 / include / parallel / random_shuffle.h
index 663962b43f326c5824883c3e7678eb150a8ee5f7..6e0ebef1523e8dab39d924418e4e99ec97c23f82 100644 (file)
@@ -1,11 +1,11 @@
 // -*- C++ -*-
 
-// Copyright (C) 2007 Free Software Foundation, Inc.
+// Copyright (C) 2007, 2008, 2009 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
+// Foundation; either version 3, or (at your option) any later
 // version.
 
 // This library is distributed in the hope that it will be useful, but
 // 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, 59 Temple Place - Suite 330, Boston,
-// MA 02111-1307, USA.
-
-// As a special exception, you may use this file as part of a free
-// software library without restriction.  Specifically, if other files
-// instantiate templates or use macros or inline functions from this
-// file, or you compile this file and link it with other files to
-// produce an executable, this file does not by itself cause the
-// resulting executable to be covered by the GNU General Public
-// License.  This exception does not however invalidate any other
-// reasons why the executable file might be covered by the GNU General
-// Public License.
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
 
 /** @file parallel/random_shuffle.h
  *  @brief Parallel implementation of std::random_shuffle().
@@ -124,7 +118,7 @@ template<typename RandomNumberGenerator>
 /** @brief Random shuffle code executed by each thread.
   *  @param pus Array of thread-local data records. */
 template<typename RandomAccessIterator, typename RandomNumberGenerator>
-  inline void 
+  void 
   parallel_random_shuffle_drs_pu(DRSSorterPU<RandomAccessIterator,
                                  RandomNumberGenerator>* pus)
   {
@@ -213,8 +207,8 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
         thread_index_t target_p = bin_proc[target_bin];
 
         // Last column [d->num_threads] stays unchanged.
-        ::new(&(temporaries[target_p][dist[target_bin + 1]++])) value_type(
-              *(source + i + start));
+        ::new(&(temporaries[target_p][dist[target_bin + 1]++]))
+           value_type(*(source + i + start));
       }
 
     delete[] oracles;
@@ -237,7 +231,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
             ((b == d->bins_begin) ? 0 : sd->dist[b][d->num_threads]));
       }
 
-    delete[] sd->temporaries[iam];
+    ::operator delete(sd->temporaries[iam]);
   }
 
 /** @brief Round up to the next greater power of 2.
@@ -249,7 +243,7 @@ template<typename T>
     if (x <= 1)
       return 1;
     else
-      return (T)1 << (log2(x - 1) + 1);
+      return (T)1 << (__log2(x - 1) + 1);
   }
 
 /** @brief Main parallel random shuffle step.
@@ -260,13 +254,13 @@ template<typename T>
   *  @param rng Random number generator to use.
   */
 template<typename RandomAccessIterator, typename RandomNumberGenerator>
-  inline void
-  parallel_random_shuffle_drs(
-      RandomAccessIterator begin,
-      RandomAccessIterator end,
-      typename std::iterator_traits<RandomAccessIterator>::difference_type n,
-      thread_index_t num_threads,
-      RandomNumberGenerator& rng)
+  void
+  parallel_random_shuffle_drs(RandomAccessIterator begin,
+                             RandomAccessIterator end,
+                             typename std::iterator_traits
+                             <RandomAccessIterator>::difference_type n,
+                             thread_index_t num_threads,
+                             RandomNumberGenerator& rng)
   {
     typedef std::iterator_traits<RandomAccessIterator> traits_type;
     typedef typename traits_type::value_type value_type;
@@ -274,6 +268,8 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
 
     _GLIBCXX_CALL(n)
 
+    const _Settings& __s = _Settings::get();
+
     if (num_threads > n)
       num_threads = static_cast<thread_index_t>(n);
 
@@ -284,7 +280,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
 
     // Must fit into L1.
     num_bins_cache = std::max<difference_type>(
-        1, n / (Settings::L1_cache_size_lb / sizeof(value_type)));
+        1, n / (__s.L1_cache_size_lb / sizeof(value_type)));
     num_bins_cache = round_up_to_pow2(num_bins_cache);
 
     // No more buckets than TLB entries, power of 2
@@ -293,7 +289,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
 
 #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB
     // 2 TLB entries needed per bin.
-    num_bins = std::min<difference_type>(Settings::TLB_size / 2, num_bins);
+    num_bins = std::min<difference_type>(__s.TLB_size / 2, num_bins);
 #endif
     num_bins = round_up_to_pow2(num_bins);
 
@@ -303,7 +299,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
         // Now try the L2 cache
         // Must fit into L2
         num_bins_cache = static_cast<bin_index>(std::max<difference_type>(
-            1, n / (Settings::L2_cache_size / sizeof(value_type))));
+            1, n / (__s.L2_cache_size / sizeof(value_type))));
         num_bins_cache = round_up_to_pow2(num_bins_cache);
 
         // No more buckets than TLB entries, power of 2.
@@ -313,7 +309,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
 #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB
         // 2 TLB entries needed per bin.
         num_bins = std::min(
-            static_cast<difference_type>(Settings::TLB_size / 2), num_bins);
+            static_cast<difference_type>(__s.TLB_size / 2), num_bins);
 #endif
           num_bins = round_up_to_pow2(num_bins);
 #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1
@@ -331,6 +327,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
 
 #   pragma omp parallel num_threads(num_threads)
       {
+        thread_index_t num_threads = omp_get_num_threads();
 #       pragma omp single
           {
             pus = new DRSSorterPU<RandomAccessIterator, random_number>
@@ -349,7 +346,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
             starts = sd.starts = new difference_type[num_threads + 1];
             int bin_cursor = 0;
             sd.num_bins = num_bins;
-            sd.num_bits = log2(num_bins);
+            sd.num_bits = __log2(num_bins);
 
             difference_type chunk_length = n / num_threads,
                             split = n % num_threads, start = 0;
@@ -373,9 +370,9 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
               }
             starts[num_threads] = start;
           } //single
-      // Now shuffle in parallel.
-      parallel_random_shuffle_drs_pu(pus);
-    }
+        // Now shuffle in parallel.
+        parallel_random_shuffle_drs_pu(pus);
+      }  // parallel
 
     delete[] starts;
     delete[] sd.bin_proc;
@@ -393,7 +390,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
  *  @param rng Random number generator to use.
  */
 template<typename RandomAccessIterator, typename RandomNumberGenerator>
-  inline void
+  void
   sequential_random_shuffle(RandomAccessIterator begin, 
                             RandomAccessIterator end,
                             RandomNumberGenerator& rng)
@@ -403,6 +400,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
     typedef typename traits_type::difference_type difference_type;
 
     difference_type n = end - begin;
+    const _Settings& __s = _Settings::get();
 
     bin_index num_bins, num_bins_cache;
 
@@ -410,7 +408,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
     // Try the L1 cache first, must fit into L1.
     num_bins_cache =
         std::max<difference_type>
-            (1, n / (Settings::L1_cache_size_lb / sizeof(value_type)));
+            (1, n / (__s.L1_cache_size_lb / sizeof(value_type)));
     num_bins_cache = round_up_to_pow2(num_bins_cache);
 
     // No more buckets than TLB entries, power of 2
@@ -418,7 +416,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
     num_bins = std::min(n, (difference_type)num_bins_cache);
 #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB
     // 2 TLB entries needed per bin
-    num_bins = std::min((difference_type)Settings::TLB_size / 2, num_bins);
+    num_bins = std::min((difference_type)__s.TLB_size / 2, num_bins);
 #endif
     num_bins = round_up_to_pow2(num_bins);
 
@@ -428,7 +426,7 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
         // Now try the L2 cache, must fit into L2.
         num_bins_cache =
             static_cast<bin_index>(std::max<difference_type>(
-                1, n / (Settings::L2_cache_size / sizeof(value_type))));
+                1, n / (__s.L2_cache_size / sizeof(value_type))));
         num_bins_cache = round_up_to_pow2(num_bins_cache);
 
         // No more buckets than TLB entries, power of 2
@@ -439,14 +437,14 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
 #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB
         // 2 TLB entries needed per bin
         num_bins =
-            std::min<difference_type>(Settings::TLB_size / 2, num_bins);
+            std::min<difference_type>(__s.TLB_size / 2, num_bins);
 #endif
         num_bins = round_up_to_pow2(num_bins);
 #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1
       }
 #endif
 
-    int num_bits = log2(num_bins);
+    int num_bits = __log2(num_bins);
 
     if (num_bins > 1)
       {
@@ -487,10 +485,13 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
                                       rng);
           }
 
+        // Copy elements back.
+        std::copy(target, target + n, begin);
+
         delete[] dist0;
         delete[] dist1;
         delete[] oracles;
-        delete[] target;
+        ::operator delete(target);
       }
     else
       __gnu_sequential::random_shuffle(begin, end, rng);
@@ -515,4 +516,4 @@ template<typename RandomAccessIterator, typename RandomNumberGenerator>
 
 }
 
-#endif
+#endif /* _GLIBCXX_PARALLEL_RANDOM_SHUFFLE_H */