Mercurial > hg > octave-nkf
annotate src/oct-map.cc @ 8682:38968f09f7ca
optimize Octave_map::index
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Thu, 05 Feb 2009 15:15:59 +0100 |
parents | 280fae940bb0 |
children | eb63fbe60fab |
rev | line source |
---|---|
1278 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2006, 2007 |
4 John W. Eaton | |
1278 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
1278 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
1278 | 21 |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include <config.h> | |
26 #endif | |
27 | |
3932 | 28 #include "error.h" |
1755 | 29 #include "str-vec.h" |
30 | |
1278 | 31 #include "oct-map.h" |
32 #include "utils.h" | |
33 | |
6959 | 34 Octave_map::Octave_map (const dim_vector& dv, const Cell& key_vals) |
5880 | 35 : map (), key_list (), dimensions (dv) |
36 { | |
37 Cell c (dv); | |
38 | |
6959 | 39 if (key_vals.is_cellstr ()) |
5880 | 40 { |
6959 | 41 for (octave_idx_type i = 0; i < key_vals.numel (); i++) |
6946 | 42 { |
6959 | 43 std::string k = key_vals(i).string_value (); |
6946 | 44 map[k] = c; |
45 key_list.push_back (k); | |
46 } | |
5880 | 47 } |
6946 | 48 else |
49 error ("Octave_map: expecting keys to be cellstr"); | |
5880 | 50 } |
51 | |
7046 | 52 Octave_map |
53 Octave_map::squeeze (void) const | |
54 { | |
55 Octave_map retval (dims ().squeeze ()); | |
56 | |
57 for (const_iterator pa = begin (); pa != end (); pa++) | |
58 { | |
59 Cell tmp = contents (pa).squeeze (); | |
60 | |
61 if (error_state) | |
62 break; | |
63 | |
64 retval.assign (key (pa), tmp); | |
65 } | |
66 | |
67 return retval; | |
68 } | |
69 | |
70 Octave_map | |
71 Octave_map::permute (const Array<int>& vec, bool inv) const | |
72 { | |
73 Octave_map retval (dims ()); | |
74 | |
75 for (const_iterator pa = begin (); pa != end (); pa++) | |
76 { | |
77 Cell tmp = contents (pa).permute (vec, inv); | |
78 | |
79 if (error_state) | |
80 break; | |
81 | |
82 retval.assign (key (pa), tmp); | |
83 } | |
84 | |
85 return retval; | |
86 } | |
87 | |
5328 | 88 Cell& |
89 Octave_map::contents (const std::string& k) | |
90 { | |
5880 | 91 maybe_add_to_key_list (k); |
92 | |
5328 | 93 return map[k]; |
94 } | |
95 | |
4513 | 96 Cell |
4675 | 97 Octave_map::contents (const std::string& k) const |
4197 | 98 { |
4587 | 99 const_iterator p = seek (k); |
4197 | 100 |
4513 | 101 return p != end () ? p->second : Cell (); |
4197 | 102 } |
103 | |
5156 | 104 int |
105 Octave_map::intfield (const std::string& k, int def_val) const | |
106 { | |
107 int retval = def_val; | |
108 | |
109 Cell c = contents (k); | |
110 | |
111 if (! c.is_empty ()) | |
112 retval = c(0).int_value (); | |
113 | |
114 return retval; | |
115 } | |
116 | |
117 std::string | |
118 Octave_map::stringfield (const std::string& k, | |
119 const std::string& def_val) const | |
120 { | |
121 std::string retval = def_val; | |
122 | |
123 Cell c = contents (k); | |
124 | |
125 if (! c.is_empty ()) | |
126 retval = c(0).string_value (); | |
127 | |
128 return retval; | |
129 } | |
130 | |
1755 | 131 string_vector |
3933 | 132 Octave_map::keys (void) const |
1278 | 133 { |
6639 | 134 assert (nfields () == key_list.size ()); |
5881 | 135 |
5880 | 136 return string_vector (key_list); |
1278 | 137 } |
138 | |
4567 | 139 Octave_map |
5571 | 140 Octave_map::transpose (void) const |
141 { | |
142 assert (ndims () == 2); | |
5593 | 143 |
5571 | 144 dim_vector dv = dims (); |
145 | |
5593 | 146 octave_idx_type nr = dv(0); |
147 octave_idx_type nc = dv(1); | |
148 | |
149 dim_vector new_dims (nc, nr); | |
150 | |
151 Octave_map retval (new_dims); | |
5571 | 152 |
153 for (const_iterator p = begin (); p != end (); p++) | |
154 retval.assign (key(p), Cell (contents(p).transpose ())); | |
155 | |
156 return retval; | |
157 } | |
158 | |
159 Octave_map | |
4567 | 160 Octave_map::reshape (const dim_vector& new_dims) const |
161 { | |
162 Octave_map retval; | |
163 | |
164 if (new_dims != dims ()) | |
165 { | |
166 for (const_iterator p = begin (); p != end (); p++) | |
4675 | 167 retval.assign (key(p), contents(p).reshape (new_dims)); |
4567 | 168 |
4936 | 169 retval.dimensions = new_dims; |
4567 | 170 } |
4936 | 171 else |
172 retval = *this; | |
4567 | 173 |
174 return retval; | |
175 } | |
176 | |
5781 | 177 void |
178 Octave_map::resize (const dim_vector& dv, bool fill) | |
4936 | 179 { |
180 if (dv != dims ()) | |
181 { | |
6639 | 182 if (nfields () == 0) |
6609 | 183 dimensions = dv; |
184 else | |
4936 | 185 { |
6609 | 186 for (const_iterator p = begin (); p != end (); p++) |
187 { | |
188 Cell tmp = contents(p); | |
5781 | 189 |
6609 | 190 if (fill) |
191 tmp.resize(dv, Cell::resize_fill_value ()); | |
192 else | |
193 tmp.resize(dv); | |
5781 | 194 |
6609 | 195 dimensions = dv; |
5781 | 196 |
6609 | 197 assign (key(p), tmp); |
198 } | |
4936 | 199 } |
200 } | |
201 } | |
202 | |
4915 | 203 Octave_map |
5275 | 204 Octave_map::concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx) |
4806 | 205 { |
4937 | 206 Octave_map retval; |
4936 | 207 |
6639 | 208 if (nfields () == rb.nfields ()) |
4936 | 209 { |
5881 | 210 for (const_iterator pa = begin (); pa != end (); pa++) |
4936 | 211 { |
5881 | 212 const_iterator pb = rb.seek (key(pa)); |
4937 | 213 |
5003 | 214 if (pb == rb.end ()) |
4937 | 215 { |
216 error ("field name mismatch in structure concatenation"); | |
217 break; | |
218 } | |
4936 | 219 |
5073 | 220 retval.assign (key(pa), |
221 contents(pa).insert (rb.contents(pb), ra_idx)); | |
4937 | 222 } |
4936 | 223 } |
4937 | 224 else |
7959
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
225 { |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
226 dim_vector dv = dims (); |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
227 |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
228 if (dv.all_zero ()) |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
229 retval = rb; |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
230 else |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
231 { |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
232 dv = rb.dims (); |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
233 |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
234 if (dv.all_zero ()) |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
235 retval = *this; |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
236 else |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
237 error ("invalid structure concatenation"); |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
238 } |
a73b80cd1f10
allow empty matrix by cell (or struct) concatentation
John W. Eaton <jwe@octave.org>
parents:
7046
diff
changeset
|
239 } |
4937 | 240 |
4915 | 241 return retval; |
4806 | 242 } |
243 | |
6609 | 244 static bool |
245 keys_ok (const Octave_map& a, const Octave_map& b, string_vector& keys) | |
4197 | 246 { |
6609 | 247 bool retval = false; |
248 | |
249 keys = string_vector (); | |
4197 | 250 |
6639 | 251 if (a.nfields () == 0) |
6609 | 252 { |
253 keys = b.keys (); | |
254 retval = true; | |
255 } | |
256 else | |
257 { | |
8503
8ba2ee57c594
remove qsort in favor of sort
Jaroslav Hajek <highegg@gmail.com>
parents:
8294
diff
changeset
|
258 string_vector a_keys = a.keys().sort (); |
8ba2ee57c594
remove qsort in favor of sort
Jaroslav Hajek <highegg@gmail.com>
parents:
8294
diff
changeset
|
259 string_vector b_keys = b.keys().sort (); |
4197 | 260 |
6609 | 261 octave_idx_type a_len = a_keys.length (); |
262 octave_idx_type b_len = b_keys.length (); | |
263 | |
264 if (a_len == b_len) | |
4197 | 265 { |
6609 | 266 for (octave_idx_type i = 0; i < a_len; i++) |
267 { | |
268 if (a_keys[i] != b_keys[i]) | |
269 goto done; | |
270 } | |
4197 | 271 |
6609 | 272 keys = a_keys; |
273 retval = true; | |
274 } | |
4197 | 275 } |
6609 | 276 |
277 done: | |
4197 | 278 return retval; |
279 } | |
280 | |
281 Octave_map& | |
5592 | 282 Octave_map::maybe_delete_elements (const octave_value_list& idx) |
283 { | |
284 string_vector t_keys = keys(); | |
285 octave_idx_type len = t_keys.length (); | |
286 | |
287 if (len > 0) | |
288 { | |
289 for (octave_idx_type i = 0; i < len; i++) | |
290 { | |
291 std::string k = t_keys[i]; | |
292 | |
8175
977d5204cf67
fix null assignment for structs
Jaroslav Hajek <highegg@gmail.com>
parents:
7959
diff
changeset
|
293 map[k] = contents(k).delete_elements (idx); |
5592 | 294 |
295 if (error_state) | |
296 break; | |
297 } | |
298 | |
299 if (!error_state) | |
300 dimensions = contents(t_keys[0]).dims(); | |
301 } | |
302 | |
303 return *this; | |
304 } | |
305 | |
306 Octave_map& | |
4513 | 307 Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs) |
4197 | 308 { |
6609 | 309 string_vector t_keys; |
4197 | 310 |
6609 | 311 if (keys_ok (*this, rhs, t_keys)) |
4197 | 312 { |
5275 | 313 octave_idx_type len = t_keys.length (); |
4197 | 314 |
6609 | 315 if (len == 0) |
4197 | 316 { |
6609 | 317 Cell tmp_lhs (dims ()); |
318 Cell tmp_rhs (rhs.dims ()); | |
319 | |
320 tmp_lhs.assign (idx, tmp_rhs, Matrix ()); | |
4197 | 321 |
6609 | 322 if (! error_state) |
323 resize (tmp_lhs.dims ()); | |
324 else | |
325 error ("size mismatch in structure assignment"); | |
326 } | |
327 else | |
328 { | |
329 for (octave_idx_type i = 0; i < len; i++) | |
330 { | |
331 std::string k = t_keys[i]; | |
4197 | 332 |
6609 | 333 Cell t_rhs = rhs.contents (k); |
334 | |
335 assign (idx, k, t_rhs); | |
4197 | 336 |
6609 | 337 if (error_state) |
338 break; | |
339 } | |
4197 | 340 } |
341 } | |
342 else | |
343 error ("field name mismatch in structure assignment"); | |
344 | |
345 return *this; | |
346 } | |
347 | |
4561 | 348 static dim_vector |
349 common_size (const dim_vector& a, const dim_vector& b) | |
350 { | |
351 dim_vector retval; | |
352 | |
5275 | 353 octave_idx_type a_len = a.length (); |
354 octave_idx_type b_len = b.length (); | |
4561 | 355 |
5275 | 356 octave_idx_type new_len = std::max (a_len, b_len); |
357 octave_idx_type min_len = std::min (a_len, b_len); | |
4561 | 358 |
359 retval.resize (new_len); | |
360 | |
5275 | 361 for (octave_idx_type i = 0; i < min_len; i++) |
4561 | 362 retval(i) = std::max (a(i), b(i)); |
363 | |
364 if (a_len < b_len) | |
365 { | |
5275 | 366 for (octave_idx_type i = min_len; i < b_len; i++) |
4561 | 367 retval(i) = b(i); |
368 } | |
369 else if (a_len > b_len) | |
370 { | |
5275 | 371 for (octave_idx_type i = min_len; i < a_len; i++) |
4561 | 372 retval(i) = a(i); |
373 } | |
374 | |
375 return retval; | |
376 } | |
377 | |
3932 | 378 Octave_map& |
4587 | 379 Octave_map::assign (const octave_value_list& idx, const std::string& k, |
4513 | 380 const Cell& rhs) |
3932 | 381 { |
5881 | 382 Cell tmp; |
383 | |
384 if (contains (k)) | |
385 tmp = map[k]; | |
3932 | 386 |
4216 | 387 octave_value fill_value = Matrix (); |
388 | |
389 tmp.assign (idx, rhs, fill_value); | |
3932 | 390 |
391 if (! error_state) | |
392 { | |
4561 | 393 dim_vector rhs_dims = tmp.dims (); |
3943 | 394 |
4561 | 395 dim_vector curr_dims = dims (); |
396 | |
397 dim_vector new_dims = common_size (rhs_dims, curr_dims); | |
3932 | 398 |
4561 | 399 if (new_dims != rhs_dims) |
3932 | 400 { |
4625 | 401 tmp.resize (new_dims, fill_value); |
3943 | 402 } |
5329 | 403 |
404 if (new_dims != curr_dims) | |
3943 | 405 { |
4219 | 406 for (iterator p = begin (); p != end (); p++) |
5328 | 407 contents(p).resize (new_dims, fill_value); |
4561 | 408 } |
3932 | 409 |
4561 | 410 dimensions = new_dims; |
3932 | 411 |
5880 | 412 maybe_add_to_key_list (k); |
413 | |
4587 | 414 map[k] = tmp; |
3932 | 415 } |
416 | |
417 return *this; | |
418 } | |
419 | |
3933 | 420 Octave_map& |
4675 | 421 Octave_map::assign (const std::string& k, const octave_value& rhs) |
422 { | |
6639 | 423 if (nfields () == 0) |
4675 | 424 { |
5880 | 425 maybe_add_to_key_list (k); |
426 | |
4675 | 427 map[k] = Cell (rhs); |
428 | |
429 dimensions = dim_vector (1, 1); | |
430 } | |
431 else | |
432 { | |
433 dim_vector dv = dims (); | |
434 | |
435 if (dv.all_ones ()) | |
5880 | 436 { |
437 maybe_add_to_key_list (k); | |
438 | |
439 map[k] = Cell (rhs); | |
440 } | |
4675 | 441 else |
442 error ("invalid structure assignment"); | |
443 } | |
444 | |
445 return *this; | |
446 } | |
447 | |
448 Octave_map& | |
4587 | 449 Octave_map::assign (const std::string& k, const Cell& rhs) |
3933 | 450 { |
6639 | 451 if (nfields () == 0) |
4563 | 452 { |
5880 | 453 maybe_add_to_key_list (k); |
454 | |
4587 | 455 map[k] = rhs; |
4563 | 456 |
4730 | 457 dimensions = rhs.dims (); |
4563 | 458 } |
3933 | 459 else |
460 { | |
4562 | 461 if (dims () == rhs.dims ()) |
5880 | 462 { |
463 maybe_add_to_key_list (k); | |
464 | |
465 map[k] = rhs; | |
466 } | |
3933 | 467 else |
468 error ("invalid structure assignment"); | |
469 } | |
470 | |
471 return *this; | |
472 } | |
473 | |
474 Octave_map | |
7046 | 475 Octave_map::index (const octave_value_list& idx, bool resize_ok) const |
3933 | 476 { |
477 Octave_map retval; | |
8682
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
478 octave_idx_type n_idx = idx.length (); |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
479 if (n_idx > 0) |
3933 | 480 { |
8682
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
481 Array<idx_vector> ra_idx (n_idx); |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
482 for (octave_idx_type i = 0; i < n_idx; i++) |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
483 { |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
484 ra_idx(i) = idx(i).index_vector (); |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
485 if (error_state) |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
486 break; |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
487 } |
3933 | 488 |
8682
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
489 if (! error_state) |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
490 { |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
491 for (const_iterator p = begin (); p != end (); p++) |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
492 { |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
493 |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
494 Cell tmp = contents (p); |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
495 tmp = tmp.ArrayN<octave_value>::index (ra_idx, resize_ok); |
3933 | 496 |
8682
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
497 if (error_state) |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
498 break; |
8294
b2a6309b2d87
oct-map.cc: copy key_list in indexing functions
John W. Eaton <jwe@octave.org>
parents:
8175
diff
changeset
|
499 |
8682
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
500 retval.assign (key(p), tmp); |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
501 } |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
502 |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
503 // Preserve order of keys. |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
504 retval.key_list = key_list; |
38968f09f7ca
optimize Octave_map::index
Jaroslav Hajek <highegg@gmail.com>
parents:
8679
diff
changeset
|
505 } |
3933 | 506 } |
5435 | 507 else |
5539 | 508 retval = *this; |
3933 | 509 |
5539 | 510 return retval; |
3933 | 511 } |
512 | |
1278 | 513 /* |
514 ;;; Local Variables: *** | |
515 ;;; mode: C++ *** | |
516 ;;; End: *** | |
517 */ |