*/
#include <stdio.h>
+#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#define F 100
#define SIZE 2048
-uint64_t exp16_table[20]={
+uint64_t exp16_table[21]={
65537,
65538,
65540,
484249,
3578144,
195360063,
+ 582360139072LL,
};
#if 1
// 16.16 fixpoint exp()
return out;
}
// 16.16 fixpoint log()
-static uint64_t log16(uint64_t a){
+static int64_t log16(uint64_t a){
int i;
int out=0;
-
- assert(a >= (1<<16));
+
+ if(a < 1<<16)
+ return -log16((1LL<<32) / a);
a<<=16;
- for(i=19;i>=0;i--){
- if(a<(exp16_table[i]<<16)) continue;
+ for(i=20;i>=0;i--){
+ int64_t b= exp16_table[i];
+ if(a<(b<<16)) continue;
out |= 1<<i;
- a = ((a<<16) + exp16_table[i]/2)/exp16_table[i];
+ a = ((a/b)<<16) + (((a%b)<<16) + b/2)/b;
}
return out;
}
FILE *f[2];
uint8_t buf[2][SIZE];
uint64_t psnr;
+ int len= argc<4 ? 1 : atoi(argv[3]);
+ int64_t max= (1<<(8*len))-1;
+ int shift= argc<5 ? 0 : atoi(argv[4]);
- if(argc!=3){
- printf("tiny_psnr <file1> <file2>\n");
+ if(argc<3){
+ printf("tiny_psnr <file1> <file2> [<elem size> [<shift>]]\n");
return -1;
}
- f[0]= fopen(argv[1], "r");
- f[1]= fopen(argv[2], "r");
+ f[0]= fopen(argv[1], "rb");
+ f[1]= fopen(argv[2], "rb");
+ fseek(f[shift<0], shift < 0 ? -shift : shift, SEEK_SET);
for(i=0;;){
if( fread(buf[0], SIZE, 1, f[0]) != 1) break;
if( fread(buf[1], SIZE, 1, f[1]) != 1) break;
for(j=0; j<SIZE; i++,j++){
- const int a= buf[0][j];
- const int b= buf[1][j];
+ int64_t a= buf[0][j];
+ int64_t b= buf[1][j];
+ if(len==2){
+ a= (int16_t)(a | (buf[0][++j]<<8));
+ b= (int16_t)(b | (buf[1][ j]<<8));
+ }
sse += (a-b) * (a-b);
}
}
- dev= int_sqrt((sse*F*F)/i);
+ if(!i) i=1;
+ dev= int_sqrt( ((sse/i)*F*F) + (((sse%i)*F*F) + i/2)/i );
if(sse)
- psnr= (log16(256*256*255*255LL*i/sse)*284619LL*F + (1<<31)) / (1LL<<32);
+ psnr= ((2*log16(max<<16) + log16(i) - log16(sse))*284619LL*F + (1<<31)) / (1LL<<32);
else
psnr= 100*F-1; //floating point free infinity :)