Coverage Report

Created: 2026-05-27 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vorbis/lib/sharedbook.c
Line
Count
Source
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-2015             *
9
 * by the Xiph.Org Foundation https://xiph.org/                     *
10
 *                                                                  *
11
 ********************************************************************
12
13
 function: basic shared codebook operations
14
15
 ********************************************************************/
16
17
#include <stdlib.h>
18
#include <limits.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 ******************************************/
29
30
445k
int ov_ilog(ogg_uint32_t v){
31
445k
  int ret;
32
3.07M
  for(ret=0;v;ret++)v>>=1;
33
445k
  return ret;
34
445k
}
35
36
/* 32 bit float (not IEEE; nonnormalized mantissa +
37
   biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm
38
   Why not IEEE?  It's just not that important here. */
39
40
#define VQ_FEXP 10
41
40.6k
#define VQ_FMAN 21
42
20.3k
#define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */
43
44
/* doesn't currently guard under/overflow */
45
0
long _float32_pack(float val){
46
0
  int sign=0;
47
0
  long exp;
48
0
  long mant;
49
0
  if(val<0){
50
0
    sign=0x80000000;
51
0
    val= -val;
52
0
  }
53
0
  exp= floor(log(val)/log(2.f)+.001); /* +epsilon */
54
0
  mant=rint(ldexp(val,(VQ_FMAN-1)-exp));
55
0
  exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN;
56
57
0
  return(sign|exp|mant);
58
0
}
59
60
20.3k
float _float32_unpack(long val){
61
20.3k
  double mant=val&0x1fffff;
62
20.3k
  int    sign=val&0x80000000;
63
20.3k
  long   exp =(val&0x7fe00000L)>>VQ_FMAN;
64
20.3k
  if(sign)mant= -mant;
65
20.3k
  exp=exp-(VQ_FMAN-1)-VQ_FEXP_BIAS;
66
  /* clamp excessive exponent values */
67
20.3k
  if (exp>63){
68
3.52k
    exp=63;
69
3.52k
  }
70
20.3k
  if (exp<-63){
71
9.15k
    exp=-63;
72
9.15k
  }
73
20.3k
  return(ldexp(mant,exp));
74
20.3k
}
75
76
/* given a list of word lengths, generate a list of codewords.  Works
77
   for length ordered or unordered, always assigns the lowest valued
78
   codewords first.  Extended to handle unused entries (length 0) */
79
24.1k
ogg_uint32_t *_make_words(char *l,long n,long sparsecount){
80
24.1k
  long i,j,count=0;
81
24.1k
  ogg_uint32_t marker[33];
82
24.1k
  ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
83
24.1k
  memset(marker,0,sizeof(marker));
84
85
3.81M
  for(i=0;i<n;i++){
86
3.78M
    long length=l[i];
87
3.78M
    if(length>0){
88
2.91M
      ogg_uint32_t entry=marker[length];
89
90
      /* when we claim a node for an entry, we also claim the nodes
91
         below it (pruning off the imagined tree that may have dangled
92
         from it) as well as blocking the use of any nodes directly
93
         above for leaves */
94
95
      /* update ourself */
96
2.91M
      if(length<32 && (entry>>length)){
97
        /* error condition; the lengths must specify an overpopulated tree */
98
24
        _ogg_free(r);
99
24
        return(NULL);
100
24
      }
101
2.91M
      r[count++]=entry;
102
103
      /* Look to see if the next shorter marker points to the node
104
         above. if so, update it and repeat.  */
105
2.91M
      {
106
5.81M
        for(j=length;j>0;j--){
107
108
5.79M
          if(marker[j]&1){
109
            /* have to jump branches */
110
2.89M
            if(j==1)
111
17.9k
              marker[1]++;
112
2.87M
            else
113
2.87M
              marker[j]=marker[j-1]<<1;
114
2.89M
            break; /* invariant says next upper marker would already
115
                      have been moved if it was on the same path */
116
2.89M
          }
117
2.90M
          marker[j]++;
118
2.90M
        }
119
2.91M
      }
120
121
      /* prune the tree; the implicit invariant says all the longer
122
         markers were dangling from our just-taken node.  Dangle them
123
         from our *new* node. */
124
49.7M
      for(j=length+1;j<33;j++)
125
47.3M
        if((marker[j]>>1) == entry){
126
46.8M
          entry=marker[j];
127
46.8M
          marker[j]=marker[j-1]<<1;
128
46.8M
        }else
129
518k
          break;
130
2.91M
    }else
131
870k
      if(sparsecount==0)count++;
132
3.78M
  }
133
134
  /* any underpopulated tree must be rejected. */
135
  /* Single-entry codebooks are a retconned extension to the spec.
136
     They have a single codeword '0' of length 1 that results in an
137
     underpopulated tree.  Shield that case from the underformed tree check. */
138
24.1k
  if(!(count==1 && marker[2]==2)){
139
588k
    for(i=1;i<33;i++)
140
570k
      if(marker[i] & (0xffffffffUL>>(32-i))){
141
101
        _ogg_free(r);
142
101
        return(NULL);
143
101
      }
144
17.9k
  }
145
146
  /* bitreverse the words because our bitwise packer/unpacker is LSb
147
     endian */
148
3.50M
  for(i=0,count=0;i<n;i++){
149
3.48M
    ogg_uint32_t temp=0;
150
32.5M
    for(j=0;j<l[i];j++){
151
29.0M
      temp<<=1;
152
29.0M
      temp|=(r[count]>>j)&1;
153
29.0M
    }
154
155
3.48M
    if(sparsecount){
156
3.48M
      if(l[i])
157
2.61M
        r[count++]=temp;
158
3.48M
    }else
159
0
      r[count++]=temp;
160
3.48M
  }
161
162
24.0k
  return(r);
163
24.1k
}
164
165
/* there might be a straightforward one-line way to do the below
166
   that's portable and totally safe against roundoff, but I haven't
167
   thought of it.  Therefore, we opt on the side of caution */
168
14.9k
long _book_maptype1_quantvals(const static_codebook *b){
169
14.9k
  long vals;
170
14.9k
  if(b->entries<1){
171
170
    return(0);
172
170
  }
173
14.7k
  vals=floor(pow((float)b->entries,1.f/b->dim));
174
175
  /* the above *should* be reliable, but we'll not assume that FP is
176
     ever reliable when bitstream sync is at stake; verify via integer
177
     means that vals really is the greatest value of dim for which
178
     vals^b->bim <= b->entries */
179
  /* treat the above as an initial guess */
180
14.7k
  if(vals<1){
181
0
    vals=1;
182
0
  }
183
14.7k
  while(1){
184
14.7k
    long acc=1;
185
14.7k
    long acc1=1;
186
14.7k
    int i;
187
16.0M
    for(i=0;i<b->dim;i++){
188
16.0M
      if(b->entries/vals<acc)break;
189
16.0M
      acc*=vals;
190
16.0M
      if(LONG_MAX/(vals+1)<acc1)acc1=LONG_MAX;
191
165k
      else acc1*=vals+1;
192
16.0M
    }
193
14.7k
    if(i>=b->dim && acc<=b->entries && acc1>b->entries){
194
14.7k
      return(vals);
195
14.7k
    }else{
196
1
      if(i<b->dim || acc>b->entries){
197
1
        vals--;
198
1
      }else{
199
0
        vals++;
200
0
      }
201
1
    }
202
14.7k
  }
203
14.7k
}
204
205
/* unpack the quantized list of values for encode/decode ***********/
206
/* we need to deal with two map types: in map type 1, the values are
207
   generated algorithmically (each column of the vector counts through
208
   the values in the quant vector). in map type 2, all the values came
209
   in in an explicit list.  Both value lists must be unpacked */
210
24.0k
float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){
211
24.0k
  long j,k,count=0;
212
24.0k
  if(b->maptype==1 || b->maptype==2){
213
10.1k
    int quantvals;
214
10.1k
    float mindel=_float32_unpack(b->q_min);
215
10.1k
    float delta=_float32_unpack(b->q_delta);
216
10.1k
    float *r=_ogg_calloc(n*b->dim,sizeof(*r));
217
218
    /* maptype 1 and 2 both use a quantized value vector, but
219
       different sizes */
220
10.1k
    switch(b->maptype){
221
6.76k
    case 1:
222
      /* most of the time, entries%dimensions == 0, but we need to be
223
         well defined.  We define that the possible vales at each
224
         scalar is values == entries/dim.  If entries%dim != 0, we'll
225
         have 'too few' values (values*dim<entries), which means that
226
         we'll have 'left over' entries; left over entries use zeroed
227
         values (and are wasted).  So don't generate codebooks like
228
         that */
229
6.76k
      quantvals=_book_maptype1_quantvals(b);
230
1.29M
      for(j=0;j<b->entries;j++){
231
1.28M
        if((sparsemap && b->lengthlist[j]) || !sparsemap){
232
731k
          float last=0.f;
233
731k
          int indexdiv=1;
234
21.7M
          for(k=0;k<b->dim;k++){
235
20.9M
            int index= (j/indexdiv)%quantvals;
236
20.9M
            float val=b->quantlist[index];
237
20.9M
            val=fabs(val)*delta+mindel+last;
238
20.9M
            if(b->q_sequencep)last=val;
239
20.9M
            if(sparsemap)
240
20.9M
              r[sparsemap[count]*b->dim+k]=val;
241
0
            else
242
0
              r[count*b->dim+k]=val;
243
20.9M
            indexdiv*=quantvals;
244
20.9M
          }
245
731k
          count++;
246
731k
        }
247
248
1.28M
      }
249
6.76k
      break;
250
3.39k
    case 2:
251
21.8k
      for(j=0;j<b->entries;j++){
252
18.4k
        if((sparsemap && b->lengthlist[j]) || !sparsemap){
253
10.0k
          float last=0.f;
254
255
33.5k
          for(k=0;k<b->dim;k++){
256
23.4k
            float val=b->quantlist[j*b->dim+k];
257
23.4k
            val=fabs(val)*delta+mindel+last;
258
23.4k
            if(b->q_sequencep)last=val;
259
23.4k
            if(sparsemap)
260
23.4k
              r[sparsemap[count]*b->dim+k]=val;
261
0
            else
262
0
              r[count*b->dim+k]=val;
263
23.4k
          }
264
10.0k
          count++;
265
10.0k
        }
266
18.4k
      }
267
3.39k
      break;
268
10.1k
    }
269
270
10.1k
    return(r);
271
10.1k
  }
272
13.9k
  return(NULL);
273
24.0k
}
274
275
28.6k
void vorbis_staticbook_destroy(static_codebook *b){
276
28.6k
  if(b->allocedp){
277
28.6k
    if(b->quantlist)_ogg_free(b->quantlist);
278
28.6k
    if(b->lengthlist)_ogg_free(b->lengthlist);
279
28.6k
    memset(b,0,sizeof(*b));
280
28.6k
    _ogg_free(b);
281
28.6k
  } /* otherwise, it is in static memory */
282
28.6k
}
283
284
26.2k
void vorbis_book_clear(codebook *b){
285
  /* static book is not cleared; we're likely called on the lookup and
286
     the static codebook belongs to the info struct */
287
26.2k
  if(b->valuelist)_ogg_free(b->valuelist);
288
26.2k
  if(b->codelist)_ogg_free(b->codelist);
289
290
26.2k
  if(b->dec_index)_ogg_free(b->dec_index);
291
26.2k
  if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
292
26.2k
  if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
293
294
26.2k
  memset(b,0,sizeof(*b));
295
26.2k
}
296
297
0
int vorbis_book_init_encode(codebook *c,const static_codebook *s){
298
299
0
  memset(c,0,sizeof(*c));
300
0
  c->c=s;
301
0
  c->entries=s->entries;
302
0
  c->used_entries=s->entries;
303
0
  c->dim=s->dim;
304
0
  c->codelist=_make_words(s->lengthlist,s->entries,0);
305
  /* c->valuelist=_book_unquantize(s,s->entries,NULL); */
306
0
  c->quantvals=_book_maptype1_quantvals(s);
307
0
  c->minval=(int)rint(_float32_unpack(s->q_min));
308
0
  c->delta=(int)rint(_float32_unpack(s->q_delta));
309
310
0
  return(0);
311
0
}
312
313
3.67M
static ogg_uint32_t bitreverse(ogg_uint32_t x){
314
3.67M
  x=    ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL);
315
3.67M
  x=    ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL);
316
3.67M
  x=    ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL);
317
3.67M
  x=    ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL);
318
3.67M
  return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL);
319
3.67M
}
320
321
13.6M
static int sort32a(const void *a,const void *b){
322
13.6M
  return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)-
323
13.6M
    ( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b);
324
13.6M
}
325
326
/* decode codebook arrangement is more heavily optimized than encode */
327
25.6k
int vorbis_book_init_decode(codebook *c,const static_codebook *s){
328
25.6k
  int i,j,n=0,tabn;
329
25.6k
  int *sortindex=NULL;
330
25.6k
  ogg_uint32_t *codes=NULL;
331
25.6k
  ogg_uint32_t **codep=NULL;
332
333
25.6k
  memset(c,0,sizeof(*c));
334
335
  /* count actually used entries and find max length */
336
3.82M
  for(i=0;i<s->entries;i++)
337
3.79M
    if(s->lengthlist[i]>0)
338
2.91M
      n++;
339
340
25.6k
  c->entries=s->entries;
341
25.6k
  c->used_entries=n;
342
25.6k
  c->dim=s->dim;
343
344
25.6k
  if(n>0){
345
    /* two different remappings go on here.
346
347
    First, we collapse the likely sparse codebook down only to
348
    actually represented values/words.  This collapsing needs to be
349
    indexed as map-valueless books are used to encode original entry
350
    positions as integers.
351
352
    Second, we reorder all vectors, including the entry index above,
353
    by sorted bitreversed codeword to allow treeless decode. */
354
355
    /* perform sort */
356
24.1k
    codes=_make_words(s->lengthlist,s->entries,c->used_entries);
357
24.1k
    if(codes==NULL)goto err_out;
358
359
24.0k
    codep=_ogg_malloc(sizeof(*codep)*n);
360
24.0k
    if(codep==NULL)goto err_out;
361
362
2.63M
    for(i=0;i<n;i++){
363
2.61M
      codes[i]=bitreverse(codes[i]);
364
2.61M
      codep[i]=codes+i;
365
2.61M
    }
366
367
24.0k
    qsort(codep,n,sizeof(*codep),sort32a);
368
369
24.0k
    sortindex=_ogg_malloc(n*sizeof(*sortindex));
370
24.0k
    if(sortindex==NULL)goto err_out;
371
372
24.0k
    c->codelist=_ogg_malloc(n*sizeof(*c->codelist));
373
24.0k
    if(c->codelist==NULL)goto err_out;
374
    /* the index is a reverse index */
375
2.63M
    for(i=0;i<n;i++){
376
2.61M
      int position=codep[i]-codes;
377
2.61M
      sortindex[position]=i;
378
2.61M
    }
379
24.0k
    _ogg_free(codep); codep=NULL;
380
381
2.63M
    for(i=0;i<n;i++)
382
2.61M
      c->codelist[sortindex[i]]=codes[i];
383
24.0k
    _ogg_free(codes); codes=NULL;
384
385
24.0k
    c->valuelist=_book_unquantize(s,n,sortindex);
386
24.0k
    c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index));
387
24.0k
    if(c->dec_index==NULL)goto err_out;
388
389
3.50M
    for(n=0,i=0;i<s->entries;i++)
390
3.48M
      if(s->lengthlist[i]>0)
391
2.61M
        c->dec_index[sortindex[n++]]=i;
392
393
24.0k
    c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths));
394
24.0k
    if(c->dec_codelengths==NULL)goto err_out;
395
24.0k
    c->dec_maxlength=0;
396
3.50M
    for(n=0,i=0;i<s->entries;i++)
397
3.48M
      if(s->lengthlist[i]>0){
398
2.61M
        c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
399
2.61M
        if(s->lengthlist[i]>c->dec_maxlength)
400
94.9k
          c->dec_maxlength=s->lengthlist[i];
401
2.61M
      }
402
24.0k
    _ogg_free(sortindex); sortindex=NULL;
403
404
24.0k
    if(n==1 && c->dec_maxlength==1){
405
      /* special case the 'single entry codebook' with a single bit
406
       fastpath table (that always returns entry 0 )in order to use
407
       unmodified decode paths. */
408
6.25k
      c->dec_firsttablen=1;
409
6.25k
      c->dec_firsttable=_ogg_calloc(2,sizeof(*c->dec_firsttable));
410
6.25k
      if(c->dec_firsttable==NULL)goto err_out;
411
6.25k
      c->dec_firsttable[0]=c->dec_firsttable[1]=1;
412
413
17.8k
    }else{
414
17.8k
      c->dec_firsttablen=ov_ilog(c->used_entries)-4; /* this is magic */
415
17.8k
      if(c->dec_firsttablen<5)c->dec_firsttablen=5;
416
17.8k
      if(c->dec_firsttablen>8)c->dec_firsttablen=8;
417
418
17.8k
      tabn=1<<c->dec_firsttablen;
419
17.8k
      c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
420
17.8k
      if(c->dec_firsttable==NULL)goto err_out;
421
422
2.62M
      for(i=0;i<n;i++){
423
2.60M
        if(c->dec_codelengths[i]<=c->dec_firsttablen){
424
161k
          ogg_uint32_t orig=bitreverse(c->codelist[i]);
425
664k
          for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
426
503k
            c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
427
161k
        }
428
2.60M
      }
429
430
      /* now fill in 'unused' entries in the firsttable with hi/lo search
431
         hints for the non-direct-hits */
432
17.8k
      {
433
17.8k
        ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
434
17.8k
        long lo=0,hi=0;
435
436
721k
        for(i=0;i<tabn;i++){
437
704k
          ogg_uint32_t word=((ogg_uint32_t)i<<(32-c->dec_firsttablen));
438
704k
          if(c->dec_firsttable[bitreverse(word)]==0){
439
2.52M
            while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
440
2.76M
            while(    hi<n && word>=(c->codelist[hi]&mask))hi++;
441
442
            /* we only actually have 15 bits per hint to play with here.
443
               In order to overflow gracefully (nothing breaks, efficiency
444
               just drops), encode as the difference from the extremes. */
445
201k
            {
446
201k
              unsigned long loval=lo;
447
201k
              unsigned long hival=n-hi;
448
449
201k
              if(loval>0x7fff)loval=0x7fff;
450
201k
              if(hival>0x7fff)hival=0x7fff;
451
201k
              c->dec_firsttable[bitreverse(word)]=
452
201k
                0x80000000UL | (loval<<15) | hival;
453
201k
            }
454
201k
          }
455
704k
        }
456
17.8k
      }
457
17.8k
    }
458
24.0k
  }
459
460
25.5k
  return(0);
461
125
 err_out:
462
125
  _ogg_free(sortindex);
463
125
  _ogg_free(codep);
464
125
  _ogg_free(codes);
465
125
  vorbis_book_clear(c);
466
125
  return(-1);
467
25.6k
}
468
469
0
long vorbis_book_codeword(codebook *book,int entry){
470
0
  if(book->c) /* only use with encode; decode optimizations are
471
                 allowed to break this */
472
0
    return book->codelist[entry];
473
0
  return -1;
474
0
}
475
476
0
long vorbis_book_codelen(codebook *book,int entry){
477
0
  if(book->c) /* only use with encode; decode optimizations are
478
                 allowed to break this */
479
0
    return book->c->lengthlist[entry];
480
0
  return -1;
481
0
}
482
483
#ifdef _V_SELFTEST
484
485
/* Unit tests of the dequantizer; this stuff will be OK
486
   cross-platform, I simply want to be sure that special mapping cases
487
   actually work properly; a bug could go unnoticed for a while */
488
489
#include <stdio.h>
490
491
/* cases:
492
493
   no mapping
494
   full, explicit mapping
495
   algorithmic mapping
496
497
   nonsequential
498
   sequential
499
*/
500
501
static long full_quantlist1[]={0,1,2,3,    4,5,6,7, 8,3,6,1};
502
static long partial_quantlist1[]={0,7,2};
503
504
/* no mapping */
505
static_codebook test1={
506
  4,16,
507
  NULL,
508
  0,
509
  0,0,0,0,
510
  NULL,
511
  0
512
};
513
static float *test1_result=NULL;
514
515
/* linear, full mapping, nonsequential */
516
static_codebook test2={
517
  4,3,
518
  NULL,
519
  2,
520
  -533200896,1611661312,4,0,
521
  full_quantlist1,
522
  0
523
};
524
static float test2_result[]={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2};
525
526
/* linear, full mapping, sequential */
527
static_codebook test3={
528
  4,3,
529
  NULL,
530
  2,
531
  -533200896,1611661312,4,1,
532
  full_quantlist1,
533
  0
534
};
535
static float test3_result[]={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6};
536
537
/* linear, algorithmic mapping, nonsequential */
538
static_codebook test4={
539
  3,27,
540
  NULL,
541
  1,
542
  -533200896,1611661312,4,0,
543
  partial_quantlist1,
544
  0
545
};
546
static float test4_result[]={-3,-3,-3, 4,-3,-3, -1,-3,-3,
547
                              -3, 4,-3, 4, 4,-3, -1, 4,-3,
548
                              -3,-1,-3, 4,-1,-3, -1,-1,-3,
549
                              -3,-3, 4, 4,-3, 4, -1,-3, 4,
550
                              -3, 4, 4, 4, 4, 4, -1, 4, 4,
551
                              -3,-1, 4, 4,-1, 4, -1,-1, 4,
552
                              -3,-3,-1, 4,-3,-1, -1,-3,-1,
553
                              -3, 4,-1, 4, 4,-1, -1, 4,-1,
554
                              -3,-1,-1, 4,-1,-1, -1,-1,-1};
555
556
/* linear, algorithmic mapping, sequential */
557
static_codebook test5={
558
  3,27,
559
  NULL,
560
  1,
561
  -533200896,1611661312,4,1,
562
  partial_quantlist1,
563
  0
564
};
565
static float test5_result[]={-3,-6,-9, 4, 1,-2, -1,-4,-7,
566
                              -3, 1,-2, 4, 8, 5, -1, 3, 0,
567
                              -3,-4,-7, 4, 3, 0, -1,-2,-5,
568
                              -3,-6,-2, 4, 1, 5, -1,-4, 0,
569
                              -3, 1, 5, 4, 8,12, -1, 3, 7,
570
                              -3,-4, 0, 4, 3, 7, -1,-2, 2,
571
                              -3,-6,-7, 4, 1, 0, -1,-4,-5,
572
                              -3, 1, 0, 4, 8, 7, -1, 3, 2,
573
                              -3,-4,-5, 4, 3, 2, -1,-2,-3};
574
575
void run_test(static_codebook *b,float *comp){
576
  float *out=_book_unquantize(b,b->entries,NULL);
577
  int i;
578
579
  if(comp){
580
    if(!out){
581
      fprintf(stderr,"_book_unquantize incorrectly returned NULL\n");
582
      exit(1);
583
    }
584
585
    for(i=0;i<b->entries*b->dim;i++)
586
      if(fabs(out[i]-comp[i])>.0001){
587
        fprintf(stderr,"disagreement in unquantized and reference data:\n"
588
                "position %d, %g != %g\n",i,out[i],comp[i]);
589
        exit(1);
590
      }
591
592
  }else{
593
    if(out){
594
      fprintf(stderr,"_book_unquantize returned a value array: \n"
595
              " correct result should have been NULL\n");
596
      exit(1);
597
    }
598
  }
599
  _ogg_free(out);
600
}
601
602
int main(){
603
  /* run the nine dequant tests, and compare to the hand-rolled results */
604
  fprintf(stderr,"Dequant test 1... ");
605
  run_test(&test1,test1_result);
606
  fprintf(stderr,"OK\nDequant test 2... ");
607
  run_test(&test2,test2_result);
608
  fprintf(stderr,"OK\nDequant test 3... ");
609
  run_test(&test3,test3_result);
610
  fprintf(stderr,"OK\nDequant test 4... ");
611
  run_test(&test4,test4_result);
612
  fprintf(stderr,"OK\nDequant test 5... ");
613
  run_test(&test5,test5_result);
614
  fprintf(stderr,"OK\n\n");
615
616
  return(0);
617
}
618
619
#endif