GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MArray.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 // This file should not include config.h. It is only included in other
27 // C++ source files that should have included config.h before including
28 // this file.
29 
30 #include "MArray.h"
31 #include "Array-util.h"
32 #include "lo-error.h"
33 
34 template <typename T>
35 class _idxadds_helper
36 {
37 public:
38  _idxadds_helper (T *a, T v) : m_array (a), m_val (v) { }
39 
40  void operator () (octave_idx_type i)
41  { m_array[i] += m_val; }
42 
43 private:
44  T *m_array;
45  T m_val;
46 };
47 
48 template <typename T>
49 class _idxadda_helper
50 {
51 public:
52  _idxadda_helper (T *a, const T *v) : m_array (a), m_vals (v) { }
53 
54  void operator () (octave_idx_type i)
55  { m_array[i] += *m_vals++; }
56 
57 private:
58  T *m_array;
59  const T *m_vals;
60 };
61 
62 template <typename T>
63 void
65 {
66  octave_idx_type n = this->numel ();
67  octave_idx_type ext = idx.extent (n);
68  if (ext > n)
69  {
70  this->resize1 (ext);
71  n = ext;
72  }
73 
74  octave_quit ();
75 
76  octave_idx_type len = idx.length (n);
77  idx.loop (len, _idxadds_helper<T> (this->fortran_vec (), val));
78 }
79 
80 template <typename T>
81 void
83 {
84  octave_idx_type n = this->numel ();
85  octave_idx_type ext = idx.extent (n);
86  if (ext > n)
87  {
88  this->resize1 (ext);
89  n = ext;
90  }
91 
92  octave_quit ();
93 
94  octave_idx_type len = std::min (idx.length (n), vals.numel ());
95  idx.loop (len, _idxadda_helper<T> (this->fortran_vec (), vals.data ()));
96 }
97 
98 template <typename T, T op (typename ref_param<T>::type,
99  typename ref_param<T>::type)>
100 struct _idxbinop_helper
101 {
102 public:
103  _idxbinop_helper (T *a, const T *v) : m_array (a), m_vals (v) { }
104 
105  void operator () (octave_idx_type i)
106  { m_array[i] = op (m_array[i], *m_vals++); }
107 
108 private:
109  T *m_array;
110  const T *m_vals;
111 };
112 
113 template <typename T>
114 void
116 {
117  octave_idx_type n = this->numel ();
118  octave_idx_type ext = idx.extent (n);
119  if (ext > n)
120  {
121  this->resize1 (ext);
122  n = ext;
123  }
124 
125  octave_quit ();
126 
127  octave_idx_type len = std::min (idx.length (n), vals.numel ());
128  idx.loop (len, _idxbinop_helper<T, octave::math::min> (this->fortran_vec (),
129  vals.data ()));
130 }
131 
132 template <typename T>
133 void
135 {
136  octave_idx_type n = this->numel ();
137  octave_idx_type ext = idx.extent (n);
138  if (ext > n)
139  {
140  this->resize1 (ext);
141  n = ext;
142  }
143 
144  octave_quit ();
145 
146  octave_idx_type len = std::min (idx.length (n), vals.numel ());
147  idx.loop (len, _idxbinop_helper<T, octave::math::max> (this->fortran_vec (),
148  vals.data ()));
149 }
150 
151 template <typename T>
152 void
154  const MArray<T>& vals, int dim)
155 {
156  int nd = std::max (this->ndims (), vals.ndims ());
157  if (dim < 0)
158  dim = vals.dims ().first_non_singleton ();
159  else if (dim > nd)
160  nd = dim;
161 
162  // Check dimensions.
163  dim_vector ddv = Array<T>::dims ().redim (nd);
164  dim_vector sdv = vals.dims ().redim (nd);
165 
166  octave_idx_type ext = idx.extent (ddv(dim));
167 
168  if (ext > ddv(dim))
169  {
170  ddv(dim) = ext;
171  Array<T>::resize (ddv);
172  ext = ddv(dim);
173  }
174 
175  octave_idx_type l, n, u, ns;
176  get_extent_triplet (ddv, dim, l, n, u);
177  ns = sdv(dim);
178 
179  sdv(dim) = ddv(dim) = 0;
180  if (ddv != sdv)
181  (*current_liboctave_error_handler) ("accumdim: dimension mismatch");
182 
183  T *dst = Array<T>::fortran_vec ();
184  const T *src = vals.data ();
185  octave_idx_type len = idx.length (ns);
186 
187  if (l == 1)
188  {
189  for (octave_idx_type j = 0; j < u; j++)
190  {
191  octave_quit ();
192 
193  idx.loop (len, _idxadda_helper<T> (dst + j*n, src + j*ns));
194  }
195  }
196  else
197  {
198  for (octave_idx_type j = 0; j < u; j++)
199  {
200  octave_quit ();
201  for (octave_idx_type i = 0; i < len; i++)
202  {
203  octave_idx_type k = idx(i);
204 
205  mx_inline_add2 (l, dst + l*k, src + l*i);
206  }
207 
208  dst += l*n;
209  src += l*ns;
210  }
211  }
212 }
213 
214 // N-dimensional array with math ops.
215 template <typename T>
216 void
218 {
219  if (Array<T>::is_shared ())
220  *this = - *this;
221  else
222  do_mx_inplace_op<T> (*this, mx_inline_uminus2);
223 }
224 
225 // Element by element MArray by scalar ops.
226 
227 template <typename T>
228 MArray<T>&
229 operator += (MArray<T>& a, const T& s)
230 {
231  if (a.is_shared ())
232  a = a + s;
233  else
234  do_ms_inplace_op<T, T> (a, s, mx_inline_add2);
235  return a;
236 }
237 
238 template <typename T>
239 MArray<T>&
240 operator -= (MArray<T>& a, const T& s)
241 {
242  if (a.is_shared ())
243  a = a - s;
244  else
245  do_ms_inplace_op<T, T> (a, s, mx_inline_sub2);
246  return a;
247 }
248 
249 template <typename T>
250 MArray<T>&
251 operator *= (MArray<T>& a, const T& s)
252 {
253  if (a.is_shared ())
254  a = a * s;
255  else
256  do_ms_inplace_op<T, T> (a, s, mx_inline_mul2);
257  return a;
258 }
259 
260 template <typename T>
261 MArray<T>&
262 operator /= (MArray<T>& a, const T& s)
263 {
264  if (a.is_shared ())
265  a = a / s;
266  else
267  do_ms_inplace_op<T, T> (a, s, mx_inline_div2);
268  return a;
269 }
270 
271 // Element by element MArray by MArray ops.
272 
273 template <typename T>
274 MArray<T>&
276 {
277  if (a.is_shared ())
278  a = a + b;
279  else
280  do_mm_inplace_op<T, T> (a, b, mx_inline_add2, mx_inline_add2, "+=");
281  return a;
282 }
283 
284 template <typename T>
285 MArray<T>&
287 {
288  if (a.is_shared ())
289  a = a - b;
290  else
291  do_mm_inplace_op<T, T> (a, b, mx_inline_sub2, mx_inline_sub2, "-=");
292  return a;
293 }
294 
295 template <typename T>
296 MArray<T>&
298 {
299  if (a.is_shared ())
300  return a = product (a, b);
301  else
302  do_mm_inplace_op<T, T> (a, b, mx_inline_mul2, mx_inline_mul2, ".*=");
303  return a;
304 }
305 
306 template <typename T>
307 MArray<T>&
309 {
310  if (a.is_shared ())
311  return a = quotient (a, b);
312  else
313  do_mm_inplace_op<T, T> (a, b, mx_inline_div2, mx_inline_div2, "./=");
314  return a;
315 }
316 
317 // Element by element MArray by scalar ops.
318 
319 #define MARRAY_NDS_OP(OP, FN) \
320  template <typename T> \
321  MArray<T> \
322  operator OP (const MArray<T>& a, const T& s) \
323  { \
324  return do_ms_binary_op<T, T, T> (a, s, FN); \
325  }
326 
331 
332 // Element by element scalar by MArray ops.
333 
334 #define MARRAY_SND_OP(OP, FN) \
335  template <typename T> \
336  MArray<T> \
337  operator OP (const T& s, const MArray<T>& a) \
338  { \
339  return do_sm_binary_op<T, T, T> (s, a, FN); \
340  }
341 
346 
347 // Element by element MArray by MArray ops.
348 
349 #define MARRAY_NDND_OP(FCN, OP, FN) \
350  template <typename T> \
351  MArray<T> \
352  FCN (const MArray<T>& a, const MArray<T>& b) \
353  { \
354  return do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN); \
355  }
356 
361 
362 template <typename T>
363 MArray<T>
364 operator + (const MArray<T>& a)
365 {
366  return a;
367 }
368 
369 template <typename T>
370 MArray<T>
372 {
373  return do_mx_unary_op<T, T> (a, mx_inline_uminus);
374 }
375 
376 template <typename T>
377 void
379 {
380  // This guards against accidental implicit instantiations.
381  // Array<T, Alloc> instances should always be explicit and use INSTANTIATE_ARRAY.
382  T::__xXxXx__ ();
383 }
384 
385 #define INSTANTIATE_MARRAY(T, API) \
386  template <> API void \
387  MArray<T>::instantiation_guard () { } \
388  \
389  template class API MArray<T>
MArray< T > & quotient_eq(MArray< T > &a, const MArray< T > &b)
Definition: MArray.cc:308
#define MARRAY_NDS_OP(OP, FN)
Definition: MArray.cc:319
MArray< T > operator-(const MArray< T > &a, const T &s)
Definition: MArray.cc:328
MArray< T > & product_eq(MArray< T > &a, const MArray< T > &b)
Definition: MArray.cc:297
MArray< T > quotient(const MArray< T > &a, const MArray< T > &b)
Definition: MArray.cc:360
MArray< T > & operator*=(MArray< T > &a, const T &s)
Definition: MArray.cc:251
MArray< T > & operator+=(MArray< T > &a, const T &s)
Definition: MArray.cc:229
#define MARRAY_SND_OP(OP, FN)
Definition: MArray.cc:334
MArray< T > & operator/=(MArray< T > &a, const T &s)
Definition: MArray.cc:262
MArray< T > & operator-=(MArray< T > &a, const T &s)
Definition: MArray.cc:240
MArray< T > product(const MArray< T > &a, const MArray< T > &b)
Definition: MArray.cc:359
#define MARRAY_NDND_OP(FCN, OP, FN)
Definition: MArray.cc:349
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:130
T * fortran_vec()
Size of the specified dimension.
Definition: Array-base.cc:1764
int ndims() const
Size of the specified dimension.
Definition: Array.h:671
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array-base.cc:1023
const T * data() const
Size of the specified dimension.
Definition: Array.h:663
bool is_shared() const
Size of the specified dimension.
Definition: Array.h:668
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:503
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
Template for N-dimensional array classes with like-type math operators.
Definition: MArray.h:63
void idx_min(const octave::idx_vector &idx, const MArray< T > &vals)
Definition: MArray.cc:115
void idx_add_nd(const octave::idx_vector &idx, const MArray< T > &vals, int dim=-1)
Definition: MArray.cc:153
void idx_add(const octave::idx_vector &idx, T val)
Performs indexed accumulative addition.
Definition: MArray.cc:64
void idx_max(const octave::idx_vector &idx, const MArray< T > &vals)
Definition: MArray.cc:134
void changesign()
Definition: MArray.cc:217
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
int first_non_singleton(int def=0) const
Definition: dim-vector.h:444
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
Definition: dim-vector.cc:226
octave::idx_vector idx_vector
Definition: idx-vector.h:1022
void mx_inline_div2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:130
void mx_inline_sub2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:128
void mx_inline_add2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:127
void mx_inline_sub(std::size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:109
void mx_inline_uminus(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:56
void mx_inline_uminus2(std::size_t n, R *r)
Definition: mx-inlines.cc:64
void mx_inline_div(std::size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:111
void mx_inline_add(std::size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:108
void mx_inline_mul2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:129
void mx_inline_mul(std::size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:110
octave_idx_type n
Definition: mx-inlines.cc:761
void get_extent_triplet(const dim_vector &dims, int &dim, octave_idx_type &l, octave_idx_type &n, octave_idx_type &u)
Definition: mx-inlines.cc:1508
T::size_type numel(const T &str)
Definition: oct-string.cc:74
F77_RET_T len
Definition: xerbla.cc:61