GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
MArray.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1993-2025 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
34template <typename T>
35class _idxadds_helper
36{
37public:
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
43private:
44 T *m_array;
45 T m_val;
46};
47
48template <typename T>
49class _idxadda_helper
50{
51public:
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
57private:
58 T *m_array;
59 const T *m_vals;
60};
61
62template <typename T>
63void
64MArray<T>::idx_add (const octave::idx_vector& idx, T val)
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->rwdata (), val));
78}
79
80template <typename T>
81void
82MArray<T>::idx_add (const octave::idx_vector& idx, const MArray<T>& vals)
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->rwdata (), vals.data ()));
96}
97
98template <typename T, T op (typename ref_param<T>::type,
99 typename ref_param<T>::type)>
100struct _idxbinop_helper
101{
102public:
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++); }
108private:
109 T *m_array;
110 const T *m_vals;
112
113template <typename T>
114void
115MArray<T>::idx_min (const octave::idx_vector& idx, const MArray<T>& vals)
116{
117 octave_idx_type n = this->numel ();
118 octave_idx_type ext = idx.extent (n);
119 if (ext > n)
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->rwdata (),
129 vals.data ()));
130}
131
132template <typename T>
133void
134MArray<T>::idx_max (const octave::idx_vector& idx, const MArray<T>& vals)
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->rwdata (),
148 vals.data ()));
149}
150
151template <typename T>
152void
153MArray<T>::idx_add_nd (const octave::idx_vector& idx,
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>::rwdata ();
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.
215template <typename T>
216void
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
227template <typename T>
229operator += (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
238template <typename T>
240operator -= (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
249template <typename T>
251operator *= (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
260template <typename T>
262operator /= (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
273template <typename 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
284template <typename 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
295template <typename 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
306template <typename 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
362template <typename T>
363MArray<T>
364operator + (const MArray<T>& a)
365{
366 return a;
367}
368
369template <typename T>
372{
373 return do_mx_unary_op<T, T> (a, mx_inline_uminus);
374}
375
376template <typename T>
377void
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>
#define MARRAY_NDS_OP(OP, FN)
Definition MArray.cc:319
MArray< T > & operator+=(MArray< T > &a, const T &s)
Definition MArray.cc:229
MArray< T > & quotient_eq(MArray< T > &a, const MArray< T > &b)
Definition MArray.cc:308
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 > operator-(const MArray< T > &a, const T &s)
Definition MArray.cc:328
MArray< T > product(const MArray< T > &a, const MArray< T > &b)
Definition MArray.cc:359
MArray< T > & operator*=(MArray< T > &a, const T &s)
Definition MArray.cc:251
#define MARRAY_SND_OP(OP, FN)
Definition MArray.cc:334
MArray< T > & product_eq(MArray< T > &a, const MArray< T > &b)
Definition MArray.cc:297
#define MARRAY_NDND_OP(FCN, OP, FN)
Definition MArray.cc:349
MArray< T > quotient(const MArray< T > &a, const MArray< T > &b)
Definition MArray.cc:360
N Dimensional Array with copy-on-write semantics.
Definition Array.h:130
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Definition Array.h:507
int ndims() const
Size of the specified dimension.
Definition Array.h:679
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
const T * data() const
Size of the specified dimension.
Definition Array.h:665
bool is_shared() const
Size of the specified dimension.
Definition Array.h:676
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
Template for N-dimensional array classes with like-type math operators.
Definition MArray.h:61
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:90
int first_non_singleton(int def=0) const
Definition dim-vector.h:440
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
void mx_inline_div2(std::size_t n, R *r, const X *x)
void mx_inline_sub2(std::size_t n, R *r, const X *x)
void mx_inline_add2(std::size_t n, R *r, const X *x)
void mx_inline_sub(std::size_t n, R *r, const X *x, const Y *y)
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)
void mx_inline_add(std::size_t n, R *r, const X *x, const Y *y)
void mx_inline_mul2(std::size_t n, R *r, const X *x)
void mx_inline_mul(std::size_t n, R *r, const X *x, const Y *y)
void get_extent_triplet(const dim_vector &dims, int &dim, octave_idx_type &l, octave_idx_type &n, octave_idx_type &u)
T::size_type numel(const T &str)
Definition oct-string.cc:74
F77_RET_T len
Definition xerbla.cc:61