GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
dim-vector.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2003-2018 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
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License 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 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <limits>
29 #include <new>
30 #include <sstream>
31 
32 #include "Array.h"
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 nd = ndims ();
59 
60  for (int i = 0; i < nd; 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 << xelem (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 (xelem (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  new_dims.chop_all_singletons ();
126 
127  // preserve orientation if there is only one non-singleton dimension left
128  if (new_dims.ndims () == 2 && xelem(0) == 1 && new_dims.elem(1) == 1)
129  return new_dims.as_row ();
130 
131  return new_dims;
132 }
133 
134 // This is the rule for cat(). cat (dim, A, B) works if one
135 // of the following holds, in this order:
136 //
137 // 1. size (A, k) == size (B, k) for all k != dim.
138 // In this case, size (C, dim) = size (A, dim) + size (B, dim) and
139 // other sizes remain intact.
140 //
141 // 2. A is 0x0, in which case B is the result
142 // 3. B is 0x0, in which case A is the result
143 
144 bool
145 dim_vector::concat (const dim_vector& dvb, int dim)
146 {
147  int orig_nd = ndims ();
148  int ndb = dvb.ndims ();
149  int new_nd = (dim < ndb ? ndb : dim + 1);
150  if (new_nd > orig_nd)
151  resize (new_nd, 1);
152  else
153  new_nd = orig_nd;
154 
155  make_unique ();
156 
157  bool match = true;
158 
159  for (int i = 0; i < ndb; i++)
160  {
161  if (i != dim && rep[i] != dvb(i))
162  {
163  match = false;
164  break;
165  }
166  }
167 
168  for (int i = ndb; i < new_nd; i++)
169  {
170  if (i != dim && rep[i] != 1)
171  {
172  match = false;
173  break;
174  }
175  }
176 
177  if (match)
178  rep[dim] += (dim < ndb ? dvb(dim) : 1);
179  else
180  {
181  // Dimensions don't match. The only allowed fix is to omit 0x0.
182  if (ndb == 2 && dvb(0) == 0 && dvb(1) == 0)
183  match = true;
184  else if (orig_nd == 2 && rep[0] == 0 && rep[1] == 0)
185  {
186  *this = dvb;
187  match = true;
188  }
189  }
190 
192 
193  return match;
194 }
195 
196 // Rules for horzcat/vertcat are yet looser.
197 // two arrays A, B can be concatenated
198 // horizontally (dim = 2) or vertically (dim = 1) if one of the
199 // following holds, in this order:
200 //
201 // 1. cat (dim, A, B) works
202 //
203 // 2. A, B are 2D and one of them is an empty vector, in which
204 // case the result is the other one except if both of them
205 // are empty vectors, in which case the result is 0x0.
206 
207 bool
208 dim_vector::hvcat (const dim_vector& dvb, int dim)
209 {
210  if (concat (dvb, dim))
211  return true;
212  else if (ndims () == 2 && dvb.ndims () == 2)
213  {
214  bool e2dv = rep[0] + rep[1] == 1;
215  bool e2dvb = dvb(0) + dvb(1) == 1;
216  if (e2dvb)
217  {
218  if (e2dv)
219  *this = dim_vector ();
220  return true;
221  }
222  else if (e2dv)
223  {
224  *this = dvb;
225  return true;
226  }
227  }
228 
229  return false;
230 }
231 
233 dim_vector::redim (int n) const
234 {
235  int n_dims = ndims ();
236 
237  if (n_dims == n)
238  return *this;
239  else if (n_dims < n)
240  {
241  dim_vector retval = alloc (n);
242 
243  std::copy_n (rep, n_dims, retval.rep);
244  std::fill_n (retval.rep + n_dims, n - n_dims, 1);
245 
246  return retval;
247  }
248  else
249  {
250  if (n < 1)
251  n = 1;
252 
253  dim_vector retval = alloc (n);
254 
255  std::copy_n (rep, n-1, retval.rep);
256 
257  // Accumulate overflow dimensions into last remaining dimension
258  int k = rep[n-1];
259  for (int i = n; i < n_dims; i++)
260  k *= rep[i];
261 
262  retval.rep[n-1] = k;
263 
264  // All dim_vectors are at least 2-D. Make Nx1 if necessary.
265  if (n == 1)
266  retval.rep[1] = 1;
267 
268  return retval;
269  }
270 }
271 
274 {
275  octave_idx_type nd = ndims ();
276 
278 
279  for (octave_idx_type i = 0; i < nd; i++)
280  retval(i) = elem (i);
281 
282  return retval;
283 }
std::string str(char sep='x') const
Definition: dim-vector.cc:73
octave_idx_type safe_numel(void) const
The following function will throw a std::bad_alloc () exception if the requested size is larger than ...
Definition: dim-vector.cc:103
dim_vector as_row(void) const
Definition: dim-vector.h:414
for large enough k
Definition: lu.cc:617
void resize(int n, int fill_value=0)
Definition: dim-vector.h:310
octave_idx_type & xelem(int i)
Definition: dim-vector.h:212
void make_unique(void)
Definition: dim-vector.h:150
octave_idx_type & elem(int i)
Definition: dim-vector.h:218
octave_base_value * rep
The real representation.
Definition: ov.h:1505
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:145
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:45
Array< octave_idx_type > as_array(void) const
Definition: dim-vector.cc:273
octave_value retval
Definition: data.cc:6246
static dim_vector alloc(int n)
Definition: dim-vector.h:264
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
Definition: dim-vector.cc:233
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:227
bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
Definition: dim-vector.cc:208
dim_vector squeeze(void) const
Definition: dim-vector.cc:122
for i
Definition: data.cc:5264
static octave_idx_type dim_max(void)
Definition: dim-vector.cc:47
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:295
dim_vector(void)
Definition: dim-vector.h:255
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
void chop_trailing_singletons(void)
Definition: dim-vector.h:226
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:888
int num_ones(void) const
Definition: dim-vector.cc:91