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