Mercurial > forge
changeset 9862:d6a81872c52d octave-forge
structcat accepts argument to set value of missing fields
author | i7tiol |
---|---|
date | Sun, 25 Mar 2012 08:59:59 +0000 |
parents | ed325676175e |
children | 3381a9ed0a6f |
files | main/struct/src/structcat.cc |
diffstat | 1 files changed, 78 insertions(+), 112 deletions(-) [+] |
line wrap: on
line diff
--- a/main/struct/src/structcat.cc Sat Mar 24 21:59:22 2012 +0000 +++ b/main/struct/src/structcat.cc Sun Mar 25 08:59:59 2012 +0000 @@ -1,8 +1,6 @@ /* -Copyright (C) 2009 John W. Eaton -Copyright (C) 2009 Jaroslav Hajek <highegg@gmail.com> -Copyright (C) 2010, 2011 Olaf Till +Copyright (C) 2010, 2011, 2012 Olaf Till This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,37 +17,38 @@ */ -// This code and the comments are taken and slightly modified from -// Octave-3.2.4, src/data.cc (do_cat()), src/ov.cc (do_cat_op ()), -// src/OPERATORS/op-struct.cc, src/ops.h, and oct-map.cc -// (Octave_map::concat ()). +// Code of the files of Octave-3.2.4 src/data.cc (do_cat()), src/ov.cc +// (do_cat_op ()), src/OPERATORS/op-struct.cc, src/ops.h, and +// oct-map.cc (Octave_map::concat ()) has been studied and initially +// re-used, but in the end it has been made differently here. #include <octave/oct.h> #include <octave/ov-struct.h> -static octave_value -structcat_cat_op_fcn (const octave_value& v1, const octave_value& v2, - const Array<octave_idx_type>& ra_idx) +static Octave_map +structcat_op_fcn (const Octave_map& m1, const Octave_map& m2, + const dim_vector& dv, + const Array<octave_idx_type>& ra_idx, + const octave_value& fillv) { - Octave_map m1 = v1.map_value (); - Octave_map m2 = v2.map_value (); + Octave_map retval (dv); - dim_vector dv1 (m1.dims ()); - - Octave_map retval (dv1); - - Cell c2 (m2.dims ()); + Cell c2 (m2.dims (), fillv); for (Octave_map::const_iterator pa = m1.begin (); pa != m1.end (); pa++) { + Cell c (dv); + + c.insert (m1.contents(pa), 0, 0); + Octave_map::const_iterator pb = m2.seek (m1.key(pa)); if (pb == m2.end ()) - retval.assign (m1.key(pa), - m1.contents(pa).insert (c2, ra_idx)); + c.insert (c2, ra_idx); else - retval.assign (m1.key(pa), - m1.contents(pa).insert (m2.contents(pb), ra_idx)); + c.insert (m2.contents(pb), ra_idx); + + retval.assign (m1.key(pa), c); } for (Octave_map::const_iterator pa = m2.begin (); pa != m2.end (); pa++) @@ -58,9 +57,10 @@ if (pb == m1.end ()) { - Cell c1 (dv1); + Cell c (dv, fillv); + retval.assign (m2.key(pa), - c1.insert (m2.contents(pa), ra_idx)); + c.insert (m2.contents(pa), ra_idx)); } } @@ -71,115 +71,81 @@ DEFUN_DLD (structcat, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} structcat (@var{dim}, @var{struct1}, @dots{}, @var{structn})\n\ -Return the concatenation of N-d structures @var{struct1}, @dots{}, @var{structn} along dimension @var{dim}. Differently to @code{cat}, fields need not match --- missing fields get an empty matrix value. Without structure arguments, an empty structure array is returned.\n\ +@deftypefnx {Loadable Function} {} structcat (@var{dim}, @var{default}, @var{struct1}, @dots{}, @var{structn})\n\ +Return the concatenation of N-d structures @var{struct1}, @dots{}, @var{structn} along dimension @var{dim}. Differently to @code{cat}, fields need not match --- missing fields get an empty matrix value. Without structure arguments, an empty structure array is returned. If a scalar argument @var{default} is given, missing fields get its value instead of an empty matrix value.\n\ +\n\ +@seealso{structcat_default}\n\ @end deftypefn") { std::string fname ("structcat"); - octave_value retval; + Octave_map retval; - int n_args = args.length (); + octave_idx_type n_args = args.length (); - if (n_args == 1) - retval = Octave_map (); - else if (n_args == 2) - retval = args(1).map_value (); - else if (n_args > 2) + if (n_args == 0) + print_usage (); + else { octave_idx_type dim = args(0).int_value () - 1; - if (error_state) + if (error_state || dim < 0) { - error ("%s: expecting first argument to be a integer", + error ("%s: first argument must be a positive integer", fname.c_str ()); - return retval; + return octave_value (); } - - if (dim >= 0) + + octave_idx_type m1_id; + octave_value fillv; + + if (n_args > 1 && args(1).is_scalar_type ()) { - dim_vector dv = args(1).dims (); - std::string result_type ("struct"); + m1_id = 2; - for (int i = 2; i < args.length (); i++) - { - // Construct a dimension vector which holds the - // dimensions of the final array after concatenation. - - if (! dv.concat (args(i).dims (), dim)) - { - // Dimensions do not match. - error ("%s: dimension mismatch", fname.c_str ()); - return retval; - } - - if (args(i).class_name () != result_type) - { - error ("%s: some argument not a structure", - fname.c_str ()); - return retval; - } + fillv = args(1); + } + else + { + m1_id = 1; + + fillv = Matrix (); + } + + dim_vector dv; + + octave_idx_type idx_len = dv.length (); + + if (dim >= idx_len) idx_len = dim + 1; + + Array<octave_idx_type> ra_idx (dim_vector (idx_len, 1), 0); + + for (octave_idx_type i = m1_id; i < n_args; i++) + { + if (! args(i).is_map ()) + { + error ("%s: some argument not a structure", fname.c_str ()); + + return octave_value (); } - // The lines below might seem crazy, since we take a - // copy of the first argument, resize it to be empty and - // then resize it to be full. This is done since it - // means that there is no recopying of data, as would - // happen if we used a single resize. It should be - // noted that resize operation is also significantly - // slower than the do_cat_op function, so it makes sense - // to have an empty matrix and copy all data. - // - // We might also start with a empty octave_value using - // tmp = octave_value_typeinfo::lookup_type - // (args(1).type_name()); - // and then directly resize. However, for some types there might - // be some additional setup needed, and so this should be avoided. + dim_vector dvi = args(i).dims (), old_dv = dv; - octave_value tmp = args (1); - tmp = tmp.resize (dim_vector (0, 0)).resize (dv); - - if (error_state) - return retval; + if (! dv.concat (dvi, dim)) + { + error ("%s: dimension mismatch", fname.c_str ()); - int dv_len = dv.length (); - Array<octave_idx_type> ra_idx (dim_vector (dv_len, 1), 0); - - for (int j = 1; j < n_args; j++) - { - dim_vector dv_tmp = args (j).dims (); - - if (! dv_tmp.all_zero ()) - { - tmp = structcat_cat_op_fcn (tmp, args(j), ra_idx); + return octave_value (); + } - if (error_state) - return retval; - - if (dim >= dv_len) - { - if (j > 1) - error ("%s: indexing error", fname.c_str ()); - break; - } - else - ra_idx (dim) += (dim < dv_tmp.length () ? - dv_tmp (dim) : 1); - } - } - retval = tmp; + if (! dvi.all_zero ()) + { + retval = structcat_op_fcn (retval, args(i).map_value (), + dv, ra_idx, fillv); - if (! error_state) - { - // Reshape, chopping trailing singleton dimensions - dv.chop_trailing_singletons (); - retval = retval.reshape (dv); + ra_idx(dim) += (dim < dvi.length () ? dvi(dim) : 1); } - } - else - error ("%s: invalid dimension argument", fname.c_str ()); + } } - else - print_usage (); - - return retval; + return octave_value (retval); }