GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
shuffle.hpp
1 /**
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 #ifndef GRAPHLAB_INPLACE_SHUFFLE_HPP
25 #define GRAPHLAB_INPLACE_SHUFFLE_HPP
26 #include <algorithm>
27 #include <vector>
28 #include <cassert>
29 #include <iterator>
30 
31 #ifndef __NO_OPENMP__
32 #include <omp.h>
33 #endif
34 
35 
36 
37 namespace graphlab {
38 /**
39  * Shuffles a random access container inplace such at
40  * newcont[i] = cont[targets[i]]
41  * targets must be the same size as the container
42  * Both the container and the targets vector will be modified.
43  */
44 template <typename Iterator, typename sizetype>
45 void inplace_shuffle(Iterator begin,
46  Iterator end,
47  std::vector<sizetype> &targets) {
48  size_t len = std::distance(begin, end);
49  assert(len == targets.size());
50 
51  for (size_t i = 0;i < len; ++i) {
52  // begin the permutation cycle
53  if (i != targets[i]) {
54  typename std::iterator_traits<Iterator>::value_type v = *(begin + i);
55  size_t j = i;
56  while(j != targets[j]) {
57  size_t next = targets[j];
58  if (next != i) {
59  *(begin + j) = *(begin + next);
60  targets[j] = j;
61  j = next;
62  }
63  else {
64  // end of cycle
65  *(begin + j) = v;
66  targets[j] = j;
67  break;
68  }
69  }
70  }
71  }
72 }
73 
74 /**
75  * Shuffles a random access container inplace such at
76  * newcont[i] = cont[targets[i]]
77  * targets must be the same size as the container
78  */
79 template <typename Container, typename sizetype>
80 void outofplace_shuffle(Container &c,
81  const std::vector<sizetype> &targets) {
82  Container result(targets.size());
83 #ifdef _OPENMP
84 #pragma omp parallel for
85 #endif
86  for (ssize_t i = 0;i < ssize_t(targets.size()); ++i) {
87  result[i] = c[targets[i]];
88  }
89  std::swap(c, result);
90 }
91 
92 }
93 #endif