Additional optimizations, rearrangement.
[platform/upstream/libvorbis.git] / vq / distribution.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
10
11  ********************************************************************
12
13  function: utility for finding the distribution in a data set
14  last mod: $Id: distribution.c,v 1.6 2001/06/15 21:15:43 xiphmont Exp $
15
16  ********************************************************************/
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <math.h>
21 #include <string.h>
22 #include <errno.h>
23 #include "bookutil.h"
24
25 /* command line:
26    distribution file.vqd
27 */
28
29 int ascend(const void *a,const void *b){
30   return(**((long **)a)-**((long **)b));
31 }
32
33 int main(int argc,char *argv[]){
34   FILE *in;
35   long lines=0;
36   float min;
37   float max;
38   long bins=-1;
39   int flag=0;
40   long *countarray;
41   long total=0;
42   char *line;
43
44   if(argv[1]==NULL){
45     fprintf(stderr,"Usage: distribution {data.vqd [bins]| book.vqh} \n\n");
46     exit(1);
47   }
48   if(argv[2]!=NULL)
49     bins=atoi(argv[2])-1;
50
51   in=fopen(argv[1],"r");
52   if(!in){
53     fprintf(stderr,"Could not open input file %s\n",argv[1]);
54     exit(1);
55   }
56
57   if(strrchr(argv[1],'.') && strcmp(strrchr(argv[1],'.'),".vqh")==0){
58     /* load/decode a book */
59
60     codebook *b=codebook_load(argv[1]);
61     static_codebook *c=(static_codebook *)(b->c);
62     float delta;
63     int i;
64     fclose(in);
65
66     switch(c->maptype){
67     case 0:
68       printf("entropy codebook only; no mappings\n");
69       exit(0);
70       break;
71     case 1:
72       bins=_book_maptype1_quantvals(c);
73       break;
74     case 2:
75       bins=c->entries*c->dim;
76       break;
77     }
78
79     max=min=_float32_unpack(c->q_min);
80     delta=_float32_unpack(c->q_delta);
81
82     for(i=0;i<bins;i++){
83       float val=c->quantlist[i]*delta+min;
84       if(val>max)max=val;
85     }
86
87     printf("Minimum scalar value: %f\n",min);
88     printf("Maximum scalar value: %f\n",max);
89
90     switch(c->maptype){
91     case 1:
92       {
93         /* lattice codebook.  dump it. */
94         int j,k;
95         long maxcount=0;
96         long **sort=calloc(bins,sizeof(long *));
97         long base=c->lengthlist[0];
98         countarray=calloc(bins,sizeof(long));
99
100         for(i=0;i<bins;i++)sort[i]=c->quantlist+i;
101         qsort(sort,bins,sizeof(long *),ascend);
102
103         for(i=0;i<b->entries;i++)
104           if(c->lengthlist[i]>base)base=c->lengthlist[i];
105
106         /* dump a full, correlated count */
107         for(j=0;j<b->entries;j++){
108           if(c->lengthlist[j]){
109             int indexdiv=1;
110             printf("%4ld: ",j);
111             for(k=0;k<b->dim;k++){      
112               int index= (j/indexdiv)%bins;
113               printf("%+3.1f,", c->quantlist[index]*_float32_unpack(c->q_delta)+
114                      _float32_unpack(c->q_min));
115               indexdiv*=bins;
116             }
117             printf("\t|",(1<<(base-c->lengthlist[j])));
118             for(k=0;k<base-c->lengthlist[j];k++)printf("*");
119             printf("\n");
120           }
121         }
122
123         /* do a rough count */
124         for(j=0;j<b->entries;j++){
125           int indexdiv=1;
126           for(k=0;k<b->dim;k++){
127             if(c->lengthlist[j]){
128               int index= (j/indexdiv)%bins;
129               countarray[index]+=(1<<(base-c->lengthlist[j]));
130               indexdiv*=bins;
131             }
132           }
133         }
134
135         /* dump the count */
136
137         {
138           long maxcount=0,i,j;
139           for(i=0;i<bins;i++)
140             if(countarray[i]>maxcount)maxcount=countarray[i];
141       
142           for(i=0;i<bins;i++){
143             int ptr=sort[i]-c->quantlist;
144             int stars=rint(50./maxcount*countarray[ptr]);
145             printf("%+08f (%8ld) |",c->quantlist[ptr]*delta+min,countarray[ptr]);
146             for(j=0;j<stars;j++)printf("*");
147             printf("\n");
148           }
149         }
150       }
151       break;
152     case 2:
153       {
154         /* trained, full mapping codebook. */
155         printf("Can't do probability dump of a trained [type 2] codebook (yet)\n");
156       }
157       break;
158     }
159   }else{
160     /* load/count a data file */
161
162     /* do it the simple way; two pass. */
163     line=setup_line(in);
164     while(line){      
165       float code;
166       lines++;
167       if(!(lines&0xff))spinnit("getting min/max. lines so far...",lines);
168       
169       while(!flag && sscanf(line,"%f",&code)==1){
170         line=strchr(line,',');
171         min=max=code;
172         flag=1;
173       }
174       
175       while(line && sscanf(line,"%f",&code)==1){
176         line=strchr(line,',');
177         if(line)line++;
178         if(code<min)min=code;
179         if(code>max)max=code;
180       }
181       
182       line=setup_line(in);
183     }
184     
185     if(bins<1){
186       if((int)(max-min)==min-max){
187         bins=max-min;
188       }else{
189         bins=25;
190       }
191     }
192     
193     printf("\r                                                     \r");
194     printf("Minimum scalar value: %f\n",min);
195     printf("Maximum scalar value: %f\n",max);
196     
197     printf("\n counting hits into %d bins...\n",bins+1);
198     countarray=calloc(bins+1,sizeof(long));
199     
200     rewind(in);
201     line=setup_line(in);
202     while(line){      
203       float code;
204       lines--;
205       if(!(lines&0xff))spinnit("counting distribution. lines so far...",lines);
206       
207       while(line && sscanf(line,"%f",&code)==1){
208         line=strchr(line,',');
209         if(line)line++;
210         
211         code-=min;
212         code/=(max-min);
213         code*=bins;
214         countarray[(int)rint(code)]++;
215         total++;
216       }
217       
218       line=setup_line(in);
219     }
220
221     fclose(in);
222     
223     /* make a pretty graph */
224     {
225       long maxcount=0,i,j;
226       for(i=0;i<bins+1;i++)
227         if(countarray[i]>maxcount)maxcount=countarray[i];
228       
229       printf("\r                                                     \r");
230       printf("Total scalars: %ld\n",total);
231       for(i=0;i<bins+1;i++){
232         int stars=rint(50./maxcount*countarray[i]);
233         printf("%08f (%8ld) |",(max-min)/bins*i+min,countarray[i]);
234         for(j=0;j<stars;j++)printf("*");
235       printf("\n");
236       }
237     }
238   }
239   printf("\nDone.\n");
240   exit(0);
241 }