Mercurial > octave
comparison libinterp/corefcn/data.cc @ 30230:bd02f48ac38f
allow size function to query arbitrary list of dimensions (bug #61098)
* data.cc (Fsize): Allow DIM argument to be a vector or for a list of
dimensions to be specified as individual arguments. New tests from
Kai T. Ohlhus <k.ohlhus@gmail.com>.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 29 Sep 2021 16:22:00 +0900 |
parents | 7d6709900da7 |
children | 81d26e8481a6 |
comparison
equal
deleted
inserted
replaced
30229:3b3ec2ea46ef | 30230:bd02f48ac38f |
---|---|
2654 | 2654 |
2655 DEFUN (size, args, nargout, | 2655 DEFUN (size, args, nargout, |
2656 doc: /* -*- texinfo -*- | 2656 doc: /* -*- texinfo -*- |
2657 @deftypefn {} {@var{sz} =} size (@var{a}) | 2657 @deftypefn {} {@var{sz} =} size (@var{a}) |
2658 @deftypefnx {} {@var{dim_sz} =} size (@var{a}, @var{dim}) | 2658 @deftypefnx {} {@var{dim_sz} =} size (@var{a}, @var{dim}) |
2659 @deftypefnx {} {@var{dim_sz} =} size (@var{a}, @var{d1}, @var{d2}, @dots{}) | |
2659 @deftypefnx {} {[@var{rows}, @var{cols}, @dots{}, @var{dim_N_sz}] =} size (@dots{}) | 2660 @deftypefnx {} {[@var{rows}, @var{cols}, @dots{}, @var{dim_N_sz}] =} size (@dots{}) |
2660 Return a row vector with the size (number of elements) of each dimension for | 2661 Return a row vector with the size (number of elements) of each dimension for |
2661 the object @var{a}. | 2662 the object @var{a}. |
2662 | 2663 |
2663 When given a second argument, @var{dim}, return the size of the corresponding | 2664 When given a second argument, @var{dim}, return the size of the corresponding |
2664 dimension. | 2665 dimension. If @var{dim} is a vector, return each of the corresponding |
2666 dimensions. Multiple dimensions may also be specified as separate arguments. | |
2665 | 2667 |
2666 With a single output argument, @code{size} returns a row vector. When called | 2668 With a single output argument, @code{size} returns a row vector. When called |
2667 with multiple output arguments, @code{size} returns the size of dimension N | 2669 with multiple output arguments, @code{size} returns the size of dimension N |
2668 in the Nth argument. The number of rows, dimension 1, is returned in the | 2670 in the Nth argument. The number of rows, dimension 1, is returned in the |
2669 first argument, the number of columns, dimension 2, is returned in the | 2671 first argument, the number of columns, dimension 2, is returned in the |
2710 @end example | 2712 @end example |
2711 | 2713 |
2712 @seealso{numel, ndims, length, rows, columns, size_equal, common_size} | 2714 @seealso{numel, ndims, length, rows, columns, size_equal, common_size} |
2713 @end deftypefn */) | 2715 @end deftypefn */) |
2714 { | 2716 { |
2715 octave_value_list retval; | |
2716 | |
2717 int nargin = args.length (); | 2717 int nargin = args.length (); |
2718 | 2718 |
2719 if (nargin == 0) | |
2720 print_usage (); | |
2721 | |
2722 // For compatibility with Matlab, size returns dimensions as doubles. | |
2723 | |
2724 Matrix m; | |
2725 | |
2726 dim_vector dimensions = args(0).dims (); | |
2727 int ndims = dimensions.ndims (); | |
2728 | |
2719 if (nargin == 1) | 2729 if (nargin == 1) |
2720 { | 2730 { |
2721 const dim_vector dimensions = args(0).dims (); | |
2722 | |
2723 if (nargout > 1) | 2731 if (nargout > 1) |
2724 { | 2732 { |
2725 const dim_vector rdims = dimensions.redim (nargout); | 2733 dimensions = dimensions.redim (nargout); |
2726 retval.resize (nargout); | 2734 ndims = dimensions.ndims (); |
2727 for (int i = 0; i < nargout; i++) | 2735 } |
2728 retval(i) = rdims(i); | 2736 |
2737 m.resize (1, ndims); | |
2738 | |
2739 for (octave_idx_type i = 0; i < ndims; i++) | |
2740 m(i) = dimensions(i); | |
2741 } | |
2742 else | |
2743 { | |
2744 Array<octave_idx_type> query_dims; | |
2745 | |
2746 if (nargin > 2) | |
2747 { | |
2748 query_dims.resize (dim_vector (1, nargin-1)); | |
2749 | |
2750 for (octave_idx_type i = 0; i < nargin-1; i++) | |
2751 query_dims(i) = args(i+1).idx_type_value (true); | |
2729 } | 2752 } |
2730 else | 2753 else |
2754 query_dims = args(1).octave_idx_type_vector_value (true); | |
2755 | |
2756 if (nargout > 1 && nargout != query_dims.numel ()) | |
2757 error ("size: nargout > 1 but does not match number of requested dimensions"); | |
2758 | |
2759 octave_idx_type nidx = query_dims.numel (); | |
2760 | |
2761 m.resize (1, nidx); | |
2762 | |
2763 for (octave_idx_type i = 0; i < nidx; i++) | |
2731 { | 2764 { |
2732 int ndims = dimensions.ndims (); | 2765 octave_idx_type nd = query_dims.xelem (i); |
2733 | 2766 |
2734 Matrix m (1, ndims); | 2767 if (nd < 1) |
2735 | 2768 error ("size: requested dimension DIM (= %" |
2736 for (int i = 0; i < ndims; i++) | 2769 OCTAVE_IDX_TYPE_FORMAT ") out of range", nd); |
2737 m.xelem (i) = dimensions(i); | 2770 |
2738 | 2771 m(i) = nd <= ndims ? dimensions (nd-1) : 1; |
2739 retval(0) = m; | |
2740 } | 2772 } |
2741 } | 2773 } |
2742 else if (nargin == 2 && nargout < 2) | 2774 |
2743 { | 2775 if (nargout > 1) |
2744 if (! args(1).is_real_scalar ()) | 2776 { |
2745 error ("size: DIM must be a positive integer"); | 2777 octave_value_list retval (nargout); |
2746 | 2778 |
2747 octave_idx_type nd = args(1).idx_type_value (); | 2779 for (octave_idx_type i = 0; i < nargout; i++) |
2748 | 2780 retval(i) = m(i); |
2749 const dim_vector dv = args(0).dims (); | 2781 |
2750 | 2782 return retval; |
2751 if (nd < 1) | 2783 } |
2752 error ("size: requested dimension DIM (= %" OCTAVE_IDX_TYPE_FORMAT ") " | 2784 |
2753 "out of range", nd); | 2785 return ovl (m); |
2754 | 2786 } |
2755 if (nd <= dv.ndims ()) | 2787 |
2756 retval(0) = dv(nd-1); | 2788 /* |
2757 else | 2789 ## Plain call |
2758 retval(0) = 1; | 2790 |
2759 } | 2791 %!assert (size ([1, 2; 3, 4; 5, 6]), [3, 2]) |
2760 else | 2792 |
2761 print_usage (); | 2793 %!test |
2762 | 2794 %! [nr, nc] = size ([1, 2; 3, 4; 5, 6]); |
2763 return retval; | 2795 %! assert (nr, 3) |
2764 } | 2796 %! assert (nc, 2) |
2797 | |
2798 %!test | |
2799 %! [nr, remainder] = size (ones (2, 3, 4, 5)); | |
2800 %! assert (nr, 2) | |
2801 %! assert (remainder, 60) | |
2802 | |
2803 ## Call for single existing dimension | |
2804 | |
2805 %!assert (size ([1, 2; 3, 4; 5, 6], 1), 3) | |
2806 %!assert (size ([1, 2; 3, 4; 5, 6], 2), 2) | |
2807 | |
2808 ## Call for single non-existing dimension | |
2809 | |
2810 %!assert (size ([1, 2; 3, 4; 5, 6], 3), 1) | |
2811 %!assert (size ([1, 2; 3, 4; 5, 6], 4), 1) | |
2812 | |
2813 ## Call for more than existing dimensions | |
2814 | |
2815 %!test | |
2816 %! [nr, nc, e1, e2] = size ([1, 2; 3, 4; 5, 6]); | |
2817 %! assert (nr, 3) | |
2818 %! assert (nc, 2) | |
2819 %! assert (e1, 1) | |
2820 %! assert (e2, 1) | |
2821 | |
2822 ## Call for two arbitrary dimensions | |
2823 | |
2824 %!test | |
2825 %! dim = [3, 2, 1, 1, 1]; | |
2826 %! for i = 1:5 | |
2827 %! for j = 1:5 | |
2828 %! assert (size ([1, 2; 3, 4; 5, 6], i, j), [dim(i), dim(j)]) | |
2829 %! assert (size ([1, 2; 3, 4; 5, 6], [i, j]), [dim(i), dim(j)]) | |
2830 %! [a, b] = size ([1, 2; 3, 4; 5, 6], i, j); | |
2831 %! assert (a, dim(i)); | |
2832 %! assert (b, dim(j)); | |
2833 %! [a, b] = size ([1, 2; 3, 4; 5, 6], [i, j]); | |
2834 %! assert (a, dim(i)); | |
2835 %! assert (b, dim(j)); | |
2836 %! end | |
2837 %! end | |
2838 | |
2839 ## Call for three arbitrary dimensions | |
2840 | |
2841 %!test | |
2842 %! dim = [3, 2, 1, 1, 1]; | |
2843 %! for i = 1:5 | |
2844 %! for j = 1:5 | |
2845 %! for k = 1:5 | |
2846 %! assert (size ([1, 2; 3, 4; 5, 6], i, j, k), [dim(i), dim(j), dim(k)]) | |
2847 %! assert (size ([1, 2; 3, 4; 5, 6], [i, j, k]), [dim(i), dim(j), dim(k)]) | |
2848 %! [a, b, c] = size ([1, 2; 3, 4; 5, 6], i, j, k); | |
2849 %! assert (a, dim(i)); | |
2850 %! assert (b, dim(j)); | |
2851 %! assert (c, dim(k)); | |
2852 %! [a, b, c] = size ([1, 2; 3, 4; 5, 6], [i, j, k]); | |
2853 %! assert (a, dim(i)); | |
2854 %! assert (b, dim(j)); | |
2855 %! assert (c, dim(k)); | |
2856 %! end | |
2857 %! end | |
2858 %! end | |
2859 | |
2860 %!error <does not match number of requested dimensions> | |
2861 %! [a, b, c] = size ([1, 2; 3, 4; 5, 6], 1:4) | |
2862 */ | |
2765 | 2863 |
2766 DEFUN (size_equal, args, , | 2864 DEFUN (size_equal, args, , |
2767 doc: /* -*- texinfo -*- | 2865 doc: /* -*- texinfo -*- |
2768 @deftypefn {} {} size_equal (@var{a}, @var{b}, @dots{}) | 2866 @deftypefn {} {} size_equal (@var{a}, @var{b}, @dots{}) |
2769 Return true if the dimensions of all arguments agree. | 2867 Return true if the dimensions of all arguments agree. |