GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
dNDArray.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-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#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <istream>
31#include <limits>
32#include <ostream>
33
34#include "Array-util.h"
35#include "dNDArray.h"
36#include "f77-fcn.h"
37#include "lo-error.h"
38#include "lo-ieee.h"
39#include "lo-mappers.h"
40#include "mx-base.h"
41#include "mx-op-defs.h"
42#include "oct-fftw.h"
43#include "oct-locbuf.h"
44
45#include "bsxfun-defs.cc"
46
47NDArray::NDArray (const Array<octave_idx_type>& a, bool zero_based,
48 bool negative_to_nan)
49{
50 const octave_idx_type *pa = a.data ();
51 resize (a.dims ());
52 double *ptmp = rwdata ();
53 if (negative_to_nan)
54 {
55 double nan_val = lo_ieee_nan_value ();
56
57 if (zero_based)
58 for (octave_idx_type i = 0; i < a.numel (); i++)
59 {
60 double val = static_cast<double>
61 (pa[i] + static_cast<octave_idx_type> (1));
62 if (val <= 0)
63 ptmp[i] = nan_val;
64 else
65 ptmp[i] = val;
66 }
67 else
68 for (octave_idx_type i = 0; i < a.numel (); i++)
69 {
70 double val = static_cast<double> (pa[i]);
71 if (val <= 0)
72 ptmp[i] = nan_val;
73 else
74 ptmp[i] = val;
75 }
76 }
77 else
78 {
79 if (zero_based)
80 for (octave_idx_type i = 0; i < a.numel (); i++)
81 ptmp[i] = static_cast<double>
82 (pa[i] + static_cast<octave_idx_type> (1));
83 else
84 for (octave_idx_type i = 0; i < a.numel (); i++)
85 ptmp[i] = static_cast<double> (pa[i]);
86 }
87}
88
90 : MArray<double> (a.dims ())
91{
92 octave_idx_type n = a.numel ();
93 for (octave_idx_type i = 0; i < n; i++)
94 xelem (i) = static_cast<unsigned char> (a(i));
95}
96
97#if defined (HAVE_FFTW)
98
100NDArray::fourier (int dim) const
101{
102 const dim_vector& dv = dims ();
103
104 if (dim > dv.ndims () || dim < 0)
105 return ComplexNDArray ();
106
107 octave_idx_type stride = 1;
108 octave_idx_type n = dv(dim);
109
110 for (int i = 0; i < dim; i++)
111 stride *= dv(i);
112
113 octave_idx_type howmany = numel () / dv(dim);
114 howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
115 octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);
116 octave_idx_type dist = (stride == 1 ? n : 1);
117
118 const double *in (data ());
119 ComplexNDArray retval (dv);
120 Complex *out (retval.rwdata ());
121
122 // Need to be careful here about the distance between fft's
123 for (octave_idx_type k = 0; k < nloop; k++)
124 octave::fftw::fft (in + k * stride * n, out + k * stride * n,
125 n, howmany, stride, dist);
126
127 return retval;
128}
129
131NDArray::ifourier (int dim) const
132{
133 const dim_vector& dv = dims ();
134
135 if (dim > dv.ndims () || dim < 0)
136 return ComplexNDArray ();
137
138 octave_idx_type stride = 1;
139 octave_idx_type n = dv(dim);
140
141 for (int i = 0; i < dim; i++)
142 stride *= dv(i);
143
144 octave_idx_type howmany = numel () / dv(dim);
145 howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
146 octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);
147 octave_idx_type dist = (stride == 1 ? n : 1);
148
149 ComplexNDArray retval (*this);
150 Complex *out (retval.rwdata ());
151
152 // Need to be careful here about the distance between fft's
153 for (octave_idx_type k = 0; k < nloop; k++)
154 octave::fftw::ifft (out + k * stride * n, out + k * stride * n,
155 n, howmany, stride, dist);
156
157 return retval;
158}
159
162{
163 const dim_vector& dv = dims ();
164 if (dv.ndims () < 2)
165 return ComplexNDArray ();
166
167 dim_vector dv2 (dv(0), dv(1));
168 const double *in = data ();
169 ComplexNDArray retval (dv);
170 Complex *out = retval.rwdata ();
171 octave_idx_type howmany = numel () / dv(0) / dv(1);
172 octave_idx_type dist = dv(0) * dv(1);
173
174 for (octave_idx_type i=0; i < howmany; i++)
175 octave::fftw::fftNd (in + i*dist, out + i*dist, 2, dv2);
176
177 return retval;
178}
179
182{
183 const dim_vector& dv = dims ();
184 if (dv.ndims () < 2)
185 return ComplexNDArray ();
186
187 dim_vector dv2 (dv(0), dv(1));
188 ComplexNDArray retval (*this);
189 Complex *out = retval.rwdata ();
190 octave_idx_type howmany = numel () / dv(0) / dv(1);
191 octave_idx_type dist = dv(0) * dv(1);
192
193 for (octave_idx_type i=0; i < howmany; i++)
194 octave::fftw::ifftNd (out + i*dist, out + i*dist, 2, dv2);
195
196 return retval;
197}
198
201{
202 const dim_vector& dv = dims ();
203 int rank = dv.ndims ();
204
205 const double *in (data ());
206 ComplexNDArray retval (dv);
207 Complex *out (retval.rwdata ());
208
209 octave::fftw::fftNd (in, out, rank, dv);
210
211 return retval;
212}
213
216{
217 const dim_vector& dv = dims ();
218 int rank = dv.ndims ();
219
220 ComplexNDArray tmp (*this);
221 Complex *in (tmp.rwdata ());
222 ComplexNDArray retval (dv);
223 Complex *out (retval.rwdata ());
224
225 octave::fftw::ifftNd (in, out, rank, dv);
226
227 return retval;
228}
229
230#else
231
233NDArray::fourier (int dim) const
234{
235 octave_unused_parameter (dim);
236
237 (*current_liboctave_error_handler)
238 ("support for FFTW was unavailable or disabled when liboctave was built");
239
240 return ComplexNDArray ();
241}
242
244NDArray::ifourier (int dim) const
245{
246 octave_unused_parameter (dim);
247
248 (*current_liboctave_error_handler)
249 ("support for FFTW was unavailable or disabled when liboctave was built");
250
251 return ComplexNDArray ();
252}
253
255NDArray::fourier2d () const
256{
257 (*current_liboctave_error_handler)
258 ("support for FFTW was unavailable or disabled when liboctave was built");
259
260 return ComplexNDArray ();
261}
262
264NDArray::ifourier2d () const
265{
266 (*current_liboctave_error_handler)
267 ("support for FFTW was unavailable or disabled when liboctave was built");
268
269 return ComplexNDArray ();
270}
271
273NDArray::fourierNd () const
274{
275 (*current_liboctave_error_handler)
276 ("support for FFTW was unavailable or disabled when liboctave was built");
277
278 return ComplexNDArray ();
279}
280
282NDArray::ifourierNd () const
283{
284 (*current_liboctave_error_handler)
285 ("support for FFTW was unavailable or disabled when liboctave was built");
286
287 return ComplexNDArray ();
288}
289
290#endif
291
292// unary operations
293
296{
297 if (any_element_is_nan ())
298 octave::err_nan_to_logical_conversion ();
299
300 return do_mx_unary_op<bool, double> (*this, mx_inline_not);
301}
302
303bool
305{
306 return (neg_zero ? test_all (octave::math::negative_sign)
307 : do_mx_check<double> (*this, mx_inline_any_negative));
308}
309
310bool
312{
313 return (neg_zero ? test_all (octave::math::positive_sign)
314 : do_mx_check<double> (*this, mx_inline_any_positive));
315}
316
317bool
319{
320 return do_mx_check<double> (*this, mx_inline_any_nan);
321}
322
323bool
325{
326 return ! do_mx_check<double> (*this, mx_inline_all_finite);
327}
328
329bool
331{
332 return ! test_all (octave::is_one_or_zero);
333}
334
335bool
337{
338 return test_all (octave::is_zero);
339}
340
341bool
343{
344 return test_all (octave::is_int_or_inf_or_nan);
345}
346
347// Return nonzero if any element of M is not an integer. Also extract
348// the largest and smallest values and return them in MAX_VAL and MIN_VAL.
349
350bool
351NDArray::all_integers (double& max_val, double& min_val) const
352{
353 octave_idx_type nel = numel ();
354
355 if (nel > 0)
356 {
357 max_val = elem (0);
358 min_val = elem (0);
359 }
360 else
361 return false;
362
363 for (octave_idx_type i = 0; i < nel; i++)
364 {
365 double val = elem (i);
366
367 if (val > max_val)
368 max_val = val;
369
370 if (val < min_val)
371 min_val = val;
372
373 if (! octave::math::isinteger (val))
374 return false;
375 }
376
377 return true;
378}
379
380bool
382{
383 return test_all (octave::math::isinteger);
384}
385
386bool
388{
389 return test_any (octave::too_large_for_float);
390}
391
392// FIXME: this is not quite the right thing.
393
395NDArray::all (int dim) const
396{
397 return do_mx_red_op<bool, double> (*this, dim, mx_inline_all);
398}
399
401NDArray::any (int dim) const
402{
403 return do_mx_red_op<bool, double> (*this, dim, mx_inline_any);
404}
405
407NDArray::cumprod (int dim) const
408{
409 return do_mx_cum_op<double, double> (*this, dim, mx_inline_cumprod);
410}
411
413NDArray::cumsum (int dim) const
414{
415 return do_mx_cum_op<double, double> (*this, dim, mx_inline_cumsum);
416}
417
419NDArray::prod (int dim) const
420{
421 return do_mx_red_op<double, double> (*this, dim, mx_inline_prod);
422}
423
425NDArray::sum (int dim) const
426{
427 return do_mx_red_op<double, double> (*this, dim, mx_inline_sum);
428}
429
431NDArray::xsum (int dim) const
432{
433 return do_mx_red_op<double, double> (*this, dim, mx_inline_xsum);
434}
435
437NDArray::sumsq (int dim) const
438{
439 return do_mx_red_op<double, double> (*this, dim, mx_inline_sumsq);
440}
441
443NDArray::max (int dim) const
444{
445 return do_mx_minmax_op<double> (*this, dim, mx_inline_max);
446}
447
449NDArray::max (Array<octave_idx_type>& idx_arg, int dim) const
450{
451 return do_mx_minmax_op<double> (*this, idx_arg, dim, mx_inline_max);
452}
453
455NDArray::min (int dim) const
456{
457 return do_mx_minmax_op<double> (*this, dim, mx_inline_min);
458}
459
461NDArray::min (Array<octave_idx_type>& idx_arg, int dim) const
462{
463 return do_mx_minmax_op<double> (*this, idx_arg, dim, mx_inline_min);
464}
465
467NDArray::cummax (int dim) const
468{
469 return do_mx_cumminmax_op<double> (*this, dim, mx_inline_cummax);
470}
471
474{
475 return do_mx_cumminmax_op<double> (*this, idx_arg, dim, mx_inline_cummax);
476}
477
479NDArray::cummin (int dim) const
480{
481 return do_mx_cumminmax_op<double> (*this, dim, mx_inline_cummin);
482}
483
486{
487 return do_mx_cumminmax_op<double> (*this, idx_arg, dim, mx_inline_cummin);
488}
489
491NDArray::diff (octave_idx_type order, int dim) const
492{
493 return do_mx_diff_op<double> (*this, dim, order, mx_inline_diff);
494}
495
498{
499 if (rb.numel () > 0)
500 insert (rb, ra_idx);
501 return *this;
502}
503
506{
507 ComplexNDArray retval (*this);
508 if (rb.numel () > 0)
509 retval.insert (rb, ra_idx);
510 return retval;
511}
512
515{
516 charNDArray retval (dims ());
517 octave_idx_type nel = numel ();
518
519 for (octave_idx_type i = 0; i < nel; i++)
520 {
521 double d = elem (i);
522
523 if (octave::math::isnan (d))
524 (*current_liboctave_error_handler)
525 ("invalid conversion from NaN to character");
526
527 octave_idx_type ival = octave::math::nint_big (d);
528
529 if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())
530 // FIXME: is there something better to do? Should we warn the user?
531 ival = 0;
532
533 retval.elem (i) = static_cast<char> (ival);
534 }
535
536 if (rb.isempty ())
537 return retval;
538
539 retval.insert (rb, ra_idx);
540 return retval;
541}
542
545{
546 return do_mx_unary_op<double, Complex> (a, mx_inline_real);
547}
548
551{
552 return do_mx_unary_op<double, Complex> (a, mx_inline_imag);
553}
554
555NDArray&
557{
558 Array<double>::insert (a, r, c);
559 return *this;
560}
561
562NDArray&
564{
566 return *this;
567}
568
571{
572 return do_mx_unary_map<double, double, std::abs> (*this);
573}
574
577{
578 return do_mx_unary_map<bool, double, octave::math::isnan> (*this);
579}
580
583{
584 return do_mx_unary_map<bool, double, octave::math::isinf> (*this);
585}
586
589{
590 return do_mx_unary_map<bool, double, octave::math::isfinite> (*this);
591}
592
593void
595 const dim_vector& dimensions,
596 int start_dimension)
597{
598 ::increment_index (ra_idx, dimensions, start_dimension);
599}
600
603 const dim_vector& dimensions)
604{
605 return ::compute_index (ra_idx, dimensions);
606}
607
610{
611 return MArray<double>::diag (k);
612}
613
616{
617 return MArray<double>::diag (m, n);
618}
619
620// This contains no information on the array structure !!!
621std::ostream&
622operator << (std::ostream& os, const NDArray& a)
623{
624 octave_idx_type nel = a.numel ();
625
626 for (octave_idx_type i = 0; i < nel; i++)
627 {
628 os << ' ';
629 octave::write_value<double> (os, a.elem (i));
630 os << "\n";
631 }
632 return os;
633}
634
635std::istream&
636operator >> (std::istream& is, NDArray& a)
637{
638 octave_idx_type nel = a.numel ();
639
640 if (nel > 0)
641 {
642 double tmp;
643 for (octave_idx_type i = 0; i < nel; i++)
644 {
645 tmp = octave::read_value<double> (is);
646 if (is)
647 a.elem (i) = tmp;
648 else
649 return is;
650 }
651 }
652
653 return is;
654}
655
657
660
663
666
669
#define BSXFUN_STDREL_DEFS_MXLOOP(ARRAY)
#define BSXFUN_STDOP_DEFS_MXLOOP(ARRAY)
#define BSXFUN_OP2_DEF_MXLOOP(OP, ARRAY, ARRAY1, ARRAY2, LOOP)
#define BSXFUN_OP_DEF_MXLOOP(OP, ARRAY, LOOP)
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
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition Array.h:525
bool test_all(F fcn) const
Size of the specified dimension.
Definition Array.h:924
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition Array.h:563
bool test_any(F fcn) const
Simpler calls.
Definition Array.h:920
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Array< T, Alloc > & insert(const Array< T, Alloc > &a, const Array< octave_idx_type > &idx)
Insert an array into another at a specified position.
bool isempty() const
Size of the specified dimension.
Definition Array.h:652
const T * data() const
Size of the specified dimension.
Definition Array.h:665
T * rwdata()
Size of the specified dimension.
Array< T, Alloc > diag(octave_idx_type k=0) const
Get the kth super or subdiagonal.
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
ComplexNDArray & insert(const NDArray &a, octave_idx_type r, octave_idx_type c)
Definition CNDArray.cc:508
Template for N-dimensional array classes with like-type math operators.
Definition MArray.h:61
ComplexNDArray ifourier(int dim=1) const
Definition dNDArray.cc:131
bool any_element_is_inf_or_nan() const
Definition dNDArray.cc:324
bool any_element_not_one_or_zero() const
Definition dNDArray.cc:330
NDArray abs() const
Definition dNDArray.cc:570
NDArray diag(octave_idx_type k=0) const
Definition dNDArray.cc:609
static octave_idx_type compute_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions)
Definition dNDArray.cc:602
NDArray min(int dim=-1) const
Definition dNDArray.cc:455
boolNDArray isinf() const
Definition dNDArray.cc:582
NDArray diff(octave_idx_type order=1, int dim=-1) const
Definition dNDArray.cc:491
ComplexNDArray fourier2d() const
Definition dNDArray.cc:161
ComplexNDArray fourierNd() const
Definition dNDArray.cc:200
NDArray cumsum(int dim=-1) const
Definition dNDArray.cc:413
NDArray cummax(int dim=-1) const
Definition dNDArray.cc:467
NDArray sumsq(int dim=-1) const
Definition dNDArray.cc:437
bool any_element_is_nan() const
Definition dNDArray.cc:318
bool too_large_for_float() const
Definition dNDArray.cc:387
NDArray max(int dim=-1) const
Definition dNDArray.cc:443
boolNDArray isfinite() const
Definition dNDArray.cc:588
ComplexNDArray fourier(int dim=1) const
Definition dNDArray.cc:100
bool any_element_is_positive(bool=false) const
Definition dNDArray.cc:311
NDArray prod(int dim=-1) const
Definition dNDArray.cc:419
static void increment_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions, int start_dimension=0)
Definition dNDArray.cc:594
NDArray cummin(int dim=-1) const
Definition dNDArray.cc:479
NDArray cumprod(int dim=-1) const
Definition dNDArray.cc:407
boolNDArray all(int dim=-1) const
Definition dNDArray.cc:395
ComplexNDArray ifourier2d() const
Definition dNDArray.cc:181
bool all_elements_are_int_or_inf_or_nan() const
Definition dNDArray.cc:342
boolNDArray isnan() const
Definition dNDArray.cc:576
boolNDArray operator!() const
Definition dNDArray.cc:295
NDArray xsum(int dim=-1) const
Definition dNDArray.cc:431
NDArray & insert(const NDArray &a, octave_idx_type r, octave_idx_type c)
Definition dNDArray.cc:556
boolNDArray any(int dim=-1) const
Definition dNDArray.cc:401
NDArray()
Definition dNDArray.h:41
bool all_integers() const
Definition dNDArray.cc:381
bool any_element_is_negative(bool=false) const
Definition dNDArray.cc:304
bool all_elements_are_zero() const
Definition dNDArray.cc:336
ComplexNDArray ifourierNd() const
Definition dNDArray.cc:215
NDArray concat(const NDArray &rb, const Array< octave_idx_type > &ra_idx)
Definition dNDArray.cc:497
friend class ComplexNDArray
Definition dNDArray.h:141
NDArray sum(int dim=-1) const
Definition dNDArray.cc:425
charNDArray & insert(const charNDArray &a, octave_idx_type r, octave_idx_type c)
Definition chNDArray.cc:166
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
octave_idx_type ndims() const
Number of dimensions.
Definition dim-vector.h:253
std::ostream & operator<<(std::ostream &os, const NDArray &a)
Definition dNDArray.cc:622
NDArray real(const ComplexNDArray &a)
Definition dNDArray.cc:544
NDArray imag(const ComplexNDArray &a)
Definition dNDArray.cc:550
std::istream & operator>>(std::istream &is, NDArray &a)
Definition dNDArray.cc:636
double lo_ieee_nan_value()
Definition lo-ieee.cc:84
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
bool mx_inline_any(const T *v, octave_idx_type n)
T mx_inline_xsum(const T *v, octave_idx_type n)
void mx_inline_cummin(const T *v, T *r, octave_idx_type n)
void mx_inline_cumprod(const T *v, T *r, octave_idx_type n)
void mx_inline_cumsum(const T *v, T *r, octave_idx_type n)
bool mx_inline_any_nan(std::size_t n, const T *x)
void mx_inline_max(const T *v, T *r, octave_idx_type n)
void mx_inline_not(std::size_t n, bool *r, const X *x)
void mx_inline_cummax(const T *v, T *r, octave_idx_type n)
bool mx_inline_all(const T *v, octave_idx_type n)
void mx_inline_real(std::size_t n, T *r, const std::complex< T > *x)
T mx_inline_sumsq(const T *v, octave_idx_type n)
bool mx_inline_any_positive(std::size_t n, const T *x)
void mx_inline_imag(std::size_t n, T *r, const std::complex< T > *x)
T mx_inline_sum(const T *v, octave_idx_type n)
void mx_inline_min(const T *v, T *r, octave_idx_type n)
T mx_inline_prod(const T *v, octave_idx_type n)
void mx_inline_diff(const T *v, T *r, octave_idx_type n, octave_idx_type order)
bool mx_inline_all_finite(std::size_t n, const T *x)
bool mx_inline_any_negative(std::size_t n, const T *x)
void mx_inline_pow(std::size_t n, R *r, const X *x, const Y *y)
#define NDND_BOOL_OPS(ND1, ND2)
Definition mx-op-defs.h:350
#define NDS_BOOL_OPS(ND, S)
Definition mx-op-defs.h:256
#define NDND_CMP_OPS(ND1, ND2)
Definition mx-op-defs.h:333
#define SND_BOOL_OPS(S, ND)
Definition mx-op-defs.h:303
#define NDS_CMP_OPS(ND, S)
Definition mx-op-defs.h:239
#define SND_CMP_OPS(S, ND)
Definition mx-op-defs.h:286
#define MINMAX_FCNS(T, S)
Definition mx-op-defs.h:589
std::complex< double > Complex
Definition oct-cmplx.h:33
octave_int< T > pow(const octave_int< T > &a, const octave_int< T > &b)
const octave_base_value const Array< octave_idx_type > & ra_idx