~ubuntu-branches/ubuntu/wily/octave-miscellaneous/wily

« back to all changes in this revision

Viewing changes to src/partarray.cc

  • Committer: Package Import Robot
  • Author(s): Sébastien Villemot
  • Date: 2012-10-17 13:40:55 UTC
  • mfrom: (1.1.6)
  • mto: (5.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 13.
  • Revision ID: package-import@ubuntu.com-20121017134055-e8lrxjd3qgcd3kmt
Tags: upstream-1.2.0
Import upstream version 1.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2010,2011 Olaf Till <i7tiol@t-online.de>
 
2
//
 
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
 
6
// version.
 
7
//
 
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
 
11
// details.
 
12
//
 
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/>.
 
15
 
 
16
#include <octave/oct.h>
 
17
#include <octave/ov-struct.h>
 
18
 
 
19
template<class NDA>
 
20
static Cell
 
21
do_partarray (const NDA& a, const std::string& fname,
 
22
              const octave_value_list& args)
 
23
{
 
24
  // FIXME: some type-independent code should probably go into an
 
25
  // extra function (no template) to avoid its repetitive instanciation
 
26
 
 
27
  int nidc = args.length () - 1;
 
28
 
 
29
  dim_vector dv = a.dims ();
 
30
 
 
31
  int ndims = dv.length ();
 
32
 
 
33
  int maxdims = ndims > nidc ? ndims : nidc;
 
34
 
 
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++);
 
37
 
 
38
  int nc = 1;
 
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];
 
43
  //
 
44
  Array<octave_idx_type> step (dim_vector (maxdims, 1));
 
45
  step(0) = 1;
 
46
  for (int i = 0; i < maxdims; i++)
 
47
    {
 
48
      int cnidx;
 
49
      octave_value arg;
 
50
      if (i >= nidc || (arg = args(i + 1)).is_empty ())
 
51
        {
 
52
          Array<octave_idx_type> bidx (dim_vector (1, 1), 1);
 
53
          Array<octave_idx_type> eidx (dim_vector (1, 1), alldims(i));
 
54
          bidc[i] = bidx;
 
55
          eidc[i] = eidx;
 
56
          cnidx = 1;
 
57
        }
 
58
      else
 
59
        {
 
60
          dim_vector argdims = arg.dims ();
 
61
          if (argdims.length () > 2 || argdims(1) != 2)
 
62
            {
 
63
              error ("%s: argument %i: wrong dimensions",
 
64
                     fname.c_str (), i + 2);
 
65
              return Cell ();
 
66
            }
 
67
          cnidx =
 
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++)
 
73
            {
 
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;
 
80
            }
 
81
        }
 
82
      nc *= (nidx(i) = cnidx);
 
83
      if (i < maxdims - 1)
 
84
        step(i + 1) = step(i) * alldims(i);
 
85
    }
 
86
  if (error_state)
 
87
    return Cell ();
 
88
 
 
89
  dim_vector rdv (nc, 1);
 
90
 
 
91
  Cell retval (rdv);
 
92
 
 
93
  // preparations are done, start now; take care, indices are
 
94
  // one-based, since given by user
 
95
 
 
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++)
 
99
    {
 
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++)
 
104
        {
 
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;
 
108
          lengths(j) = length;
 
109
          n *= length;
 
110
          cursor += (begin - 1) * step(j);
 
111
        }
 
112
      Array<octave_idx_type> starts (dim_vector (maxdims - 1, 1), cursor);
 
113
      Array<octave_idx_type> idx_cursors (dim_vector (maxdims, 1), 0);
 
114
      // copy the subarray
 
115
      dim_vector subdv;
 
116
      subdv.resize (maxdims);
 
117
      for (octave_idx_type k = 0; k < maxdims; k++)
 
118
        subdv(k) = lengths(k);
 
119
      NDA asub (subdv);
 
120
      for (octave_idx_type k = 0; k < n; k++)
 
121
        {
 
122
          asub(k) = a(cursor++);
 
123
          idx_cursors(0)++;
 
124
          for (int l = 0; l < maxdims - 1; l++)
 
125
            {
 
126
              if (idx_cursors(l) == lengths(l))
 
127
                {
 
128
                  idx_cursors(l) = 0;
 
129
                  idx_cursors(l + 1)++;
 
130
                  cursor = starts(l) + step(l + 1);
 
131
                  for (int m = 0; m <= l; starts(m) = cursor, m++);
 
132
                }
 
133
            }
 
134
        }
 
135
      // insert subarray into cell
 
136
      retval(i, 0) = octave_value (asub);
 
137
      // prepare next combination
 
138
      cidx(0)++;
 
139
      for (int j = 0; j < maxdims - 1; j++)
 
140
        if (cidx(j) >= nidx(j))
 
141
          {
 
142
            cidx(j) = 0;
 
143
            cidx(j + 1)++;
 
144
          }
 
145
    }
 
146
 
 
147
  return retval;
 
148
}
 
149
 
 
150
DEFUN_DLD (partarray, args, ,
 
151
  "-*- texinfo -*-\n\
 
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\
 
154
\n\
 
155
Does not work with structure arrays at the moment.\n\
 
156
@end deftypefn")
 
157
{
 
158
  static bool warned = false;
 
159
  if (!warned){
 
160
    warning_with_id ("Octave:deprecated-function",
 
161
                     "partarray has been deprecated, and will be removed in the future. Use `mat2cell' instead.");
 
162
    warned = true;
 
163
  }
 
164
  std::string fname ("partarray");
 
165
 
 
166
  if (args.length () == 0)
 
167
    {
 
168
      print_usage ();
 
169
      return octave_value_list ();
 
170
    }
 
171
 
 
172
  octave_value array = args(0);
 
173
  octave_value retval;
 
174
 
 
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 ())
 
184
    {
 
185
      if (array.is_integer_type ())
 
186
        {
 
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);
 
203
        }
 
204
      else if (array.is_complex_type ())
 
205
        {
 
206
          if (array.is_single_type ())
 
207
            retval = do_partarray (array.float_complex_array_value (),
 
208
                                   fname, args);
 
209
          else
 
210
            retval = do_partarray (array.complex_array_value (), fname, args);
 
211
        }
 
212
      else
 
213
        {
 
214
          if (array.is_single_type ())
 
215
            retval = do_partarray (array.float_array_value (), fname, args);
 
216
          else
 
217
            retval = do_partarray (array.array_value (), fname, args);
 
218
        }
 
219
    }
 
220
  // FIXME: This seems to work in cellfun.cc, but not here ...
 
221
  /*
 
222
  else if (array.is_map ())
 
223
    retval = do_partarray (array.map_value (), fname, args);
 
224
  */
 
225
  else if (array.is_cell ())
 
226
    retval = do_partarray (array.cell_value (), fname, args);
 
227
  else
 
228
    gripe_wrong_type_arg (fname, array);
 
229
 
 
230
  return octave_value (retval);
 
231
}