Chris@49
|
1 // Copyright (C) 2012 Ryan Curtin
|
Chris@49
|
2 // Copyright (C) 2012 Conrad Sanderson
|
Chris@49
|
3 //
|
Chris@49
|
4 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
7
|
Chris@49
|
8
|
Chris@49
|
9 //! \addtogroup spop_min
|
Chris@49
|
10 //! @{
|
Chris@49
|
11
|
Chris@49
|
12
|
Chris@49
|
13
|
Chris@49
|
14 template<typename T1>
|
Chris@49
|
15 inline
|
Chris@49
|
16 void
|
Chris@49
|
17 spop_min::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_min>& in)
|
Chris@49
|
18 {
|
Chris@49
|
19 arma_extra_debug_sigprint();
|
Chris@49
|
20
|
Chris@49
|
21 typedef typename T1::elem_type eT;
|
Chris@49
|
22
|
Chris@49
|
23 const uword dim = in.aux_uword_a;
|
Chris@49
|
24 arma_debug_check((dim > 1), "min(): incorrect usage. dim must be 0 or 1");
|
Chris@49
|
25
|
Chris@49
|
26 const SpProxy<T1> p(in.m);
|
Chris@49
|
27
|
Chris@49
|
28 if(p.is_alias(out) == false)
|
Chris@49
|
29 {
|
Chris@49
|
30 spop_min::apply_noalias(out, p, dim);
|
Chris@49
|
31 }
|
Chris@49
|
32 else
|
Chris@49
|
33 {
|
Chris@49
|
34 SpMat<eT> tmp;
|
Chris@49
|
35
|
Chris@49
|
36 spop_min::apply_noalias(tmp, p, dim);
|
Chris@49
|
37
|
Chris@49
|
38 out.steal_mem(tmp);
|
Chris@49
|
39 }
|
Chris@49
|
40 }
|
Chris@49
|
41
|
Chris@49
|
42
|
Chris@49
|
43
|
Chris@49
|
44 template<typename T1>
|
Chris@49
|
45 inline
|
Chris@49
|
46 void
|
Chris@49
|
47 spop_min::apply_noalias
|
Chris@49
|
48 (
|
Chris@49
|
49 SpMat<typename T1::elem_type>& result,
|
Chris@49
|
50 const SpProxy<T1>& p,
|
Chris@49
|
51 const uword dim,
|
Chris@49
|
52 const typename arma_not_cx<typename T1::elem_type>::result* junk
|
Chris@49
|
53 )
|
Chris@49
|
54 {
|
Chris@49
|
55 arma_extra_debug_sigprint();
|
Chris@49
|
56 arma_ignore(junk);
|
Chris@49
|
57
|
Chris@49
|
58 typedef typename T1::elem_type eT;
|
Chris@49
|
59
|
Chris@49
|
60 if(dim == 0)
|
Chris@49
|
61 {
|
Chris@49
|
62 // minimum in each column
|
Chris@49
|
63 result.set_size(1, p.get_n_cols());
|
Chris@49
|
64
|
Chris@49
|
65 if(p.get_n_nonzero() == 0)
|
Chris@49
|
66 {
|
Chris@49
|
67 return;
|
Chris@49
|
68 }
|
Chris@49
|
69
|
Chris@49
|
70 typename SpProxy<T1>::const_iterator_type it = p.begin();
|
Chris@49
|
71
|
Chris@49
|
72 uword cur_col = it.col();
|
Chris@49
|
73 uword elem_in_col = 1;
|
Chris@49
|
74 eT cur_min = (*it);
|
Chris@49
|
75 ++it;
|
Chris@49
|
76
|
Chris@49
|
77 while(it != p.end())
|
Chris@49
|
78 {
|
Chris@49
|
79 if(it.col() != cur_col)
|
Chris@49
|
80 {
|
Chris@49
|
81 // was the column full?
|
Chris@49
|
82 if(elem_in_col == p.get_n_rows())
|
Chris@49
|
83 {
|
Chris@49
|
84 result.at(0, cur_col) = cur_min;
|
Chris@49
|
85 }
|
Chris@49
|
86 else
|
Chris@49
|
87 {
|
Chris@49
|
88 result.at(0, cur_col) = std::min(eT(0), cur_min);
|
Chris@49
|
89 }
|
Chris@49
|
90
|
Chris@49
|
91 cur_col = it.col();
|
Chris@49
|
92 elem_in_col = 0;
|
Chris@49
|
93 cur_min = (*it);
|
Chris@49
|
94 }
|
Chris@49
|
95 else
|
Chris@49
|
96 {
|
Chris@49
|
97 cur_min = std::min(cur_min, *it);
|
Chris@49
|
98 }
|
Chris@49
|
99
|
Chris@49
|
100 ++elem_in_col;
|
Chris@49
|
101 ++it;
|
Chris@49
|
102 }
|
Chris@49
|
103
|
Chris@49
|
104 if(elem_in_col == p.get_n_rows())
|
Chris@49
|
105 {
|
Chris@49
|
106 result.at(0, cur_col) = cur_min;
|
Chris@49
|
107 }
|
Chris@49
|
108 else
|
Chris@49
|
109 {
|
Chris@49
|
110 result.at(0, cur_col) = std::min(eT(0), cur_min);
|
Chris@49
|
111 }
|
Chris@49
|
112 }
|
Chris@49
|
113 else
|
Chris@49
|
114 {
|
Chris@49
|
115 // minimum in each row
|
Chris@49
|
116 result.set_size(p.get_n_rows(), 1);
|
Chris@49
|
117
|
Chris@49
|
118 if(p.get_n_nonzero() == 0)
|
Chris@49
|
119 {
|
Chris@49
|
120 return;
|
Chris@49
|
121 }
|
Chris@49
|
122
|
Chris@49
|
123 typename SpProxy<T1>::const_row_iterator_type it = p.begin_row();
|
Chris@49
|
124
|
Chris@49
|
125 uword cur_row = it.row();
|
Chris@49
|
126 uword elem_in_row = 1;
|
Chris@49
|
127 eT cur_min = (*it);
|
Chris@49
|
128 ++it;
|
Chris@49
|
129
|
Chris@49
|
130 while(it.pos() < p.get_n_nonzero())
|
Chris@49
|
131 {
|
Chris@49
|
132 if(it.row() != cur_row)
|
Chris@49
|
133 {
|
Chris@49
|
134 // was the row full?
|
Chris@49
|
135 if(elem_in_row == p.get_n_cols())
|
Chris@49
|
136 {
|
Chris@49
|
137 result.at(cur_row, 0) = cur_min;
|
Chris@49
|
138 }
|
Chris@49
|
139 else
|
Chris@49
|
140 {
|
Chris@49
|
141 result.at(cur_row, 0) = std::min(eT(0), cur_min);
|
Chris@49
|
142 }
|
Chris@49
|
143
|
Chris@49
|
144 cur_row = it.row();
|
Chris@49
|
145 elem_in_row = 0;
|
Chris@49
|
146 cur_min = (*it);
|
Chris@49
|
147 }
|
Chris@49
|
148 else
|
Chris@49
|
149 {
|
Chris@49
|
150 cur_min = std::min(cur_min, *it);
|
Chris@49
|
151 }
|
Chris@49
|
152
|
Chris@49
|
153 ++elem_in_row;
|
Chris@49
|
154 ++it;
|
Chris@49
|
155 }
|
Chris@49
|
156
|
Chris@49
|
157 if(elem_in_row == p.get_n_cols())
|
Chris@49
|
158 {
|
Chris@49
|
159 result.at(cur_row, 0) = cur_min;
|
Chris@49
|
160 }
|
Chris@49
|
161 else
|
Chris@49
|
162 {
|
Chris@49
|
163 result.at(cur_row, 0) = std::min(eT(0), cur_min);
|
Chris@49
|
164 }
|
Chris@49
|
165 }
|
Chris@49
|
166 }
|
Chris@49
|
167
|
Chris@49
|
168
|
Chris@49
|
169
|
Chris@49
|
170 template<typename T1>
|
Chris@49
|
171 inline
|
Chris@49
|
172 void
|
Chris@49
|
173 spop_min::apply_noalias
|
Chris@49
|
174 (
|
Chris@49
|
175 SpMat<typename T1::elem_type>& result,
|
Chris@49
|
176 const SpProxy<T1>& p,
|
Chris@49
|
177 const uword dim,
|
Chris@49
|
178 const typename arma_cx_only<typename T1::elem_type>::result* junk
|
Chris@49
|
179 )
|
Chris@49
|
180 {
|
Chris@49
|
181 arma_extra_debug_sigprint();
|
Chris@49
|
182 arma_ignore(junk);
|
Chris@49
|
183
|
Chris@49
|
184 typedef typename T1::elem_type eT;
|
Chris@49
|
185 typedef typename get_pod_type<eT>::result T;
|
Chris@49
|
186
|
Chris@49
|
187 if(dim == 0)
|
Chris@49
|
188 {
|
Chris@49
|
189 // minimum in each column
|
Chris@49
|
190 result.set_size(1, p.get_n_cols());
|
Chris@49
|
191
|
Chris@49
|
192 if(p.get_n_nonzero() == 0)
|
Chris@49
|
193 {
|
Chris@49
|
194 return;
|
Chris@49
|
195 }
|
Chris@49
|
196
|
Chris@49
|
197 typename SpProxy<T1>::const_iterator_type it = p.begin();
|
Chris@49
|
198
|
Chris@49
|
199 uword cur_col = it.col();
|
Chris@49
|
200 uword elem_in_col = 1;
|
Chris@49
|
201
|
Chris@49
|
202 eT cur_min_orig = *it;
|
Chris@49
|
203 T cur_min_abs = std::abs(cur_min_orig);
|
Chris@49
|
204
|
Chris@49
|
205 ++it;
|
Chris@49
|
206
|
Chris@49
|
207 while(it != p.end())
|
Chris@49
|
208 {
|
Chris@49
|
209 if(it.col() != cur_col)
|
Chris@49
|
210 {
|
Chris@49
|
211 // was the column full?
|
Chris@49
|
212 if(elem_in_col == p.get_n_rows())
|
Chris@49
|
213 {
|
Chris@49
|
214 result.at(0, cur_col) = cur_min_orig;
|
Chris@49
|
215 }
|
Chris@49
|
216 else
|
Chris@49
|
217 {
|
Chris@49
|
218 eT val1 = eT(0);
|
Chris@49
|
219
|
Chris@49
|
220 result.at(0, cur_col) = ( std::abs(val1) < cur_min_abs ) ? val1 : cur_min_orig;
|
Chris@49
|
221 }
|
Chris@49
|
222
|
Chris@49
|
223 cur_col = it.col();
|
Chris@49
|
224 elem_in_col = 0;
|
Chris@49
|
225
|
Chris@49
|
226 cur_min_orig = *it;
|
Chris@49
|
227 cur_min_abs = std::abs(cur_min_orig);
|
Chris@49
|
228 }
|
Chris@49
|
229 else
|
Chris@49
|
230 {
|
Chris@49
|
231 eT val1_orig = *it;
|
Chris@49
|
232 T val1_abs = std::abs(val1_orig);
|
Chris@49
|
233
|
Chris@49
|
234 if( val1_abs < cur_min_abs )
|
Chris@49
|
235 {
|
Chris@49
|
236 cur_min_abs = val1_abs;
|
Chris@49
|
237 cur_min_orig = val1_orig;
|
Chris@49
|
238 }
|
Chris@49
|
239 }
|
Chris@49
|
240
|
Chris@49
|
241 ++elem_in_col;
|
Chris@49
|
242 ++it;
|
Chris@49
|
243 }
|
Chris@49
|
244
|
Chris@49
|
245 if(elem_in_col == p.get_n_rows())
|
Chris@49
|
246 {
|
Chris@49
|
247 result.at(0, cur_col) = cur_min_orig;
|
Chris@49
|
248 }
|
Chris@49
|
249 else
|
Chris@49
|
250 {
|
Chris@49
|
251 eT val1 = eT(0);
|
Chris@49
|
252
|
Chris@49
|
253 result.at(0, cur_col) = ( std::abs(val1) < cur_min_abs ) ? val1 : cur_min_orig;
|
Chris@49
|
254 }
|
Chris@49
|
255 }
|
Chris@49
|
256 else
|
Chris@49
|
257 {
|
Chris@49
|
258 // minimum in each row
|
Chris@49
|
259 result.set_size(p.get_n_rows(), 1);
|
Chris@49
|
260
|
Chris@49
|
261 if(p.get_n_nonzero() == 0)
|
Chris@49
|
262 {
|
Chris@49
|
263 return;
|
Chris@49
|
264 }
|
Chris@49
|
265
|
Chris@49
|
266 typename SpProxy<T1>::const_row_iterator_type it = p.begin_row();
|
Chris@49
|
267
|
Chris@49
|
268 uword cur_row = it.row();
|
Chris@49
|
269 uword elem_in_row = 1;
|
Chris@49
|
270
|
Chris@49
|
271 eT cur_min_orig = *it;
|
Chris@49
|
272 T cur_min_abs = std::abs(cur_min_orig);
|
Chris@49
|
273
|
Chris@49
|
274 ++it;
|
Chris@49
|
275
|
Chris@49
|
276 while(it.pos() < p.get_n_nonzero())
|
Chris@49
|
277 {
|
Chris@49
|
278 if(it.row() != cur_row)
|
Chris@49
|
279 {
|
Chris@49
|
280 // was the row full?
|
Chris@49
|
281 if(elem_in_row == p.get_n_cols())
|
Chris@49
|
282 {
|
Chris@49
|
283 result.at(cur_row, 0) = cur_min_orig;
|
Chris@49
|
284 }
|
Chris@49
|
285 else
|
Chris@49
|
286 {
|
Chris@49
|
287 eT val1 = eT(0);
|
Chris@49
|
288
|
Chris@49
|
289 result.at(cur_row, 0) = ( std::abs(val1) < cur_min_abs ) ? val1 : cur_min_orig;
|
Chris@49
|
290 }
|
Chris@49
|
291
|
Chris@49
|
292 cur_row = it.row();
|
Chris@49
|
293 elem_in_row = 0;
|
Chris@49
|
294
|
Chris@49
|
295 cur_min_orig = *it;
|
Chris@49
|
296 cur_min_abs = std::abs(cur_min_orig);
|
Chris@49
|
297 }
|
Chris@49
|
298 else
|
Chris@49
|
299 {
|
Chris@49
|
300 eT val1_orig = *it;
|
Chris@49
|
301 T val1_abs = std::abs(val1_orig);
|
Chris@49
|
302
|
Chris@49
|
303 if( val1_abs < cur_min_abs )
|
Chris@49
|
304 {
|
Chris@49
|
305 cur_min_abs = val1_abs;
|
Chris@49
|
306 cur_min_orig = val1_orig;
|
Chris@49
|
307 }
|
Chris@49
|
308 }
|
Chris@49
|
309
|
Chris@49
|
310 ++elem_in_row;
|
Chris@49
|
311 ++it;
|
Chris@49
|
312 }
|
Chris@49
|
313
|
Chris@49
|
314 if(elem_in_row == p.get_n_cols())
|
Chris@49
|
315 {
|
Chris@49
|
316 result.at(cur_row, 0) = cur_min_orig;
|
Chris@49
|
317 }
|
Chris@49
|
318 else
|
Chris@49
|
319 {
|
Chris@49
|
320 eT val1 = eT(0);
|
Chris@49
|
321
|
Chris@49
|
322 result.at(cur_row, 0) = ( std::abs(val1) < cur_min_abs ) ? val1 : cur_min_orig;
|
Chris@49
|
323 }
|
Chris@49
|
324 }
|
Chris@49
|
325 }
|
Chris@49
|
326
|
Chris@49
|
327
|
Chris@49
|
328
|
Chris@49
|
329 template<typename T1>
|
Chris@49
|
330 inline
|
Chris@49
|
331 typename T1::elem_type
|
Chris@49
|
332 spop_min::vector_min
|
Chris@49
|
333 (
|
Chris@49
|
334 const T1& x,
|
Chris@49
|
335 const typename arma_not_cx<typename T1::elem_type>::result* junk
|
Chris@49
|
336 )
|
Chris@49
|
337 {
|
Chris@49
|
338 arma_extra_debug_sigprint();
|
Chris@49
|
339 arma_ignore(junk);
|
Chris@49
|
340
|
Chris@49
|
341 typedef typename T1::elem_type eT;
|
Chris@49
|
342
|
Chris@49
|
343 const SpProxy<T1> p(x);
|
Chris@49
|
344
|
Chris@49
|
345 if(p.get_n_nonzero() == 0)
|
Chris@49
|
346 {
|
Chris@49
|
347 return eT(0);
|
Chris@49
|
348 }
|
Chris@49
|
349
|
Chris@49
|
350 if(SpProxy<T1>::must_use_iterator == false)
|
Chris@49
|
351 {
|
Chris@49
|
352 // direct access of values
|
Chris@49
|
353 if(p.get_n_nonzero() == p.get_n_elem())
|
Chris@49
|
354 {
|
Chris@49
|
355 return op_min::direct_min(p.get_values(), p.get_n_nonzero());
|
Chris@49
|
356 }
|
Chris@49
|
357 else
|
Chris@49
|
358 {
|
Chris@49
|
359 return std::min(eT(0), op_min::direct_min(p.get_values(), p.get_n_nonzero()));
|
Chris@49
|
360 }
|
Chris@49
|
361 }
|
Chris@49
|
362 else
|
Chris@49
|
363 {
|
Chris@49
|
364 // use iterator
|
Chris@49
|
365 typename SpProxy<T1>::const_iterator_type it = p.begin();
|
Chris@49
|
366
|
Chris@49
|
367 eT result = (*it);
|
Chris@49
|
368 ++it;
|
Chris@49
|
369
|
Chris@49
|
370 while(it != p.end())
|
Chris@49
|
371 {
|
Chris@49
|
372 if((*it) < result)
|
Chris@49
|
373 {
|
Chris@49
|
374 result = (*it);
|
Chris@49
|
375 }
|
Chris@49
|
376
|
Chris@49
|
377 ++it;
|
Chris@49
|
378 }
|
Chris@49
|
379
|
Chris@49
|
380 if(p.get_n_nonzero() == p.get_n_elem())
|
Chris@49
|
381 {
|
Chris@49
|
382 return result;
|
Chris@49
|
383 }
|
Chris@49
|
384 else
|
Chris@49
|
385 {
|
Chris@49
|
386 return std::min(eT(0), result);
|
Chris@49
|
387 }
|
Chris@49
|
388 }
|
Chris@49
|
389 }
|
Chris@49
|
390
|
Chris@49
|
391
|
Chris@49
|
392
|
Chris@49
|
393 template<typename T1>
|
Chris@49
|
394 inline
|
Chris@49
|
395 typename T1::elem_type
|
Chris@49
|
396 spop_min::vector_min
|
Chris@49
|
397 (
|
Chris@49
|
398 const T1& x,
|
Chris@49
|
399 const typename arma_cx_only<typename T1::elem_type>::result* junk
|
Chris@49
|
400 )
|
Chris@49
|
401 {
|
Chris@49
|
402 arma_extra_debug_sigprint();
|
Chris@49
|
403 arma_ignore(junk);
|
Chris@49
|
404
|
Chris@49
|
405 typedef typename T1::elem_type eT;
|
Chris@49
|
406 typedef typename get_pod_type<eT>::result T;
|
Chris@49
|
407
|
Chris@49
|
408 const SpProxy<T1> p(x);
|
Chris@49
|
409
|
Chris@49
|
410 if(p.get_n_nonzero() == 0)
|
Chris@49
|
411 {
|
Chris@49
|
412 return eT(0);
|
Chris@49
|
413 }
|
Chris@49
|
414
|
Chris@49
|
415 if(SpProxy<T1>::must_use_iterator == false)
|
Chris@49
|
416 {
|
Chris@49
|
417 // direct access of values
|
Chris@49
|
418 if(p.get_n_nonzero() == p.get_n_elem())
|
Chris@49
|
419 {
|
Chris@49
|
420 return op_min::direct_min(p.get_values(), p.get_n_nonzero());
|
Chris@49
|
421 }
|
Chris@49
|
422 else
|
Chris@49
|
423 {
|
Chris@49
|
424 const eT val1 = eT(0);
|
Chris@49
|
425 const eT val2 = op_min::direct_min(p.get_values(), p.get_n_nonzero());
|
Chris@49
|
426
|
Chris@49
|
427 return ( std::abs(val1) < std::abs(val2) ) ? val1 : val2;
|
Chris@49
|
428 }
|
Chris@49
|
429 }
|
Chris@49
|
430 else
|
Chris@49
|
431 {
|
Chris@49
|
432 // use iterator
|
Chris@49
|
433 typename SpProxy<T1>::const_iterator_type it = p.begin();
|
Chris@49
|
434
|
Chris@49
|
435 eT best_val_orig = *it;
|
Chris@49
|
436 T best_val_abs = std::abs(best_val_orig);
|
Chris@49
|
437
|
Chris@49
|
438 ++it;
|
Chris@49
|
439
|
Chris@49
|
440 while(it != p.end())
|
Chris@49
|
441 {
|
Chris@49
|
442 eT val_orig = *it;
|
Chris@49
|
443 T val_abs = std::abs(val_orig);
|
Chris@49
|
444
|
Chris@49
|
445 if(val_abs < best_val_abs)
|
Chris@49
|
446 {
|
Chris@49
|
447 best_val_abs = val_abs;
|
Chris@49
|
448 best_val_orig = val_orig;
|
Chris@49
|
449 }
|
Chris@49
|
450
|
Chris@49
|
451 ++it;
|
Chris@49
|
452 }
|
Chris@49
|
453
|
Chris@49
|
454 if(p.get_n_nonzero() == p.get_n_elem())
|
Chris@49
|
455 {
|
Chris@49
|
456 return best_val_orig;
|
Chris@49
|
457 }
|
Chris@49
|
458 else
|
Chris@49
|
459 {
|
Chris@49
|
460 const eT val1 = eT(0);
|
Chris@49
|
461
|
Chris@49
|
462 return ( std::abs(val1) < best_val_abs ) ? val1 : best_val_orig;
|
Chris@49
|
463 }
|
Chris@49
|
464 }
|
Chris@49
|
465 }
|
Chris@49
|
466
|
Chris@49
|
467
|
Chris@49
|
468
|
Chris@49
|
469 //! @}
|