comparison armadillo-3.900.4/include/armadillo_bits/spop_var_meat.hpp @ 49:1ec0e2823891

Switch to using subrepo copies of qm-dsp, nnls-chroma, vamp-plugin-sdk; update Armadillo version; assume build without external BLAS/LAPACK
author Chris Cannam
date Thu, 13 Jun 2013 10:25:24 +0100
parents
children
comparison
equal deleted inserted replaced
48:69251e11a913 49:1ec0e2823891
1 // Copyright (C) 2012 Ryan Curtin
2 // Copyright (C) 2012 Conrad Sanderson
3 //
4 // This Source Code Form is subject to the terms of the Mozilla Public
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8
9 //! \addtogroup spop_var
10 //! @{
11
12
13
14 template<typename T1>
15 inline
16 void
17 spop_var::apply(SpMat<typename T1::pod_type>& out, const mtSpOp<typename T1::pod_type, T1, spop_var>& in)
18 {
19 arma_extra_debug_sigprint();
20
21 //typedef typename T1::elem_type in_eT;
22 typedef typename T1::pod_type out_eT;
23
24 const uword norm_type = in.aux_uword_a;
25 const uword dim = in.aux_uword_b;
26
27 arma_debug_check((norm_type > 1), "var(): incorrect usage. norm_type must be 0 or 1");
28 arma_debug_check((dim > 1), "var(): incorrect usage. dim must be 0 or 1");
29
30 SpProxy<T1> p(in.m);
31
32 if(p.is_alias(out) == false)
33 {
34 spop_var::apply_noalias(out, p, norm_type, dim);
35 }
36 else
37 {
38 SpMat<out_eT> tmp;
39
40 spop_var::apply_noalias(tmp, p, norm_type, dim);
41
42 out.steal_mem(tmp);
43 }
44 }
45
46
47
48 template<typename T1>
49 inline
50 void
51 spop_var::apply_noalias
52 (
53 SpMat<typename T1::pod_type>& out_ref,
54 const SpProxy<T1>& p,
55 const uword norm_type,
56 const uword dim
57 )
58 {
59 arma_extra_debug_sigprint();
60
61 typedef typename T1::elem_type in_eT;
62 //typedef typename T1::pod_type out_eT;
63
64 const uword p_n_rows = p.get_n_rows();
65 const uword p_n_cols = p.get_n_cols();
66
67 if(dim == 0)
68 {
69 arma_extra_debug_print("spop_var::apply(), dim = 0");
70
71 arma_debug_check((p_n_rows == 0), "var(): given object has zero rows");
72
73 out_ref.set_size(1, p_n_cols);
74
75 for(uword col = 0; col < p_n_cols; ++col)
76 {
77 if(SpProxy<T1>::must_use_iterator == true)
78 {
79 // We must use an iterator; we can't access memory directly.
80 typename SpProxy<T1>::const_iterator_type it = p.begin_col(col);
81 typename SpProxy<T1>::const_iterator_type end = p.begin_col(col + 1);
82
83 const uword n_zero = p.get_n_rows() - (end.pos() - it.pos());
84
85 // in_eT is used just to get the specialization right (complex / noncomplex)
86 out_ref.at(col) = spop_var::iterator_var(it, end, n_zero, norm_type, in_eT(0));
87 }
88 else
89 {
90 // We can use direct memory access to calculate the variance.
91 out_ref.at(col) = spop_var::direct_var
92 (
93 &p.get_values()[p.get_col_ptrs()[col]],
94 p.get_col_ptrs()[col + 1] - p.get_col_ptrs()[col],
95 p.get_n_rows(),
96 norm_type
97 );
98 }
99 }
100 }
101 else if(dim == 1)
102 {
103 arma_extra_debug_print("spop_var::apply_noalias(), dim = 1");
104
105 arma_debug_check((p_n_cols == 0), "var(): given object has zero columns");
106
107 out_ref.set_size(p_n_rows, 1);
108
109 for(uword row = 0; row < p_n_rows; ++row)
110 {
111 // We have to use an iterator here regardless of whether or not we can
112 // directly access memory.
113 typename SpProxy<T1>::const_row_iterator_type it = p.begin_row(row);
114 typename SpProxy<T1>::const_row_iterator_type end = p.end_row(row);
115
116 const uword n_zero = p.get_n_cols() - (end.pos() - it.pos());
117
118 out_ref.at(row) = spop_var::iterator_var(it, end, n_zero, norm_type, in_eT(0));
119 }
120 }
121 }
122
123
124
125 template<typename T1>
126 inline
127 typename T1::pod_type
128 spop_var::var_vec
129 (
130 const T1& X,
131 const uword norm_type
132 )
133 {
134 arma_extra_debug_sigprint();
135
136 arma_debug_check((norm_type > 1), "var(): incorrect usage. norm_type must be 0 or 1.");
137
138 // conditionally unwrap it into a temporary and then directly operate.
139
140 const unwrap_spmat<T1> tmp(X);
141
142 return direct_var(tmp.M.values, tmp.M.n_nonzero, tmp.M.n_elem, norm_type);
143 }
144
145
146
147 template<typename eT>
148 inline
149 eT
150 spop_var::direct_var
151 (
152 const eT* const X,
153 const uword length,
154 const uword N,
155 const uword norm_type
156 )
157 {
158 arma_extra_debug_sigprint();
159
160 if(length >= 2 && N >= 2)
161 {
162 const eT acc1 = spop_mean::direct_mean(X, length, N);
163
164 eT acc2 = eT(0);
165 eT acc3 = eT(0);
166
167 uword i, j;
168
169 for(i = 0, j = 1; j < length; i += 2, j += 2)
170 {
171 const eT Xi = X[i];
172 const eT Xj = X[j];
173
174 const eT tmpi = acc1 - Xi;
175 const eT tmpj = acc1 - Xj;
176
177 acc2 += tmpi * tmpi + tmpj * tmpj;
178 acc3 += tmpi + tmpj;
179 }
180
181 if(i < length)
182 {
183 const eT Xi = X[i];
184
185 const eT tmpi = acc1 - Xi;
186
187 acc2 += tmpi * tmpi;
188 acc3 += tmpi;
189 }
190
191 // Now add in all zero elements.
192 acc2 += (N - length) * (acc1 * acc1);
193 acc3 += (N - length) * acc1;
194
195 const eT norm_val = (norm_type == 0) ? eT(N - 1) : eT(N);
196 const eT var_val = (acc2 - (acc3 * acc3) / eT(N)) / norm_val;
197
198 return var_val;
199 }
200 else if(length == 1 && N > 1) // if N == 1, then variance is zero.
201 {
202 const eT mean = X[0] / eT(N);
203 const eT val = mean - X[0];
204
205 const eT acc2 = (val * val) + (N - length) * (mean * mean);
206 const eT acc3 = val + (N - length) * mean;
207
208 const eT norm_val = (norm_type == 0) ? eT(N - 1) : eT(N);
209 const eT var_val = (acc2 - (acc3 * acc3) / eT(N)) / norm_val;
210
211 return var_val;
212 }
213 else
214 {
215 return eT(0);
216 }
217 }
218
219
220
221 template<typename T>
222 inline
223 T
224 spop_var::direct_var
225 (
226 const std::complex<T>* const X,
227 const uword length,
228 const uword N,
229 const uword norm_type
230 )
231 {
232 arma_extra_debug_sigprint();
233
234 typedef typename std::complex<T> eT;
235
236 if(length >= 2 && N >= 2)
237 {
238 const eT acc1 = spop_mean::direct_mean(X, length, N);
239
240 T acc2 = T(0);
241 eT acc3 = eT(0);
242
243 for (uword i = 0; i < length; ++i)
244 {
245 const eT tmp = acc1 - X[i];
246
247 acc2 += std::norm(tmp);
248 acc3 += tmp;
249 }
250
251 // Add zero elements to sums
252 acc2 += std::norm(acc1) * T(N - length);
253 acc3 += acc1 * T(N - length);
254
255 const T norm_val = (norm_type == 0) ? T(N - 1) : T(N);
256 const T var_val = (acc2 - std::norm(acc3) / T(N)) / norm_val;
257
258 return var_val;
259 }
260 else if(length == 1 && N > 1) // if N == 1, then variance is zero.
261 {
262 const eT mean = X[0] / T(N);
263 const eT val = mean - X[0];
264
265 const T acc2 = std::norm(val) + (N - length) * std::norm(mean);
266 const eT acc3 = val + T(N - length) * mean;
267
268 const T norm_val = (norm_type == 0) ? T(N - 1) : T(N);
269 const T var_val = (acc2 - std::norm(acc3) / T(N)) / norm_val;
270
271 return var_val;
272 }
273 else
274 {
275 return T(0); // All elements are zero
276 }
277 }
278
279
280
281 template<typename T1, typename eT>
282 inline
283 eT
284 spop_var::iterator_var
285 (
286 T1& it,
287 const T1& end,
288 const uword n_zero,
289 const uword norm_type,
290 const eT junk1,
291 const typename arma_not_cx<eT>::result* junk2
292 )
293 {
294 arma_extra_debug_sigprint();
295 arma_ignore(junk1);
296 arma_ignore(junk2);
297
298 T1 new_it(it); // for mean
299 // T1 backup_it(it); // in case we have to call robust iterator_var
300 eT mean = spop_mean::iterator_mean(new_it, end, n_zero, eT(0));
301
302 eT acc2 = eT(0);
303 eT acc3 = eT(0);
304
305 const uword it_begin_pos = it.pos();
306
307 while (it != end)
308 {
309 const eT tmp = mean - (*it);
310
311 acc2 += (tmp * tmp);
312 acc3 += (tmp);
313
314 ++it;
315 }
316
317 const uword n_nonzero = (it.pos() - it_begin_pos);
318 if (n_nonzero == 0)
319 {
320 return eT(0);
321 }
322
323 if (n_nonzero + n_zero == 1)
324 {
325 return eT(0); // only one element
326 }
327
328 // Add in entries for zeros.
329 acc2 += eT(n_zero) * (mean * mean);
330 acc3 += eT(n_zero) * mean;
331
332 const eT norm_val = (norm_type == 0) ? eT(n_zero + n_nonzero - 1) : eT(n_zero + n_nonzero);
333 const eT var_val = (acc2 - (acc3 * acc3) / eT(n_nonzero + n_zero)) / norm_val;
334
335 return var_val;
336 }
337
338
339
340 template<typename T1, typename eT>
341 inline
342 typename get_pod_type<eT>::result
343 spop_var::iterator_var
344 (
345 T1& it,
346 const T1& end,
347 const uword n_zero,
348 const uword norm_type,
349 const eT junk1,
350 const typename arma_cx_only<eT>::result* junk2
351 )
352 {
353 arma_extra_debug_sigprint();
354 arma_ignore(junk1);
355 arma_ignore(junk2);
356
357 typedef typename get_pod_type<eT>::result T;
358
359 T1 new_it(it); // for mean
360 // T1 backup_it(it); // in case we have to call robust iterator_var
361 eT mean = spop_mean::iterator_mean(new_it, end, n_zero, eT(0));
362
363 T acc2 = T(0);
364 eT acc3 = eT(0);
365
366 const uword it_begin_pos = it.pos();
367
368 while (it != end)
369 {
370 eT tmp = mean - (*it);
371
372 acc2 += std::norm(tmp);
373 acc3 += (tmp);
374
375 ++it;
376 }
377
378 const uword n_nonzero = (it.pos() - it_begin_pos);
379 if (n_nonzero == 0)
380 {
381 return T(0);
382 }
383
384 if (n_nonzero + n_zero == 1)
385 {
386 return T(0); // only one element
387 }
388
389 // Add in entries for zero elements.
390 acc2 += T(n_zero) * std::norm(mean);
391 acc3 += T(n_zero) * mean;
392
393 const T norm_val = (norm_type == 0) ? T(n_zero + n_nonzero - 1) : T(n_zero + n_nonzero);
394 const T var_val = (acc2 - std::norm(acc3) / T(n_nonzero + n_zero)) / norm_val;
395
396 return var_val;
397 }
398
399
400
401 //! @}