# HG changeset patch # User carandraug # Date 1331568249 0 # Node ID 65943644e1ccae4a4aacb91af20c214f7effc1fe # Parent effb2d7106ffbc656e37458382e07de57d66a184 partarray: recover function from revision 8274 before being removed. We want to deprecate it first diff -r effb2d7106ff -r 65943644e1cc main/miscellaneous/src/partarray.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/miscellaneous/src/partarray.cc Mon Mar 12 16:04:09 2012 +0000 @@ -0,0 +1,229 @@ +/* + +Copyright (C) 2010, 2011 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 . + +*/ + +#include +#include + +template +static Cell +do_partarray (const NDA& a, const std::string& fname, + const octave_value_list& args) +{ + // FIXME: some type-independent code should probably go into an + // extra function (no template) to avoid its repetitive instanciation + + int nidc = args.length () - 1; + + dim_vector dv = a.dims (); + + int ndims = dv.length (); + + int maxdims = ndims > nidc ? ndims : nidc; + + Array alldims (dim_vector (maxdims, 1)); + for (int i = 0; i < maxdims; alldims(i) = i < ndims ? dv(i) : 1, i++); + + int nc = 1; + Array nidx (dim_vector (maxdims, 1)); + // Octave-3.2.4 reports "missing symbol" with Array >, + // though 3.3.54+ does not + Array bidc [maxdims], eidc [maxdims]; + // + Array step (dim_vector (maxdims, 1)); + step(0) = 1; + for (int i = 0; i < maxdims; i++) + { + int cnidx; + octave_value arg; + if (i >= nidc || (arg = args(i + 1)).is_empty ()) + { + Array bidx (dim_vector (1, 1), 1); + Array eidx (dim_vector (1, 1), alldims(i)); + bidc[i] = bidx; + eidc[i] = eidx; + cnidx = 1; + } + else + { + dim_vector argdims = arg.dims (); + if (argdims.length () > 2 || argdims(1) != 2) + { + error ("%s: argument %i: wrong dimensions", + fname.c_str (), i + 2); + return Cell (); + } + cnidx = + (bidc[i] = octave_value (arg.matrix_value ().column (0)). + octave_idx_type_vector_value ()).length (); + eidc[i] = octave_value (arg.matrix_value ().column (1)). + octave_idx_type_vector_value (); + for (int j = 0; j < cnidx; j++) + { + if (bidc[i](j) < 1 || eidc[i](j) > alldims(i)) + error ("%s: index given by row %i of argument %i exceeds array dimensions", + fname.c_str (), j, i + 2); + if (bidc[i](j) > eidc[i](j)) + // so later length calculations yield 0 + eidc[i](j) = bidc[i](j) - 1; + } + } + nc *= (nidx(i) = cnidx); + if (i < maxdims - 1) + step(i + 1) = step(i) * alldims(i); + } + if (error_state) + return Cell (); + + dim_vector rdv (nc, 1); + + Cell retval (rdv); + + // preparations are done, start now; take care, indices are + // one-based, since given by user + + // go through all combinations of indices into user indices + Array cidx (dim_vector (maxdims, 1), 0); // current combination + for (int i = 0; i < nc; i++) + { + // set cursor to start of subarray and calculate some lengths + octave_idx_type n = 1, cursor = 0; + Array lengths (dim_vector (maxdims, 1)); + for (int j = 0; j < maxdims; j++) + { + octave_idx_type begin = bidc[j](cidx(j)); + octave_idx_type end = eidc[j](cidx(j)); + octave_idx_type length = end + 1 - begin; + lengths(j) = length; + n *= length; + cursor += (begin - 1) * step(j); + } + Array starts (dim_vector (maxdims - 1, 1), cursor); + Array idx_cursors (dim_vector (maxdims, 1), 0); + // copy the subarray + dim_vector subdv; + subdv.resize (maxdims); + for (octave_idx_type k = 0; k < maxdims; k++) + subdv(k) = lengths(k); + NDA asub (subdv); + for (octave_idx_type k = 0; k < n; k++) + { + asub(k) = a(cursor++); + idx_cursors(0)++; + for (int l = 0; l < maxdims - 1; l++) + { + if (idx_cursors(l) == lengths(l)) + { + idx_cursors(l) = 0; + idx_cursors(l + 1)++; + cursor = starts(l) + step(l + 1); + for (int m = 0; m <= l; starts(m) = cursor, m++); + } + } + } + // insert subarray into cell + retval(i, 0) = octave_value (asub); + // prepare next combination + cidx(0)++; + for (int j = 0; j < maxdims - 1; j++) + if (cidx(j) >= nidx(j)) + { + cidx(j) = 0; + cidx(j + 1)++; + } + } + + return retval; +} + +DEFUN_DLD (partarray, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} partarray (@var{a}, @var{idx}, ...)\n\ +Return a column cell array with subarrays of the @var{a}. Start and end indices of subarrays are given in the rows of @var{idx}. @var{idx} can be given for each dimension, empty @var{idx} means no partitioning in the respective dimension. Order of returned subarrays: rows of @var{idx} of some dimension are completely used before using the next row of @var{idx} of the higher dimension.\n\ +\n\ +Does not work with structure arrays at the moment.\n\ +@end deftypefn") +{ + std::string fname ("partarray"); + + if (args.length () == 0) + { + print_usage (); + return octave_value_list (); + } + + octave_value array = args(0); + octave_value retval; + + // The idea to use a function template was taken from Octaves + // num2cell in src/DLD-FUNCTIONS/cellfun.cc. The following code, + // which distinguishes the applicable types for the template, was + // cut and pasted from there and adapted. + if (array.is_bool_type ()) + retval = do_partarray (array.bool_array_value (), fname, args); + else if (array.is_char_matrix ()) + retval = do_partarray (array.char_array_value (), fname, args); + else if (array.is_numeric_type ()) + { + if (array.is_integer_type ()) + { + if (array.is_int8_type ()) + retval = do_partarray (array.int8_array_value (), fname, args); + else if (array.is_int16_type ()) + retval = do_partarray (array.int16_array_value (), fname, args); + else if (array.is_int32_type ()) + retval = do_partarray (array.int32_array_value (), fname, args); + else if (array.is_int64_type ()) + retval = do_partarray (array.int64_array_value (), fname, args); + else if (array.is_uint8_type ()) + retval = do_partarray (array.uint8_array_value (), fname, args); + else if (array.is_uint16_type ()) + retval = do_partarray (array.uint16_array_value (), fname, args); + else if (array.is_uint32_type ()) + retval = do_partarray (array.uint32_array_value (), fname, args); + else if (array.is_uint64_type ()) + retval = do_partarray (array.uint64_array_value (), fname, args); + } + else if (array.is_complex_type ()) + { + if (array.is_single_type ()) + retval = do_partarray (array.float_complex_array_value (), + fname, args); + else + retval = do_partarray (array.complex_array_value (), fname, args); + } + else + { + if (array.is_single_type ()) + retval = do_partarray (array.float_array_value (), fname, args); + else + retval = do_partarray (array.array_value (), fname, args); + } + } + // FIXME: This seems to work in cellfun.cc, but not here ... + /* + else if (array.is_map ()) + retval = do_partarray (array.map_value (), fname, args); + */ + else if (array.is_cell ()) + retval = do_partarray (array.cell_value (), fname, args); + else + gripe_wrong_type_arg (fname, array); + + return octave_value (retval); +}