vSMC  v3.0.0
Scalable Monte Carlo
state_matrix.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/core/state_matrix.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, 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 VSMC_CORE_STATE_MATRIX_HPP
33 #define VSMC_CORE_STATE_MATRIX_HPP
34 
35 #include <vsmc/internal/common.hpp>
37 
38 #define VSMC_RUNTIME_ASSERT_CORE_STATE_MATRIX_UNPACK_SIZE(psize, dim) \
39  VSMC_RUNTIME_ASSERT((psize >= dim), \
40  "**StateMatrix::state_unpack** INPUT PACK SIZE TOO SMALL")
41 
42 namespace vsmc
43 {
44 
45 namespace internal
46 {
47 
48 template <std::size_t Dim>
50 {
51  public:
52  static constexpr std::size_t dim() { return Dim; }
53 
54  protected:
55  void swap(StateMatrixDim<Dim> &) noexcept {}
56 
57  static void set_dim(std::size_t) {}
58 }; // class StateMatrixDim
59 
60 template <>
62 {
63  public:
64  StateMatrixDim() : dim_(0) {}
65 
66  std::size_t dim() const { return dim_; }
67 
68  protected:
69  void swap(StateMatrixDim<Dynamic> &other) noexcept
70  {
71  std::swap(dim_, other.dim_);
72  }
73 
74  void set_dim(std::size_t dim) { dim_ = dim; }
75 
76  private:
77  std::size_t dim_;
78 }; // class StateMatrixDim
79 
80 } // namespace vsmc::internal
81 
84 template <MatrixLayout Layout, std::size_t Dim, typename T>
86 {
87  public:
88  using size_type = std::size_t;
89  using value_type = T;
91 
92  template <typename S>
94  {
95  public:
97  typename Particle<S>::size_type id, Particle<S> *pptr)
98  : SingleParticleBase<S>(id, pptr)
99  {
100  }
101 
102  std::size_t dim() const { return this->particle().state().dim(); }
103 
104  value_type &operator()(std::size_t pos) const
105  {
106  return this->particle().state()(
107  static_cast<size_type>(this->id()), pos);
108  }
109  }; // class single_particle_type
110 
112  size_type size() const { return size_; }
113 
115  void reserve(size_type N) { data_.reserve(N * this->dim()); }
116 
121  void reserve(size_type N, std::size_t dim)
122  {
123  data_.reserve(N * (Dim == Dynamic ? dim : this->dim()));
124  }
125 
126  void shrink_to_fit() { data_.shrink_to_fit(); }
127 
128  value_type *data() { return data_.data(); }
129 
130  const value_type *data() const { return data_.data(); }
131 
132  void swap(StateMatrixBase<Layout, Dim, T> &other) noexcept
133  {
135  std::swap(size_, other.size_);
136  data_.swap(other.data_);
137  }
138 
139  protected:
140  explicit StateMatrixBase(size_type N) : size_(N), data_(N * Dim) {}
141 
142  StateMatrixBase(size_type N, std::size_t dim) : size_(N)
143  {
144  static_assert(Dim == Dynamic, "**StateMatrix::StateMatrix** USED WITH "
145  "AN OBJECT WITH FIXED DIMENSION");
146  resize_data(N, dim);
147  }
148 
150 
152  const StateMatrixBase<Layout, Dim, T> &) = default;
153 
155 
157  StateMatrixBase<Layout, Dim, T> &&other) noexcept
158  {
159  swap(other);
160 
161  return *this;
162  }
163 
164  void resize_data(size_type N, std::size_t dim)
165  {
166  size_ = N;
167  this->set_dim(dim);
168  data_.resize(N * dim);
169  }
170 
171  std::size_t data_size() const { return data_.size(); }
172 
173  friend bool operator==(const StateMatrixBase<Layout, Dim, T> &state1,
174  const StateMatrixBase<Layout, Dim, T> &state2)
175  {
176  if (state1.dim() != state2.dim())
177  return false;
178  if (state1.size_ != state2.size_)
179  return false;
180  if (state1.data_ != state2.data_)
181  return false;
182  return true;
183  }
184 
185  friend bool operator!=(const StateMatrixBase<Layout, Dim, T> &state1,
186  const StateMatrixBase<Layout, Dim, T> &state2)
187  {
188  return !(state1 == state2);
189  }
190 
191  private:
192  size_type size_;
193  Vector<T> data_;
194 }; // class StateMatrixBase
195 
198 template <MatrixLayout Layout, std::size_t Dim, typename T>
200  StateMatrixBase<Layout, Dim, T> &state2) noexcept
201 {
202  state1.swap(state2);
203 }
204 
207 template <std::size_t Dim, typename T>
208 class StateMatrix<RowMajor, Dim, T> : public StateMatrixBase<RowMajor, Dim, T>
209 {
210  public:
215 
217 
219  {
220  }
221 
222  void resize(size_type N) { resize_both(N, this->dim()); }
223 
224  void resize(size_type N, std::size_t dim)
225  {
226  static_assert(Dim == Dynamic, "**StateMatrix::resize** USED WITH AN "
227  "OBJECT WITH FIXED DIMENSION");
228  resize_both(N, dim);
229  }
230 
231  void resize_dim(std::size_t dim)
232  {
233  static_assert(Dim == Dynamic, "**StateMatrix::resize_dim** USED WITH "
234  "AN OBJECT WITH FIXED DIMENSION");
235  resize_both(this->size(), dim);
236  }
237 
238  T &operator()(size_type id, std::size_t pos)
239  {
240  return this->data()[id * this->dim() + pos];
241  }
242 
243  const T &operator()(size_type id, std::size_t pos) const
244  {
245  return this->data()[id * this->dim() + pos];
246  }
247 
248  template <typename OutputIter>
249  OutputIter read_state(std::size_t pos, OutputIter first) const
250  {
251  for (size_type i = 0; i != this->size(); ++i, ++first)
252  *first = operator()(i, pos);
253 
254  return first;
255  }
256 
257  template <typename OutputIter>
258  OutputIter read_state_matrix(MatrixLayout layout, OutputIter first) const
259  {
260  if (layout == RowMajor)
261  first = std::copy_n(this->data(), this->data_size(), first);
262 
263  if (layout == ColMajor)
264  for (std::size_t d = 0; d != this->dim(); ++d)
265  for (size_type i = 0; i != this->size(); ++i, ++first)
266  *first = operator()(i, d);
267 
268  return first;
269  }
270 
272  {
273  return this->data() + id * this->dim();
274  }
275 
276  const value_type *row_data(size_type id) const
277  {
278  return this->data() + id * this->dim();
279  }
280 
291  template <typename IntType, typename InputIter>
292  void select(IntType N, InputIter index)
293  {
294  size_type n = static_cast<size_type>(N);
295  if (this->size() == 0 || internal::is_nullptr(index)) {
296  this->resize(n);
297  return;
298  }
299 
300  if (n > this->size())
301  this->resize(n);
302  for (size_type dst = 0; dst != n; ++dst, ++index)
303  duplicate(static_cast<size_type>(*index), dst);
304  if (n < this->size())
305  this->resize(n);
306 
307  return;
308  }
309 
311  {
312  if (src == dst)
313  return;
314 
315  duplicate_dispatch(src, dst, std::integral_constant < bool,
316  Dim == Dynamic || 8 < Dim > ());
317  }
318 
320  {
321  pack_type pack(this->dim());
322  std::copy(row_data(id), row_data(id) + this->dim(), pack.data());
323 
324  return pack;
325  }
326 
327  void state_unpack(size_type id, const pack_type &pack)
328  {
330  pack.size(), this->dim());
331 
332  const value_type *ptr = pack.data();
333  std::copy(ptr, ptr + this->dim(), row_data(id));
334  }
335 
337  {
339  pack.size(), this->dim());
340 
341  const value_type *ptr = pack.data();
342  std::move(ptr, ptr + this->dim(), row_data(id));
343  }
344 
345  private:
346  void resize_both(size_type N, std::size_t dim)
347  {
348  if (N == this->size() && dim == this->dim())
349  return;
350 
351  if (dim == this->dim()) {
352  this->resize_data(N, dim);
353  return;
354  }
355 
357  tmp.resize_data(N, dim);
358  const size_type K = std::min(N, this->size());
359  const std::size_t D = std::min(dim, this->dim());
360  if (D > 0)
361  for (size_type k = 0; k != K; ++k)
362  std::copy_n(row_data(k), D, tmp.row_data(k));
363  *this = std::move(tmp);
364  }
365 
366  void duplicate_dispatch(size_type src, size_type dst, std::true_type)
367  {
368  std::copy(row_data(src), row_data(src) + this->dim(), row_data(dst));
369  }
370 
371  void duplicate_dispatch(size_type src, size_type dst, std::false_type)
372  {
373  duplicate_pos<0>(row_data(src), row_data(dst),
374  std::integral_constant<bool, 0 < Dim>());
375  }
376 
377  template <std::size_t D>
378  void duplicate_pos(const value_type *, value_type *, std::false_type)
379  {
380  }
381 
382  template <std::size_t D>
383  void duplicate_pos(const value_type *src, value_type *dst, std::true_type)
384  {
385  dst[D] = src[D];
386  duplicate_pos<D + 1>(
387  src, dst, std::integral_constant<bool, D + 1 < Dim>());
388  }
389 }; // class StateMatrix
390 
393 template <std::size_t Dim, typename T>
394 class StateMatrix<ColMajor, Dim, T> : public StateMatrixBase<ColMajor, Dim, T>
395 {
396  public:
401 
403 
405  {
406  }
407 
408  void resize(size_type N) { resize_both(N, this->dim()); }
409 
410  void resize(size_type N, std::size_t dim)
411  {
412  static_assert(Dim == Dynamic, "**StateMatrix::resize** USED WITH AN "
413  "OBJECT WITH FIXED DIMENSION");
414  resize_both(N, dim);
415  }
416 
417  void resize_dim(std::size_t dim)
418  {
419  static_assert(Dim == Dynamic, "**StateMatrix::resize_dim** USED WITH "
420  "AN OBJECT WITH FIXED DIMENSION");
421  resize_both(this->size(), dim);
422  }
423 
424  T &operator()(size_type id, std::size_t pos)
425  {
426  return this->data()[pos * this->size() + id];
427  }
428 
429  const T &operator()(size_type id, std::size_t pos) const
430  {
431  return this->data()[pos * this->size() + id];
432  }
433 
434  template <typename OutputIter>
435  OutputIter read_state(std::size_t pos, OutputIter first) const
436  {
437  return std::copy_n(col_data(pos), this->size(), first);
438  }
439 
440  template <typename OutputIter>
441  OutputIter read_state_matrix(MatrixLayout layout, OutputIter first) const
442  {
443  if (layout == RowMajor)
444  for (size_type i = 0; i != this->size(); ++i)
445  for (std::size_t d = 0; d != this->size(); ++d, ++first)
446  *first = operator()(i, d);
447 
448  if (layout == ColMajor)
449  first = std::copy_n(this->data(), this->data_size(), first);
450 
451  return first;
452  }
453 
454  value_type *col_data(std::size_t pos)
455  {
456  return this->data() + pos * this->size();
457  }
458 
459  const value_type *col_data(std::size_t pos) const
460  {
461  return this->data() + pos * this->size();
462  }
463 
474  template <typename InputIter>
475  void select(size_type N, InputIter index)
476  {
477  size_type n = static_cast<size_type>(N);
478  if (this->size() == 0 || internal::is_nullptr(index)) {
479  this->resize(N);
480  return;
481  }
482 
483  InputIter idx = index;
484  if (n == this->size()) {
485  for (std::size_t d = 0; d != this->dim(); ++d) {
486  idx = index;
487  for (size_type dst = 0; dst != n; ++dst, ++idx) {
488  operator()(dst, d) = operator()(
489  static_cast<size_type>(*idx), d);
490  }
491  }
492  } else {
494  tmp.resize_data(N, this->dim());
495  for (std::size_t d = 0; d != this->dim(); ++d) {
496  idx = index;
497  for (size_type dst = 0; dst != n; ++dst, ++idx)
498  tmp(dst, d) = operator()(static_cast<size_type>(*idx), d);
499  }
500  *this = std::move(tmp);
501  }
502 
503  return;
504  }
505 
507  {
508  if (src == dst)
509  return;
510 
511  duplicate_dispatch(src, dst, std::integral_constant < bool,
512  Dim == Dynamic || 8 < Dim > ());
513  }
514 
516  {
517  pack_type pack(this->dim());
518  for (std::size_t d = 0; d != this->dim(); ++d)
519  pack[d] = operator()(id, d);
520 
521  return pack;
522  }
523 
524  void state_unpack(size_type id, const pack_type &pack)
525  {
527  pack.size(), this->dim());
528 
529  for (std::size_t d = 0; d != this->dim(); ++d)
530  operator()(id, d) = pack[d];
531  }
532 
534  {
536  pack.size(), this->dim());
537 
538  for (std::size_t d = 0; d != this->dim(); ++d)
539  operator()(id, d) = std::move(pack[d]);
540  }
541 
542  private:
543  void resize_both(size_type N, std::size_t dim)
544  {
545  if (N == this->size() && dim == this->dim())
546  return;
547 
548  if (N == this->size()) {
549  this->resize_data(N, dim);
550  return;
551  }
552 
554  tmp.resize_data(N, dim);
555  const size_type K = std::min(N, this->size());
556  const std::size_t D = std::min(dim, this->dim());
557  if (K > 0)
558  for (std::size_t d = 0; d != D; ++d)
559  std::copy_n(col_data(d), K, tmp.col_data(d));
560  *this = std::move(tmp);
561  }
562 
563  void duplicate_dispatch(size_type src, size_type dst, std::true_type)
564  {
565  for (std::size_t d = 0; d != this->dim(); ++d)
566  operator()(dst, d) = operator()(src, d);
567  }
568 
569  void duplicate_dispatch(size_type src, size_type dst, std::false_type)
570  {
571  duplicate_pos<0>(this->data() + src, this->data() + dst,
572  std::integral_constant<bool, 0 < Dim>());
573  }
574 
575  template <std::size_t D>
576  void duplicate_pos(const value_type *, value_type *, std::false_type)
577  {
578  }
579 
580  template <std::size_t D>
581  void duplicate_pos(const value_type *src, value_type *dst, std::true_type)
582  {
583  dst[D * this->size()] = src[D * this->size()];
584  duplicate_pos<D + 1>(
585  src, dst, std::integral_constant<bool, D + 1 < Dim>());
586  }
587 }; // class StateMatrix
588 
589 } // namespace vsmc
590 
591 #endif // VSMC_CORE_STATE_MATRIX_HPP
single_particle_type(typename Particle< S >::size_type id, Particle< S > *pptr)
Definition: monitor.hpp:48
StateMatrix(size_type N, std::size_t dim)
Particle class representing the whole particle set.
Definition: particle.hpp:83
void state_unpack(size_type id, const pack_type &pack)
void select(IntType N, InputIter index)
Copy particles.
Particle::value_type subtype.
Base type of StateMatrix.
pack_type state_pack(size_type id) const
MatrixLayout
Matrix layout.
Definition: defines.hpp:51
OutputIter read_state(std::size_t pos, OutputIter first) const
size_type size() const
The numbrer of particles.
void duplicate(size_type src, size_type dst)
friend bool operator==(const StateMatrixBase< Layout, Dim, T > &state1, const StateMatrixBase< Layout, Dim, T > &state2)
typename state_matrix_base_type::size_type size_type
void state_unpack(size_type id, pack_type &&pack)
const value_type * row_data(size_type id) const
typename state_matrix_base_type::pack_type pack_type
void duplicate(size_type src, size_type dst)
pack_type state_pack(size_type id) const
void state_unpack(size_type id, pack_type &&pack)
typename state_matrix_base_type::pack_type pack_type
static constexpr std::size_t dim()
OutputIter read_state_matrix(MatrixLayout layout, OutputIter first) const
value_type * col_data(std::size_t pos)
value_type * row_data(size_type id)
typename state_matrix_base_type::value_type value_type
void reserve(size_type N, std::size_t dim)
Reserve space for specified number of particles and dimensions.
Particle::value_type subtype.
const T & operator()(size_type id, std::size_t pos) const
void resize_data(size_type N, std::size_t dim)
StateMatrixBase(size_type N)
StateMatrix(size_type N, std::size_t dim)
StateMatrixBase(size_type N, std::size_t dim)
void reserve(size_type N)
Reserve space for specified number of particles.
void state_unpack(size_type id, const pack_type &pack)
T & operator()(size_type id, std::size_t pos)
A thin wrapper over a complete Particle.
void swap(StateMatrixBase< Layout, Dim, T > &other) noexcept
std::size_t data_size() const
void resize(size_type N, std::size_t dim)
void swap(StateMatrixDim< Dim > &) noexcept
bool is_nullptr(T ptr, std::true_type)
Definition: basic.hpp:131
const value_type * data() const
value_type & operator()(std::size_t pos) const
friend bool operator!=(const StateMatrixBase< Layout, Dim, T > &state1, const StateMatrixBase< Layout, Dim, T > &state2)
OutputIter read_state_matrix(MatrixLayout layout, OutputIter first) const
#define VSMC_RUNTIME_ASSERT_CORE_STATE_MATRIX_UNPACK_SIZE(psize, dim)
StateMatrixBase< Layout, Dim, T > & operator=(StateMatrixBase< Layout, Dim, T > &&other) noexcept
typename state_matrix_base_type::value_type value_type
void swap(StateMatrixDim< Dynamic > &other) noexcept
T & operator()(size_type id, std::size_t pos)
OutputIter read_state(std::size_t pos, OutputIter first) const
void resize(size_type N, std::size_t dim)
const T & operator()(size_type id, std::size_t pos) const
const value_type * col_data(std::size_t pos) const
static void set_dim(std::size_t)
void select(size_type N, InputIter index)
Copy particles.
void swap(StateMatrixBase< Layout, Dim, T > &state1, StateMatrixBase< Layout, Dim, T > &state2) noexcept
Swap two StateMatrixBase objects.
typename state_matrix_base_type::size_type size_type