GNU Octave 10.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-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 <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 "lo-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 : (howmany > stride ? stride : howmany));
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 : (howmany > stride ? stride : howmany));
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::x_nint (r_val) != r_val
332 || octave::math::x_nint (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
359{
360 return do_mx_cum_op<Complex, Complex> (*this, dim, mx_inline_cumprod);
361}
362
365{
366 return do_mx_cum_op<Complex, Complex> (*this, dim, mx_inline_cumsum);
367}
368
370ComplexNDArray::prod (int dim) const
371{
372 return do_mx_red_op<Complex, Complex> (*this, dim, mx_inline_prod);
373}
374
376ComplexNDArray::sum (int dim) const
377{
378 return do_mx_red_op<Complex, Complex> (*this, dim, mx_inline_sum);
379}
380
382ComplexNDArray::xsum (int dim) const
383{
384 return do_mx_red_op<Complex, Complex> (*this, dim, mx_inline_xsum);
385}
386
389{
390 return do_mx_red_op<double, Complex> (*this, dim, mx_inline_sumsq);
391}
392
395{
396 return do_mx_diff_op<Complex> (*this, dim, order, mx_inline_diff);
397}
398
402{
403 if (rb.numel () > 0)
404 insert (rb, ra_idx);
405 return *this;
406}
407
410{
411 ComplexNDArray tmp (rb);
412 if (rb.numel () > 0)
413 insert (tmp, ra_idx);
414 return *this;
415}
416
419{
420 ComplexNDArray retval (ra);
421 if (rb.numel () > 0)
422 retval.insert (rb, ra_idx);
423 return retval;
424}
425
426static const Complex Complex_NaN_result (octave::numeric_limits<double>::NaN (),
427 octave::numeric_limits<double>::NaN ());
428
430ComplexNDArray::max (int dim) const
431{
432 return do_mx_minmax_op<Complex> (*this, dim, mx_inline_max);
433}
434
437{
438 return do_mx_minmax_op<Complex> (*this, idx_arg, dim, mx_inline_max);
439}
440
442ComplexNDArray::min (int dim) const
443{
444 return do_mx_minmax_op<Complex> (*this, dim, mx_inline_min);
445}
446
449{
450 return do_mx_minmax_op<Complex> (*this, idx_arg, dim, mx_inline_min);
451}
452
455{
456 return do_mx_cumminmax_op<Complex> (*this, dim, mx_inline_cummax);
457}
458
461{
462 return do_mx_cumminmax_op<Complex> (*this, idx_arg, dim, mx_inline_cummax);
463}
464
467{
468 return do_mx_cumminmax_op<Complex> (*this, dim, mx_inline_cummin);
469}
470
473{
474 return do_mx_cumminmax_op<Complex> (*this, idx_arg, dim, mx_inline_cummin);
475}
476
479{
480 return do_mx_unary_map<double, Complex, std::abs> (*this);
481}
482
485{
486 return do_mx_unary_map<bool, Complex, octave::math::isnan> (*this);
487}
488
491{
492 return do_mx_unary_map<bool, Complex, octave::math::isinf> (*this);
493}
494
497{
498 return do_mx_unary_map<bool, Complex, octave::math::isfinite> (*this);
499}
500
503{
504 return do_mx_unary_map<Complex, Complex, std::conj<double>> (a);
505}
506
509{
510 const dim_vector& a_dv = a.dims ();
511 const dim_vector& dv = dims ();
512
513 int n = a_dv.ndims ();
514
515 if (n != dv.ndims ())
516 (*current_liboctave_error_handler)
517 ("Array<T>::insert: invalid indexing operation");
518
519 Array<octave_idx_type> a_ra_idx (dim_vector (a_dv.ndims (), 1), 0);
520
521 a_ra_idx.elem (0) = r;
522 a_ra_idx.elem (1) = c;
523
524 for (int i = 0; i < n; i++)
525 {
526 if (a_ra_idx(i) < 0 || (a_ra_idx(i) + a_dv(i)) > dv(i))
527 (*current_liboctave_error_handler)
528 ("Array<T>::insert: range error for insert");
529 }
530
531 a_ra_idx.elem (0) = 0;
532 a_ra_idx.elem (1) = 0;
533
534 octave_idx_type n_elt = a.numel ();
535
536 // IS make_unique () NECESSARY HERE?
537
538 for (octave_idx_type i = 0; i < n_elt; i++)
539 {
541
542 ra_idx.elem (0) = a_ra_idx(0) + r;
543 ra_idx.elem (1) = a_ra_idx(1) + c;
544
545 elem (ra_idx) = a.elem (a_ra_idx);
546
547 increment_index (a_ra_idx, a_dv);
548 }
549
550 return *this;
551}
552
556{
557 Array<Complex>::insert (a, r, c);
558 return *this;
559}
560
564{
566 return *this;
567}
568
569void
571 const dim_vector& dimensions,
572 int start_dimension)
573{
574 ::increment_index (ra_idx, dimensions, start_dimension);
575}
576
579 const dim_vector& dimensions)
580{
581 return ::compute_index (ra_idx, dimensions);
582}
583
589
595
596// This contains no information on the array structure !!!
597std::ostream&
598operator << (std::ostream& os, const ComplexNDArray& a)
599{
600 octave_idx_type nel = a.numel ();
601
602 for (octave_idx_type i = 0; i < nel; i++)
603 {
604 os << ' ';
605 octave::write_value<Complex> (os, a.elem (i));
606 os << "\n";
607 }
608 return os;
609}
610
611std::istream&
612operator >> (std::istream& is, ComplexNDArray& a)
613{
614 octave_idx_type nel = a.numel ();
615
616 if (nel > 0)
617 {
618 Complex tmp;
619 for (octave_idx_type i = 0; i < nel; i++)
620 {
621 tmp = octave::read_value<Complex> (is);
622 if (is)
623 a.elem (i) = tmp;
624 else
625 return is;
626 }
627 }
628
629 return is;
630}
631
633
636
639
642
643ComplexNDArray& operator *= (ComplexNDArray& a, double s)
644{
645 if (a.is_shared ())
646 a = a * s;
647 else
648 do_ms_inplace_op<Complex, double> (a, s, mx_inline_mul2);
649 return a;
650}
651
654{
655 if (a.is_shared ())
656 return a = a / s;
657 else
658 do_ms_inplace_op<Complex, double> (a, s, mx_inline_div2);
659 return a;
660}
661
664
ComplexNDArray conj(const ComplexNDArray &a)
Definition CNDArray.cc:502
ComplexNDArray & operator/=(ComplexNDArray &a, double s)
Definition CNDArray.cc:653
std::istream & operator>>(std::istream &is, ComplexNDArray &a)
Definition CNDArray.cc:612
std::ostream & operator<<(std::ostream &os, const ComplexNDArray &a)
Definition CNDArray.cc:598
ComplexNDArray concat(NDArray &ra, ComplexNDArray &rb, const Array< octave_idx_type > &ra_idx)
Definition CNDArray.cc:418
#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.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
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
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.h:665
bool is_shared() const
Size of the specified dimension.
Definition Array.h:676
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 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 prod(int dim=-1) const
Definition CNDArray.cc:370
NDArray abs() const
Definition CNDArray.cc:478
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:570
static octave_idx_type compute_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions)
Definition CNDArray.cc:578
ComplexNDArray cummax(int dim=-1) const
Definition CNDArray.cc:454
ComplexNDArray sumsq(int dim=-1) const
Definition CNDArray.cc:388
ComplexNDArray concat(const ComplexNDArray &rb, const Array< octave_idx_type > &ra_idx)
Definition CNDArray.cc:400
ComplexNDArray diag(octave_idx_type k=0) const
Definition CNDArray.cc:585
ComplexNDArray cumsum(int dim=-1) const
Definition CNDArray.cc:364
ComplexNDArray min(int dim=-1) const
Definition CNDArray.cc:442
ComplexNDArray & insert(const NDArray &a, octave_idx_type r, octave_idx_type c)
Definition CNDArray.cc:508
ComplexNDArray ifourier(int dim=1) const
Definition CNDArray.cc:89
boolNDArray isinf() const
Definition CNDArray.cc:490
ComplexNDArray diff(octave_idx_type order=1, int dim=-1) const
Definition CNDArray.cc:394
bool any_element_is_nan() const
Definition CNDArray.cc:265
ComplexNDArray max(int dim=-1) const
Definition CNDArray.cc:430
bool all_elements_are_real() const
Definition CNDArray.cc:279
ComplexNDArray xsum(int dim=-1) const
Definition CNDArray.cc:382
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
ComplexNDArray cumprod(int dim=-1) const
Definition CNDArray.cc:358
boolNDArray all(int dim=-1) const
Definition CNDArray.cc:346
ComplexNDArray cummin(int dim=-1) const
Definition CNDArray.cc:466
boolNDArray isnan() const
Definition CNDArray.cc:484
ComplexNDArray sum(int dim=-1) const
Definition CNDArray.cc:376
ComplexNDArray ifourierNd() const
Definition CNDArray.cc:175
ComplexNDArray fourierNd() const
Definition CNDArray.cc:160
bool too_large_for_float() const
Definition CNDArray.cc:340
boolNDArray isfinite() const
Definition CNDArray.cc:496
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:90
octave_idx_type ndims() const
Number of dimensions.
Definition dim-vector.h:253
bool mx_inline_any(const T *v, octave_idx_type n)
void mx_inline_div2(std::size_t n, R *r, const X *x)
T mx_inline_xsum(const T *v, octave_idx_type n)
void mx_inline_cummin(const T *v, T *r, octave_idx_type n)
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_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)
void mx_inline_mul2(std::size_t n, R *r, const X *x)
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_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)
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