Mercurial > octave-nkf
comparison libinterp/octave-value/ov-classdef.cc @ 16696:665fa0f621cc classdef
Support combination of object array extension and multi-level indexing.
* libinterp/octave-value/ov-classdef.h
(octave_classdef::subsref(string, list<octave_value_list, bool)): New
method.
(cdef_object_array:subsref, cdef_object_scalar::subsref,
cdef_object_rep): Add boolean argument "auto_add".
(cdef_object_array::fill_empty_values(Array&)): New method.
(cdef_object_array::fill_empty_values()): Rewrite using the overload.
(cdef_object::subsasgn, cdef_object::make_unique): New boolean argument
"ignore_copies" for assignment optimization.
* libinterp/octave-value/ov-classdef.cc
(octave_classdef::subsref(string, list<octave_value_list, bool)): New
method.
(cdef_object_array::fill_empty_values()): Move implementation to the
overload version.
(cdef_object_array::subsasgn): Optimize assignment to avoir unnecessary
copies of value objects.
(cdef_object_array::subsref): New auto_add argument for automatic
extension of the array.
(cdef_object_scalar::subsref): New auto_add argument. Implement
(-indexing by delegating to a new array object.
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Thu, 23 May 2013 21:41:51 -0400 |
parents | 2823f8e3da77 |
children | 13b3b92ea99c |
comparison
equal
deleted
inserted
replaced
16695:2823f8e3da77 | 16696:665fa0f621cc |
---|---|
770 if (type.length () > skip && idx.size () > skip) | 770 if (type.length () > skip && idx.size () > skip) |
771 retval = retval(0).next_subsref (nargout, type, idx, skip); | 771 retval = retval(0).next_subsref (nargout, type, idx, skip); |
772 } | 772 } |
773 | 773 |
774 return retval; | 774 return retval; |
775 } | |
776 | |
777 octave_value | |
778 octave_classdef::subsref (const std::string& type, | |
779 const std::list<octave_value_list>& idx, | |
780 bool auto_add) | |
781 { | |
782 size_t skip = 0; | |
783 octave_value_list retval; | |
784 | |
785 // FIXME: should check "subsref" method first | |
786 // ? not sure this still applied with auto_add version of subsref | |
787 | |
788 retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add); | |
789 | |
790 if (! error_state) | |
791 { | |
792 if (type.length () > skip && idx.size () > skip) | |
793 retval = retval(0).next_subsref (1, type, idx, skip); | |
794 } | |
795 | |
796 return retval.length () > 0 ? retval(0) : octave_value (); | |
775 } | 797 } |
776 | 798 |
777 octave_value | 799 octave_value |
778 octave_classdef::subsasgn (const std::string& type, | 800 octave_classdef::subsasgn (const std::string& type, |
779 const std::list<octave_value_list>& idx, | 801 const std::list<octave_value_list>& idx, |
1026 | 1048 |
1027 octave_value_list | 1049 octave_value_list |
1028 cdef_object_scalar::subsref (const std::string& type, | 1050 cdef_object_scalar::subsref (const std::string& type, |
1029 const std::list<octave_value_list>& idx, | 1051 const std::list<octave_value_list>& idx, |
1030 int nargout, size_t& skip, | 1052 int nargout, size_t& skip, |
1031 const cdef_class& context) | 1053 const cdef_class& context, bool auto_add) |
1032 { | 1054 { |
1033 skip = 0; | 1055 skip = 0; |
1034 | 1056 |
1035 cdef_class cls = (context.ok () ? context : get_class ()); | 1057 cdef_class cls = (context.ok () ? context : get_class ()); |
1036 | 1058 |
1094 else | 1116 else |
1095 error ("subsref: unknown method or property: %s", name.c_str ()); | 1117 error ("subsref: unknown method or property: %s", name.c_str ()); |
1096 } | 1118 } |
1097 break; | 1119 break; |
1098 } | 1120 } |
1121 | |
1122 case '(': | |
1123 { | |
1124 refcount++; | |
1125 | |
1126 cdef_object this_obj (this); | |
1127 | |
1128 Array<cdef_object> arr (dim_vector (1, 1), this_obj); | |
1129 | |
1130 cdef_object new_obj = cdef_object (new cdef_object_array (arr)); | |
1131 | |
1132 new_obj.set_class (get_class ()); | |
1133 | |
1134 retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add); | |
1135 } | |
1136 break; | |
1137 | |
1099 default: | 1138 default: |
1100 error ("object cannot be indexed with `%c'", type[0]); | 1139 error ("object cannot be indexed with `%c'", type[0]); |
1101 break; | 1140 break; |
1102 } | 1141 } |
1103 | 1142 |
1219 | 1258 |
1220 octave_value_list | 1259 octave_value_list |
1221 cdef_object_array::subsref (const std::string& type, | 1260 cdef_object_array::subsref (const std::string& type, |
1222 const std::list<octave_value_list>& idx, | 1261 const std::list<octave_value_list>& idx, |
1223 int /* nargout */, size_t& skip, | 1262 int /* nargout */, size_t& skip, |
1224 const cdef_class& /* context */) | 1263 const cdef_class& /* context */, bool auto_add) |
1225 { | 1264 { |
1226 octave_value_list retval; | 1265 octave_value_list retval; |
1227 | 1266 |
1228 skip = 1; | 1267 skip = 1; |
1229 | 1268 |
1242 is_scalar = is_scalar && iv(i).is_scalar (); | 1281 is_scalar = is_scalar && iv(i).is_scalar (); |
1243 } | 1282 } |
1244 | 1283 |
1245 if (! error_state) | 1284 if (! error_state) |
1246 { | 1285 { |
1247 Array<cdef_object> ires = array.index (iv); | 1286 Array<cdef_object> ires = array.index (iv, auto_add); |
1248 | 1287 |
1249 if (! error_state) | 1288 if (! error_state) |
1250 { | 1289 { |
1290 // If resizing is enabled (auto_add = true), it's possible | |
1291 // indexing was out-of-bound and the result array contains | |
1292 // invalid cdef_objects. | |
1293 | |
1294 if (auto_add) | |
1295 fill_empty_values (ires); | |
1296 | |
1251 if (is_scalar) | 1297 if (is_scalar) |
1252 retval(0) = to_ov (ires(0)); | 1298 retval(0) = to_ov (ires(0)); |
1253 else | 1299 else |
1254 { | 1300 { |
1255 cdef_object array_obj (new cdef_object_array (ires)); | 1301 cdef_object array_obj (new cdef_object_array (ires)); |
1404 | 1450 |
1405 if (! error_state) | 1451 if (! error_state) |
1406 { | 1452 { |
1407 cdef_object obj = a(0); | 1453 cdef_object obj = a(0); |
1408 | 1454 |
1455 int ignore_copies = 0; | |
1456 | |
1409 // If the object in 'a' is not valid, this means the index | 1457 // If the object in 'a' is not valid, this means the index |
1410 // was out-of-bound and we need to create a new object. | 1458 // was out-of-bound and we need to create a new object. |
1411 | 1459 |
1412 if (! obj.ok ()) | 1460 if (! obj.ok ()) |
1413 obj = get_class ().construct_object (octave_value_list ()); | 1461 obj = get_class ().construct_object (octave_value_list ()); |
1462 else | |
1463 // Optimize the subsasgn call to come. There are 2 copies | |
1464 // that we can safely ignore: | |
1465 // - 1 in "array" | |
1466 // - 1 in "a" | |
1467 ignore_copies = 2; | |
1414 | 1468 |
1415 std::list<octave_value_list> next_idx (idx); | 1469 std::list<octave_value_list> next_idx (idx); |
1416 | 1470 |
1417 next_idx.erase (next_idx.begin ()); | 1471 next_idx.erase (next_idx.begin ()); |
1418 | 1472 |
1419 octave_value tmp = obj.subsasgn (type.substr (1), next_idx, | 1473 octave_value tmp = obj.subsasgn (type.substr (1), next_idx, |
1420 rhs); | 1474 rhs, ignore_copies); |
1421 | 1475 |
1422 if (! error_state) | 1476 if (! error_state) |
1423 { | 1477 { |
1424 cdef_object robj = to_cdef (tmp); | 1478 cdef_object robj = to_cdef (tmp); |
1425 | 1479 |
1465 | 1519 |
1466 return retval; | 1520 return retval; |
1467 } | 1521 } |
1468 | 1522 |
1469 void | 1523 void |
1470 cdef_object_array::fill_empty_values (void) | 1524 cdef_object_array::fill_empty_values (Array<cdef_object>& arr) |
1471 { | 1525 { |
1472 cdef_class cls = get_class (); | 1526 cdef_class cls = get_class (); |
1473 | 1527 |
1474 if (! error_state) | 1528 if (! error_state) |
1475 { | 1529 { |
1476 cdef_object obj; | 1530 cdef_object obj; |
1477 | 1531 |
1478 int n = array.numel (); | 1532 int n = arr.numel (); |
1479 | 1533 |
1480 for (int i = 0; ! error_state && i < n; i++) | 1534 for (int i = 0; ! error_state && i < n; i++) |
1481 { | 1535 { |
1482 if (! array.xelem (i).ok ()) | 1536 if (! arr.xelem (i).ok ()) |
1483 { | 1537 { |
1484 if (! obj.ok ()) | 1538 if (! obj.ok ()) |
1485 { | 1539 { |
1486 obj = cls.construct_object (octave_value_list ()); | 1540 obj = cls.construct_object (octave_value_list ()); |
1487 | 1541 |
1488 if (! error_state) | 1542 if (! error_state) |
1489 array.xelem (i) = obj; | 1543 arr.xelem (i) = obj; |
1490 } | 1544 } |
1491 else | 1545 else |
1492 array.xelem (i) = obj.copy (); | 1546 arr.xelem (i) = obj.copy (); |
1493 } | 1547 } |
1494 } | 1548 } |
1495 } | 1549 } |
1496 } | 1550 } |
1497 | 1551 |