GNU Octave  4.0.0
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-2015 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 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <iostream>
29 
30 #include "dim-vector.h"
31 
32 // The maximum allowed value for a dimension extent. This will normally be a
33 // tiny bit off the maximum value of octave_idx_type.
34 // Currently 1 is subtracted to allow safe conversion of any 2D Array into
35 // Sparse, but this offset may change in the future.
38 {
40 }
41 
42 void
44 {
45  make_unique ();
46 
47  int j = 0;
48  int l = ndims ();
49 
50  for (int i = 0; i < l; i++)
51  {
52  if (rep[i] != 1)
53  rep[j++] = rep[i];
54  }
55 
56  if (j == 1)
57  rep[1] = 1;
58 
59  ndims () = j > 2 ? j : 2;
60 }
61 
62 std::string
63 dim_vector::str (char sep) const
64 {
65  std::ostringstream buf;
66 
67  for (int i = 0; i < length (); i++)
68  {
69  buf << elem (i);
70 
71  if (i < length () - 1)
72  buf << sep;
73  }
74 
75  std::string retval = buf.str ();
76 
77  return retval;
78 }
79 
80 int
82 {
83  int retval = 0;
84 
85  for (int i = 0; i < length (); i++)
86  if (elem (i) == 1)
87  retval++;
88 
89  return retval;
90 }
91 
94 {
96  octave_idx_type n = 1;
97  int n_dims = length ();
98 
99  for (int i = 0; i < n_dims; i++)
100  {
101  n *= rep[i];
102  if (rep[i] != 0)
103  idx_max /= rep[i];
104  if (idx_max <= 0)
105  throw std::bad_alloc ();
106  }
107 
108  return n;
109 }
110 
113 {
114  dim_vector new_dims = *this;
115 
116  bool dims_changed = 1;
117 
118  int k = 0;
119 
120  for (int i = 0; i < length (); i++)
121  {
122  if (elem (i) == 1)
123  dims_changed = true;
124  else
125  new_dims(k++) = elem (i);
126  }
127 
128  if (dims_changed)
129  {
130  if (k == 0)
131  new_dims = dim_vector (1, 1);
132  else if (k == 1)
133  {
134  // There is one non-singleton dimension, so we need
135  // to decide the correct orientation.
136 
137  if (elem (0) == 1)
138  {
139  // The original dimension vector had a leading
140  // singleton dimension.
141 
142  octave_idx_type tmp = new_dims(0);
143 
144  new_dims.resize (2);
145 
146  new_dims(0) = 1;
147  new_dims(1) = tmp;
148  }
149  else
150  {
151  // The first element of the original dimension vector
152  // was not a singleton dimension.
153 
154  new_dims.resize (2);
155 
156  new_dims(1) = 1;
157  }
158  }
159  else
160  new_dims.resize (k);
161  }
162 
163  return new_dims;
164 }
165 
166 // This is the rule for cat(). cat (dim, A, B) works if one
167 // of the following holds, in this order:
168 //
169 // 1. size (A, k) == size (B, k) for all k != dim.
170 // In this case, size (C, dim) = size (A, dim) + size (B, dim) and
171 // other sizes remain intact.
172 //
173 // 2. A is 0x0, in which case B is the result
174 // 3. B is 0x0, in which case A is the result
175 
176 bool
177 dim_vector::concat (const dim_vector& dvb, int dim)
178 {
179  int orig_nd = ndims ();
180  int ndb = dvb.ndims ();
181  int new_nd = dim < ndb ? ndb : dim + 1;
182  if (new_nd > orig_nd)
183  resize (new_nd, 1);
184  else
185  new_nd = orig_nd;
186 
187  make_unique ();
188 
189  bool match = true;
190 
191  for (int i = 0; i < ndb; i++)
192  {
193  if (i != dim && rep[i] != dvb(i))
194  {
195  match = false;
196  break;
197  }
198  }
199 
200  for (int i = ndb; i < new_nd; i++)
201  {
202  if (i != dim && rep[i] != 1)
203  {
204  match = false;
205  break;
206  }
207  }
208 
209  if (match)
210  rep[dim] += (dim < ndb ? dvb(dim) : 1);
211  else
212  {
213  // Dimensions don't match. The only allowed fix is
214  // to omit 0x0.
215  if (ndb == 2 && dvb(0) == 0 && dvb(1) == 0)
216  match = true;
217  else if (orig_nd == 2 && rep[0] == 0 && rep[1] == 0)
218  {
219  *this = dvb;
220  match = true;
221  }
222  }
223 
225 
226  return match;
227 }
228 
229 // Rules for horzcat/vertcat are yet looser.
230 // two arrays A, B can be concatenated
231 // horizontally (dim = 2) or vertically (dim = 1) if one of the
232 // following holds, in this order:
233 //
234 // 1. cat (dim, A, B) works
235 //
236 // 2. A, B are 2D and one of them is an empty vector, in which
237 // case the result is the other one except if both of them
238 // are empty vectors, in which case the result is 0x0.
239 
240 bool
241 dim_vector::hvcat (const dim_vector& dvb, int dim)
242 {
243  if (concat (dvb, dim))
244  return true;
245  else if (length () == 2 && dvb.length () == 2)
246  {
247  bool e2dv = rep[0] + rep[1] == 1;
248  bool e2dvb = dvb(0) + dvb(1) == 1;
249  if (e2dvb)
250  {
251  if (e2dv)
252  *this = dim_vector ();
253  return true;
254  }
255  else if (e2dv)
256  {
257  *this = dvb;
258  return true;
259  }
260  }
261 
262  return false;
263 }
264 
266 dim_vector::redim (int n) const
267 {
268  int n_dims = length ();
269 
270  if (n_dims == n)
271  return *this;
272  else if (n_dims < n)
273  {
274  dim_vector retval = alloc (n);
275 
276  for (int i = 0; i < n_dims; i++)
277  retval.rep[i] = rep[i];
278 
279  for (int i = n_dims; i < n; i++)
280  retval.rep[i] = 1;
281 
282  return retval;
283  }
284  else
285  {
286  if (n < 1) n = 1;
287 
288  dim_vector retval = alloc (n);
289 
290  retval.rep[1] = 1;
291 
292  for (int i = 0; i < n-1; i++)
293  retval.rep[i] = rep[i];
294 
295  int k = rep[n-1];
296  for (int i = n; i < n_dims; i++)
297  k *= rep[i];
298 
299  retval.rep[n-1] = k;
300 
301  return retval;
302  }
303 }
std::string str(char sep= 'x') const
Definition: dim-vector.cc:63
void resize(int n, int fill_value=0)
Definition: dim-vector.h:287
void make_unique(void)
Definition: dim-vector.h:128
octave_idx_type & elem(int i)
Definition: dim-vector.h:197
int num_ones(void) const
Definition: dim-vector.cc:81
dim_vector squeeze(void) const
Definition: dim-vector.cc:112
octave_idx_type * rep
Definition: dim-vector.h:59
bool concat(const dim_vector &dvb, int dim)
This corresponds to cat().
Definition: dim-vector.cc:177
octave_idx_type safe_numel(void) const
Definition: dim-vector.cc:93
octave_idx_type & ndims(void) const
Definition: dim-vector.h:61
void chop_all_singletons(void)
Definition: dim-vector.cc:43
static const octave_idx_type idx_max
Definition: dlmread.cc:44
dim_vector redim(int n) const
Definition: dim-vector.cc:266
static dim_vector alloc(int n)
Definition: dim-vector.h:256
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
Definition: dim-vector.cc:241
static bool match(const std::string &filename_arg, const std::string &path_elt_arg)
Definition: kpse.cc:1738
static octave_idx_type dim_max(void)
Definition: dim-vector.cc:37
dim_vector(void)
Definition: dim-vector.h:247
void chop_trailing_singletons(void)
Definition: dim-vector.h:214
int length(void) const
Definition: dim-vector.h:281