00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <math.h>
00021 #include <string.h>
00022 #include <errno.h>
00023 #include "../lib/scales.h"
00024 #include "bookutil.h"
00025 #include "vqgen.h"
00026 #include "vqsplit.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 static int longsort(const void *a, const void *b){
00048 return(**((long **)a)-**((long **)b));
00049 }
00050
00051 static int addtosearch(int entry,long **tempstack,long *tempcount,int add){
00052 long *ptr=tempstack[entry];
00053 long i=tempcount[entry];
00054
00055 if(ptr){
00056 while(i--)
00057 if(*ptr++==add)return(0);
00058 tempstack[entry]=_ogg_realloc(tempstack[entry],
00059 (tempcount[entry]+1)*sizeof(long));
00060 }else{
00061 tempstack[entry]=_ogg_malloc(sizeof(long));
00062 }
00063
00064 tempstack[entry][tempcount[entry]++]=add;
00065 return(1);
00066 }
00067
00068 static void setvals(int dim,encode_aux_pigeonhole *p,
00069 long *temptrack,float *tempmin,float *tempmax,
00070 int seqp){
00071 int i;
00072 float last=0.f;
00073 for(i=0;i<dim;i++){
00074 tempmin[i]=(temptrack[i])*p->del+p->min+last;
00075 tempmax[i]=tempmin[i]+p->del;
00076 if(seqp)last=tempmin[i];
00077 }
00078 }
00079
00080
00081
00082
00083
00084 static float minerror(int dim,float *a,encode_aux_pigeonhole *p,
00085 long *temptrack,float *tempmin,float *tempmax){
00086 int i;
00087 float err=0.f;
00088 for(i=0;i<dim;i++){
00089 float eval=0.f;
00090 if(a[i]<tempmin[i]){
00091 eval=tempmin[i]-a[i];
00092 }else if(a[i]>tempmax[i]){
00093 eval=a[i]-tempmax[i];
00094 }
00095 err+=eval*eval;
00096 }
00097 return(err);
00098 }
00099
00100 static float maxerror(int dim,float *a,encode_aux_pigeonhole *p,
00101 long *temptrack,float *tempmin,float *tempmax){
00102 int i;
00103 float err=0.f,eval;
00104 for(i=0;i<dim;i++){
00105 if(a[i]<tempmin[i]){
00106 eval=tempmax[i]-a[i];
00107 }else if(a[i]>tempmax[i]){
00108 eval=a[i]-tempmin[i];
00109 }else{
00110 float t1=a[i]-tempmin[i];
00111 eval=tempmax[i]-a[i];
00112 if(t1>eval)eval=t1;
00113 }
00114 err+=eval*eval;
00115 }
00116 return(err);
00117 }
00118
00119 int main(int argc,char *argv[]){
00120 codebook *b;
00121 static_codebook *c;
00122 int entries=-1,dim=-1;
00123 float min,del;
00124 char *name;
00125 long i,j;
00126 float *suggestions;
00127 int suggcount=0;
00128
00129 if(argv[1]==NULL){
00130 fprintf(stderr,"Need a lattice book on the command line.\n");
00131 exit(1);
00132 }
00133
00134 {
00135 char *ptr;
00136 char *filename=strdup(argv[1]);
00137
00138 b=codebook_load(filename);
00139 c=(static_codebook *)(b->c);
00140
00141 ptr=strrchr(filename,'.');
00142 if(ptr){
00143 *ptr='\0';
00144 name=strdup(filename);
00145 }else{
00146 name=strdup(filename);
00147 }
00148 }
00149
00150 if(c->maptype!=1){
00151 fprintf(stderr,"Provided book is not a latticebook.\n");
00152 exit(1);
00153 }
00154
00155 entries=b->entries;
00156 dim=b->dim;
00157 min=_float32_unpack(c->q_min);
00158 del=_float32_unpack(c->q_delta);
00159
00160
00161 if(c->q_sequencep==0){
00162
00163 long quantvals=_book_maptype1_quantvals(c);
00164 long **quantsort=alloca(quantvals*sizeof(long *));
00165 encode_aux_threshmatch *t=_ogg_calloc(1,sizeof(encode_aux_threshmatch));
00166 c->thresh_tree=t;
00167
00168 fprintf(stderr,"Adding threshold hint to %s...\n",name);
00169
00170
00171 if(argv[2]){
00172 char *ptr=strdup(argv[2]);
00173 suggestions=alloca(sizeof(float)*quantvals);
00174
00175 for(suggcount=0;ptr && suggcount<quantvals;suggcount++){
00176 char *ptr2=strchr(ptr,',');
00177 if(ptr2)*ptr2++='\0';
00178 suggestions[suggcount]=atof(ptr);
00179 ptr=ptr2;
00180 }
00181 }
00182
00183
00184 t->quantthresh=_ogg_calloc(quantvals-1,sizeof(float));
00185 t->quantmap=_ogg_calloc(quantvals,sizeof(int));
00186 t->threshvals=quantvals;
00187 t->quantvals=quantvals;
00188
00189
00190 for(i=0;i<quantvals;i++)quantsort[i]=c->quantlist+i;
00191 qsort(quantsort,quantvals,sizeof(long *),longsort);
00192
00193
00194 for(i=0;i<quantvals;i++)t->quantmap[i]=quantsort[i]-c->quantlist;
00195 for(i=0;i<quantvals-1;i++){
00196 float v1=*(quantsort[i])*del+min;
00197 float v2=*(quantsort[i+1])*del+min;
00198
00199 for(j=0;j<suggcount;j++)
00200 if(v1<suggestions[j] && suggestions[j]<v2){
00201 t->quantthresh[i]=suggestions[j];
00202 break;
00203 }
00204
00205 if(j==suggcount){
00206 t->quantthresh[i]=(v1+v2)*.5;
00207 }
00208 }
00209 }
00210
00211
00212 #if 0
00213 for(i=0;i<entries;i++)if(c->lengthlist[i]==0)break;
00214 if(c->q_sequencep || i<entries){
00215 long **tempstack;
00216 long *tempcount;
00217 long *temptrack;
00218 float *tempmin;
00219 float *tempmax;
00220 long totalstack=0;
00221 long pigeons;
00222 long subpigeons;
00223 long quantvals=_book_maptype1_quantvals(c);
00224 int changep=1,factor;
00225
00226 encode_aux_pigeonhole *p=_ogg_calloc(1,sizeof(encode_aux_pigeonhole));
00227 c->pigeon_tree=p;
00228
00229 fprintf(stderr,"Adding pigeonhole hint to %s...\n",name);
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 factor=3;
00243 p->del=del;
00244 p->min=min;
00245 p->quantvals=quantvals;
00246 {
00247 int max=0;
00248 for(i=0;i<quantvals;i++)if(max<c->quantlist[i])max=c->quantlist[i];
00249 p->mapentries=max;
00250 }
00251 p->pigeonmap=_ogg_malloc(p->mapentries*sizeof(long));
00252 p->quantvals=(quantvals+factor-1)/factor;
00253
00254
00255
00256
00257 for(i=0;i<p->mapentries;i++){
00258 float thisval=del*i+min;
00259 int quant=0;
00260 float err=fabs(c->quantlist[0]*del+min-thisval);
00261 for(j=1;j<quantvals;j++){
00262 float thiserr=fabs(c->quantlist[j]*del+min-thisval);
00263 if(thiserr<err){
00264 quant=j/factor;
00265 err=thiserr;
00266 }
00267 }
00268 p->pigeonmap[i]=quant;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 pigeons=1;
00285 subpigeons=1;
00286 for(i=0;i<dim;i++)subpigeons*=p->mapentries;
00287 for(i=0;i<dim;i++)pigeons*=p->quantvals;
00288 temptrack=_ogg_calloc(dim,sizeof(long));
00289 tempmin=_ogg_calloc(dim,sizeof(float));
00290 tempmax=_ogg_calloc(dim,sizeof(float));
00291 tempstack=_ogg_calloc(pigeons,sizeof(long *));
00292 tempcount=_ogg_calloc(pigeons,sizeof(long));
00293
00294 while(1){
00295 float errorpost=-1;
00296 char buffer[80];
00297
00298
00299
00300 int entry=0;
00301 for(i=dim-1;i>=0;i--)entry=entry*p->quantvals+p->pigeonmap[temptrack[i]];
00302 setvals(dim,p,temptrack,tempmin,tempmax,c->q_sequencep);
00303 sprintf(buffer,"Building pigeonhole search list [%ld]...",totalstack);
00304
00305
00306
00307
00308 for(i=0;i<entries;i++){
00309 if(c->lengthlist[i]>0){
00310 float this=maxerror(dim,b->valuelist+i*dim,p,
00311 temptrack,tempmin,tempmax);
00312 if(errorpost==-1 || this<errorpost)errorpost=this;
00313 spinnit(buffer,subpigeons);
00314 }
00315 }
00316
00317
00318
00319 for(i=0;i<entries;i++)
00320 if(c->lengthlist[i]>0){
00321 spinnit(buffer,subpigeons);
00322 if(minerror(dim,b->valuelist+i*dim,p,
00323 temptrack,tempmin,tempmax)<errorpost)
00324 totalstack+=addtosearch(entry,tempstack,tempcount,i);
00325 }
00326
00327 for(i=0;i<dim;i++){
00328 temptrack[i]++;
00329 if(temptrack[i]<p->mapentries)break;
00330 temptrack[i]=0;
00331 }
00332 if(i==dim)break;
00333 subpigeons--;
00334 }
00335
00336 fprintf(stderr,"\r "
00337 "\rTotal search list size (all entries): %ld\n",totalstack);
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 p->fitmap=_ogg_malloc(pigeons*sizeof(long));
00353 for(i=0;i<pigeons;i++)p->fitmap[i]=-1;
00354 while(changep){
00355 char buffer[80];
00356 changep=0;
00357
00358 for(i=0;i<pigeons;i++){
00359 if(p->fitmap[i]<0 && tempcount[i]){
00360 for(j=i+1;j<pigeons;j++){
00361 if(p->fitmap[j]<0 && tempcount[j]){
00362
00363 int amiss=0,bmiss=0,ii,jj;
00364 for(ii=0;ii<tempcount[i];ii++){
00365 for(jj=0;jj<tempcount[j];jj++)
00366 if(tempstack[i][ii]==tempstack[j][jj])break;
00367 if(jj==tempcount[j])amiss++;
00368 }
00369 for(jj=0;jj<tempcount[j];jj++){
00370 for(ii=0;ii<tempcount[i];ii++)
00371 if(tempstack[i][ii]==tempstack[j][jj])break;
00372 if(ii==tempcount[i])bmiss++;
00373 }
00374 if(amiss==0 ||
00375 bmiss==0 ||
00376 (amiss*2<tempcount[i] && bmiss*2<tempcount[j] &&
00377 tempcount[i]+bmiss<entries/30)){
00378
00379
00380 for(jj=0;jj<tempcount[j];jj++)
00381 totalstack+=addtosearch(i,tempstack,tempcount,
00382 tempstack[j][jj]);
00383 totalstack-=tempcount[j];
00384 p->fitmap[j]=i;
00385 changep=1;
00386 }
00387 }
00388 }
00389 sprintf(buffer,"Consolidating [%ld total, %s]... ",totalstack,
00390 changep?"reit":"nochange");
00391 spinnit(buffer,pigeons-i);
00392 }
00393 }
00394 }
00395
00396
00397 fprintf(stderr,"\r "
00398 "\rFinal total list size: %ld\n",totalstack);
00399
00400
00401 p->fittotal=totalstack;
00402 p->fitlist=_ogg_malloc((totalstack+1)*sizeof(long));
00403 p->fitlength=_ogg_malloc(pigeons*sizeof(long));
00404 {
00405 long usage=0;
00406 for(i=0;i<pigeons;i++){
00407 if(p->fitmap[i]==-1){
00408 if(tempcount[i])
00409 memcpy(p->fitlist+usage,tempstack[i],tempcount[i]*sizeof(long));
00410 p->fitmap[i]=usage;
00411 p->fitlength[i]=tempcount[i];
00412 usage+=tempcount[i];
00413 if(usage>totalstack){
00414 fprintf(stderr,"Internal error; usage>totalstack\n");
00415 exit(1);
00416 }
00417 }else{
00418 p->fitlength[i]=p->fitlength[p->fitmap[i]];
00419 p->fitmap[i]=p->fitmap[p->fitmap[i]];
00420 }
00421 }
00422 }
00423 }
00424 #endif
00425
00426 write_codebook(stdout,name,c);
00427 fprintf(stderr,"\r "
00428 "\nDone.\n");
00429 exit(0);
00430 }