GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
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