Coverage Report

Created: 2026-05-16 07:49

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
380k
int ov_ilog(ogg_uint32_t v){
31
380k
  int ret;
32
2.69M
  for(ret=0;v;ret++)v>>=1;
33
380k
  return ret;
34
380k
}
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
3.63k
#define VQ_FMAN 21
42
1.81k
#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
1.81k
float _float32_unpack(long val){
61
1.81k
  double mant=val&0x1fffff;
62
1.81k
  int    sign=val&0x80000000;
63
1.81k
  long   exp =(val&0x7fe00000L)>>VQ_FMAN;
64
1.81k
  if(sign)mant= -mant;
65
1.81k
  exp=exp-(VQ_FMAN-1)-VQ_FEXP_BIAS;
66
  /* clamp excessive exponent values */
67
1.81k
  if (exp>63){
68
50
    exp=63;
69
50
  }
70
1.81k
  if (exp<-63){
71
1.40k
    exp=-63;
72
1.40k
  }
73
1.81k
  return(ldexp(mant,exp));
74
1.81k
}
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
1.05k
ogg_uint32_t *_make_words(char *l,long n,long sparsecount){
80
1.05k
  long i,j,count=0;
81
1.05k
  ogg_uint32_t marker[33];
82
1.05k
  ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
83
1.05k
  memset(marker,0,sizeof(marker));
84
85
3.15k
  for(i=0;i<n;i++){
86
2.10k
    long length=l[i];
87
2.10k
    if(length>0){
88
2.09k
      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.09k
      if(length<32 && (entry>>length)){
97
        /* error condition; the lengths must specify an overpopulated tree */
98
14
        _ogg_free(r);
99
14
        return(NULL);
100
14
      }
101
2.08k
      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.08k
      {
106
7.67k
        for(j=length;j>0;j--){
107
108
6.61k
          if(marker[j]&1){
109
            /* have to jump branches */
110
1.02k
            if(j==1)
111
281
              marker[1]++;
112
742
            else
113
742
              marker[j]=marker[j-1]<<1;
114
1.02k
            break; /* invariant says next upper marker would already
115
                      have been moved if it was on the same path */
116
1.02k
          }
117
5.59k
          marker[j]++;
118
5.59k
        }
119
2.08k
      }
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
40.4k
      for(j=length+1;j<33;j++)
125
38.8k
        if((marker[j]>>1) == entry){
126
38.3k
          entry=marker[j];
127
38.3k
          marker[j]=marker[j-1]<<1;
128
38.3k
        }else
129
515
          break;
130
2.08k
    }else
131
9
      if(sparsecount==0)count++;
132
2.10k
  }
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
1.04k
  if(!(count==1 && marker[2]==2)){
139
8.76k
    for(i=1;i<33;i++)
140
8.50k
      if(marker[i] & (0xffffffffUL>>(32-i))){
141
136
        _ogg_free(r);
142
136
        return(NULL);
143
136
      }
144
397
  }
145
146
  /* bitreverse the words because our bitwise packer/unpacker is LSb
147
     endian */
148
2.07k
  for(i=0,count=0;i<n;i++){
149
1.16k
    ogg_uint32_t temp=0;
150
2.33k
    for(j=0;j<l[i];j++){
151
1.16k
      temp<<=1;
152
1.16k
      temp|=(r[count]>>j)&1;
153
1.16k
    }
154
155
1.16k
    if(sparsecount){
156
1.16k
      if(l[i])
157
1.16k
        r[count++]=temp;
158
1.16k
    }else
159
0
      r[count++]=temp;
160
1.16k
  }
161
162
908
  return(r);
163
1.04k
}
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
2.30k
long _book_maptype1_quantvals(const static_codebook *b){
169
2.30k
  long vals;
170
2.30k
  if(b->entries<1){
171
12
    return(0);
172
12
  }
173
2.29k
  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
2.29k
  if(vals<1){
181
0
    vals=1;
182
0
  }
183
2.29k
  while(1){
184
2.29k
    long acc=1;
185
2.29k
    long acc1=1;
186
2.29k
    int i;
187
28.4M
    for(i=0;i<b->dim;i++){
188
28.4M
      if(b->entries/vals<acc)break;
189
28.4M
      acc*=vals;
190
28.4M
      if(LONG_MAX/(vals+1)<acc1)acc1=LONG_MAX;
191
59.6k
      else acc1*=vals+1;
192
28.4M
    }
193
2.29k
    if(i>=b->dim && acc<=b->entries && acc1>b->entries){
194
2.29k
      return(vals);
195
2.29k
    }else{
196
0
      if(i<b->dim || acc>b->entries){
197
0
        vals--;
198
0
      }else{
199
0
        vals++;
200
0
      }
201
0
    }
202
2.29k
  }
203
2.29k
}
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
908
float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){
211
908
  long j,k,count=0;
212
908
  if(b->maptype==1 || b->maptype==2){
213
908
    int quantvals;
214
908
    float mindel=_float32_unpack(b->q_min);
215
908
    float delta=_float32_unpack(b->q_delta);
216
908
    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
908
    switch(b->maptype){
221
904
    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
904
      quantvals=_book_maptype1_quantvals(b);
230
2.06k
      for(j=0;j<b->entries;j++){
231
1.16k
        if((sparsemap && b->lengthlist[j]) || !sparsemap){
232
1.16k
          float last=0.f;
233
1.16k
          int indexdiv=1;
234
17.7M
          for(k=0;k<b->dim;k++){
235
17.7M
            int index= (j/indexdiv)%quantvals;
236
17.7M
            float val=b->quantlist[index];
237
17.7M
            val=fabs(val)*delta+mindel+last;
238
17.7M
            if(b->q_sequencep)last=val;
239
17.7M
            if(sparsemap)
240
17.7M
              r[sparsemap[count]*b->dim+k]=val;
241
0
            else
242
0
              r[count*b->dim+k]=val;
243
17.7M
            indexdiv*=quantvals;
244
17.7M
          }
245
1.16k
          count++;
246
1.16k
        }
247
248
1.16k
      }
249
904
      break;
250
4
    case 2:
251
8
      for(j=0;j<b->entries;j++){
252
4
        if((sparsemap && b->lengthlist[j]) || !sparsemap){
253
4
          float last=0.f;
254
255
10
          for(k=0;k<b->dim;k++){
256
6
            float val=b->quantlist[j*b->dim+k];
257
6
            val=fabs(val)*delta+mindel+last;
258
6
            if(b->q_sequencep)last=val;
259
6
            if(sparsemap)
260
6
              r[sparsemap[count]*b->dim+k]=val;
261
0
            else
262
0
              r[count*b->dim+k]=val;
263
6
          }
264
4
          count++;
265
4
        }
266
4
      }
267
4
      break;
268
908
    }
269
270
908
    return(r);
271
908
  }
272
0
  return(NULL);
273
908
}
274
275
1.69k
void vorbis_staticbook_destroy(static_codebook *b){
276
1.69k
  if(b->allocedp){
277
1.69k
    if(b->quantlist)_ogg_free(b->quantlist);
278
1.69k
    if(b->lengthlist)_ogg_free(b->lengthlist);
279
1.69k
    memset(b,0,sizeof(*b));
280
1.69k
    _ogg_free(b);
281
1.69k
  } /* otherwise, it is in static memory */
282
1.69k
}
283
284
1.20k
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
1.20k
  if(b->valuelist)_ogg_free(b->valuelist);
288
1.20k
  if(b->codelist)_ogg_free(b->codelist);
289
290
1.20k
  if(b->dec_index)_ogg_free(b->dec_index);
291
1.20k
  if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
292
1.20k
  if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
293
294
1.20k
  memset(b,0,sizeof(*b));
295
1.20k
}
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
10.0k
static ogg_uint32_t bitreverse(ogg_uint32_t x){
314
10.0k
  x=    ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL);
315
10.0k
  x=    ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL);
316
10.0k
  x=    ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL);
317
10.0k
  x=    ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL);
318
10.0k
  return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL);
319
10.0k
}
320
321
261
static int sort32a(const void *a,const void *b){
322
261
  return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)-
323
261
    ( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b);
324
261
}
325
326
/* decode codebook arrangement is more heavily optimized than encode */
327
1.05k
int vorbis_book_init_decode(codebook *c,const static_codebook *s){
328
1.05k
  int i,j,n=0,tabn;
329
1.05k
  int *sortindex=NULL;
330
1.05k
  ogg_uint32_t *codes=NULL;
331
1.05k
  ogg_uint32_t **codep=NULL;
332
333
1.05k
  memset(c,0,sizeof(*c));
334
335
  /* count actually used entries and find max length */
336
3.83k
  for(i=0;i<s->entries;i++)
337
2.77k
    if(s->lengthlist[i]>0)
338
2.76k
      n++;
339
340
1.05k
  c->entries=s->entries;
341
1.05k
  c->used_entries=n;
342
1.05k
  c->dim=s->dim;
343
344
1.05k
  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
1.05k
    codes=_make_words(s->lengthlist,s->entries,c->used_entries);
357
1.05k
    if(codes==NULL)goto err_out;
358
359
908
    codep=_ogg_malloc(sizeof(*codep)*n);
360
908
    if(codep==NULL)goto err_out;
361
362
2.07k
    for(i=0;i<n;i++){
363
1.16k
      codes[i]=bitreverse(codes[i]);
364
1.16k
      codep[i]=codes+i;
365
1.16k
    }
366
367
908
    qsort(codep,n,sizeof(*codep),sort32a);
368
369
908
    sortindex=_ogg_malloc(n*sizeof(*sortindex));
370
908
    if(sortindex==NULL)goto err_out;
371
372
908
    c->codelist=_ogg_malloc(n*sizeof(*c->codelist));
373
908
    if(c->codelist==NULL)goto err_out;
374
    /* the index is a reverse index */
375
2.07k
    for(i=0;i<n;i++){
376
1.16k
      int position=codep[i]-codes;
377
1.16k
      sortindex[position]=i;
378
1.16k
    }
379
908
    _ogg_free(codep); codep=NULL;
380
381
2.07k
    for(i=0;i<n;i++)
382
1.16k
      c->codelist[sortindex[i]]=codes[i];
383
908
    _ogg_free(codes); codes=NULL;
384
385
908
    c->valuelist=_book_unquantize(s,n,sortindex);
386
908
    c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index));
387
908
    if(c->dec_index==NULL)goto err_out;
388
389
2.07k
    for(n=0,i=0;i<s->entries;i++)
390
1.16k
      if(s->lengthlist[i]>0)
391
1.16k
        c->dec_index[sortindex[n++]]=i;
392
393
908
    c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths));
394
908
    if(c->dec_codelengths==NULL)goto err_out;
395
908
    c->dec_maxlength=0;
396
2.07k
    for(n=0,i=0;i<s->entries;i++)
397
1.16k
      if(s->lengthlist[i]>0){
398
1.16k
        c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
399
1.16k
        if(s->lengthlist[i]>c->dec_maxlength)
400
908
          c->dec_maxlength=s->lengthlist[i];
401
1.16k
      }
402
908
    _ogg_free(sortindex); sortindex=NULL;
403
404
908
    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
647
      c->dec_firsttablen=1;
409
647
      c->dec_firsttable=_ogg_calloc(2,sizeof(*c->dec_firsttable));
410
647
      if(c->dec_firsttable==NULL)goto err_out;
411
647
      c->dec_firsttable[0]=c->dec_firsttable[1]=1;
412
413
647
    }else{
414
261
      c->dec_firsttablen=ov_ilog(c->used_entries)-4; /* this is magic */
415
261
      if(c->dec_firsttablen<5)c->dec_firsttablen=5;
416
261
      if(c->dec_firsttablen>8)c->dec_firsttablen=8;
417
418
261
      tabn=1<<c->dec_firsttablen;
419
261
      c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
420
261
      if(c->dec_firsttable==NULL)goto err_out;
421
422
783
      for(i=0;i<n;i++){
423
522
        if(c->dec_codelengths[i]<=c->dec_firsttablen){
424
522
          ogg_uint32_t orig=bitreverse(c->codelist[i]);
425
8.87k
          for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
426
8.35k
            c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
427
522
        }
428
522
      }
429
430
      /* now fill in 'unused' entries in the firsttable with hi/lo search
431
         hints for the non-direct-hits */
432
261
      {
433
261
        ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
434
261
        long lo=0,hi=0;
435
436
8.61k
        for(i=0;i<tabn;i++){
437
8.35k
          ogg_uint32_t word=((ogg_uint32_t)i<<(32-c->dec_firsttablen));
438
8.35k
          if(c->dec_firsttable[bitreverse(word)]==0){
439
0
            while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
440
0
            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
0
            {
446
0
              unsigned long loval=lo;
447
0
              unsigned long hival=n-hi;
448
449
0
              if(loval>0x7fff)loval=0x7fff;
450
0
              if(hival>0x7fff)hival=0x7fff;
451
0
              c->dec_firsttable[bitreverse(word)]=
452
0
                0x80000000UL | (loval<<15) | hival;
453
0
            }
454
0
          }
455
8.35k
        }
456
261
      }
457
261
    }
458
908
  }
459
460
908
  return(0);
461
150
 err_out:
462
150
  _ogg_free(sortindex);
463
150
  _ogg_free(codep);
464
150
  _ogg_free(codes);
465
150
  vorbis_book_clear(c);
466
150
  return(-1);
467
1.05k
}
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