GNU Octave  6.2.0
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-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // or <https://octave.org/copyright/>.
7 //
8 // Copyirght (C) 2009, 2010 VZLU Prague
9 //
10 // This file is part of Octave.
11 //
12 // Octave is free software: you can redistribute it and/or modify it
13 // under the terms of the GNU General Public License as published by
14 // the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // Octave is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with Octave; see the file COPYING. If not, see
24 // <https://www.gnu.org/licenses/>.
25 //
26 ////////////////////////////////////////////////////////////////////////
27 
28 #if defined (HAVE_CONFIG_H)
29 # include "config.h"
30 #endif
31 
32 #include <limits>
33 #include <new>
34 #include <sstream>
35 
36 #include "Array.h"
37 #include "dim-vector.h"
38 
41 {
42  // Create a statically allocated rep object with an initial reference
43  // count of 1. The dim_vector constructor that uses this object will
44  // increment the reference count. The dim_vector destructor and copy
45  // assignment operator will decrement the reference count but those
46  // operations can never cause the count to become zero so they will
47  // never call delete on this object.
48 
49  static octave_idx_type nr[4] = { 1, 2, 0, 0 };
50 
51  return &nr[2];
52 }
53 
54 // The maximum allowed value for a dimension extent. This will normally be a
55 // tiny bit off the maximum value of octave_idx_type.
56 // Currently 1 is subtracted to allow safe conversion of any 2D Array into
57 // Sparse, but this offset may change in the future.
60 {
62 }
63 
64 void
66 {
67  make_unique ();
68 
69  int j = 0;
70  int nd = ndims ();
71 
72  for (int i = 0; i < nd; i++)
73  {
74  if (rep[i] != 1)
75  rep[j++] = rep[i];
76  }
77 
78  if (j == 1)
79  rep[1] = 1;
80 
81  rep[-1] = (j > 2 ? j : 2);
82 }
83 
84 std::string
85 dim_vector::str (char sep) const
86 {
87  std::ostringstream buf;
88 
89  for (int i = 0; i < ndims (); i++)
90  {
91  buf << xelem (i);
92 
93  if (i < ndims () - 1)
94  buf << sep;
95  }
96 
97  std::string retval = buf.str ();
98 
99  return retval;
100 }
101 
102 int
104 {
105  int retval = 0;
106 
107  for (int i = 0; i < ndims (); i++)
108  if (xelem (i) == 1)
109  retval++;
110 
111  return retval;
112 }
113 
116 {
118  octave_idx_type n = 1;
119  int n_dims = ndims ();
120 
121  for (int i = 0; i < n_dims; i++)
122  {
123  n *= rep[i];
124  if (rep[i] != 0)
125  idx_max /= rep[i];
126  if (idx_max <= 0)
127  throw std::bad_alloc ();
128  }
129 
130  return n;
131 }
132 
135 {
136  dim_vector new_dims = *this;
137  new_dims.chop_all_singletons ();
138 
139  // preserve orientation if there is only one non-singleton dimension left
140  if (new_dims.ndims () == 2 && xelem(0) == 1 && new_dims.elem(1) == 1)
141  return new_dims.as_row ();
142 
143  return new_dims;
144 }
145 
146 // This is the rule for cat(). cat (dim, A, B) works if one
147 // of the following holds, in this order:
148 //
149 // 1. size (A, k) == size (B, k) for all k != dim.
150 // In this case, size (C, dim) = size (A, dim) + size (B, dim) and
151 // other sizes remain intact.
152 //
153 // 2. A is 0x0, in which case B is the result
154 // 3. B is 0x0, in which case A is the result
155 
156 bool
157 dim_vector::concat (const dim_vector& dvb, int dim)
158 {
159  int orig_nd = ndims ();
160  int ndb = dvb.ndims ();
161  int new_nd = (dim < ndb ? ndb : dim + 1);
162  if (new_nd > orig_nd)
163  resize (new_nd, 1);
164  else
165  new_nd = orig_nd;
166 
167  make_unique ();
168 
169  bool match = true;
170 
171  for (int i = 0; i < ndb; i++)
172  {
173  if (i != dim && rep[i] != dvb(i))
174  {
175  match = false;
176  break;
177  }
178  }
179 
180  for (int i = ndb; i < new_nd; i++)
181  {
182  if (i != dim && rep[i] != 1)
183  {
184  match = false;
185  break;
186  }
187  }
188 
189  if (match)
190  rep[dim] += (dim < ndb ? dvb(dim) : 1);
191  else
192  {
193  // Dimensions don't match. The only allowed fix is to omit 0x0.
194  if (ndb == 2 && dvb(0) == 0 && dvb(1) == 0)
195  match = true;
196  else if (orig_nd == 2 && rep[0] == 0 && rep[1] == 0)
197  {
198  *this = dvb;
199  match = true;
200  }
201  }
202 
204 
205  return match;
206 }
207 
208 // Rules for horzcat/vertcat are yet looser.
209 // two arrays A, B can be concatenated
210 // horizontally (dim = 2) or vertically (dim = 1) if one of the
211 // following holds, in this order:
212 //
213 // 1. cat (dim, A, B) works
214 //
215 // 2. A, B are 2D and one of them is an empty vector, in which
216 // case the result is the other one except if both of them
217 // are empty vectors, in which case the result is 0x0.
218 
219 bool
220 dim_vector::hvcat (const dim_vector& dvb, int dim)
221 {
222  if (concat (dvb, dim))
223  return true;
224  else if (ndims () == 2 && dvb.ndims () == 2)
225  {
226  bool e2dv = rep[0] + rep[1] == 1;
227  bool e2dvb = dvb(0) + dvb(1) == 1;
228  if (e2dvb)
229  {
230  if (e2dv)
231  *this = dim_vector ();
232  return true;
233  }
234  else if (e2dv)
235  {
236  *this = dvb;
237  return true;
238  }
239  }
240 
241  return false;
242 }
243 
245 dim_vector::redim (int n) const
246 {
247  int n_dims = ndims ();
248 
249  if (n_dims == n)
250  return *this;
251  else if (n_dims < n)
252  {
253  dim_vector retval = alloc (n);
254 
255  std::copy_n (rep, n_dims, retval.rep);
256  std::fill_n (retval.rep + n_dims, n - n_dims, 1);
257 
258  return retval;
259  }
260  else
261  {
262  if (n < 1)
263  n = 1;
264 
265  dim_vector retval = alloc (n);
266 
267  std::copy_n (rep, n-1, retval.rep);
268 
269  // Accumulate overflow dimensions into last remaining dimension
270  int k = rep[n-1];
271  for (int i = n; i < n_dims; i++)
272  k *= rep[i];
273 
274  retval.rep[n-1] = k;
275 
276  // All dim_vectors are at least 2-D. Make Nx1 if necessary.
277  if (n == 1)
278  retval.rep[1] = 1;
279 
280  return retval;
281  }
282 }
283 
286 {
287  octave_idx_type nd = ndims ();
288 
290 
291  for (octave_idx_type i = 0; i < nd; i++)
292  retval(i) = elem (i);
293 
294  return retval;
295 }
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
Array< T >::ArrayRep * rep
Definition: Array.h:219
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
Array< octave_idx_type > as_array(void) const
Definition: dim-vector.cc:285
bool concat(const dim_vector &dvb, int dim)
This corresponds to cat().
Definition: dim-vector.cc:157
void chop_all_singletons(void)
Definition: dim-vector.cc:65
std::string str(char sep='x') const
Definition: dim-vector.cc:85
void resize(int n, int fill_value=0)
Definition: dim-vector.h:349
static dim_vector alloc(int n)
Definition: dim-vector.h:281
static octave_idx_type * nil_rep(void)
Definition: dim-vector.cc:40
static octave_idx_type dim_max(void)
Definition: dim-vector.cc:59
int num_ones(void) const
Definition: dim-vector.cc:103
bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
Definition: dim-vector.cc:220
void chop_trailing_singletons(void)
Definition: dim-vector.h:241
dim_vector(void)
Definition: dim-vector.h:270
octave_idx_type & xelem(int i)
Definition: dim-vector.h:227
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:334
dim_vector squeeze(void) const
Definition: dim-vector.cc:134
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
Definition: dim-vector.cc:245
void make_unique(void)
Definition: dim-vector.h:165
dim_vector as_row(void) const
Definition: dim-vector.h:453
octave_idx_type & elem(int i)
Definition: dim-vector.h:233
octave_idx_type * rep
Definition: dim-vector.h:98
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:115
static const octave_idx_type idx_max
Definition: dlmread.cc:50
octave_idx_type n
Definition: mx-inlines.cc:753
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811