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