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_sort_index
20 //! @{
21 
22 
23 
24 template<typename T1, bool sort_stable>
25 inline
26 bool
arma_sort_index_helper(Mat<uword> & out,const Proxy<T1> & P,const uword sort_type)27 arma_sort_index_helper(Mat<uword>& out, const Proxy<T1>& P, const uword sort_type)
28   {
29   arma_extra_debug_sigprint();
30 
31   typedef typename T1::elem_type eT;
32 
33   const uword n_elem = P.get_n_elem();
34 
35   out.set_size(n_elem, 1);
36 
37   std::vector< arma_sort_index_packet<eT> > packet_vec(n_elem);
38 
39   if(Proxy<T1>::use_at == false)
40     {
41     for(uword i=0; i<n_elem; ++i)
42       {
43       const eT val = P[i];
44 
45       if(arma_isnan(val))  { out.soft_reset(); return false; }
46 
47       packet_vec[i].val   = val;
48       packet_vec[i].index = i;
49       }
50     }
51   else
52     {
53     const uword n_rows = P.get_n_rows();
54     const uword n_cols = P.get_n_cols();
55 
56     uword i = 0;
57 
58     for(uword col=0; col < n_cols; ++col)
59     for(uword row=0; row < n_rows; ++row)
60       {
61       const eT val = P.at(row,col);
62 
63       if(arma_isnan(val))  { out.soft_reset(); return false; }
64 
65       packet_vec[i].val   = val;
66       packet_vec[i].index = i;
67 
68       ++i;
69       }
70     }
71 
72 
73   if(sort_type == 0)
74     {
75     // ascend
76 
77     arma_sort_index_helper_ascend<eT> comparator;
78 
79     if(sort_stable == false)
80       {
81       std::sort( packet_vec.begin(), packet_vec.end(), comparator );
82       }
83     else
84       {
85       std::stable_sort( packet_vec.begin(), packet_vec.end(), comparator );
86       }
87     }
88   else
89     {
90     // descend
91 
92     arma_sort_index_helper_descend<eT> comparator;
93 
94     if(sort_stable == false)
95       {
96       std::sort( packet_vec.begin(), packet_vec.end(), comparator );
97       }
98     else
99       {
100       std::stable_sort( packet_vec.begin(), packet_vec.end(), comparator );
101       }
102     }
103 
104   uword* out_mem = out.memptr();
105 
106   for(uword i=0; i<n_elem; ++i)
107     {
108     out_mem[i] = packet_vec[i].index;
109     }
110 
111   return true;
112   }
113 
114 
115 
116 template<typename T1>
117 inline
118 bool
apply_noalias(Mat<uword> & out,const Proxy<T1> & P,const uword sort_type)119 op_sort_index::apply_noalias(Mat<uword>& out, const Proxy<T1>& P, const uword sort_type)
120   {
121   arma_extra_debug_sigprint();
122 
123   return arma_sort_index_helper<T1,false>(out, P, sort_type);
124   }
125 
126 
127 
128 template<typename T1>
129 inline
130 void
apply(Mat<uword> & out,const mtOp<uword,T1,op_sort_index> & in)131 op_sort_index::apply(Mat<uword>& out, const mtOp<uword,T1,op_sort_index>& in)
132   {
133   arma_extra_debug_sigprint();
134 
135   const Proxy<T1> P(in.m);
136 
137   if(P.get_n_elem() == 0)  { out.set_size(0,1); return; }
138 
139   const uword sort_type = in.aux_uword_a;
140 
141   bool all_non_nan = false;
142 
143   if(P.is_alias(out))
144     {
145     Mat<uword> out2;
146 
147     all_non_nan = op_sort_index::apply_noalias(out2, P, sort_type);
148 
149     out.steal_mem(out2);
150     }
151   else
152     {
153     all_non_nan = op_sort_index::apply_noalias(out, P, sort_type);
154     }
155 
156   arma_debug_check( (all_non_nan == false), "sort_index(): detected NaN" );
157   }
158 
159 
160 
161 template<typename T1>
162 inline
163 bool
apply_noalias(Mat<uword> & out,const Proxy<T1> & P,const uword sort_type)164 op_stable_sort_index::apply_noalias(Mat<uword>& out, const Proxy<T1>& P, const uword sort_type)
165   {
166   arma_extra_debug_sigprint();
167 
168   return arma_sort_index_helper<T1,true>(out, P, sort_type);
169   }
170 
171 
172 
173 template<typename T1>
174 inline
175 void
apply(Mat<uword> & out,const mtOp<uword,T1,op_stable_sort_index> & in)176 op_stable_sort_index::apply(Mat<uword>& out, const mtOp<uword,T1,op_stable_sort_index>& in)
177   {
178   arma_extra_debug_sigprint();
179 
180   const Proxy<T1> P(in.m);
181 
182   if(P.get_n_elem() == 0)  { out.set_size(0,1); return; }
183 
184   const uword sort_type = in.aux_uword_a;
185 
186   bool all_non_nan = false;
187 
188   if(P.is_alias(out))
189     {
190     Mat<uword> out2;
191 
192     all_non_nan = op_stable_sort_index::apply_noalias(out2, P, sort_type);
193 
194     out.steal_mem(out2);
195     }
196   else
197     {
198     all_non_nan = op_stable_sort_index::apply_noalias(out, P, sort_type);
199     }
200 
201   arma_debug_check( (all_non_nan == false), "stable_sort_index(): detected NaN" );
202   }
203 
204 
205 
206 //! @}
207