comparison scripts/specfun/nchoosek.m @ 30204:1cd077e9f127

allow nchoosek to accept character vectors (bug #61199) * nchoosek.m: Allow input of possible values to be a character array. Ensure output is the same type as array of possible values. New tests.
author John W. Eaton <jwe@octave.org>
date Thu, 23 Sep 2021 00:00:12 -0400
parents 7854d5752dd2
children 23a907b2dbd5
comparison
equal deleted inserted replaced
30203:75fb18f0469a 30204:1cd077e9f127
92 92
93 function C = nchoosek (v, k) 93 function C = nchoosek (v, k)
94 94
95 if (nargin != 2 95 if (nargin != 2
96 || ! (isreal (k) && isscalar (k)) 96 || ! (isreal (k) && isscalar (k))
97 || ! (isnumeric (v) && isvector (v))) 97 || ! ((isnumeric (v) || ischar (v)) && isvector (v)))
98 print_usage (); 98 print_usage ();
99 endif 99 endif
100 if (k < 0 || k != fix (k)) 100 if (k < 0 || k != fix (k))
101 error ("nchoosek: K must be an integer >= 0"); 101 error ("nchoosek: K must be an integer >= 0");
102 elseif (isscalar (v) && (iscomplex (v) || v < k || v < 0 || v != fix (v))) 102 elseif (isscalar (v) && (iscomplex (v) || v < k || v < 0 || v != fix (v)))
111 C = round (prod ((v-k+1:v)./(1:k))); 111 C = round (prod ((v-k+1:v)./(1:k)));
112 if (C*2*k*eps >= 0.5) 112 if (C*2*k*eps >= 0.5)
113 warning ("nchoosek: possible loss of precision"); 113 warning ("nchoosek: possible loss of precision");
114 endif 114 endif
115 elseif (k == 0) 115 elseif (k == 0)
116 C = zeros (1,0); 116 if (is_sq_string (v))
117 C = resize ('', 1, 0);
118 elseif (is_dq_string (v))
119 C = resize ("", 1, 0);
120 else
121 C = zeros (1, 0, class (v));
122 endif
117 elseif (k == 1) 123 elseif (k == 1)
118 C = v(:); 124 C = v(:);
119 elseif (k == n) 125 elseif (k == n)
120 C = v(:).'; 126 C = v(:).';
121 elseif (k > n) 127 elseif (k > n)
122 C = zeros (0, k, class (v)); 128 if (is_sq_string (v))
129 C = resize ('', 0, k);
130 elseif (is_dq_string (v))
131 C = resize ("", 0, k);
132 else
133 C = zeros (0, k, class (v));
134 endif
123 elseif (k == 2) 135 elseif (k == 2)
124 ## Can do it without transpose. 136 ## Can do it without transpose.
125 x = repelems (v(1:n-1), [1:n-1; n-1:-1:1]).'; 137 x = repelems (v(1:n-1), [1:n-1; n-1:-1:1]).';
126 y = cat (1, cellslices (v(:), 2:n, n*ones (1, n-1)){:}); 138 y = cat (1, cellslices (v(:), 2:n, n*ones (1, n-1)){:});
127 C = [x, y]; 139 C = [x, y];
152 %!error <Invalid call> nchoosek () 164 %!error <Invalid call> nchoosek ()
153 %!error <Invalid call> nchoosek (1) 165 %!error <Invalid call> nchoosek (1)
154 166
155 %!error nchoosek (100, 2i) 167 %!error nchoosek (100, 2i)
156 %!error nchoosek (100, [2 3]) 168 %!error nchoosek (100, [2 3])
157 %!error nchoosek ("100", 45)
158 %!error nchoosek (100*ones (2, 2), 45) 169 %!error nchoosek (100*ones (2, 2), 45)
159 %!error <K must be an integer .= 0> nchoosek (100, -45) 170 %!error <K must be an integer .= 0> nchoosek (100, -45)
160 %!error <K must be an integer .= 0> nchoosek (100, 45.5) 171 %!error <K must be an integer .= 0> nchoosek (100, 45.5)
161 %!error <N must be a non-negative integer .= K> nchoosek (100i, 2) 172 %!error <N must be a non-negative integer .= K> nchoosek (100i, 2)
162 %!error <N must be a non-negative integer .= K> nchoosek (100, 145) 173 %!error <N must be a non-negative integer .= K> nchoosek (100, 145)
163 %!error <N must be a non-negative integer .= K> nchoosek (-100, 45) 174 %!error <N must be a non-negative integer .= K> nchoosek (-100, 45)
164 %!error <N must be a non-negative integer .= K> nchoosek (100.5, 45) 175 %!error <N must be a non-negative integer .= K> nchoosek (100.5, 45)
165 %!warning <possible loss of precision> nchoosek (100, 45); 176 %!warning <possible loss of precision> nchoosek (100, 45);
177
178 %!assert (nchoosek ('a':'b', 2), 'ab')
179 %!assert (nchoosek ("a":"b", 2), "ab")
180
181 %!test
182 %! x = nchoosek ('a':'b', 3);
183 %! assert (size (x), [0, 3]);
184 %! assert (is_sq_string (x));
185 %! x = nchoosek ('a':'b', 0);
186 %! assert (size (x), [1, 0]);
187 %! assert (is_sq_string (x));
188 %!
189 %! x = nchoosek ("a":"b", 3);
190 %! assert (size (x), [0, 3]);
191 %! assert (is_dq_string (x));
192 %! x = nchoosek ("a":"b", 0);
193 %! assert (size (x), [1, 0]);
194 %! assert (is_dq_string (x));
195 %!
196 %! x = nchoosek (uint8(1):uint8(2), 3);
197 %! assert (size (x), [0, 3]);
198 %! assert (class (x), "uint8");
199 %! x = nchoosek (uint8(1):uint8(2), 0);
200 %! assert (size (x), [1, 0]);
201 %! assert (class (x), "uint8");