GNU Octave  8.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 Properties Friends Macros Pages
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