changelog shortlog tags changeset files revisions annotate raw

src/data.cc

changeset 9846: 1d90fc211872
parent:f80c566bc751
author: John W. Eaton <jwe@octave.org>
date: Sat Nov 21 21:44:51 2009 -0500 (6 hours ago)
permissions: -rw-r--r--
description: configure.ac: report freetype, fontconfig, and fltk cflags and libs info
1/*
2
3Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
4 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
5Copyright (C) 2009 Jaroslav Hajek
6Copyright (C) 2009 VZLU Prague
7
8This file is part of Octave.
9
10Octave is free software; you can redistribute it and/or modify it
11under the terms of the GNU General Public License as published by the
12Free Software Foundation; either version 3 of the License, or (at your
13option) any later version.
14
15Octave is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
21along with Octave; see the file COPYING. If not, see
22<http://www.gnu.org/licenses/>.
23
24*/
25
26#ifdef HAVE_CONFIG_H
27#include <config.h>
28#endif
29
30#include "systime.h"
31
32#ifdef HAVE_SYS_TYPES_H
33#include <sys/types.h>
34#endif
35
36#ifdef HAVE_SYS_RESOURCE_H
37#include <sys/resource.h>
38#endif
39
40#include <cfloat>
41
42#include <string>
43
44#include "lo-ieee.h"
45#include "lo-math.h"
46#include "str-vec.h"
47#include "quit.h"
48#include "mx-base.h"
49
50#include "Cell.h"
51#include "defun.h"
52#include "error.h"
53#include "gripes.h"
54#include "oct-map.h"
55#include "oct-obj.h"
56#include "ov.h"
57#include "ov-float.h"
58#include "ov-complex.h"
59#include "ov-flt-complex.h"
60#include "ov-cx-mat.h"
61#include "ov-flt-cx-mat.h"
62#include "ov-cx-sparse.h"
63#include "parse.h"
64#include "pt-mat.h"
65#include "utils.h"
66#include "variables.h"
67#include "pager.h"
68#include "xnorm.h"
69
70#if ! defined (HAVE_HYPOTF) && defined (HAVE__HYPOTF)
71#define hypotf _hypotf
72#define HAVE_HYPOTF 1
73#endif
74
75#define ANY_ALL(FCN) \
76 \
77 octave_value retval; \
78 \
79 int nargin = args.length (); \
80 \
81 if (nargin == 1 || nargin == 2) \
82 { \
83 int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
84 \
85 if (! error_state) \
86 { \
87 if (dim >= -1) \
88 retval = args(0).FCN (dim); \
89 else \
90 error (#FCN ": invalid dimension argument = %d", dim + 1); \
91 } \
92 else \
93 error (#FCN ": expecting dimension argument to be an integer"); \
94 } \
95 else \
96 print_usage (); \
97 \
98 return retval
99
100DEFUN (all, args, ,
101 "-*- texinfo -*-\n\
102@deftypefn {Built-in Function} {} all (@var{x}, @var{dim})\n\
103The function @code{all} behaves like the function @code{any}, except\n\
104that it returns true only if all the elements of a vector, or all the\n\
105elements along dimension @var{dim} of a matrix, are nonzero.\n\
106@end deftypefn")
107{
108 ANY_ALL (all);
109}
110
111/*
112
113%!test
114%! x = ones (3);
115%! x(1,1) = 0;
116%! assert((all (all (rand (3) + 1) == [1, 1, 1]) == 1
117%! && all (all (x) == [0, 1, 1]) == 1
118%! && all (x, 1) == [0, 1, 1]
119%! && all (x, 2) == [0; 1; 1]));
120
121%!test
122%! x = ones (3, 'single');
123%! x(1,1) = 0;
124%! assert((all (all (single (rand (3) + 1)) == [1, 1, 1]) == 1
125%! && all (all (x) == [0, 1, 1]) == 1
126%! && all (x, 1) == [0, 1, 1]
127%! && all (x, 2) == [0; 1; 1]));
128
129%!error <Invalid call to all.*> all ();
130%!error <Invalid call to all.*> all (1, 2, 3);
131
132 */
133
134DEFUN (any, args, ,
135 "-*- texinfo -*-\n\
136@deftypefn {Built-in Function} {} any (@var{x}, @var{dim})\n\
137For a vector argument, return 1 if any element of the vector is\n\
138nonzero.\n\
139\n\
140For a matrix argument, return a row vector of ones and\n\
141zeros with each element indicating whether any of the elements of the\n\
142corresponding column of the matrix are nonzero. For example,\n\
143\n\
144@example\n\
145@group\n\
146any (eye (2, 4))\n\
147 @result{} [ 1, 1, 0, 0 ]\n\
148@end group\n\
149@end example\n\
150\n\
151If the optional argument @var{dim} is supplied, work along dimension\n\
152@var{dim}. For example,\n\
153\n\
154@example\n\
155@group\n\
156any (eye (2, 4), 2)\n\
157 @result{} [ 1; 1 ]\n\
158@end group\n\
159@end example\n\
160@end deftypefn")
161{
162 ANY_ALL (any);
163}
164
165/*
166
167%!test
168%! x = zeros (3);
169%! x(3,3) = 1;
170%! assert((all (any (x) == [0, 0, 1]) == 1
171%! && all (any (ones (3)) == [1, 1, 1]) == 1
172%! && any (x, 1) == [0, 0, 1]
173%! && any (x, 2) == [0; 0; 1]));
174
175%!test
176%! x = zeros (3,'single');
177%! x(3,3) = 1;
178%! assert((all (any (x) == [0, 0, 1]) == 1
179%! && all (any (ones (3, 'single')) == [1, 1, 1]) == 1
180%! && any (x, 1) == [0, 0, 1]
181%! && any (x, 2) == [0; 0; 1]));
182
183%!error <Invalid call to any.*> any ();
184%!error <Invalid call to any.*> any (1, 2, 3);
185
186 */
187
188// These mapping functions may also be useful in other places, eh?
189
190typedef double (*d_dd_fcn) (double, double);
191typedef float (*f_ff_fcn) (float, float);
192
193static NDArray
194map_d_m (d_dd_fcn f, double x, const NDArray& y)
195{
196 NDArray retval (y.dims ());
197 double *r_data = retval.fortran_vec ();
198
199 const double *y_data = y.data ();
200
201 octave_idx_type nel = y.numel ();
202
203 for (octave_idx_type i = 0; i < nel; i++)
204 {
205 OCTAVE_QUIT;
206 r_data[i] = f (x, y_data[i]);
207 }
208
209 return retval;
210}
211
212static FloatNDArray
213map_f_fm (f_ff_fcn f, float x, const FloatNDArray& y)
214{
215 FloatNDArray retval (y.dims ());
216 float *r_data = retval.fortran_vec ();
217
218 const float *y_data = y.data ();
219
220 octave_idx_type nel = y.numel ();
221
222 for (octave_idx_type i = 0; i < nel; i++)
223 {
224 OCTAVE_QUIT;
225 r_data[i] = f (x, y_data[i]);
226 }
227
228 return retval;
229}
230
231static NDArray
232map_m_d (d_dd_fcn f, const NDArray& x, double y)
233{
234 NDArray retval (x.dims ());
235 double *r_data = retval.fortran_vec ();
236
237 const double *x_data = x.data ();
238
239 octave_idx_type nel = x.numel ();
240
241 for (octave_idx_type i = 0; i < nel; i++)
242 {
243 OCTAVE_QUIT;
244 r_data[i] = f (x_data[i], y);
245 }
246
247 return retval;
248}
249
250static FloatNDArray
251map_fm_f (f_ff_fcn f, const FloatNDArray& x, float y)
252{
253 FloatNDArray retval (x.dims ());
254 float *r_data = retval.fortran_vec ();
255
256 const float *x_data = x.data ();
257
258 octave_idx_type nel = x.numel ();
259
260 for (octave_idx_type i = 0; i < nel; i++)
261 {
262 OCTAVE_QUIT;
263 r_data[i] = f (x_data[i], y);
264 }
265
266 return retval;
267}
268
269static NDArray
270map_m_m (d_dd_fcn f, const NDArray& x, const NDArray& y)
271{
272 assert (x.dims () == y.dims ());
273
274 NDArray retval (x.dims ());
275 double *r_data = retval.fortran_vec ();
276
277 const double *x_data = x.data ();
278 const double *y_data = y.data ();
279
280 octave_idx_type nel = x.numel ();
281
282 for (octave_idx_type i = 0; i < nel; i++)
283 {
284 OCTAVE_QUIT;
285 r_data[i] = f (x_data[i], y_data[i]);
286 }
287
288 return retval;
289}
290
291static FloatNDArray
292map_fm_fm (f_ff_fcn f, const FloatNDArray& x, const FloatNDArray& y)
293{
294 assert (x.dims () == y.dims ());
295
296 FloatNDArray retval (x.dims ());
297 float *r_data = retval.fortran_vec ();
298
299 const float *x_data = x.data ();
300 const float *y_data = y.data ();
301
302 octave_idx_type nel = x.numel ();
303
304 for (octave_idx_type i = 0; i < nel; i++)
305 {
306 OCTAVE_QUIT;
307 r_data[i] = f (x_data[i], y_data[i]);
308 }
309
310 return retval;
311}
312
313static SparseMatrix
314map_d_s (d_dd_fcn f, double x, const SparseMatrix& y)
315{
316 octave_idx_type nr = y.rows ();
317 octave_idx_type nc = y.columns ();
318 SparseMatrix retval;
319 double f_zero = f (x, 0.);
320
321 if (f_zero != 0)
322 {
323 retval = SparseMatrix (nr, nc, f_zero);
324
325 for (octave_idx_type j = 0; j < nc; j++)
326 for (octave_idx_type i = y.cidx (j); i < y.cidx (j+1); i++)
327 {
328 OCTAVE_QUIT;
329 retval.data (y.ridx(i) + j * nr) = f (x, y.data (i));
330 }
331
332 retval.maybe_compress (true);
333 }
334 else
335 {
336 octave_idx_type nz = y.nnz ();
337 retval = SparseMatrix (nr, nc, nz);
338 octave_idx_type ii = 0;
339 retval.cidx (ii) = 0;
340
341 for (octave_idx_type j = 0; j < nc; j++)
342 {
343 for (octave_idx_type i = y.cidx (j); i < y.cidx (j+1); i++)
344 {
345 OCTAVE_QUIT;
346 double val = f (x, y.data (i));
347
348 if (val != 0.0)
349 {
350 retval.data (ii) = val;
351 retval.ridx (ii++) = y.ridx (i);
352 }
353 }
354 retval.cidx (j + 1) = ii;
355 }
356
357 retval.maybe_compress (false);
358 }
359
360 return retval;
361}
362
363static SparseMatrix
364map_s_d (d_dd_fcn f, const SparseMatrix& x, double y)
365{
366 octave_idx_type nr = x.rows ();
367 octave_idx_type nc = x.columns ();
368 SparseMatrix retval;
369 double f_zero = f (0., y);
370
371 if (f_zero != 0)
372 {
373 retval = SparseMatrix (nr, nc, f_zero);
374
375 for (octave_idx_type j = 0; j < nc; j++)
376 for (octave_idx_type i = x.cidx (j); i < x.cidx (j+1); i++)
377 {
378 OCTAVE_QUIT;
379 retval.data (x.ridx(i) + j * nr) = f (x.data (i), y);
380 }
381
382 retval.maybe_compress (true);
383 }
384 else
385 {
386 octave_idx_type nz = x.nnz ();
387 retval = SparseMatrix (nr, nc, nz);
388 octave_idx_type ii = 0;
389 retval.cidx (ii) = 0;
390
391 for (octave_idx_type j = 0; j < nc; j++)
392 {
393 for (octave_idx_type i = x.cidx (j); i < x.cidx (j+1); i++)
394 {
395 OCTAVE_QUIT;
396 double val = f (x.data (i), y);
397
398 if (val != 0.0)
399 {
400 retval.data (ii) = val;
401 retval.ridx (ii++) = x.ridx (i);
402 }
403 }
404 retval.cidx (j + 1) = ii;
405 }
406
407 retval.maybe_compress (false);
408 }
409
410 return retval;
411}
412
413static SparseMatrix
414map_s_s (d_dd_fcn f, const SparseMatrix& x, const SparseMatrix& y)
415{
416 octave_idx_type nr = x.rows ();
417 octave_idx_type nc = x.columns ();
418
419 octave_idx_type y_nr = y.rows ();
420 octave_idx_type y_nc = y.columns ();
421
422 assert (nr == y_nr && nc == y_nc);
423
424 SparseMatrix retval;
425 double f_zero = f (0., 0.);
426
427 if (f_zero != 0)
428 {
429 retval = SparseMatrix (nr, nc, f_zero);
430 octave_idx_type k1 = 0, k2 = 0;
431
432 for (octave_idx_type j = 0; j < nc; j++)
433 {
434 while (k1 < x.cidx(j+1) && k2 < y.cidx(j+1))
435 {
436 OCTAVE_QUIT;
437 if (k1 >= x.cidx(j+1))
438 {
439 retval.data (y.ridx(k2) + j * nr) = f (0.0, y.data (k2));
440 k2++;
441 }
442 else if (k2 >= y.cidx(j+1))
443 {
444 retval.data (x.ridx(k1) + j * nr) = f (x.data (k1), 0.0);
445 k1++;
446 }
447 else
448 {
449 octave_idx_type rx = x.ridx(k1);
450 octave_idx_type ry = y.ridx(k2);
451
452 if (rx < ry)
453 {
454 retval.data (rx + j * nr) = f (x.data (k1), 0.0);
455 k1++;
456 }
457 else if (rx > ry)
458 {
459 retval.data (ry + j * nr) = f (0.0, y.data (k2));
460 k2++;
461 }
462 else
463 {
464 retval.data (ry + j * nr) = f (x.data (k1), y.data (k2));
465 k1++;
466 k2++;
467 }
468 }
469 }
470 }
471
472 retval.maybe_compress (true);
473 }
474 else
475 {
476 octave_idx_type nz = x.nnz () + y.nnz ();
477 retval = SparseMatrix (nr, nc, nz);
478 octave_idx_type ii = 0;
479 retval.cidx (ii) = 0;
480 octave_idx_type k1 = 0, k2 = 0;
481
482 for (octave_idx_type j = 0; j < nc; j++)
483 {
484 while (k1 < x.cidx(j+1) && k2 < y.cidx(j+1))
485 {
486 OCTAVE_QUIT;
487 double val;
488 octave_idx_type r;
489 if (k1 >= x.cidx(j+1))
490 {
491 r = y.ridx (k2);
492 val = f (0.0, y.data (k2++));
493 }
494 else if (k2 >= y.cidx(j+1))
495 {
496 r = x.ridx (k1);
497 val = f (x.data (k1++), 0.0);
498 }
499 else
500 {
501 octave_idx_type rx = x.ridx(k1);
502 octave_idx_type ry = y.ridx(k2);
503
504 if (rx < ry)
505 {
506 r = x.ridx (k1);
507 val = f (x.data (k1++), 0.0);
508 }
509 else if (rx > ry)
510 {
511 r = y.ridx (k2);
512 val = f (0.0, y.data (k2++));
513 }
514 else
515 {
516 r = y.ridx (k2);
517 val = f (x.data (k1++), y.data (k2++));
518 }
519 }
520 if (val != 0.0)
521 {
522 retval.data (ii) = val;
523 retval.ridx (ii++) = r;
524 }
525 }
526 retval.cidx (j + 1) = ii;
527 }
528
529 retval.maybe_compress (false);
530 }
531
532 return retval;
533}
534
535DEFUN (atan2, args, ,
536 "-*- texinfo -*-\n\
537@deftypefn {Mapping Function} {} atan2 (@var{y}, @var{x})\n\
538Compute atan (@var{y} / @var{x}) for corresponding elements of @var{y}\n\
539and @var{x}. Signal an error if @var{y} and @var{x} do not match in size\n\
540and orientation.\n\
541@end deftypefn")
542{
543 octave_value retval;
544
545 int nargin = args.length ();
546
547 if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
548 {
549 if (args(0).is_integer_type () || args(1).is_integer_type ())
550 error ("atan2: not defined for integer types");
551 else
552 {
553 octave_value arg_y = args(0);
554 octave_value arg_x = args(1);
555
556 dim_vector y_dims = arg_y.dims ();
557 dim_vector x_dims = arg_x.dims ();
558
559 bool y_is_scalar = y_dims.all_ones ();
560 bool x_is_scalar = x_dims.all_ones ();
561
562 bool is_float = arg_y.is_single_type () || arg_x.is_single_type ();
563
564 if (y_is_scalar && x_is_scalar)
565 {
566 if (is_float)
567 {
568 float y = arg_y.float_value ();
569
570 if (! error_state)
571 {
572 float x = arg_x.float_value ();
573
574 if (! error_state)
575 retval = atan2f (y, x);
576 }
577 }
578 else
579 {
580 double y = arg_y.double_value ();
581
582 if (! error_state)
583 {
584 double x = arg_x.double_value ();
585
586 if (! error_state)
587 retval = atan2 (y, x);
588 }
589 }
590 }
591 else if (y_is_scalar)
592 {
593 if (is_float)
594 {
595 float y = arg_y.float_value ();
596
597 if (! error_state)
598 {
599 // Even if x is sparse return a full matrix here
600 FloatNDArray x = arg_x.float_array_value ();
601
602 if (! error_state)
603 retval = map_f_fm (atan2f, y, x);
604 }
605 }
606 else
607 {
608 double y = arg_y.double_value ();
609
610 if (! error_state)
611 {
612 // Even if x is sparse return a full matrix here
613 NDArray x = arg_x.array_value ();
614
615 if (! error_state)
616 retval = map_d_m (atan2, y, x);
617 }
618 }
619 }
620 else if (x_is_scalar)
621 {
622 if (arg_y.is_sparse_type ())
623 {
624 SparseMatrix y = arg_y.sparse_matrix_value ();
625
626 if (! error_state)
627 {
628 double x = arg_x.double_value ();
629
630 if (! error_state)
631 retval = map_s_d (atan2, y, x);
632 }
633 }
634 else if (is_float)
635 {
636 FloatNDArray y = arg_y.float_array_value ();
637
638 if (! error_state)
639 {
640 float x = arg_x.float_value ();
641
642 if (! error_state)
643 retval = map_fm_f (atan2f, y, x);
644 }
645 }
646 else
647 {
648 NDArray y = arg_y.array_value ();
649
650 if (! error_state)
651 {
652 double x = arg_x.double_value ();
653
654 if (! error_state)
655 retval = map_m_d (atan2, y, x);
656 }
657 }
658 }
659 else if (y_dims == x_dims)
660 {
661 // Even if y is sparse return a full matrix here
662 if (arg_x.is_sparse_type ())
663 {
664 SparseMatrix y = arg_y.sparse_matrix_value ();
665
666 if (! error_state)
667 {
668 SparseMatrix x = arg_x.sparse_matrix_value ();
669
670 if (! error_state)
671 retval = map_s_s (atan2, y, x);
672 }
673 }
674 else if (is_float)
675 {
676 FloatNDArray y = arg_y.array_value ();
677
678 if (! error_state)
679 {
680 FloatNDArray x = arg_x.array_value ();
681
682 if (! error_state)
683 retval = map_fm_fm (atan2f, y, x);
684 }
685 }
686 else
687 {
688 NDArray y = arg_y.array_value ();
689
690 if (! error_state)
691 {
692 NDArray x = arg_x.array_value ();
693
694 if (! error_state)
695 retval = map_m_m (atan2, y, x);
696 }
697 }
698 }
699 else
700 error ("atan2: nonconformant matrices");
701 }
702 }
703 else
704 print_usage ();
705
706 return retval;
707}
708
709/*
710%!assert (size (atan2 (zeros (0, 2), zeros (0, 2))), [0, 2])
711%!assert (size (atan2 (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
712%!assert (size (atan2 (rand (2, 3, 4), 1)), [2, 3, 4])
713%!assert (size (atan2 (1, rand (2, 3, 4))), [2, 3, 4])
714%!assert (size (atan2 (1, 2)), [1, 1])
715
716%!test
717%! rt2 = sqrt (2);
718%! rt3 = sqrt (3);
719%! v = [0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0];
720%! y = [0, rt3, 1, rt3, -rt3, -1, -rt3, 0];
721%! x = [1, 3, 1, 1, 1, 1, 3, 1];
722%! assert(atan2 (y, x), v, sqrt (eps));
723
724%!test
725%! rt2 = sqrt (2);
726%! rt3 = sqrt (3);
727%! v = single([0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0]);
728%! y = single([0, rt3, 1, rt3, -rt3, -1, -rt3, 0]);
729%! x = single([1, 3, 1, 1, 1, 1, 3, 1]);
730%! assert(atan2 (y, x), v, sqrt (eps('single')));
731
732%!error <Invalid call to atan2.*> atan2 ();
733%!error <Invalid call to atan2.*> atan2 (1, 2, 3);
734
735*/
736
737
738
739DEFUN (hypot, args, ,
740 "-*- texinfo -*-\n\
741@deftypefn {Built-in Function} {} hypot (@var{x}, @var{y})\n\
742Compute the element-by-element square root of the sum of the squares of\n\
743@var{x} and @var{y}. This is equivalent to\n\
744@code{sqrt (@var{x}.^2 + @var{y}.^2)}, but calculated in a manner that\n\
745avoids overflows for large values of @var{x} or @var{y}.\n\
746@end deftypefn")
747{
748 octave_value retval;
749
750 int nargin = args.length ();
751
752 if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
753 {
754 if (args(0).is_integer_type () || args(1).is_integer_type ())
755 error ("hypot: not defined for integer types");
756 else
757 {
758 octave_value arg_x = args(0);
759 octave_value arg_y = args(1);
760
761 dim_vector x_dims = arg_x.dims ();
762 dim_vector y_dims = arg_y.dims ();
763
764 bool x_is_scalar = x_dims.all_ones ();
765 bool y_is_scalar = y_dims.all_ones ();
766
767 bool is_float = arg_y.is_single_type () || arg_x.is_single_type ();
768
769 if (y_is_scalar && x_is_scalar)
770 {
771 if (is_float)
772 {
773 float x;
774 if (arg_x.is_complex_type ())
775 x = abs (arg_x.float_complex_value ());
776 else
777 x = arg_x.float_value ();
778
779 if (! error_state)
780 {
781 float y;
782 if (arg_y.is_complex_type ())
783 y = abs (arg_y.float_complex_value ());
784 else
785 y = arg_y.float_value ();
786
787 if (! error_state)
788 retval = hypotf (x, y);
789 }
790 }
791 else
792 {
793 double x;
794 if (arg_x.is_complex_type ())
795 x = abs (arg_x.complex_value ());
796 else
797 x = arg_x.double_value ();
798
799 if (! error_state)
800 {
801 double y;
802 if (arg_y.is_complex_type ())
803 y = abs (arg_y.complex_value ());
804 else
805 y = arg_y.double_value ();
806
807 if (! error_state)
808 retval = hypot (x, y);
809 }
810 }
811 }
812 else if (y_is_scalar)
813 {
814 if (is_float)
815 {
816 FloatNDArray x;
817 if (arg_x.is_complex_type ())
818 x = arg_x.float_complex_array_value ().abs ();
819 else
820 x = arg_x.float_array_value ();
821
822 if (! error_state)
823 {
824 float y;
825 if (arg_y.is_complex_type ())
826 y = abs (arg_y.float_complex_value ());
827 else
828 y = arg_y.float_value ();
829
830 if (! error_state)
831 retval = map_fm_f (hypotf, x, y);
832 }
833 }
834 else
835 {
836 NDArray x;
837 if (arg_x.is_complex_type ())
838 x = arg_x.complex_array_value ().abs ();
839 else
840 x = arg_x.array_value ();
841
842 if (! error_state)
843 {
844 double y;
845 if (arg_y.is_complex_type ())
846 y = abs (arg_y.complex_value ());
847 else
848 y = arg_y.double_value ();
849
850 if (! error_state)
851 retval = map_m_d (hypot, x, y);
852 }
853 }
854 }
855 else if (x_is_scalar)
856 {
857 if (is_float)
858 {
859 float x;
860 if (arg_x.is_complex_type ())
861 x = abs (arg_x.float_complex_value ());
862 else
863 x = arg_x.float_value ();
864
865 if (! error_state)
866 {
867 FloatNDArray y;
868 if (arg_y.is_complex_type ())
869 y = arg_y.float_complex_array_value ().abs ();
870 else
871 y = arg_y.float_array_value ();
872
873 if (! error_state)
874 retval = map_f_fm (hypotf, x, y);
875 }
876 }
877 else
878 {
879 double x;
880 if (arg_x.is_complex_type ())
881 x = abs (arg_x.complex_value ());
882 else
883 x = arg_x.double_value ();
884
885 if (! error_state)
886 {
887 NDArray y;
888 if (arg_y.is_complex_type ())
889 y = arg_y.complex_array_value ().abs ();
890 else
891 y = arg_y.array_value ();
892
893 if (! error_state)
894 retval = map_d_m (hypot, x, y);
895 }
896 }
897 }
898 else if (y_dims == x_dims)
899 {
900 if (arg_x.is_sparse_type () && arg_y.is_sparse_type ())
901 {
902 SparseMatrix x;
903 if (arg_x.is_complex_type ())
904 x = arg_x.sparse_complex_matrix_value ().abs ();
905 else
906 x = arg_x.sparse_matrix_value ();
907
908 if (! error_state)
909 {
910 SparseMatrix y;
911 if (arg_y.is_complex_type ())
912 y = arg_y.sparse_complex_matrix_value ().abs ();
913 else
914 y = arg_y.sparse_matrix_value ();
915
916 if (! error_state)
917 retval = map_s_s (hypot, x, y);
918 }
919 }
920 else if (is_float)
921 {
922 FloatNDArray x;
923 if (arg_x.is_complex_type ())
924 x = arg_x.float_complex_array_value ().abs ();
925 else
926 x = arg_x.float_array_value ();
927
928 if (! error_state)
929 {
930 FloatNDArray y;
931 if (arg_y.is_complex_type ())
932 y = arg_y.float_complex_array_value ().abs ();
933 else
934 y = arg_y.float_array_value ();
935
936 if (! error_state)
937 retval = map_fm_fm (hypotf, x, y);
938 }
939 }
940 else
941 {
942 NDArray x;
943 if (arg_x.is_complex_type ())
944 x = arg_x.complex_array_value ().abs ();
945 else
946 x = arg_x.array_value ();
947
948 if (! error_state)
949 {
950 NDArray y;
951 if (arg_y.is_complex_type ())
952 y = arg_y.complex_array_value ().abs ();
953 else
954 y = arg_y.array_value ();
955
956 if (! error_state)
957 retval = map_m_m (hypot, x, y);
958 }
959 }
960 }
961 else
962 error ("hypot: nonconformant matrices");
963 }
964 }
965 else
966 print_usage ();
967
968 return retval;
969}
970
971/*
972%!assert (size (hypot (zeros (0, 2), zeros (0, 2))), [0, 2])
973%!assert (size (hypot (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
974%!assert (size (hypot (rand (2, 3, 4), 1)), [2, 3, 4])
975%!assert (size (hypot (1, rand (2, 3, 4))), [2, 3, 4])
976%!assert (size (hypot (1, 2)), [1, 1])
977%!assert (hypot (1:10, 1:10), sqrt(2) * [1:10], 16*eps)
978%!assert (hypot (single(1:10), single(1:10)), single(sqrt(2) * [1:10]));
979*/
980
981template<typename T, typename ET>
982void
983map_2_xlog2 (const Array<T>& x, Array<T>& f, Array<ET>& e)
984{
985 f = Array<T>(x.dims ());
986 e = Array<ET>(x.dims ());
987 for (octave_idx_type i = 0; i < x.numel (); i++)
988 {
989 int exp;
990 f.xelem (i) = xlog2 (x(i), exp);
991 e.xelem (i) = exp;
992 }
993}
994
995DEFUN (log2, args, nargout,
996 "-*- texinfo -*-\n\
997@deftypefn {Mapping Function} {} log2 (@var{x})\n\
998@deftypefnx {Mapping Function} {[@var{f}, @var{e}] =} log2 (@var{x})\n\
999Compute the base-2 logarithm of each element of @var{x}.\n\
1000\n\
1001If called with two output arguments, split @var{x} into\n\
1002binary mantissa and exponent so that\n\
1003@tex\n\
1004${1 \\over 2} \\le \\left| f \\right| < 1$\n\
1005@end tex\n\
1006@ifnottex\n\
1007@code{1/2 <= abs(f) < 1}\n\
1008@end ifnottex\n\
1009and @var{e} is an integer. If\n\
1010@tex\n\
1011$x = 0$, $f = e = 0$.\n\
1012@end tex\n\
1013@ifnottex\n\
1014@code{x = 0}, @code{f = e = 0}.\n\
1015@end ifnottex\n\
1016@seealso{pow2, log, log10, exp}\n\
1017@end deftypefn")
1018{
1019 octave_value_list retval;
1020
1021 if (args.length () == 1)
1022 {
1023 if (nargout < 2)
1024 retval(0) = args(0).log2 ();
1025 else if (args(0).is_single_type ())
1026 {
1027 if (args(0).is_real_type ())
1028 {
1029 FloatNDArray f;
1030 FloatNDArray x = args(0).float_array_value ();
1031 // FIXME -- should E be an int value?
1032 FloatMatrix e;
1033 map_2_xlog2 (x, f, e);
1034 retval (1) = e;
1035 retval (0) = f;
1036 }
1037 else if (args(0).is_complex_type ())
1038 {
1039 FloatComplexNDArray f;
1040 FloatComplexNDArray x = args(0).float_complex_array_value ();
1041 // FIXME -- should E be an int value?
1042 FloatNDArray e;
1043 map_2_xlog2 (x, f, e);
1044 retval (1) = e;
1045 retval (0) = f;
1046 }
1047 }
1048 else if (args(0).is_real_type ())
1049 {
1050 NDArray f;
1051 NDArray x = args(0).array_value ();
1052 // FIXME -- should E be an int value?
1053 Matrix e;
1054 map_2_xlog2 (x, f, e);
1055 retval (1) = e;
1056 retval (0) = f;
1057 }
1058 else if (args(0).is_complex_type ())
1059 {
1060 ComplexNDArray f;
1061 ComplexNDArray x = args(0).complex_array_value ();
1062 // FIXME -- should E be an int value?
1063 NDArray e;
1064 map_2_xlog2 (x, f, e);
1065 retval (1) = e;
1066 retval (0) = f;
1067 }
1068 else
1069 gripe_wrong_type_arg ("log2", args(0));
1070 }
1071 else
1072 print_usage ();
1073
1074 return retval;
1075}
1076
1077/*
1078%!assert(log2 ([1/4, 1/2, 1, 2, 4]), [-2, -1, 0, 1, 2]);
1079%!assert(log2(Inf), Inf);
1080%!assert(isnan(log2(NaN)));
1081%!assert(log2(4*i), 2 + log2(1*i));
1082%!assert(log2(complex(0,Inf)), Inf + log2(i));
1083
1084%!test
1085%! [f, e] = log2 ([0,-1; 2,-4; Inf,-Inf]);
1086%! assert (f, [0,-0.5; 0.5,-0.5; Inf,-Inf]);
1087%! assert (e(1:2,:), [0,1;2,3])
1088
1089%!test
1090%! [f, e] = log2 (complex (zeros (3, 2), [0,-1; 2,-4; Inf,-Inf]));
1091%! assert (f, complex (zeros (3, 2), [0,-0.5; 0.5,-0.5; Inf,-Inf]));
1092%! assert (e(1:2,:), [0,1; 2,3]);
1093*/
1094
1095DEFUN (fmod, args, ,
1096 "-*- texinfo -*-\n\
1097@deftypefn {Mapping Function} {} fmod (@var{x}, @var{y})\n\
1098Compute the floating point remainder of dividing @var{x} by @var{y}\n\
1099using the C library function @code{fmod}. The result has the same\n\
1100sign as @var{x}. If @var{y} is zero, the result is implementation-dependent.\n\
1101@seealso{mod, rem}\n\
1102@end deftypefn")
1103{
1104 octave_value retval;
1105
1106 int nargin = args.length ();
1107
1108 if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
1109 {
1110 octave_value arg_x = args(0);
1111 octave_value arg_y = args(1);
1112
1113 dim_vector y_dims = arg_y.dims ();
1114 dim_vector x_dims = arg_x.dims ();
1115
1116 bool y_is_scalar = y_dims.all_ones ();
1117 bool x_is_scalar = x_dims.all_ones ();
1118
1119 bool is_float = arg_y.is_single_type () || arg_x.is_single_type ();
1120
1121 if (y_is_scalar && x_is_scalar)
1122 {
1123 if (is_float)
1124 {
1125 float y = arg_y.float_value ();
1126
1127 if (! error_state)
1128 {
1129 float x = arg_x.float_value ();
1130
1131 if (! error_state)
1132 retval = fmod (x, y);
1133 }
1134 }
1135 else
1136 {
1137 double y = arg_y.double_value ();
1138
1139 if (! error_state)
1140 {
1141 double x = arg_x.double_value ();
1142
1143 if (! error_state)
1144 retval = fmod (x, y);
1145 }
1146 }
1147 }
1148 else if (y_is_scalar)
1149 {
1150 if (is_float)
1151 {
1152 float y = arg_y.float_value ();
1153
1154 if (! error_state)
1155 {
1156 FloatNDArray x = arg_x.float_array_value ();
1157
1158 if (! error_state)
1159 retval = map_fm_f (fmodf, x, y);
1160 }
1161 }
1162 else
1163 {
1164 double y = arg_y.double_value ();
1165
1166 if (! error_state)
1167 {
1168 if (arg_x.is_sparse_type ())
1169 {
1170 SparseMatrix x = arg_x.sparse_matrix_value ();
1171
1172 if (! error_state)
1173 retval = map_s_d (fmod, x, y);
1174 }
1175 else
1176 {
1177 NDArray x = arg_x.array_value ();
1178
1179 if (! error_state)
1180 retval = map_m_d (fmod, x, y);
1181 }
1182 }
1183 }
1184 }
1185 else if (x_is_scalar)
1186 {
1187 if (arg_y.is_sparse_type ())
1188 {
1189 SparseMatrix y = arg_y.sparse_matrix_value ();
1190
1191 if (! error_state)
1192 {
1193 double x = arg_x.double_value ();
1194
1195 if (! error_state)
1196 retval = map_d_s (fmod, x, y);
1197 }
1198 }
1199 else if (is_float)
1200 {
1201 FloatNDArray y = arg_y.float_array_value ();
1202
1203 if (! error_state)
1204 {
1205 float x = arg_x.float_value ();
1206
1207 if (! error_state)
1208 retval = map_f_fm (fmodf, x, y);
1209 }
1210 }
1211 else
1212 {
1213 NDArray y = arg_y.array_value ();
1214
1215 if (! error_state)
1216 {
1217 double x = arg_x.double_value ();
1218
1219 if (! error_state)
1220 retval = map_d_m (fmod, x, y);
1221 }
1222 }
1223 }
1224 else if (y_dims == x_dims)
1225 {
1226 if (arg_y.is_sparse_type () || arg_x.is_sparse_type ())
1227 {
1228 SparseMatrix y = arg_y.sparse_matrix_value ();
1229
1230 if (! error_state)
1231 {
1232 SparseMatrix x = arg_x.sparse_matrix_value ();
1233
1234 if (! error_state)
1235 retval = map_s_s (fmod, x, y);
1236 }
1237 }
1238 else if (is_float)
1239 {
1240 FloatNDArray y = arg_y.float_array_value ();
1241
1242 if (! error_state)
1243 {
1244 FloatNDArray x = arg_x.float_array_value ();
1245
1246 if (! error_state)
1247 retval = map_fm_fm (fmodf, x, y);
1248 }
1249 }
1250 else
1251 {
1252 NDArray y = arg_y.array_value ();
1253
1254 if (! error_state)
1255 {
1256 NDArray x = arg_x.array_value ();
1257
1258 if (! error_state)
1259 retval = map_m_m (fmod, x, y);
1260 }
1261 }
1262 }
1263 else
1264 error ("fmod: nonconformant matrices");
1265 }
1266 else
1267 print_usage ();
1268
1269 return retval;
1270}
1271
1272/*
1273%!assert (size (fmod (zeros (0, 2), zeros (0, 2))), [0, 2])
1274%!assert (size (fmod (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
1275%!assert (size (fmod (rand (2, 3, 4), 1)), [2, 3, 4])
1276%!assert (size (fmod (1, rand (2, 3, 4))), [2, 3, 4])
1277%!assert (size (fmod (1, 2)), [1, 1])
1278*/
1279
1280// FIXME Need to convert the reduction functions of this file for single precision
1281
1282#define NATIVE_REDUCTION_1(FCN, TYPE, DIM) \
1283 (arg.is_ ## TYPE ## _type ()) \
1284 { \
1285 TYPE ## NDArray tmp = arg. TYPE ##_array_value (); \
1286 \
1287 if (! error_state) \
1288 { \
1289 octave_ ## TYPE::clear_conv_flags (); \
1290 retval = tmp.FCN (DIM); \
1291 if (octave_ ## TYPE::get_trunc_flag ()) \
1292 { \
1293 gripe_native_integer_math_truncated (#FCN, \
1294 octave_ ## TYPE::type_name ()); \
1295 octave_ ## TYPE::clear_conv_flags (); \
1296 } \
1297 } \
1298 }
1299
1300#define NATIVE_REDUCTION(FCN, BOOL_FCN) \
1301 \
1302 octave_value retval; \
1303 \
1304 int nargin = args.length (); \
1305 \
1306 bool isnative = false; \
1307 bool isdouble = false; \
1308 \
1309 if (nargin > 1 && args(nargin - 1).is_string ()) \
1310 { \
1311 std::string str = args(nargin - 1).string_value (); \
1312 \
1313 if (! error_state) \
1314 { \
1315 if (str == "native") \
1316 isnative = true; \
1317 else if (str == "double") \
1318 isdouble = true; \
1319 else \
1320 error ("sum: unrecognized string argument"); \
1321 nargin --; \
1322 } \
1323 } \
1324 \
1325 if (nargin == 1 || nargin == 2) \
1326 { \
1327 octave_value arg = args(0); \
1328 \
1329 int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
1330 \
1331 if (! error_state) \
1332 { \
1333 if (dim >= -1) \
1334 { \
1335 if (arg.is_sparse_type ()) \
1336 { \
1337 if (arg.is_real_type ()) \
1338 { \
1339 SparseMatrix tmp = arg.sparse_matrix_value (); \
1340 \
1341 if (! error_state) \
1342 retval = tmp.FCN (dim); \
1343 } \
1344 else \
1345 { \
1346 SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \
1347 \
1348 if (! error_state) \
1349 retval = tmp.FCN (dim); \
1350 } \
1351 } \
1352 else \
1353 { \
1354 if (isnative) \
1355 { \
1356 if NATIVE_REDUCTION_1 (FCN, uint8, dim) \
1357 else if NATIVE_REDUCTION_1 (FCN, uint16, dim) \
1358 else if NATIVE_REDUCTION_1 (FCN, uint32, dim) \
1359 else if NATIVE_REDUCTION_1 (FCN, uint64, dim) \
1360 else if NATIVE_REDUCTION_1 (FCN, int8, dim) \
1361 else if NATIVE_REDUCTION_1 (FCN, int16, dim) \
1362 else if NATIVE_REDUCTION_1 (FCN, int32, dim) \
1363 else if NATIVE_REDUCTION_1 (FCN, int64, dim) \
1364 else if (arg.is_bool_type ()) \
1365 { \
1366 boolNDArray tmp = arg.bool_array_value (); \
1367 if (! error_state) \
1368 retval = boolNDArray (tmp.BOOL_FCN (dim)); \
1369 } \
1370 else if (arg.is_char_matrix ()) \
1371 { \
1372 error (#FCN, ": invalid char type"); \
1373 } \
1374 else if (!isdouble && arg.is_single_type ()) \
1375 { \
1376 if (arg.is_complex_type ()) \
1377 { \
1378 FloatComplexNDArray tmp = \
1379 arg.float_complex_array_value (); \
1380 \
1381 if (! error_state) \
1382 retval = tmp.FCN (dim); \
1383 } \
1384 else if (arg.is_real_type ()) \
1385 { \
1386 FloatNDArray tmp = arg.float_array_value (); \
1387 \
1388 if (! error_state) \
1389 retval = tmp.FCN (dim); \
1390 } \
1391 } \
1392 else if (arg.is_complex_type ()) \
1393 { \
1394 ComplexNDArray tmp = arg.complex_array_value (); \
1395 \
1396 if (! error_state) \
1397 retval = tmp.FCN (dim); \
1398 } \
1399 else if (arg.is_real_type ()) \
1400 { \
1401 NDArray tmp = arg.array_value (); \
1402 \
1403 if (! error_state) \
1404 retval = tmp.FCN (dim); \
1405 } \
1406 else \
1407 { \
1408 gripe_wrong_type_arg (#FCN, arg); \
1409 return retval; \
1410 } \
1411 } \
1412 else if (arg.is_bool_type ()) \
1413 { \
1414 boolNDArray tmp = arg.bool_array_value (); \
1415 if (! error_state) \
1416 retval = tmp.FCN (dim); \
1417 } \
1418 else if (!isdouble && arg.is_single_type ()) \
1419 { \
1420 if (arg.is_real_type ()) \
1421 { \
1422 FloatNDArray tmp = arg.float_array_value (); \
1423 \
1424 if (! error_state) \
1425 retval = tmp.FCN (dim); \
1426 } \
1427 else if (arg.is_complex_type ()) \
1428 { \
1429 FloatComplexNDArray tmp = \
1430 arg.float_complex_array_value (); \
1431 \
1432 if (! error_state) \
1433 retval = tmp.FCN (dim); \
1434 } \
1435 } \
1436 else if (arg.is_real_type ()) \
1437 { \
1438 NDArray tmp = arg.array_value (); \
1439 \
1440 if (! error_state) \
1441 retval = tmp.FCN (dim); \
1442 } \
1443 else if (arg.is_complex_type ()) \
1444 { \
1445 ComplexNDArray tmp = arg.complex_array_value (); \
1446 \
1447 if (! error_state) \
1448 retval = tmp.FCN (dim); \
1449 } \
1450 else \
1451 { \
1452 gripe_wrong_type_arg (#FCN, arg); \
1453 return retval; \
1454 } \
1455 } \
1456 } \
1457 else \
1458 error (#FCN ": invalid dimension argument = %d", dim + 1); \
1459 } \
1460 \
1461 } \
1462 else \
1463 print_usage (); \
1464 \
1465 return retval
1466
1467#define DATA_REDUCTION(FCN) \
1468 \
1469 octave_value retval; \
1470 \
1471 int nargin = args.length (); \
1472 \
1473 if (nargin == 1 || nargin == 2) \
1474 { \
1475 octave_value arg = args(0); \
1476 \
1477 int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
1478 \
1479 if (! error_state) \
1480 { \
1481 if (dim >= -1) \
1482 { \
1483 if (arg.is_real_type ()) \
1484 { \
1485 if (arg.is_sparse_type ()) \
1486 { \
1487 SparseMatrix tmp = arg.sparse_matrix_value (); \
1488 \
1489 if (! error_state) \
1490 retval = tmp.FCN (dim); \
1491 } \
1492 else if (arg.is_single_type ()) \
1493 { \
1494 FloatNDArray tmp = arg.float_array_value (); \
1495 \
1496 if (! error_state) \
1497 retval = tmp.FCN (dim); \
1498 } \
1499 else \
1500 { \
1501 NDArray tmp = arg.array_value (); \
1502 \
1503 if (! error_state) \
1504 retval = tmp.FCN (dim); \
1505 } \
1506 } \
1507 else if (arg.is_complex_type ()) \
1508 { \
1509 if (arg.is_sparse_type ()) \
1510 { \
1511 SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \
1512 \
1513 if (! error_state) \
1514 retval = tmp.FCN (dim); \
1515 } \
1516 else if (arg.is_single_type ()) \
1517 { \
1518 FloatComplexNDArray tmp = arg.float_complex_array_value (); \
1519 \
1520 if (! error_state) \
1521 retval = tmp.FCN (dim); \
1522 } \
1523 else \
1524 { \
1525 ComplexNDArray tmp = arg.complex_array_value (); \
1526 \
1527 if (! error_state) \
1528 retval = tmp.FCN (dim); \
1529 } \
1530 } \
1531 else \
1532 { \
1533 gripe_wrong_type_arg (#FCN, arg); \
1534 return retval; \
1535 } \
1536 } \
1537 else \
1538 error (#FCN ": invalid dimension argument = %d", dim + 1); \
1539 } \
1540 } \
1541 else \
1542 print_usage (); \
1543 \
1544 return retval
1545
1546DEFUN (cumprod, args, ,
1547 "-*- texinfo -*-\n\
1548@deftypefn {Built-in Function} {} cumprod (@var{x})\n\
1549@deftypefnx {Built-in Function} {} cumprod (@var{x}, @var{dim})\n\
1550Cumulative product of elements along dimension @var{dim}. If\n\
1551@var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
1552\n\
1553@seealso{prod, cumsum}\n\
1554@end deftypefn")
1555{
1556 DATA_REDUCTION (cumprod);
1557}
1558
1559/*
1560
1561%!assert (cumprod ([1, 2, 3]), [1, 2, 6]);
1562%!assert (cumprod ([-1; -2; -3]), [-1; 2; -6]);
1563%!assert (cumprod ([i, 2+i, -3+2i, 4]), [i, -1+2i, -1-8i, -4-32i]);
1564%!assert (cumprod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [1, 2, 3; i, 4i, 9i; -1+i, -8+8i, -27+27i]);
1565
1566%!assert (cumprod (single([1, 2, 3])), single([1, 2, 6]));
1567%!assert (cumprod (single([-1; -2; -3])), single([-1; 2; -6]));
1568%!assert (cumprod (single([i, 2+i, -3+2i, 4])), single([i, -1+2i, -1-8i, -4-32i]));
1569%!assert (cumprod (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([1, 2, 3; i, 4i, 9i; -1+i, -8+8i, -27+27i]));
1570
1571%!error <Invalid call to cumprod.*> cumprod ();
1572
1573%!assert (cumprod ([2, 3; 4, 5], 1), [2, 3; 8, 15]);
1574%!assert (cumprod ([2, 3; 4, 5], 2), [2, 6; 4, 20]);
1575
1576%!assert (cumprod (single([2, 3; 4, 5]), 1), single([2, 3; 8, 15]));
1577%!assert (cumprod (single([2, 3; 4, 5]), 2), single([2, 6; 4, 20]));
1578
1579 */
1580
1581DEFUN (cumsum, args, ,
1582 "-*- texinfo -*-\n\
1583@deftypefn {Built-in Function} {} cumsum (@var{x})\n\
1584@deftypefnx {Built-in Function} {} cumsum (@var{x}, @var{dim})\n\
1585@deftypefnx {Built-in Function} {} cumsum (@dots{}, 'native')\n\
1586Cumulative sum of elements along dimension @var{dim}. If @var{dim}\n\
1587is omitted, it defaults to the first non-singleton dimension.\n\
1588\n\
1589The \"native\" argument implies the summation is performed in native type.\n\
1590 See @code{sum} for a complete description and example of the use of\n\
1591\"native\".\n\
1592@seealso{sum, cumprod}\n\
1593@end deftypefn")
1594{
1595 octave_value retval;
1596
1597 int nargin = args.length ();
1598
1599 bool isnative = false;
1600 bool isdouble = false;
1601
1602 if (nargin > 1 && args(nargin - 1).is_string ())
1603 {
1604 std::string str = args(nargin - 1).string_value ();
1605
1606 if (! error_state)
1607 {
1608 if (str == "native")
1609 isnative = true;
1610 else if (str == "double")
1611 isdouble = true;
1612 else
1613 error ("sum: unrecognized string argument");
1614 nargin --;
1615 }
1616 }
1617
1618 if (error_state)
1619 return retval;
1620
1621 if (nargin == 1 || nargin == 2)
1622 {
1623 octave_value arg = args(0);
1624
1625 int dim = -1;
1626 if (nargin == 2)
1627 {
1628 dim = args(1).int_value () - 1;
1629 if (dim < 0)
1630 error ("cumsum: invalid dimension argument = %d", dim + 1);
1631 }
1632
1633 if (! error_state)
1634 {
1635 switch (arg.builtin_type ())
1636 {
1637 case btyp_double:
1638 if (arg.is_sparse_type ())
1639 retval = arg.sparse_matrix_value ().cumsum (dim);
1640 else
1641 retval = arg.array_value ().cumsum (dim);
1642 break;
1643 case btyp_complex:
1644 if (arg.is_sparse_type ())
1645 retval = arg.sparse_complex_matrix_value ().cumsum (dim);
1646 else
1647 retval = arg.complex_array_value ().cumsum (dim);
1648 break;
1649 case btyp_float:
1650 if (isdouble)
1651 retval = arg.array_value ().cumsum (dim);
1652 else
1653 retval = arg.float_array_value ().cumsum (dim);
1654 break;
1655 case btyp_float_complex:
1656 if (isdouble)
1657 retval = arg.complex_array_value ().cumsum (dim);
1658 else
1659 retval = arg.float_complex_array_value ().cumsum (dim);
1660 break;
1661
1662#define MAKE_INT_BRANCH(X) \
1663 case btyp_ ## X: \
1664 if (isnative) \
1665 retval = arg.X ## _array_value ().cumsum (dim); \
1666 else \
1667 retval = arg.array_value ().cumsum (dim); \
1668 break
1669 MAKE_INT_BRANCH (int8);
1670 MAKE_INT_BRANCH (int16);
1671 MAKE_INT_BRANCH (int32);
1672 MAKE_INT_BRANCH (int64);
1673 MAKE_INT_BRANCH (uint8);
1674 MAKE_INT_BRANCH (uint16);
1675 MAKE_INT_BRANCH (uint32);
1676 MAKE_INT_BRANCH (uint64);
1677#undef MAKE_INT_BRANCH
1678
1679 case btyp_bool:
1680 if (arg.is_sparse_type ())
1681 {
1682 SparseMatrix cs = arg.sparse_matrix_value ().cumsum (dim);
1683 if (isnative)
1684 retval = cs != 0.0;
1685 else
1686 retval = cs;
1687 }
1688 else
1689 {
1690 NDArray cs = arg.bool_array_value ().cumsum (dim);
1691 if (isnative)
1692 retval = cs != 0.0;
1693 else
1694 retval = cs;
1695 }
1696 break;
1697
1698 default:
1699 gripe_wrong_type_arg ("cumsum", arg);
1700 }
1701 }
1702 }
1703 else
1704 print_usage ();
1705
1706 return retval;
1707}
1708
1709/*
1710
1711%!assert (cumsum ([1, 2, 3]), [1, 3, 6]);
1712%!assert (cumsum ([-1; -2; -3]), [-1; -3; -6]);
1713%!assert (cumsum ([i, 2+i, -3+2i, 4]), [i, 2+2i, -1+4i, 3+4i]);
1714%!assert (cumsum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [1, 2, 3; 1+i, 2+2i, 3+3i; 2+2i, 4+4i, 6+6i]);
1715
1716%!assert (cumsum (single([1, 2, 3])), single([1, 3, 6]));
1717%!assert (cumsum (single([-1; -2; -3])), single([-1; -3; -6]));
1718%!assert (cumsum (single([i, 2+i, -3+2i, 4])), single([i, 2+2i, -1+4i, 3+4i]));
1719%!assert (cumsum (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([1, 2, 3; 1+i, 2+2i, 3+3i; 2+2i, 4+4i, 6+6i]));
1720
1721%!error <Invalid call to cumsum.*> cumsum ();
1722
1723%!assert (cumsum ([1, 2; 3, 4], 1), [1, 2; 4, 6]);
1724%!assert (cumsum ([1, 2; 3, 4], 2), [1, 3; 3, 7]);
1725
1726%!assert (cumsum (single([1, 2; 3, 4]), 1), single([1, 2; 4, 6]));
1727%!assert (cumsum (single([1, 2; 3, 4]), 2), single([1, 3; 3, 7]));
1728
1729 */
1730
1731DEFUN (diag, args, ,
1732 "-*- texinfo -*-\n\
1733@deftypefn {Built-in Function} {} diag (@var{v}, @var{k})\n\
1734Return a diagonal matrix with vector @var{v} on diagonal @var{k}. The\n\
1735second argument is optional. If it is positive, the vector is placed on\n\
1736the @var{k}-th super-diagonal. If it is negative, it is placed on the\n\
1737@var{-k}-th sub-diagonal. The default value of @var{k} is 0, and the\n\
1738vector is placed on the main diagonal. For example,\n\
1739\n\
1740@example\n\
1741@group\n\
1742diag ([1, 2, 3], 1)\n\
1743 @result{} 0 1 0 0\n\
1744 0 0 2 0\n\
1745 0 0 0 3\n\
1746 0 0 0 0\n\
1747@end group\n\
1748@end example\n\
1749\n\
1750@noindent\n\
1751Given a matrix argument, instead of a vector, @code{diag} extracts the\n\
1752@var{k}-th diagonal of the matrix.\n\
1753@end deftypefn")
1754{
1755 octave_value retval;
1756
1757 int nargin = args.length ();
1758
1759 if (nargin == 1 && args(0).is_defined ())
1760 retval = args(0).diag();
1761 else if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
1762 {
1763 octave_idx_type k = args(1).int_value ();
1764
1765 if (error_state)
1766 error ("diag: invalid second argument");
1767 else
1768 retval = args(0).diag(k);
1769 }
1770 else if (nargin == 3)
1771 {
1772 octave_value arg0 = args(0);
1773 if (arg0.ndims () == 2 && (args(0).rows () == 1 || args(0).columns () == 1))
1774 {
1775 octave_idx_type m = args(1).int_value (), n = args(2).int_value ();
1776 if (! error_state)
1777 retval = arg0.diag ().resize (dim_vector (m, n));
1778 else
1779 error ("diag: invalid dimensions");
1780 }
1781 else
1782 error ("diag: first argument must be a vector");
1783 }
1784 else
1785 print_usage ();
1786
1787 return retval;
1788}
1789
1790/*
1791
1792%!assert(full (diag ([1; 2; 3])), [1, 0, 0; 0, 2, 0; 0, 0, 3]);
1793%!assert(diag ([1; 2; 3], 1), [0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]);
1794%!assert(diag ([1; 2; 3], 2), [0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]);
1795%!assert(diag ([1; 2; 3],-1), [0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]);
1796%!assert(diag ([1; 2; 3],-2), [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0]);
1797
1798%!assert(diag ([1, 0, 0; 0, 2, 0; 0, 0, 3]), [1; 2; 3]);
1799%!assert(diag ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0], 1), [1; 2; 3]);
1800%!assert(diag ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0], -1), [1; 2; 3]);
1801
1802%!assert(full (diag (single([1; 2; 3]))), single([1, 0, 0; 0, 2, 0; 0, 0, 3]));
1803%!assert(diag (single([1; 2; 3]), 1), single([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]));
1804%!assert(diag (single([1; 2; 3]), 2), single([0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]));
1805%!assert(diag (single([1; 2; 3]),-1), single([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]));
1806%!assert(diag (single([1; 2; 3]),-2), single([0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0]));
1807
1808%!assert(diag (single([1, 0, 0; 0, 2, 0; 0, 0, 3])), single([1; 2; 3]));
1809%!assert(diag (single([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), single([1; 2; 3]));
1810%!assert(diag (single([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), single([1; 2; 3]));
1811
1812%!assert(diag (int8([1; 2; 3])), int8([1, 0, 0; 0, 2, 0; 0, 0, 3]));
1813%!assert(diag (int8([1; 2; 3]), 1), int8([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]));
1814%!assert(diag (int8([1; 2; 3]), 2), int8([0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]));
1815%!assert(diag (int8([1; 2; 3]),-1), int8([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]));
1816%!assert(diag (int8([1; 2; 3]),-2), int8([0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0]));
1817
1818%!assert(diag (int8([1, 0, 0; 0, 2, 0; 0, 0, 3])), int8([1; 2; 3]));
1819%!assert(diag (int8([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), int8([1; 2; 3]));
1820%!assert(diag (int8([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), int8([1; 2; 3]));
1821
1822%!error <Invalid call to diag.*> diag ();
1823
1824 */
1825
1826DEFUN (prod, args, ,
1827 "-*- texinfo -*-\n\
1828@deftypefn {Built-in Function} {} prod (@var{x})\n\
1829@deftypefnx {Built-in Function} {} prod (@var{x}, @var{dim})\n\
1830Product of elements along dimension @var{dim}. If @var{dim} is\n\
1831omitted, it defaults to the first non-singleton dimension.\n\
1832@seealso{cumprod, sum}\n\
1833@end deftypefn")
1834{
1835 DATA_REDUCTION (prod);
1836}
1837
1838/*
1839
1840%!assert (prod ([1, 2, 3]), 6);
1841%!assert (prod ([-1; -2; -3]), -6);
1842%!assert (prod ([i, 2+i, -3+2i, 4]), -4 - 32i);
1843%!assert (prod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [-1+i, -8+8i, -27+27i]);
1844
1845%!assert (prod (single([1, 2, 3])), single(6));
1846%!assert (prod (single([-1; -2; -3])), single(-6));
1847%!assert (prod (single([i, 2+i, -3+2i, 4])), single(-4 - 32i));
1848%!assert (prod (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([-1+i, -8+8i, -27+27i]));
1849
1850%!error <Invalid call to prod.*> prod ();
1851
1852%!assert (prod ([1, 2; 3, 4], 1), [3, 8]);
1853%!assert (prod ([1, 2; 3, 4], 2), [2; 12]);
1854%!assert (prod (zeros (1, 0)), 1);
1855%!assert (prod (zeros (1, 0), 1), zeros (1, 0));
1856%!assert (prod (zeros (1, 0), 2), 1);
1857%!assert (prod (zeros (0, 1)), 1);
1858%!assert (prod (zeros (0, 1), 1), 1);
1859%!assert (prod (zeros (0, 1), 2), zeros (0, 1));
1860%!assert (prod (zeros (2, 0)), zeros (1, 0));
1861%!assert (prod (zeros (2, 0), 1), zeros (1, 0));
1862%!assert (prod (zeros (2, 0), 2), [1; 1]);
1863%!assert (prod (zeros (0, 2)), [1, 1]);
1864%!assert (prod (zeros (0, 2), 1), [1, 1]);
1865%!assert (prod (zeros (0, 2), 2), zeros(0, 1));
1866
1867%!assert (prod (single([1, 2; 3, 4]), 1), single([3, 8]));
1868%!assert (prod (single([1, 2; 3, 4]), 2), single([2; 12]));
1869%!assert (prod (zeros (1, 0, 'single')), single(1));
1870%!assert (prod (zeros (1, 0, 'single'), 1), zeros (1, 0, 'single'));
1871%!assert (prod (zeros (1, 0, 'single'), 2), single(1));
1872%!assert (prod (zeros (0, 1, 'single')), single(1));
1873%!assert (prod (zeros (0, 1, 'single'), 1), single(1));
1874%!assert (prod (zeros (0, 1, 'single'), 2), zeros (0, 1, 'single'));
1875%!assert (prod (zeros (2, 0, 'single')), zeros (1, 0, 'single'));
1876%!assert (prod (zeros (2, 0, 'single'), 1), zeros (1, 0, 'single'));
1877%!assert (prod (zeros (2, 0, 'single'), 2), single([1; 1]));
1878%!assert (prod (zeros (0, 2, 'single')), single([1, 1]));
1879%!assert (prod (zeros (0, 2, 'single'), 1), single([1, 1]));
1880%!assert (prod (zeros (0, 2, 'single'), 2), zeros(0, 1, 'single'));
1881
1882 */
1883
1884#define SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR) \
1885 do \
1886 { \
1887 int dv_len = dv.length (); \
1888 Array<octave_idx_type> ra_idx (dv_len > 1 ? dv_len : 2, 0); \
1889 \
1890 for (int j = 1; j < n_args; j++) \
1891 { \
1892 OCTAVE_QUIT; \
1893 \
1894 TYPE ra = args(j).EXTRACTOR (); \
1895 \
1896 if (! error_state) \
1897 { \
1898 result.insert (ra, ra_idx); \
1899 \
1900 if (error_state) \
1901 return retval; \
1902 \
1903 dim_vector dv_tmp = args (j).dims (); \
1904 \
1905 if (dim >= dv_len) \
1906 { \
1907 if (j > 1) \
1908 error ("%s: indexing error", fname.c_str ()); \
1909 break; \
1910 } \
1911 else \
1912 ra_idx (dim) += (dim < dv_tmp.length () ? dv_tmp (dim) : 1); \
1913 } \
1914 } \
1915 } \
1916 while (0)
1917
1918#define DO_SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR) \
1919 do \
1920 { \
1921 TYPE result (dv); \
1922 \
1923 SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR); \
1924 \
1925 retval = result; \
1926 } \
1927 while (0)
1928
1929static octave_value
1930do_cat (const octave_value_list& args, std::string fname)
1931{
1932 octave_value retval;
1933
1934 int n_args = args.length ();
1935
1936 if (n_args == 1)
1937 retval = Matrix ();
1938 else if (n_args == 2)
1939 retval = args(1);
1940 else if (n_args > 2)
1941 {
1942 octave_idx_type dim = args(0).int_value () - 1;
1943
1944 if (error_state)
1945 {
1946 error ("cat: expecting first argument to be a integer");
1947 return retval;
1948 }
1949
1950 if (dim >= 0)
1951 {
1952
1953 dim_vector dv = args(1).dims ();
1954 std::string result_type = args(1).class_name ();
1955
1956 bool all_sq_strings_p = args(1).is_sq_string ();
1957 bool all_dq_strings_p = args(1).is_dq_string ();
1958 bool all_real_p = args(1).is_real_type ();
1959 bool any_sparse_p = args(1).is_sparse_type();
1960
1961 for (int i = 2; i < args.length (); i++)
1962 {
1963 // add_dims constructs a dimension vector which holds the
1964 // dimensions of the final array after concatenation.
1965
1966 if (! dv.concat (args(i).dims (), dim))
1967 {
1968 // Dimensions do not match.
1969 error ("cat: dimension mismatch");
1970 return retval;
1971 }
1972
1973 result_type =
1974 get_concat_class (result_type, args(i).class_name ());
1975
1976 if (all_sq_strings_p && ! args(i).is_sq_string ())
1977 all_sq_strings_p = false;
1978 if (all_dq_strings_p && ! args(i).is_dq_string ())
1979 all_dq_strings_p = false;
1980 if (all_real_p && ! args(i).is_real_type ())
1981 all_real_p = false;
1982 if (!any_sparse_p && args(i).is_sparse_type ())
1983 any_sparse_p = true;
1984 }
1985
1986 if (result_type == "double")
1987 {
1988 if (any_sparse_p)
1989 {
1990 if (all_real_p)
1991 DO_SINGLE_TYPE_CONCAT (SparseMatrix, sparse_matrix_value);
1992 else
1993 DO_SINGLE_TYPE_CONCAT (SparseComplexMatrix, sparse_complex_matrix_value);
1994 }
1995 else
1996 {
1997 if (all_real_p)
1998 DO_SINGLE_TYPE_CONCAT (NDArray, array_value);
1999 else
2000 DO_SINGLE_TYPE_CONCAT (ComplexNDArray, complex_array_value);
2001 }
2002 }
2003 else if (result_type == "single")
2004 {
2005 if (all_real_p)
2006 DO_SINGLE_TYPE_CONCAT (FloatNDArray, float_array_value);
2007 else
2008 DO_SINGLE_TYPE_CONCAT (FloatComplexNDArray,
2009 float_complex_array_value);
2010 }
2011 else if (result_type == "char")
2012 {
2013 char type = all_dq_strings_p ? '"' : '\'';
2014
2015 maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
2016
2017 charNDArray result (dv, Vstring_fill_char);
2018
2019 SINGLE_TYPE_CONCAT (charNDArray, char_array_value);
2020
2021 retval = octave_value (result, type);
2022 }
2023 else if (result_type == "logical")
2024 {
2025 if (any_sparse_p)
2026 DO_SINGLE_TYPE_CONCAT (SparseBoolMatrix, sparse_bool_matrix_value);
2027 else
2028 DO_SINGLE_TYPE_CONCAT (boolNDArray, bool_array_value);
2029 }
2030 else if (result_type == "int8")
2031 DO_SINGLE_TYPE_CONCAT (int8NDArray, int8_array_value);
2032 else if (result_type == "int16")
2033 DO_SINGLE_TYPE_CONCAT (int16NDArray, int16_array_value);
2034 else if (result_type == "int32")
2035 DO_SINGLE_TYPE_CONCAT (int32NDArray, int32_array_value);
2036 else if (result_type == "int64")
2037 DO_SINGLE_TYPE_CONCAT (int64NDArray, int64_array_value);
2038 else if (result_type == "uint8")
2039 DO_SINGLE_TYPE_CONCAT (uint8NDArray, uint8_array_value);
2040 else if (result_type == "uint16")
2041 DO_SINGLE_TYPE_CONCAT (uint16NDArray, uint16_array_value);
2042 else if (result_type == "uint32")
2043 DO_SINGLE_TYPE_CONCAT (uint32NDArray, uint32_array_value);
2044 else if (result_type == "uint64")
2045 DO_SINGLE_TYPE_CONCAT (uint64NDArray, uint64_array_value);
2046 else
2047 {
2048 // The lines below might seem crazy, since we take a copy
2049 // of the first argument, resize it to be empty and then resize
2050 // it to be full. This is done since it means that there is no
2051 // recopying of data, as would happen if we used a single resize.
2052 // It should be noted that resize operation is also significantly
2053 // slower than the do_cat_op function, so it makes sense to have
2054 // an empty matrix and copy all data.
2055 //
2056 // We might also start with a empty octave_value using
2057 // tmp = octave_value_typeinfo::lookup_type
2058 // (args(1).type_name());
2059 // and then directly resize. However, for some types there might
2060 // be some additional setup needed, and so this should be avoided.
2061
2062 octave_value tmp = args (1);
2063 tmp = tmp.resize (dim_vector (0,0)).resize (dv);
2064
2065 if (error_state)
2066 return retval;
2067
2068 int dv_len = dv.length ();
2069 Array<octave_idx_type> ra_idx (dv_len, 0);
2070
2071 for (int j = 1; j < n_args; j++)
2072 {
2073 // Can't fast return here to skip empty matrices as something
2074 // like cat(1,[],single([])) must return an empty matrix of
2075 // the right type.
2076 tmp = do_cat_op (tmp, args (j), ra_idx);
2077
2078 if (error_state)
2079 return retval;
2080
2081 dim_vector dv_tmp = args (j).dims ();
2082
2083 if (dim >= dv_len)
2084 {
2085 if (j > 1)
2086 error ("%s: indexing error", fname.c_str ());
2087 break;
2088 }
2089 else
2090 ra_idx (dim) += (dim < dv_tmp.length () ?
2091 dv_tmp (dim) : 1);
2092 }
2093 retval = tmp;
2094 }
2095
2096 if (! error_state)
2097 {
2098 // Reshape, chopping trailing singleton dimensions
2099 dv.chop_trailing_singletons ();
2100 retval = retval.reshape (dv);
2101 }
2102 }
2103 else
2104 error ("%s: invalid dimension argument", fname.c_str ());
2105 }
2106 else
2107 print_usage ();
2108
2109 return retval;
2110}
2111
2112DEFUN (horzcat, args, ,
2113 "-*- texinfo -*-\n\
2114@deftypefn {Built-in Function} {} horzcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2115Return the horizontal concatenation of N-d array objects, @var{array1},\n\
2116@var{array2}, @dots{}, @var{arrayN} along dimension 2.\n\
2117@seealso{cat, vertcat}\n\
2118@end deftypefn")
2119{
2120 octave_value_list args_tmp = args;
2121
2122 int dim = 2;
2123
2124 octave_value d (dim);
2125
2126 args_tmp.prepend (d);
2127
2128 return do_cat (args_tmp, "horzcat");
2129}
2130
2131DEFUN (vertcat, args, ,
2132 "-*- texinfo -*-\n\
2133@deftypefn {Built-in Function} {} vertcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2134Return the vertical concatenation of N-d array objects, @var{array1},\n\
2135@var{array2}, @dots{}, @var{arrayN} along dimension 1.\n\
2136@seealso{cat, horzcat}\n\
2137@end deftypefn")
2138{
2139 octave_value_list args_tmp = args;
2140
2141 int dim = 1;
2142
2143 octave_value d (dim);
2144
2145 args_tmp.prepend (d);
2146
2147 return do_cat (args_tmp, "vertcat");
2148}
2149
2150DEFUN (cat, args, ,
2151 "-*- texinfo -*-\n\
2152@deftypefn {Built-in Function} {} cat (@var{dim}, @var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2153Return the concatenation of N-d array objects, @var{array1},\n\
2154@var{array2}, @dots{}, @var{arrayN} along dimension @var{dim}.\n\
2155\n\
2156@example\n\
2157@group\n\
2158A = ones (2, 2);\n\
2159B = zeros (2, 2);\n\
2160cat (2, A, B)\n\
2161@result{} ans =\n\
2162\n\
2163 1 1 0 0\n\
2164 1 1 0 0\n\
2165@end group\n\
2166@end example\n\
2167\n\
2168Alternatively, we can concatenate @var{A} and @var{B} along the\n\
2169second dimension the following way:\n\
2170\n\
2171@example\n\
2172@group\n\
2173[A, B].\n\
2174@end group\n\
2175@end example\n\
2176\n\
2177@var{dim} can be larger than the dimensions of the N-d array objects\n\
2178and the result will thus have @var{dim} dimensions as the\n\
2179following example shows:\n\
2180@example\n\
2181@group\n\
2182cat (4, ones(2, 2), zeros (2, 2))\n\
2183@result{} ans =\n\
2184\n\
2185 ans(:,:,1,1) =\n\
2186\n\
2187 1 1\n\
2188 1 1\n\
2189\n\
2190 ans(:,:,1,2) =\n\
2191 0 0\n\
2192 0 0\n\
2193@end group\n\
2194@end example\n\
2195@seealso{horzcat, vertcat}\n\
2196@end deftypefn")
2197{
2198 return do_cat (args, "cat");
2199}
2200
2201/*
2202
2203%!function ret = testcat (t1, t2, tr, cmplx)
2204%! assert (cat (1, cast ([], t1), cast([], t2)), cast ([], tr));
2205%!
2206%! assert (cat (1, cast (1, t1), cast (2, t2)), cast ([1; 2], tr));
2207%! assert (cat (1, cast (1, t1), cast ([2; 3], t2)), cast ([1; 2; 3], tr));
2208%! assert (cat (1, cast ([1; 2], t1), cast (3, t2)), cast ([1; 2; 3], tr));
2209%! assert (cat (1, cast ([1; 2], t1), cast ([3; 4], t2)), cast ([1; 2; 3; 4], tr));
2210%! assert (cat (2, cast (1, t1), cast (2, t2)), cast ([1, 2], tr));
2211%! assert (cat (2, cast (1, t1), cast ([2, 3], t2)), cast ([1, 2, 3], tr));
2212%! assert (cat (2, cast ([1, 2], t1), cast (3, t2)), cast ([1, 2, 3], tr));
2213%! assert (cat (2, cast ([1, 2], t1), cast ([3, 4], t2)), cast ([1, 2, 3, 4], tr));
2214%!
2215%! assert ([cast(1, t1); cast(2, t2)], cast ([1; 2], tr));
2216%! assert ([cast(1, t1); cast([2; 3], t2)], cast ([1; 2; 3], tr));
2217%! assert ([cast([1; 2], t1); cast(3, t2)], cast ([1; 2; 3], tr));
2218%! assert ([cast([1; 2], t1); cast([3; 4], t2)], cast ([1; 2; 3; 4], tr));
2219%! assert ([cast(1, t1), cast(2, t2)], cast ([1, 2], tr));
2220%! assert ([cast(1, t1), cast([2, 3], t2)], cast ([1, 2, 3], tr));
2221%! assert ([cast([1, 2], t1), cast(3, t2)], cast ([1, 2, 3], tr));
2222%! assert ([cast([1, 2], t1), cast([3, 4], t2)], cast ([1, 2, 3, 4], tr));
2223%!
2224%! if (nargin == 3 || cmplx)
2225%! assert (cat (1, cast (1i, t1), cast (2, t2)), cast ([1i; 2], tr));
2226%! assert (cat (1, cast (1i, t1), cast ([2; 3], t2)), cast ([1i; 2; 3], tr));
2227%! assert (cat (1, cast ([1i; 2], t1), cast (3, t2)), cast ([1i; 2; 3], tr));
2228%! assert (cat (1, cast ([1i; 2], t1), cast ([3; 4], t2)), cast ([1i; 2; 3; 4], tr));
2229%! assert (cat (2, cast (1i, t1), cast (2, t2)), cast ([1i, 2], tr));
2230%! assert (cat (2, cast (1i, t1), cast ([2, 3], t2)), cast ([1i, 2, 3], tr));
2231%! assert (cat (2, cast ([1i, 2], t1), cast (3, t2)), cast ([1i, 2, 3], tr));
2232%! assert (cat (2, cast ([1i, 2], t1), cast ([3, 4], t2)), cast ([1i, 2, 3, 4], tr));
2233%!
2234%! assert ([cast(1i, t1); cast(2, t2)], cast ([1i; 2], tr));
2235%! assert ([cast(1i, t1); cast([2; 3], t2)], cast ([1i; 2; 3], tr));
2236%! assert ([cast([1i; 2], t1); cast(3, t2)], cast ([1i; 2; 3], tr));
2237%! assert ([cast([1i; 2], t1); cast([3; 4], t2)], cast ([1i; 2; 3; 4], tr));
2238%! assert ([cast(1i, t1), cast(2, t2)], cast ([1i, 2], tr));
2239%! assert ([cast(1i, t1), cast([2, 3], t2)], cast ([1i, 2, 3], tr));
2240%! assert ([cast([1i, 2], t1), cast(3, t2)], cast ([1i, 2, 3], tr));
2241%! assert ([cast([1i, 2], t1), cast([3, 4], t2)], cast ([1i, 2, 3, 4], tr));
2242%!
2243%! assert (cat (1, cast (1, t1), cast (2i, t2)), cast ([1; 2i], tr));
2244%! assert (cat (1, cast (1, t1), cast ([2i; 3], t2)), cast ([1; 2i; 3], tr));
2245%! assert (cat (1, cast ([1; 2], t1), cast (3i, t2)), cast ([1; 2; 3i], tr));
2246%! assert (cat (1, cast ([1; 2], t1), cast ([3i; 4], t2)), cast ([1; 2; 3i; 4], tr));
2247%! assert (cat (2, cast (1, t1), cast (2i, t2)), cast ([1, 2i], tr));
2248%! assert (cat (2, cast (1, t1), cast ([2i, 3], t2)), cast ([1, 2i, 3], tr));
2249%! assert (cat (2, cast ([1, 2], t1), cast (3i, t2)), cast ([1, 2, 3i], tr));
2250%! assert (cat (2, cast ([1, 2], t1), cast ([3i, 4], t2)), cast ([1, 2, 3i, 4], tr));
2251%!
2252%! assert ([cast(1, t1); cast(2i, t2)], cast ([1; 2i], tr));
2253%! assert ([cast(1, t1); cast([2i; 3], t2)], cast ([1; 2i; 3], tr));
2254%! assert ([cast([1; 2], t1); cast(3i, t2)], cast ([1; 2; 3i], tr));
2255%! assert ([cast([1; 2], t1); cast([3i; 4], t2)], cast ([1; 2; 3i; 4], tr));
2256%! assert ([cast(1, t1), cast(2i, t2)], cast ([1, 2i], tr));
2257%! assert ([cast(1, t1), cast([2i, 3], t2)], cast ([1, 2i, 3], tr));
2258%! assert ([cast([1, 2], t1), cast(3i, t2)], cast ([1, 2, 3i], tr));
2259%! assert ([cast([1, 2], t1), cast([3i, 4], t2)], cast ([1, 2, 3i, 4], tr));
2260%!
2261%! assert (cat (1, cast (1i, t1), cast (2i, t2)), cast ([1i; 2i], tr));
2262%! assert (cat (1, cast (1i, t1), cast ([2i; 3], t2)), cast ([1i; 2i; 3], tr));
2263%! assert (cat (1, cast ([1i; 2], t1), cast (3i, t2)), cast ([1i; 2; 3i], tr));
2264%! assert (cat (1, cast ([1i; 2], t1), cast ([3i; 4], t2)), cast ([1i; 2; 3i; 4], tr));
2265%! assert (cat (2, cast (1i, t1), cast (2i, t2)), cast ([1i, 2i], tr));
2266%! assert (cat (2, cast (1i, t1), cast ([2i, 3], t2)), cast ([1i, 2i, 3], tr));
2267%! assert (cat (2, cast ([1i, 2], t1), cast (3i, t2)), cast ([1i, 2, 3i], tr));
2268%! assert (cat (2, cast ([1i, 2], t1), cast ([3i, 4], t2)), cast ([1i, 2, 3i, 4], tr));
2269%!
2270%! assert ([cast(1i, t1); cast(2i, t2)], cast ([1i; 2i], tr));
2271%! assert ([cast(1i, t1); cast([2i; 3], t2)], cast ([1i; 2i; 3], tr));
2272%! assert ([cast([1i; 2], t1); cast(3i, t2)], cast ([1i; 2; 3i], tr));
2273%! assert ([cast([1i; 2], t1); cast([3i; 4], t2)], cast ([1i; 2; 3i; 4], tr));
2274%! assert ([cast(1i, t1), cast(2i, t2)], cast ([1i, 2i], tr));
2275%! assert ([cast(1i, t1), cast([2i, 3], t2)], cast ([1i, 2i, 3], tr));
2276%! assert ([cast([1i, 2], t1), cast(3i, t2)], cast ([1i, 2, 3i], tr));
2277%! assert ([cast([1i, 2], t1), cast([3i, 4], t2)], cast ([1i, 2, 3i, 4], tr));
2278%! endif
2279%! ret = true;
2280
2281%!assert (testcat('double', 'double', 'double'));
2282%!assert (testcat('single', 'double', 'single'));
2283%!assert (testcat('double', 'single', 'single'));
2284%!assert (testcat('single', 'single', 'single'));
2285
2286%!assert (testcat('double', 'int8', 'int8', false));
2287%!assert (testcat('int8', 'double', 'int8', false));
2288%!assert (testcat('single', 'int8', 'int8', false));
2289%!assert (testcat('int8', 'single', 'int8', false));
2290%!assert (testcat('int8', 'int8', 'int8', false));
2291%!assert (testcat('double', 'int16', 'int16', false));
2292%!assert (testcat('int16', 'double', 'int16', false));
2293%!assert (testcat('single', 'int16', 'int16', false));
2294%!assert (testcat('int16', 'single', 'int16', false));
2295%!assert (testcat('int16', 'int16', 'int16', false));
2296%!assert (testcat('double', 'int32', 'int32', false));
2297%!assert (testcat('int32', 'double', 'int32', false));
2298%!assert (testcat('single', 'int32', 'int32', false));
2299%!assert (testcat('int32', 'single', 'int32', false));
2300%!assert (testcat('int32', 'int32', 'int32', false));
2301%!assert (testcat('double', 'int64', 'int64', false));
2302%!assert (testcat('int64', 'double', 'int64', false));
2303%!assert (testcat('single', 'int64', 'int64', false));
2304%!assert (testcat('int64', 'single', 'int64', false));
2305%!assert (testcat('int64', 'int64', 'int64', false));
2306
2307%!assert (testcat('double', 'uint8', 'uint8', false));
2308%!assert (testcat('uint8', 'double', 'uint8', false));
2309%!assert (testcat('single', 'uint8', 'uint8', false));
2310%!assert (testcat('uint8', 'single', 'uint8', false));
2311%!assert (testcat('uint8', 'uint8', 'uint8', false));
2312%!assert (testcat('double', 'uint16', 'uint16', false));
2313%!assert (testcat('uint16', 'double', 'uint16', false));
2314%!assert (testcat('single', 'uint16', 'uint16', false));
2315%!assert (testcat('uint16', 'single', 'uint16', false));
2316%!assert (testcat('uint16', 'uint16', 'uint16', false));
2317%!assert (testcat('double', 'uint32', 'uint32', false));
2318%!assert (testcat('uint32', 'double', 'uint32', false));
2319%!assert (testcat('single', 'uint32', 'uint32', false));
2320%!assert (testcat('uint32', 'single', 'uint32', false));
2321%!assert (testcat('uint32', 'uint32', 'uint32', false));
2322%!assert (testcat('double', 'uint64', 'uint64', false));
2323%!assert (testcat('uint64', 'double', 'uint64', false));
2324%!assert (testcat('single', 'uint64', 'uint64', false));
2325%!assert (testcat('uint64', 'single', 'uint64', false));
2326%!assert (testcat('uint64', 'uint64', 'uint64', false));
2327
2328*/
2329
2330static octave_value
2331do_permute (const octave_value_list& args, bool inv)
2332{
2333 octave_value retval;
2334
2335 if (args.length () == 2 && args(1).length () >= args(1).ndims ())
2336 {
2337 Array<int> vec = args(1).int_vector_value ();
2338
2339 // FIXME -- maybe we should create an idx_vector object
2340 // here and pass that to permute?
2341
2342 int n = vec.length ();
2343
2344 for (int i = 0; i < n; i++)
2345 vec(i)--;
2346
2347 octave_value ret = args(0).permute (vec, inv);
2348
2349 if (! error_state)
2350 retval = ret;
2351 }
2352 else
2353 print_usage ();
2354
2355 return retval;
2356}
2357
2358DEFUN (permute, args, ,
2359 "-*- texinfo -*-\n\
2360@deftypefn {Built-in Function} {} permute (@var{a}, @var{perm})\n\
2361Return the generalized transpose for an N-d array object @var{a}.\n\
2362The permutation vector @var{perm} must contain the elements\n\
2363@code{1:ndims(a)} (in any order, but each element must appear just once).\n\
2364@seealso{ipermute}\n\
2365@end deftypefn")
2366{
2367 return do_permute (args, false);
2368}
2369
2370DEFUN (ipermute, args, ,
2371 "-*- texinfo -*-\n\
2372@deftypefn {Built-in Function} {} ipermute (@var{a}, @var{iperm})\n\
2373The inverse of the @code{permute} function. The expression\n\
2374\n\
2375@example\n\
2376ipermute (permute (a, perm), perm)\n\
2377@end example\n\
2378returns the original array @var{a}.\n\
2379@seealso{permute}\n\
2380@end deftypefn")
2381{
2382 return do_permute (args, true);
2383}
2384
2385DEFUN (length, args, ,
2386 "-*- texinfo -*-\n\
2387@deftypefn {Built-in Function} {} length (@var{a})\n\
2388Return the `length' of the object @var{a}. For matrix objects, the\n\
2389length is the number of rows or columns, whichever is greater (this\n\
2390odd definition is used for compatibility with @sc{matlab}).\n\
2391@end deftypefn")
2392{
2393 octave_value retval;
2394
2395 if (args.length () == 1)
2396 retval = args(0).length ();
2397 else
2398 print_usage ();
2399
2400 return retval;
2401}
2402
2403DEFUN (ndims, args, ,
2404 "-*- texinfo -*-\n\
2405@deftypefn {Built-in Function} {} ndims (@var{a})\n\
2406Returns the number of dimensions of array @var{a}.\n\
2407For any array, the result will always be larger than or equal to 2.\n\
2408Trailing singleton dimensions are not counted.\n\
2409@end deftypefn")
2410{
2411 octave_value retval;
2412
2413 if (args.length () == 1)
2414 retval = args(0).ndims ();
2415 else
2416 print_usage ();
2417
2418 return retval;
2419}
2420
2421DEFUN (numel, args, ,
2422 "-*- texinfo -*-\n\
2423@deftypefn {Built-in Function} {} numel (@var{a})\n\
2424@deftypefnx {Built-in Function} {} numel (@var{a}, @var{idx1}, @var{idx2}, @dots{})\n\
2425Returns the number of elements in the object @var{a}.\n\
2426Optionally, if indices @var{idx1}, @var{idx2}, @dots{} are supplied,\n\
2427return the number of elements that would result from the indexing\n\
2428@example\n\
2429 @var{a}(@var{idx1}, @var{idx2}, @dots{})\n\
2430@end example\n\
2431This method is also called when an object appears as lvalue with cs-list\n\
2432indexing, i.e., @code{object@{@dots{}@}} or @code{object(@dots{}).field}.\n\
2433@seealso{size}\n\
2434@end deftypefn")
2435{
2436 octave_value retval;
2437 octave_idx_type nargin = args.length ();
2438
2439 if (nargin == 1)
2440 retval = args(0).numel ();
2441 else if (nargin > 1)
2442 {
2443 // Don't use numel (const octave_value_list&) here as that corresponds to
2444 // an overloaded call, not to builtin!
2445 retval = dims_to_numel (args(0).dims (), args.slice (1, nargin-1));
2446 }
2447 else
2448 print_usage ();
2449
2450 return retval;
2451}
2452
2453DEFUN (size, args, nargout,
2454 "-*- texinfo -*-\n\
2455@deftypefn {Built-in Function} {} size (@var{a}, @var{n})\n\
2456Return the number rows and columns of @var{a}.\n\
2457\n\
2458With one input argument and one output argument, the result is returned\n\
2459in a row vector. If there are multiple output arguments, the number of\n\
2460rows is assigned to the first, and the number of columns to the second,\n\
2461etc. For example,\n\
2462\n\
2463@example\n\
2464@group\n\
2465size ([1, 2; 3, 4; 5, 6])\n\
2466 @result{} [ 3, 2 ]\n\
2467\n\
2468[nr, nc] = size ([1, 2; 3, 4; 5, 6])\n\
2469 @result{} nr = 3\n\
2470 @result{} nc = 2\n\
2471@end group\n\
2472@end example\n\
2473\n\
2474If given a second argument, @code{size} will return the size of the\n\
2475corresponding dimension. For example\n\
2476\n\
2477@example\n\
2478@group\n\
2479size ([1, 2; 3, 4; 5, 6], 2)\n\
2480 @result{} 2\n\
2481@end group\n\
2482@end example\n\
2483\n\
2484@noindent\n\
2485returns the number of columns in the given matrix.\n\
2486@seealso{numel}\n\
2487@end deftypefn")
2488{
2489 octave_value_list retval;
2490
2491 int nargin = args.length ();
2492
2493 if (nargin == 1)
2494 {
2495 const dim_vector dimensions = args(0).dims ();
2496
2497 if (nargout > 1)
2498 {
2499 const dim_vector rdims = dimensions.redim (nargout);
2500 retval.resize (nargout);
2501 for (int i = 0; i < nargout; i++)
2502 retval(i) = rdims(i);
2503 }
2504 else
2505 {
2506 int ndims = dimensions.length ();
2507
2508 NoAlias<Matrix> m (1, ndims);
2509
2510 for (int i = 0; i < ndims; i++)
2511 m(i) = dimensions(i);
2512
2513 retval(0) = m;
2514 }
2515 }
2516 else if (nargin == 2 && nargout < 2)
2517 {
2518 octave_idx_type nd = args(1).int_value (true);
2519
2520 if (error_state)
2521 error ("size: expecting scalar as second argument");
2522 else
2523 {
2524 const dim_vector dv = args(0).dims ();
2525
2526 if (nd > 0)
2527 {
2528 if (nd <= dv.length ())
2529 retval(0) = dv(nd-1);
2530 else
2531 retval(0) = 1;
2532 }
2533 else
2534 error ("size: requested dimension (= %d) out of range", nd);
2535 }
2536 }
2537 else
2538 print_usage ();
2539
2540 return retval;
2541}
2542
2543DEFUN (size_equal, args, ,
2544 "-*- texinfo -*-\n\
2545@deftypefn {Built-in Function} {} size_equal (@var{a}, @var{b}, @dots{})\n\
2546Return true if the dimensions of all arguments agree.\n\
2547Trailing singleton dimensions are ignored.\n\
2548Called with a single argument, size_equal returns true.\n\
2549@seealso{size, numel}\n\
2550@end deftypefn")
2551{
2552 octave_value retval;
2553
2554 int nargin = args.length ();
2555
2556 if (nargin >= 1)
2557 {
2558 retval = true;
2559
2560 dim_vector a_dims = args(0).dims ();
2561
2562 for (int i = 1; i < nargin; ++i)
2563 {
2564 dim_vector b_dims = args(i).dims ();
2565
2566 if (a_dims != b_dims)
2567 {
2568 retval = false;
2569 break;
2570 }
2571 }
2572 }
2573 else
2574 print_usage ();
2575
2576 return retval;
2577}
2578
2579DEFUN (nnz, args, ,
2580 "-*- texinfo -*-\n\
2581@deftypefn {Built-in Function} {@var{scalar} =} nnz (@var{a})\n\
2582Returns the number of non zero elements in @var{a}.\n\
2583@seealso{sparse}\n\
2584@end deftypefn")
2585{
2586 octave_value retval;
2587
2588 if (args.length () == 1)
2589 retval = args(0).nnz ();
2590 else
2591 print_usage ();
2592
2593 return retval;
2594}
2595
2596DEFUN (nzmax, args, ,
2597 "-*- texinfo -*-\n\
2598@deftypefn {Built-in Function} {@var{scalar} =} nzmax (@var{SM})\n\
2599Return the amount of storage allocated to the sparse matrix @var{SM}.\n\
2600Note that Octave tends to crop unused memory at the first opportunity\n\
2601for sparse objects. There are some cases of user created sparse objects\n\
2602where the value returned by @dfn{nzmax} will not be the same as @dfn{nnz},\n\
2603but in general they will give the same result.\n\
2604@seealso{sparse, spalloc}\n\
2605@end deftypefn")
2606{
2607 octave_value retval;
2608
2609 if (args.length() == 1)
2610 retval = args(0).nzmax ();
2611 else
2612 print_usage ();
2613
2614 return retval;
2615}
2616
2617DEFUN (rows, args, ,
2618 "-*- texinfo -*-\n\
2619@deftypefn {Built-in Function} {} rows (@var{a})\n\
2620Return the number of rows of @var{a}.\n\
2621@seealso{size, numel, columns, length, isscalar, isvector, ismatrix}\n\
2622@end deftypefn")
2623{
2624 octave_value retval;
2625
2626 if (args.length () == 1)
2627 retval = args(0).rows ();
2628 else
2629 print_usage ();
2630
2631 return retval;
2632}
2633
2634DEFUN (columns, args, ,
2635 "-*- texinfo -*-\n\
2636@deftypefn {Built-in Function} {} columns (@var{a})\n\
2637Return the number of columns of @var{a}.\n\
2638@seealso{size, numel, rows, length, isscalar, isvector, ismatrix}\n\
2639@end deftypefn")
2640{
2641 octave_value retval;
2642
2643 if (args.length () == 1)
2644 retval = args(0).columns ();
2645 else
2646 print_usage ();
2647
2648 return retval;
2649}
2650
2651DEFUN (sum, args, ,
2652 "-*- texinfo -*-\n\
2653@deftypefn {Built-in Function} {} sum (@var{x})\n\
2654@deftypefnx {Built-in Function} {} sum (@var{x}, @var{dim})\n\
2655@deftypefnx {Built-in Function} {} sum (@dots{}, 'native')\n\
2656@deftypefnx {Built-in Function} {} sum (@dots{}, 'double')\n\
2657@deftypefnx {Built-in Function} {} sum (@dots{}, 'extra')\n\
2658Sum of elements along dimension @var{dim}. If @var{dim} is\n\
2659omitted, it defaults to the first non-singleton dimension.\n\
2660\n\
2661If the optional argument 'native' is given, then the sum is performed\n\
2662in the same type as the original argument, rather than in the default\n\
2663double type. For example\n\
2664\n\
2665@example\n\
2666@group\n\
2667sum ([true, true])\n\
2668 @result{} 2\n\
2669sum ([true, true], 'native')\n\
2670 @result{} true\n\
2671@end group\n\
2672@end example\n\
2673 \n\
2674On the contrary, if 'double' is given, the sum is performed in double precision\n\
2675even for single precision inputs.\n\
2676\n\
2677For double precision inputs, 'extra' indicates that a more accurate algorithm\n\
2678than straightforward summation is to be used. For single precision inputs, 'extra' is\n\
2679the same as 'double'. Otherwise, 'extra' has no effect.\n\
2680@seealso{cumsum, sumsq, prod}\n\
2681@end deftypefn")
2682{
2683 octave_value retval;
2684
2685 int nargin = args.length ();
2686
2687 bool isnative = false;
2688 bool isdouble = false;
2689 bool isextra = false;
2690
2691 if (nargin > 1 && args(nargin - 1).is_string ())
2692 {
2693 std::string str = args(nargin - 1).string_value ();
2694
2695 if (! error_state)
2696 {
2697 if (str == "native")
2698 isnative = true;
2699 else if (str == "double")
2700 isdouble = true;
2701 else if (str == "extra")
2702 isextra = true;
2703 else
2704 error ("sum: unrecognized string argument");
2705 nargin --;
2706 }
2707 }
2708
2709 if (error_state)
2710 return retval;
2711
2712 if (nargin == 1 || nargin == 2)
2713 {
2714 octave_value arg = args(0);
2715
2716 int dim = -1;
2717 if (nargin == 2)
2718 {
2719 dim = args(1).int_value () - 1;
2720 if (dim < 0)
2721 error ("sum: invalid dimension argument = %d", dim + 1);
2722 }
2723
2724 if (! error_state)
2725 {
2726 switch (arg.builtin_type ())
2727 {
2728 case btyp_double:
2729 if (arg.is_sparse_type ())
2730 {
2731 if (isextra)
2732 warning ("sum: 'extra' not yet implemented for sparse matrices");
2733 retval = arg.sparse_matrix_value ().sum (dim);
2734 }
2735 else if (isextra)
2736 retval = arg.array_value ().xsum (dim);
2737 else
2738 retval = arg.array_value ().sum (dim);
2739 break;
2740 case btyp_complex:
2741 if (arg.is_sparse_type ())
2742 {
2743 if (isextra)
2744 warning ("sum: 'extra' not yet implemented for sparse matrices");
2745 retval = arg.sparse_complex_matrix_value ().sum (dim);
2746 }
2747 else if (isextra)
2748 retval = arg.complex_array_value ().xsum (dim);
2749 else
2750 retval = arg.complex_array_value ().sum (dim);
2751 break;
2752 case btyp_float:
2753 if (isdouble || isextra)
2754 retval = arg.float_array_value ().dsum (dim);
2755 else
2756 retval = arg.float_array_value ().sum (dim);
2757 break;
2758 case btyp_float_complex:
2759 if (isdouble || isextra)
2760 retval = arg.float_complex_array_value ().dsum (dim);
2761 else
2762 retval = arg.float_complex_array_value ().sum (dim);
2763 break;
2764
2765#define MAKE_INT_BRANCH(X) \
2766 case btyp_ ## X: \
2767 if (isnative) \
2768 retval = arg.X ## _array_value ().sum (dim); \
2769 else \
2770 retval = arg.X ## _array_value ().dsum (dim); \
2771 break
2772 MAKE_INT_BRANCH (int8);
2773 MAKE_INT_BRANCH (int16);
2774 MAKE_INT_BRANCH (int32);
2775 MAKE_INT_BRANCH (int64);
2776 MAKE_INT_BRANCH (uint8);
2777 MAKE_INT_BRANCH (uint16);
2778 MAKE_INT_BRANCH (uint32);
2779 MAKE_INT_BRANCH (uint64);
2780#undef MAKE_INT_BRANCH
2781
2782 case btyp_bool:
2783 if (arg.is_sparse_type ())
2784 {
2785 if (isnative)
2786 retval = arg.sparse_bool_matrix_value ().any (dim);
2787 else
2788 retval = arg.sparse_matrix_value ().sum (dim);
2789 }
2790 else if (isnative)
2791 retval = arg.bool_array_value ().any (dim);
2792 else
2793 retval = arg.bool_array_value ().sum (dim);
2794 break;
2795
2796 default:
2797 gripe_wrong_type_arg ("sum", arg);
2798 }
2799 }
2800 }
2801 else
2802 print_usage ();
2803
2804 return retval;
2805}
2806
2807/*
2808
2809%!assert (sum([true,true]), 2)
2810%!assert (sum([true,true],'native'), true)
2811%!assert (sum(int8([127,10,-20])), 117);
2812%!assert (sum(int8([127,10,-20]),'native'), int8(107));
2813
2814%!assert(sum ([1, 2, 3]), 6)
2815%!assert(sum ([-1; -2; -3]), -6);
2816%!assert(sum ([i, 2+i, -3+2i, 4]), 3+4i);
2817%!assert(sum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [2+2i, 4+4i, 6+6i]);
2818
2819%!assert(sum (single([1, 2, 3])), single(6))
2820%!assert(sum (single([-1; -2; -3])), single(-6));
2821%!assert(sum (single([i, 2+i, -3+2i, 4])), single(3+4i));
2822%!assert(sum (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([2+2i, 4+4i, 6+6i]));
2823
2824%!error <Invalid call to sum.*> sum ();
2825
2826%!assert (sum ([1, 2; 3, 4], 1), [4, 6]);
2827%!assert (sum ([1, 2; 3, 4], 2), [3; 7]);
2828%!assert (sum (zeros (1, 0)), 0);
2829%!assert (sum (zeros (1, 0), 1), zeros(1, 0));
2830%!assert (sum (zeros (1, 0), 2), 0);
2831%!assert (sum (zeros (0, 1)), 0);
2832%!assert (sum (zeros (0, 1), 1), 0);
2833%!assert (sum (zeros (0, 1), 2), zeros(0, 1));
2834%!assert (sum (zeros (2, 0)), zeros(1, 0));
2835%!assert (sum (zeros (2, 0), 1), zeros(1, 0));
2836%!assert (sum (zeros (2, 0), 2), [0; 0]);
2837%!assert (sum (zeros (0, 2)), [0, 0]);
2838%!assert (sum (zeros (0, 2), 1), [0, 0]);
2839%!assert (sum (zeros (0, 2), 2), zeros(0, 1));
2840%!assert (sum (zeros (2, 2, 0, 3)), zeros(1, 2, 0, 3));
2841%!assert (sum (zeros (2, 2, 0, 3), 2), zeros(2, 1, 0, 3));
2842%!assert (sum (zeros (2, 2, 0, 3), 3), zeros(2, 2, 1, 3));
2843%!assert (sum (zeros (2, 2, 0, 3), 4), zeros(2, 2, 0));
2844%!assert (sum (zeros (2, 2, 0, 3), 7), zeros(2, 2, 0, 3));
2845
2846%!assert (sum (single([1, 2; 3, 4]), 1), single([4, 6]));
2847%!assert (sum (single([1, 2; 3, 4]), 2), single([3; 7]));
2848%!assert (sum (zeros (1, 0, 'single')), single(0));
2849%!assert (sum (zeros (1, 0, 'single'), 1), zeros(1, 0, 'single'));
2850%!assert (sum (zeros (1, 0, 'single'), 2), single(0));
2851%!assert (sum (zeros (0, 1, 'single')), single(0));
2852%!assert (sum (zeros (0, 1, 'single'), 1), single(0));
2853%!assert (sum (zeros (0, 1, 'single'), 2), zeros(0, 1, 'single'));
2854%!assert (sum (zeros (2, 0, 'single')), zeros(1, 0, 'single'));
2855%!assert (sum (zeros (2, 0, 'single'), 1), zeros(1, 0, 'single'));
2856%!assert (sum (zeros (2, 0, 'single'), 2), single([0; 0]));
2857%!assert (sum (zeros (0, 2, 'single')), single([0, 0]));
2858%!assert (sum (zeros (0, 2, 'single'), 1), single([0, 0]));
2859%!assert (sum (zeros (0, 2, 'single'), 2), zeros(0, 1, 'single'));
2860%!assert (sum (zeros (2, 2, 0, 3, 'single')), zeros(1, 2, 0, 3, 'single'));
2861%!assert (sum (zeros (2, 2, 0, 3, 'single'), 2), zeros(2, 1, 0, 3, 'single'));
2862%!assert (sum (zeros (2, 2, 0, 3, 'single'), 3), zeros(2, 2, 1, 3, 'single'));
2863%!assert (sum (zeros (2, 2, 0, 3, 'single'), 4), zeros(2, 2, 0, 'single'));
2864%!assert (sum (zeros (2, 2, 0, 3, 'single'), 7), zeros(2, 2, 0, 3, 'single'));
2865
2866*/
2867
2868DEFUN (sumsq, args, ,
2869 "-*- texinfo -*-\n\
2870@deftypefn {Built-in Function} {} sumsq (@var{x})\n\
2871@deftypefnx {Built-in Function} {} sumsq (@var{x}, @var{dim})\n\
2872Sum of squares of elements along dimension @var{dim}. If @var{dim}\n\
2873is omitted, it defaults to the first non-singleton dimension.\n\
2874\n\
2875This function is conceptually equivalent to computing\n\
2876@example\n\
2877sum (x .* conj (x), dim)\n\
2878@end example\n\
2879but it uses less memory and avoids calling @code{conj} if @var{x} is real.\n\
2880@seealso{sum}\n\
2881@end deftypefn")
2882{
2883 DATA_REDUCTION (sumsq);
2884}
2885
2886/*
2887
2888%!assert(sumsq ([1, 2, 3]), 14)
2889%!assert(sumsq ([-1; -2; 4i]), 21);
2890%!assert(sumsq ([1, 2, 3; 2, 3, 4; 4i, 6i, 2]), [21, 49, 29]);
2891
2892%!assert(sumsq (single([1, 2, 3])), single(14))
2893%!assert(sumsq (single([-1; -2; 4i])), single(21));
2894%!assert(sumsq (single([1, 2, 3; 2, 3, 4; 4i, 6i, 2])), single([21, 49, 29]));
2895
2896%!error <Invalid call to sumsq.*> sumsq ();
2897
2898%!assert (sumsq ([1, 2; 3, 4], 1), [10, 20]);
2899%!assert (sumsq ([1, 2; 3, 4], 2), [5; 25]);
2900
2901%!assert (sumsq (single([1, 2; 3, 4]), 1), single([10, 20]));
2902%!assert (sumsq (single([1, 2; 3, 4]), 2), single([5; 25]));
2903
2904 */
2905
2906DEFUN (islogical, args, ,
2907 "-*- texinfo -*-\n\
2908@deftypefn {Built-in Function} {} islogical (@var{x})\n\
2909Return true if @var{x} is a logical object.\n\
2910@end deftypefn")
2911{
2912 octave_value retval;
2913
2914 if (args.length () == 1)
2915 retval = args(0).is_bool_type ();
2916 else
2917 print_usage ();
2918
2919 return retval;
2920}
2921
2922DEFALIAS (isbool, islogical);
2923
2924/*
2925
2926%!assert (islogical(true), true)
2927%!assert (islogical(false), true)
2928%!assert (islogical([true, false]), true)
2929%!assert (islogical(1), false)
2930%!assert (islogical(1i), false)
2931%!assert (islogical([1,1]), false)
2932%!assert (islogical(single(1)), false)
2933%!assert (islogical(single(1i)), false)
2934%!assert (islogical(single([1,1])), false)
2935
2936 */
2937
2938DEFUN (isinteger, args, ,
2939 "-*- texinfo -*-\n\
2940@deftypefn {Built-in Function} {} isinteger (@var{x})\n\
2941Return true if @var{x} is an integer object (int8, uint8, int16, etc.).\n\
2942Note that @code{isinteger (14)} is false because numeric constants in\n\
2943Octave are double precision floating point values.\n\
2944@seealso{isreal, isnumeric, class, isa}\n\
2945@end deftypefn")
2946{
2947 octave_value retval;
2948
2949 if (args.length () == 1)
2950 retval = args(0).is_integer_type ();
2951 else
2952 print_usage ();
2953
2954 return retval;
2955}
2956
2957DEFUN (iscomplex, args, ,
2958 "-*- texinfo -*-\n\
2959@deftypefn {Built-in Function} {} iscomplex (@var{x})\n\
2960Return true if @var{x} is a complex-valued numeric object.\n\
2961@end deftypefn")
2962{
2963 octave_value retval;
2964
2965 if (args.length () == 1)
2966 retval = args(0).is_complex_type ();
2967 else
2968 print_usage ();
2969
2970 return retval;
2971}
2972
2973DEFUN (isfloat, args, ,
2974 "-*- texinfo -*-\n\
2975@deftypefn {Built-in Function} {} isfloat (@var{x})\n\
2976Return true if @var{x} is a floating-point numeric object.\n\
2977@end deftypefn")
2978{
2979 octave_value retval;
2980
2981 if (args.length () == 1)
2982 retval = args(0).is_float_type ();
2983 else
2984 print_usage ();
2985
2986 return retval;
2987}
2988
2989// FIXME -- perhaps this should be implemented with an
2990// octave_value member function?
2991
2992DEFUN (complex, args, ,
2993 "-*- texinfo -*-\n\
2994@deftypefn {Built-in Function} {} complex (@var{x})\n\
2995@deftypefnx {Built-in Function} {} complex (@var{re}, @var{im})\n\
2996Return a complex result from real arguments. With 1 real argument @var{x},\n\
2997return the complex result @code{@var{x} + 0i}. With 2 real arguments,\n\
2998return the complex result @code{@var{re} + @var{im}}. @code{complex} can\n\
2999often be more convenient than expressions such as @code{a + i*b}.\n\
3000For example:\n\
3001\n\
3002@example\n\
3003@group\n\
3004complex ([1, 2], [3, 4])\n\
3005@result{}\n\
3006 1 + 3i 2 + 4i\n\
3007@end group\n\
3008@end example\n\
3009@seealso{real, imag, iscomplex}\n\
3010@end deftypefn")
3011{
3012 octave_value retval;
3013
3014 int nargin = args.length ();
3015
3016 if (nargin == 1)
3017 {
3018 octave_value arg = args(0);
3019
3020 if (arg.is_complex_type ())
3021 retval = arg;
3022 else
3023 {
3024 if (arg.is_sparse_type ())
3025 {
3026 SparseComplexMatrix val = arg.sparse_complex_matrix_value ();
3027
3028 if (! error_state)
3029 retval = octave_value (new octave_sparse_complex_matrix (val));
3030 }
3031 else if (arg.is_single_type ())
3032 {
3033 if (arg.numel () == 1)
3034 {
3035 FloatComplex val = arg.float_complex_value ();
3036
3037 if (! error_state)
3038 retval = octave_value (new octave_float_complex (val));
3039 }
3040 else
3041 {
3042 FloatComplexNDArray val = arg.float_complex_array_value ();
3043
3044 if (! error_state)
3045 retval = octave_value (new octave_float_complex_matrix (val));
3046 }
3047 }
3048 else
3049 {
3050 if (arg.numel () == 1)
3051 {
3052 Complex val = arg.complex_value ();
3053
3054 if (! error_state)
3055 retval = octave_value (new octave_complex (val));
3056 }
3057 else
3058 {
3059 ComplexNDArray val = arg.complex_array_value ();
3060
3061 if (! error_state)
3062 retval = octave_value (new octave_complex_matrix (val));
3063 }
3064 }
3065
3066 if (error_state)
3067 error ("complex: invalid conversion");
3068 }
3069 }
3070 else if (nargin == 2)
3071 {
3072 octave_value re = args(0);
3073 octave_value im = args(1);
3074
3075 if (re.is_sparse_type () && im.is_sparse_type ())
3076 {
3077 const SparseMatrix re_val = re.sparse_matrix_value ();
3078 const SparseMatrix im_val = im.sparse_matrix_value ();
3079
3080 if (!error_state)
3081 {
3082 if (re.numel () == 1)
3083 {
3084 SparseComplexMatrix result;
3085 if (re_val.nnz () == 0)
3086 result = Complex(0, 1) * SparseComplexMatrix (im_val);
3087 else
3088 {
3089 result = SparseComplexMatrix (im_val.dims (), re_val (0));
3090 octave_idx_type nr = im_val.rows ();
3091 octave_idx_type nc = im_val.cols ();
3092
3093 for (octave_idx_type j = 0; j < nc; j++)
3094 {
3095 octave_idx_type off = j * nr;
3096 for (octave_idx_type i = im_val.cidx(j);
3097 i < im_val.cidx(j + 1); i++)
3098 result.data (im_val.ridx(i) + off) =
3099 result.data (im_val.ridx(i) + off) +
3100 Complex (0, im_val.data (i));
3101 }
3102 }
3103 retval = octave_value (new octave_sparse_complex_matrix (result));
3104 }
3105 else if (im.numel () == 1)
3106 {
3107 SparseComplexMatrix result;
3108 if (im_val.nnz () == 0)
3109 result = SparseComplexMatrix (re_val);
3110 else
3111 {
3112 result = SparseComplexMatrix (re_val.rows(), re_val.cols(), Complex(0, im_val (0)));
3113 octave_idx_type nr = re_val.rows ();
3114 octave_idx_type nc = re_val.cols ();
3115
3116 for (octave_idx_type j = 0; j < nc; j++)
3117 {
3118 octave_idx_type off = j * nr;
3119 for (octave_idx_type i = re_val.cidx(j);
3120 i < re_val.cidx(j + 1); i++)
3121 result.data (re_val.ridx(i) + off) =
3122 result.data (re_val.ridx(i) + off) +
3123 re_val.data (i);
3124 }
3125 }
3126 retval = octave_value (new octave_sparse_complex_matrix (result));
3127 }
3128 else
3129 {
3130 if (re_val.dims () == im_val.dims ())
3131 {
3132 SparseComplexMatrix result = SparseComplexMatrix(re_val)
3133 + Complex(0, 1) * SparseComplexMatrix (im_val);
3134 retval = octave_value (new octave_sparse_complex_matrix (result));
3135 }
3136 else
3137 error ("complex: dimension mismatch");
3138 }
3139 }
3140 }
3141 else if (re.is_single_type () || im.is_single_type ())
3142 {
3143 if (re.numel () == 1)
3144 {
3145 float re_val = re.float_value ();
3146
3147 if (im.numel () == 1)
3148 {
3149 float im_val = im.double_value ();
3150
3151 if (! error_state)
3152 retval = octave_value (new octave_float_complex (FloatComplex (re_val, im_val)));
3153 }
3154 else
3155 {
3156 const FloatNDArray im_val = im.float_array_value ();
3157
3158 if (! error_state)
3159 {
3160 FloatComplexNDArray result (im_val.dims (), FloatComplex ());
3161
3162 for (octave_idx_type i = 0; i < im_val.numel (); i++)
3163 result.xelem (i) = FloatComplex (re_val, im_val(i));
3164
3165 retval = octave_value (new octave_float_complex_matrix (result));
3166 }
3167 }
3168 }
3169 else
3170 {
3171 const FloatNDArray re_val = re.float_array_value ();
3172
3173 if (im.numel () == 1)
3174 {
3175 float im_val = im.float_value ();
3176
3177 if (! error_state)
3178 {
3179 FloatComplexNDArray result (re_val.dims (), FloatComplex ());
3180
3181 for (octave_idx_type i = 0; i < re_val.numel (); i++)
3182 result.xelem (i) = FloatComplex (re_val(i), im_val);
3183
3184 retval = octave_value (new octave_float_complex_matrix (result));
3185 }
3186 }
3187 else
3188 {
3189 const FloatNDArray im_val = im.float_array_value ();
3190
3191 if (! error_state)
3192 {
3193 if (re_val.dims () == im_val.dims ())
3194 {
3195 FloatComplexNDArray result (re_val.dims (), FloatComplex ());
3196
3197 for (octave_idx_type i = 0; i < re_val.numel (); i++)
3198 result.xelem (i) = FloatComplex (re_val(i), im_val(i));
3199
3200 retval = octave_value (new octave_float_complex_matrix (result));
3201 }
3202 else
3203 error ("complex: dimension mismatch");
3204 }
3205 }
3206 }
3207 }
3208 else if (re.numel () == 1)
3209 {
3210 double re_val = re.double_value ();
3211
3212 if (im.numel () == 1)
3213 {
3214 double im_val = im.double_value ();
3215
3216 if (! error_state)
3217 retval = octave_value (new octave_complex (Complex (re_val, im_val)));
3218 }
3219 else
3220 {
3221 const NDArray im_val = im.array_value ();
3222
3223 if (! error_state)
3224 {
3225 ComplexNDArray result (im_val.dims (), Complex ());
3226
3227 for (octave_idx_type i = 0; i < im_val.numel (); i++)
3228 result.xelem (i) = Complex (re_val, im_val(i));
3229
3230 retval = octave_value (new octave_complex_matrix (result));
3231 }
3232 }
3233 }
3234 else
3235 {
3236 const NDArray re_val = re.array_value ();
3237
3238 if (im.numel () == 1)
3239 {
3240 double im_val = im.double_value ();
3241
3242 if (! error_state)
3243 {
3244 ComplexNDArray result (re_val.dims (), Complex ());
3245
3246 for (octave_idx_type i = 0; i < re_val.numel (); i++)
3247 result.xelem (i) = Complex (re_val(i), im_val);
3248
3249 retval = octave_value (new octave_complex_matrix (result));
3250 }
3251 }
3252 else
3253 {
3254 const NDArray im_val = im.array_value ();
3255
3256 if (! error_state)
3257 {
3258 if (re_val.dims () == im_val.dims ())
3259 {
3260 ComplexNDArray result (re_val.dims (), Complex ());
3261
3262 for (octave_idx_type i = 0; i < re_val.numel (); i++)
3263 result.xelem (i) = Complex (re_val(i), im_val(i));
3264
3265 retval = octave_value (new octave_complex_matrix (result));
3266 }
3267 else
3268 error ("complex: dimension mismatch");
3269 }
3270 }
3271 }
3272
3273 if (error_state)
3274 error ("complex: invalid conversion");
3275 }
3276 else
3277 print_usage ();
3278
3279 return retval;
3280}
3281
3282DEFUN (isreal, args, ,
3283 "-*- texinfo -*-\n\
3284@deftypefn {Built-in Function} {} isreal (@var{x})\n\
3285Return true if @var{x} is a real-valued numeric object.\n\
3286@end deftypefn")
3287{
3288 octave_value retval;
3289
3290 if (args.length () == 1)
3291 retval = args(0).is_real_type ();
3292 else
3293 print_usage ();
3294
3295 return retval;
3296}
3297
3298DEFUN (isempty, args, ,
3299 "-*- texinfo -*-\n\
3300@deftypefn {Built-in Function} {} isempty (@var{a})\n\
3301Return 1 if @var{a} is an empty matrix (either the number of rows, or\n\
3302the number of columns, or both are zero). Otherwise, return 0.\n\
3303@end deftypefn")
3304{
3305 octave_value retval = false;
3306
3307 if (args.length () == 1)
3308 retval = args(0).is_empty ();
3309 else
3310 print_usage ();
3311
3312 return retval;
3313}
3314
3315DEFUN (isnumeric, args, ,
3316 "-*- texinfo -*-\n\
3317@deftypefn {Built-in Function} {} isnumeric (@var{x})\n\
3318Return nonzero if @var{x} is a numeric object.\n\
3319@end deftypefn")
3320{
3321 octave_value retval;
3322
3323 if (args.length () == 1)
3324 retval = args(0).is_numeric_type ();
3325 else
3326 print_usage ();
3327
3328 return retval;
3329}
3330
3331DEFUN (islist, args, ,
3332 "-*- texinfo -*-\n\
3333@deftypefn {Built-in Function} {} islist (@var{x})\n\
3334Return nonzero if @var{x} is a list.\n\
3335@end deftypefn")
3336{
3337 octave_value retval;
3338
3339 if (args.length () == 1)
3340 retval = args(0).is_list ();
3341 else
3342 print_usage ();
3343
3344 return retval;
3345}
3346
3347DEFUN (ismatrix, args, ,
3348 "-*- texinfo -*-\n\
3349@deftypefn {Built-in Function} {} ismatrix (@var{a})\n\
3350Return 1 if @var{a} is a matrix. Otherwise, return 0.\n\
3351@end deftypefn")
3352{
3353 octave_value retval = false;
3354
3355 if (args.length () == 1)
3356 {
3357 octave_value arg = args(0);
3358
3359 if (arg.is_scalar_type () || arg.is_range ())
3360 retval = true;
3361 else if (arg.is_matrix_type ())
3362 retval = (arg.rows () >= 1 && arg.columns () >= 1);
3363 }
3364 else
3365 print_usage ();
3366
3367 return retval;
3368}
3369
3370/*
3371