final beta 4 commit
[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.4 2001/02/26 03:51:12 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         /* do a rough count */
107         for(j=0;j<b->entries;j++){
108           int indexdiv=1;
109           for(k=0;k<b->dim;k++){
110             if(c->lengthlist[j]){
111               int index= (j/indexdiv)%bins;
112               countarray[index]+=(1<<(base-c->lengthlist[j]));
113               indexdiv*=bins;
114             }
115           }
116         }
117
118         /* dump the count */
119
120         {
121           long maxcount=0,i,j;
122           for(i=0;i<bins;i++)
123             if(countarray[i]>maxcount)maxcount=countarray[i];
124       
125           for(i=0;i<bins;i++){
126             int ptr=sort[i]-c->quantlist;
127             int stars=rint(50./maxcount*countarray[ptr]);
128             printf("%+08f (%8ld) |",c->quantlist[ptr]*delta+min,countarray[ptr]);
129             for(j=0;j<stars;j++)printf("*");
130             printf("\n");
131           }
132         }
133       }
134       break;
135     case 2:
136       {
137         /* trained, full mapping codebook. */
138         printf("Can't do probability dump of a trained [type 2] codebook (yet)\n");
139       }
140       break;
141     }
142   }else{
143     /* load/count a data file */
144
145     /* do it the simple way; two pass. */
146     line=setup_line(in);
147     while(line){      
148       float code;
149       lines++;
150       if(!(lines&0xff))spinnit("getting min/max. lines so far...",lines);
151       
152       while(!flag && sscanf(line,"%f",&code)==1){
153         line=strchr(line,',');
154         min=max=code;
155         flag=1;
156       }
157       
158       while(sscanf(line,"%f",&code)==1){
159         line=strchr(line,',');
160         if(line)line++;
161         if(code<min)min=code;
162         if(code>max)max=code;
163       }
164       
165       line=setup_line(in);
166     }
167     
168     if(bins<1){
169       if((int)(max-min)==min-max){
170         bins=max-min;
171       }else{
172         bins=25;
173       }
174     }
175     
176     printf("\r                                                     \r");
177     printf("Minimum scalar value: %f\n",min);
178     printf("Maximum scalar value: %f\n",max);
179     
180     printf("\n counting hits into %d bins...\n",bins+1);
181     countarray=calloc(bins+1,sizeof(long));
182     
183     rewind(in);
184     line=setup_line(in);
185     while(line){      
186       float code;
187       lines--;
188       if(!(lines&0xff))spinnit("counting distribution. lines so far...",lines);
189       
190       while(sscanf(line,"%f",&code)==1){
191         line=strchr(line,',');
192         if(line)line++;
193         
194         code-=min;
195         code/=(max-min);
196         code*=bins;
197         countarray[(int)rint(code)]++;
198         total++;
199       }
200       
201       line=setup_line(in);
202     }
203
204     fclose(in);
205     
206     /* make a pretty graph */
207     {
208       long maxcount=0,i,j;
209       for(i=0;i<bins+1;i++)
210         if(countarray[i]>maxcount)maxcount=countarray[i];
211       
212       printf("\r                                                     \r");
213       printf("Total scalars: %ld\n",total);
214       for(i=0;i<bins+1;i++){
215         int stars=rint(50./maxcount*countarray[i]);
216         printf("%08f (%8ld) |",(max-min)/bins*i+min,countarray[i]);
217         for(j=0;j<stars;j++)printf("*");
218       printf("\n");
219       }
220     }
221   }
222   printf("\nDone.\n");
223   exit(0);
224 }