1
// Copyright (C) 2010,2011 Olaf Till <i7tiol@t-online.de>
3
// This program is free software; you can redistribute it and/or modify it under
4
// the terms of the GNU General Public License as published by the Free Software
5
// Foundation; either version 3 of the License, or (at your option) any later
8
// This program is distributed in the hope that it will be useful, but WITHOUT
9
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13
// You should have received a copy of the GNU General Public License along with
14
// this program; if not, see <http://www.gnu.org/licenses/>.
16
#include <octave/oct.h>
17
#include <octave/ov-struct.h>
21
do_partarray (const NDA& a, const std::string& fname,
22
const octave_value_list& args)
24
// FIXME: some type-independent code should probably go into an
25
// extra function (no template) to avoid its repetitive instanciation
27
int nidc = args.length () - 1;
29
dim_vector dv = a.dims ();
31
int ndims = dv.length ();
33
int maxdims = ndims > nidc ? ndims : nidc;
35
Array<octave_idx_type> alldims (dim_vector (maxdims, 1));
36
for (int i = 0; i < maxdims; alldims(i) = i < ndims ? dv(i) : 1, i++);
39
Array<int> nidx (dim_vector (maxdims, 1));
40
// Octave-3.2.4 reports "missing symbol" with Array<Array< > >,
41
// though 3.3.54+ does not
42
Array<octave_idx_type> bidc [maxdims], eidc [maxdims];
44
Array<octave_idx_type> step (dim_vector (maxdims, 1));
46
for (int i = 0; i < maxdims; i++)
50
if (i >= nidc || (arg = args(i + 1)).is_empty ())
52
Array<octave_idx_type> bidx (dim_vector (1, 1), 1);
53
Array<octave_idx_type> eidx (dim_vector (1, 1), alldims(i));
60
dim_vector argdims = arg.dims ();
61
if (argdims.length () > 2 || argdims(1) != 2)
63
error ("%s: argument %i: wrong dimensions",
64
fname.c_str (), i + 2);
68
(bidc[i] = octave_value (arg.matrix_value ().column (0)).
69
octave_idx_type_vector_value ()).length ();
70
eidc[i] = octave_value (arg.matrix_value ().column (1)).
71
octave_idx_type_vector_value ();
72
for (int j = 0; j < cnidx; j++)
74
if (bidc[i](j) < 1 || eidc[i](j) > alldims(i))
75
error ("%s: index given by row %i of argument %i exceeds array dimensions",
76
fname.c_str (), j, i + 2);
77
if (bidc[i](j) > eidc[i](j))
78
// so later length calculations yield 0
79
eidc[i](j) = bidc[i](j) - 1;
82
nc *= (nidx(i) = cnidx);
84
step(i + 1) = step(i) * alldims(i);
89
dim_vector rdv (nc, 1);
93
// preparations are done, start now; take care, indices are
94
// one-based, since given by user
96
// go through all combinations of indices into user indices
97
Array<int> cidx (dim_vector (maxdims, 1), 0); // current combination
98
for (int i = 0; i < nc; i++)
100
// set cursor to start of subarray and calculate some lengths
101
octave_idx_type n = 1, cursor = 0;
102
Array<octave_idx_type> lengths (dim_vector (maxdims, 1));
103
for (int j = 0; j < maxdims; j++)
105
octave_idx_type begin = bidc[j](cidx(j));
106
octave_idx_type end = eidc[j](cidx(j));
107
octave_idx_type length = end + 1 - begin;
110
cursor += (begin - 1) * step(j);
112
Array<octave_idx_type> starts (dim_vector (maxdims - 1, 1), cursor);
113
Array<octave_idx_type> idx_cursors (dim_vector (maxdims, 1), 0);
116
subdv.resize (maxdims);
117
for (octave_idx_type k = 0; k < maxdims; k++)
118
subdv(k) = lengths(k);
120
for (octave_idx_type k = 0; k < n; k++)
122
asub(k) = a(cursor++);
124
for (int l = 0; l < maxdims - 1; l++)
126
if (idx_cursors(l) == lengths(l))
129
idx_cursors(l + 1)++;
130
cursor = starts(l) + step(l + 1);
131
for (int m = 0; m <= l; starts(m) = cursor, m++);
135
// insert subarray into cell
136
retval(i, 0) = octave_value (asub);
137
// prepare next combination
139
for (int j = 0; j < maxdims - 1; j++)
140
if (cidx(j) >= nidx(j))
150
DEFUN_DLD (partarray, args, ,
152
@deftypefn {Loadable Function} {} partarray (@var{a}, @var{idx}, @dots{})\n\
153
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\
155
Does not work with structure arrays at the moment.\n\
158
static bool warned = false;
160
warning_with_id ("Octave:deprecated-function",
161
"partarray has been deprecated, and will be removed in the future. Use `mat2cell' instead.");
164
std::string fname ("partarray");
166
if (args.length () == 0)
169
return octave_value_list ();
172
octave_value array = args(0);
175
// The idea to use a function template was taken from Octaves
176
// num2cell in src/DLD-FUNCTIONS/cellfun.cc. The following code,
177
// which distinguishes the applicable types for the template, was
178
// cut and pasted from there and adapted.
179
if (array.is_bool_type ())
180
retval = do_partarray (array.bool_array_value (), fname, args);
181
else if (array.is_char_matrix ())
182
retval = do_partarray (array.char_array_value (), fname, args);
183
else if (array.is_numeric_type ())
185
if (array.is_integer_type ())
187
if (array.is_int8_type ())
188
retval = do_partarray (array.int8_array_value (), fname, args);
189
else if (array.is_int16_type ())
190
retval = do_partarray (array.int16_array_value (), fname, args);
191
else if (array.is_int32_type ())
192
retval = do_partarray (array.int32_array_value (), fname, args);
193
else if (array.is_int64_type ())
194
retval = do_partarray (array.int64_array_value (), fname, args);
195
else if (array.is_uint8_type ())
196
retval = do_partarray (array.uint8_array_value (), fname, args);
197
else if (array.is_uint16_type ())
198
retval = do_partarray (array.uint16_array_value (), fname, args);
199
else if (array.is_uint32_type ())
200
retval = do_partarray (array.uint32_array_value (), fname, args);
201
else if (array.is_uint64_type ())
202
retval = do_partarray (array.uint64_array_value (), fname, args);
204
else if (array.is_complex_type ())
206
if (array.is_single_type ())
207
retval = do_partarray (array.float_complex_array_value (),
210
retval = do_partarray (array.complex_array_value (), fname, args);
214
if (array.is_single_type ())
215
retval = do_partarray (array.float_array_value (), fname, args);
217
retval = do_partarray (array.array_value (), fname, args);
220
// FIXME: This seems to work in cellfun.cc, but not here ...
222
else if (array.is_map ())
223
retval = do_partarray (array.map_value (), fname, args);
225
else if (array.is_cell ())
226
retval = do_partarray (array.cell_value (), fname, args);
228
gripe_wrong_type_arg (fname, array);
230
return octave_value (retval);