8b15155f16cd086b11c13e99830d21593a88277e
[platform/upstream/libvorbis.git] / vq / bookutil.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5  * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
6  * PLEASE READ THESE TERMS DISTRIBUTING.                            *
7  *                                                                  *
8  * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000             *
9  * by Monty <monty@xiph.org> and The XIPHOPHORUS Company            *
10  * http://www.xiph.org/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: utility functions for loading .vqh and .vqd files
15  last mod: $Id: bookutil.c,v 1.17 2000/10/12 03:13:01 xiphmont Exp $
16
17  ********************************************************************/
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <math.h>
22 #include <string.h>
23 #include <errno.h>
24 #include "vorbis/codebook.h"
25 #include "../lib/sharedbook.h"
26 #include "bookutil.h"
27
28 /* A few little utils for reading files */
29 /* read a line.  Use global, persistent buffering */
30 static char *linebuffer=NULL;
31 static int  lbufsize=0;
32 char *get_line(FILE *in){
33   long sofar=0;
34   if(feof(in))return NULL;
35
36   while(1){
37     int gotline=0;
38
39     while(!gotline){
40       if(sofar+1>=lbufsize){
41         if(!lbufsize){  
42           lbufsize=1024;
43           linebuffer=malloc(lbufsize);
44         }else{
45           lbufsize*=2;
46           linebuffer=realloc(linebuffer,lbufsize);
47         }
48       }
49       {
50         long c=fgetc(in);
51         switch(c){
52         case EOF:
53           if(sofar==0)return(NULL);
54           /* fallthrough correct */
55         case '\n':
56           linebuffer[sofar]='\0';
57           gotline=1;
58           break;
59         default:
60           linebuffer[sofar++]=c;
61           linebuffer[sofar]='\0';
62           break;
63         }
64       }
65     }
66     
67     if(linebuffer[0]=='#'){
68       sofar=0;
69     }else{
70       return(linebuffer);
71     }
72   }
73 }
74
75 /* read the next numerical value from the given file */
76 static char *value_line_buff=NULL;
77
78 int get_line_value(FILE *in,float *value){
79   char *next;
80
81   if(!value_line_buff)return(-1);
82
83   *value=strtod(value_line_buff, &next);
84   if(next==value_line_buff){
85     value_line_buff=NULL;
86     return(-1);
87   }else{
88     value_line_buff=next;
89     while(*value_line_buff>44)value_line_buff++;
90     if(*value_line_buff==44)value_line_buff++;
91     return(0);
92   }
93 }
94
95 int get_next_value(FILE *in,float *value){
96   while(1){
97     if(get_line_value(in,value)){
98       value_line_buff=get_line(in);
99       if(!value_line_buff)return(-1);
100     }else{
101       return(0);
102     }
103   }
104 }
105
106 int get_next_ivalue(FILE *in,long *ivalue){
107   float value;
108   int ret=get_next_value(in,&value);
109   *ivalue=value;
110   return(ret);
111 }
112
113 static float sequence_base=0.;
114 static int v_sofar=0;
115 void reset_next_value(void){
116   value_line_buff=NULL;
117   sequence_base=0.;
118   v_sofar=0;
119 }
120
121 char *setup_line(FILE *in){
122   reset_next_value();
123   value_line_buff=get_line(in);
124   return(value_line_buff);
125 }
126
127
128 int get_vector(codebook *b,FILE *in,int start, int n,float *a){
129   int i;
130   const static_codebook *c=b->c;
131
132   while(1){
133
134     if(v_sofar==n || get_line_value(in,a)){
135       reset_next_value();
136       if(get_next_value(in,a))
137         break;
138       for(i=0;i<start;i++){
139         sequence_base=*a;
140         get_line_value(in,a);
141       }
142     }
143
144     for(i=1;i<c->dim;i++)
145       if(get_line_value(in,a+i))
146         break;
147     
148     if(i==c->dim){
149       float temp=a[c->dim-1];
150       for(i=0;i<c->dim;i++)a[i]-=sequence_base;
151       if(c->q_sequencep)sequence_base=temp;
152       v_sofar++;
153       return(0);
154     }
155     sequence_base=0.;
156   }
157
158   return(-1);
159 }
160
161 /* read lines fromt he beginning until we find one containing the
162    specified string */
163 char *find_seek_to(FILE *in,char *s){
164   rewind(in);
165   while(1){
166     char *line=get_line(in);
167     if(line){
168       if(strstr(line,s))
169         return(line);
170     }else
171       return(NULL);
172   }
173 }
174
175
176 /* this reads the format as written by vqbuild/latticebuild; innocent
177    (legal) tweaking of the file that would not affect its valid
178    header-ness will break this routine */
179
180 codebook *codebook_load(char *filename){
181   codebook *b=calloc(1,sizeof(codebook));
182   static_codebook *c=(static_codebook *)(b->c=calloc(1,sizeof(static_codebook)));
183   encode_aux_nearestmatch *a=NULL;
184   encode_aux_threshmatch *t=NULL;
185   encode_aux_pigeonhole *p=NULL;
186   int quant_to_read=0;
187   FILE *in=fopen(filename,"r");
188   char *line;
189   long i;
190
191   if(in==NULL){
192     fprintf(stderr,"Couldn't open codebook %s\n",filename);
193     exit(1);
194   }
195
196   /* find the codebook struct */
197   find_seek_to(in,"static static_codebook _vq_book_");
198
199   /* get the major important values */
200   line=get_line(in);
201   if(sscanf(line,"%ld, %ld,",
202             &(c->dim),&(c->entries))!=2){
203     fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
204     exit(1);
205   }
206   line=get_line(in);
207   line=get_line(in);
208   if(sscanf(line,"%d, %ld, %ld, %d, %d,",
209             &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant),
210             &(c->q_sequencep))!=5){
211     fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
212     exit(1);
213   }
214   
215   /* find the auxiliary encode struct[s] (if any) */
216   if(find_seek_to(in,"static encode_aux_nearestmatch _vq_aux")){
217     /* how big? */
218     c->nearest_tree=a=calloc(1,sizeof(encode_aux_nearestmatch));
219     line=get_line(in);
220     line=get_line(in);
221     line=get_line(in);
222     line=get_line(in);
223     line=get_line(in);
224     if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){
225       fprintf(stderr,"2: syntax in %s in line:\t %s",filename,line);
226       exit(1);
227     }
228
229     /* load ptr0 */
230     find_seek_to(in,"static long _vq_ptr0");
231     reset_next_value();
232     a->ptr0=malloc(sizeof(long)*a->aux);
233     for(i=0;i<a->aux;i++)
234       if(get_next_ivalue(in,a->ptr0+i)){
235         fprintf(stderr,"out of data while reading codebook %s\n",filename);
236         exit(1);
237       }
238     
239     /* load ptr1 */
240     find_seek_to(in,"static long _vq_ptr1");
241     reset_next_value();
242     a->ptr1=malloc(sizeof(long)*a->aux);
243     for(i=0;i<a->aux;i++)
244       if(get_next_ivalue(in,a->ptr1+i)){
245         fprintf(stderr,"out of data while reading codebook %s\n",filename);
246         exit(1);
247     }
248     
249     
250     /* load p */
251     find_seek_to(in,"static long _vq_p_");
252     reset_next_value();
253     a->p=malloc(sizeof(long)*a->aux);
254     for(i=0;i<a->aux;i++)
255       if(get_next_ivalue(in,a->p+i)){
256         fprintf(stderr,"out of data while reading codebook %s\n",filename);
257         exit(1);
258       }
259     
260     /* load q */
261     find_seek_to(in,"static long _vq_q_");
262     reset_next_value();
263     a->q=malloc(sizeof(long)*a->aux);
264     for(i=0;i<a->aux;i++)
265       if(get_next_ivalue(in,a->q+i)){
266         fprintf(stderr,"out of data while reading codebook %s\n",filename);
267         exit(1);
268       }    
269   }
270   
271   if(find_seek_to(in,"static encode_aux_threshmatch _vq_aux")){
272     /* how big? */
273     c->thresh_tree=t=calloc(1,sizeof(encode_aux_threshmatch));
274     line=get_line(in);
275     line=get_line(in);
276     line=get_line(in);
277     if(sscanf(line,"%d",&(t->quantvals))!=1){
278       fprintf(stderr,"3: syntax in %s in line:\t %s",filename,line);
279       exit(1);
280     }
281     line=get_line(in);
282     if(sscanf(line,"%d",&(t->threshvals))!=1){
283       fprintf(stderr,"4: syntax in %s in line:\t %s",filename,line);
284       exit(1);
285     }
286     /* load quantthresh */
287     find_seek_to(in,"static float _vq_quantthresh_");
288     reset_next_value();
289     t->quantthresh=malloc(sizeof(float)*t->threshvals);
290     for(i=0;i<t->threshvals-1;i++)
291       if(get_next_value(in,t->quantthresh+i)){
292         fprintf(stderr,"out of data 1 while reading codebook %s\n",filename);
293         exit(1);
294       }    
295     /* load quantmap */
296     find_seek_to(in,"static long _vq_quantmap_");
297     reset_next_value();
298     t->quantmap=malloc(sizeof(long)*t->threshvals);
299     for(i=0;i<t->threshvals;i++)
300       if(get_next_ivalue(in,t->quantmap+i)){
301         fprintf(stderr,"out of data 2 while reading codebook %s\n",filename);
302         exit(1);
303       }    
304   }
305     
306   if(find_seek_to(in,"static encode_aux_pigeonhole _vq_aux")){
307     int pigeons=1,i;
308     /* how big? */
309     c->pigeon_tree=p=calloc(1,sizeof(encode_aux_pigeonhole));
310     line=get_line(in);
311     if(sscanf(line,"%lf, %lf, %d, %d",&(p->min),&(p->del),
312               &(p->mapentries),&(p->quantvals))!=4){
313       fprintf(stderr,"5: syntax in %s in line:\t %s",filename,line);
314       exit(1);
315     }
316     line=get_line(in);
317     line=get_line(in);
318     if(sscanf(line,"%ld",&(p->fittotal))!=1){
319       fprintf(stderr,"6: syntax in %s in line:\t %s",filename,line);
320       exit(1);
321     }
322     /* load pigeonmap */
323     find_seek_to(in,"static long _vq_pigeonmap_");
324     reset_next_value();
325     p->pigeonmap=malloc(sizeof(long)*p->mapentries);
326     for(i=0;i<p->mapentries;i++)
327       if(get_next_ivalue(in,p->pigeonmap+i)){
328         fprintf(stderr,"out of data (pigeonmap) while reading codebook %s\n",filename);
329         exit(1);
330       }    
331     /* load fitlist */
332     find_seek_to(in,"static long _vq_fitlist_");
333     reset_next_value();
334     p->fitlist=malloc(sizeof(long)*p->fittotal);
335     for(i=0;i<p->fittotal;i++)
336       if(get_next_ivalue(in,p->fitlist+i)){
337         fprintf(stderr,"out of data (fitlist) while reading codebook %s\n",filename);
338         exit(1);
339       }    
340     /* load fitmap */
341     find_seek_to(in,"static long _vq_fitmap_");
342     reset_next_value();
343     for(i=0;i<c->dim;i++)pigeons*=p->quantvals;
344     p->fitmap=malloc(sizeof(long)*pigeons);
345     for(i=0;i<pigeons;i++)
346       if(get_next_ivalue(in,p->fitmap+i)){
347         fprintf(stderr,"out of data (fitmap) while reading codebook %s\n",filename);
348         exit(1);
349       }    
350  
351     /* load fitlength */
352     find_seek_to(in,"static long _vq_fitlength_");
353     reset_next_value();
354     p->fitlength=malloc(sizeof(long)*pigeons);
355     for(i=0;i<pigeons;i++)
356       if(get_next_ivalue(in,p->fitlength+i)){
357         fprintf(stderr,"out of data (fitlength) while reading codebook %s\n",filename);
358         exit(1);
359       }    
360   }
361
362   switch(c->maptype){
363   case 0:
364     quant_to_read=0;
365     break;
366   case 1:
367     quant_to_read=_book_maptype1_quantvals(c);
368     break;
369   case 2:
370     quant_to_read=c->entries*c->dim;
371     break;
372   }
373     
374   /* load the quantized entries */
375   find_seek_to(in,"static long _vq_quantlist_");
376   reset_next_value();
377   c->quantlist=malloc(sizeof(long)*quant_to_read);
378   for(i=0;i<quant_to_read;i++)
379     if(get_next_ivalue(in,c->quantlist+i)){
380       fprintf(stderr,"out of data while reading codebook %s\n",filename);
381       exit(1);
382     }
383   
384   /* load the lengthlist */
385   find_seek_to(in,"static long _vq_lengthlist");
386   reset_next_value();
387   c->lengthlist=malloc(sizeof(long)*c->entries);
388   for(i=0;i<c->entries;i++)
389     if(get_next_ivalue(in,c->lengthlist+i)){
390       fprintf(stderr,"out of data while reading codebook %s\n",filename);
391       exit(1);
392     }
393
394   /* got it all */
395   fclose(in);
396   
397   vorbis_book_init_encode(b,c);
398
399   return(b);
400 }
401
402 void spinnit(char *s,int n){
403   static int p=0;
404   static long lasttime=0;
405   long test;
406   struct timeval thistime;
407
408   gettimeofday(&thistime,NULL);
409   test=thistime.tv_sec*10+thistime.tv_usec/100000;
410   if(lasttime!=test){
411     lasttime=test;
412
413     fprintf(stderr,"%s%d ",s,n);
414
415     p++;if(p>3)p=0;
416     switch(p){
417     case 0:
418       fprintf(stderr,"|    \r");
419       break;
420     case 1:
421       fprintf(stderr,"/    \r");
422       break;
423     case 2:
424       fprintf(stderr,"-    \r");
425       break;
426     case 3:
427       fprintf(stderr,"\\    \r");
428       break;
429     }
430     fflush(stderr);
431   }
432 }
433
434 void build_tree_from_lengths(int vals, long *hist, long *lengths){
435   int i,j;
436   long *membership=malloc(vals*sizeof(long));
437   long *histsave=alloca(vals*sizeof(long));
438   memcpy(histsave,hist,vals*sizeof(long));
439
440   for(i=0;i<vals;i++)membership[i]=i;
441
442   /* find codeword lengths */
443   /* much more elegant means exist.  Brute force n^2, minimum thought */
444   for(i=vals;i>1;i--){
445     int first=-1,second=-1;
446     long least=-1;
447         
448     spinnit("building... ",i);
449     
450     /* find the two nodes to join */
451     for(j=0;j<vals;j++)
452       if(least==-1 || hist[j]<least){
453         least=hist[j];
454         first=membership[j];
455       }
456     least=-1;
457     for(j=0;j<vals;j++)
458       if((least==-1 || hist[j]<least) && membership[j]!=first){
459         least=hist[j];
460         second=membership[j];
461       }
462     if(first==-1 || second==-1){
463       fprintf(stderr,"huffman fault; no free branch\n");
464       exit(1);
465     }
466     
467     /* join them */
468     least=hist[first]+hist[second];
469     for(j=0;j<vals;j++)
470       if(membership[j]==first || membership[j]==second){
471         membership[j]=first;
472         hist[j]=least;
473         lengths[j]++;
474       }
475   }
476   for(i=0;i<vals-1;i++)
477     if(membership[i]!=membership[i+1]){
478       fprintf(stderr,"huffman fault; failed to build single tree\n");
479       exit(1);
480     }
481
482   /* for sanity check purposes: how many bits would it have taken to
483      encode the training set? */
484   {
485     long bitsum=0;
486     long samples=0;
487     for(i=0;i<vals;i++){
488       bitsum+=(histsave[i]-1)*lengths[i];
489       samples+=histsave[i]-1;
490     }
491
492     if(samples){
493       fprintf(stderr,"\rTotal samples in training set: %ld      \n",samples);
494       fprintf(stderr,"\rTotal bits used to represent training set: %ld\n",
495               bitsum);
496     }
497   }
498
499   free(membership);
500 }
501
502 /* wrap build_tree_from_lengths to allow zero entries in the histogram */
503 void build_tree_from_lengths0(int vals, long *hist, long *lengths){
504
505   /* pack the 'sparse' hit list into a dense list, then unpack
506      the lengths after the build */
507
508   int upper=0,i;
509   long *lengthlist=calloc(vals,sizeof(long));
510   long *newhist=alloca(vals*sizeof(long));
511
512   for(i=0;i<vals;i++)
513     if(hist[i]>0)
514       newhist[upper++]=hist[i];
515
516   if(upper != vals){
517     fprintf(stderr,"\rEliminating %d unused entries; %d entries remain\n",
518             vals-upper,upper);
519   }
520     
521   build_tree_from_lengths(upper,newhist,lengthlist);
522       
523   upper=0;
524   for(i=0;i<vals;i++)
525     if(hist[i]>0)
526       lengths[i]=lengthlist[upper++];
527     else
528       lengths[i]=0;
529
530   free(lengthlist);
531 }
532
533 void write_codebook(FILE *out,char *name,const static_codebook *c){
534   encode_aux_pigeonhole *p=c->pigeon_tree;
535   encode_aux_threshmatch *t=c->thresh_tree;
536   encode_aux_nearestmatch *n=c->nearest_tree;
537   int i,j,k;
538
539   /* save the book in C header form */
540   fprintf(out,
541  "/********************************************************************\n"
542  " *                                                                  *\n"
543  " * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *\n"
544  " * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *\n"
545  " * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *\n"
546  " * PLEASE READ THESE TERMS DISTRIBUTING.                            *\n"
547  " *                                                                  *\n"
548  " * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *\n"
549  " * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *\n"
550  " * http://www.xiph.org/                                             *\n"
551  " *                                                                  *\n"
552  " ********************************************************************\n"
553  "\n"
554  " function: static codebook autogenerated by vq/somethingorother\n"
555  "\n"
556  " ********************************************************************/\n\n");
557
558   fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
559   fprintf(out,"#include \"vorbis/codebook.h\"\n\n");
560
561   /* first, the static vectors, then the book structure to tie it together. */
562   /* quantlist */
563   if(c->quantlist){
564     long vals=(c->maptype==1?_book_maptype1_quantvals(c):c->entries*c->dim);
565     fprintf(out,"static long _vq_quantlist_%s[] = {\n",name);
566     for(j=0;j<vals;j++){
567       fprintf(out,"\t%ld,\n",c->quantlist[j]);
568     }
569     fprintf(out,"};\n\n");
570   }
571
572   /* lengthlist */
573   fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
574   for(j=0;j<c->entries;){
575     fprintf(out,"\t");
576     for(k=0;k<16 && j<c->entries;k++,j++)
577       fprintf(out,"%2ld,",c->lengthlist[j]);
578     fprintf(out,"\n");
579   }
580   fprintf(out,"};\n\n");
581
582   if(t){
583     /* quantthresh */
584     fprintf(out,"static float _vq_quantthresh_%s[] = {\n",name);
585     for(j=0;j<t->threshvals-1;){
586       fprintf(out,"\t");
587       for(k=0;k<8 && j<t->threshvals-1;k++,j++)
588         fprintf(out,"%.5g, ",t->quantthresh[j]);
589       fprintf(out,"\n");
590     }
591     fprintf(out,"};\n\n");
592
593     /* quantmap */
594     fprintf(out,"static long _vq_quantmap_%s[] = {\n",name);
595     for(j=0;j<t->threshvals;){
596       fprintf(out,"\t");
597       for(k=0;k<8 && j<t->threshvals;k++,j++)
598         fprintf(out,"%5ld,",t->quantmap[j]);
599       fprintf(out,"\n");
600     }
601     fprintf(out,"};\n\n");  
602
603     fprintf(out,"static encode_aux_threshmatch _vq_auxt_%s = {\n",name);
604     fprintf(out,"\t_vq_quantthresh_%s,\n",name);
605     fprintf(out,"\t_vq_quantmap_%s,\n",name);
606     fprintf(out,"\t%d,\n",t->quantvals);
607     fprintf(out,"\t%d\n};\n\n",t->threshvals);
608   }
609
610   if(p){
611     int pigeons=1;
612     for(i=0;i<c->dim;i++)pigeons*=p->quantvals;
613
614     /* pigeonmap */
615     fprintf(out,"static long _vq_pigeonmap_%s[] = {\n",name);
616     for(j=0;j<p->mapentries;){
617       fprintf(out,"\t");
618       for(k=0;k<8 && j<p->mapentries;k++,j++)
619         fprintf(out,"%5ld, ",p->pigeonmap[j]);
620       fprintf(out,"\n");
621     }
622     fprintf(out,"};\n\n");
623     /* fitlist */
624     fprintf(out,"static long _vq_fitlist_%s[] = {\n",name);
625     for(j=0;j<p->fittotal;){
626       fprintf(out,"\t");
627       for(k=0;k<8 && j<p->fittotal;k++,j++)
628         fprintf(out,"%5ld, ",p->fitlist[j]);
629       fprintf(out,"\n");
630     }
631     fprintf(out,"};\n\n");
632     /* fitmap */
633     fprintf(out,"static long _vq_fitmap_%s[] = {\n",name);
634     for(j=0;j<pigeons;){
635       fprintf(out,"\t");
636       for(k=0;k<8 && j<pigeons;k++,j++)
637         fprintf(out,"%5ld, ",p->fitmap[j]);
638       fprintf(out,"\n");
639     }
640     fprintf(out,"};\n\n");
641     /* fitlength */
642     fprintf(out,"static long _vq_fitlength_%s[] = {\n",name);
643     for(j=0;j<pigeons;){
644       fprintf(out,"\t");
645       for(k=0;k<8 && j<pigeons;k++,j++)
646         fprintf(out,"%5ld, ",p->fitlength[j]);
647       fprintf(out,"\n");
648     }
649     fprintf(out,"};\n\n");
650
651     fprintf(out,"static encode_aux_pigeonhole _vq_auxp_%s = {\n",name);
652     fprintf(out,"\t%g, %g, %d, %d,\n",
653             p->min,p->del,p->mapentries,p->quantvals);
654
655     fprintf(out,"\t_vq_pigeonmap_%s,\n",name);
656
657     fprintf(out,"\t%ld,\n",p->fittotal);
658     fprintf(out,"\t_vq_fitlist_%s,\n",name);
659     fprintf(out,"\t_vq_fitmap_%s,\n",name);
660     fprintf(out,"\t_vq_fitlength_%s\n};\n\n",name);
661   }
662
663   if(n){
664     
665     /* ptr0 */
666     fprintf(out,"static long _vq_ptr0_%s[] = {\n",name);
667     for(j=0;j<n->aux;){
668       fprintf(out,"\t");
669       for(k=0;k<8 && j<n->aux;k++,j++)
670         fprintf(out,"%6ld,",n->ptr0[j]);
671       fprintf(out,"\n");
672     }
673     fprintf(out,"};\n\n");
674     
675     /* ptr1 */
676     fprintf(out,"static long _vq_ptr1_%s[] = {\n",name);
677     for(j=0;j<n->aux;){
678       fprintf(out,"\t");
679       for(k=0;k<8 && j<n->aux;k++,j++)
680         fprintf(out,"%6ld,",n->ptr1[j]);
681       fprintf(out,"\n");
682     }
683     fprintf(out,"};\n\n");
684     
685     /* p */
686     fprintf(out,"static long _vq_p_%s[] = {\n",name);
687     for(j=0;j<n->aux;){
688       fprintf(out,"\t");
689       for(k=0;k<8 && j<n->aux;k++,j++)
690         fprintf(out,"%6ld,",n->p[j]*c->dim);
691       fprintf(out,"\n");
692     }
693     fprintf(out,"};\n\n");
694     
695     /* q */
696     fprintf(out,"static long _vq_q_%s[] = {\n",name);
697     for(j=0;j<n->aux;){
698       fprintf(out,"\t");
699       for(k=0;k<8 && j<n->aux;k++,j++)
700         fprintf(out,"%6ld,",n->q[j]*c->dim);
701       fprintf(out,"\n");
702     }
703     fprintf(out,"};\n\n");
704   
705     fprintf(out,"static encode_aux_nearestmatch _vq_auxn_%s = {\n",name);
706     fprintf(out,"\t_vq_ptr0_%s,\n",name);
707     fprintf(out,"\t_vq_ptr1_%s,\n",name);
708     fprintf(out,"\t_vq_p_%s,\n",name);
709     fprintf(out,"\t_vq_q_%s,\n",name);
710     fprintf(out,"\t%ld, %ld\n};\n\n",n->aux,n->aux);
711   }
712
713   /* tie it all together */
714   
715   fprintf(out,"static static_codebook _vq_book_%s = {\n",name);
716   
717   fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries);
718   fprintf(out,"\t_vq_lengthlist_%s,\n",name);
719   fprintf(out,"\t%d, %ld, %ld, %d, %d,\n",
720           c->maptype,c->q_min,c->q_delta,c->q_quant,c->q_sequencep);
721   if(c->quantlist)
722     fprintf(out,"\t_vq_quantlist_%s,\n",name);
723   else
724     fprintf(out,"\tNULL,\n");
725
726   if(n)
727     fprintf(out,"\t&_vq_auxn_%s,\n",name);
728   else
729     fprintf(out,"\tNULL,\n");
730   if(t)
731     fprintf(out,"\t&_vq_auxt_%s,\n",name);
732   else
733     fprintf(out,"\tNULL,\n");
734   if(p)
735     fprintf(out,"\t&_vq_auxp_%s,\n",name);
736   else
737     fprintf(out,"\tNULL,\n");
738
739   fprintf(out,"};\n\n");
740
741   fprintf(out,"\n#endif\n");
742 }