MCKL
Monte Carlo Kernel Library
particle.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/core/particle.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_CORE_PARTICLE_HPP
33 #define MCKL_CORE_PARTICLE_HPP
34 
35 #include <mckl/internal/common.hpp>
36 #include <mckl/core/is_equal.hpp>
37 #include <mckl/core/iterator.hpp>
38 #include <mckl/core/weight.hpp>
39 #include <mckl/random/rng_set.hpp>
40 #include <mckl/random/seed.hpp>
41 
42 namespace mckl {
43 
44 template <typename>
45 class Particle;
46 
49 template <typename T>
51 {
52  public:
53  ParticleIndexBase() : pptr_(nullptr), i_(0) {}
54 
56  : pptr_(pptr), i_(i)
57  {
58  }
59 
60  Particle<T> &particle() const { return *pptr_; }
61 
62  Particle<T> *particle_ptr() const { return pptr_; }
63 
64  T &state() const { return pptr_->state(); }
65 
66  typename Particle<T>::size_type i() const { return i_; }
67 
68  typename Particle<T>::rng_type &rng() const { return pptr_->rng(i_); }
69 
70  private:
71  Particle<T> *pptr_;
72  typename Particle<T>::size_type i_;
73 }; // class ParticleIndexBase
74 
79 
80 template <typename T>
86 class ParticleIndex final : public ParticleIndexBaseType<T>
87 {
88  public:
89  using difference_type =
90  std::make_signed_t<typename Particle<T>::size_type>;
92  using pointer = const ParticleIndex *;
93  using reference = const ParticleIndex &;
94  using iterator_category = std::random_access_iterator_tag;
95 
96  ParticleIndex() = default;
97 
99  : ParticleIndexBaseType<T>(i, pptr)
100  {
101  }
102 
104  reference operator*() const noexcept { return *this; }
105 
107  pointer operator->() const noexcept { return this; }
108 
110  template <typename IntType>
112  {
113  return ParticleIndex(static_cast<typename Particle<T>::size_type>(
114  static_cast<difference_type>(this->i()) +
115  static_cast<difference_type>(n)),
116  this->particle_ptr());
117  }
118 
119  friend bool operator==(
120  const ParticleIndex &idx1, const ParticleIndex &idx2)
121  {
122  runtime_assert(idx1.particle_ptr() == idx2.particle_ptr(),
123  "Compare two ParticleIndex objects from two different particle "
124  "systems");
125 
126  return idx1.i() == idx2.i();
127  }
128 
129  friend bool operator!=(
130  const ParticleIndex &idx1, const ParticleIndex &idx2)
131  {
132  runtime_assert(idx1.particle_ptr() == idx2.particle_ptr(),
133  "Compare two ParticleIndex objects from two different particle "
134  "systems");
135 
136  return idx1.i() != idx2.i();
137  }
138 
139  friend bool operator<(const ParticleIndex &idx1, const ParticleIndex &idx2)
140  {
141  runtime_assert(idx1.particle_ptr() == idx2.particle_ptr(),
142  "Compare two ParticleIndex objects from two different particle "
143  "systems");
144 
145  return idx1.i() < idx2.i();
146  }
147 
148  friend bool operator>(const ParticleIndex &idx1, const ParticleIndex &idx2)
149  {
150  runtime_assert(idx1.particle_ptr() == idx2.particle_ptr(),
151  "Compare two ParticleIndex objects from two different particle "
152  "systems");
153 
154  return idx1.i() > idx2.i();
155  }
156 
157  friend bool operator<=(
158  const ParticleIndex &idx1, const ParticleIndex &idx2)
159  {
160  runtime_assert(idx1.particle_ptr() == idx2.particle_ptr(),
161  "Compare two ParticleIndex objects from two different particle "
162  "systems");
163 
164  return idx1.i() <= idx2.i();
165  }
166 
167  friend bool operator>=(
168  const ParticleIndex &idx1, const ParticleIndex &idx2)
169  {
170  runtime_assert(idx1.particle_ptr() == idx2.particle_ptr(),
171  "Compare two ParticleIndex objects from two different particle "
172  "systems");
173 
174  return idx1.i() >= idx2.i();
175  }
176 
178  {
179  return idx = ParticleIndex(idx.i() + 1, idx.particle_ptr());
180  }
181 
183  {
184  ParticleIndex ret(idx);
185  ++idx;
186 
187  return ret;
188  }
189 
191  {
192  return idx = ParticleIndex(idx.i() - 1, idx.particle_ptr());
193  }
194 
196  {
197  ParticleIndex ret(idx);
198  --idx;
199 
200  return ret;
201  }
202 
203  template <typename IntType>
204  friend ParticleIndex operator+(const ParticleIndex &idx, IntType n)
205  {
206  return ParticleIndex(static_cast<typename Particle<T>::size_type>(
207  static_cast<difference_type>(idx.i()) +
208  static_cast<difference_type>(n)),
209  idx.particle_ptr());
210  }
211 
212  template <typename IntType>
213  friend ParticleIndex operator+(IntType n, const ParticleIndex &idx)
214  {
215  return idx + n;
216  }
217 
218  template <typename IntType>
219  friend ParticleIndex operator-(const ParticleIndex &idx, IntType n)
220  {
221  return idx + (-static_cast<difference_type>(n));
222  }
223 
224  template <typename IntType>
225  friend ParticleIndex &operator+=(ParticleIndex &idx, IntType n)
226  {
227  return idx = idx + n;
228  }
229 
230  template <typename IntType>
231  friend ParticleIndex &operator-=(ParticleIndex &idx, IntType n)
232  {
233  return idx = idx - n;
234  }
235 
237  const ParticleIndex &idx1, const ParticleIndex &idx2)
238  {
239  runtime_assert(idx1.particle_ptr() == idx2.particle_ptr(),
240  "Substract two ParticleIndex objects from two different "
241  "particle systems");
242 
243  return static_cast<difference_type>(idx1.i()) -
244  static_cast<difference_type>(idx2.i());
245  }
246 }; // class ParticleIndex
247 
250 template <typename T>
251 class ParticleRange : public Range<ParticleIndex<T>>
252 {
253  public:
255 
256  Particle<T> &particle() const { return this->begin()->particle(); }
257 
258  Particle<T> *particle_ptr() const { return this->begin()->particle_ptr(); }
259 
261  {
262  return this->begin()->i();
263  }
264 
265  typename Particle<T>::size_type iend() const { return this->end()->i(); }
266 }; // class ParticleRange
267 
278 template <typename T>
279 class Particle
280 {
281  public:
283  using state_type = T;
286  using rng_type = typename rng_set_type::rng_type;
287 
290  : weight_(0), rng_set_(0), rng_(Seed<rng_type>::instance().get())
291  {
292  }
293 
298  template <typename... Args>
299  explicit Particle(size_type N, Args &&... args)
300  : state_(N, std::forward<Args>(args)...)
301  , weight_(static_cast<SizeType<weight_type>>(N))
302  , rng_set_(static_cast<SizeType<rng_set_type>>(N))
303  , rng_(Seed<rng_type>::instance().get())
304  {
305  }
306 
308  Particle clone() const
309  {
310  Particle particle(*this);
311  particle.rng_set_.reset();
312  particle.rng_.seed(Seed<rng_type>::instance().get());
313 
314  return particle;
315  }
316 
318  size_type size() const { return state_.size(); }
319 
324  template <typename InputIter>
325  void select(size_type n, InputIter index)
326  {
327  state_.select(n, index);
328  weight_.resize(static_cast<SizeType<weight_type>>(n));
329  weight_.set_equal();
330  rng_set_.resize(static_cast<SizeType<rng_set_type>>(n));
331  }
332 
334  state_type &state() { return state_; }
335 
337  const state_type &state() const { return state_; }
338 
340  weight_type &weight() { return weight_; }
341 
343  const weight_type &weight() const { return weight_; }
344 
346  rng_set_type &rng_set() { return rng_set_; }
347 
349  const rng_set_type &rng_set() const { return rng_set_; }
350 
353  {
354  return rng_set_[static_cast<std::size_t>(i)];
355  }
356 
358  const rng_type &rng(size_type i) const
359  {
360  return rng_set_[static_cast<std::size_t>(i)];
361  }
362 
364  rng_type &rng() { return rng_; }
365 
367  const rng_type &rng() const { return rng_; }
368 
371  {
372  runtime_assert<std::out_of_range>(
373  i <= size(), "**Particle::at** index out of range");
374 
375  return operator[](i);
376  }
377 
380  {
381  return ParticleIndex<T>(i, this);
382  }
383 
385  ParticleIndex<T> begin() { return operator[](0); }
386 
388  ParticleIndex<T> end() { return operator[](size()); }
389 
392  {
393  return ParticleRange<T>(begin(), end(), grainsize);
394  }
395 
399  size_type ibegin, size_type iend, size_type grainsize = 1)
400  {
401  return ParticleRange<T>(operator[](ibegin), operator[](iend),
402  grainsize);
403  }
404 
405  friend bool operator==(const Particle &p1, const Particle &p2)
406  {
407  return p1.weight_ == p2.weight_ && p1.state_ == p2.state_;
408  }
409 
410  friend bool operator!=(const Particle &p1, const Particle &p2)
411  {
412  return !(p1 == p2);
413  }
414 
415  private:
416  state_type state_;
417  weight_type weight_;
418  rng_set_type rng_set_;
419  rng_type rng_;
420 }; // class Particle
421 
422 template <typename T>
423 inline bool is_equal(const Particle<T> &p1, const Particle<T> &p2)
424 {
425  return is_equal(p1.weight(), p2.weight()) &&
426  is_equal(p1.state(), p2.state());
427 }
428 
429 } // namespace mckl
430 
431 #endif // MCKL_CORE_PARTICLE_HPP
std::random_access_iterator_tag iterator_category
Definition: particle.hpp:94
friend difference_type operator-(const ParticleIndex &idx1, const ParticleIndex &idx2)
Definition: particle.hpp:236
friend bool operator<=(const ParticleIndex &idx1, const ParticleIndex &idx2)
Definition: particle.hpp:157
friend bool operator==(const Particle &p1, const Particle &p2)
Definition: particle.hpp:405
const rng_type & rng(size_type i) const
Get an (parallel) RNG stream for a given particle.
Definition: particle.hpp:358
Particle< T >::size_type i() const
Definition: particle.hpp:66
void select(size_type n, InputIter index)
Resize by selecting according to user supplied index vector.
Definition: particle.hpp:325
typename WeightTypeTrait< T >::type WeightType
Definition: weight.hpp:232
Particle()
Default constructor.
Definition: particle.hpp:289
friend ParticleIndex operator--(ParticleIndex &idx, int)
Definition: particle.hpp:195
friend ParticleIndex operator-(const ParticleIndex &idx, IntType n)
Definition: particle.hpp:219
friend bool operator>=(const ParticleIndex &idx1, const ParticleIndex &idx2)
Definition: particle.hpp:167
STL namespace.
rng_type & rng(size_type i)
Get an (parallel) RNG stream for a given particle.
Definition: particle.hpp:352
rng_type & rng()
Get the (sequential) RNG used stream for resampling.
Definition: particle.hpp:364
ParticleIndex< T > end()
Get a ParticleIndex<T> object for one pass the last particle.
Definition: particle.hpp:388
ParticleIndex operator[](IntType n)
Subscript operator return a new index.
Definition: particle.hpp:111
#define MCKL_DEFINE_TYPE_TEMPLATE_DISPATCH_TRAIT(Outer, Inner, Default)
Definition: traits.hpp:101
friend ParticleIndex & operator+=(ParticleIndex &idx, IntType n)
Definition: particle.hpp:225
typename RNGSetTypeTrait< T >::type RNGSetType
Definition: rng_set.hpp:177
Particle clone() const
Clone the Particle except the RNG engines.
Definition: particle.hpp:308
Range of ParticleIndex.
Definition: particle.hpp:251
rng_set_type & rng_set()
Read and write access to the RNG collection object.
Definition: particle.hpp:346
friend bool operator>(const ParticleIndex &idx1, const ParticleIndex &idx2)
Definition: particle.hpp:148
const weight_type & weight() const
Read only access to the weight collection object.
Definition: particle.hpp:343
ParticleRange< T > range(size_type ibegin, size_type iend, size_type grainsize=1)
Get a ParticleRange<T> object given a range denoted by integral values.
Definition: particle.hpp:398
friend ParticleIndex & operator--(ParticleIndex &idx)
Definition: particle.hpp:190
friend bool operator<(const ParticleIndex &idx1, const ParticleIndex &idx2)
Definition: particle.hpp:139
Particle< T > & particle() const
Definition: particle.hpp:256
friend bool operator!=(const Particle &p1, const Particle &p2)
Definition: particle.hpp:410
weight_type & weight()
Read and write access to the weight collection object.
Definition: particle.hpp:340
pointer operator->() const noexcept
Member selection operator returns a pointer the index itself.
Definition: particle.hpp:107
typename rng_set_type::rng_type rng_type
Definition: particle.hpp:286
ParticleIndex< T > begin()
Get a ParticleIndex<T> object for the first particle.
Definition: particle.hpp:385
Particle(size_type N, Args &&... args)
Construct a particle system.
Definition: particle.hpp:299
Particle< T > * particle_ptr() const
Definition: particle.hpp:258
const state_type & state() const
Read only access to the state collection object.
Definition: particle.hpp:337
Particle< T > & particle() const
Definition: particle.hpp:60
ParticleRange< T > range(size_type grainsize=1)
Get a Range<ParticleItrator<T>> object of all particles.
Definition: particle.hpp:391
reference operator*() const noexcept
Dereference operator returns a reference to the index itself.
Definition: particle.hpp:104
friend bool operator==(const ParticleIndex &idx1, const ParticleIndex &idx2)
Definition: particle.hpp:119
ParticleIndexBase(typename Particle< T >::size_type i, Particle< T > *pptr)
Definition: particle.hpp:55
size_type size() const
The number of particles.
Definition: particle.hpp:318
friend ParticleIndex & operator-=(ParticleIndex &idx, IntType n)
Definition: particle.hpp:231
friend ParticleIndex operator+(const ParticleIndex &idx, IntType n)
Definition: particle.hpp:204
SizeType< T > size_type
Definition: particle.hpp:282
ParticleIndex(typename Particle< T >::size_type i, Particle< T > *pptr)
Definition: particle.hpp:98
Definition: mcmc.hpp:40
state_type & state()
Read and write access to the state collection object.
Definition: particle.hpp:334
friend bool operator!=(const ParticleIndex &idx1, const ParticleIndex &idx2)
Definition: particle.hpp:129
friend ParticleIndex operator++(ParticleIndex &idx, int)
Definition: particle.hpp:182
Particle< T >::size_type iend() const
Definition: particle.hpp:265
A thin wrapper over a complete Particle.
Definition: particle.hpp:86
bool is_equal(const float &v1, const float &v2)
Definition: is_equal.hpp:41
const rng_type & rng() const
Get the (sequential) RNG used stream for resampling.
Definition: particle.hpp:367
Particle< T >::rng_type & rng() const
Definition: particle.hpp:68
const rng_set_type & rng_set() const
Read only access to the RNG collection object.
Definition: particle.hpp:349
ParticleIndex< T > at(size_type i)
Get a ParticleIndex<T> object for the i-th particle.
Definition: particle.hpp:370
friend ParticleIndex operator+(IntType n, const ParticleIndex &idx)
Definition: particle.hpp:213
Particle system.
Definition: particle.hpp:45
ParticleIndex< T > operator[](size_type i)
Get a ParticleIndex<T> object for the i-th particle.
Definition: particle.hpp:379
RNG default seed generator.
Definition: seed.hpp:339
A thin wrapper over a complete Particle.
Definition: particle.hpp:50
Particle< T > * particle_ptr() const
Definition: particle.hpp:62
std::make_signed_t< typename Particle< T >::size_type > difference_type
Definition: particle.hpp:90
void runtime_assert(bool cond, const char *msg, bool soft=false)
Definition: assert.hpp:65
Particle< T >::size_type ibegin() const
Definition: particle.hpp:260
friend ParticleIndex & operator++(ParticleIndex &idx)
Definition: particle.hpp:177
typename SizeTypeTrait< T >::type SizeType
Definition: traits.hpp:166