Add test coverage for entropy coder compatibility.
authorTimothy B. Terriberry <tterribe@xiph.org>
Wed, 22 Dec 2010 01:30:45 +0000 (17:30 -0800)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Wed, 22 Dec 2010 01:41:52 +0000 (20:41 -0500)
This ensures that the various alternative routines in the entropy
 encoder and decoder (e.g., ec_{enc|dec}_bit_logp()) really are
 just specialized optimizations of the same general ec_encode()
 and ec_decode() routines.
This is done by randomly picking one to encode with for each symbol,
 and randomly picking a different one to decode with.

tests/ectest.c

index eebab32..48f9fa4 100644 (file)
@@ -167,8 +167,103 @@ int main(int _argc,char **_argv){
          j+1,ec_dec_tell(&dec,3),tell[j+1],seed);
       }
     }
+    free(tell);
     free(data);
   }
+  /*Test compatibility between multiple different encode/decode routines.*/
+  for(i=0;i<409600;i++){
+    unsigned *logp1;
+    unsigned *data;
+    unsigned *tell;
+    unsigned *enc_method;
+    int       j;
+    sz=rand()/((RAND_MAX>>(rand()%9))+1);
+    logp1=(unsigned *)malloc(sz*sizeof(*logp1));
+    data=(unsigned *)malloc(sz*sizeof(*data));
+    tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
+    enc_method=(unsigned *)malloc(sz*sizeof(*enc_method));
+    ec_byte_writeinit_buffer(&buf, ptr, DATA_SIZE2);
+    ec_enc_init(&enc,&buf);
+    tell[0]=ec_enc_tell(&enc,3);
+    for(j=0;j<sz;j++){
+      data[j]=rand()/((RAND_MAX>>1)+1);
+      logp1[j]=(rand()%15)+1;
+      enc_method[j]=rand()%3;
+      switch(enc_method[j]){
+        case 0:{
+          ec_encode(&enc,data[j]?(1<<logp1[j])-1:0,
+           (1<<logp1[j])-(data[j]?0:1),1<<logp1[j]);
+        }break;
+        case 1:{
+          ec_encode_bin(&enc,data[j]?(1<<logp1[j])-1:0,
+           (1<<logp1[j])-(data[j]?0:1),logp1[j]);
+        }break;
+        case 2:{
+          ec_enc_bit_logp(&enc,data[j],logp1[j]);
+        }break;
+      }
+      tell[j+1]=ec_enc_tell(&enc,3);
+    }
+    ec_enc_done(&enc);
+    if((ec_enc_tell(&enc,0)+7)/8<ec_byte_bytes(&buf)){
+      fprintf(stderr,"tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
+       ec_byte_bytes(&buf),(ec_enc_tell(&enc,0)+7)/8,seed);
+      ret=-1;
+    }
+    ec_byte_readinit(&buf,ptr,DATA_SIZE2);
+    ec_dec_init(&dec,&buf);
+    if(ec_dec_tell(&dec,3)!=tell[0]){
+      fprintf(stderr,
+       "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
+       0,ec_dec_tell(&dec,3),tell[0],seed);
+    }
+    for(j=0;j<sz;j++){
+      int fs;
+      int dec_method;
+      dec_method=rand()/((RAND_MAX>>2)+1);
+      switch(dec_method){
+        case 0:{
+          fs=ec_decode(&dec,1<<logp1[j]);
+          sym=fs>=(1<<logp1[j])-1;
+          ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
+           (1<<logp1[j])-(sym?0:1),1<<logp1[j]);
+        }break;
+        case 1:{
+          fs=ec_decode_bin(&dec,logp1[j]);
+          sym=fs>=(1<<logp1[j])-1;
+          ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
+           (1<<logp1[j])-(sym?0:1),1<<logp1[j]);
+        }break;
+        case 2:{
+          sym=ec_dec_bit_logp(&dec,logp1[j]);
+        }break;
+        case 3:{
+          int cdf[3];
+          cdf[0]=0;
+          cdf[1]=(1<<logp1[j])-1;
+          cdf[2]=1<<logp1[j];
+          sym=ec_dec_cdf(&dec,cdf,logp1[j]);
+        }break;
+      }
+      if(sym!=data[j]){
+        fprintf(stderr,
+         "Decoded %i instead of %i with logp1 of %i at position %i of %i (Random seed: %u).\n",
+         sym,data[j],logp1[j],j,sz,seed);
+        fprintf(stderr,"Encoding method: %i, decoding method: %i\n",
+         enc_method[j],dec_method);
+        ret=-1;
+      }
+      if(ec_dec_tell(&dec,3)!=tell[j+1]){
+        fprintf(stderr,
+         "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
+         j+1,ec_dec_tell(&dec,3),tell[j+1],seed);
+      }
+    }
+    free(enc_method);
+    free(tell);
+    free(data);
+    free(logp1);
+  }
   free(ptr);
   return ret;
 }