GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
fCNDArray.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 "f77-fcn.h"
36#include "fCNDArray.h"
37#include "lo-ieee.h"
38#include "lo-mappers.h"
39#include "mx-base.h"
40#include "mx-op-defs.h"
41#include "mx-fcnda-fs.h"
42#include "oct-fftw.h"
43#include "oct-locbuf.h"
44
45#include "bsxfun-defs.cc"
46
48 : MArray<FloatComplex> (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 FloatComplexNDArray ();
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 FloatComplex *in (data ());
77 FloatComplexNDArray retval (dv);
78 FloatComplex *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 FloatComplexNDArray ();
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 FloatComplex *in (data ());
108 FloatComplexNDArray retval (dv);
109 FloatComplex *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 FloatComplexNDArray ();
125
126 dim_vector dv2 (dv(0), dv(1));
127 const FloatComplex *in = data ();
128 FloatComplexNDArray retval (dv);
129 FloatComplex *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 FloatComplexNDArray ();
145
146 dim_vector dv2 (dv(0), dv(1));
147 const FloatComplex *in = data ();
148 FloatComplexNDArray retval (dv);
149 FloatComplex *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 FloatComplex *in (data ());
166 FloatComplexNDArray retval (dv);
167 FloatComplex *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 FloatComplex *in (data ());
181 FloatComplexNDArray retval (dv);
182 FloatComplex *out (retval.rwdata ());
183
184 octave::fftw::ifftNd (in, out, rank, dv);
185
186 return retval;
187}
188
189#else
190
192FloatComplexNDArray::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 FloatComplexNDArray ();
200}
201
203FloatComplexNDArray::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 FloatComplexNDArray ();
211}
212
215{
216 (*current_liboctave_error_handler)
217 ("support for FFTW was unavailable or disabled when liboctave was built");
218
219 return FloatComplexNDArray ();
220}
221
224{
225 (*current_liboctave_error_handler)
226 ("support for FFTW was unavailable or disabled when liboctave was built");
227
228 return FloatComplexNDArray ();
229}
230
233{
234 (*current_liboctave_error_handler)
235 ("support for FFTW was unavailable or disabled when liboctave was built");
236
237 return FloatComplexNDArray ();
238}
239
242{
243 (*current_liboctave_error_handler)
244 ("support for FFTW was unavailable or disabled when liboctave was built");
245
246 return FloatComplexNDArray ();
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, FloatComplex> (*this, mx_inline_not);
260}
261
262// FIXME: this is not quite the right thing.
263
264bool
266{
267 return do_mx_check<FloatComplex> (*this, mx_inline_any_nan);
268}
269
270bool
272{
273 return ! do_mx_check<FloatComplex> (*this, mx_inline_all_finite);
274}
275
276// Return true if no elements have imaginary components.
277
278bool
280{
281 return do_mx_check<FloatComplex> (*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
289FloatComplexNDArray::all_integers (float& max_val, float& min_val) const
290{
291 octave_idx_type nel = numel ();
292
293 if (nel > 0)
294 {
295 FloatComplex val = elem (0);
296
297 float r_val = val.real ();
298 float 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 FloatComplex val = elem (i);
315
316 float r_val = val.real ();
317 float 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 false;
343}
344
347{
348 return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_all);
349}
350
353{
354 return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_any);
355}
356
359{
360 return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim,
362}
363
366{
367 return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim,
369}
370
373{
374 return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_prod);
375}
376
379{
380 return do_mx_red_op<Complex, FloatComplex> (*this, dim, mx_inline_dprod);
381}
382
385{
386 return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_sum);
387}
388
391{
392 return do_mx_red_op<Complex, FloatComplex> (*this, dim, mx_inline_dsum);
393}
394
397{
398 return do_mx_red_op<float, FloatComplex> (*this, dim, mx_inline_sumsq);
399}
400
403{
404 return do_mx_diff_op<FloatComplex> (*this, dim, order, mx_inline_diff);
405}
406
410{
411 if (rb.numel () > 0)
412 insert (rb, ra_idx);
413 return *this;
414}
415
419{
420 FloatComplexNDArray tmp (rb);
421 if (rb.numel () > 0)
422 insert (tmp, ra_idx);
423 return *this;
424}
425
429{
430 FloatComplexNDArray retval (ra);
431 if (rb.numel () > 0)
432 retval.insert (rb, ra_idx);
433 return retval;
434}
435
436static const FloatComplex FloatComplex_NaN_result (octave::numeric_limits<float>::NaN (),
437 octave::numeric_limits<float>::NaN ());
438
441{
442 return do_mx_minmax_op<FloatComplex> (*this, dim, mx_inline_max);
443}
444
447{
448 return do_mx_minmax_op<FloatComplex> (*this, idx_arg, dim, mx_inline_max);
449}
450
453{
454 return do_mx_minmax_op<FloatComplex> (*this, dim, mx_inline_min);
455}
456
459{
460 return do_mx_minmax_op<FloatComplex> (*this, idx_arg, dim, mx_inline_min);
461}
462
465{
466 return do_mx_cumminmax_op<FloatComplex> (*this, dim, mx_inline_cummax);
467}
468
471{
472 return do_mx_cumminmax_op<FloatComplex> (*this, idx_arg, dim,
474}
475
478{
479 return do_mx_cumminmax_op<FloatComplex> (*this, dim, mx_inline_cummin);
480}
481
484{
485 return do_mx_cumminmax_op<FloatComplex> (*this, idx_arg, dim,
487}
488
491{
492 return do_mx_unary_map<float, FloatComplex, std::abs> (*this);
493}
494
497{
498 return do_mx_unary_map<bool, FloatComplex, octave::math::isnan> (*this);
499}
500
503{
504 return do_mx_unary_map<bool, FloatComplex, octave::math::isinf> (*this);
505}
506
509{
510 return do_mx_unary_map<bool, FloatComplex, octave::math::isfinite> (*this);
511}
512
515{
516 return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float>> (a);
517}
518
522{
523 const dim_vector& a_dv = a.dims ();
524 const dim_vector& dv = dims ();
525
526 int n = a_dv.ndims ();
527
528 if (n == dv.ndims ())
529 {
530 Array<octave_idx_type> a_ra_idx (dim_vector (a_dv.ndims (), 1), 0);
531
532 a_ra_idx.elem (0) = r;
533 a_ra_idx.elem (1) = c;
534
535 for (int i = 0; i < n; i++)
536 {
537 if (a_ra_idx(i) < 0 || (a_ra_idx(i) + a_dv(i)) > dv(i))
538 (*current_liboctave_error_handler)
539 ("Array<T>::insert: range error for insert");
540 }
541
542 a_ra_idx.elem (0) = 0;
543 a_ra_idx.elem (1) = 0;
544
545 octave_idx_type n_elt = a.numel ();
546
547 // IS make_unique () NECESSARY HERE?
548
549 for (octave_idx_type i = 0; i < n_elt; i++)
550 {
552
553 ra_idx.elem (0) = a_ra_idx(0) + r;
554 ra_idx.elem (1) = a_ra_idx(1) + c;
555
556 elem (ra_idx) = a.elem (a_ra_idx);
557
558 increment_index (a_ra_idx, a_dv);
559 }
560 }
561 else
563 ("Array<T>::insert: invalid indexing operation");
564
565 return *this;
566}
567
575
583
584void
586 const dim_vector& dimensions,
587 int start_dimension)
588{
589 ::increment_index (ra_idx, dimensions, start_dimension);
590}
591
594 const dim_vector& dimensions)
595{
596 return ::compute_index (ra_idx, dimensions);
597}
598
604
610
611// This contains no information on the array structure !!!
612std::ostream&
613operator << (std::ostream& os, const FloatComplexNDArray& a)
614{
615 octave_idx_type nel = a.numel ();
616
617 for (octave_idx_type i = 0; i < nel; i++)
618 {
619 os << ' ';
620 octave::write_value<Complex> (os, a.elem (i));
621 os << "\n";
622 }
623 return os;
624}
625
626std::istream&
628{
629 octave_idx_type nel = a.numel ();
630
631 if (nel > 0)
632 {
633 FloatComplex tmp;
634 for (octave_idx_type i = 0; i < nel; i++)
635 {
636 tmp = octave::read_value<FloatComplex> (is);
637 if (is)
638 a.elem (i) = tmp;
639 else
640 return is;
641 }
642 }
643
644 return is;
645}
646
648
651
654
657
658FloatComplexNDArray& operator *= (FloatComplexNDArray& a, float s)
659{
660 if (a.is_shared ())
661 a = a * s;
662 else
663 do_ms_inplace_op<FloatComplex, float> (a, s, mx_inline_mul2);
664 return a;
665}
666
669{
670 if (a.is_shared ())
671 a = a / s;
672 else
673 do_ms_inplace_op<FloatComplex, float> (a, s, mx_inline_div2);
674 return a;
675}
676
679
#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
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
bool any_element_is_inf_or_nan() const
Definition fCNDArray.cc:271
FloatComplexNDArray max(int dim=-1) const
Definition fCNDArray.cc:440
bool all_integers(float &max_val, float &min_val) const
Definition fCNDArray.cc:289
FloatComplexNDArray fourier2d() const
Definition fCNDArray.cc:120
FloatComplexNDArray ifourierNd() const
Definition fCNDArray.cc:175
FloatComplexNDArray sum(int dim=-1) const
Definition fCNDArray.cc:384
FloatComplexNDArray min(int dim=-1) const
Definition fCNDArray.cc:452
FloatComplexNDArray cumprod(int dim=-1) const
Definition fCNDArray.cc:358
FloatComplexNDArray cummin(int dim=-1) const
Definition fCNDArray.cc:477
FloatNDArray abs() const
Definition fCNDArray.cc:490
FloatComplexNDArray cummax(int dim=-1) const
Definition fCNDArray.cc:464
FloatComplexNDArray sumsq(int dim=-1) const
Definition fCNDArray.cc:396
bool too_large_for_float() const
Definition fCNDArray.cc:340
ComplexNDArray dsum(int dim=-1) const
Definition fCNDArray.cc:390
FloatComplexNDArray diff(octave_idx_type order=1, int dim=-1) const
Definition fCNDArray.cc:402
FloatComplexNDArray & insert(const NDArray &a, octave_idx_type r, octave_idx_type c)
Definition fCNDArray.cc:520
static void increment_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions, int start_dimension=0)
Definition fCNDArray.cc:585
bool any_element_is_nan() const
Definition fCNDArray.cc:265
FloatComplexNDArray prod(int dim=-1) const
Definition fCNDArray.cc:372
boolNDArray operator!() const
Definition fCNDArray.cc:254
FloatComplexNDArray ifourier(int dim=1) const
Definition fCNDArray.cc:89
boolNDArray isinf() const
Definition fCNDArray.cc:502
FloatComplexNDArray cumsum(int dim=-1) const
Definition fCNDArray.cc:365
boolNDArray all(int dim=-1) const
Definition fCNDArray.cc:346
FloatComplexNDArray concat(const FloatComplexNDArray &rb, const Array< octave_idx_type > &ra_idx)
Definition fCNDArray.cc:408
FloatComplexNDArray fourierNd() const
Definition fCNDArray.cc:160
boolNDArray any(int dim=-1) const
Definition fCNDArray.cc:352
static octave_idx_type compute_index(Array< octave_idx_type > &ra_idx, const dim_vector &dimensions)
Definition fCNDArray.cc:593
FloatComplexNDArray ifourier2d() const
Definition fCNDArray.cc:140
boolNDArray isnan() const
Definition fCNDArray.cc:496
FloatComplexNDArray diag(octave_idx_type k=0) const
Definition fCNDArray.cc:600
bool all_elements_are_real() const
Definition fCNDArray.cc:279
boolNDArray isfinite() const
Definition fCNDArray.cc:508
FloatComplexNDArray fourier(int dim=1) const
Definition fCNDArray.cc:58
ComplexNDArray dprod(int dim=-1) const
Definition fCNDArray.cc:378
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
std::ostream & operator<<(std::ostream &os, const FloatComplexNDArray &a)
Definition fCNDArray.cc:613
FloatComplexNDArray concat(NDArray &ra, FloatComplexNDArray &rb, const Array< octave_idx_type > &ra_idx)
Definition fCNDArray.cc:427
std::istream & operator>>(std::istream &is, FloatComplexNDArray &a)
Definition fCNDArray.cc:627
FloatComplexNDArray & operator/=(FloatComplexNDArray &a, float s)
Definition fCNDArray.cc:668
FloatComplexNDArray conj(const FloatComplexNDArray &a)
Definition fCNDArray.cc:514
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition lo-error.c:41
bool mx_inline_any(const T *v, octave_idx_type n)
void mx_inline_div2(std::size_t n, R *r, const X *x)
subst_template_param< std::complex, T, double >::type mx_inline_dprod(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)
subst_template_param< std::complex, T, double >::type mx_inline_dsum(const T *v, octave_idx_type n)
#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< float > FloatComplex
Definition oct-cmplx.h:34
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