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
fNDArray.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 "fNDArray.h"
36 #include "functor.h"
37 #include "lo-error.h"
38 #include "lo-ieee.h"
39 #include "lo-mappers.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<float> (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 FloatNDArray::fourier (int dim) const
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 float *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 
89 FloatNDArray::ifourier (int dim) const
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  FloatComplexNDArray retval (*this);
108  FloatComplex *out (retval.fortran_vec ());
109 
110  // Need to be careful here about the distance between fft's
111  for (octave_idx_type k = 0; k < nloop; k++)
112  octave_fftw::ifft (out + k * stride * n, out + k * stride * n,
113  n, howmany, stride, dist);
114 
115  return retval;
116 }
117 
120 {
121  dim_vector dv = dims ();
122  if (dv.length () < 2)
123  return FloatComplexNDArray ();
124 
125  dim_vector dv2(dv(0), dv(1));
126  const float *in = fortran_vec ();
127  FloatComplexNDArray retval (dv);
128  FloatComplex *out = retval.fortran_vec ();
129  octave_idx_type howmany = numel () / dv(0) / dv(1);
130  octave_idx_type dist = dv(0) * dv(1);
131 
132  for (octave_idx_type i=0; i < howmany; i++)
133  octave_fftw::fftNd (in + i*dist, out + i*dist, 2, dv2);
134 
135  return retval;
136 }
137 
140 {
141  dim_vector dv = dims ();
142  if (dv.length () < 2)
143  return FloatComplexNDArray ();
144 
145  dim_vector dv2(dv(0), dv(1));
146  FloatComplexNDArray retval (*this);
147  FloatComplex *out = retval.fortran_vec ();
148  octave_idx_type howmany = numel () / dv(0) / dv(1);
149  octave_idx_type dist = dv(0) * dv(1);
150 
151  for (octave_idx_type i=0; i < howmany; i++)
152  octave_fftw::ifftNd (out + i*dist, out + i*dist, 2, dv2);
153 
154  return retval;
155 }
156 
159 {
160  dim_vector dv = dims ();
161  int rank = dv.length ();
162 
163  const float *in (fortran_vec ());
164  FloatComplexNDArray retval (dv);
165  FloatComplex *out (retval.fortran_vec ());
166 
167  octave_fftw::fftNd (in, out, rank, dv);
168 
169  return retval;
170 }
171 
174 {
175  dim_vector dv = dims ();
176  int rank = dv.length ();
177 
178  FloatComplexNDArray tmp (*this);
179  FloatComplex *in (tmp.fortran_vec ());
180  FloatComplexNDArray retval (dv);
181  FloatComplex *out (retval.fortran_vec ());
182 
183  octave_fftw::ifftNd (in, out, rank, dv);
184 
185  return retval;
186 }
187 
188 #else
189 
190 extern "C"
191 {
192  // Note that the original complex fft routines were not written for
193  // float complex arguments. They have been modified by adding an
194  // implicit float precision (a-h,o-z) statement at the beginning of
195  // each subroutine.
196 
197  F77_RET_T
198  F77_FUNC (cffti, CFFTI) (const octave_idx_type&, FloatComplex*);
199 
200  F77_RET_T
201  F77_FUNC (cfftf, CFFTF) (const octave_idx_type&, FloatComplex*,
202  FloatComplex*);
203 
204  F77_RET_T
205  F77_FUNC (cfftb, CFFTB) (const octave_idx_type&, FloatComplex*,
206  FloatComplex*);
207 }
208 
210 FloatNDArray::fourier (int dim) const
211 {
212  dim_vector dv = dims ();
213 
214  if (dim > dv.length () || dim < 0)
215  return FloatComplexNDArray ();
216 
217  FloatComplexNDArray retval (dv);
218  octave_idx_type npts = dv(dim);
219  octave_idx_type nn = 4*npts+15;
220  Array<FloatComplex> wsave (nn);
221  FloatComplex *pwsave = wsave.fortran_vec ();
222 
223  OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
224 
225  octave_idx_type stride = 1;
226 
227  for (int i = 0; i < dim; i++)
228  stride *= dv(i);
229 
230  octave_idx_type howmany = numel () / npts;
231  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
232  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
233  octave_idx_type dist = (stride == 1 ? npts : 1);
234 
235  F77_FUNC (cffti, CFFTI) (npts, pwsave);
236 
237  for (octave_idx_type k = 0; k < nloop; k++)
238  {
239  for (octave_idx_type j = 0; j < howmany; j++)
240  {
241  octave_quit ();
242 
243  for (octave_idx_type i = 0; i < npts; i++)
244  tmp[i] = elem ((i + k*npts)*stride + j*dist);
245 
246  F77_FUNC (cfftf, CFFTF) (npts, tmp, pwsave);
247 
248  for (octave_idx_type i = 0; i < npts; i++)
249  retval((i + k*npts)*stride + j*dist) = tmp[i];
250  }
251  }
252 
253  return retval;
254 }
255 
257 FloatNDArray::ifourier (int dim) const
258 {
259  dim_vector dv = dims ();
260 
261  if (dim > dv.length () || dim < 0)
262  return FloatComplexNDArray ();
263 
264  FloatComplexNDArray retval (dv);
265  octave_idx_type npts = dv(dim);
266  octave_idx_type nn = 4*npts+15;
267  Array<FloatComplex> wsave (nn);
268  FloatComplex *pwsave = wsave.fortran_vec ();
269 
270  OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
271 
272  octave_idx_type stride = 1;
273 
274  for (int i = 0; i < dim; i++)
275  stride *= dv(i);
276 
277  octave_idx_type howmany = numel () / npts;
278  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
279  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
280  octave_idx_type dist = (stride == 1 ? npts : 1);
281 
282  F77_FUNC (cffti, CFFTI) (npts, pwsave);
283 
284  for (octave_idx_type k = 0; k < nloop; k++)
285  {
286  for (octave_idx_type j = 0; j < howmany; j++)
287  {
288  octave_quit ();
289 
290  for (octave_idx_type i = 0; i < npts; i++)
291  tmp[i] = elem ((i + k*npts)*stride + j*dist);
292 
293  F77_FUNC (cfftb, CFFTB) (npts, tmp, pwsave);
294 
295  for (octave_idx_type i = 0; i < npts; i++)
296  retval((i + k*npts)*stride + j*dist) = tmp[i] /
297  static_cast<float> (npts);
298  }
299  }
300 
301  return retval;
302 }
303 
305 FloatNDArray::fourier2d (void) const
306 {
307  dim_vector dv = dims ();
308  dim_vector dv2 (dv(0), dv(1));
309  int rank = 2;
310  FloatComplexNDArray retval (*this);
311  octave_idx_type stride = 1;
312 
313  for (int i = 0; i < rank; i++)
314  {
315  octave_idx_type npts = dv2(i);
316  octave_idx_type nn = 4*npts+15;
317  Array<FloatComplex> wsave (nn);
318  FloatComplex *pwsave = wsave.fortran_vec ();
319  Array<FloatComplex> row (npts);
320  FloatComplex *prow = row.fortran_vec ();
321 
322  octave_idx_type howmany = numel () / npts;
323  howmany = (stride == 1 ? howmany :
324  (howmany > stride ? stride : howmany));
325  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
326  octave_idx_type dist = (stride == 1 ? npts : 1);
327 
328  F77_FUNC (cffti, CFFTI) (npts, pwsave);
329 
330  for (octave_idx_type k = 0; k < nloop; k++)
331  {
332  for (octave_idx_type j = 0; j < howmany; j++)
333  {
334  octave_quit ();
335 
336  for (octave_idx_type l = 0; l < npts; l++)
337  prow[l] = retval((l + k*npts)*stride + j*dist);
338 
339  F77_FUNC (cfftf, CFFTF) (npts, prow, pwsave);
340 
341  for (octave_idx_type l = 0; l < npts; l++)
342  retval((l + k*npts)*stride + j*dist) = prow[l];
343  }
344  }
345 
346  stride *= dv2(i);
347  }
348 
349  return retval;
350 }
351 
353 FloatNDArray::ifourier2d (void) const
354 {
355  dim_vector dv = dims ();
356  dim_vector dv2 (dv(0), dv(1));
357  int rank = 2;
358  FloatComplexNDArray retval (*this);
359  octave_idx_type stride = 1;
360 
361  for (int i = 0; i < rank; i++)
362  {
363  octave_idx_type npts = dv2(i);
364  octave_idx_type nn = 4*npts+15;
365  Array<FloatComplex> wsave (nn);
366  FloatComplex *pwsave = wsave.fortran_vec ();
367  Array<FloatComplex> row (npts);
368  FloatComplex *prow = row.fortran_vec ();
369 
370  octave_idx_type howmany = numel () / npts;
371  howmany = (stride == 1 ? howmany :
372  (howmany > stride ? stride : howmany));
373  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
374  octave_idx_type dist = (stride == 1 ? npts : 1);
375 
376  F77_FUNC (cffti, CFFTI) (npts, pwsave);
377 
378  for (octave_idx_type k = 0; k < nloop; k++)
379  {
380  for (octave_idx_type j = 0; j < howmany; j++)
381  {
382  octave_quit ();
383 
384  for (octave_idx_type l = 0; l < npts; l++)
385  prow[l] = retval((l + k*npts)*stride + j*dist);
386 
387  F77_FUNC (cfftb, CFFTB) (npts, prow, pwsave);
388 
389  for (octave_idx_type l = 0; l < npts; l++)
390  retval((l + k*npts)*stride + j*dist) =
391  prow[l] / static_cast<float> (npts);
392  }
393  }
394 
395  stride *= dv2(i);
396  }
397 
398  return retval;
399 }
400 
402 FloatNDArray::fourierNd (void) const
403 {
404  dim_vector dv = dims ();
405  int rank = dv.length ();
406  FloatComplexNDArray retval (*this);
407  octave_idx_type stride = 1;
408 
409  for (int i = 0; i < rank; i++)
410  {
411  octave_idx_type npts = dv(i);
412  octave_idx_type nn = 4*npts+15;
413  Array<FloatComplex> wsave (nn);
414  FloatComplex *pwsave = wsave.fortran_vec ();
415  Array<FloatComplex> row (npts);
416  FloatComplex *prow = row.fortran_vec ();
417 
418  octave_idx_type howmany = numel () / npts;
419  howmany = (stride == 1 ? howmany :
420  (howmany > stride ? stride : howmany));
421  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
422  octave_idx_type dist = (stride == 1 ? npts : 1);
423 
424  F77_FUNC (cffti, CFFTI) (npts, pwsave);
425 
426  for (octave_idx_type k = 0; k < nloop; k++)
427  {
428  for (octave_idx_type j = 0; j < howmany; j++)
429  {
430  octave_quit ();
431 
432  for (octave_idx_type l = 0; l < npts; l++)
433  prow[l] = retval((l + k*npts)*stride + j*dist);
434 
435  F77_FUNC (cfftf, CFFTF) (npts, prow, pwsave);
436 
437  for (octave_idx_type l = 0; l < npts; l++)
438  retval((l + k*npts)*stride + j*dist) = prow[l];
439  }
440  }
441 
442  stride *= dv(i);
443  }
444 
445  return retval;
446 }
447 
449 FloatNDArray::ifourierNd (void) const
450 {
451  dim_vector dv = dims ();
452  int rank = dv.length ();
453  FloatComplexNDArray retval (*this);
454  octave_idx_type stride = 1;
455 
456  for (int i = 0; i < rank; i++)
457  {
458  octave_idx_type npts = dv(i);
459  octave_idx_type nn = 4*npts+15;
460  Array<FloatComplex> wsave (nn);
461  FloatComplex *pwsave = wsave.fortran_vec ();
462  Array<FloatComplex> row (npts);
463  FloatComplex *prow = row.fortran_vec ();
464 
465  octave_idx_type howmany = numel () / npts;
466  howmany = (stride == 1 ? howmany :
467  (howmany > stride ? stride : howmany));
468  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
469  octave_idx_type dist = (stride == 1 ? npts : 1);
470 
471  F77_FUNC (cffti, CFFTI) (npts, pwsave);
472 
473  for (octave_idx_type k = 0; k < nloop; k++)
474  {
475  for (octave_idx_type j = 0; j < howmany; j++)
476  {
477  octave_quit ();
478 
479  for (octave_idx_type l = 0; l < npts; l++)
480  prow[l] = retval((l + k*npts)*stride + j*dist);
481 
482  F77_FUNC (cfftb, CFFTB) (npts, prow, pwsave);
483 
484  for (octave_idx_type l = 0; l < npts; l++)
485  retval((l + k*npts)*stride + j*dist) =
486  prow[l] / static_cast<float> (npts);
487  }
488  }
489 
490  stride *= dv(i);
491  }
492 
493  return retval;
494 }
495 
496 #endif
497 
498 // unary operations
499 
502 {
503  if (any_element_is_nan ())
505 
506  return do_mx_unary_op<bool, float> (*this, mx_inline_not);
507 }
508 
509 bool
511 {
512  return (neg_zero ? test_all (xnegative_sign)
513  : do_mx_check<float> (*this, mx_inline_any_negative));
514 }
515 
516 bool
518 {
519  return (neg_zero ? test_all (xpositive_sign)
520  : do_mx_check<float> (*this, mx_inline_any_positive));
521 }
522 
523 bool
525 {
526  return do_mx_check<float> (*this, mx_inline_any_nan);
527 }
528 
529 bool
531 {
532  return ! do_mx_check<float> (*this, mx_inline_all_finite);
533 }
534 
535 bool
537 {
538  return ! test_all (xis_one_or_zero);
539 }
540 
541 bool
543 {
544  return test_all (xis_zero);
545 }
546 
547 bool
549 {
551 }
552 
553 // Return nonzero if any element of M is not an integer. Also extract
554 // the largest and smallest values and return them in MAX_VAL and MIN_VAL.
555 
556 bool
557 FloatNDArray::all_integers (float& max_val, float& min_val) const
558 {
559  octave_idx_type nel = nelem ();
560 
561  if (nel > 0)
562  {
563  max_val = elem (0);
564  min_val = elem (0);
565  }
566  else
567  return false;
568 
569  for (octave_idx_type i = 0; i < nel; i++)
570  {
571  float val = elem (i);
572 
573  if (val > max_val)
574  max_val = val;
575 
576  if (val < min_val)
577  min_val = val;
578 
579  if (! xisinteger (val))
580  return false;
581  }
582 
583  return true;
584 }
585 
586 bool
588 {
589  return test_all (xisinteger);
590 }
591 
592 bool
594 {
595  return false;
596 }
597 
598 // FIXME: this is not quite the right thing.
599 
601 FloatNDArray::all (int dim) const
602 {
603  return do_mx_red_op<bool, float> (*this, dim, mx_inline_all);
604 }
605 
607 FloatNDArray::any (int dim) const
608 {
609  return do_mx_red_op<bool, float> (*this, dim, mx_inline_any);
610 }
611 
613 FloatNDArray::cumprod (int dim) const
614 {
615  return do_mx_cum_op<float, float> (*this, dim, mx_inline_cumprod);
616 }
617 
619 FloatNDArray::cumsum (int dim) const
620 {
621  return do_mx_cum_op<float, float> (*this, dim, mx_inline_cumsum);
622 }
623 
625 FloatNDArray::prod (int dim) const
626 {
627  return do_mx_red_op<float, float> (*this, dim, mx_inline_prod);
628 }
629 
631 FloatNDArray::sum (int dim) const
632 {
633  return do_mx_red_op<float, float> (*this, dim, mx_inline_sum);
634 }
635 
636 NDArray
637 FloatNDArray::dsum (int dim) const
638 {
639  return do_mx_red_op<double, float> (*this, dim, mx_inline_dsum);
640 }
641 
643 FloatNDArray::sumsq (int dim) const
644 {
645  return do_mx_red_op<float, float> (*this, dim, mx_inline_sumsq);
646 }
647 
649 FloatNDArray::max (int dim) const
650 {
651  return do_mx_minmax_op<float> (*this, dim, mx_inline_max);
652 }
653 
655 FloatNDArray::max (Array<octave_idx_type>& idx_arg, int dim) const
656 {
657  return do_mx_minmax_op<float> (*this, idx_arg, dim, mx_inline_max);
658 }
659 
661 FloatNDArray::min (int dim) const
662 {
663  return do_mx_minmax_op<float> (*this, dim, mx_inline_min);
664 }
665 
667 FloatNDArray::min (Array<octave_idx_type>& idx_arg, int dim) const
668 {
669  return do_mx_minmax_op<float> (*this, idx_arg, dim, mx_inline_min);
670 }
671 
673 FloatNDArray::cummax (int dim) const
674 {
675  return do_mx_cumminmax_op<float> (*this, dim, mx_inline_cummax);
676 }
677 
680 {
681  return do_mx_cumminmax_op<float> (*this, idx_arg, dim, mx_inline_cummax);
682 }
683 
685 FloatNDArray::cummin (int dim) const
686 {
687  return do_mx_cumminmax_op<float> (*this, dim, mx_inline_cummin);
688 }
689 
692 {
693  return do_mx_cumminmax_op<float> (*this, idx_arg, dim, mx_inline_cummin);
694 }
695 
697 FloatNDArray::diff (octave_idx_type order, int dim) const
698 {
699  return do_mx_diff_op<float> (*this, dim, order, mx_inline_diff);
700 }
701 
704  const Array<octave_idx_type>& ra_idx)
705 {
706  if (rb.numel () > 0)
707  insert (rb, ra_idx);
708  return *this;
709 }
710 
713  const Array<octave_idx_type>& ra_idx)
714 {
715  FloatComplexNDArray retval (*this);
716  if (rb.numel () > 0)
717  retval.insert (rb, ra_idx);
718  return retval;
719 }
720 
723  const Array<octave_idx_type>& ra_idx)
724 {
725  charNDArray retval (dims ());
726  octave_idx_type nel = numel ();
727 
728  for (octave_idx_type i = 0; i < nel; i++)
729  {
730  float d = elem (i);
731 
732  if (xisnan (d))
733  {
734  (*current_liboctave_error_handler)
735  ("invalid conversion from NaN to character");
736  return retval;
737  }
738  else
739  {
740  octave_idx_type ival = NINTbig (d);
741 
742  if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())
743  // FIXME: is there something better to do? Should we warn the user?
744  ival = 0;
745 
746  retval.elem (i) = static_cast<char>(ival);
747  }
748  }
749 
750  if (rb.numel () == 0)
751  return retval;
752 
753  retval.insert (rb, ra_idx);
754  return retval;
755 }
756 
759 {
760  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_real);
761 }
762 
765 {
766  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_imag);
767 }
768 
772 {
773  Array<float>::insert (a, r, c);
774  return *this;
775 }
776 
779  const Array<octave_idx_type>& ra_idx)
780 {
781  Array<float>::insert (a, ra_idx);
782  return *this;
783 }
784 
786 FloatNDArray::abs (void) const
787 {
788  return do_mx_unary_map<float, float, std::abs> (*this);
789 }
790 
793 {
794  return do_mx_unary_map<bool, float, xisnan> (*this);
795 }
796 
799 {
800  return do_mx_unary_map<bool, float, xisinf> (*this);
801 }
802 
805 {
806  return do_mx_unary_map<bool, float, xfinite> (*this);
807 }
808 
811 {
812  FloatMatrix retval;
813 
814  if (ndims () == 2)
815  retval = FloatMatrix (Array<float> (*this));
816  else
818  ("invalid conversion of FloatNDArray to FloatMatrix");
819 
820  return retval;
821 }
822 
823 void
825  const dim_vector& dimensions,
826  int start_dimension)
827 {
828  ::increment_index (ra_idx, dimensions, start_dimension);
829 }
830 
833  const dim_vector& dimensions)
834 {
835  return ::compute_index (ra_idx, dimensions);
836 }
837 
840 {
841  return MArray<float>::diag (k);
842 }
843 
846 {
847  return MArray<float>::diag (m, n);
848 }
849 
850 // This contains no information on the array structure !!!
851 std::ostream&
852 operator << (std::ostream& os, const FloatNDArray& a)
853 {
854  octave_idx_type nel = a.nelem ();
855 
856  for (octave_idx_type i = 0; i < nel; i++)
857  {
858  os << " ";
859  octave_write_float (os, a.elem (i));
860  os << "\n";
861  }
862  return os;
863 }
864 
865 std::istream&
866 operator >> (std::istream& is, FloatNDArray& a)
867 {
868  octave_idx_type nel = a.nelem ();
869 
870  if (nel > 0)
871  {
872  float tmp;
873  for (octave_idx_type i = 0; i < nel; i++)
874  {
875  tmp = octave_read_value<float> (is);
876  if (is)
877  a.elem (i) = tmp;
878  else
879  goto done;
880  }
881  }
882 
883 done:
884 
885  return is;
886 }
887 
888 MINMAX_FCNS (FloatNDArray, float)
889 
890 NDS_CMP_OPS (FloatNDArray, float)
891 NDS_BOOL_OPS (FloatNDArray, float)
892 
893 SND_CMP_OPS (float, FloatNDArray)
894 SND_BOOL_OPS (float, FloatNDArray)
895 
896 NDND_CMP_OPS (FloatNDArray, FloatNDArray)
897 NDND_BOOL_OPS (FloatNDArray, FloatNDArray)
898 
899 BSXFUN_STDOP_DEFS_MXLOOP (FloatNDArray)
900 BSXFUN_STDREL_DEFS_MXLOOP (FloatNDArray)
901 
902 BSXFUN_OP_DEF_MXLOOP (pow, FloatNDArray, mx_inline_pow)
903 BSXFUN_OP2_DEF_MXLOOP (pow, FloatComplexNDArray, FloatComplexNDArray,
904  FloatNDArray, mx_inline_pow)
905 BSXFUN_OP2_DEF_MXLOOP (pow, FloatComplexNDArray, FloatNDArray,
906  FloatComplexNDArray, mx_inline_pow)