# HG changeset patch # User John W. Eaton # Date 1320177546 14400 # Node ID 1cb3ae93578d1baa88096569544eb7a1dbb1da2b # Parent 990762e784fe8dbde23a04cd0d11d2310fdb8827 correctly distribute parent classes * ov-class.cc (octave_class::octave_class): Correctly distribute parent classes for all combinations of parent class and map sizes, whether or not the map has fields. diff --git a/src/ov-class.cc b/src/ov-class.cc --- a/src/ov-class.cc +++ b/src/ov-class.cc @@ -80,23 +80,120 @@ error ("parents must be objects"); else { - std::string cnm = parent.class_name (); + std::string pcnm = parent.class_name (); - if (find_parent_class (cnm)) + if (find_parent_class (pcnm)) error ("duplicate class in parent tree"); else { - parent_list.push_back (cnm); + parent_list.push_back (pcnm); - if (map.numel () > 1) + octave_idx_type nel = map.numel (); + octave_idx_type p_nel = parent.numel (); + + if (nel == 0) { - // If MAP has more than one element, put the parent - // class object in each element. + if (p_nel == 0) + { + // No elements in MAP or the parent class object, + // so just add the field name. + + map.assign (pcnm, Cell (map.dims ())); + } + else if (p_nel == 1) + { + if (map.nfields () == 0) + { + // No elements or fields in MAP, but the + // parent is class object with one element. + // Resize to match size of parent class and + // make the parent a field in MAP. + + map.resize (parent.dims ()); + + map.assign (pcnm, parent); + } + else + { + // No elements in MAP, but we have at least + // one field. So don't resize, just add the + // field name. - map.assign (cnm, Cell (map.dims (), parent)); + map.assign (pcnm, Cell (map.dims ())); + } + } + else if (map.nfields () == 0) + { + // No elements or fields in MAP and more than one + // element in the parent class object, so we can + // resize MAP to match parent dimsenions, then + // distribute the elements of the parent object to + // the elements of MAP. + + dim_vector parent_dims = parent.dims (); + + map.resize (parent_dims); + + Cell c (parent_dims); + + octave_map pmap = parent.map_value (); + + std::list plist + = parent.parent_class_name_list (); + + for (octave_idx_type i = 0; i < p_nel; i++) + c(i) = octave_value (pmap.index(i), pcnm, plist); + + map.assign (pcnm, c); + } + else + error ("class: parent class dimension mismatch"); + } + else if (nel == 1 && p_nel == 1) + { + // Simple assignment. + + map.assign (pcnm, parent); } else - map.assign (cnm, parent); + { + if (p_nel == 1) + { + // Broadcast the scalar parent class object to + // each element of MAP. + + Cell pcell (map.dims (), parent); + + map.assign (pcnm, pcell); + } + + else if (nel == p_nel) + { + // FIXME -- is there a better way to do this? + + // The parent class object has the same number of + // elements as the map we are using to create the + // new object, so distribute those elements to + // each element of the new object by first + // splitting the elements of the parent class + // object into a cell array with one element per + // cell. Then do the assignment all at once. + + Cell c (parent.dims ()); + + octave_map pmap = parent.map_value (); + + std::list plist + = parent.parent_class_name_list (); + + for (octave_idx_type i = 0; i < p_nel; i++) + c(i) = octave_value (pmap.index(i), pcnm, plist); + + map.assign (pcnm, c); + } + else + error ("class: parent class dimension mismatch"); + } } } }