blob: 46e3f4580ea89b0fc5fdd2be830c550337d79af8 [file] [log] [blame]
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +11001/* (C) 2007 Timothy B. Terriberry */
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +11002/*
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions
5 are met:
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +11006
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +11007 - Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +11009
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110010 - Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110013
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110014 - Neither the name of the Xiph.org Foundation nor the names of its
15 contributors may be used to endorse or promote products derived from
16 this software without specific prior written permission.
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110017
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110018 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
22 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*/
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110030#include <stdlib.h>
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110031#include "cwrs.h"
32
33/*Returns the numer of ways of choosing _m elements from a set of size _n with
34 replacement when a sign bit is needed for each unique element.*/
35#if 0
36static unsigned ncwrs(int _n,int _m){
37 static unsigned c[32][32];
38 if(_n<0||_m<0)return 0;
39 if(!c[_n][_m]){
40 if(_m<=0)c[_n][_m]=1;
41 else if(_n>0)c[_n][_m]=ncwrs(_n-1,_m)+ncwrs(_n,_m-1)+ncwrs(_n-1,_m-1);
42 }
43 return c[_n][_m];
44}
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110045#else
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110046unsigned ncwrs(int _n,int _m){
47 unsigned ret;
48 unsigned f;
49 unsigned d;
50 int i;
51 if(_n<0||_m<0)return 0;
52 if(_m==0)return 1;
53 if(_n==0)return 0;
54 ret=0;
55 f=_n;
56 d=1;
57 for(i=1;i<=_m;i++){
58 ret+=f*d<<i;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110059 f=(f*(_n-i))/(i+1);
60 d=(d*(_m-i))/i;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110061 }
62 return ret;
63}
64#endif
65
Jean-Marc Valinf8db8002007-12-11 14:52:56 +110066celt_uint64_t ncwrs64(int _n,int _m){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110067 celt_uint64_t ret;
68 celt_uint64_t f;
69 celt_uint64_t d;
70 int i;
71 if(_n<0||_m<0)return 0;
72 if(_m==0)return 1;
73 if(_n==0)return 0;
74 ret=0;
75 f=_n;
76 d=1;
77 for(i=1;i<=_m;i++){
78 ret+=f*d<<i;
79 f=(f*(_n-i))/(i+1);
80 d=(d*(_m-i))/i;
81 }
82 return ret;
Jean-Marc Valinf8db8002007-12-11 14:52:56 +110083}
84
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110085/*Returns the _i'th combination of _m elements chosen from a set of size _n
86 with associated sign bits.
87 _x: Returns the combination with elements sorted in ascending order.
88 _s: Returns the associated sign bits.*/
89void cwrsi(int _n,int _m,unsigned _i,int *_x,int *_s){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110090 int j;
91 int k;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110092 for(k=j=0;k<_m;k++){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110093 unsigned pn;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110094 unsigned p;
95 unsigned t;
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110096 p=ncwrs(_n-j,_m-k-1);
97 pn=ncwrs(_n-j-1,_m-k-1);
98 p+=pn;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110099 if(k>0){
100 t=p>>1;
101 if(t<=_i||_s[k-1])_i+=t;
102 }
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100103 while(p<=_i){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100104 _i-=p;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100105 j++;
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100106 p=pn;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100107 pn=ncwrs(_n-j-1,_m-k-1);
108 p+=pn;
109 }
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100110 t=p>>1;
111 _s[k]=_i>=t;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100112 _x[k]=j;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100113 if(_s[k])_i-=t;
114 }
115}
116
117/*Returns the index of the given combination of _m elements chosen from a set
118 of size _n with associated sign bits.
119 _x: The combination with elements sorted in ascending order.
120 _s: The associated sign bits.*/
121unsigned icwrs(int _n,int _m,const int *_x,const int *_s){
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100122 unsigned i;
123 int j;
124 int k;
125 i=0;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100126 for(k=j=0;k<_m;k++){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100127 unsigned pn;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100128 unsigned p;
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100129 p=ncwrs(_n-j,_m-k-1);
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100130 pn=ncwrs(_n-j-1,_m-k-1);
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100131 p+=pn;
132 if(k>0)p>>=1;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100133 while(j<_x[k]){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100134 i+=p;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100135 j++;
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100136 p=pn;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100137 pn=ncwrs(_n-j-1,_m-k-1);
138 p+=pn;
139 }
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100140 if((k==0||_x[k]!=_x[k-1])&&_s[k])i+=p>>1;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100141 }
142 return i;
143}
144
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100145/*Returns the _i'th combination of _m elements chosen from a set of size _n
146 with associated sign bits.
147 _x: Returns the combination with elements sorted in ascending order.
148 _s: Returns the associated sign bits.*/
149void cwrsi64(int _n,int _m,celt_uint64_t _i,int *_x,int *_s){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100150 int j;
151 int k;
152 for(k=j=0;k<_m;k++){
153 celt_uint64_t pn;
154 celt_uint64_t p;
155 celt_uint64_t t;
156 p=ncwrs64(_n-j,_m-k-1);
157 pn=ncwrs64(_n-j-1,_m-k-1);
158 p+=pn;
159 if(k>0){
160 t=p>>1;
161 if(t<=_i||_s[k-1])_i+=t;
162 }
163 while(p<=_i){
164 _i-=p;
165 j++;
166 p=pn;
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100167 pn=ncwrs64(_n-j-1,_m-k-1);
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100168 p+=pn;
169 }
170 t=p>>1;
171 _s[k]=_i>=t;
172 _x[k]=j;
173 if(_s[k])_i-=t;
174 }
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100175}
176
177/*Returns the index of the given combination of _m elements chosen from a set
178 of size _n with associated sign bits.
179 _x: The combination with elements sorted in ascending order.
180 _s: The associated sign bits.*/
181celt_uint64_t icwrs64(int _n,int _m,const int *_x,const int *_s){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100182 celt_uint64_t i;
183 int j;
184 int k;
185 i=0;
186 for(k=j=0;k<_m;k++){
187 celt_uint64_t pn;
188 celt_uint64_t p;
189 p=ncwrs64(_n-j,_m-k-1);
190 pn=ncwrs64(_n-j-1,_m-k-1);
191 p+=pn;
192 if(k>0)p>>=1;
193 while(j<_x[k]){
194 i+=p;
195 j++;
196 p=pn;
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100197 pn=ncwrs64(_n-j-1,_m-k-1);
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100198 p+=pn;
199 }
200 if((k==0||_x[k]!=_x[k-1])&&_s[k])i+=p>>1;
201 }
202 return i;
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100203}
204
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100205/*Converts a combination _x of _m unit pulses with associated sign bits _s into
206 a pulse vector _y of length _n.
207 _y: Returns the vector of pulses.
208 _x: The combination with elements sorted in ascending order.
209 _s: The associated sign bits.*/
210void comb2pulse(int _n,int _m,int *_y,const int *_x,const int *_s){
211 int j;
212 int k;
213 int n;
214 for(k=j=0;k<_m;k+=n){
215 for(n=1;k+n<_m&&_x[k+n]==_x[k];n++);
216 while(j<_x[k])_y[j++]=0;
217 _y[j++]=_s[k]?-n:n;
218 }
219 while(j<_n)_y[j++]=0;
220}
221
222/*Converts a pulse vector vector _y of length _n into a combination of _m unit
223 pulses with associated sign bits _s.
224 _x: Returns the combination with elements sorted in ascending order.
225 _s: Returns the associated sign bits.
226 _y: The vector of pulses, whose sum of absolute values must be _m.*/
227void pulse2comb(int _n,int _m,int *_x,int *_s,const int *_y){
228 int j;
229 int k;
230 for(k=j=0;j<_n;j++){
231 if(_y[j]){
232 int n;
233 int s;
234 n=abs(_y[j]);
235 s=_y[j]<0;
236 for(;n-->0;k++){
237 _x[k]=j;
238 _s[k]=s;
239 }
240 }
241 }
242}
243
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100244#if 0
245#include <stdio.h>
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100246#define NMAX (10)
247#define MMAX (9)
248
249int main(int _argc,char **_argv){
250 int n;
251 for(n=0;n<=NMAX;n++){
252 int m;
253 for(m=0;m<=MMAX;m++){
254 unsigned nc;
255 unsigned i;
256 nc=ncwrs(n,m);
257 for(i=0;i<nc;i++){
258 int x[MMAX];
259 int s[MMAX];
260 int x2[MMAX];
261 int s2[MMAX];
262 int y[NMAX];
263 int j;
264 int k;
265 cwrsi(n,m,i,x,s);
266 printf("%6u of %u:",i,nc);
267 for(k=0;k<m;k++){
268 printf(" %c%i",k>0&&x[k]==x[k-1]?' ':s[k]?'-':'+',x[k]);
269 }
270 printf(" ->");
271 if(icwrs(n,m,x,s)!=i){
272 fprintf(stderr,"Combination-index mismatch.\n");
273 }
274 comb2pulse(n,m,y,x,s);
275 for(j=0;j<n;j++)printf(" %c%i",y[j]?y[j]<0?'-':'+':' ',abs(y[j]));
276 printf("\n");
277 pulse2comb(n,m,x2,s2,y);
278 for(k=0;k<m;k++)if(x[k]!=x2[k]||s[k]!=s2[k]){
279 fprintf(stderr,"Pulse-combination mismatch.\n");
280 break;
281 }
282 }
283 printf("\n");
284 }
285 }
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100286 return -1;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100287}
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100288#endif
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100289
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100290#if 0
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100291#include <stdio.h>
292#define NMAX (32)
293#define MMAX (16)
294
295int main(int _argc,char **_argv){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100296 int n;
297 for(n=0;n<=NMAX;n+=3){
298 int m;
299 for(m=0;m<=MMAX;m++){
300 celt_uint64_t nc;
301 celt_uint64_t i;
302 nc=ncwrs64(n,m);
303 printf("%d/%d: %llu",n,m, nc);
304 for(i=0;i<nc;i+=100000){
305 int x[MMAX];
306 int s[MMAX];
307 int x2[MMAX];
308 int s2[MMAX];
309 int y[NMAX];
310 int j;
311 int k;
312 cwrsi64(n,m,i,x,s);
313 /*printf("%llu of %llu:",i,nc);
314 for(k=0;k<m;k++){
315 printf(" %c%i",k>0&&x[k]==x[k-1]?' ':s[k]?'-':'+',x[k]);
316 }
317 printf(" ->");*/
318 if(icwrs64(n,m,x,s)!=i){
319 fprintf(stderr,"Combination-index mismatch.\n");
320 }
321 comb2pulse(n,m,y,x,s);
322 /*for(j=0;j<n;j++)printf(" %c%i",y[j]?y[j]<0?'-':'+':' ',abs(y[j]));
323 printf("\n");*/
324 pulse2comb(n,m,x2,s2,y);
325 for(k=0;k<m;k++)if(x[k]!=x2[k]||s[k]!=s2[k]){
326 fprintf(stderr,"Pulse-combination mismatch.\n");
327 break;
328 }
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100329 }
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100330 printf("\n");
331 }
332 }
333 return 0;
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100334}
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100335#endif