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: