vSMC  v3.0.0
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 
37 namespace vsmc
38 {
39 
42 template <typename RealType = double>
44 {
46  "**Covariance** USED WITH RealType OTHER THAN float OR double");
47 
48  public:
49  using result_type = RealType;
50 
71  void operator()(MatrixLayout layout, std::size_t n, std::size_t p,
72  const result_type *x, const result_type *w, result_type *mean,
73  result_type *cov, MatrixLayout cov_layout = RowMajor,
74  bool cov_upper = false, bool cov_packed = false)
75  {
76  if (n * p == 0)
77  return;
78 
79  if (x == nullptr)
80  return;
81 
82  if (mean == nullptr && cov == nullptr)
83  return;
84 
85  internal::size_check<VSMC_BLAS_INT>(p, "Covariance::operator()");
86  internal::size_check<VSMC_BLAS_INT>(n, "Covariance::operator()");
87 
88  result_type sw = w == nullptr ?
89  static_cast<result_type>(n) :
90  std::accumulate(w, w + n, static_cast<result_type>(0));
91  mean_.resize(p);
92  if (w == nullptr) {
93  if (layout == RowMajor) {
94  std::fill(mean_.begin(), mean_.end(), 0);
95  for (std::size_t i = 0; i != n; ++i)
96  add(p, x + i * p, mean_.data(), mean_.data());
97  } else {
98  for (std::size_t i = 0; i != p; ++i) {
99  mean_[i] = std::accumulate(x + i * n, x + (i + 1) * n,
100  static_cast<result_type>(0));
101  }
102  }
103  } else {
104  mean_init(layout, n, p, x, w);
105  }
106  div(p, mean_.data(), sw, mean_.data());
107  if (mean != nullptr)
108  std::copy(mean_.begin(), mean_.end(), mean);
109  if (cov == nullptr)
110  return;
111 
112  result_type sw2 =
113  w == nullptr ? static_cast<result_type>(n) : swsqr(n, w);
114  result_type B = sw / (sw * sw - sw2);
115  result_type BW = B * sw;
116  cov_.resize(p * p);
117  std::fill(cov_.begin(), cov_.end(), 0);
118  cov_init(layout, p, static_cast<result_type *>(nullptr));
119  if (w == nullptr) {
120  cov_update(layout, n, p, x, B, BW);
121  } else {
122  wsqrt_.resize(n);
123  buffer_.resize(n * p);
124  sqrt(n, w, wsqrt_.data());
125  if (layout == RowMajor) {
126  for (std::size_t i = 0; i != n; ++i)
127  mul(p, x + i * p, wsqrt_[i], buffer_.data() + i * p);
128  } else {
129  for (std::size_t i = 0; i != p; ++i)
130  mul(n, x + i * n, wsqrt_.data(), buffer_.data() + i * n);
131  }
132  cov_update(layout, n, p, buffer_.data(), B, BW);
133  }
134  cov_pack(p, cov, layout, cov_layout, cov_upper, cov_packed);
135  }
136 
137  private:
138  Vector<result_type> mean_;
139  Vector<result_type> cov_;
140  Vector<result_type> wsqrt_;
141  Vector<result_type> buffer_;
142 
143  void mean_init(MatrixLayout layout, std::size_t n, std::size_t p,
144  const float *x, const float *w)
145  {
146  internal::cblas_sgemv(layout == RowMajor ? internal::CblasRowMajor :
147  internal::CblasColMajor,
148  internal::CblasTrans, static_cast<VSMC_BLAS_INT>(n),
149  static_cast<VSMC_BLAS_INT>(p), 1.0, x,
150  static_cast<VSMC_BLAS_INT>(layout == RowMajor ? p : n), w, 1, 0.0,
151  mean_.data(), 1);
152  }
153 
154  void mean_init(MatrixLayout layout, std::size_t n, std::size_t p,
155  const double *x, const double *w)
156  {
157  internal::cblas_dgemv(layout == RowMajor ? internal::CblasRowMajor :
158  internal::CblasColMajor,
159  internal::CblasTrans, static_cast<VSMC_BLAS_INT>(n),
160  static_cast<VSMC_BLAS_INT>(p), 1.0, x,
161  static_cast<VSMC_BLAS_INT>(layout == RowMajor ? p : n), w, 1, 0.0,
162  mean_.data(), 1);
163  }
164 
165  static float swsqr(std::size_t n, const float *w)
166  {
167  return internal::cblas_sdot(static_cast<VSMC_BLAS_INT>(n), w, 1, w, 1);
168  }
169 
170  static double swsqr(std::size_t n, const double *w)
171  {
172  return internal::cblas_ddot(static_cast<VSMC_BLAS_INT>(n), w, 1, w, 1);
173  }
174 
175  void cov_init(MatrixLayout layout, std::size_t p, float *)
176  {
177  internal::cblas_ssyr(layout == RowMajor ? internal::CblasRowMajor :
178  internal::CblasColMajor,
179  internal::CblasLower, static_cast<VSMC_BLAS_INT>(p), 1,
180  mean_.data(), 1, cov_.data(), static_cast<VSMC_BLAS_INT>(p));
181  }
182 
183  void cov_init(MatrixLayout layout, std::size_t p, double *)
184  {
185  internal::cblas_dsyr(layout == RowMajor ? internal::CblasRowMajor :
186  internal::CblasColMajor,
187  internal::CblasLower, static_cast<VSMC_BLAS_INT>(p), 1,
188  mean_.data(), 1, cov_.data(), static_cast<VSMC_BLAS_INT>(p));
189  }
190 
191  void cov_update(MatrixLayout layout, std::size_t n, std::size_t p,
192  const float *x, float B, float BW)
193  {
194  internal::cblas_ssyrk(layout == RowMajor ? internal::CblasRowMajor :
195  internal::CblasColMajor,
196  internal::CblasLower, internal::CblasTrans,
197  static_cast<VSMC_BLAS_INT>(p), static_cast<VSMC_BLAS_INT>(n), B, x,
198  static_cast<VSMC_BLAS_INT>(layout == RowMajor ? p : n), -BW,
199  cov_.data(), static_cast<VSMC_BLAS_INT>(p));
200  }
201 
202  void cov_update(MatrixLayout layout, std::size_t n, std::size_t p,
203  const double *x, double B, double BW)
204  {
205  internal::cblas_dsyrk(layout == RowMajor ? internal::CblasRowMajor :
206  internal::CblasColMajor,
207  internal::CblasLower, internal::CblasTrans,
208  static_cast<VSMC_BLAS_INT>(p), static_cast<VSMC_BLAS_INT>(n), B, x,
209  static_cast<VSMC_BLAS_INT>(layout == RowMajor ? p : n), -BW,
210  cov_.data(), static_cast<VSMC_BLAS_INT>(p));
211  }
212 
213  void cov_pack(std::size_t p, result_type *cov, MatrixLayout layout,
214  MatrixLayout cov_layout, bool cov_upper, bool cov_packed)
215  {
216  if (layout == RowMajor)
217  for (std::size_t i = 0; i != p; ++i)
218  for (std::size_t j = 0; j != i; ++j)
219  cov_[j * p + i] = cov_[i * p + j];
220 
221  if (layout == ColMajor)
222  for (std::size_t i = 0; i != p; ++i)
223  for (std::size_t j = 0; j != i; ++j)
224  cov_[i * p + j] = cov_[j * p + i];
225 
226  if (!cov_packed) {
227  std::copy(cov_.begin(), cov_.end(), cov);
228  return;
229  }
230 
231  unsigned l = cov_layout == RowMajor ? 0 : 1;
232  unsigned u = cov_upper ? 1 : 0;
233  unsigned c = (l << 1) + u;
234  switch (c) {
235  case 0: // Row, Lower, Pack
236  for (size_t i = 0; i != p; ++i)
237  for (std::size_t j = 0; j <= i; ++j)
238  *cov++ = cov_[i * p + j];
239  break;
240  case 1: // Row, Upper, Pack
241  for (std::size_t i = 0; i != p; ++i)
242  for (std::size_t j = i; j != p; ++j)
243  *cov++ = cov_[i * p + j];
244  break;
245  case 2: // Col, Lower, Pack
246  for (std::size_t j = 0; j != p; ++j)
247  for (std::size_t i = j; i != p; ++i)
248  *cov++ = cov_[j * p + i];
249  break;
250  case 3: // Col, Upper, Pack
251  for (std::size_t j = 0; j != p; ++j)
252  for (std::size_t i = 0; i <= j; ++i)
253  *cov++ = cov_[j * p + i];
254  break;
255  default: break;
256  }
257  }
258 }; // class Covariance
259 
260 } // namespace vsmc
261 
262 #endif // VSMC_UTILITY_COVARIANCE_HPP
std::vector< T, Alloc > Vector
std::vector with Allocator as default allocator
Definition: monitor.hpp:48
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:77
#define VSMC_BLAS_INT
Definition: cblas.hpp:42
void sqrt(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:96
MatrixLayout
Matrix layout.
Definition: defines.hpp:51
Covariance.
Definition: covariance.hpp:43
void div(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:95
void add(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:74
RealType result_type
Definition: covariance.hpp:49
void operator()(MatrixLayout layout, std::size_t n, std::size_t p, 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:71