vSMC
vSMC: Scalable Monte Carlo
covariance.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/utility/covariance.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_UTILITY_COVARIANCE_HPP
33 #define VSMC_UTILITY_COVARIANCE_HPP
34 
35 #include <vsmc/internal/common.hpp>
36 #if VSMC_USE_MKL_VSL
37 #include <vsmc/utility/mkl.hpp>
38 #endif
39 
40 namespace vsmc
41 {
42 
43 namespace internal
44 {
45 
46 template <typename RealType>
47 inline void cov_pack(std::size_t dim, const RealType *cov, RealType *chol,
48  MatrixLayout layout, bool upper, bool packed)
49 {
50  unsigned l = layout == RowMajor ? 0 : 1;
51  unsigned u = upper ? 1 : 0;
52  unsigned p = packed ? 1 : 0;
53  unsigned c = (l << 2) + (u << 1) + p;
54  switch (c) {
55  case 0: // Row, Lower, Full
56  for (std::size_t i = 0; i != dim; ++i)
57  for (std::size_t j = 0; j <= i; ++j)
58  *chol++ = cov[i * dim + j];
59  break;
60  case 1: // Row, Lower, Pack
61  std::copy_n(cov, dim * (dim + 1) / 2, chol);
62  break;
63  case 2: // Row, Upper, Full
64  for (std::size_t i = 0; i != dim; ++i)
65  for (std::size_t j = 0; j <= i; ++j)
66  *chol++ = cov[j * dim + i];
67  break;
68  case 3: // Row, Upper, Pack
69  for (std::size_t i = 0; i != dim; ++i)
70  for (std::size_t j = 0; j <= i; ++j)
71  *chol++ = cov[dim * j - j * (j + 1) / 2 + i];
72  break;
73  case 4: // Col, Lower, Full
74  for (std::size_t i = 0; i != dim; ++i)
75  for (std::size_t j = 0; j <= i; ++j)
76  *chol++ = cov[j * dim + i];
77  break;
78  case 5: // Col, Lower, Pack
79  for (std::size_t i = 0; i != dim; ++i)
80  for (std::size_t j = 0; j <= i; ++j)
81  *chol++ = cov[dim * j - j * (j + 1) / 2 + i];
82  break;
83  case 6: // Col, Upper, Full
84  for (std::size_t j = 0; j != dim; ++j)
85  for (std::size_t i = 0; i <= j; ++i)
86  *chol++ = cov[j * dim + i];
87  break;
88  case 7: // Col, Upper, Pack
89  std::copy_n(cov, dim * (dim + 1) / 2, chol);
90  break;
91  default: break;
92  }
93 }
94 
95 inline int cov_chol(std::size_t dim, float *chol)
96 {
97  return static_cast<int>(::LAPACKE_spptrf(
98  LAPACK_ROW_MAJOR, 'L', static_cast<lapack_int>(dim), chol));
99 }
100 
101 inline int cov_chol(std::size_t dim, double *chol)
102 {
103  return static_cast<int>(::LAPACKE_dpptrf(
104  LAPACK_ROW_MAJOR, 'L', static_cast<lapack_int>(dim), chol));
105 }
106 
107 } // namespace vsmc::internal
108 
128 template <typename RealType>
129 inline int cov_chol(std::size_t dim, const RealType *cov, RealType *chol,
130  MatrixLayout layout = RowMajor, bool upper = false, bool packed = false)
131 {
133  "**cov_chol** USED WITH RealType OTHER THAN float OR double");
134 
135  internal::cov_pack(dim, cov, chol, layout, upper, packed);
136  return internal::cov_chol(dim, chol);
137 }
138 
141 template <typename RealType = double>
143 {
145  "**Covariance** USED WITH RealType OTHER THAN float OR double");
146 
147  public:
148  using result_type = RealType;
149 
170  void operator()(MatrixLayout layout, std::size_t n, std::size_t dim,
171  const result_type *x, const result_type *w, result_type *mean,
172  result_type *cov, MatrixLayout cov_layout = RowMajor,
173  bool cov_upper = false, bool cov_packed = false)
174  {
175  if (n * dim == 0)
176  return;
177 
178  if (x == nullptr)
179  return;
180 
181  if (mean == nullptr && cov == nullptr)
182  return;
183 
184 #if VSMC_USE_MKL_VSL
185  MKL_INT px = static_cast<MKL_INT>(dim);
186  MKL_INT nx = static_cast<MKL_INT>(n);
187  MKL_INT xstorage = layout == RowMajor ? VSL_SS_MATRIX_STORAGE_COLS :
188  VSL_SS_MATRIX_STORAGE_ROWS;
189  MKL_INT cov_storage = storage(cov_layout, cov_upper, cov_packed);
190  unsigned MKL_INT64 estimates = 0;
191  if (mean != nullptr)
192  estimates |= VSL_SS_MEAN;
193  if (cov != nullptr)
194  estimates |= VSL_SS_COV;
195 
196  MKLSSTask<result_type> task(&px, &nx, &xstorage, x, w, nullptr);
197  task.edit_cov_cor(mean, cov, &cov_storage, nullptr, nullptr);
198  task.compute(estimates, VSL_SS_METHOD_FAST);
199 #else // VSMC_USE_MKL_VSL
200  result_type sw = w == nullptr ?
201  static_cast<result_type>(n) :
202  std::accumulate(w, w + n, static_cast<result_type>(0));
203  mean_.resize(dim);
204  if (w == nullptr) {
205  if (layout == RowMajor) {
206  std::fill(mean_.begin(), mean_.end(), 0);
207  for (std::size_t i = 0; i != n; ++i)
208  add(dim, x + i * dim, mean_.data(), mean_.data());
209  } else {
210  for (std::size_t i = 0; i != dim; ++i) {
211  mean_[i] = std::accumulate(x + i * n, x + (i + 1) * n,
212  static_cast<result_type>(0));
213  }
214  }
215  } else {
216  mean_init(layout, n, dim, x, w);
217  }
218  div(dim, mean_.data(), sw, mean_.data());
219  if (mean != nullptr)
220  std::copy(mean_.begin(), mean_.end(), mean);
221  if (cov == nullptr)
222  return;
223 
224  result_type sw2 =
225  w == nullptr ? static_cast<result_type>(n) : swsqr(n, w);
226  result_type B = sw / (sw * sw - sw2);
227  result_type BW = B * sw;
228  cov_.resize(dim * dim);
229  std::fill(cov_.begin(), cov_.end(), 0);
230  cov_init(layout, dim, static_cast<result_type *>(nullptr));
231  if (w == nullptr) {
232  cov_update(layout, n, dim, x, B, BW);
233  } else {
234  wsqrt_.resize(n);
235  buffer_.resize(n * dim);
236  sqrt(n, w, wsqrt_.data());
237  if (layout == RowMajor) {
238  for (std::size_t i = 0; i != n; ++i)
239  mul(dim, x + i * dim, wsqrt_[i], buffer_.data() + i * dim);
240  } else {
241  for (std::size_t i = 0; i != dim; ++i)
242  mul(n, x + i * n, wsqrt_.data(), buffer_.data() + i * n);
243  }
244  cov_update(layout, n, dim, buffer_.data(), B, BW);
245  }
246  cov_pack(dim, cov, layout, cov_layout, cov_upper, cov_packed);
247 #endif // VSMC_USE_MKL_VSL
248  }
249 
250  private:
251 #if VSMC_USE_MKL_VSL
252  MKL_INT storage(MatrixLayout layout, bool upper, bool packed)
253  {
254  if (!packed)
255  return VSL_SS_MATRIX_STORAGE_FULL;
256 
257  if (layout == RowMajor)
258  return upper ? VSL_SS_MATRIX_STORAGE_U_PACKED :
259  VSL_SS_MATRIX_STORAGE_L_PACKED;
260 
261  return upper ? VSL_SS_MATRIX_STORAGE_L_PACKED :
262  VSL_SS_MATRIX_STORAGE_U_PACKED;
263  }
264 #else // VSMC_USE_MKL_VSL
265  Vector<result_type> mean_;
266  Vector<result_type> cov_;
267  Vector<result_type> wsqrt_;
268  Vector<result_type> buffer_;
269 
270  void mean_init(MatrixLayout layout, std::size_t n, std::size_t dim,
271  const float *x, const float *w)
272  {
273  ::cblas_sgemv(layout == RowMajor ? ::CblasRowMajor : ::CblasColMajor,
274  ::CblasTrans, static_cast<VSMC_CBLAS_INT>(n),
275  static_cast<VSMC_CBLAS_INT>(dim), 1.0, x,
276  static_cast<VSMC_CBLAS_INT>(layout == RowMajor ? dim : n), w, 1,
277  0.0, mean_.data(), 1);
278  }
279 
280  void mean_init(MatrixLayout layout, std::size_t n, std::size_t dim,
281  const double *x, const double *w)
282  {
283  ::cblas_dgemv(layout == RowMajor ? ::CblasRowMajor : ::CblasColMajor,
284  ::CblasTrans, static_cast<VSMC_CBLAS_INT>(n),
285  static_cast<VSMC_CBLAS_INT>(dim), 1.0, x,
286  static_cast<VSMC_CBLAS_INT>(layout == RowMajor ? dim : n), w, 1,
287  0.0, mean_.data(), 1);
288  }
289 
290  static float swsqr(std::size_t n, const float *w)
291  {
292  return ::cblas_sdot(static_cast<VSMC_CBLAS_INT>(n), w, 1, w, 1);
293  }
294 
295  static double swsqr(std::size_t n, const double *w)
296  {
297  return ::cblas_ddot(static_cast<VSMC_CBLAS_INT>(n), w, 1, w, 1);
298  }
299 
300  void cov_init(MatrixLayout layout, std::size_t dim, float *)
301  {
302  ::cblas_ssyr(layout == RowMajor ? ::CblasRowMajor : ::CblasColMajor,
303  ::CblasLower, static_cast<VSMC_CBLAS_INT>(dim), 1, mean_.data(), 1,
304  cov_.data(), static_cast<VSMC_CBLAS_INT>(dim));
305  }
306 
307  void cov_init(MatrixLayout layout, std::size_t dim, double *)
308  {
309  ::cblas_dsyr(layout == RowMajor ? ::CblasRowMajor : ::CblasColMajor,
310  ::CblasLower, static_cast<VSMC_CBLAS_INT>(dim), 1, mean_.data(), 1,
311  cov_.data(), static_cast<VSMC_CBLAS_INT>(dim));
312  }
313 
314  void cov_update(MatrixLayout layout, std::size_t n, std::size_t dim,
315  const float *x, float B, float BW)
316  {
317  ::cblas_ssyrk(layout == RowMajor ? ::CblasRowMajor : ::CblasColMajor,
318  ::CblasLower, ::CblasTrans, static_cast<VSMC_CBLAS_INT>(dim),
319  static_cast<VSMC_CBLAS_INT>(n), B, x,
320  static_cast<VSMC_CBLAS_INT>(layout == RowMajor ? dim : n), -BW,
321  cov_.data(), static_cast<VSMC_CBLAS_INT>(dim));
322  }
323 
324  void cov_update(MatrixLayout layout, std::size_t n, std::size_t dim,
325  const double *x, double B, double BW)
326  {
327  ::cblas_dsyrk(layout == RowMajor ? ::CblasRowMajor : ::CblasColMajor,
328  ::CblasLower, ::CblasTrans, static_cast<VSMC_CBLAS_INT>(dim),
329  static_cast<VSMC_CBLAS_INT>(n), B, x,
330  static_cast<VSMC_CBLAS_INT>(layout == RowMajor ? dim : n), -BW,
331  cov_.data(), static_cast<VSMC_CBLAS_INT>(dim));
332  }
333 
334  void cov_pack(std::size_t dim, result_type *cov, MatrixLayout layout,
335  MatrixLayout cov_layout, bool cov_upper, bool cov_packed)
336  {
337  if (layout == RowMajor)
338  for (std::size_t i = 0; i != dim; ++i)
339  for (std::size_t j = 0; j != i; ++j)
340  cov_[j * dim + i] = cov_[i * dim + j];
341 
342  if (layout == ColMajor)
343  for (std::size_t i = 0; i != dim; ++i)
344  for (std::size_t j = 0; j != i; ++j)
345  cov_[i * dim + j] = cov_[j * dim + i];
346 
347  if (!cov_packed) {
348  std::copy(cov_.begin(), cov_.end(), cov);
349  return;
350  }
351 
352  unsigned l = cov_layout == RowMajor ? 0 : 1;
353  unsigned u = cov_upper ? 1 : 0;
354  unsigned c = (l << 1) + u;
355  switch (c) {
356  case 0: // Row, Lower, Pack
357  for (size_t i = 0; i != dim; ++i)
358  for (std::size_t j = 0; j <= i; ++j)
359  *cov++ = cov_[i * dim + j];
360  break;
361  case 1: // Row, Upper, Pack
362  for (std::size_t i = 0; i != dim; ++i)
363  for (std::size_t j = i; j != dim; ++j)
364  *cov++ = cov_[i * dim + j];
365  break;
366  case 2: // Col, Lower, Pack
367  for (std::size_t j = 0; j != dim; ++j)
368  for (std::size_t i = j; i != dim; ++i)
369  *cov++ = cov_[j * dim + i];
370  break;
371  case 3: // Col, Upper, Pack
372  for (std::size_t j = 0; j != dim; ++j)
373  for (std::size_t i = 0; i <= j; ++i)
374  *cov++ = cov_[j * dim + i];
375  break;
376  default: break;
377  }
378  }
379 #endif // VSMC_USE_MKL_VSL
380 }; // class Covariance
381 
382 } // namespace vsmc
383 
384 #endif // VSMC_UTILITY_COVARIANCE_HPP
Definition: monitor.hpp:49
typename std::conditional< std::is_scalar< T >::value, AlignedVector< T >, std::vector< T >>::type Vector
AlignedVector for scalar type and std::vector for others.
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:112
void sqrt(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:129
MatrixLayout
Matrix layout.
Definition: defines.hpp:49
int compute(unsigned MKL_INT64 estimates, MKL_INT method)
vslSSCompute
Definition: mkl.hpp:859
void operator()(MatrixLayout layout, std::size_t n, std::size_t dim, const result_type *x, const result_type *w, result_type *mean, result_type *cov, MatrixLayout cov_layout=RowMajor, bool cov_upper=false, bool cov_packed=false)
Compute the sample covariance matrix.
Definition: covariance.hpp:170
Covariance.
Definition: covariance.hpp:142
#define VSMC_CBLAS_INT
Definition: cblas.h:50
int cov_chol(std::size_t dim, float *chol)
Definition: covariance.hpp:95
int edit_cov_cor(const result_type *mean, const result_type *cov, const MKL_INT *cov_storage, const result_type *cor, const MKL_INT *cor_storage)
vslSSEditCovCor
Definition: mkl.hpp:767
MKL VSLSSTaskPtr
Definition: mkl.hpp:703
void div(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:128
void cov_pack(std::size_t dim, const RealType *cov, RealType *chol, MatrixLayout layout, bool upper, bool packed)
Definition: covariance.hpp:47
void add(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:109
RealType result_type
Definition: covariance.hpp:148