bjontegaard.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*Daala video codec
  2. Copyright (c) 2014 Daala project contributors. All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions are met:
  5. - Redistributions of source code must retain the above copyright notice, this
  6. list of conditions and the following disclaimer.
  7. - Redistributions in binary form must reproduce the above copyright notice,
  8. this list of conditions and the following disclaimer in the documentation
  9. and/or other materials provided with the distribution.
  10. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
  11. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  13. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  14. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  15. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  16. SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  17. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  18. OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  19. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
  20. #include <float.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <math.h>
  24. #include <string.h>
  25. #include "cholesky.h"
  26. #include "qr.h"
  27. #include "svd.h"
  28. #define MIN(a,b) ((a)>(b)?(b):(a))
  29. #define MAX(a,b) ((a)>(b)?(a):(b))
  30. #define PRINT_COMP (0)
  31. #define USE_SVD (0)
  32. #define USE_CHOL (0)
  33. #define USE_QR (1)
  34. #if !(USE_SVD + USE_CHOL + USE_QR == 1)
  35. # error "One of USE_SVD, USE_CHOL or USE_QR must be enabled"
  36. #endif
  37. #if PRINT_COMP
  38. void printMatrix(const char *_name,const double *_m,int _r,int _c) {
  39. int j;
  40. int i;
  41. printf("%s=[\n",_name);
  42. for (j=0;j<_r;j++) {
  43. for (i=0;i<_c;i++) {
  44. printf("%s%G",i>0?",":"",(double)_m[j*_c+i]);
  45. }
  46. printf("\n");
  47. }
  48. printf("]\n");
  49. }
  50. #endif
  51. static void polyfit(const double *_x,const double *_y,int _n,double *_c,
  52. int _deg) {
  53. int m;
  54. double *x;
  55. #if USE_SVD || USE_CHOL
  56. double *xtx;
  57. double *xty;
  58. int k;
  59. #endif
  60. int j;
  61. int i;
  62. m=_deg+1;
  63. /* Compute the Vandermonde matrix X */
  64. x=(double *)malloc(sizeof(*x)*_n*m);
  65. for (j=0;j<_n;j++) {
  66. x[j*m+0]=1;
  67. for (i=1;i<m;i++) {
  68. x[j*m+i]=x[j*m+i-1]*_x[j];
  69. }
  70. }
  71. #if PRINT_COMP
  72. printMatrix("x",x,_n,m);
  73. #endif
  74. #if USE_SVD || USE_CHOL
  75. /* Compute X^T*X */
  76. xtx=(double *)malloc(sizeof(*xtx)*m*m);
  77. for (j=0;j<m;j++) {
  78. for (i=0;i<m;i++) {
  79. xtx[j*m+i]=0;
  80. for (k=0;k<_n;k++) {
  81. xtx[j*m+i]+=x[k*m+j]*x[k*m+i];
  82. }
  83. }
  84. }
  85. #if PRINT_COMP
  86. printMatrix("xtx",xtx,m,m);
  87. #endif
  88. /* Compute X^T*Y */
  89. xty=(double *)malloc(sizeof(*xty)*m);
  90. for (j=0;j<m;j++) {
  91. xty[j]=0;
  92. for (k=0;k<_n;k++) {
  93. xty[j]+=x[k*m+j]*_y[k];
  94. }
  95. }
  96. #if PRINT_COMP
  97. printMatrix("xty",xty,m,1);
  98. #endif
  99. #endif
  100. #if USE_SVD
  101. {
  102. double *w;
  103. double **wp;
  104. double *s;
  105. /* Compute (X^T*X)^-1 */
  106. w=(double *)malloc(sizeof(*w)*m*2*m);
  107. wp=(double **)malloc(sizeof(*wp)*2*m);
  108. s=(double *)malloc(sizeof(*s)*m);
  109. for (j=0;j<m;j++) {
  110. for (i=0;i<m;i++) {
  111. w[j*m+i]=xtx[j*m+i];
  112. }
  113. }
  114. for (j=0;j<2*m;j++) {
  115. wp[j]=&w[j*m];
  116. }
  117. svd_pseudoinverse(wp,s,m,m);
  118. #if PRINT_COMP
  119. printMatrix("xtx^-1",w,m,m);
  120. #endif
  121. /* Compute (X^T*X)^-1*(X^T*Y) */
  122. for (j=0;j<m;j++) {
  123. _c[j]=0;
  124. for (k=0;k<m;k++) {
  125. _c[j]+=w[j*m+k]*xty[k];
  126. }
  127. }
  128. free(w);
  129. free(wp);
  130. free(s);
  131. }
  132. #elif USE_CHOL
  133. {
  134. double *r;
  135. int *pivot;
  136. int rank;
  137. double *tau;
  138. double *work;
  139. r=(double *)malloc(sizeof(*r)*UT_SZ(m,m));
  140. pivot=(int *)malloc(sizeof(*pivot)*m);
  141. tau=(double *)malloc(sizeof(*tau)*m);
  142. work=(double *)malloc(sizeof(*work)*m);
  143. for (j=0;j<m;j++) {
  144. for (i=j;i<m;i++) {
  145. r[UT_IDX(j,i,m)]=xtx[j*m+i];
  146. }
  147. }
  148. rank=cholesky(r,pivot,DBL_EPSILON,m);
  149. chdecomp(r,tau,rank,m);
  150. chsolve(r,pivot,tau,_c,xty,work,rank,m);
  151. free(r);
  152. free(pivot);
  153. free(tau);
  154. free(work);
  155. }
  156. #elif USE_QR
  157. {
  158. double *qrt;
  159. double *d;
  160. double *b;
  161. qrt=(double *)malloc(sizeof(*qrt)*_n*m);
  162. d=(double *)malloc(sizeof(*d)*MIN(m,_n));
  163. /* Compute x^T as input */
  164. for (j=0;j<_n;j++) {
  165. for (i=0;i<m;i++) {
  166. qrt[i*_n+j]=x[j*m+i];
  167. }
  168. }
  169. qrdecomp_hh(qrt,_n,d,NULL,0,NULL,m,_n);
  170. b=(double *)malloc(sizeof(*b)*_n);
  171. for (j=0;j<_n;j++) {
  172. b[j]=_y[j];
  173. }
  174. /* Solve _x*b=_y using QR decomposition */
  175. qrsolve_hh(qrt,_n,d,b,_n,m,_n,1);
  176. for (j=0;j<m;j++) {
  177. _c[j]=b[j];
  178. }
  179. free(qrt);
  180. free(d);
  181. free(b);
  182. }
  183. #endif
  184. free(x);
  185. #if USE_SVD || USE_CHOL
  186. free(xtx);
  187. free(xty);
  188. #endif
  189. #if PRINT_COMP
  190. printMatrix("c",_c,m,1);
  191. #endif
  192. }
  193. static void polyint(const double *_c,int _deg,double *_ci) {
  194. int i;
  195. _ci[0]=0;
  196. for (i=1;i<_deg+2;i++) {
  197. _ci[i]=_c[i-1]/i;
  198. }
  199. }
  200. static double polyval(const double *_c,int _deg,double _x) {
  201. double x;
  202. double val;
  203. int i;
  204. x=1;
  205. val=0;
  206. for (i=0;i<_deg+1;i++) {
  207. val+=_c[i]*x;
  208. x*=_x;
  209. }
  210. return(val);
  211. }
  212. static double min(double *_v,int _n) {
  213. int i;
  214. double min;
  215. min=_v[0];
  216. for (i=1;i<_n;i++) {
  217. min=MIN(min,_v[i]);
  218. }
  219. return(min);
  220. }
  221. static double max(double *_v,int _n) {
  222. int i;
  223. double max;
  224. max=_v[0];
  225. for (i=1;i<_n;i++) {
  226. max=MAX(max,_v[i]);
  227. }
  228. return(max);
  229. }
  230. #define DELIM (",")
  231. static int parseInts(int *_p,int _n,char *_s) {
  232. int i;
  233. char *s;
  234. i=0;
  235. s=strtok(_s,DELIM);
  236. while (s!=NULL&&i<_n) {
  237. _p[i]=atoi(s);
  238. i++;
  239. s=strtok(NULL,DELIM);
  240. }
  241. return s==NULL&&i==_n;
  242. }
  243. static int parseDoubles(double *_p,int _n,char *_s) {
  244. int i;
  245. char *s;
  246. i=0;
  247. s=strtok(_s,DELIM);
  248. while (s!=NULL&&i<_n) {
  249. _p[i]=atof(s);
  250. i++;
  251. s=strtok(NULL,DELIM);
  252. }
  253. return s==NULL&&i==_n;
  254. }
  255. #define RATE (0)
  256. #define PSNR (1)
  257. #define DEG (3)
  258. /* Compute the Bjontegaard metric between two RD-curves */
  259. int main(int _argc,char *_argv[]) {
  260. int type;
  261. int n1;
  262. int *area1;
  263. int *size1;
  264. double *rate1;
  265. double *psnr1;
  266. int n2;
  267. int *area2;
  268. int *size2;
  269. double *rate2;
  270. double *psnr2;
  271. int i;
  272. double p1[DEG+1];
  273. double p1i[DEG+2];
  274. double p2[DEG+1];
  275. double p2i[DEG+2];
  276. double min_int;
  277. double max_int;
  278. double int1;
  279. double int2;
  280. double avg_diff;
  281. if (_argc!=10) {
  282. printf("usage: bjontegaard <type> <n1> <area1> <size1> <psnr1> <n2> <area2> <size2> <psnr2>\n");
  283. return EXIT_FAILURE;
  284. }
  285. type=atoi(_argv[1]);
  286. n1=atoi(_argv[2]);
  287. n2=atoi(_argv[6]);
  288. area1=(int *)malloc(sizeof(*area1)*n1);
  289. size1=(int *)malloc(sizeof(*size1)*n1);
  290. rate1=(double *)malloc(sizeof(*rate1)*n1);
  291. psnr1=(double *)malloc(sizeof(*psnr1)*n1);
  292. area2=(int *)malloc(sizeof(*area2)*n2);
  293. size2=(int *)malloc(sizeof(*size2)*n2);
  294. rate2=(double *)malloc(sizeof(*rate2)*n2);
  295. psnr2=(double *)malloc(sizeof(*psnr2)*n2);
  296. if (!parseInts(area1,n1,_argv[3])) {
  297. printf("error parsing %i ints from '%s'\n",n1,_argv[3]);
  298. return EXIT_FAILURE;
  299. }
  300. if (!parseInts(size1,n1,_argv[4])) {
  301. printf("error parsing %i ints from '%s'\n",n1,_argv[4]);
  302. return EXIT_FAILURE;
  303. }
  304. if (!parseDoubles(psnr1,n1,_argv[5])) {
  305. printf("error parsing %i doubles from '%s'\n",n1,_argv[5]);
  306. return EXIT_FAILURE;
  307. }
  308. if (!parseInts(area2,n2,_argv[7])) {
  309. printf("error parsing %i ints from '%s'\n",n1,_argv[7]);
  310. return EXIT_FAILURE;
  311. }
  312. if (!parseInts(size2,n2,_argv[8])) {
  313. printf("error parsing %i ints from '%s'\n",n1,_argv[8]);
  314. return EXIT_FAILURE;
  315. }
  316. if (!parseDoubles(psnr2,n2,_argv[9])) {
  317. printf("error parsing %i doubles from '%s'\n",n1,_argv[9]);
  318. return EXIT_FAILURE;
  319. }
  320. /* Compute the rate in log scale */
  321. for (i=0;i<n1;i++) {
  322. rate1[i]=log(((double)size1[i])/area1[i]);
  323. }
  324. for (i=0;i<n2;i++) {
  325. rate2[i]=log(((double)size2[i])/area2[i]);
  326. }
  327. if (type==RATE) {
  328. /* find best fit least squares polynomial for each curve */
  329. polyfit(psnr1,rate1,n1,p1,DEG);
  330. polyfit(psnr2,rate2,n2,p2,DEG);
  331. /* find the overlapping range */
  332. min_int=MAX(min(psnr1,n1),min(psnr2,n2));
  333. max_int=MIN(max(psnr1,n1),max(psnr2,n2));
  334. }
  335. else {
  336. /* find best fit least squares polynomial for each curve */
  337. polyfit(rate1,psnr1,n1,p1,DEG);
  338. polyfit(rate2,psnr2,n2,p2,DEG);
  339. /* find the overlapping range */
  340. min_int=MAX(min(rate1,n1),min(rate2,n2));
  341. max_int=MIN(max(rate1,n1),max(rate2,n2));
  342. }
  343. /* compute the integral */
  344. polyint(p1,DEG,p1i);
  345. polyint(p2,DEG,p2i);
  346. int1=polyval(p1i,DEG+1,max_int)-polyval(p1i,DEG+1,min_int);
  347. int2=polyval(p2i,DEG+1,max_int)-polyval(p2i,DEG+1,min_int);
  348. /* find average difference */
  349. avg_diff=(int2-int1)/(max_int-min_int);
  350. if (type==RATE) {
  351. avg_diff=(exp(avg_diff)-1)*100;
  352. }
  353. printf("%G\n",avg_diff);
  354. free(size1);
  355. free(area1);
  356. free(rate1);
  357. free(psnr1);
  358. free(size2);
  359. free(area2);
  360. free(rate2);
  361. free(psnr2);
  362. return EXIT_SUCCESS;
  363. }