GNU Octave 11.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
CNDArray.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2026 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 <complex>
31#include <istream>
32#include <ostream>
33
34#include "Array-util.h"
35#include "CNDArray.h"
36#include "f77-fcn.h"
37#include "lo-ieee.h"
38#include "mappers.h"
39#include "mx-base.h"
40#include "mx-cnda-s.h"
41#include "mx-op-defs.h"
42#include "oct-fftw.h"
43#include "oct-locbuf.h"
44
45#include "bsxfun-defs.cc"
46
48 : MArray<Complex> (a.dims ())
49{
50 octave_idx_type n = a.numel ();
51 for (octave_idx_type i = 0; i < n; i++)
52 xelem (i) = static_cast<unsigned char> (a(i));
53}
54
55#if defined (HAVE_FFTW)
56
59{
60 const dim_vector& dv = dims ();
61
62 if (dim > dv.ndims () || dim < 0)
63 return ComplexNDArray ();
64
65 octave_idx_type stride = 1;
66 octave_idx_type n = dv(dim);
67
68 for (int i = 0; i < dim; i++)
69 stride *= dv(i);
70
71 octave_idx_type howmany = numel () / dv(dim);
72 howmany = (stride == 1) ? howmany : std::min (howmany, stride);
73 octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);
74 octave_idx_type dist = (stride == 1 ? n : 1);
75
76 const Complex *in (data ());
77 ComplexNDArray retval (dv);
78 Complex *out (retval.rwdata ());
79
80 // Need to be careful here about the distance between fft's
81 for (octave_idx_type k = 0; k < nloop; k++)
82 octave::fftw::fft (in + k * stride * n, out + k * stride * n,
83 n, howmany, stride, dist);
84
85 return retval;
86}
87
90{
91 const dim_vector& dv = dims ();
92
93 if (dim > dv.ndims () || dim < 0)
94 return ComplexNDArray ();
95
96 octave_idx_type stride = 1;
97 octave_idx_type n = dv(dim);
98
99 for (int i = 0; i < dim; i++)
100 stride *= dv(i);
101
102 octave_idx_type howmany = numel () / dv(dim);
103 howmany = (stride == 1) ? howmany : std::min (howmany, stride);
104 octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv(dim) / stride);
105 octave_idx_type dist = (stride == 1 ? n : 1);
106
107 const Complex *in (data ());
108 ComplexNDArray retval (dv);
109 Complex *out (retval.rwdata ());
110
111 // Need to be careful here about the distance between fft's
112 for (octave_idx_type k = 0; k < nloop; k++)
113 octave::fftw::ifft (in + k * stride * n, out + k * stride * n,
114 n, howmany, stride, dist);
115
116 return retval;
117}
118
121{
122 const dim_vector& dv = dims ();
123 if (dv.ndims () < 2)
124 return ComplexNDArray ();
125
126 dim_vector dv2 (dv(0), dv(1));
127 const Complex *in = data ();
128 ComplexNDArray retval (dv);
129 Complex *out = retval.rwdata ();
130 octave_idx_type howmany = numel () / dv(0) / dv(1);
131 octave_idx_type dist = dv(0) * dv(1);
132
133 for (octave_idx_type i=0; i < howmany; i++)
134 octave::fftw::fftNd (in + i*dist, out + i*dist, 2, dv2);
135
136 return retval;
137}
138
141{
142 const dim_vector& dv = dims ();
143 if (dv.ndims () < 2)
144 return ComplexNDArray ();
145
146 dim_vector dv2 (dv(0), dv(1));
147 const Complex *in = data ();
148 ComplexNDArray retval (dv);
149 Complex *out = retval.rwdata ();
150 octave_idx_type howmany = numel () / dv(0) / dv(1);
151 octave_idx_type dist = dv(0) * dv(1);
152
153 for (octave_idx_type i=0; i < howmany; i++)
154 octave::fftw::ifftNd (in + i*dist, out + i*dist, 2, dv2);
155
156 return retval;
157}
158
161{
162 const dim_vector& dv = dims ();
163 int rank = dv.ndims ();
164
165 const Complex *in (data ());
166 ComplexNDArray retval (dv);
167 Complex *out (retval.rwdata ());
168
169 octave::fftw::fftNd (in, out, rank, dv);
170
171 return retval;
172}
173
176{
177 const dim_vector& dv = dims ();
178 int rank = dv.ndims ();
179
180 const Complex *in (data ());
181 ComplexNDArray retval (dv);
182 Complex *out (retval.rwdata ());
183
184 octave::fftw::ifftNd (in, out, rank, dv);
185
186 return retval;
187}
188
189#else
190
192ComplexNDArray::fourier (int dim) const
193{
194 octave_unused_parameter (dim);
195
196 (*current_liboctave_error_handler)
197 ("support for FFTW was unavailable or disabled when liboctave was built");
198
199 return ComplexNDArray ();
200}
201
203ComplexNDArray::ifourier (int dim) const
204{
205 octave_unused_parameter (dim);
206
207 (*current_liboctave_error_handler)
208 ("support for FFTW was unavailable or disabled when liboctave was built");
209
210 return ComplexNDArray ();
211}
212
215{
216 (*current_liboctave_error_handler)
217 ("support for FFTW was unavailable or disabled when liboctave was built");
218
219 return ComplexNDArray ();
220}
221
224{
225 (*current_liboctave_error_handler)
226 ("support for FFTW was unavailable or disabled when liboctave was built");
227
228 return ComplexNDArray ();
229}
230
233{
234 (*current_liboctave_error_handler)
235 ("support for FFTW was unavailable or disabled when liboctave was built");
236
237 return ComplexNDArray ();
238}
239
242{
243 (*current_liboctave_error_handler)
244 ("support for FFTW was unavailable or disabled when liboctave was built");
245
246 return ComplexNDArray ();
247}
248
249#endif
250
251// unary operations
252
255{
256 if (any_element_is_nan ())
257 octave::err_nan_to_logical_conversion ();
258
259 return do_mx_unary_op<bool, Complex> (*this, mx_inline_not);
260}
261
262// FIXME: this is not quite the right thing.
263
264bool
266{
267 return do_mx_check<Complex> (*this, mx_inline_any_nan);
268}
269
270bool
272{
273 return ! do_mx_check<Complex> (*this, mx_inline_all_finite);
274}
275
276// Return true if no elements have imaginary components.
277
278bool
280{
281 return do_mx_check<Complex> (*this, mx_inline_all_real);
282}
283
284// Return nonzero if any element of CM has a non-integer real or
285// imaginary part. Also extract the largest and smallest (real or
286// imaginary) values and return them in MAX_VAL and MIN_VAL.
287
288bool
289ComplexNDArray::all_integers (double& max_val, double& min_val) const
290{
291 octave_idx_type nel = numel ();
292
293 if (nel > 0)
294 {
295 Complex val = elem (0);
296
297 double r_val = val.real ();
298 double i_val = val.imag ();
299
300 max_val = r_val;
301 min_val = r_val;
302
303 if (i_val > max_val)
304 max_val = i_val;
305
306 if (i_val < max_val)
307 min_val = i_val;
308 }
309 else
310 return false;
311
312 for (octave_idx_type i = 0; i < nel; i++)
313 {
314 Complex val = elem (i);
315
316 double r_val = val.real ();
317 double i_val = val.imag ();
318
319 if (r_val > max_val)
320 max_val = r_val;
321
322 if (i_val > max_val)
323 max_val = i_val;
324
325 if (r_val < min_val)
326 min_val = r_val;
327
328 if (i_val < min_val)
329 min_val = i_val;
330
331 if (octave::math::round (r_val) != r_val
332 || octave::math::round (i_val) != i_val)
333 return false;
334 }
335
336 return true;
337}
338
339bool
341{
342 return test_any (octave::too_large_for_float);
343}
344
346ComplexNDArray::all (int dim) const
347{
348 return do_mx_red_op<bool, Complex> (*this, dim, mx_inline_all);
349}
350
352ComplexNDArray::any (int dim) const
353{
354 return do_mx_red_op<bool, Complex> (*this, dim, mx_inline_any);
355}
356
358ComplexNDArray::flip (int dim) const
359{
360 return do_mx_flip_op<Complex, Complex> (*this, dim, mx_inline_flip);
361}
362
364ComplexNDArray::cumprod (int dim, bool nanflag) const
365{
366 return do_mx_cum_op<Complex, Complex> (*this, dim, nanflag, mx_inline_cumprod);
367}
368
370ComplexNDArray::cumsum (int dim, bool nanflag) const
371{
372 return do_mx_cum_op<Complex, Complex> (*this, dim, nanflag, mx_inline_cumsum);
373}
374
376ComplexNDArray::prod (int dim, bool nanflag) const
377{
378 return do_mx_red_op<Complex, Complex> (*this, dim, nanflag, mx_inline_prod);
379}
380
382ComplexNDArray::sum (int dim, bool nanflag) const
383{
384 return do_mx_red_op<Complex, Complex> (*this, dim, nanflag, mx_inline_sum);
385}
386
388ComplexNDArray::xsum (int dim, bool nanflag) const
389{
390 return do_mx_red_op<Complex, Complex> (*this, dim, nanflag, mx_inline_xsum);
391}
392
394ComplexNDArray::sumsq (int dim, bool nanflag) const
395{
396 return do_mx_red_op<double, Complex> (*this, dim, nanflag, mx_inline_sumsq);
397}
398
401{
402 return do_mx_diff_op<Complex> (*this, dim, order, mx_inline_diff);
403}
404
408{
409 if (rb.numel () > 0)
410 insert (rb, ra_idx);
411 return *this;
412}
413
416{
417 ComplexNDArray tmp (rb);
418 if (rb.numel () > 0)
419 insert (tmp, ra_idx);
420 return *this;
421}
422
425{
426 ComplexNDArray retval (ra);
427 if (rb.numel () > 0)
428 retval.insert (rb, ra_idx);
429 return retval;
430}
431
432static const Complex Complex_NaN_result (octave::numeric_limits<double>::NaN (),
433 octave::numeric_limits<double>::NaN ());
434
436ComplexNDArray::max (int dim, bool nanflag, bool realabs) const
437{
438 return do_mx_minmax_op<Complex> (*this, dim, nanflag, realabs, mx_inline_cmax);
439}
440
443 int dim, bool nanflag, bool realabs) const
444{
445 return do_mx_minmax_op<Complex> (*this, idx_arg, dim, nanflag,
446 realabs, mx_inline_cmax);
447}
448
450ComplexNDArray::min (int dim, bool nanflag, bool realabs) const
451{
452 return do_mx_minmax_op<Complex> (*this, dim, nanflag, realabs, mx_inline_cmin);
453}
454
457 int dim, bool nanflag, bool realabs) const
458{
459 return do_mx_minmax_op<Complex> (*this, idx_arg, dim, nanflag,
460 realabs, mx_inline_cmin);
461}
462
464ComplexNDArray::cummax (int dim, bool nanflag, bool realabs) const
465{
466 return do_mx_cumminmax_op<Complex> (*this, dim, nanflag,
467 realabs, mx_inline_ccummax);
468}
469
472 int dim, bool nanflag, bool realabs) const
473{
474 return do_mx_cumminmax_op<Complex> (*this, idx_arg, dim, nanflag,
475 realabs, mx_inline_ccummax);
476}
477
479ComplexNDArray::cummin (int dim, bool nanflag, bool realabs) const
480{
481 return do_mx_cumminmax_op<Complex> (*this, dim, nanflag,
482 realabs, mx_inline_ccummin);
483}
484
487 int dim, bool nanflag, bool realabs) const
488{
489 return do_mx_cumminmax_op<Complex> (*this, idx_arg, dim, nanflag,
490 realabs, mx_inline_ccummin);
491}
492
495{
496 return do_mx_unary_map<double, Complex, std::abs> (*this);
497}
498
501{
502 return do_mx_unary_map<bool, Complex, octave::math::isnan> (*this);
503}
504
507{
508 return do_mx_unary_map<bool, Complex, octave::math::isinf> (*this);
509}
510
513{
514 return do_mx_unary_map<bool, Complex, octave::math::isfinite> (*this);
515}
516
519{
520 return do_mx_unary_map<Complex, Complex, std::conj<double>> (a);
521}
522
525{
526 const dim_vector& a_dv = a.dims ();
527 const dim_vector& dv = dims ();
528
529 int n = a_dv.ndims ();
530
531 if (n != dv.ndims ())
532 (*current_liboctave_error_handler)
533 ("Array<T>::insert: invalid indexing operation");
534
535 Array<octave_idx_type> a_ra_idx (dim_vector (a_dv.ndims (), 1), 0);
536
537 a_ra_idx.elem (0) = r;
538 a_ra_idx.elem (1) = c;
539
540 for (int i = 0; i < n; i++)
541 {
542 if (a_ra_idx(i) < 0 || (a_ra_idx(i) + a_dv(i)) > dv(i))
543 (*current_liboctave_error_handler)
544 ("Array<T>::insert: range error for insert");
545 }
546
547 a_ra_idx.elem (0) = 0;
548 a_ra_idx.elem (1) = 0;
549
550 octave_idx_type n_elt = a.numel ();
551
552 // IS make_unique () NECESSARY HERE?
553
554 for (octave_idx_type i = 0; i < n_elt; i++)
555 {
557
558 ra_idx.elem (0) = a_ra_idx(0) + r;
559 ra_idx.elem (1) = a_ra_idx(1) + c;
560
561 elem (ra_idx) = a.elem (a_ra_idx);
562
563 increment_index (a_ra_idx, a_dv);
564 }
565
566 return *this;
567}
568
572{
573 Array<Complex>::insert (a, r, c);
574 return *this;
575}
576
580{
582 return *this;
583}
584
585void
587 const dim_vector& dimensions,
588 int start_dimension)
589{
590 ::increment_index (ra_idx, dimensions, start_dimension);
591}
592
595 const dim_vector& dimensions)
596{
597 return ::compute_index (ra_idx, dimensions);
598}
599
605
611
612// This contains no information on the array structure !!!
613std::ostream&
614operator << (std::ostream& os, const ComplexNDArray& a)
615{
616 octave_idx_type nel = a.numel ();
617
618 for (octave_idx_type i = 0; i < nel; i++)
619 {
620 os << ' ';
621 octave::write_value<Complex> (os, a.elem (i));
622 os << "\n";
623 }
624 return os;
625}
626
627std::istream&
628operator >> (std::istream& is, ComplexNDArray& a)
629{
630 octave_idx_type nel = a.numel ();
631
632 if (nel > 0)
633 {
634 Complex tmp;
635 for (octave_idx_type i = 0; i < nel; i++)
636 {
637 tmp = octave::read_value<Complex> (is);
638 if (is)
639 a.elem (i) = tmp;
640 else
641 return is;
642 }
643 }
644
645 return is;
646}
647
649
652
655
658
659ComplexNDArray& operator *= (ComplexNDArray& a, double s)
660{
661 if (a.is_shared ())
662 a = a * s;
663 else
664 do_ms_inplace_op<Complex, double> (a, s, mx_inline_mul2);
665 return a;
666}
667
670{
671 if (a.is_shared ())
672 return a = a / s;
673 else
674 do_ms_inplace_op<Complex, double> (a, s, mx_inline_div2);
675 return a;
676}
677
680
ComplexNDArray conj(const ComplexNDArray &a)
Definition CNDArray.cc:518
ComplexNDArray & operator/=(ComplexNDArray &a, double s)
Definition CNDArray.cc:669
std::istream & operator>>(std::istream &is, ComplexNDArray &a)
Definition CNDArray.cc:628
std::ostream & operator<<(std::ostream &os, const ComplexNDArray &a)
Definition CNDArray.cc:614
ComplexNDArray concat(NDArray &ra, ComplexNDArray &rb, const Array< octave_idx_type > &ra_idx)
Definition CNDArray.cc:424
#define BSXFUN_STDREL_DEFS_MXLOOP(ARRAY)
#define BSXFUN_STDOP_DEFS_MXLOOP(ARRAY)
#define BSXFUN_OP_DEF_MXLOOP(OP, ARRAY, LOOP)
N Dimensional Array with copy-on-write semantics.
Definition Array-base.h:130
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Definition Array-base.h:529
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition Array-base.h:547
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition Array-base.h:585
bool test_any(F fcn) const
Simpler calls.
Definition Array-base.h:947
Array< T, Alloc > & insert(const Array< T, Alloc > &a, const Array< octave_idx_type > &idx)
Insert an array into another at a specified position.
const T * data() const
Size of the specified dimension.
Definition Array-base.h:687
bool is_shared() const
Size of the specified dimension.
Definition Array-base.h:698
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-base.h:440
ComplexNDArray fourier(int dim=1) const
Definition CNDArray.cc:58
boolNDArray any(int dim=-1) const
Definition CNDArray.cc:352
bool any_element_is_inf_or_nan() const
Definition CNDArray.cc:271
ComplexNDArray xsum(int dim=-1, bool nanflag=false) const
Definition CNDArray.cc:388
NDArray abs() const
Definition CNDArray.cc:494
ComplexNDArray max(int dim=-1, bool nanflag=true, bool realabs=false) const
Definition CNDArray.cc:436
ComplexNDArray ifourier2d() const
Definition CNDArray.cc:140
static void increment_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions, int start_dimension=0)
Definition CNDArray.cc:586
static octave_idx_type compute_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions)
Definition CNDArray.cc:594
ComplexNDArray cumprod(int dim=-1, bool nanflag=false) const
Definition CNDArray.cc:364
ComplexNDArray min(int dim=-1, bool nanflag=true, bool realabs=false) const
Definition CNDArray.cc:450
ComplexNDArray concat(const ComplexNDArray &rb, const Array< octave_idx_type > &ra_idx)
Definition CNDArray.cc:406
ComplexNDArray cummax(int dim=-1, bool nanflag=true, bool realabs=false) const
Definition CNDArray.cc:464
ComplexNDArray diag(octave_idx_type k=0) const
Definition CNDArray.cc:601
ComplexNDArray & insert(const NDArray &a, octave_idx_type r, octave_idx_type c)
Definition CNDArray.cc:524
ComplexNDArray ifourier(int dim=1) const
Definition CNDArray.cc:89
boolNDArray isinf() const
Definition CNDArray.cc:506
ComplexNDArray sumsq(int dim=-1, bool nanflag=false) const
Definition CNDArray.cc:394
ComplexNDArray diff(octave_idx_type order=1, int dim=-1) const
Definition CNDArray.cc:400
ComplexNDArray cummin(int dim=-1, bool nanflag=true, bool realabs=false) const
Definition CNDArray.cc:479
bool any_element_is_nan() const
Definition CNDArray.cc:265
ComplexNDArray flip(int dim=-1) const
Definition CNDArray.cc:358
bool all_elements_are_real() const
Definition CNDArray.cc:279
ComplexNDArray fourier2d() const
Definition CNDArray.cc:120
boolNDArray operator!() const
Definition CNDArray.cc:254
bool all_integers(double &max_val, double &min_val) const
Definition CNDArray.cc:289
boolNDArray all(int dim=-1) const
Definition CNDArray.cc:346
ComplexNDArray cumsum(int dim=-1, bool nanflag=false) const
Definition CNDArray.cc:370
boolNDArray isnan() const
Definition CNDArray.cc:500
ComplexNDArray ifourierNd() const
Definition CNDArray.cc:175
ComplexNDArray sum(int dim=-1, bool nanflag=false) const
Definition CNDArray.cc:382
ComplexNDArray fourierNd() const
Definition CNDArray.cc:160
ComplexNDArray prod(int dim=-1, bool nanflag=false) const
Definition CNDArray.cc:376
bool too_large_for_float() const
Definition CNDArray.cc:340
boolNDArray isfinite() const
Definition CNDArray.cc:512
Template for N-dimensional array classes with like-type math operators.
Definition MArray.h:61
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:92
octave_idx_type ndims() const
Number of dimensions.
Definition dim-vector.h:263
bool mx_inline_any(const T *v, octave_idx_type n)
void mx_inline_div2(std::size_t n, R *r, const X *x)
void mx_inline_ccummax(const std::complex< T > *v, std::complex< T > *r, octave_idx_type n, const bool nanflag, const bool realabs)
bool mx_inline_all_real(std::size_t n, const std::complex< T > *x)
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_not(std::size_t n, bool *r, const X *x)
void mx_inline_cmax(const std::complex< T > *v, std::complex< T > *r, octave_idx_type n, const bool nanflag, const bool realabs)
void mx_inline_flip(const T *v, T *r, octave_idx_type n)
void mx_inline_mul2(std::size_t n, R *r, const X *x)
void mx_inline_cmin(const std::complex< T > *v, std::complex< T > *r, octave_idx_type n, const bool nanflag, const bool realabs)
bool mx_inline_all(const T *v, octave_idx_type n)
T mx_inline_sumsq(const T *v, octave_idx_type n)
T mx_inline_sum(const T *v, octave_idx_type n)
void mx_inline_ccummin(const std::complex< T > *v, std::complex< T > *r, octave_idx_type n, const bool nanflag, const bool realabs)
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)
T mx_inline_xsum(const T *v, octave_idx_type n, bool nanflag)
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:697
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