GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
dim-vector.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2003-2017 John W. Eaton
4 Copyirght (C) 2009, 2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <sstream>
29 #include <limits>
30 #include <string>
31 #include <new>
32 
33 #include "dim-vector.h"
34 
37 {
38  static dim_vector zv (0, 0);
39  return zv.rep;
40 }
41 
42 // The maximum allowed value for a dimension extent. This will normally be a
43 // tiny bit off the maximum value of octave_idx_type.
44 // Currently 1 is subtracted to allow safe conversion of any 2D Array into
45 // Sparse, but this offset may change in the future.
48 {
50 }
51 
52 void
54 {
55  make_unique ();
56 
57  int j = 0;
58  int l = ndims ();
59 
60  for (int i = 0; i < l; i++)
61  {
62  if (rep[i] != 1)
63  rep[j++] = rep[i];
64  }
65 
66  if (j == 1)
67  rep[1] = 1;
68 
69  rep[-1] = j > 2 ? j : 2;
70 }
71 
73 dim_vector::str (char sep) const
74 {
75  std::ostringstream buf;
76 
77  for (int i = 0; i < ndims (); i++)
78  {
79  buf << elem (i);
80 
81  if (i < ndims () - 1)
82  buf << sep;
83  }
84 
85  std::string retval = buf.str ();
86 
87  return retval;
88 }
89 
90 int
92 {
93  int retval = 0;
94 
95  for (int i = 0; i < ndims (); i++)
96  if (elem (i) == 1)
97  retval++;
98 
99  return retval;
100 }
101 
104 {
106  octave_idx_type n = 1;
107  int n_dims = ndims ();
108 
109  for (int i = 0; i < n_dims; i++)
110  {
111  n *= rep[i];
112  if (rep[i] != 0)
113  idx_max /= rep[i];
114  if (idx_max <= 0)
115  throw std::bad_alloc ();
116  }
117 
118  return n;
119 }
120 
123 {
124  dim_vector new_dims = *this;
125 
126  bool dims_changed = 1;
127 
128  int k = 0;
129 
130  for (int i = 0; i < ndims (); i++)
131  {
132  if (elem (i) == 1)
133  dims_changed = true;
134  else
135  new_dims(k++) = elem (i);
136  }
137 
138  if (dims_changed)
139  {
140  if (k == 0)
141  new_dims = dim_vector (1, 1);
142  else if (k == 1)
143  {
144  // There is one non-singleton dimension, so we need
145  // to decide the correct orientation.
146 
147  if (elem (0) == 1)
148  {
149  // The original dimension vector had a leading
150  // singleton dimension.
151 
152  octave_idx_type tmp = new_dims(0);
153 
154  new_dims.resize (2);
155 
156  new_dims(0) = 1;
157  new_dims(1) = tmp;
158  }
159  else
160  {
161  // The first element of the original dimension vector
162  // was not a singleton dimension.
163 
164  new_dims.resize (2);
165 
166  new_dims(1) = 1;
167  }
168  }
169  else
170  new_dims.resize (k);
171  }
172 
173  return new_dims;
174 }
175 
176 // This is the rule for cat(). cat (dim, A, B) works if one
177 // of the following holds, in this order:
178 //
179 // 1. size (A, k) == size (B, k) for all k != dim.
180 // In this case, size (C, dim) = size (A, dim) + size (B, dim) and
181 // other sizes remain intact.
182 //
183 // 2. A is 0x0, in which case B is the result
184 // 3. B is 0x0, in which case A is the result
185 
186 bool
187 dim_vector::concat (const dim_vector& dvb, int dim)
188 {
189  int orig_nd = ndims ();
190  int ndb = dvb.ndims ();
191  int new_nd = dim < ndb ? ndb : dim + 1;
192  if (new_nd > orig_nd)
193  resize (new_nd, 1);
194  else
195  new_nd = orig_nd;
196 
197  make_unique ();
198 
199  bool match = true;
200 
201  for (int i = 0; i < ndb; i++)
202  {
203  if (i != dim && rep[i] != dvb(i))
204  {
205  match = false;
206  break;
207  }
208  }
209 
210  for (int i = ndb; i < new_nd; i++)
211  {
212  if (i != dim && rep[i] != 1)
213  {
214  match = false;
215  break;
216  }
217  }
218 
219  if (match)
220  rep[dim] += (dim < ndb ? dvb(dim) : 1);
221  else
222  {
223  // Dimensions don't match. The only allowed fix is to omit 0x0.
224  if (ndb == 2 && dvb(0) == 0 && dvb(1) == 0)
225  match = true;
226  else if (orig_nd == 2 && rep[0] == 0 && rep[1] == 0)
227  {
228  *this = dvb;
229  match = true;
230  }
231  }
232 
234 
235  return match;
236 }
237 
238 // Rules for horzcat/vertcat are yet looser.
239 // two arrays A, B can be concatenated
240 // horizontally (dim = 2) or vertically (dim = 1) if one of the
241 // following holds, in this order:
242 //
243 // 1. cat (dim, A, B) works
244 //
245 // 2. A, B are 2D and one of them is an empty vector, in which
246 // case the result is the other one except if both of them
247 // are empty vectors, in which case the result is 0x0.
248 
249 bool
250 dim_vector::hvcat (const dim_vector& dvb, int dim)
251 {
252  if (concat (dvb, dim))
253  return true;
254  else if (ndims () == 2 && dvb.ndims () == 2)
255  {
256  bool e2dv = rep[0] + rep[1] == 1;
257  bool e2dvb = dvb(0) + dvb(1) == 1;
258  if (e2dvb)
259  {
260  if (e2dv)
261  *this = dim_vector ();
262  return true;
263  }
264  else if (e2dv)
265  {
266  *this = dvb;
267  return true;
268  }
269  }
270 
271  return false;
272 }
273 
275 dim_vector::redim (int n) const
276 {
277  int n_dims = ndims ();
278 
279  if (n_dims == n)
280  return *this;
281  else if (n_dims < n)
282  {
283  dim_vector retval = alloc (n);
284 
285  for (int i = 0; i < n_dims; i++)
286  retval.rep[i] = rep[i];
287 
288  for (int i = n_dims; i < n; i++)
289  retval.rep[i] = 1;
290 
291  return retval;
292  }
293  else
294  {
295  if (n < 1) n = 1;
296 
297  dim_vector retval = alloc (n);
298 
299  retval.rep[1] = 1;
300 
301  for (int i = 0; i < n-1; i++)
302  retval.rep[i] = rep[i];
303 
304  int k = rep[n-1];
305  for (int i = n; i < n_dims; i++)
306  k *= rep[i];
307 
308  retval.rep[n-1] = k;
309 
310  return retval;
311  }
312 }
for(octave_idx_type n=0;n< hcv.numel();n++)
Definition: graphics.cc:10128
std::string str(char sep= 'x') const
Definition: dim-vector.cc:73
for large enough k
Definition: lu.cc:606
void resize(int n, int fill_value=0)
Definition: dim-vector.h:316
void make_unique(void)
Definition: dim-vector.h:154
octave_idx_type & elem(int i)
Definition: dim-vector.h:215
int num_ones(void) const
Definition: dim-vector.cc:91
dim_vector squeeze(void) const
Definition: dim-vector.cc:122
octave_idx_type * rep
Definition: dim-vector.h:93
bool concat(const dim_vector &dvb, int dim)
This corresponds to cat().
Definition: dim-vector.cc:187
octave_idx_type safe_numel(void) const
Definition: dim-vector.cc:103
void chop_all_singletons(void)
Definition: dim-vector.cc:53
static octave_idx_type * nil_rep(void)
Definition: dim-vector.cc:36
static const octave_idx_type idx_max
Definition: dlmread.cc:44
double tmp
Definition: data.cc:6300
octave_value retval
Definition: data.cc:6294
dim_vector redim(int n) const
Definition: dim-vector.cc:275
static dim_vector alloc(int n)
Definition: dim-vector.h:270
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:228
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:301
bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
Definition: dim-vector.cc:250
static octave_idx_type dim_max(void)
Definition: dim-vector.cc:47
dim_vector(void)
Definition: dim-vector.h:261
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
void chop_trailing_singletons(void)
Definition: dim-vector.h:232
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854