Chris@49
|
1 // Copyright (C) 2010-2013 NICTA (www.nicta.com.au)
|
Chris@49
|
2 // Copyright (C) 2010-2013 Conrad Sanderson
|
Chris@49
|
3 // Copyright (C) 2010 Dimitrios Bouzas
|
Chris@49
|
4 //
|
Chris@49
|
5 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
8
|
Chris@49
|
9
|
Chris@49
|
10
|
Chris@49
|
11 //! \addtogroup op_find
|
Chris@49
|
12 //! @{
|
Chris@49
|
13
|
Chris@49
|
14
|
Chris@49
|
15
|
Chris@49
|
16 template<typename T1>
|
Chris@49
|
17 inline
|
Chris@49
|
18 uword
|
Chris@49
|
19 op_find::helper
|
Chris@49
|
20 (
|
Chris@49
|
21 Mat<uword>& indices,
|
Chris@49
|
22 const Base<typename T1::elem_type, T1>& X
|
Chris@49
|
23 )
|
Chris@49
|
24 {
|
Chris@49
|
25 arma_extra_debug_sigprint();
|
Chris@49
|
26
|
Chris@49
|
27 typedef typename T1::elem_type eT;
|
Chris@49
|
28
|
Chris@49
|
29 const Proxy<T1> A(X.get_ref());
|
Chris@49
|
30
|
Chris@49
|
31 const uword n_elem = A.get_n_elem();
|
Chris@49
|
32
|
Chris@49
|
33 indices.set_size(n_elem, 1);
|
Chris@49
|
34
|
Chris@49
|
35 uword* indices_mem = indices.memptr();
|
Chris@49
|
36 uword n_nz = 0;
|
Chris@49
|
37
|
Chris@49
|
38 if(Proxy<T1>::prefer_at_accessor == false)
|
Chris@49
|
39 {
|
Chris@49
|
40 typename Proxy<T1>::ea_type PA = A.get_ea();
|
Chris@49
|
41
|
Chris@49
|
42 for(uword i=0; i<n_elem; ++i)
|
Chris@49
|
43 {
|
Chris@49
|
44 if(PA[i] != eT(0)) { indices_mem[n_nz] = i; ++n_nz; }
|
Chris@49
|
45 }
|
Chris@49
|
46 }
|
Chris@49
|
47 else
|
Chris@49
|
48 {
|
Chris@49
|
49 const uword n_rows = A.get_n_rows();
|
Chris@49
|
50 const uword n_cols = A.get_n_cols();
|
Chris@49
|
51
|
Chris@49
|
52 uword i = 0;
|
Chris@49
|
53
|
Chris@49
|
54 for(uword col=0; col < n_cols; ++col)
|
Chris@49
|
55 for(uword row=0; row < n_rows; ++row)
|
Chris@49
|
56 {
|
Chris@49
|
57 if(A.at(row,col) != eT(0)) { indices_mem[n_nz] = i; ++n_nz; }
|
Chris@49
|
58
|
Chris@49
|
59 ++i;
|
Chris@49
|
60 }
|
Chris@49
|
61 }
|
Chris@49
|
62
|
Chris@49
|
63 return n_nz;
|
Chris@49
|
64 }
|
Chris@49
|
65
|
Chris@49
|
66
|
Chris@49
|
67
|
Chris@49
|
68 template<typename T1, typename op_type>
|
Chris@49
|
69 inline
|
Chris@49
|
70 uword
|
Chris@49
|
71 op_find::helper
|
Chris@49
|
72 (
|
Chris@49
|
73 Mat<uword>& indices,
|
Chris@49
|
74 const mtOp<uword, T1, op_type>& X,
|
Chris@49
|
75 const typename arma_op_rel_only<op_type>::result junk1,
|
Chris@49
|
76 const typename arma_not_cx<typename T1::elem_type>::result junk2
|
Chris@49
|
77 )
|
Chris@49
|
78 {
|
Chris@49
|
79 arma_extra_debug_sigprint();
|
Chris@49
|
80 arma_ignore(junk1);
|
Chris@49
|
81 arma_ignore(junk2);
|
Chris@49
|
82
|
Chris@49
|
83 typedef typename T1::elem_type eT;
|
Chris@49
|
84
|
Chris@49
|
85 const eT val = X.aux;
|
Chris@49
|
86
|
Chris@49
|
87 const Proxy<T1> A(X.m);
|
Chris@49
|
88
|
Chris@49
|
89 const uword n_elem = A.get_n_elem();
|
Chris@49
|
90
|
Chris@49
|
91 indices.set_size(n_elem, 1);
|
Chris@49
|
92
|
Chris@49
|
93 uword* indices_mem = indices.memptr();
|
Chris@49
|
94 uword n_nz = 0;
|
Chris@49
|
95
|
Chris@49
|
96 if(Proxy<T1>::prefer_at_accessor == false)
|
Chris@49
|
97 {
|
Chris@49
|
98 typename Proxy<T1>::ea_type PA = A.get_ea();
|
Chris@49
|
99
|
Chris@49
|
100 uword i,j;
|
Chris@49
|
101 for(i=0, j=1; j < n_elem; i+=2, j+=2)
|
Chris@49
|
102 {
|
Chris@49
|
103 const eT tpi = PA[i];
|
Chris@49
|
104 const eT tpj = PA[j];
|
Chris@49
|
105
|
Chris@49
|
106 bool not_zero_i;
|
Chris@49
|
107 bool not_zero_j;
|
Chris@49
|
108
|
Chris@49
|
109 if(is_same_type<op_type, op_rel_lt_pre >::value == true) { not_zero_i = (val < tpi); }
|
Chris@49
|
110 else if(is_same_type<op_type, op_rel_lt_post >::value == true) { not_zero_i = (tpi < val); }
|
Chris@49
|
111 else if(is_same_type<op_type, op_rel_gt_pre >::value == true) { not_zero_i = (val > tpi); }
|
Chris@49
|
112 else if(is_same_type<op_type, op_rel_gt_post >::value == true) { not_zero_i = (tpi > val); }
|
Chris@49
|
113 else if(is_same_type<op_type, op_rel_lteq_pre >::value == true) { not_zero_i = (val <= tpi); }
|
Chris@49
|
114 else if(is_same_type<op_type, op_rel_lteq_post>::value == true) { not_zero_i = (tpi <= val); }
|
Chris@49
|
115 else if(is_same_type<op_type, op_rel_gteq_pre >::value == true) { not_zero_i = (val >= tpi); }
|
Chris@49
|
116 else if(is_same_type<op_type, op_rel_gteq_post>::value == true) { not_zero_i = (tpi >= val); }
|
Chris@49
|
117 else if(is_same_type<op_type, op_rel_eq >::value == true) { not_zero_i = (tpi == val); }
|
Chris@49
|
118 else if(is_same_type<op_type, op_rel_noteq >::value == true) { not_zero_i = (tpi != val); }
|
Chris@49
|
119 else not_zero_i = false;
|
Chris@49
|
120
|
Chris@49
|
121 if(is_same_type<op_type, op_rel_lt_pre >::value == true) { not_zero_j = (val < tpj); }
|
Chris@49
|
122 else if(is_same_type<op_type, op_rel_lt_post >::value == true) { not_zero_j = (tpj < val); }
|
Chris@49
|
123 else if(is_same_type<op_type, op_rel_gt_pre >::value == true) { not_zero_j = (val > tpj); }
|
Chris@49
|
124 else if(is_same_type<op_type, op_rel_gt_post >::value == true) { not_zero_j = (tpj > val); }
|
Chris@49
|
125 else if(is_same_type<op_type, op_rel_lteq_pre >::value == true) { not_zero_j = (val <= tpj); }
|
Chris@49
|
126 else if(is_same_type<op_type, op_rel_lteq_post>::value == true) { not_zero_j = (tpj <= val); }
|
Chris@49
|
127 else if(is_same_type<op_type, op_rel_gteq_pre >::value == true) { not_zero_j = (val >= tpj); }
|
Chris@49
|
128 else if(is_same_type<op_type, op_rel_gteq_post>::value == true) { not_zero_j = (tpj >= val); }
|
Chris@49
|
129 else if(is_same_type<op_type, op_rel_eq >::value == true) { not_zero_j = (tpj == val); }
|
Chris@49
|
130 else if(is_same_type<op_type, op_rel_noteq >::value == true) { not_zero_j = (tpj != val); }
|
Chris@49
|
131 else not_zero_j = false;
|
Chris@49
|
132
|
Chris@49
|
133 if(not_zero_i == true) { indices_mem[n_nz] = i; ++n_nz; }
|
Chris@49
|
134 if(not_zero_j == true) { indices_mem[n_nz] = j; ++n_nz; }
|
Chris@49
|
135 }
|
Chris@49
|
136
|
Chris@49
|
137 if(i < n_elem)
|
Chris@49
|
138 {
|
Chris@49
|
139 bool not_zero;
|
Chris@49
|
140
|
Chris@49
|
141 const eT tmp = PA[i];
|
Chris@49
|
142
|
Chris@49
|
143 if(is_same_type<op_type, op_rel_lt_pre >::value == true) { not_zero = (val < tmp); }
|
Chris@49
|
144 else if(is_same_type<op_type, op_rel_lt_post >::value == true) { not_zero = (tmp < val); }
|
Chris@49
|
145 else if(is_same_type<op_type, op_rel_gt_pre >::value == true) { not_zero = (val > tmp); }
|
Chris@49
|
146 else if(is_same_type<op_type, op_rel_gt_post >::value == true) { not_zero = (tmp > val); }
|
Chris@49
|
147 else if(is_same_type<op_type, op_rel_lteq_pre >::value == true) { not_zero = (val <= tmp); }
|
Chris@49
|
148 else if(is_same_type<op_type, op_rel_lteq_post>::value == true) { not_zero = (tmp <= val); }
|
Chris@49
|
149 else if(is_same_type<op_type, op_rel_gteq_pre >::value == true) { not_zero = (val >= tmp); }
|
Chris@49
|
150 else if(is_same_type<op_type, op_rel_gteq_post>::value == true) { not_zero = (tmp >= val); }
|
Chris@49
|
151 else if(is_same_type<op_type, op_rel_eq >::value == true) { not_zero = (tmp == val); }
|
Chris@49
|
152 else if(is_same_type<op_type, op_rel_noteq >::value == true) { not_zero = (tmp != val); }
|
Chris@49
|
153 else not_zero = false;
|
Chris@49
|
154
|
Chris@49
|
155 if(not_zero == true) { indices_mem[n_nz] = i; ++n_nz; }
|
Chris@49
|
156 }
|
Chris@49
|
157 }
|
Chris@49
|
158 else
|
Chris@49
|
159 {
|
Chris@49
|
160 const uword n_rows = A.get_n_rows();
|
Chris@49
|
161 const uword n_cols = A.get_n_cols();
|
Chris@49
|
162
|
Chris@49
|
163 uword i = 0;
|
Chris@49
|
164
|
Chris@49
|
165 for(uword col=0; col < n_cols; ++col)
|
Chris@49
|
166 for(uword row=0; row < n_rows; ++row)
|
Chris@49
|
167 {
|
Chris@49
|
168 const eT tmp = A.at(row,col);
|
Chris@49
|
169
|
Chris@49
|
170 bool not_zero;
|
Chris@49
|
171
|
Chris@49
|
172 if(is_same_type<op_type, op_rel_lt_pre >::value == true) { not_zero = (val < tmp); }
|
Chris@49
|
173 else if(is_same_type<op_type, op_rel_lt_post >::value == true) { not_zero = (tmp < val); }
|
Chris@49
|
174 else if(is_same_type<op_type, op_rel_gt_pre >::value == true) { not_zero = (val > tmp); }
|
Chris@49
|
175 else if(is_same_type<op_type, op_rel_gt_post >::value == true) { not_zero = (tmp > val); }
|
Chris@49
|
176 else if(is_same_type<op_type, op_rel_lteq_pre >::value == true) { not_zero = (val <= tmp); }
|
Chris@49
|
177 else if(is_same_type<op_type, op_rel_lteq_post>::value == true) { not_zero = (tmp <= val); }
|
Chris@49
|
178 else if(is_same_type<op_type, op_rel_gteq_pre >::value == true) { not_zero = (val >= tmp); }
|
Chris@49
|
179 else if(is_same_type<op_type, op_rel_gteq_post>::value == true) { not_zero = (tmp >= val); }
|
Chris@49
|
180 else if(is_same_type<op_type, op_rel_eq >::value == true) { not_zero = (tmp == val); }
|
Chris@49
|
181 else if(is_same_type<op_type, op_rel_noteq >::value == true) { not_zero = (tmp != val); }
|
Chris@49
|
182 else not_zero = false;
|
Chris@49
|
183
|
Chris@49
|
184 if(not_zero == true) { indices_mem[n_nz] = i; ++n_nz; }
|
Chris@49
|
185
|
Chris@49
|
186 ++i;
|
Chris@49
|
187 }
|
Chris@49
|
188 }
|
Chris@49
|
189
|
Chris@49
|
190 return n_nz;
|
Chris@49
|
191 }
|
Chris@49
|
192
|
Chris@49
|
193
|
Chris@49
|
194
|
Chris@49
|
195 template<typename T1, typename op_type>
|
Chris@49
|
196 inline
|
Chris@49
|
197 uword
|
Chris@49
|
198 op_find::helper
|
Chris@49
|
199 (
|
Chris@49
|
200 Mat<uword>& indices,
|
Chris@49
|
201 const mtOp<uword, T1, op_type>& X,
|
Chris@49
|
202 const typename arma_op_rel_only<op_type>::result junk1,
|
Chris@49
|
203 const typename arma_cx_only<typename T1::elem_type>::result junk2
|
Chris@49
|
204 )
|
Chris@49
|
205 {
|
Chris@49
|
206 arma_extra_debug_sigprint();
|
Chris@49
|
207 arma_ignore(junk1);
|
Chris@49
|
208 arma_ignore(junk2);
|
Chris@49
|
209
|
Chris@49
|
210 typedef typename T1::elem_type eT;
|
Chris@49
|
211 typedef typename Proxy<T1>::ea_type ea_type;
|
Chris@49
|
212
|
Chris@49
|
213 const eT val = X.aux;
|
Chris@49
|
214
|
Chris@49
|
215 const Proxy<T1> A(X.m);
|
Chris@49
|
216
|
Chris@49
|
217 ea_type PA = A.get_ea();
|
Chris@49
|
218 const uword n_elem = A.get_n_elem();
|
Chris@49
|
219
|
Chris@49
|
220 indices.set_size(n_elem, 1);
|
Chris@49
|
221
|
Chris@49
|
222 uword* indices_mem = indices.memptr();
|
Chris@49
|
223 uword n_nz = 0;
|
Chris@49
|
224
|
Chris@49
|
225 for(uword i=0; i<n_elem; ++i)
|
Chris@49
|
226 {
|
Chris@49
|
227 const eT tmp = PA[i];
|
Chris@49
|
228
|
Chris@49
|
229 bool not_zero;
|
Chris@49
|
230
|
Chris@49
|
231 if(is_same_type<op_type, op_rel_eq >::value == true) { not_zero = (tmp == val); }
|
Chris@49
|
232 else if(is_same_type<op_type, op_rel_noteq>::value == true) { not_zero = (tmp != val); }
|
Chris@49
|
233 else not_zero = false;
|
Chris@49
|
234
|
Chris@49
|
235 if(not_zero == true) { indices_mem[n_nz] = i; ++n_nz; }
|
Chris@49
|
236 }
|
Chris@49
|
237
|
Chris@49
|
238 return n_nz;
|
Chris@49
|
239 }
|
Chris@49
|
240
|
Chris@49
|
241
|
Chris@49
|
242
|
Chris@49
|
243 template<typename T1, typename T2, typename glue_type>
|
Chris@49
|
244 inline
|
Chris@49
|
245 uword
|
Chris@49
|
246 op_find::helper
|
Chris@49
|
247 (
|
Chris@49
|
248 Mat<uword>& indices,
|
Chris@49
|
249 const mtGlue<uword, T1, T2, glue_type>& X,
|
Chris@49
|
250 const typename arma_glue_rel_only<glue_type>::result junk1,
|
Chris@49
|
251 const typename arma_not_cx<typename T1::elem_type>::result junk2,
|
Chris@49
|
252 const typename arma_not_cx<typename T2::elem_type>::result junk3
|
Chris@49
|
253 )
|
Chris@49
|
254 {
|
Chris@49
|
255 arma_extra_debug_sigprint();
|
Chris@49
|
256 arma_ignore(junk1);
|
Chris@49
|
257 arma_ignore(junk2);
|
Chris@49
|
258 arma_ignore(junk3);
|
Chris@49
|
259
|
Chris@49
|
260 typedef typename T1::elem_type eT1;
|
Chris@49
|
261 typedef typename T2::elem_type eT2;
|
Chris@49
|
262
|
Chris@49
|
263 typedef typename Proxy<T1>::ea_type ea_type1;
|
Chris@49
|
264 typedef typename Proxy<T2>::ea_type ea_type2;
|
Chris@49
|
265
|
Chris@49
|
266 const Proxy<T1> A(X.A);
|
Chris@49
|
267 const Proxy<T2> B(X.B);
|
Chris@49
|
268
|
Chris@49
|
269 arma_debug_assert_same_size(A, B, "relational operator");
|
Chris@49
|
270
|
Chris@49
|
271 ea_type1 PA = A.get_ea();
|
Chris@49
|
272 ea_type2 PB = B.get_ea();
|
Chris@49
|
273
|
Chris@49
|
274 const uword n_elem = B.get_n_elem();
|
Chris@49
|
275
|
Chris@49
|
276 indices.set_size(n_elem, 1);
|
Chris@49
|
277
|
Chris@49
|
278 uword* indices_mem = indices.memptr();
|
Chris@49
|
279 uword n_nz = 0;
|
Chris@49
|
280
|
Chris@49
|
281 for(uword i=0; i<n_elem; ++i)
|
Chris@49
|
282 {
|
Chris@49
|
283 const eT1 tmp1 = PA[i];
|
Chris@49
|
284 const eT2 tmp2 = PB[i];
|
Chris@49
|
285
|
Chris@49
|
286 bool not_zero;
|
Chris@49
|
287
|
Chris@49
|
288 if(is_same_type<glue_type, glue_rel_lt >::value == true) { not_zero = (tmp1 < tmp2); }
|
Chris@49
|
289 else if(is_same_type<glue_type, glue_rel_gt >::value == true) { not_zero = (tmp1 > tmp2); }
|
Chris@49
|
290 else if(is_same_type<glue_type, glue_rel_lteq >::value == true) { not_zero = (tmp1 <= tmp2); }
|
Chris@49
|
291 else if(is_same_type<glue_type, glue_rel_gteq >::value == true) { not_zero = (tmp1 >= tmp2); }
|
Chris@49
|
292 else if(is_same_type<glue_type, glue_rel_eq >::value == true) { not_zero = (tmp1 == tmp2); }
|
Chris@49
|
293 else if(is_same_type<glue_type, glue_rel_noteq >::value == true) { not_zero = (tmp1 != tmp2); }
|
Chris@49
|
294 else not_zero = false;
|
Chris@49
|
295
|
Chris@49
|
296 if(not_zero == true) { indices_mem[n_nz] = i; ++n_nz; }
|
Chris@49
|
297 }
|
Chris@49
|
298
|
Chris@49
|
299 return n_nz;
|
Chris@49
|
300 }
|
Chris@49
|
301
|
Chris@49
|
302
|
Chris@49
|
303
|
Chris@49
|
304 template<typename T1, typename T2, typename glue_type>
|
Chris@49
|
305 inline
|
Chris@49
|
306 uword
|
Chris@49
|
307 op_find::helper
|
Chris@49
|
308 (
|
Chris@49
|
309 Mat<uword>& indices,
|
Chris@49
|
310 const mtGlue<uword, T1, T2, glue_type>& X,
|
Chris@49
|
311 const typename arma_glue_rel_only<glue_type>::result junk1,
|
Chris@49
|
312 const typename arma_cx_only<typename T1::elem_type>::result junk2,
|
Chris@49
|
313 const typename arma_cx_only<typename T2::elem_type>::result junk3
|
Chris@49
|
314 )
|
Chris@49
|
315 {
|
Chris@49
|
316 arma_extra_debug_sigprint();
|
Chris@49
|
317 arma_ignore(junk1);
|
Chris@49
|
318 arma_ignore(junk2);
|
Chris@49
|
319 arma_ignore(junk3);
|
Chris@49
|
320
|
Chris@49
|
321 typedef typename Proxy<T1>::ea_type ea_type1;
|
Chris@49
|
322 typedef typename Proxy<T2>::ea_type ea_type2;
|
Chris@49
|
323
|
Chris@49
|
324 const Proxy<T1> A(X.A);
|
Chris@49
|
325 const Proxy<T2> B(X.B);
|
Chris@49
|
326
|
Chris@49
|
327 arma_debug_assert_same_size(A, B, "relational operator");
|
Chris@49
|
328
|
Chris@49
|
329 ea_type1 PA = A.get_ea();
|
Chris@49
|
330 ea_type2 PB = B.get_ea();
|
Chris@49
|
331
|
Chris@49
|
332 const uword n_elem = B.get_n_elem();
|
Chris@49
|
333
|
Chris@49
|
334 indices.set_size(n_elem, 1);
|
Chris@49
|
335
|
Chris@49
|
336 uword* indices_mem = indices.memptr();
|
Chris@49
|
337 uword n_nz = 0;
|
Chris@49
|
338
|
Chris@49
|
339 for(uword i=0; i<n_elem; ++i)
|
Chris@49
|
340 {
|
Chris@49
|
341 bool not_zero;
|
Chris@49
|
342
|
Chris@49
|
343 if(is_same_type<glue_type, glue_rel_eq >::value == true) { not_zero = (PA[i] == PB[i]); }
|
Chris@49
|
344 else if(is_same_type<glue_type, glue_rel_noteq >::value == true) { not_zero = (PA[i] != PB[i]); }
|
Chris@49
|
345 else not_zero = false;
|
Chris@49
|
346
|
Chris@49
|
347 if(not_zero == true) { indices_mem[n_nz] = i; ++n_nz; }
|
Chris@49
|
348 }
|
Chris@49
|
349
|
Chris@49
|
350 return n_nz;
|
Chris@49
|
351 }
|
Chris@49
|
352
|
Chris@49
|
353
|
Chris@49
|
354
|
Chris@49
|
355 template<typename T1>
|
Chris@49
|
356 inline
|
Chris@49
|
357 void
|
Chris@49
|
358 op_find::apply(Mat<uword>& out, const mtOp<uword, T1, op_find>& X)
|
Chris@49
|
359 {
|
Chris@49
|
360 arma_extra_debug_sigprint();
|
Chris@49
|
361
|
Chris@49
|
362 const uword k = X.aux_uword_a;
|
Chris@49
|
363 const uword type = X.aux_uword_b;
|
Chris@49
|
364
|
Chris@49
|
365 Mat<uword> indices;
|
Chris@49
|
366 const uword n_nz = op_find::helper(indices, X.m);
|
Chris@49
|
367
|
Chris@49
|
368 if(n_nz > 0)
|
Chris@49
|
369 {
|
Chris@49
|
370 if(type == 0) // "first"
|
Chris@49
|
371 {
|
Chris@49
|
372 out = (k > 0 && k <= n_nz) ? indices.rows(0, k-1 ) : indices.rows(0, n_nz-1);
|
Chris@49
|
373 }
|
Chris@49
|
374 else // "last"
|
Chris@49
|
375 {
|
Chris@49
|
376 out = (k > 0 && k <= n_nz) ? indices.rows(n_nz-k, n_nz-1) : indices.rows(0, n_nz-1);
|
Chris@49
|
377 }
|
Chris@49
|
378 }
|
Chris@49
|
379 else
|
Chris@49
|
380 {
|
Chris@49
|
381 out.set_size(0,1); // empty column vector
|
Chris@49
|
382 }
|
Chris@49
|
383 }
|
Chris@49
|
384
|
Chris@49
|
385
|
Chris@49
|
386
|
Chris@49
|
387 //! @}
|