GNU Octave  8.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-2023 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>
36 {
37 public:
38  _idxadds_helper (T *a, T v) : m_array (a), m_val (v) { }
39 
41  { m_array[i] += m_val; }
42 
43 private:
44  T *m_array;
45  T m_val;
46 };
47 
48 template <typename T>
50 {
51 public:
52  _idxadda_helper (T *a, const T *v) : m_array (a), m_vals (v) { }
53 
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)>
101 {
102 public:
103  _idxbinop_helper (T *a, const T *v) : m_array (a), m_vals (v) { }
104 
106  { m_array[i] = op (m_array[i], *m_vals++); }
107 
108 private:
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>
153  const MArray<T>& vals, int dim)
154 {
155  int nd = std::max (this->ndims (), vals.ndims ());
156  if (dim < 0)
157  dim = vals.dims ().first_non_singleton ();
158  else if (dim > nd)
159  nd = dim;
160 
161  // Check dimensions.
162  dim_vector ddv = Array<T>::dims ().redim (nd);
163  dim_vector sdv = vals.dims ().redim (nd);
164 
165  octave_idx_type ext = idx.extent (ddv(dim));
166 
167  if (ext > ddv(dim))
168  {
169  ddv(dim) = ext;
170  Array<T>::resize (ddv);
171  ext = ddv(dim);
172  }
173 
174  octave_idx_type l, n, u, ns;
175  get_extent_triplet (ddv, dim, l, n, u);
176  ns = sdv(dim);
177 
178  sdv(dim) = ddv(dim) = 0;
179  if (ddv != sdv)
180  (*current_liboctave_error_handler) ("accumdim: dimension mismatch");
181 
182  T *dst = Array<T>::fortran_vec ();
183  const T *src = vals.data ();
184  octave_idx_type len = idx.length (ns);
185 
186  if (l == 1)
187  {
188  for (octave_idx_type j = 0; j < u; j++)
189  {
190  octave_quit ();
191 
192  idx.loop (len, _idxadda_helper<T> (dst + j*n, src + j*ns));
193  }
194  }
195  else
196  {
197  for (octave_idx_type j = 0; j < u; j++)
198  {
199  octave_quit ();
200  for (octave_idx_type i = 0; i < len; i++)
201  {
202  octave_idx_type k = idx(i);
203 
204  mx_inline_add2 (l, dst + l*k, src + l*i);
205  }
206 
207  dst += l*n;
208  src += l*ns;
209  }
210  }
211 }
212 
213 // N-dimensional array with math ops.
214 template <typename T>
215 void
217 {
218  if (Array<T>::is_shared ())
219  *this = - *this;
220  else
221  do_mx_inplace_op<T> (*this, mx_inline_uminus2);
222 }
223 
224 // Element by element MArray by scalar ops.
225 
226 template <typename T>
227 MArray<T>&
228 operator += (MArray<T>& a, const T& s)
229 {
230  if (a.is_shared ())
231  a = a + s;
232  else
233  do_ms_inplace_op<T, T> (a, s, mx_inline_add2);
234  return a;
235 }
236 
237 template <typename T>
238 MArray<T>&
239 operator -= (MArray<T>& a, const T& s)
240 {
241  if (a.is_shared ())
242  a = a - s;
243  else
244  do_ms_inplace_op<T, T> (a, s, mx_inline_sub2);
245  return a;
246 }
247 
248 template <typename T>
249 MArray<T>&
250 operator *= (MArray<T>& a, const T& s)
251 {
252  if (a.is_shared ())
253  a = a * s;
254  else
255  do_ms_inplace_op<T, T> (a, s, mx_inline_mul2);
256  return a;
257 }
258 
259 template <typename T>
260 MArray<T>&
261 operator /= (MArray<T>& a, const T& s)
262 {
263  if (a.is_shared ())
264  a = a / s;
265  else
266  do_ms_inplace_op<T, T> (a, s, mx_inline_div2);
267  return a;
268 }
269 
270 // Element by element MArray by MArray ops.
271 
272 template <typename T>
273 MArray<T>&
275 {
276  if (a.is_shared ())
277  a = a + b;
278  else
279  do_mm_inplace_op<T, T> (a, b, mx_inline_add2, mx_inline_add2, "+=");
280  return a;
281 }
282 
283 template <typename T>
284 MArray<T>&
286 {
287  if (a.is_shared ())
288  a = a - b;
289  else
290  do_mm_inplace_op<T, T> (a, b, mx_inline_sub2, mx_inline_sub2, "-=");
291  return a;
292 }
293 
294 template <typename T>
295 MArray<T>&
297 {
298  if (a.is_shared ())
299  return a = product (a, b);
300  else
301  do_mm_inplace_op<T, T> (a, b, mx_inline_mul2, mx_inline_mul2, ".*=");
302  return a;
303 }
304 
305 template <typename T>
306 MArray<T>&
308 {
309  if (a.is_shared ())
310  return a = quotient (a, b);
311  else
312  do_mm_inplace_op<T, T> (a, b, mx_inline_div2, mx_inline_div2, "./=");
313  return a;
314 }
315 
316 // Element by element MArray by scalar ops.
317 
318 #define MARRAY_NDS_OP(OP, FN) \
319  template <typename T> \
320  MArray<T> \
321  operator OP (const MArray<T>& a, const T& s) \
322  { \
323  return do_ms_binary_op<T, T, T> (a, s, FN); \
324  }
325 
330 
331 // Element by element scalar by MArray ops.
332 
333 #define MARRAY_SND_OP(OP, FN) \
334  template <typename T> \
335  MArray<T> \
336  operator OP (const T& s, const MArray<T>& a) \
337  { \
338  return do_sm_binary_op<T, T, T> (s, a, FN); \
339  }
340 
345 
346 // Element by element MArray by MArray ops.
347 
348 #define MARRAY_NDND_OP(FCN, OP, FN) \
349  template <typename T> \
350  MArray<T> \
351  FCN (const MArray<T>& a, const MArray<T>& b) \
352  { \
353  return do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN); \
354  }
355 
360 
361 template <typename T>
362 MArray<T>
363 operator + (const MArray<T>& a)
364 {
365  return a;
366 }
367 
368 template <typename T>
369 MArray<T>
371 {
372  return do_mx_unary_op<T, T> (a, mx_inline_uminus);
373 }
374 
375 template <typename T>
377 {
378  // This guards against accidental implicit instantiations.
379  // Array<T, Alloc> instances should always be explicit and use INSTANTIATE_ARRAY.
380  T::__xXxXx__ ();
381 }
382 
383 #define INSTANTIATE_MARRAY(T, API) \
384  template <> API void \
385  MArray<T>::instantiation_guard () { } \
386  \
387  template class API MArray<T>
MArray< T > & quotient_eq(MArray< T > &a, const MArray< T > &b)
Definition: MArray.cc:307
#define MARRAY_NDS_OP(OP, FN)
Definition: MArray.cc:318
MArray< T > operator-(const MArray< T > &a, const T &s)
Definition: MArray.cc:327
MArray< T > & product_eq(MArray< T > &a, const MArray< T > &b)
Definition: MArray.cc:296
MArray< T > quotient(const MArray< T > &a, const MArray< T > &b)
Definition: MArray.cc:359
MArray< T > & operator*=(MArray< T > &a, const T &s)
Definition: MArray.cc:250
MArray< T > & operator+=(MArray< T > &a, const T &s)
Definition: MArray.cc:228
#define MARRAY_SND_OP(OP, FN)
Definition: MArray.cc:333
MArray< T > & operator/=(MArray< T > &a, const T &s)
Definition: MArray.cc:261
MArray< T > & operator-=(MArray< T > &a, const T &s)
Definition: MArray.cc:239
MArray< T > product(const MArray< T > &a, const MArray< T > &b)
Definition: MArray.cc:358
#define MARRAY_NDND_OP(FCN, OP, FN)
Definition: MArray.cc:348
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
OCTARRAY_OVERRIDABLE_FUNC_API const T * data(void) const
Size of the specified dimension.
Definition: Array.h:663
OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:414
OCTARRAY_OVERRIDABLE_FUNC_API const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:503
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array-base.cc:1032
OCTARRAY_API T * fortran_vec(void)
Size of the specified dimension.
Definition: Array-base.cc:1766
OCTARRAY_OVERRIDABLE_FUNC_API bool is_shared(void) const
Size of the specified dimension.
Definition: Array.h:674
OCTARRAY_OVERRIDABLE_FUNC_API int ndims(void) const
Size of the specified dimension.
Definition: Array.h:677
Template for N-dimensional array classes with like-type math operators.
Definition: MArray.h:63
OCTARRAY_API void idx_min(const octave::idx_vector &idx, const MArray< T > &vals)
Definition: MArray.cc:115
OCTARRAY_API void idx_add_nd(const octave::idx_vector &idx, const MArray< T > &vals, int dim=-1)
Definition: MArray.cc:152
OCTARRAY_API void changesign(void)
Definition: MArray.cc:216
OCTARRAY_API void idx_add(const octave::idx_vector &idx, T val)
Performs indexed accumulative addition.
Definition: MArray.cc:64
OCTARRAY_API void idx_max(const octave::idx_vector &idx, const MArray< T > &vals)
Definition: MArray.cc:134
static OCTARRAY_API void instantiation_guard()
Definition: MArray.cc:376
const T * m_vals
Definition: MArray.cc:59
void operator()(octave_idx_type i)
Definition: MArray.cc:54
_idxadda_helper(T *a, const T *v)
Definition: MArray.cc:52
void operator()(octave_idx_type i)
Definition: MArray.cc:40
_idxadds_helper(T *a, T v)
Definition: MArray.cc:38
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
OCTAVE_API 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:1039
void mx_inline_div2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:129
void mx_inline_sub2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:127
void mx_inline_add2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:126
void mx_inline_sub(std::size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:108
void mx_inline_uminus(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:55
void mx_inline_uminus2(std::size_t n, R *r)
Definition: mx-inlines.cc:63
void mx_inline_div(std::size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:110
void mx_inline_add(std::size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:107
void mx_inline_mul2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:128
void mx_inline_mul(std::size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:109
octave_idx_type n
Definition: mx-inlines.cc:753
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:1499
T::size_type numel(const T &str)
Definition: oct-string.cc:71
_idxbinop_helper(T *a, const T *v)
Definition: MArray.cc:103
void operator()(octave_idx_type i)
Definition: MArray.cc:105
const T * m_vals
Definition: MArray.cc:110
F77_RET_T len
Definition: xerbla.cc:61