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 }