1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17
18
19 //! \addtogroup op_max
20 //! @{
21
22
23
24 template<typename T1>
25 inline
26 void
apply(Mat<typename T1::elem_type> & out,const Op<T1,op_max> & in)27 op_max::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_max>& in)
28 {
29 arma_extra_debug_sigprint();
30
31 typedef typename T1::elem_type eT;
32
33 const uword dim = in.aux_uword_a;
34 arma_debug_check( (dim > 1), "max(): parameter 'dim' must be 0 or 1" );
35
36 const quasi_unwrap<T1> U(in.m);
37 const Mat<eT>& X = U.M;
38
39 if(U.is_alias(out) == false)
40 {
41 op_max::apply_noalias(out, X, dim);
42 }
43 else
44 {
45 Mat<eT> tmp;
46
47 op_max::apply_noalias(tmp, X, dim);
48
49 out.steal_mem(tmp);
50 }
51 }
52
53
54
55 template<typename eT>
56 inline
57 void
apply_noalias(Mat<eT> & out,const Mat<eT> & X,const uword dim,const typename arma_not_cx<eT>::result * junk)58 op_max::apply_noalias(Mat<eT>& out, const Mat<eT>& X, const uword dim, const typename arma_not_cx<eT>::result* junk)
59 {
60 arma_extra_debug_sigprint();
61 arma_ignore(junk);
62
63 const uword X_n_rows = X.n_rows;
64 const uword X_n_cols = X.n_cols;
65
66 if(dim == 0)
67 {
68 arma_extra_debug_print("op_max::apply(): dim = 0");
69
70 out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols);
71
72 if(X_n_rows == 0) { return; }
73
74 eT* out_mem = out.memptr();
75
76 for(uword col=0; col<X_n_cols; ++col)
77 {
78 out_mem[col] = op_max::direct_max( X.colptr(col), X_n_rows );
79 }
80 }
81 else
82 if(dim == 1)
83 {
84 arma_extra_debug_print("op_max::apply(): dim = 1");
85
86 out.set_size(X_n_rows, (X_n_cols > 0) ? 1 : 0);
87
88 if(X_n_cols == 0) { return; }
89
90 eT* out_mem = out.memptr();
91
92 arrayops::copy(out_mem, X.colptr(0), X_n_rows);
93
94 for(uword col=1; col<X_n_cols; ++col)
95 {
96 const eT* col_mem = X.colptr(col);
97
98 for(uword row=0; row<X_n_rows; ++row)
99 {
100 const eT col_val = col_mem[row];
101
102 if(col_val > out_mem[row]) { out_mem[row] = col_val; }
103 }
104 }
105 }
106 }
107
108
109
110 template<typename eT>
111 inline
112 void
apply_noalias(Mat<eT> & out,const Mat<eT> & X,const uword dim,const typename arma_cx_only<eT>::result * junk)113 op_max::apply_noalias(Mat<eT>& out, const Mat<eT>& X, const uword dim, const typename arma_cx_only<eT>::result* junk)
114 {
115 arma_extra_debug_sigprint();
116 arma_ignore(junk);
117
118 const uword X_n_rows = X.n_rows;
119 const uword X_n_cols = X.n_cols;
120
121 if(dim == 0)
122 {
123 arma_extra_debug_print("op_max::apply(): dim = 0");
124
125 out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols);
126
127 if(X_n_rows == 0) { return; }
128
129 eT* out_mem = out.memptr();
130
131 for(uword col=0; col<X_n_cols; ++col)
132 {
133 out_mem[col] = op_max::direct_max( X.colptr(col), X_n_rows );
134 }
135 }
136 else
137 if(dim == 1)
138 {
139 arma_extra_debug_print("op_max::apply(): dim = 1");
140
141 out.set_size(X_n_rows, (X_n_cols > 0) ? 1 : 0);
142
143 if(X_n_cols == 0) { return; }
144
145 eT* out_mem = out.memptr();
146
147 for(uword row=0; row<X_n_rows; ++row)
148 {
149 out_mem[row] = op_max::direct_max( X, row );
150 }
151 }
152 }
153
154
155
156 template<typename T1>
157 inline
158 void
apply(Cube<typename T1::elem_type> & out,const OpCube<T1,op_max> & in)159 op_max::apply(Cube<typename T1::elem_type>& out, const OpCube<T1,op_max>& in)
160 {
161 arma_extra_debug_sigprint();
162
163 typedef typename T1::elem_type eT;
164
165 const uword dim = in.aux_uword_a;
166 arma_debug_check( (dim > 2), "max(): parameter 'dim' must be 0 or 1 or 2" );
167
168 const unwrap_cube<T1> U(in.m);
169
170 if(U.is_alias(out) == false)
171 {
172 op_max::apply_noalias(out, U.M, dim);
173 }
174 else
175 {
176 Cube<eT> tmp;
177
178 op_max::apply_noalias(tmp, U.M, dim);
179
180 out.steal_mem(tmp);
181 }
182 }
183
184
185
186 template<typename eT>
187 inline
188 void
apply_noalias(Cube<eT> & out,const Cube<eT> & X,const uword dim,const typename arma_not_cx<eT>::result * junk)189 op_max::apply_noalias(Cube<eT>& out, const Cube<eT>& X, const uword dim, const typename arma_not_cx<eT>::result* junk)
190 {
191 arma_extra_debug_sigprint();
192 arma_ignore(junk);
193
194 const uword X_n_rows = X.n_rows;
195 const uword X_n_cols = X.n_cols;
196 const uword X_n_slices = X.n_slices;
197
198 if(dim == 0)
199 {
200 arma_extra_debug_print("op_max::apply(): dim = 0");
201
202 out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols, X_n_slices);
203
204 if(X_n_rows == 0) { return; }
205
206 for(uword slice=0; slice < X_n_slices; ++slice)
207 {
208 eT* out_mem = out.slice_memptr(slice);
209
210 for(uword col=0; col < X_n_cols; ++col)
211 {
212 out_mem[col] = op_max::direct_max( X.slice_colptr(slice,col), X_n_rows );
213 }
214 }
215 }
216 else
217 if(dim == 1)
218 {
219 arma_extra_debug_print("op_max::apply(): dim = 1");
220
221 out.set_size(X_n_rows, (X_n_cols > 0) ? 1 : 0, X_n_slices);
222
223 if(X_n_cols == 0) { return; }
224
225 for(uword slice=0; slice < X_n_slices; ++slice)
226 {
227 eT* out_mem = out.slice_memptr(slice);
228
229 arrayops::copy(out_mem, X.slice_colptr(slice,0), X_n_rows);
230
231 for(uword col=1; col < X_n_cols; ++col)
232 {
233 const eT* col_mem = X.slice_colptr(slice,col);
234
235 for(uword row=0; row < X_n_rows; ++row)
236 {
237 const eT col_val = col_mem[row];
238
239 if(col_val > out_mem[row]) { out_mem[row] = col_val; }
240 }
241 }
242 }
243 }
244 else
245 if(dim == 2)
246 {
247 arma_extra_debug_print("op_max::apply(): dim = 2");
248
249 out.set_size(X_n_rows, X_n_cols, (X_n_slices > 0) ? 1 : 0);
250
251 if(X_n_slices == 0) { return; }
252
253 const uword N = X.n_elem_slice;
254
255 eT* out_mem = out.slice_memptr(0);
256
257 arrayops::copy(out_mem, X.slice_memptr(0), N);
258
259 for(uword slice=1; slice < X_n_slices; ++slice)
260 {
261 const eT* X_mem = X.slice_memptr(slice);
262
263 for(uword i=0; i < N; ++i)
264 {
265 const eT val = X_mem[i];
266
267 if(val > out_mem[i]) { out_mem[i] = val; }
268 }
269 }
270 }
271 }
272
273
274
275 template<typename eT>
276 inline
277 void
apply_noalias(Cube<eT> & out,const Cube<eT> & X,const uword dim,const typename arma_cx_only<eT>::result * junk)278 op_max::apply_noalias(Cube<eT>& out, const Cube<eT>& X, const uword dim, const typename arma_cx_only<eT>::result* junk)
279 {
280 arma_extra_debug_sigprint();
281 arma_ignore(junk);
282
283 const uword X_n_rows = X.n_rows;
284 const uword X_n_cols = X.n_cols;
285 const uword X_n_slices = X.n_slices;
286
287 if(dim == 0)
288 {
289 arma_extra_debug_print("op_max::apply(): dim = 0");
290
291 out.set_size((X_n_rows > 0) ? 1 : 0, X_n_cols, X_n_slices);
292
293 if(X_n_rows == 0) { return; }
294
295 for(uword slice=0; slice < X_n_slices; ++slice)
296 {
297 eT* out_mem = out.slice_memptr(slice);
298
299 for(uword col=0; col < X_n_cols; ++col)
300 {
301 out_mem[col] = op_max::direct_max( X.slice_colptr(slice,col), X_n_rows );
302 }
303 }
304 }
305 else
306 if(dim == 1)
307 {
308 arma_extra_debug_print("op_max::apply(): dim = 1");
309
310 out.set_size(X_n_rows, (X_n_cols > 0) ? 1 : 0, X_n_slices);
311
312 if(X_n_cols == 0) { return; }
313
314 for(uword slice=0; slice < X_n_slices; ++slice)
315 {
316 eT* out_mem = out.slice_memptr(slice);
317
318 const Mat<eT> tmp('j', X.slice_memptr(slice), X_n_rows, X_n_cols);
319
320 for(uword row=0; row < X_n_rows; ++row)
321 {
322 out_mem[row] = op_max::direct_max(tmp, row);
323 }
324 }
325 }
326 else
327 if(dim == 2)
328 {
329 arma_extra_debug_print("op_max::apply(): dim = 2");
330
331 out.set_size(X_n_rows, X_n_cols, (X_n_slices > 0) ? 1 : 0);
332
333 if(X_n_slices == 0) { return; }
334
335 const uword N = X.n_elem_slice;
336
337 eT* out_mem = out.slice_memptr(0);
338
339 arrayops::copy(out_mem, X.slice_memptr(0), N);
340
341 for(uword slice=1; slice < X_n_slices; ++slice)
342 {
343 const eT* X_mem = X.slice_memptr(slice);
344
345 for(uword i=0; i < N; ++i)
346 {
347 const eT& val = X_mem[i];
348
349 if(std::abs(val) > std::abs(out_mem[i])) { out_mem[i] = val; }
350 }
351 }
352 }
353 }
354
355
356
357 template<typename eT>
358 inline
359 eT
direct_max(const eT * const X,const uword n_elem)360 op_max::direct_max(const eT* const X, const uword n_elem)
361 {
362 arma_extra_debug_sigprint();
363
364 eT max_val = priv::most_neg<eT>();
365
366 uword i,j;
367 for(i=0, j=1; j<n_elem; i+=2, j+=2)
368 {
369 const eT X_i = X[i];
370 const eT X_j = X[j];
371
372 if(X_i > max_val) { max_val = X_i; }
373 if(X_j > max_val) { max_val = X_j; }
374 }
375
376 if(i < n_elem)
377 {
378 const eT X_i = X[i];
379
380 if(X_i > max_val) { max_val = X_i; }
381 }
382
383 return max_val;
384 }
385
386
387
388 template<typename eT>
389 inline
390 eT
direct_max(const eT * const X,const uword n_elem,uword & index_of_max_val)391 op_max::direct_max(const eT* const X, const uword n_elem, uword& index_of_max_val)
392 {
393 arma_extra_debug_sigprint();
394
395 eT max_val = priv::most_neg<eT>();
396
397 uword best_index = 0;
398
399 uword i,j;
400 for(i=0, j=1; j<n_elem; i+=2, j+=2)
401 {
402 const eT X_i = X[i];
403 const eT X_j = X[j];
404
405 if(X_i > max_val)
406 {
407 max_val = X_i;
408 best_index = i;
409 }
410
411 if(X_j > max_val)
412 {
413 max_val = X_j;
414 best_index = j;
415 }
416 }
417
418 if(i < n_elem)
419 {
420 const eT X_i = X[i];
421
422 if(X_i > max_val)
423 {
424 max_val = X_i;
425 best_index = i;
426 }
427 }
428
429 index_of_max_val = best_index;
430
431 return max_val;
432 }
433
434
435
436 template<typename eT>
437 inline
438 eT
direct_max(const Mat<eT> & X,const uword row)439 op_max::direct_max(const Mat<eT>& X, const uword row)
440 {
441 arma_extra_debug_sigprint();
442
443 const uword X_n_cols = X.n_cols;
444
445 eT max_val = priv::most_neg<eT>();
446
447 uword i,j;
448 for(i=0, j=1; j < X_n_cols; i+=2, j+=2)
449 {
450 const eT tmp_i = X.at(row,i);
451 const eT tmp_j = X.at(row,j);
452
453 if(tmp_i > max_val) { max_val = tmp_i; }
454 if(tmp_j > max_val) { max_val = tmp_j; }
455 }
456
457 if(i < X_n_cols)
458 {
459 const eT tmp_i = X.at(row,i);
460
461 if(tmp_i > max_val) { max_val = tmp_i; }
462 }
463
464 return max_val;
465 }
466
467
468
469 template<typename eT>
470 inline
471 eT
max(const subview<eT> & X)472 op_max::max(const subview<eT>& X)
473 {
474 arma_extra_debug_sigprint();
475
476 if(X.n_elem == 0)
477 {
478 arma_debug_check(true, "max(): object has no elements");
479
480 return Datum<eT>::nan;
481 }
482
483 const uword X_n_rows = X.n_rows;
484 const uword X_n_cols = X.n_cols;
485
486 eT max_val = priv::most_neg<eT>();
487
488 if(X_n_rows == 1)
489 {
490 const Mat<eT>& A = X.m;
491
492 const uword start_row = X.aux_row1;
493 const uword start_col = X.aux_col1;
494
495 const uword end_col_p1 = start_col + X_n_cols;
496
497 uword i,j;
498 for(i=start_col, j=start_col+1; j < end_col_p1; i+=2, j+=2)
499 {
500 const eT tmp_i = A.at(start_row, i);
501 const eT tmp_j = A.at(start_row, j);
502
503 if(tmp_i > max_val) { max_val = tmp_i; }
504 if(tmp_j > max_val) { max_val = tmp_j; }
505 }
506
507 if(i < end_col_p1)
508 {
509 const eT tmp_i = A.at(start_row, i);
510
511 if(tmp_i > max_val) { max_val = tmp_i; }
512 }
513 }
514 else
515 {
516 for(uword col=0; col < X_n_cols; ++col)
517 {
518 max_val = (std::max)(max_val, op_max::direct_max(X.colptr(col), X_n_rows));
519 }
520 }
521
522 return max_val;
523 }
524
525
526
527 template<typename T1>
528 inline
529 typename arma_not_cx<typename T1::elem_type>::result
max(const Base<typename T1::elem_type,T1> & X)530 op_max::max(const Base<typename T1::elem_type,T1>& X)
531 {
532 arma_extra_debug_sigprint();
533
534 typedef typename T1::elem_type eT;
535
536 const Proxy<T1> P(X.get_ref());
537
538 const uword n_elem = P.get_n_elem();
539
540 if(n_elem == 0)
541 {
542 arma_debug_check(true, "max(): object has no elements");
543
544 return Datum<eT>::nan;
545 }
546
547 eT max_val = priv::most_neg<eT>();
548
549 if(Proxy<T1>::use_at == false)
550 {
551 typedef typename Proxy<T1>::ea_type ea_type;
552
553 ea_type A = P.get_ea();
554
555 uword i,j;
556
557 for(i=0, j=1; j<n_elem; i+=2, j+=2)
558 {
559 const eT tmp_i = A[i];
560 const eT tmp_j = A[j];
561
562 if(tmp_i > max_val) { max_val = tmp_i; }
563 if(tmp_j > max_val) { max_val = tmp_j; }
564 }
565
566 if(i < n_elem)
567 {
568 const eT tmp_i = A[i];
569
570 if(tmp_i > max_val) { max_val = tmp_i; }
571 }
572 }
573 else
574 {
575 const uword n_rows = P.get_n_rows();
576 const uword n_cols = P.get_n_cols();
577
578 if(n_rows == 1)
579 {
580 uword i,j;
581 for(i=0, j=1; j < n_cols; i+=2, j+=2)
582 {
583 const eT tmp_i = P.at(0,i);
584 const eT tmp_j = P.at(0,j);
585
586 if(tmp_i > max_val) { max_val = tmp_i; }
587 if(tmp_j > max_val) { max_val = tmp_j; }
588 }
589
590 if(i < n_cols)
591 {
592 const eT tmp_i = P.at(0,i);
593
594 if(tmp_i > max_val) { max_val = tmp_i; }
595 }
596 }
597 else
598 {
599 for(uword col=0; col < n_cols; ++col)
600 {
601 uword i,j;
602 for(i=0, j=1; j < n_rows; i+=2, j+=2)
603 {
604 const eT tmp_i = P.at(i,col);
605 const eT tmp_j = P.at(j,col);
606
607 if(tmp_i > max_val) { max_val = tmp_i; }
608 if(tmp_j > max_val) { max_val = tmp_j; }
609 }
610
611 if(i < n_rows)
612 {
613 const eT tmp_i = P.at(i,col);
614
615 if(tmp_i > max_val) { max_val = tmp_i; }
616 }
617 }
618 }
619 }
620
621 return max_val;
622 }
623
624
625
626 template<typename T1>
627 inline
628 typename arma_not_cx<typename T1::elem_type>::result
max(const BaseCube<typename T1::elem_type,T1> & X)629 op_max::max(const BaseCube<typename T1::elem_type,T1>& X)
630 {
631 arma_extra_debug_sigprint();
632
633 typedef typename T1::elem_type eT;
634
635 const ProxyCube<T1> P(X.get_ref());
636
637 const uword n_elem = P.get_n_elem();
638
639 if(n_elem == 0)
640 {
641 arma_debug_check(true, "max(): object has no elements");
642
643 return Datum<eT>::nan;
644 }
645
646 eT max_val = priv::most_neg<eT>();
647
648 if(ProxyCube<T1>::use_at == false)
649 {
650 typedef typename ProxyCube<T1>::ea_type ea_type;
651
652 ea_type A = P.get_ea();
653
654 uword i,j;
655
656 for(i=0, j=1; j<n_elem; i+=2, j+=2)
657 {
658 const eT tmp_i = A[i];
659 const eT tmp_j = A[j];
660
661 if(tmp_i > max_val) { max_val = tmp_i; }
662 if(tmp_j > max_val) { max_val = tmp_j; }
663 }
664
665 if(i < n_elem)
666 {
667 const eT tmp_i = A[i];
668
669 if(tmp_i > max_val) { max_val = tmp_i; }
670 }
671 }
672 else
673 {
674 const uword n_rows = P.get_n_rows();
675 const uword n_cols = P.get_n_cols();
676 const uword n_slices = P.get_n_slices();
677
678 for(uword slice=0; slice < n_slices; ++slice)
679 for(uword col=0; col < n_cols; ++col )
680 for(uword row=0; row < n_rows; ++row )
681 {
682 const eT tmp = P.at(row,col,slice);
683
684 if(tmp > max_val) { max_val = tmp; }
685 }
686 }
687
688 return max_val;
689 }
690
691
692
693 template<typename T1>
694 inline
695 typename arma_not_cx<typename T1::elem_type>::result
max_with_index(const Proxy<T1> & P,uword & index_of_max_val)696 op_max::max_with_index(const Proxy<T1>& P, uword& index_of_max_val)
697 {
698 arma_extra_debug_sigprint();
699
700 typedef typename T1::elem_type eT;
701
702 const uword n_elem = P.get_n_elem();
703
704 if(n_elem == 0)
705 {
706 arma_debug_check(true, "max(): object has no elements");
707
708 return Datum<eT>::nan;
709 }
710
711 eT best_val = priv::most_neg<eT>();
712 uword best_index = 0;
713
714 if(Proxy<T1>::use_at == false)
715 {
716 typedef typename Proxy<T1>::ea_type ea_type;
717
718 ea_type A = P.get_ea();
719
720 for(uword i=0; i<n_elem; ++i)
721 {
722 const eT tmp = A[i];
723
724 if(tmp > best_val) { best_val = tmp; best_index = i; }
725 }
726 }
727 else
728 {
729 const uword n_rows = P.get_n_rows();
730 const uword n_cols = P.get_n_cols();
731
732 if(n_rows == 1)
733 {
734 for(uword i=0; i < n_cols; ++i)
735 {
736 const eT tmp = P.at(0,i);
737
738 if(tmp > best_val) { best_val = tmp; best_index = i; }
739 }
740 }
741 else
742 if(n_cols == 1)
743 {
744 for(uword i=0; i < n_rows; ++i)
745 {
746 const eT tmp = P.at(i,0);
747
748 if(tmp > best_val) { best_val = tmp; best_index = i; }
749 }
750 }
751 else
752 {
753 uword count = 0;
754
755 for(uword col=0; col < n_cols; ++col)
756 for(uword row=0; row < n_rows; ++row)
757 {
758 const eT tmp = P.at(row,col);
759
760 if(tmp > best_val) { best_val = tmp; best_index = count; }
761
762 ++count;
763 }
764 }
765 }
766
767 index_of_max_val = best_index;
768
769 return best_val;
770 }
771
772
773
774 template<typename T1>
775 inline
776 typename arma_not_cx<typename T1::elem_type>::result
max_with_index(const ProxyCube<T1> & P,uword & index_of_max_val)777 op_max::max_with_index(const ProxyCube<T1>& P, uword& index_of_max_val)
778 {
779 arma_extra_debug_sigprint();
780
781 typedef typename T1::elem_type eT;
782
783 const uword n_elem = P.get_n_elem();
784
785 if(n_elem == 0)
786 {
787 arma_debug_check(true, "max(): object has no elements");
788
789 return Datum<eT>::nan;
790 }
791
792 eT best_val = priv::most_neg<eT>();
793 uword best_index = 0;
794
795 if(ProxyCube<T1>::use_at == false)
796 {
797 typedef typename ProxyCube<T1>::ea_type ea_type;
798
799 ea_type A = P.get_ea();
800
801 for(uword i=0; i < n_elem; ++i)
802 {
803 const eT tmp = A[i];
804
805 if(tmp > best_val) { best_val = tmp; best_index = i; }
806 }
807 }
808 else
809 {
810 const uword n_rows = P.get_n_rows();
811 const uword n_cols = P.get_n_cols();
812 const uword n_slices = P.get_n_slices();
813
814 uword count = 0;
815
816 for(uword slice=0; slice < n_slices; ++slice)
817 for(uword col=0; col < n_cols; ++col )
818 for(uword row=0; row < n_rows; ++row )
819 {
820 const eT tmp = P.at(row,col,slice);
821
822 if(tmp > best_val) { best_val = tmp; best_index = count; }
823
824 ++count;
825 }
826 }
827
828 index_of_max_val = best_index;
829
830 return best_val;
831 }
832
833
834
835 template<typename T>
836 inline
837 std::complex<T>
direct_max(const std::complex<T> * const X,const uword n_elem)838 op_max::direct_max(const std::complex<T>* const X, const uword n_elem)
839 {
840 arma_extra_debug_sigprint();
841
842 uword index = 0;
843 T max_val = priv::most_neg<T>();
844
845 for(uword i=0; i<n_elem; ++i)
846 {
847 const T tmp_val = std::abs(X[i]);
848
849 if(tmp_val > max_val)
850 {
851 max_val = tmp_val;
852 index = i;
853 }
854 }
855
856 return X[index];
857 }
858
859
860
861 template<typename T>
862 inline
863 std::complex<T>
direct_max(const std::complex<T> * const X,const uword n_elem,uword & index_of_max_val)864 op_max::direct_max(const std::complex<T>* const X, const uword n_elem, uword& index_of_max_val)
865 {
866 arma_extra_debug_sigprint();
867
868 uword index = 0;
869 T max_val = priv::most_neg<T>();
870
871 for(uword i=0; i<n_elem; ++i)
872 {
873 const T tmp_val = std::abs(X[i]);
874
875 if(tmp_val > max_val)
876 {
877 max_val = tmp_val;
878 index = i;
879 }
880 }
881
882 index_of_max_val = index;
883
884 return X[index];
885 }
886
887
888
889 template<typename T>
890 inline
891 std::complex<T>
direct_max(const Mat<std::complex<T>> & X,const uword row)892 op_max::direct_max(const Mat< std::complex<T> >& X, const uword row)
893 {
894 arma_extra_debug_sigprint();
895
896 const uword X_n_cols = X.n_cols;
897
898 uword index = 0;
899 T max_val = priv::most_neg<T>();
900
901 for(uword col=0; col<X_n_cols; ++col)
902 {
903 const T tmp_val = std::abs(X.at(row,col));
904
905 if(tmp_val > max_val)
906 {
907 max_val = tmp_val;
908 index = col;
909 }
910 }
911
912 return X.at(row,index);
913 }
914
915
916
917 template<typename T>
918 inline
919 std::complex<T>
max(const subview<std::complex<T>> & X)920 op_max::max(const subview< std::complex<T> >& X)
921 {
922 arma_extra_debug_sigprint();
923
924 typedef typename std::complex<T> eT;
925
926 if(X.n_elem == 0)
927 {
928 arma_debug_check(true, "max(): object has no elements");
929
930 return Datum<eT>::nan;
931 }
932
933 const Mat<eT>& A = X.m;
934
935 const uword X_n_rows = X.n_rows;
936 const uword X_n_cols = X.n_cols;
937
938 const uword start_row = X.aux_row1;
939 const uword start_col = X.aux_col1;
940
941 const uword end_row_p1 = start_row + X_n_rows;
942 const uword end_col_p1 = start_col + X_n_cols;
943
944 T max_val = priv::most_neg<T>();
945
946 uword best_row = 0;
947 uword best_col = 0;
948
949 if(X_n_rows == 1)
950 {
951 best_col = 0;
952
953 for(uword col=start_col; col < end_col_p1; ++col)
954 {
955 const T tmp_val = std::abs( A.at(start_row, col) );
956
957 if(tmp_val > max_val)
958 {
959 max_val = tmp_val;
960 best_col = col;
961 }
962 }
963
964 best_row = start_row;
965 }
966 else
967 {
968 for(uword col=start_col; col < end_col_p1; ++col)
969 for(uword row=start_row; row < end_row_p1; ++row)
970 {
971 const T tmp_val = std::abs( A.at(row, col) );
972
973 if(tmp_val > max_val)
974 {
975 max_val = tmp_val;
976 best_row = row;
977 best_col = col;
978 }
979 }
980 }
981
982 return A.at(best_row, best_col);
983 }
984
985
986
987 template<typename T1>
988 inline
989 typename arma_cx_only<typename T1::elem_type>::result
max(const Base<typename T1::elem_type,T1> & X)990 op_max::max(const Base<typename T1::elem_type,T1>& X)
991 {
992 arma_extra_debug_sigprint();
993
994 typedef typename T1::elem_type eT;
995 typedef typename get_pod_type<eT>::result T;
996
997 const Proxy<T1> P(X.get_ref());
998
999 const uword n_elem = P.get_n_elem();
1000
1001 if(n_elem == 0)
1002 {
1003 arma_debug_check(true, "max(): object has no elements");
1004
1005 return Datum<eT>::nan;
1006 }
1007
1008 T max_val = priv::most_neg<T>();
1009
1010 if(Proxy<T1>::use_at == false)
1011 {
1012 typedef typename Proxy<T1>::ea_type ea_type;
1013
1014 ea_type A = P.get_ea();
1015
1016 uword index = 0;
1017
1018 for(uword i=0; i<n_elem; ++i)
1019 {
1020 const T tmp = std::abs(A[i]);
1021
1022 if(tmp > max_val)
1023 {
1024 max_val = tmp;
1025 index = i;
1026 }
1027 }
1028
1029 return( A[index] );
1030 }
1031 else
1032 {
1033 const uword n_rows = P.get_n_rows();
1034 const uword n_cols = P.get_n_cols();
1035
1036 uword best_row = 0;
1037 uword best_col = 0;
1038
1039 if(n_rows == 1)
1040 {
1041 for(uword col=0; col < n_cols; ++col)
1042 {
1043 const T tmp = std::abs(P.at(0,col));
1044
1045 if(tmp > max_val)
1046 {
1047 max_val = tmp;
1048 best_col = col;
1049 }
1050 }
1051 }
1052 else
1053 {
1054 for(uword col=0; col < n_cols; ++col)
1055 for(uword row=0; row < n_rows; ++row)
1056 {
1057 const T tmp = std::abs(P.at(row,col));
1058
1059 if(tmp > max_val)
1060 {
1061 max_val = tmp;
1062
1063 best_row = row;
1064 best_col = col;
1065 }
1066 }
1067 }
1068
1069 return P.at(best_row, best_col);
1070 }
1071 }
1072
1073
1074
1075 template<typename T1>
1076 inline
1077 typename arma_cx_only<typename T1::elem_type>::result
max(const BaseCube<typename T1::elem_type,T1> & X)1078 op_max::max(const BaseCube<typename T1::elem_type,T1>& X)
1079 {
1080 arma_extra_debug_sigprint();
1081
1082 typedef typename T1::elem_type eT;
1083 typedef typename get_pod_type<eT>::result T;
1084
1085 const ProxyCube<T1> P(X.get_ref());
1086
1087 const uword n_elem = P.get_n_elem();
1088
1089 if(n_elem == 0)
1090 {
1091 arma_debug_check(true, "max(): object has no elements");
1092
1093 return Datum<eT>::nan;
1094 }
1095
1096 T max_val = priv::most_neg<T>();
1097
1098 if(ProxyCube<T1>::use_at == false)
1099 {
1100 typedef typename ProxyCube<T1>::ea_type ea_type;
1101
1102 ea_type A = P.get_ea();
1103
1104 uword index = 0;
1105
1106 for(uword i=0; i<n_elem; ++i)
1107 {
1108 const T tmp = std::abs(A[i]);
1109
1110 if(tmp > max_val)
1111 {
1112 max_val = tmp;
1113 index = i;
1114 }
1115 }
1116
1117 return( A[index] );
1118 }
1119 else
1120 {
1121 const uword n_rows = P.get_n_rows();
1122 const uword n_cols = P.get_n_cols();
1123 const uword n_slices = P.get_n_slices();
1124
1125 eT max_val_orig = eT(0);
1126
1127 for(uword slice=0; slice < n_slices; ++slice)
1128 for(uword col=0; col < n_cols; ++col )
1129 for(uword row=0; row < n_rows; ++row )
1130 {
1131 const eT tmp_orig = P.at(row,col,slice);
1132 const T tmp = std::abs(tmp_orig);
1133
1134 if(tmp > max_val)
1135 {
1136 max_val = tmp;
1137 max_val_orig = tmp_orig;
1138 }
1139 }
1140
1141 return max_val_orig;
1142 }
1143 }
1144
1145
1146
1147 template<typename T1>
1148 inline
1149 typename arma_cx_only<typename T1::elem_type>::result
max_with_index(const Proxy<T1> & P,uword & index_of_max_val)1150 op_max::max_with_index(const Proxy<T1>& P, uword& index_of_max_val)
1151 {
1152 arma_extra_debug_sigprint();
1153
1154 typedef typename T1::elem_type eT;
1155 typedef typename get_pod_type<eT>::result T;
1156
1157 const uword n_elem = P.get_n_elem();
1158
1159 if(n_elem == 0)
1160 {
1161 arma_debug_check(true, "max(): object has no elements");
1162
1163 return Datum<eT>::nan;
1164 }
1165
1166 T best_val = priv::most_neg<T>();
1167
1168 if(Proxy<T1>::use_at == false)
1169 {
1170 typedef typename Proxy<T1>::ea_type ea_type;
1171
1172 ea_type A = P.get_ea();
1173
1174 uword best_index = 0;
1175
1176 for(uword i=0; i<n_elem; ++i)
1177 {
1178 const T tmp = std::abs(A[i]);
1179
1180 if(tmp > best_val) { best_val = tmp; best_index = i; }
1181 }
1182
1183 index_of_max_val = best_index;
1184
1185 return( A[best_index] );
1186 }
1187 else
1188 {
1189 const uword n_rows = P.get_n_rows();
1190 const uword n_cols = P.get_n_cols();
1191
1192 uword best_row = 0;
1193 uword best_col = 0;
1194 uword best_index = 0;
1195
1196 if(n_rows == 1)
1197 {
1198 for(uword col=0; col < n_cols; ++col)
1199 {
1200 const T tmp = std::abs(P.at(0,col));
1201
1202 if(tmp > best_val) { best_val = tmp; best_col = col; }
1203 }
1204
1205 best_index = best_col;
1206 }
1207 else
1208 if(n_cols == 1)
1209 {
1210 for(uword row=0; row < n_rows; ++row)
1211 {
1212 const T tmp = std::abs(P.at(row,0));
1213
1214 if(tmp > best_val) { best_val = tmp; best_row = row; }
1215 }
1216
1217 best_index = best_row;
1218 }
1219 else
1220 {
1221 uword count = 0;
1222
1223 for(uword col=0; col < n_cols; ++col)
1224 for(uword row=0; row < n_rows; ++row)
1225 {
1226 const T tmp = std::abs(P.at(row,col));
1227
1228 if(tmp > best_val)
1229 {
1230 best_val = tmp;
1231
1232 best_row = row;
1233 best_col = col;
1234
1235 best_index = count;
1236 }
1237
1238 ++count;
1239 }
1240 }
1241
1242 index_of_max_val = best_index;
1243
1244 return P.at(best_row, best_col);
1245 }
1246 }
1247
1248
1249
1250 template<typename T1>
1251 inline
1252 typename arma_cx_only<typename T1::elem_type>::result
max_with_index(const ProxyCube<T1> & P,uword & index_of_max_val)1253 op_max::max_with_index(const ProxyCube<T1>& P, uword& index_of_max_val)
1254 {
1255 arma_extra_debug_sigprint();
1256
1257 typedef typename T1::elem_type eT;
1258 typedef typename get_pod_type<eT>::result T;
1259
1260 const uword n_elem = P.get_n_elem();
1261
1262 if(n_elem == 0)
1263 {
1264 arma_debug_check(true, "max(): object has no elements");
1265
1266 return Datum<eT>::nan;
1267 }
1268
1269 T best_val = priv::most_neg<T>();
1270
1271 if(ProxyCube<T1>::use_at == false)
1272 {
1273 typedef typename ProxyCube<T1>::ea_type ea_type;
1274
1275 ea_type A = P.get_ea();
1276
1277 uword best_index = 0;
1278
1279 for(uword i=0; i < n_elem; ++i)
1280 {
1281 const T tmp = std::abs(A[i]);
1282
1283 if(tmp > best_val) { best_val = tmp; best_index = i; }
1284 }
1285
1286 index_of_max_val = best_index;
1287
1288 return( A[best_index] );
1289 }
1290 else
1291 {
1292 const uword n_rows = P.get_n_rows();
1293 const uword n_cols = P.get_n_cols();
1294 const uword n_slices = P.get_n_slices();
1295
1296 eT best_val_orig = eT(0);
1297 uword best_index = 0;
1298 uword count = 0;
1299
1300 for(uword slice=0; slice < n_slices; ++slice)
1301 for(uword col=0; col < n_cols; ++col )
1302 for(uword row=0; row < n_rows; ++row )
1303 {
1304 const eT tmp_orig = P.at(row,col,slice);
1305 const T tmp = std::abs(tmp_orig);
1306
1307 if(tmp > best_val)
1308 {
1309 best_val = tmp;
1310 best_val_orig = tmp_orig;
1311 best_index = count;
1312 }
1313
1314 ++count;
1315 }
1316
1317 index_of_max_val = best_index;
1318
1319 return best_val_orig;
1320 }
1321 }
1322
1323
1324
1325 //! @}
1326