OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
SortingPairBuilder.h
Go to the documentation of this file.
1 #ifndef SORTING_PAIR_BUILDER_H
2 #define SORTING_PAIR_BUILDER_H
3 
4 #include <algorithm>
5 
6 //predicate used to sort index array with std::sort
7 template<class A>
8 struct ProxyPred_t
9 {
10  ProxyPred_t(const A &a, unsigned d) : array(a), dim(d) { }
11 
12  template<class T>
13  bool operator()(const T &a, const T &b)
14  { return array[a][dim] < array[b][dim]; }
15 
16  unsigned dim;
17  const A &array;
18 };
19 
20 //simplifies usage by allowing the omission of the template parameter
21 template<class A>
22 ProxyPred_t<A> ProxyPred(const A &a, unsigned d)
23 {
24  return ProxyPred_t<A>(a, d);
25 }
26 
27 template<class PBase>
29 {
30 public:
31  enum { Dim = PBase::Dim };
32  typedef typename PBase::Position_t Position_t;
33 
34  SortingPairBuilder(PBase &p) : particles(p) { }
35 
36  template<class Pred, class OP>
37  void for_each(const Pred& pred, const OP &op)
38  {
39  std::size_t size = particles.getLocalNum()+particles.getGhostNum();
40 
41  Position_t mean[Dim];
42  Position_t variance[Dim];
43 
44  //calculate mean position
45  std::fill(mean, mean+Dim, 0);
46  for(std::size_t i = 0;i<size;++i)
47  for(int d = 0;d<Dim;++d)
48  mean[d] += particles.R[i][d];
49 
50  for(int d = 0;d<Dim;++d)
51  mean[d] /= size;
52 
53  //calculate variance for each dimension
54  std::fill(variance, variance+Dim, 0);
55  for(std::size_t i = 0;i<size;++i)
56  for(int d = 0;d<Dim;++d)
57  variance[d] += (mean[d]-particles.R[i][d])*(mean[d]-particles.R[i][d]);
58 
59  int dimension = 0;
60  int var = variance[0];
61  for(int d = 1;d<Dim;++d)
62  if(variance[d]>var)
63  {
64  dimension = d;
65  var = variance[d];
66  }
67 
68  //sort index array
69  std::size_t *indices = new std::size_t[size];
70  for(std::size_t i = 0;i<size;++i)
71  indices[i] = i;
72 
73  std::sort(indices, indices+size, ProxyPred(particles.R, dimension));
74 
75  for(std::size_t i = 0;i<size;++i)
76  for(std::size_t j = i+1;j<size;++j)
77  if(pred(particles.R[indices[i]], particles.R[indices[j]]))
78  op(indices[i], indices[j], particles);
79  else if(particles.R[indices[j]][dimension] - particles.R[indices[i]][dimension]
80  > pred.getRange(dimension))
81  break;
82  }
83 private:
84  PBase &particles;
85 };
86 
87 #endif
ProxyPred_t< A > ProxyPred(const A &a, unsigned d)
Definition: rbendmap.h:8
Position_t
Definition: Types.h:28
void for_each(const Pred &pred, const OP &op)
PBase::Position_t Position_t
const unsigned Dim
ProxyPred_t(const A &a, unsigned d)
bool operator()(const T &a, const T &b)