GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
fCNDArray.cc
Go to the documentation of this file.
1 // N-D Array manipulations.
2 /*
3 
4 Copyright (C) 1996-2013 John W. Eaton
5 Copyright (C) 2009 VZLU Prague, a.s.
6 
7 This file is part of Octave.
8 
9 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <cfloat>
30 
31 #include <vector>
32 
33 #include "Array-util.h"
34 #include "f77-fcn.h"
35 #include "fCNDArray.h"
36 #include "functor.h"
37 #include "lo-ieee.h"
38 #include "lo-mappers.h"
39 #include "MArray-defs.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 
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  dim_vector dv = dims ();
61 
62  if (dim > dv.length () || 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 (fortran_vec ());
77  FloatComplexNDArray retval (dv);
78  FloatComplex *out (retval.fortran_vec ());
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  dim_vector dv = dims ();
92 
93  if (dim > dv.length () || 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 (fortran_vec ());
108  FloatComplexNDArray retval (dv);
109  FloatComplex *out (retval.fortran_vec ());
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  dim_vector dv = dims ();
123  if (dv.length () < 2)
124  return FloatComplexNDArray ();
125 
126  dim_vector dv2(dv(0), dv(1));
127  const FloatComplex *in = fortran_vec ();
128  FloatComplexNDArray retval (dv);
129  FloatComplex *out = retval.fortran_vec ();
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  dim_vector dv = dims ();
143  if (dv.length () < 2)
144  return FloatComplexNDArray ();
145 
146  dim_vector dv2(dv(0), dv(1));
147  const FloatComplex *in = fortran_vec ();
148  FloatComplexNDArray retval (dv);
149  FloatComplex *out = retval.fortran_vec ();
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  dim_vector dv = dims ();
163  int rank = dv.length ();
164 
165  const FloatComplex *in (fortran_vec ());
166  FloatComplexNDArray retval (dv);
167  FloatComplex *out (retval.fortran_vec ());
168 
169  octave_fftw::fftNd (in, out, rank, dv);
170 
171  return retval;
172 }
173 
176 {
177  dim_vector dv = dims ();
178  int rank = dv.length ();
179 
180  const FloatComplex *in (fortran_vec ());
181  FloatComplexNDArray retval (dv);
182  FloatComplex *out (retval.fortran_vec ());
183 
184  octave_fftw::ifftNd (in, out, rank, dv);
185 
186  return retval;
187 }
188 
189 #else
190 
191 extern "C"
192 {
193  F77_RET_T
194  F77_FUNC (cffti, CFFTI) (const octave_idx_type&, FloatComplex*);
195 
196  F77_RET_T
197  F77_FUNC (cfftf, CFFTF) (const octave_idx_type&, FloatComplex*,
198  FloatComplex*);
199 
200  F77_RET_T
201  F77_FUNC (cfftb, CFFTB) (const octave_idx_type&, FloatComplex*,
202  FloatComplex*);
203 }
204 
206 FloatComplexNDArray::fourier (int dim) const
207 {
208  dim_vector dv = dims ();
209 
210  if (dim > dv.length () || dim < 0)
211  return FloatComplexNDArray ();
212 
213  FloatComplexNDArray retval (dv);
214  octave_idx_type npts = dv(dim);
215  octave_idx_type nn = 4*npts+15;
216  Array<FloatComplex> wsave (nn, 1);
217  FloatComplex *pwsave = wsave.fortran_vec ();
218 
219  OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
220 
221  octave_idx_type stride = 1;
222 
223  for (int i = 0; i < dim; i++)
224  stride *= dv(i);
225 
226  octave_idx_type howmany = numel () / npts;
227  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
228  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
229  octave_idx_type dist = (stride == 1 ? npts : 1);
230 
231  F77_FUNC (cffti, CFFTI) (npts, pwsave);
232 
233  for (octave_idx_type k = 0; k < nloop; k++)
234  {
235  for (octave_idx_type j = 0; j < howmany; j++)
236  {
237  octave_quit ();
238 
239  for (octave_idx_type i = 0; i < npts; i++)
240  tmp[i] = elem ((i + k*npts)*stride + j*dist);
241 
242  F77_FUNC (cfftf, CFFTF) (npts, tmp, pwsave);
243 
244  for (octave_idx_type i = 0; i < npts; i++)
245  retval((i + k*npts)*stride + j*dist) = tmp[i];
246  }
247  }
248 
249  return retval;
250 }
251 
253 FloatComplexNDArray::ifourier (int dim) const
254 {
255  dim_vector dv = dims ();
256 
257  if (dim > dv.length () || dim < 0)
258  return FloatComplexNDArray ();
259 
260  FloatComplexNDArray retval (dv);
261  octave_idx_type npts = dv(dim);
262  octave_idx_type nn = 4*npts+15;
263  Array<FloatComplex> wsave (nn, 1);
264  FloatComplex *pwsave = wsave.fortran_vec ();
265 
266  OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
267 
268  octave_idx_type stride = 1;
269 
270  for (int i = 0; i < dim; i++)
271  stride *= dv(i);
272 
273  octave_idx_type howmany = numel () / npts;
274  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
275  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
276  octave_idx_type dist = (stride == 1 ? npts : 1);
277 
278  F77_FUNC (cffti, CFFTI) (npts, pwsave);
279 
280  for (octave_idx_type k = 0; k < nloop; k++)
281  {
282  for (octave_idx_type j = 0; j < howmany; j++)
283  {
284  octave_quit ();
285 
286  for (octave_idx_type i = 0; i < npts; i++)
287  tmp[i] = elem ((i + k*npts)*stride + j*dist);
288 
289  F77_FUNC (cfftb, CFFTB) (npts, tmp, pwsave);
290 
291  for (octave_idx_type i = 0; i < npts; i++)
292  retval((i + k*npts)*stride + j*dist) = tmp[i] /
293  static_cast<float> (npts);
294  }
295  }
296 
297  return retval;
298 }
299 
302 {
303  dim_vector dv = dims ();
304  dim_vector dv2 (dv(0), dv(1));
305  int rank = 2;
306  FloatComplexNDArray retval (*this);
307  octave_idx_type stride = 1;
308 
309  for (int i = 0; i < rank; i++)
310  {
311  octave_idx_type npts = dv2(i);
312  octave_idx_type nn = 4*npts+15;
313  Array<FloatComplex> wsave (nn, 1);
314  FloatComplex *pwsave = wsave.fortran_vec ();
315  Array<FloatComplex> row (npts, 1);
316  FloatComplex *prow = row.fortran_vec ();
317 
318  octave_idx_type howmany = numel () / npts;
319  howmany = (stride == 1 ? howmany :
320  (howmany > stride ? stride : howmany));
321  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
322  octave_idx_type dist = (stride == 1 ? npts : 1);
323 
324  F77_FUNC (cffti, CFFTI) (npts, pwsave);
325 
326  for (octave_idx_type k = 0; k < nloop; k++)
327  {
328  for (octave_idx_type j = 0; j < howmany; j++)
329  {
330  octave_quit ();
331 
332  for (octave_idx_type l = 0; l < npts; l++)
333  prow[l] = retval((l + k*npts)*stride + j*dist);
334 
335  F77_FUNC (cfftf, CFFTF) (npts, prow, pwsave);
336 
337  for (octave_idx_type l = 0; l < npts; l++)
338  retval((l + k*npts)*stride + j*dist) = prow[l];
339  }
340  }
341 
342  stride *= dv2(i);
343  }
344 
345  return retval;
346 }
347 
350 {
351  dim_vector dv = dims ();
352  dim_vector dv2 (dv(0), dv(1));
353  int rank = 2;
354  FloatComplexNDArray retval (*this);
355  octave_idx_type stride = 1;
356 
357  for (int i = 0; i < rank; i++)
358  {
359  octave_idx_type npts = dv2(i);
360  octave_idx_type nn = 4*npts+15;
361  Array<FloatComplex> wsave (nn, 1);
362  FloatComplex *pwsave = wsave.fortran_vec ();
363  Array<FloatComplex> row (npts, 1);
364  FloatComplex *prow = row.fortran_vec ();
365 
366  octave_idx_type howmany = numel () / npts;
367  howmany = (stride == 1 ? howmany :
368  (howmany > stride ? stride : howmany));
369  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
370  octave_idx_type dist = (stride == 1 ? npts : 1);
371 
372  F77_FUNC (cffti, CFFTI) (npts, pwsave);
373 
374  for (octave_idx_type k = 0; k < nloop; k++)
375  {
376  for (octave_idx_type j = 0; j < howmany; j++)
377  {
378  octave_quit ();
379 
380  for (octave_idx_type l = 0; l < npts; l++)
381  prow[l] = retval((l + k*npts)*stride + j*dist);
382 
383  F77_FUNC (cfftb, CFFTB) (npts, prow, pwsave);
384 
385  for (octave_idx_type l = 0; l < npts; l++)
386  retval((l + k*npts)*stride + j*dist) =
387  prow[l] / static_cast<float> (npts);
388  }
389  }
390 
391  stride *= dv2(i);
392  }
393 
394  return retval;
395 }
396 
399 {
400  dim_vector dv = dims ();
401  int rank = dv.length ();
402  FloatComplexNDArray retval (*this);
403  octave_idx_type stride = 1;
404 
405  for (int i = 0; i < rank; i++)
406  {
407  octave_idx_type npts = dv(i);
408  octave_idx_type nn = 4*npts+15;
409  Array<FloatComplex> wsave (nn, 1);
410  FloatComplex *pwsave = wsave.fortran_vec ();
411  Array<FloatComplex> row (npts, 1);
412  FloatComplex *prow = row.fortran_vec ();
413 
414  octave_idx_type howmany = numel () / npts;
415  howmany = (stride == 1 ? howmany :
416  (howmany > stride ? stride : howmany));
417  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
418  octave_idx_type dist = (stride == 1 ? npts : 1);
419 
420  F77_FUNC (cffti, CFFTI) (npts, pwsave);
421 
422  for (octave_idx_type k = 0; k < nloop; k++)
423  {
424  for (octave_idx_type j = 0; j < howmany; j++)
425  {
426  octave_quit ();
427 
428  for (octave_idx_type l = 0; l < npts; l++)
429  prow[l] = retval((l + k*npts)*stride + j*dist);
430 
431  F77_FUNC (cfftf, CFFTF) (npts, prow, pwsave);
432 
433  for (octave_idx_type l = 0; l < npts; l++)
434  retval((l + k*npts)*stride + j*dist) = prow[l];
435  }
436  }
437 
438  stride *= dv(i);
439  }
440 
441  return retval;
442 }
443 
446 {
447  dim_vector dv = dims ();
448  int rank = dv.length ();
449  FloatComplexNDArray retval (*this);
450  octave_idx_type stride = 1;
451 
452  for (int i = 0; i < rank; i++)
453  {
454  octave_idx_type npts = dv(i);
455  octave_idx_type nn = 4*npts+15;
456  Array<FloatComplex> wsave (nn, 1);
457  FloatComplex *pwsave = wsave.fortran_vec ();
458  Array<FloatComplex> row (npts, 1);
459  FloatComplex *prow = row.fortran_vec ();
460 
461  octave_idx_type howmany = numel () / npts;
462  howmany = (stride == 1 ? howmany :
463  (howmany > stride ? stride : howmany));
464  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
465  octave_idx_type dist = (stride == 1 ? npts : 1);
466 
467  F77_FUNC (cffti, CFFTI) (npts, pwsave);
468 
469  for (octave_idx_type k = 0; k < nloop; k++)
470  {
471  for (octave_idx_type j = 0; j < howmany; j++)
472  {
473  octave_quit ();
474 
475  for (octave_idx_type l = 0; l < npts; l++)
476  prow[l] = retval((l + k*npts)*stride + j*dist);
477 
478  F77_FUNC (cfftb, CFFTB) (npts, prow, pwsave);
479 
480  for (octave_idx_type l = 0; l < npts; l++)
481  retval((l + k*npts)*stride + j*dist) =
482  prow[l] / static_cast<float> (npts);
483  }
484  }
485 
486  stride *= dv(i);
487  }
488 
489  return retval;
490 }
491 
492 #endif
493 
494 // unary operations
495 
498 {
499  if (any_element_is_nan ())
501 
502  return do_mx_unary_op<bool, FloatComplex> (*this, mx_inline_not);
503 }
504 
505 // FIXME: this is not quite the right thing.
506 
507 bool
509 {
510  return do_mx_check<FloatComplex> (*this, mx_inline_any_nan);
511 }
512 
513 bool
515 {
516  return ! do_mx_check<FloatComplex> (*this, mx_inline_all_finite);
517 }
518 
519 // Return true if no elements have imaginary components.
520 
521 bool
523 {
524  return do_mx_check<FloatComplex> (*this, mx_inline_all_real);
525 }
526 
527 // Return nonzero if any element of CM has a non-integer real or
528 // imaginary part. Also extract the largest and smallest (real or
529 // imaginary) values and return them in MAX_VAL and MIN_VAL.
530 
531 bool
532 FloatComplexNDArray::all_integers (float& max_val, float& min_val) const
533 {
534  octave_idx_type nel = nelem ();
535 
536  if (nel > 0)
537  {
538  FloatComplex val = elem (0);
539 
540  float r_val = std::real (val);
541  float i_val = std::imag (val);
542 
543  max_val = r_val;
544  min_val = r_val;
545 
546  if (i_val > max_val)
547  max_val = i_val;
548 
549  if (i_val < max_val)
550  min_val = i_val;
551  }
552  else
553  return false;
554 
555  for (octave_idx_type i = 0; i < nel; i++)
556  {
557  FloatComplex val = elem (i);
558 
559  float r_val = std::real (val);
560  float i_val = std::imag (val);
561 
562  if (r_val > max_val)
563  max_val = r_val;
564 
565  if (i_val > max_val)
566  max_val = i_val;
567 
568  if (r_val < min_val)
569  min_val = r_val;
570 
571  if (i_val < min_val)
572  min_val = i_val;
573 
574  if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val)
575  return false;
576  }
577 
578  return true;
579 }
580 
581 bool
583 {
584  return false;
585 }
586 
589 {
590  return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_all);
591 }
592 
595 {
596  return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_any);
597 }
598 
601 {
602  return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim,
604 }
605 
608 {
609  return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim,
611 }
612 
615 {
616  return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_prod);
617 }
618 
621 {
622  return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_sum);
623 }
624 
627 {
628  return do_mx_red_op<Complex, FloatComplex> (*this, dim, mx_inline_dsum);
629 }
630 
633 {
634  return do_mx_red_op<float, FloatComplex> (*this, dim, mx_inline_sumsq);
635 }
636 
639 {
640  return do_mx_diff_op<FloatComplex> (*this, dim, order, mx_inline_diff);
641 }
642 
645  const Array<octave_idx_type>& ra_idx)
646 {
647  if (rb.numel () > 0)
648  insert (rb, ra_idx);
649  return *this;
650 }
651 
654  const Array<octave_idx_type>& ra_idx)
655 {
656  FloatComplexNDArray tmp (rb);
657  if (rb.numel () > 0)
658  insert (tmp, ra_idx);
659  return *this;
660 }
661 
664  const Array<octave_idx_type>& ra_idx)
665 {
666  FloatComplexNDArray retval (ra);
667  if (rb.numel () > 0)
668  retval.insert (rb, ra_idx);
669  return retval;
670 }
671 
674 
677 {
678  return do_mx_minmax_op<FloatComplex> (*this, dim, mx_inline_max);
679 }
680 
683 {
684  return do_mx_minmax_op<FloatComplex> (*this, idx_arg, dim, mx_inline_max);
685 }
686 
689 {
690  return do_mx_minmax_op<FloatComplex> (*this, dim, mx_inline_min);
691 }
692 
695 {
696  return do_mx_minmax_op<FloatComplex> (*this, idx_arg, dim, mx_inline_min);
697 }
698 
701 {
702  return do_mx_cumminmax_op<FloatComplex> (*this, dim, mx_inline_cummax);
703 }
704 
707 {
708  return do_mx_cumminmax_op<FloatComplex> (*this, idx_arg, dim,
710 }
711 
714 {
715  return do_mx_cumminmax_op<FloatComplex> (*this, dim, mx_inline_cummin);
716 }
717 
720 {
721  return do_mx_cumminmax_op<FloatComplex> (*this, idx_arg, dim,
723 }
724 
727 {
728  return do_mx_unary_map<float, FloatComplex, std::abs> (*this);
729 }
730 
733 {
734  return do_mx_unary_map<bool, FloatComplex, xisnan> (*this);
735 }
736 
739 {
740  return do_mx_unary_map<bool, FloatComplex, xisinf> (*this);
741 }
742 
745 {
746  return do_mx_unary_map<bool, FloatComplex, xfinite> (*this);
747 }
748 
751 {
752  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float> > (a);
753 }
754 
758 {
759  dim_vector a_dv = a.dims ();
760 
761  int n = a_dv.length ();
762 
763  if (n == dimensions.length ())
764  {
765  Array<octave_idx_type> a_ra_idx (dim_vector (a_dv.length (), 1), 0);
766 
767  a_ra_idx.elem (0) = r;
768  a_ra_idx.elem (1) = c;
769 
770  for (int i = 0; i < n; i++)
771  {
772  if (a_ra_idx (i) < 0 || (a_ra_idx (i) + a_dv (i)) > dimensions (i))
773  {
774  (*current_liboctave_error_handler)
775  ("Array<T>::insert: range error for insert");
776  return *this;
777  }
778  }
779 
780  a_ra_idx.elem (0) = 0;
781  a_ra_idx.elem (1) = 0;
782 
783  octave_idx_type n_elt = a.numel ();
784 
785  // IS make_unique () NECCESSARY HERE??
786 
787  for (octave_idx_type i = 0; i < n_elt; i++)
788  {
789  Array<octave_idx_type> ra_idx = a_ra_idx;
790 
791  ra_idx.elem (0) = a_ra_idx (0) + r;
792  ra_idx.elem (1) = a_ra_idx (1) + c;
793 
794  elem (ra_idx) = a.elem (a_ra_idx);
795 
796  increment_index (a_ra_idx, a_dv);
797  }
798  }
799  else
801  ("Array<T>::insert: invalid indexing operation");
802 
803  return *this;
804 }
805 
809 {
810  Array<FloatComplex>::insert (a, r, c);
811  return *this;
812 }
813 
816  const Array<octave_idx_type>& ra_idx)
817 {
818  Array<FloatComplex>::insert (a, ra_idx);
819  return *this;
820 }
821 
824 {
825  FloatComplexMatrix retval;
826 
827  if (ndims () == 2)
828  retval = FloatComplexMatrix (Array<FloatComplex> (*this));
829  else
831  ("invalid conversion of FloatComplexNDArray to FloatComplexMatrix");
832 
833  return retval;
834 }
835 
836 void
838  const dim_vector& dimensions,
839  int start_dimension)
840 {
841  ::increment_index (ra_idx, dimensions, start_dimension);
842 }
843 
846  const dim_vector& dimensions)
847 {
848  return ::compute_index (ra_idx, dimensions);
849 }
850 
853 {
854  return MArray<FloatComplex>::diag (k);
855 }
856 
859 {
860  return MArray<FloatComplex>::diag (m, n);
861 }
862 
863 // This contains no information on the array structure !!!
864 std::ostream&
865 operator << (std::ostream& os, const FloatComplexNDArray& a)
866 {
867  octave_idx_type nel = a.nelem ();
868 
869  for (octave_idx_type i = 0; i < nel; i++)
870  {
871  os << " ";
872  octave_write_complex (os, a.elem (i));
873  os << "\n";
874  }
875  return os;
876 }
877 
878 std::istream&
879 operator >> (std::istream& is, FloatComplexNDArray& a)
880 {
881  octave_idx_type nel = a.nelem ();
882 
883  if (nel > 0)
884  {
885  FloatComplex tmp;
886  for (octave_idx_type i = 0; i < nel; i++)
887  {
888  tmp = octave_read_value<FloatComplex> (is);
889  if (is)
890  a.elem (i) = tmp;
891  else
892  goto done;
893  }
894  }
895 
896 done:
897 
898  return is;
899 }
900 
902 
904 NDS_BOOL_OPS (FloatComplexNDArray, FloatComplex)
905 
906 SND_CMP_OPS (FloatComplex, FloatComplexNDArray)
907 SND_BOOL_OPS (FloatComplex, FloatComplexNDArray)
908 
909 NDND_CMP_OPS (FloatComplexNDArray, FloatComplexNDArray)
910 NDND_BOOL_OPS (FloatComplexNDArray, FloatComplexNDArray)
911 
912 FloatComplexNDArray& operator *= (FloatComplexNDArray& a, float s)
913 {
914  if (a.is_shared ())
915  a = a * s;
916  else
917  do_ms_inplace_op<FloatComplex, float> (a, s, mx_inline_mul2);
918  return a;
919 }
920 
922 {
923  if (a.is_shared ())
924  a = a / s;
925  else
926  do_ms_inplace_op<FloatComplex, float> (a, s, mx_inline_div2);
927  return a;
928 }
929 
932