From: <i7...@us...> - 2010-10-18 12:02:59
|
Revision: 7863 http://octave.svn.sourceforge.net/octave/?rev=7863&view=rev Author: i7tiol Date: 2010-10-18 12:02:52 +0000 (Mon, 18 Oct 2010) Log Message: ----------- New functions. Updated version number. Modified Paths: -------------- trunk/octave-forge/main/struct/DESCRIPTION Added Paths: ----------- trunk/octave-forge/main/struct/INDEX trunk/octave-forge/main/struct/src/ trunk/octave-forge/main/struct/src/Makefile trunk/octave-forge/main/struct/src/arefields.cc trunk/octave-forge/main/struct/src/cell2fields.cc trunk/octave-forge/main/struct/src/fieldempty.cc trunk/octave-forge/main/struct/src/fields2cell.cc trunk/octave-forge/main/struct/src/structcat.cc Modified: trunk/octave-forge/main/struct/DESCRIPTION =================================================================== --- trunk/octave-forge/main/struct/DESCRIPTION 2010-10-18 11:11:21 UTC (rev 7862) +++ trunk/octave-forge/main/struct/DESCRIPTION 2010-10-18 12:02:52 UTC (rev 7863) @@ -1,7 +1,7 @@ Name: Struct -Version: 1.0.7 -Date: 2009-05-03 -Author: Etienne Grossmann +Version: 1.0.8 +Date: 2010-10-18 +Author: Etienne Grossmann and Olaf Till <ola...@un...> Maintainer: Etienne Grossmann Title: Structure Handling. Description: Additional Structure manipulations functions. Added: trunk/octave-forge/main/struct/INDEX =================================================================== --- trunk/octave-forge/main/struct/INDEX (rev 0) +++ trunk/octave-forge/main/struct/INDEX 2010-10-18 12:02:52 UTC (rev 7863) @@ -0,0 +1,12 @@ +struct >> Structure Handling +Structure handling + getfields + setfields + tars + arefields + fields2cell + cell2fields + fieldempty + structcat +Tests + test_struct \ No newline at end of file Added: trunk/octave-forge/main/struct/src/Makefile =================================================================== --- trunk/octave-forge/main/struct/src/Makefile (rev 0) +++ trunk/octave-forge/main/struct/src/Makefile 2010-10-18 12:02:52 UTC (rev 7863) @@ -0,0 +1,9 @@ +OCTS = arefields.oct fields2cell.oct fieldempty.oct structcat.oct \ + cell2fields.oct + +all: $(OCTS) + +%.oct: %.cc + mkoctfile -s $< + +clean: ; rm *.o *.oct Added: trunk/octave-forge/main/struct/src/arefields.cc =================================================================== --- trunk/octave-forge/main/struct/src/arefields.cc (rev 0) +++ trunk/octave-forge/main/struct/src/arefields.cc 2010-10-18 12:02:52 UTC (rev 7863) @@ -0,0 +1,73 @@ +/* + +Copyright (C) 2010 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 +the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <octave/oct.h> +#include <octave/ov-struct.h> + +DEFUN_DLD (arefields, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} arefields (@var{s}, @var{names})\n\ +Return a logical vector indicating which of the strings in cell array @var{names} is a valid field name of structure @var{s}.\n\ +@end deftypefn") +{ + std::string fname ("arefields"); + + if (args.length () != 2) + { + print_usage (); + return octave_value_list (); + } + + Octave_map s = args(0).map_value (); + if (error_state) + { + error ("%s: first argument must be a structure", fname.c_str ()); + return octave_value_list (); + } + + Array<std::string> names = args(1).cellstr_value (); + if (error_state) + { + error ("%s: second argument must be a cell array of strings", + fname.c_str ()); + return octave_value_list (); + } + + dim_vector dims = names.dims (); + if (dims.length () > 2 || + (dims(0) > 1 && dims(1) > 1)) + { + error ("%s: second argument must be a one-dimensional cell array", + fname.c_str ()); + return octave_value_list (); + } + + boolMatrix retval (dims); + + octave_idx_type n = names.length (); + for (octave_idx_type i = 0; i < n; i++) + { + if (s.contains (names(i))) + retval(i) = true; + else + retval(i) = false; + } + + return octave_value (retval); +} Added: trunk/octave-forge/main/struct/src/cell2fields.cc =================================================================== --- trunk/octave-forge/main/struct/src/cell2fields.cc (rev 0) +++ trunk/octave-forge/main/struct/src/cell2fields.cc 2010-10-18 12:02:52 UTC (rev 7863) @@ -0,0 +1,156 @@ +/* + +Copyright (C) 2010 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 +the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <octave/oct.h> +#include <octave/ov-struct.h> + +DEFUN_DLD (cell2fields, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} cell2fields (@var{c}, @var{fields}, @var{dim}, @var{s})\n\ +Return structure @var{s} after setting the fields @var{fields} with the slices of cell-array @var{c} vertically to dimension @var{dim}. @var{s} must have matching dimensions or be empty.\n\ +@end deftypefn") +{ + std::string fname ("cell2fields"); + + if (args.length () != 4) + { + print_usage (); + return octave_value_list (); + } + + Cell c = args(0).cell_value (); + if (error_state) + { + error ("%s: first argument must be a cell array", fname.c_str ()); + return octave_value_list (); + } + + Array<std::string> names = args(1).cellstr_value (); + if (error_state) + { + error ("%s: second argument must be a cell array of strings", fname.c_str ()); + return octave_value_list (); + } + + if (! names.dims ().is_vector ()) + { + error ("%s: second argument must be a one-dimensional cell array", + fname.c_str ()); + return octave_value_list (); + } + + octave_idx_type dim = args(2).int_value (); + if (error_state) + { + error ("%s: second argument must be an integer", + fname.c_str ()); + return octave_value_list (); + } + + Octave_map s = args(3).map_value (); + if (error_state) + { + error ("%s: third argument must be a structure", fname.c_str ()); + return octave_value_list (); + } + + octave_idx_type i, j; + + dim_vector cdims (c.dims ()); + + octave_idx_type n_cdims = cdims.length (); + + dim_vector tdims (cdims); + + octave_idx_type nr = 1; + + if (n_cdims >= dim && cdims(dim - 1) > 1) + { + nr = cdims(dim - 1); + + tdims(dim - 1) = 1; + + tdims.chop_trailing_singletons (); + } + + if (nr != names.numel ()) + { + error ("%s: second argument has incorrect length", fname.c_str ()); + + return octave_value_list (); + } + + Octave_map retval; + + if (s.keys (). length () == 0) + retval.resize (tdims); + else + { + if (s.dims () != tdims) + { + error ("%s: structure has incorrect dimenstions", fname.c_str ()); + + return octave_value_list (); + } + retval = (s); + } + + octave_idx_type nt = tdims.numel (); + + octave_idx_type base = 0, origin, cursor; + + octave_idx_type skip_count = 1; // when to skip + + octave_idx_type min_tp = n_cdims < dim - 1 ? n_cdims : dim - 1; + + for (i = 0; i < min_tp; i++) + skip_count *= cdims(i); + + octave_idx_type skip = skip_count; // how much to skip + + if (n_cdims >= dim) + skip *= cdims(dim - 1); + + for (i = 0; i < nr; i++) + { + Cell t (tdims); + + origin = base; + + cursor = 0; + + for (j = 0; j < nt; j++) + { + t(j) = c(origin + cursor++); + + if (cursor == skip_count) + { + cursor = 0; + + origin += skip; + } + } + + retval.assign (names(i), t); + + base += skip_count; + } + + return octave_value (retval); +} Added: trunk/octave-forge/main/struct/src/fieldempty.cc =================================================================== --- trunk/octave-forge/main/struct/src/fieldempty.cc (rev 0) +++ trunk/octave-forge/main/struct/src/fieldempty.cc 2010-10-18 12:02:52 UTC (rev 7863) @@ -0,0 +1,77 @@ +/* + +Copyright (C) 2010 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 +the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <octave/oct.h> +#include <octave/ov-struct.h> + +DEFUN_DLD (fieldempty, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} fieldempty (@var{s}, @var{name})\n\ +Returns a logical array with same dimensions as structure @var{s}, indicating where field @var{name} is empty.\n\ +@end deftypefn") +{ + std::string fname ("fieldempty"); + + if (args.length () != 2) + { + print_usage (); + return octave_value_list (); + } + + Octave_map s = args(0).map_value (); + if (error_state) + { + error ("%s: first argument must be a structure", fname.c_str ()); + return octave_value_list (); + } + + std::string name = args(1).string_value (); + if (error_state) + { + error ("%s: second argument must be a string", fname.c_str ()); + return octave_value_list (); + } + + if (! s.contains (name)) + { + error ("%s: no such field", fname.c_str ()); + return octave_value_list (); + } + + dim_vector sdims = s.dims (); + + boolNDArray retval (sdims); + + octave_idx_type numel = s.numel (); + + if (! numel) + return octave_value (retval); + + Cell c (s.contents (name)); + + for (octave_idx_type i = 0; i < numel; i++) + { + if (c(i).numel ()) + retval(i) = false; + else + retval(i) = true; + } + + return octave_value (retval); +} Added: trunk/octave-forge/main/struct/src/fields2cell.cc =================================================================== --- trunk/octave-forge/main/struct/src/fields2cell.cc (rev 0) +++ trunk/octave-forge/main/struct/src/fields2cell.cc 2010-10-18 12:02:52 UTC (rev 7863) @@ -0,0 +1,98 @@ +/* + +Copyright (C) 2010 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 +the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <octave/oct.h> +#include <octave/ov-struct.h> + +DEFUN_DLD (fields2cell, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} fields2cell (@var{s}, @var{names})\n\ +Works similarly to @code{struct2cell} (see there), but considers only fields given by the strings in cell array @var{names}. Returns an error if a field is missing in @var{s}.\n\ +@end deftypefn") +{ + std::string fname ("fields2cell"); + + if (args.length () != 2) + { + print_usage (); + return octave_value_list (); + } + + Octave_map s = args(0).map_value (); + if (error_state) + { + error ("%s: first argument must be a structure", fname.c_str ()); + return octave_value_list (); + } + + Array<std::string> names = args(1).cellstr_value (); + if (error_state) + { + error ("%s: second argument must be a cell array of strings", + fname.c_str ()); + return octave_value_list (); + } + + if (! names.dims ().is_vector ()) + { + error ("%s: second argument must be a one-dimensional cell array", + fname.c_str ()); + return octave_value_list (); + } + + octave_idx_type n = names.length (); + + dim_vector sdims = s.dims (); + + octave_idx_type n_sdims = sdims.length (); + + dim_vector dims; + if (sdims(n_sdims - 1) == 1) + dims.resize (n_sdims); + else + dims.resize (++n_sdims); + + dims(0) = n; + for (octave_idx_type i = 1; i < n_sdims; i++) + dims(i) = sdims(i - 1); + + Cell retval (dims); + + octave_idx_type k = s.numel (); + + for (octave_idx_type i = 0; i < n; i++) + { + if (! s.contains (names(i))) + { + error ("%s: some fields not present", fname.c_str ()); + return octave_value_list (); + } + + Cell tp = s.contents (names(i)); + + octave_idx_type l = i; + for (octave_idx_type j = 0; j < k; j++) + { + retval(l) = tp(j); + l += n; + } + } + + return octave_value (retval); +} Added: trunk/octave-forge/main/struct/src/structcat.cc =================================================================== --- trunk/octave-forge/main/struct/src/structcat.cc (rev 0) +++ trunk/octave-forge/main/struct/src/structcat.cc 2010-10-18 12:02:52 UTC (rev 7863) @@ -0,0 +1,185 @@ +/* + +Copyright (C) 2009 John W. Eaton +Copyright (C) 2009 Jaroslav Hajek +Copyright (C) 2010 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 +the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +// 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 ()). + +#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) +{ + Octave_map retval; + + Octave_map m1 = v1.map_value (); + Octave_map m2 = v2.map_value (); + + Cell c2 (m2.dims ()); + + for (Octave_map::const_iterator pa = m1.begin (); pa != m1.end (); pa++) + { + 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)); + else + retval.assign (m1.key(pa), + m1.contents(pa).insert (m2.contents(pb), ra_idx)); + } + + dim_vector dv1 (m1.dims ()); + + for (Octave_map::const_iterator pa = m2.begin (); pa != m2.end (); pa++) + { + Octave_map::const_iterator pb = m1.seek (m2.key(pa)); + + if (pb == m1.end ()) + { + Cell c1 (dv1); + retval.assign (m2.key(pa), + c1.insert (m2.contents(pa), ra_idx)); + } + } + + return retval; +} + + +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\ +@end deftypefn") +{ + std::string fname ("structcat"); + + octave_value retval; + + int 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) + { + octave_idx_type dim = args(0).int_value () - 1; + + if (error_state) + { + error ("%s: expecting first argument to be a integer", + fname.c_str ()); + return retval; + } + + if (dim >= 0) + { + dim_vector dv = args(1).dims (); + std::string result_type ("struct"); + + 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; + } + } + + // 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. + + octave_value tmp = args (1); + tmp = tmp.resize (dim_vector (0,0)).resize (dv); + + if (error_state) + return retval; + + int dv_len = dv.length (); + Array<octave_idx_type> ra_idx (dv_len, 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); + + 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 (! error_state) + { + // Reshape, chopping trailing singleton dimensions + dv.chop_trailing_singletons (); + retval = retval.reshape (dv); + } + } + else + error ("%s: invalid dimension argument", fname.c_str ()); + } + else + print_usage (); + + return retval; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |