Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/libvorbis-1.2.0/lib/sharedbook.c @ 16

Last change on this file since 16 was 16, checked in by landauf, 17 years ago

added libvorbis

File size: 19.4 KB
Line 
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-2007             *
9 * by the Xiph.Org Foundation http://www.xiph.org/                  *
10 *                                                                  *
11 ********************************************************************
12
13 function: basic shared codebook operations
14 last mod: $Id: sharedbook.c 13293 2007-07-24 00:09:47Z xiphmont $
15
16 ********************************************************************/
17
18#include <stdlib.h>
19#include <math.h>
20#include <string.h>
21#include <ogg/ogg.h>
22#include "os.h"
23#include "misc.h"
24#include "vorbis/codec.h"
25#include "codebook.h"
26#include "scales.h"
27
28/**** pack/unpack helpers ******************************************/
29int _ilog(unsigned int v){
30  int ret=0;
31  while(v){
32    ret++;
33    v>>=1;
34  }
35  return(ret);
36}
37
38/* 32 bit float (not IEEE; nonnormalized mantissa +
39   biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm
40   Why not IEEE?  It's just not that important here. */
41
42#define VQ_FEXP 10
43#define VQ_FMAN 21
44#define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */
45
46/* doesn't currently guard under/overflow */
47long _float32_pack(float val){
48  int sign=0;
49  long exp;
50  long mant;
51  if(val<0){
52    sign=0x80000000;
53    val= -val;
54  }
55  exp= floor(log(val)/log(2.f));
56  mant=rint(ldexp(val,(VQ_FMAN-1)-exp));
57  exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN;
58
59  return(sign|exp|mant);
60}
61
62float _float32_unpack(long val){
63  double mant=val&0x1fffff;
64  int    sign=val&0x80000000;
65  long   exp =(val&0x7fe00000L)>>VQ_FMAN;
66  if(sign)mant= -mant;
67  return(ldexp(mant,exp-(VQ_FMAN-1)-VQ_FEXP_BIAS));
68}
69
70/* given a list of word lengths, generate a list of codewords.  Works
71   for length ordered or unordered, always assigns the lowest valued
72   codewords first.  Extended to handle unused entries (length 0) */
73ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
74  long i,j,count=0;
75  ogg_uint32_t marker[33];
76  ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
77  memset(marker,0,sizeof(marker));
78
79  for(i=0;i<n;i++){
80    long length=l[i];
81    if(length>0){
82      ogg_uint32_t entry=marker[length];
83     
84      /* when we claim a node for an entry, we also claim the nodes
85         below it (pruning off the imagined tree that may have dangled
86         from it) as well as blocking the use of any nodes directly
87         above for leaves */
88     
89      /* update ourself */
90      if(length<32 && (entry>>length)){
91        /* error condition; the lengths must specify an overpopulated tree */
92        _ogg_free(r);
93        return(NULL);
94      }
95      r[count++]=entry;
96   
97      /* Look to see if the next shorter marker points to the node
98         above. if so, update it and repeat.  */
99      {
100        for(j=length;j>0;j--){
101         
102          if(marker[j]&1){
103            /* have to jump branches */
104            if(j==1)
105              marker[1]++;
106            else
107              marker[j]=marker[j-1]<<1;
108            break; /* invariant says next upper marker would already
109                      have been moved if it was on the same path */
110          }
111          marker[j]++;
112        }
113      }
114     
115      /* prune the tree; the implicit invariant says all the longer
116         markers were dangling from our just-taken node.  Dangle them
117         from our *new* node. */
118      for(j=length+1;j<33;j++)
119        if((marker[j]>>1) == entry){
120          entry=marker[j];
121          marker[j]=marker[j-1]<<1;
122        }else
123          break;
124    }else
125      if(sparsecount==0)count++;
126  }
127   
128  /* bitreverse the words because our bitwise packer/unpacker is LSb
129     endian */
130  for(i=0,count=0;i<n;i++){
131    ogg_uint32_t temp=0;
132    for(j=0;j<l[i];j++){
133      temp<<=1;
134      temp|=(r[count]>>j)&1;
135    }
136
137    if(sparsecount){
138      if(l[i])
139        r[count++]=temp;
140    }else
141      r[count++]=temp;
142  }
143
144  return(r);
145}
146
147/* there might be a straightforward one-line way to do the below
148   that's portable and totally safe against roundoff, but I haven't
149   thought of it.  Therefore, we opt on the side of caution */
150long _book_maptype1_quantvals(const static_codebook *b){
151  long vals=floor(pow((float)b->entries,1.f/b->dim));
152
153  /* the above *should* be reliable, but we'll not assume that FP is
154     ever reliable when bitstream sync is at stake; verify via integer
155     means that vals really is the greatest value of dim for which
156     vals^b->bim <= b->entries */
157  /* treat the above as an initial guess */
158  while(1){
159    long acc=1;
160    long acc1=1;
161    int i;
162    for(i=0;i<b->dim;i++){
163      acc*=vals;
164      acc1*=vals+1;
165    }
166    if(acc<=b->entries && acc1>b->entries){
167      return(vals);
168    }else{
169      if(acc>b->entries){
170        vals--;
171      }else{
172        vals++;
173      }
174    }
175  }
176}
177
178/* unpack the quantized list of values for encode/decode ***********/
179/* we need to deal with two map types: in map type 1, the values are
180   generated algorithmically (each column of the vector counts through
181   the values in the quant vector). in map type 2, all the values came
182   in in an explicit list.  Both value lists must be unpacked */
183float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){
184  long j,k,count=0;
185  if(b->maptype==1 || b->maptype==2){
186    int quantvals;
187    float mindel=_float32_unpack(b->q_min);
188    float delta=_float32_unpack(b->q_delta);
189    float *r=_ogg_calloc(n*b->dim,sizeof(*r));
190
191    /* maptype 1 and 2 both use a quantized value vector, but
192       different sizes */
193    switch(b->maptype){
194    case 1:
195      /* most of the time, entries%dimensions == 0, but we need to be
196         well defined.  We define that the possible vales at each
197         scalar is values == entries/dim.  If entries%dim != 0, we'll
198         have 'too few' values (values*dim<entries), which means that
199         we'll have 'left over' entries; left over entries use zeroed
200         values (and are wasted).  So don't generate codebooks like
201         that */
202      quantvals=_book_maptype1_quantvals(b);
203      for(j=0;j<b->entries;j++){
204        if((sparsemap && b->lengthlist[j]) || !sparsemap){
205          float last=0.f;
206          int indexdiv=1;
207          for(k=0;k<b->dim;k++){
208            int index= (j/indexdiv)%quantvals;
209            float val=b->quantlist[index];
210            val=fabs(val)*delta+mindel+last;
211            if(b->q_sequencep)last=val;   
212            if(sparsemap)
213              r[sparsemap[count]*b->dim+k]=val;
214            else
215              r[count*b->dim+k]=val;
216            indexdiv*=quantvals;
217          }
218          count++;
219        }
220
221      }
222      break;
223    case 2:
224      for(j=0;j<b->entries;j++){
225        if((sparsemap && b->lengthlist[j]) || !sparsemap){
226          float last=0.f;
227         
228          for(k=0;k<b->dim;k++){
229            float val=b->quantlist[j*b->dim+k];
230            val=fabs(val)*delta+mindel+last;
231            if(b->q_sequencep)last=val;   
232            if(sparsemap)
233              r[sparsemap[count]*b->dim+k]=val;
234            else
235              r[count*b->dim+k]=val;
236          }
237          count++;
238        }
239      }
240      break;
241    }
242
243    return(r);
244  }
245  return(NULL);
246}
247
248void vorbis_staticbook_clear(static_codebook *b){
249  if(b->allocedp){
250    if(b->quantlist)_ogg_free(b->quantlist);
251    if(b->lengthlist)_ogg_free(b->lengthlist);
252    if(b->nearest_tree){
253      _ogg_free(b->nearest_tree->ptr0);
254      _ogg_free(b->nearest_tree->ptr1);
255      _ogg_free(b->nearest_tree->p);
256      _ogg_free(b->nearest_tree->q);
257      memset(b->nearest_tree,0,sizeof(*b->nearest_tree));
258      _ogg_free(b->nearest_tree);
259    }
260    if(b->thresh_tree){
261      _ogg_free(b->thresh_tree->quantthresh);
262      _ogg_free(b->thresh_tree->quantmap);
263      memset(b->thresh_tree,0,sizeof(*b->thresh_tree));
264      _ogg_free(b->thresh_tree);
265    }
266
267    memset(b,0,sizeof(*b));
268  }
269}
270
271void vorbis_staticbook_destroy(static_codebook *b){
272  if(b->allocedp){
273    vorbis_staticbook_clear(b);
274    _ogg_free(b);
275  }
276}
277
278void vorbis_book_clear(codebook *b){
279  /* static book is not cleared; we're likely called on the lookup and
280     the static codebook belongs to the info struct */
281  if(b->valuelist)_ogg_free(b->valuelist);
282  if(b->codelist)_ogg_free(b->codelist);
283
284  if(b->dec_index)_ogg_free(b->dec_index);
285  if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
286  if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
287
288  memset(b,0,sizeof(*b));
289}
290
291int vorbis_book_init_encode(codebook *c,const static_codebook *s){
292
293  memset(c,0,sizeof(*c));
294  c->c=s;
295  c->entries=s->entries;
296  c->used_entries=s->entries;
297  c->dim=s->dim;
298  c->codelist=_make_words(s->lengthlist,s->entries,0);
299  c->valuelist=_book_unquantize(s,s->entries,NULL);
300
301  return(0);
302}
303
304static ogg_uint32_t bitreverse(ogg_uint32_t x){
305  x=    ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL);
306  x=    ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL);
307  x=    ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL);
308  x=    ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL);
309  return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL);
310}
311
312static int sort32a(const void *a,const void *b){
313  return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)- 
314    ( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b);
315}
316
317/* decode codebook arrangement is more heavily optimized than encode */
318int vorbis_book_init_decode(codebook *c,const static_codebook *s){
319  int i,j,n=0,tabn;
320  int *sortindex;
321  memset(c,0,sizeof(*c));
322 
323  /* count actually used entries */
324  for(i=0;i<s->entries;i++)
325    if(s->lengthlist[i]>0)
326      n++;
327
328  c->entries=s->entries;
329  c->used_entries=n;
330  c->dim=s->dim;
331
332  if(n>0){
333   
334    /* two different remappings go on here. 
335       
336    First, we collapse the likely sparse codebook down only to
337    actually represented values/words.  This collapsing needs to be
338    indexed as map-valueless books are used to encode original entry
339    positions as integers.
340   
341    Second, we reorder all vectors, including the entry index above,
342    by sorted bitreversed codeword to allow treeless decode. */
343
344    /* perform sort */
345    ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
346    ogg_uint32_t **codep=alloca(sizeof(*codep)*n);
347   
348    if(codes==NULL)goto err_out;
349   
350    for(i=0;i<n;i++){
351      codes[i]=bitreverse(codes[i]);
352      codep[i]=codes+i;
353    }
354   
355    qsort(codep,n,sizeof(*codep),sort32a);
356   
357    sortindex=alloca(n*sizeof(*sortindex));
358    c->codelist=_ogg_malloc(n*sizeof(*c->codelist));
359    /* the index is a reverse index */
360    for(i=0;i<n;i++){
361      int position=codep[i]-codes;
362      sortindex[position]=i;
363    }
364
365    for(i=0;i<n;i++)
366      c->codelist[sortindex[i]]=codes[i];
367    _ogg_free(codes);
368 
369
370    c->valuelist=_book_unquantize(s,n,sortindex);
371    c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index));
372   
373    for(n=0,i=0;i<s->entries;i++)
374      if(s->lengthlist[i]>0)
375        c->dec_index[sortindex[n++]]=i;
376   
377    c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths));
378    for(n=0,i=0;i<s->entries;i++)
379      if(s->lengthlist[i]>0)
380        c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
381   
382    c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
383    if(c->dec_firsttablen<5)c->dec_firsttablen=5;
384    if(c->dec_firsttablen>8)c->dec_firsttablen=8;
385   
386    tabn=1<<c->dec_firsttablen;
387    c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
388    c->dec_maxlength=0;
389   
390    for(i=0;i<n;i++){
391      if(c->dec_maxlength<c->dec_codelengths[i])
392        c->dec_maxlength=c->dec_codelengths[i];
393      if(c->dec_codelengths[i]<=c->dec_firsttablen){
394        ogg_uint32_t orig=bitreverse(c->codelist[i]);
395        for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
396          c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
397      }
398    }
399   
400    /* now fill in 'unused' entries in the firsttable with hi/lo search
401       hints for the non-direct-hits */
402    {
403      ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
404      long lo=0,hi=0;
405     
406      for(i=0;i<tabn;i++){
407        ogg_uint32_t word=i<<(32-c->dec_firsttablen);
408        if(c->dec_firsttable[bitreverse(word)]==0){
409          while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
410          while(    hi<n && word>=(c->codelist[hi]&mask))hi++;
411         
412          /* we only actually have 15 bits per hint to play with here.
413             In order to overflow gracefully (nothing breaks, efficiency
414             just drops), encode as the difference from the extremes. */
415          {
416            unsigned long loval=lo;
417            unsigned long hival=n-hi;
418           
419            if(loval>0x7fff)loval=0x7fff;
420            if(hival>0x7fff)hival=0x7fff;
421            c->dec_firsttable[bitreverse(word)]=
422              0x80000000UL | (loval<<15) | hival;
423          }
424        }
425      }
426    }
427  }
428
429  return(0);
430 err_out:
431  vorbis_book_clear(c);
432  return(-1);
433}
434
435static float _dist(int el,float *ref, float *b,int step){
436  int i;
437  float acc=0.f;
438  for(i=0;i<el;i++){
439    float val=(ref[i]-b[i*step]);
440    acc+=val*val;
441  }
442  return(acc);
443}
444
445int _best(codebook *book, float *a, int step){
446  encode_aux_threshmatch *tt=book->c->thresh_tree;
447
448#if 0
449  encode_aux_nearestmatch *nt=book->c->nearest_tree;
450  encode_aux_pigeonhole *pt=book->c->pigeon_tree;
451#endif
452  int dim=book->dim;
453  int k,o;
454  /*int savebest=-1;
455    float saverr;*/
456
457  /* do we have a threshhold encode hint? */
458  if(tt){
459    int index=0,i;
460    /* find the quant val of each scalar */
461    for(k=0,o=step*(dim-1);k<dim;k++,o-=step){
462
463      i=tt->threshvals>>1;
464      if(a[o]<tt->quantthresh[i]){
465
466        for(;i>0;i--)
467          if(a[o]>=tt->quantthresh[i-1])
468            break;
469       
470      }else{
471
472        for(i++;i<tt->threshvals-1;i++)
473          if(a[o]<tt->quantthresh[i])break;
474
475      }
476
477      index=(index*tt->quantvals)+tt->quantmap[i];
478    }
479    /* regular lattices are easy :-) */
480    if(book->c->lengthlist[index]>0) /* is this unused?  If so, we'll
481                                        use a decision tree after all
482                                        and fall through*/
483      return(index);
484  }
485
486#if 0
487  /* do we have a pigeonhole encode hint? */
488  if(pt){
489    const static_codebook *c=book->c;
490    int i,besti=-1;
491    float best=0.f;
492    int entry=0;
493
494    /* dealing with sequentialness is a pain in the ass */
495    if(c->q_sequencep){
496      int pv;
497      long mul=1;
498      float qlast=0;
499      for(k=0,o=0;k<dim;k++,o+=step){
500        pv=(int)((a[o]-qlast-pt->min)/pt->del);
501        if(pv<0 || pv>=pt->mapentries)break;
502        entry+=pt->pigeonmap[pv]*mul;
503        mul*=pt->quantvals;
504        qlast+=pv*pt->del+pt->min;
505      }
506    }else{
507      for(k=0,o=step*(dim-1);k<dim;k++,o-=step){
508        int pv=(int)((a[o]-pt->min)/pt->del);
509        if(pv<0 || pv>=pt->mapentries)break;
510        entry=entry*pt->quantvals+pt->pigeonmap[pv];
511      }
512    }
513
514    /* must be within the pigeonholable range; if we quant outside (or
515       in an entry that we define no list for), brute force it */
516    if(k==dim && pt->fitlength[entry]){
517      /* search the abbreviated list */
518      long *list=pt->fitlist+pt->fitmap[entry];
519      for(i=0;i<pt->fitlength[entry];i++){
520        float this=_dist(dim,book->valuelist+list[i]*dim,a,step);
521        if(besti==-1 || this<best){
522          best=this;
523          besti=list[i];
524        }
525      }
526
527      return(besti);
528    }
529  }
530
531  if(nt){
532    /* optimized using the decision tree */
533    while(1){
534      float c=0.f;
535      float *p=book->valuelist+nt->p[ptr];
536      float *q=book->valuelist+nt->q[ptr];
537     
538      for(k=0,o=0;k<dim;k++,o+=step)
539        c+=(p[k]-q[k])*(a[o]-(p[k]+q[k])*.5);
540     
541      if(c>0.f) /* in A */
542        ptr= -nt->ptr0[ptr];
543      else     /* in B */
544        ptr= -nt->ptr1[ptr];
545      if(ptr<=0)break;
546    }
547    return(-ptr);
548  }
549#endif
550
551  /* brute force it! */
552  {
553    const static_codebook *c=book->c;
554    int i,besti=-1;
555    float best=0.f;
556    float *e=book->valuelist;
557    for(i=0;i<book->entries;i++){
558      if(c->lengthlist[i]>0){
559        float this=_dist(dim,e,a,step);
560        if(besti==-1 || this<best){
561          best=this;
562          besti=i;
563        }
564      }
565      e+=dim;
566    }
567
568    /*if(savebest!=-1 && savebest!=besti){
569      fprintf(stderr,"brute force/pigeonhole disagreement:\n"
570              "original:");
571      for(i=0;i<dim*step;i+=step)fprintf(stderr,"%g,",a[i]);
572      fprintf(stderr,"\n"
573              "pigeonhole (entry %d, err %g):",savebest,saverr);
574      for(i=0;i<dim;i++)fprintf(stderr,"%g,",
575                                (book->valuelist+savebest*dim)[i]);
576      fprintf(stderr,"\n"
577              "bruteforce (entry %d, err %g):",besti,best);
578      for(i=0;i<dim;i++)fprintf(stderr,"%g,",
579                                (book->valuelist+besti*dim)[i]);
580      fprintf(stderr,"\n");
581      }*/
582    return(besti);
583  }
584}
585
586long vorbis_book_codeword(codebook *book,int entry){
587  if(book->c) /* only use with encode; decode optimizations are
588                 allowed to break this */
589    return book->codelist[entry];
590  return -1;
591}
592
593long vorbis_book_codelen(codebook *book,int entry){
594  if(book->c) /* only use with encode; decode optimizations are
595                 allowed to break this */
596    return book->c->lengthlist[entry];
597  return -1;
598}
599
600#ifdef _V_SELFTEST
601
602/* Unit tests of the dequantizer; this stuff will be OK
603   cross-platform, I simply want to be sure that special mapping cases
604   actually work properly; a bug could go unnoticed for a while */
605
606#include <stdio.h>
607
608/* cases:
609
610   no mapping
611   full, explicit mapping
612   algorithmic mapping
613
614   nonsequential
615   sequential
616*/
617
618static long full_quantlist1[]={0,1,2,3,    4,5,6,7, 8,3,6,1};
619static long partial_quantlist1[]={0,7,2};
620
621/* no mapping */
622static_codebook test1={
623  4,16,
624  NULL,
625  0,
626  0,0,0,0,
627  NULL,
628  NULL,NULL
629};
630static float *test1_result=NULL;
631 
632/* linear, full mapping, nonsequential */
633static_codebook test2={
634  4,3,
635  NULL,
636  2,
637  -533200896,1611661312,4,0,
638  full_quantlist1,
639  NULL,NULL
640};
641static float test2_result[]={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2};
642
643/* linear, full mapping, sequential */
644static_codebook test3={
645  4,3,
646  NULL,
647  2,
648  -533200896,1611661312,4,1,
649  full_quantlist1,
650  NULL,NULL
651};
652static float test3_result[]={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6};
653
654/* linear, algorithmic mapping, nonsequential */
655static_codebook test4={
656  3,27,
657  NULL,
658  1,
659  -533200896,1611661312,4,0,
660  partial_quantlist1,
661  NULL,NULL
662};
663static float test4_result[]={-3,-3,-3, 4,-3,-3, -1,-3,-3,
664                              -3, 4,-3, 4, 4,-3, -1, 4,-3,
665                              -3,-1,-3, 4,-1,-3, -1,-1,-3, 
666                              -3,-3, 4, 4,-3, 4, -1,-3, 4,
667                              -3, 4, 4, 4, 4, 4, -1, 4, 4,
668                              -3,-1, 4, 4,-1, 4, -1,-1, 4,
669                              -3,-3,-1, 4,-3,-1, -1,-3,-1,
670                              -3, 4,-1, 4, 4,-1, -1, 4,-1,
671                              -3,-1,-1, 4,-1,-1, -1,-1,-1};
672
673/* linear, algorithmic mapping, sequential */
674static_codebook test5={
675  3,27,
676  NULL,
677  1,
678  -533200896,1611661312,4,1,
679  partial_quantlist1,
680  NULL,NULL
681};
682static float test5_result[]={-3,-6,-9, 4, 1,-2, -1,-4,-7,
683                              -3, 1,-2, 4, 8, 5, -1, 3, 0,
684                              -3,-4,-7, 4, 3, 0, -1,-2,-5, 
685                              -3,-6,-2, 4, 1, 5, -1,-4, 0,
686                              -3, 1, 5, 4, 8,12, -1, 3, 7,
687                              -3,-4, 0, 4, 3, 7, -1,-2, 2,
688                              -3,-6,-7, 4, 1, 0, -1,-4,-5,
689                              -3, 1, 0, 4, 8, 7, -1, 3, 2,
690                              -3,-4,-5, 4, 3, 2, -1,-2,-3};
691
692void run_test(static_codebook *b,float *comp){
693  float *out=_book_unquantize(b,b->entries,NULL);
694  int i;
695
696  if(comp){
697    if(!out){
698      fprintf(stderr,"_book_unquantize incorrectly returned NULL\n");
699      exit(1);
700    }
701
702    for(i=0;i<b->entries*b->dim;i++)
703      if(fabs(out[i]-comp[i])>.0001){
704        fprintf(stderr,"disagreement in unquantized and reference data:\n"
705                "position %d, %g != %g\n",i,out[i],comp[i]);
706        exit(1);
707      }
708
709  }else{
710    if(out){
711      fprintf(stderr,"_book_unquantize returned a value array: \n"
712              " correct result should have been NULL\n");
713      exit(1);
714    }
715  }
716}
717
718int main(){
719  /* run the nine dequant tests, and compare to the hand-rolled results */
720  fprintf(stderr,"Dequant test 1... ");
721  run_test(&test1,test1_result);
722  fprintf(stderr,"OK\nDequant test 2... ");
723  run_test(&test2,test2_result);
724  fprintf(stderr,"OK\nDequant test 3... ");
725  run_test(&test3,test3_result);
726  fprintf(stderr,"OK\nDequant test 4... ");
727  run_test(&test4,test4_result);
728  fprintf(stderr,"OK\nDequant test 5... ");
729  run_test(&test5,test5_result);
730  fprintf(stderr,"OK\n\n");
731 
732  return(0);
733}
734
735#endif
Note: See TracBrowser for help on using the repository browser.