Mercurial > hg > octave-nkf
comparison libinterp/corefcn/find.cc @ 18968:a5286fb173cd gui-release
Match Matlab return dimensions for find on empty sparse matrices (bug #42408).
* find.cc (find_nonzero_elem_idx (const Sparse<T>& v)): Match Matlab return
dimensions for odd cases such as 0x1, 1x0, 1x1(empty) sparse matrices. The
conditions are documented in Array.cc (Array<T>::find) and are already
implemented for other array types besides sparse.
* find.cc (find_nonzero_elem_idx (const PermMatrix& v)): Match Matlab return
dimensions for odd cases such as 0x1, 1x0, 1x1(empty) permutation matrices.
author | Rik <rik@octave.org> |
---|---|
date | Sun, 25 May 2014 10:23:03 -0700 |
parents | 175b392e91fe |
children | 888f8ce79bbe 332450e56698 |
comparison
equal
deleted
inserted
replaced
18949:095fdef3d67c | 18968:a5286fb173cd |
---|---|
86 find_nonzero_elem_idx (const Sparse<T>& v, int nargout, | 86 find_nonzero_elem_idx (const Sparse<T>& v, int nargout, |
87 octave_idx_type n_to_find, int direction) | 87 octave_idx_type n_to_find, int direction) |
88 { | 88 { |
89 octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ()); | 89 octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ()); |
90 | 90 |
91 | 91 octave_idx_type nr = v.rows (); |
92 octave_idx_type nc = v.cols (); | 92 octave_idx_type nc = v.cols (); |
93 octave_idx_type nr = v.rows (); | |
94 octave_idx_type nz = v.nnz (); | 93 octave_idx_type nz = v.nnz (); |
95 | 94 |
96 // Search in the default range. | 95 // Search in the default range. |
97 octave_idx_type start_nc = -1; | 96 octave_idx_type start_nc = -1; |
98 octave_idx_type end_nc = -1; | 97 octave_idx_type end_nc = -1; |
136 } | 135 } |
137 | 136 |
138 count = (n_to_find > v.cidx (end_nc) - v.cidx (start_nc) ? | 137 count = (n_to_find > v.cidx (end_nc) - v.cidx (start_nc) ? |
139 v.cidx (end_nc) - v.cidx (start_nc) : n_to_find); | 138 v.cidx (end_nc) - v.cidx (start_nc) : n_to_find); |
140 | 139 |
141 // If the original argument was a row vector, force a row vector of | 140 octave_idx_type result_nr; |
142 // the overall indices to be returned. But see below for scalar | 141 octave_idx_type result_nc; |
143 // case... | 142 |
144 | 143 // Default case is to return a column vector, however, if the original |
145 octave_idx_type result_nr = count; | 144 // argument was a row vector, then force return of a row vector. |
146 octave_idx_type result_nc = 1; | 145 if (nr == 1) |
147 | |
148 bool scalar_arg = false; | |
149 | |
150 if (v.rows () == 1) | |
151 { | 146 { |
152 result_nr = 1; | 147 result_nr = 1; |
153 result_nc = count; | 148 result_nc = count; |
154 | 149 } |
155 scalar_arg = (v.columns () == 1); | 150 else |
151 { | |
152 result_nr = count; | |
153 result_nc = 1; | |
156 } | 154 } |
157 | 155 |
158 Matrix idx (result_nr, result_nc); | 156 Matrix idx (result_nr, result_nc); |
159 | 157 |
160 Matrix i_idx (result_nr, result_nc); | 158 Matrix i_idx (result_nr, result_nc); |
162 | 160 |
163 Array<T> val (dim_vector (result_nr, result_nc)); | 161 Array<T> val (dim_vector (result_nr, result_nc)); |
164 | 162 |
165 if (count > 0) | 163 if (count > 0) |
166 { | 164 { |
167 // Search for elements to return. Only search the region where | 165 // Search for elements to return. Only search the region where there |
168 // there are elements to be found using the count that we want | 166 // are elements to be found using the count that we want to find. |
169 // to find. | |
170 for (octave_idx_type j = start_nc, cx = 0; j < end_nc; j++) | 167 for (octave_idx_type j = start_nc, cx = 0; j < end_nc; j++) |
171 for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++ ) | 168 for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++ ) |
172 { | 169 { |
173 OCTAVE_QUIT; | 170 OCTAVE_QUIT; |
174 if (direction < 0 && i < nz - count) | 171 if (direction < 0 && i < nz - count) |
180 cx++; | 177 cx++; |
181 if (cx == count) | 178 if (cx == count) |
182 break; | 179 break; |
183 } | 180 } |
184 } | 181 } |
185 else if (scalar_arg) | 182 else |
186 { | 183 { |
187 idx.resize (0, 0); | 184 // No items found. Fixup return dimensions for Matlab compatibility. |
188 | 185 // The behavior to match is documented in Array.cc (Array<T>::find). |
189 i_idx.resize (0, 0); | 186 if ((nr == 0 && nc == 0) || nr == 1 & nc == 1) |
190 j_idx.resize (0, 0); | 187 { |
191 | 188 idx.resize (0, 0); |
192 val.resize (dim_vector (0, 0)); | 189 |
190 i_idx.resize (0, 0); | |
191 j_idx.resize (0, 0); | |
192 | |
193 val.resize (dim_vector (0, 0)); | |
194 } | |
193 } | 195 } |
194 | 196 |
195 switch (nargout) | 197 switch (nargout) |
196 { | 198 { |
197 case 0: | 199 case 0: |
229 octave_idx_type n_to_find, int direction) | 231 octave_idx_type n_to_find, int direction) |
230 { | 232 { |
231 // There are far fewer special cases to handle for a PermMatrix. | 233 // There are far fewer special cases to handle for a PermMatrix. |
232 octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ()); | 234 octave_value_list retval ((nargout == 0 ? 1 : nargout), Matrix ()); |
233 | 235 |
236 octave_idx_type nr = v.rows (); | |
234 octave_idx_type nc = v.cols (); | 237 octave_idx_type nc = v.cols (); |
235 octave_idx_type start_nc, count; | 238 octave_idx_type start_nc, count; |
236 | 239 |
237 // Determine the range to search. | 240 // Determine the range to search. |
238 if (n_to_find < 0 || n_to_find >= nc) | 241 if (n_to_find < 0 || n_to_find >= nc) |
249 else | 252 else |
250 { | 253 { |
251 start_nc = nc - n_to_find; | 254 start_nc = nc - n_to_find; |
252 count = n_to_find; | 255 count = n_to_find; |
253 } | 256 } |
254 | |
255 bool scalar_arg = (v.rows () == 1 && v.cols () == 1); | |
256 | 257 |
257 Matrix idx (count, 1); | 258 Matrix idx (count, 1); |
258 Matrix i_idx (count, 1); | 259 Matrix i_idx (count, 1); |
259 Matrix j_idx (count, 1); | 260 Matrix j_idx (count, 1); |
260 // Every value is 1. | 261 // Every value is 1. |
289 j_idx(koff) = static_cast<double> (1+j); | 290 j_idx(koff) = static_cast<double> (1+j); |
290 idx(koff) = j * nc + i + 1; | 291 idx(koff) = j * nc + i + 1; |
291 } | 292 } |
292 } | 293 } |
293 } | 294 } |
294 else if (scalar_arg) | 295 else |
295 { | 296 { |
296 // Same odd compatibility case as the other overrides. | 297 // FIXME: Is this case even possible? A scalar permutation matrix seems to devolve |
297 idx.resize (0, 0); | 298 // to a scalar full matrix, at least from the Octave command line. Perhaps |
298 i_idx.resize (0, 0); | 299 // this function could be called internally from C++ with such a matrix. |
299 j_idx.resize (0, 0); | 300 // No items found. Fixup return dimensions for Matlab compatibility. |
300 val.resize (dim_vector (0, 0)); | 301 // The behavior to match is documented in Array.cc (Array<T>::find). |
302 if ((nr == 0 && nc == 0) || nr == 1 & nc == 1) | |
303 { | |
304 idx.resize (0, 0); | |
305 | |
306 i_idx.resize (0, 0); | |
307 j_idx.resize (0, 0); | |
308 | |
309 val.resize (dim_vector (0, 0)); | |
310 } | |
301 } | 311 } |
302 | 312 |
303 switch (nargout) | 313 switch (nargout) |
304 { | 314 { |
305 case 0: | 315 case 0: |