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