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
CNDArray.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 "CNDArray.h"
35 #include "f77-fcn.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<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 
58 ComplexNDArray::fourier (int dim) const
59 {
60  dim_vector dv = dims ();
61 
62  if (dim > dv.length () || 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 (fortran_vec ());
77  ComplexNDArray retval (dv);
78  Complex *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 
89 ComplexNDArray::ifourier (int dim) const
90 {
91  dim_vector dv = dims ();
92 
93  if (dim > dv.length () || 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 (fortran_vec ());
108  ComplexNDArray retval (dv);
109  Complex *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 ComplexNDArray ();
125 
126  dim_vector dv2(dv(0), dv(1));
127  const Complex *in = fortran_vec ();
128  ComplexNDArray retval (dv);
129  Complex *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 ComplexNDArray ();
145 
146  dim_vector dv2(dv(0), dv(1));
147  const Complex *in = fortran_vec ();
148  ComplexNDArray retval (dv);
149  Complex *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 Complex *in (fortran_vec ());
166  ComplexNDArray retval (dv);
167  Complex *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 Complex *in (fortran_vec ());
181  ComplexNDArray retval (dv);
182  Complex *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  // Note that the original complex fft routines were not written for
194  // double complex arguments. They have been modified by adding an
195  // implicit double precision (a-h,o-z) statement at the beginning of
196  // each subroutine.
197 
198  F77_RET_T
199  F77_FUNC (zffti, ZFFTI) (const octave_idx_type&, Complex*);
200 
201  F77_RET_T
202  F77_FUNC (zfftf, ZFFTF) (const octave_idx_type&, Complex*, Complex*);
203 
204  F77_RET_T
205  F77_FUNC (zfftb, ZFFTB) (const octave_idx_type&, Complex*, Complex*);
206 }
207 
209 ComplexNDArray::fourier (int dim) const
210 {
211  dim_vector dv = dims ();
212 
213  if (dim > dv.length () || dim < 0)
214  return ComplexNDArray ();
215 
216  ComplexNDArray retval (dv);
217  octave_idx_type npts = dv(dim);
218  octave_idx_type nn = 4*npts+15;
219  Array<Complex> wsave (dim_vector (nn, 1));
220  Complex *pwsave = wsave.fortran_vec ();
221 
222  OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
223 
224  octave_idx_type stride = 1;
225 
226  for (int i = 0; i < dim; i++)
227  stride *= dv(i);
228 
229  octave_idx_type howmany = numel () / npts;
230  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
231  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
232  octave_idx_type dist = (stride == 1 ? npts : 1);
233 
234  F77_FUNC (zffti, ZFFTI) (npts, pwsave);
235 
236  for (octave_idx_type k = 0; k < nloop; k++)
237  {
238  for (octave_idx_type j = 0; j < howmany; j++)
239  {
240  octave_quit ();
241 
242  for (octave_idx_type i = 0; i < npts; i++)
243  tmp[i] = elem ((i + k*npts)*stride + j*dist);
244 
245  F77_FUNC (zfftf, ZFFTF) (npts, tmp, pwsave);
246 
247  for (octave_idx_type i = 0; i < npts; i++)
248  retval((i + k*npts)*stride + j*dist) = tmp[i];
249  }
250  }
251 
252  return retval;
253 }
254 
256 ComplexNDArray::ifourier (int dim) const
257 {
258  dim_vector dv = dims ();
259 
260  if (dim > dv.length () || dim < 0)
261  return ComplexNDArray ();
262 
263  ComplexNDArray retval (dv);
264  octave_idx_type npts = dv(dim);
265  octave_idx_type nn = 4*npts+15;
266  Array<Complex> wsave (dim_vector (nn, 1));
267  Complex *pwsave = wsave.fortran_vec ();
268 
269  OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
270 
271  octave_idx_type stride = 1;
272 
273  for (int i = 0; i < dim; i++)
274  stride *= dv(i);
275 
276  octave_idx_type howmany = numel () / npts;
277  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
278  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
279  octave_idx_type dist = (stride == 1 ? npts : 1);
280 
281  F77_FUNC (zffti, ZFFTI) (npts, pwsave);
282 
283  for (octave_idx_type k = 0; k < nloop; k++)
284  {
285  for (octave_idx_type j = 0; j < howmany; j++)
286  {
287  octave_quit ();
288 
289  for (octave_idx_type i = 0; i < npts; i++)
290  tmp[i] = elem ((i + k*npts)*stride + j*dist);
291 
292  F77_FUNC (zfftb, ZFFTB) (npts, tmp, pwsave);
293 
294  for (octave_idx_type i = 0; i < npts; i++)
295  retval((i + k*npts)*stride + j*dist) = tmp[i] /
296  static_cast<double> (npts);
297  }
298  }
299 
300  return retval;
301 }
302 
304 ComplexNDArray::fourier2d (void) const
305 {
306  dim_vector dv = dims ();
307  dim_vector dv2 (dv(0), dv(1));
308  int rank = 2;
309  ComplexNDArray retval (*this);
310  octave_idx_type stride = 1;
311 
312  for (int i = 0; i < rank; i++)
313  {
314  octave_idx_type npts = dv2(i);
315  octave_idx_type nn = 4*npts+15;
316  Array<Complex> wsave (dim_vector (nn, 1));
317  Complex *pwsave = wsave.fortran_vec ();
318  Array<Complex> row (dim_vector (npts, 1));
319  Complex *prow = row.fortran_vec ();
320 
321  octave_idx_type howmany = numel () / npts;
322  howmany = (stride == 1 ? howmany :
323  (howmany > stride ? stride : howmany));
324  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
325  octave_idx_type dist = (stride == 1 ? npts : 1);
326 
327  F77_FUNC (zffti, ZFFTI) (npts, pwsave);
328 
329  for (octave_idx_type k = 0; k < nloop; k++)
330  {
331  for (octave_idx_type j = 0; j < howmany; j++)
332  {
333  octave_quit ();
334 
335  for (octave_idx_type l = 0; l < npts; l++)
336  prow[l] = retval((l + k*npts)*stride + j*dist);
337 
338  F77_FUNC (zfftf, ZFFTF) (npts, prow, pwsave);
339 
340  for (octave_idx_type l = 0; l < npts; l++)
341  retval((l + k*npts)*stride + j*dist) = prow[l];
342  }
343  }
344 
345  stride *= dv2(i);
346  }
347 
348  return retval;
349 }
350 
352 ComplexNDArray::ifourier2d (void) const
353 {
354  dim_vector dv = dims ();
355  dim_vector dv2 (dv(0), dv(1));
356  int rank = 2;
357  ComplexNDArray retval (*this);
358  octave_idx_type stride = 1;
359 
360  for (int i = 0; i < rank; i++)
361  {
362  octave_idx_type npts = dv2(i);
363  octave_idx_type nn = 4*npts+15;
364  Array<Complex> wsave (dim_vector (nn, 1));
365  Complex *pwsave = wsave.fortran_vec ();
366  Array<Complex> row (dim_vector (npts, 1));
367  Complex *prow = row.fortran_vec ();
368 
369  octave_idx_type howmany = numel () / npts;
370  howmany = (stride == 1 ? howmany :
371  (howmany > stride ? stride : howmany));
372  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
373  octave_idx_type dist = (stride == 1 ? npts : 1);
374 
375  F77_FUNC (zffti, ZFFTI) (npts, pwsave);
376 
377  for (octave_idx_type k = 0; k < nloop; k++)
378  {
379  for (octave_idx_type j = 0; j < howmany; j++)
380  {
381  octave_quit ();
382 
383  for (octave_idx_type l = 0; l < npts; l++)
384  prow[l] = retval((l + k*npts)*stride + j*dist);
385 
386  F77_FUNC (zfftb, ZFFTB) (npts, prow, pwsave);
387 
388  for (octave_idx_type l = 0; l < npts; l++)
389  retval((l + k*npts)*stride + j*dist) =
390  prow[l] / static_cast<double> (npts);
391  }
392  }
393 
394  stride *= dv2(i);
395  }
396 
397  return retval;
398 }
399 
401 ComplexNDArray::fourierNd (void) const
402 {
403  dim_vector dv = dims ();
404  int rank = dv.length ();
405  ComplexNDArray retval (*this);
406  octave_idx_type stride = 1;
407 
408  for (int i = 0; i < rank; i++)
409  {
410  octave_idx_type npts = dv(i);
411  octave_idx_type nn = 4*npts+15;
412  Array<Complex> wsave (dim_vector (nn, 1));
413  Complex *pwsave = wsave.fortran_vec ();
414  Array<Complex> row (dim_vector (npts, 1));
415  Complex *prow = row.fortran_vec ();
416 
417  octave_idx_type howmany = numel () / npts;
418  howmany = (stride == 1 ? howmany :
419  (howmany > stride ? stride : howmany));
420  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
421  octave_idx_type dist = (stride == 1 ? npts : 1);
422 
423  F77_FUNC (zffti, ZFFTI) (npts, pwsave);
424 
425  for (octave_idx_type k = 0; k < nloop; k++)
426  {
427  for (octave_idx_type j = 0; j < howmany; j++)
428  {
429  octave_quit ();
430 
431  for (octave_idx_type l = 0; l < npts; l++)
432  prow[l] = retval((l + k*npts)*stride + j*dist);
433 
434  F77_FUNC (zfftf, ZFFTF) (npts, prow, pwsave);
435 
436  for (octave_idx_type l = 0; l < npts; l++)
437  retval((l + k*npts)*stride + j*dist) = prow[l];
438  }
439  }
440 
441  stride *= dv(i);
442  }
443 
444  return retval;
445 }
446 
448 ComplexNDArray::ifourierNd (void) const
449 {
450  dim_vector dv = dims ();
451  int rank = dv.length ();
452  ComplexNDArray retval (*this);
453  octave_idx_type stride = 1;
454 
455  for (int i = 0; i < rank; i++)
456  {
457  octave_idx_type npts = dv(i);
458  octave_idx_type nn = 4*npts+15;
459  Array<Complex> wsave (dim_vector (nn, 1));
460  Complex *pwsave = wsave.fortran_vec ();
461  Array<Complex> row (dim_vector (npts, 1));
462  Complex *prow = row.fortran_vec ();
463 
464  octave_idx_type howmany = numel () / npts;
465  howmany = (stride == 1 ? howmany :
466  (howmany > stride ? stride : howmany));
467  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
468  octave_idx_type dist = (stride == 1 ? npts : 1);
469 
470  F77_FUNC (zffti, ZFFTI) (npts, pwsave);
471 
472  for (octave_idx_type k = 0; k < nloop; k++)
473  {
474  for (octave_idx_type j = 0; j < howmany; j++)
475  {
476  octave_quit ();
477 
478  for (octave_idx_type l = 0; l < npts; l++)
479  prow[l] = retval((l + k*npts)*stride + j*dist);
480 
481  F77_FUNC (zfftb, ZFFTB) (npts, prow, pwsave);
482 
483  for (octave_idx_type l = 0; l < npts; l++)
484  retval((l + k*npts)*stride + j*dist) =
485  prow[l] / static_cast<double> (npts);
486  }
487  }
488 
489  stride *= dv(i);
490  }
491 
492  return retval;
493 }
494 
495 #endif
496 
497 // unary operations
498 
501 {
502  if (any_element_is_nan ())
504 
505  return do_mx_unary_op<bool, Complex> (*this, mx_inline_not);
506 }
507 
508 // FIXME: this is not quite the right thing.
509 
510 bool
512 {
513  return do_mx_check<Complex> (*this, mx_inline_any_nan);
514 }
515 
516 bool
518 {
519  return ! do_mx_check<Complex> (*this, mx_inline_all_finite);
520 }
521 
522 // Return true if no elements have imaginary components.
523 
524 bool
526 {
527  return do_mx_check<Complex> (*this, mx_inline_all_real);
528 }
529 
530 // Return nonzero if any element of CM has a non-integer real or
531 // imaginary part. Also extract the largest and smallest (real or
532 // imaginary) values and return them in MAX_VAL and MIN_VAL.
533 
534 bool
535 ComplexNDArray::all_integers (double& max_val, double& min_val) const
536 {
537  octave_idx_type nel = nelem ();
538 
539  if (nel > 0)
540  {
541  Complex val = elem (0);
542 
543  double r_val = std::real (val);
544  double i_val = std::imag (val);
545 
546  max_val = r_val;
547  min_val = r_val;
548 
549  if (i_val > max_val)
550  max_val = i_val;
551 
552  if (i_val < max_val)
553  min_val = i_val;
554  }
555  else
556  return false;
557 
558  for (octave_idx_type i = 0; i < nel; i++)
559  {
560  Complex val = elem (i);
561 
562  double r_val = std::real (val);
563  double i_val = std::imag (val);
564 
565  if (r_val > max_val)
566  max_val = r_val;
567 
568  if (i_val > max_val)
569  max_val = i_val;
570 
571  if (r_val < min_val)
572  min_val = r_val;
573 
574  if (i_val < min_val)
575  min_val = i_val;
576 
577  if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val)
578  return false;
579  }
580 
581  return true;
582 }
583 
584 bool
586 {
588 }
589 
591 ComplexNDArray::all (int dim) const
592 {
593  return do_mx_red_op<bool, Complex> (*this, dim, mx_inline_all);
594 }
595 
597 ComplexNDArray::any (int dim) const
598 {
599  return do_mx_red_op<bool, Complex> (*this, dim, mx_inline_any);
600 }
601 
603 ComplexNDArray::cumprod (int dim) const
604 {
605  return do_mx_cum_op<Complex, Complex> (*this, dim, mx_inline_cumprod);
606 }
607 
609 ComplexNDArray::cumsum (int dim) const
610 {
611  return do_mx_cum_op<Complex, Complex> (*this, dim, mx_inline_cumsum);
612 }
613 
615 ComplexNDArray::prod (int dim) const
616 {
617  return do_mx_red_op<Complex, Complex> (*this, dim, mx_inline_prod);
618 }
619 
621 ComplexNDArray::sum (int dim) const
622 {
623  return do_mx_red_op<Complex, Complex> (*this, dim, mx_inline_sum);
624 }
625 
627 ComplexNDArray::xsum (int dim) const
628 {
629  return do_mx_red_op<Complex, Complex> (*this, dim, mx_inline_xsum);
630 }
631 
633 ComplexNDArray::sumsq (int dim) const
634 {
635  return do_mx_red_op<double, Complex> (*this, dim, mx_inline_sumsq);
636 }
637 
639 ComplexNDArray::diff (octave_idx_type order, int dim) const
640 {
641  return do_mx_diff_op<Complex> (*this, dim, order, mx_inline_diff);
642 }
643 
646  const Array<octave_idx_type>& ra_idx)
647 {
648  if (rb.numel () > 0)
649  insert (rb, ra_idx);
650  return *this;
651 }
652 
655 {
656  ComplexNDArray tmp (rb);
657  if (rb.numel () > 0)
658  insert (tmp, ra_idx);
659  return *this;
660 }
661 
664 {
665  ComplexNDArray retval (ra);
666  if (rb.numel () > 0)
667  retval.insert (rb, ra_idx);
668  return retval;
669 }
670 
672 
674 ComplexNDArray::max (int dim) const
675 {
676  return do_mx_minmax_op<Complex> (*this, dim, mx_inline_max);
677 }
678 
681 {
682  return do_mx_minmax_op<Complex> (*this, idx_arg, dim, mx_inline_max);
683 }
684 
686 ComplexNDArray::min (int dim) const
687 {
688  return do_mx_minmax_op<Complex> (*this, dim, mx_inline_min);
689 }
690 
693 {
694  return do_mx_minmax_op<Complex> (*this, idx_arg, dim, mx_inline_min);
695 }
696 
698 ComplexNDArray::cummax (int dim) const
699 {
700  return do_mx_cumminmax_op<Complex> (*this, dim, mx_inline_cummax);
701 }
702 
705 {
706  return do_mx_cumminmax_op<Complex> (*this, idx_arg, dim, mx_inline_cummax);
707 }
708 
710 ComplexNDArray::cummin (int dim) const
711 {
712  return do_mx_cumminmax_op<Complex> (*this, dim, mx_inline_cummin);
713 }
714 
717 {
718  return do_mx_cumminmax_op<Complex> (*this, idx_arg, dim, mx_inline_cummin);
719 }
720 
721 NDArray
723 {
724  return do_mx_unary_map<double, Complex, std::abs> (*this);
725 }
726 
729 {
730  return do_mx_unary_map<bool, Complex, xisnan> (*this);
731 }
732 
735 {
736  return do_mx_unary_map<bool, Complex, xisinf> (*this);
737 }
738 
741 {
742  return do_mx_unary_map<bool, Complex, xfinite> (*this);
743 }
744 
747 {
748  return do_mx_unary_map<Complex, Complex, std::conj<double> > (a);
749 }
750 
753 {
754  dim_vector a_dv = a.dims ();
755 
756  int n = a_dv.length ();
757 
758  if (n == dimensions.length ())
759  {
760  Array<octave_idx_type> a_ra_idx (dim_vector (a_dv.length (), 1), 0);
761 
762  a_ra_idx.elem (0) = r;
763  a_ra_idx.elem (1) = c;
764 
765  for (int i = 0; i < n; i++)
766  {
767  if (a_ra_idx (i) < 0 || (a_ra_idx (i) + a_dv (i)) > dimensions (i))
768  {
769  (*current_liboctave_error_handler)
770  ("Array<T>::insert: range error for insert");
771  return *this;
772  }
773  }
774 
775  a_ra_idx.elem (0) = 0;
776  a_ra_idx.elem (1) = 0;
777 
778  octave_idx_type n_elt = a.numel ();
779 
780  // IS make_unique () NECCESSARY HERE??
781 
782  for (octave_idx_type i = 0; i < n_elt; i++)
783  {
784  Array<octave_idx_type> ra_idx = a_ra_idx;
785 
786  ra_idx.elem (0) = a_ra_idx (0) + r;
787  ra_idx.elem (1) = a_ra_idx (1) + c;
788 
789  elem (ra_idx) = a.elem (a_ra_idx);
790 
791  increment_index (a_ra_idx, a_dv);
792  }
793  }
794  else
796  ("Array<T>::insert: invalid indexing operation");
797 
798  return *this;
799 }
800 
804 {
805  Array<Complex>::insert (a, r, c);
806  return *this;
807 }
808 
811  const Array<octave_idx_type>& ra_idx)
812 {
813  Array<Complex>::insert (a, ra_idx);
814  return *this;
815 }
816 
819 {
820  ComplexMatrix retval;
821 
822  if (ndims () == 2)
823  retval = ComplexMatrix (Array<Complex> (*this));
824  else
826  ("invalid conversion of ComplexNDArray to ComplexMatrix");
827 
828  return retval;
829 }
830 
831 void
833  const dim_vector& dimensions,
834  int start_dimension)
835 {
836  ::increment_index (ra_idx, dimensions, start_dimension);
837 }
838 
841  const dim_vector& dimensions)
842 {
843  return ::compute_index (ra_idx, dimensions);
844 }
845 
848 {
849  return MArray<Complex>::diag (k);
850 }
851 
854 {
855  return MArray<Complex>::diag (m, n);
856 }
857 
858 // This contains no information on the array structure !!!
859 std::ostream&
860 operator << (std::ostream& os, const ComplexNDArray& a)
861 {
862  octave_idx_type nel = a.nelem ();
863 
864  for (octave_idx_type i = 0; i < nel; i++)
865  {
866  os << " ";
867  octave_write_complex (os, a.elem (i));
868  os << "\n";
869  }
870  return os;
871 }
872 
873 std::istream&
874 operator >> (std::istream& is, ComplexNDArray& a)
875 {
876  octave_idx_type nel = a.nelem ();
877 
878  if (nel > 0)
879  {
880  Complex tmp;
881  for (octave_idx_type i = 0; i < nel; i++)
882  {
883  tmp = octave_read_value<Complex> (is);
884  if (is)
885  a.elem (i) = tmp;
886  else
887  goto done;
888  }
889  }
890 
891 done:
892 
893  return is;
894 }
895 
897 
899 NDS_BOOL_OPS (ComplexNDArray, Complex)
900 
901 SND_CMP_OPS (Complex, ComplexNDArray)
902 SND_BOOL_OPS (Complex, ComplexNDArray)
903 
904 NDND_CMP_OPS (ComplexNDArray, ComplexNDArray)
905 NDND_BOOL_OPS (ComplexNDArray, ComplexNDArray)
906 
907 ComplexNDArray& operator *= (ComplexNDArray& a, double s)
908 {
909  if (a.is_shared ())
910  a = a * s;
911  else
912  do_ms_inplace_op<Complex, double> (a, s, mx_inline_mul2);
913  return a;
914 }
915 
917 {
918  if (a.is_shared ())
919  return a = a / s;
920  else
921  do_ms_inplace_op<Complex, double> (a, s, mx_inline_div2);
922  return a;
923 }
924 
927