comparison scripts/specfun/nchoosek.m @ 10800:23b3ae008f5e

optimize nchoosek
author Jaroslav Hajek <highegg@gmail.com>
date Mon, 19 Jul 2010 13:35:42 +0200
parents 95c3e38098bf
children 693e22af08ae
comparison
equal deleted inserted replaced
10799:177f1ad7c7c1 10800:23b3ae008f5e
86 A = v(:); 86 A = v(:);
87 elseif (k == n) 87 elseif (k == n)
88 A = v(:).'; 88 A = v(:).';
89 elseif (k > n) 89 elseif (k > n)
90 A = zeros (0, k, class (v)); 90 A = zeros (0, k, class (v));
91 else 91 elseif (k == 2)
92 p = cell (1, k); 92 ## Can do it without transpose.
93 ## Hack: do the op in the smallest integer class possible to avoid 93 x = repelems (v(1:n-1), [1:n-1; n-1:-1:1]).';
94 ## moving too much data. 94 y = cat (1, cellslices (v(:), 2:n, n*ones (1, n-1)){:});
95 if (n < intmax ("uint8")) 95 A = [x, y];
96 cl = "uint8"; 96 elseif (k < n)
97 elseif (n < intmax ("uint16")) 97 v = v(:).';
98 cl = "uint16"; 98 A = v(k:n);
99 elseif (n < intmax ("uint32")) 99 l = 1:n-k+1;
100 cl = "uint32"; 100 for j = 2:k
101 else 101 c = columns (A);
102 ## This would exhaust memory anyway. 102 cA = cellslices (A, l, c*ones (1, n-k+1), 2);
103 cl = "double"; 103 l = c-l+1;
104 endif 104 b = repelems (v(k-j+1:n-j+1), [1:n-k+1; l]);
105 105 A = [b; cA{:}];
106 ## Use a generalized Pascal triangle. Traverse backwards to keep 106 l = cumsum (l);
107 ## alphabetical order. 107 l = [1, 1 + l(1:n-k)];
108 for i = 1:k
109 p{i} = zeros (0, i, cl);
110 endfor 108 endfor
111 s = ones (1, 1, cl); 109 clear cA b;
112 p{1} = n*s; 110 A = A.';
113 for j = n-1:-1:1
114 for i = k:-1:2
115 q = p{i-1};
116 p{i} = [[repmat(s*j, rows (p{i-1}), 1), p{i-1}]; p{i}];
117 endfor
118 p{1} = [j;p{1}];
119 endfor
120 v = v(:);
121 A = v(p{k});
122 endif 111 endif
123 endfunction 112 endfunction
124 113
125 %!warning (nchoosek(100,45)); 114 %!warning (nchoosek(100,45));
126 %!error (nchoosek(100,45.5)); 115 %!error (nchoosek(100,45.5));