GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
dim-vector.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2003-2025 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
39// The maximum allowed value for a dimension extent. This will normally be a
40// tiny bit off the maximum value of octave_idx_type.
41// Currently 1 is subtracted to allow safe conversion of any 2D Array into
42// Sparse, but this offset may change in the future.
45{
46 return std::numeric_limits<octave_idx_type>::max () - 1;
47}
48
49void
51{
52 int j = 0;
53 int nd = ndims ();
54
55 for (int i = 0; i < nd; i++)
56 {
57 if (xelem(i) != 1)
58 xelem(j++) = xelem(i);
59 }
60
61 if (j == 1)
62 xelem(1) = 1;
63
64 m_num_dims = (j > 2 ? j : 2);
65}
66
67std::string
68dim_vector::str (char sep) const
69{
70 std::ostringstream buf;
71
72 for (int i = 0; i < ndims (); i++)
73 {
74 buf << xelem (i);
75
76 if (i < ndims () - 1)
77 buf << sep;
78 }
79
80 std::string retval = buf.str ();
81
82 return retval;
83}
84
85int
87{
88 int retval = 0;
89
90 for (int i = 0; i < ndims (); i++)
91 if (xelem (i) == 1)
92 retval++;
93
94 return retval;
95}
96
99{
100 octave_idx_type idx_max = dim_max ();
101 octave_idx_type n = 1;
102 int n_dims = ndims ();
103
104 for (int i = 0; i < n_dims; i++)
105 {
106 n *= xelem(i);
107 if (xelem(i) != 0)
108 idx_max /= xelem(i);
109 if (idx_max <= 0)
110 throw std::bad_alloc ();
111 }
112
113 return n;
114}
115
118{
119 dim_vector new_dims = *this;
120 new_dims.chop_all_singletons ();
121
122 // preserve orientation if there is only one non-singleton dimension left
123 if (new_dims.ndims () == 2 && xelem(0) == 1 && new_dims.elem(1) == 1)
124 return new_dims.as_row ();
125
126 return new_dims;
127}
128
129// This is the rule for cat(). cat (dim, A, B) works if one
130// of the following holds, in this order:
131//
132// 1. size (A, k) == size (B, k) for all k != dim.
133// In this case, size (C, dim) = size (A, dim) + size (B, dim) and
134// other sizes remain intact.
135//
136// 2. A is 0x0, in which case B is the result
137// 3. B is 0x0, in which case A is the result
138
139bool
140dim_vector::concat (const dim_vector& dvb, int dim)
141{
142 int orig_nd = ndims ();
143 int ndb = dvb.ndims ();
144 int new_nd = (dim < ndb ? ndb : dim + 1);
145 if (new_nd > orig_nd)
146 resize (new_nd, 1);
147 else
148 new_nd = orig_nd;
149
150 bool match = true;
151
152 for (int i = 0; i < ndb; i++)
153 {
154 if (i != dim && xelem(i) != dvb(i))
155 {
156 match = false;
157 break;
158 }
159 }
160
161 for (int i = ndb; i < new_nd; i++)
162 {
163 if (i != dim && xelem(i) != 1)
164 {
165 match = false;
166 break;
167 }
168 }
169
170 if (match)
171 xelem(dim) += (dim < ndb ? dvb(dim) : 1);
172 else
173 {
174 // Dimensions don't match. The only allowed fix is to omit 0x0.
175 if (ndb == 2 && dvb(0) == 0 && dvb(1) == 0)
176 match = true;
177 else if (orig_nd == 2 && xelem(0) == 0 && xelem(1) == 0)
178 {
179 *this = dvb;
180 match = true;
181 }
182 }
183
185
186 return match;
187}
188
189// Rules for horzcat/vertcat are yet looser.
190// two arrays A, B can be concatenated
191// horizontally (dim = 2) or vertically (dim = 1) if one of the
192// following holds, in this order:
193//
194// 1. cat (dim, A, B) works
195//
196// 2. A, B are 2D and one of them is an empty vector, in which
197// case the result is the other one except if both of them
198// are empty vectors, in which case the result is 0x0.
199
200bool
201dim_vector::hvcat (const dim_vector& dvb, int dim)
202{
203 if (concat (dvb, dim))
204 return true;
205 else if (ndims () == 2 && dvb.ndims () == 2)
206 {
207 bool e2dv = xelem(0) + xelem(1) == 1;
208 bool e2dvb = dvb(0) + dvb(1) == 1;
209 if (e2dvb)
210 {
211 if (e2dv)
212 *this = dim_vector ();
213 return true;
214 }
215 else if (e2dv)
216 {
217 *this = dvb;
218 return true;
219 }
220 }
221
222 return false;
223}
224
226dim_vector::redim (int n) const
227{
228 int n_dims = ndims ();
229
230 if (n_dims == n)
231 return *this;
232 else if (n_dims < n)
233 {
234 dim_vector retval = alloc (n);
235
236 std::copy_n (m_dims, n_dims, retval.m_dims);
237 std::fill_n (retval.m_dims + n_dims, n - n_dims, 1);
238
239 return retval;
240 }
241 else
242 {
243 if (n < 1)
244 n = 1;
245
246 dim_vector retval = alloc (n);
247
248 std::copy_n (m_dims, n-1, retval.m_dims);
249
250 // Accumulate overflow dimensions into last remaining dimension
251 int k = xelem(n-1);
252 for (int i = n; i < n_dims; i++)
253 k *= xelem(i);
254
255 retval.xelem(n-1) = k;
256
257 // All dim_vectors are at least 2-D. Make Nx1 if necessary.
258 if (n == 1)
259 retval.xelem(1) = 1;
260
261 return retval;
262 }
263}
264
267{
268 octave_idx_type nd = ndims ();
269
270 Array<octave_idx_type> retval (dim_vector (1, nd));
271
272 for (octave_idx_type i = 0; i < nd; i++)
273 retval(i) = elem (i);
274
275 return retval;
276}
N Dimensional Array with copy-on-write semantics.
Definition Array.h:130
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
bool concat(const dim_vector &dvb, int dim)
This corresponds to cat().
octave_idx_type safe_numel() const
The following function will throw a std::bad_alloc () exception if the requested size is larger than ...
Definition dim-vector.cc:98
std::string str(char sep='x') const
Definition dim-vector.cc:68
void chop_trailing_singletons()
Definition dim-vector.h:160
dim_vector squeeze() const
void resize(int n, int fill_value=0)
Definition dim-vector.h:268
static dim_vector alloc(int n)
Definition dim-vector.h:198
Array< octave_idx_type > as_array() const
octave_idx_type ndims() const
Number of dimensions.
Definition dim-vector.h:253
static octave_idx_type dim_max()
Definition dim-vector.cc:44
void chop_all_singletons()
Definition dim-vector.cc:50
bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
octave_idx_type & xelem(int i)
Definition dim-vector.h:147
int num_ones() const
Definition dim-vector.cc:86
octave_idx_type & elem(int i)
Definition dim-vector.h:153
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
dim_vector as_row() const
Definition dim-vector.h:383