home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2004 March / PCWELT_3_2004.ISO / pcwsoft / flaskmpeg_078_39_src.z.exe / flaskmpeg / Video / ieee1180test.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-28  |  7.4 KB  |  284 lines

  1. // IEEE1180Test.cpp: implementation of the CIEEE1180Test class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4.  
  5. #include <stdio.h>
  6. #include <malloc.h>
  7. #include <memory.h>
  8. #include <crtdbg.h>
  9. #include <math.h>
  10. #include "IEEE1180Test.h"
  11.  
  12. //////////////////////////////////////////////////////////////////////
  13. // Construction/Destruction
  14. //////////////////////////////////////////////////////////////////////
  15.  
  16. CIEEE1180Test::CIEEE1180Test()
  17. {
  18.  
  19. }
  20.  
  21. CIEEE1180Test::~CIEEE1180Test()
  22. {
  23.  
  24. }
  25. /*time $1 -256 255 1 10000
  26. time $1 -5 5     1 10000
  27. time $1 -300 300 1 10000
  28.  
  29. time $1 -256 255 -1 10000
  30. time $1 -5 5     -1 10000
  31. time $1 -300 300 -1 10000
  32. */
  33. bool CIEEE1180Test::IsIEEE1180( void (* TestIdct)(DCTELEM *block) )
  34. {
  35.   bool meet=true;
  36.  
  37.   // Initialize random generator variables
  38.   randx = 1;
  39.   z = (double) 0x7fffffff;
  40.  
  41.  
  42.   meet = meet && DoTest( -256, 255, 1, 10000, TestIdct );
  43.   meet = meet && DoTest( -5,     5, 1, 10000, TestIdct );
  44.   meet = meet && DoTest( -300, 300, 1, 10000, TestIdct );
  45.  
  46.   meet = meet && DoTest( -256, 255, 1, 10000, TestIdct );
  47.   meet = meet && DoTest( -5,     5, 1, 10000, TestIdct );
  48.   meet = meet && DoTest( -300, 300, 1, 10000, TestIdct );
  49.  
  50.   return meet;
  51. }
  52. bool CIEEE1180Test::DoTest(long minpix, long maxpix, long sign, long niters, void (* TestIdct)(DCTELEM *block))
  53. {
  54.   long curiter;
  55.   int i, j;
  56.   double max, total;
  57.   bool meet=true;
  58.   DCTELEM   block[DCTSIZE2];    /* random source data */
  59.   DCTELEM   refcoefs[DCTSIZE2]; /* coefs from reference FDCT */
  60.   DCTELEM   refout[DCTSIZE2];    /* output from reference IDCT */
  61.   DCTELEM   testout[DCTSIZE2]; /* output from test IDCT */
  62.  
  63.   // Intialize errors vector acumulators
  64.   for(i=0; i<DCTSIZE2; i++)
  65.     sumerrs[i] = 0;
  66.   for(i=0; i<DCTSIZE2; i++)
  67.     sumsqerrs[i] = 0;
  68.   for(i=0; i<DCTSIZE2; i++)
  69.     maxerr[i] = 0;
  70.  
  71.   DCTInit();
  72.  
  73.   /* Loop once per generated random-data block */
  74.  
  75.   for (curiter = 0; curiter < niters; curiter++) {
  76.  
  77.     /* generate a pseudo-random block of data */
  78.     for (i = 0; i < DCTSIZE2; i++)
  79.       block[i] = (DCTELEM) (IEEERand(-minpix,maxpix) * sign);
  80.  
  81.     /* perform reference FDCT */
  82.     memcpy(refcoefs, block, sizeof(DCTELEM)*DCTSIZE2);
  83.     RefForwardDCT(refcoefs );
  84.     /* clip */
  85.     for (i = 0; i < DCTSIZE2; i++) {
  86.       if (refcoefs[i] < -2048) refcoefs[i] = -2048;
  87.       else if (refcoefs[i] > 2047) refcoefs[i] = 2047;
  88.     }
  89.  
  90.     /* perform reference IDCT */
  91.     memcpy(refout, refcoefs, sizeof(DCTELEM)*DCTSIZE2);
  92.     RefInverseDCT(refout);
  93.     /* clip */
  94.     for (i = 0; i < DCTSIZE2; i++) {
  95.       if (refout[i] < -256) refout[i] = -256;
  96.       else if (refout[i] > 255) refout[i] = 255;
  97.     }
  98.  
  99.     /* perform test IDCT */
  100.     memcpy(testout, refcoefs, sizeof(DCTELEM)*DCTSIZE2);
  101.     TestIdct(testout);
  102.     /* clip */
  103.     for (i = 0; i < DCTSIZE2; i++) {
  104.       if (testout[i] < -256) testout[i] = -256;
  105.       else if (testout[i] > 255) testout[i] = 255;
  106.     }
  107.  
  108.     /* accumulate error stats */
  109.     for (i = 0; i < DCTSIZE2; i++) {
  110.       register int err = testout[i] - refout[i];
  111.       sumerrs[i] += err;
  112.       sumsqerrs[i] += err * err;
  113.       if (err < 0) err = -err;
  114.       if (maxerr[i] < err) maxerr[i] = err;
  115.     }
  116.  
  117.     if (curiter % 100 == 99) {
  118.       fprintf(stderr, ".");
  119.       fflush(stderr);
  120.     }
  121.   }
  122.   fprintf(stderr, "\n");
  123.  
  124.   /* print results */
  125.   _RPT4(_CRT_WARN, "IEEE test conditions: -L = %ld, +H = %ld, sign = %ld, #iters = %ld\n",
  126.      minpix, maxpix, sign, niters);
  127.  
  128.   _RPT0(_CRT_WARN, "Peak absolute values of errors:\n");
  129.   for (i = 0, j = 0; i < DCTSIZE2; i++) {
  130.     if (j < maxerr[i]) j = maxerr[i];
  131.       _RPT1(_CRT_WARN, "%4d", maxerr[i]);
  132.     if ((i%DCTSIZE) == DCTSIZE-1) _RPT0(_CRT_WARN, "\n");
  133.   }
  134.   _RPT2(_CRT_WARN, "Worst peak error = %d  (%d spec limit 1)\n\n", j,
  135.      meet = Meets((double) j, 1.0) && meet);
  136.  
  137.   _RPT0(_CRT_WARN, "Mean square errors:\n");
  138.   max = total = 0.0;
  139.   for (i = 0; i < DCTSIZE2; i++) {
  140.     double err = (double) sumsqerrs[i]  / ((double) niters);
  141.     total += (double) sumsqerrs[i];
  142.     if (max < err) max = err;
  143.     _RPT1(_CRT_WARN," %8.4f", err );
  144.     if ((i%DCTSIZE) == DCTSIZE-1) _RPT0(_CRT_WARN, "\n");
  145.   }
  146.  
  147.   _RPT2(_CRT_WARN, "Worst pmse = %.6f  (%d spec limit 0.06)\n", max, meet = Meets(max, 0.06)&&meet);
  148.   total /= (double) (64*niters);
  149.  
  150.   _RPT2(_CRT_WARN, "Overall mse = %.6f  (%d spec limit 0.02)\n\n", total, meet = Meets(total, 0.02) && meet);
  151.  
  152.   _RPT0(_CRT_WARN, "Mean errors:\n");
  153.   max = total = 0.0;
  154.   for (i = 0; i < DCTSIZE2; i++) {
  155.     double err = (double) sumerrs[i]  / ((double) niters);
  156.     total += (double) sumerrs[i];
  157.     printf(" %8.4f", err);
  158.     if (err < 0.0) err = -err;
  159.     if (max < err) max = err;
  160.     if ((i%DCTSIZE) == DCTSIZE-1) printf("\n");
  161.   }
  162.   _RPT2(_CRT_WARN, "Worst mean error = %.6f  (%d spec limit 0.015)\n", max, meet = Meets(max, 0.015)&&meet);
  163.   total /= (double) (64*niters);
  164.   _RPT2(_CRT_WARN,"Overall mean error = %.6f  (%d spec limit 0.0015)\n\n", total, meet= Meets(total, 0.0015)&&meet);
  165.  
  166.   /* test for 0 input giving 0 output */
  167.   memset(testout, 0, sizeof(DCTELEM)*DCTSIZE2);
  168.   TestIdct(testout);
  169.   for (i = 0, j=0; i < DCTSIZE2; i++) {
  170.     if (testout[i]) {
  171.       _RPT2(_CRT_WARN, "Position %d of IDCT(0) = %d (FAILS)\n", i, testout[i]);
  172.       j++;
  173.     }
  174.   }
  175.   _RPT1(_CRT_WARN, "%d elements of IDCT(0) were not zero\n\n\n", j);
  176.   if( j )
  177.     meet = false;
  178.  
  179.   return meet;
  180. }
  181.  
  182. void CIEEE1180Test::RefForwardDCT(DCTELEM *block)
  183. {
  184.   int x,y,u,v;
  185.   double tmp, tmp2;
  186.   double  res[8][8];
  187.   DCTELEM (*blk)[8] =  (DCTELEM(*)[8])block;
  188.   
  189.   for (v=0; v<8; v++) {
  190.     for (u=0; u<8; u++) {
  191.       tmp = 0.0;
  192.       for (y=0; y<8; y++) {
  193.         tmp2 = 0.0;
  194.         for (x=0; x<8; x++) {
  195.           tmp2 += (double) blk[y][x] * coslu[x][u];
  196.         }
  197.         tmp += coslu[y][v] * tmp2;
  198.       }
  199.       res[v][u] = tmp;
  200.     }
  201.   }
  202.   
  203.   for (v=0; v<8; v++) {
  204.     for (u=0; u<8; u++) {
  205.       tmp = res[v][u];
  206.       if (tmp < 0.0) {
  207.         x = - ((int) (0.5 - tmp));
  208.       } else {
  209.         x = (int) (tmp + 0.5);
  210.       }
  211.       blk[v][u] = (DCTELEM) x;
  212.     }
  213.   }
  214. }
  215.  
  216. void CIEEE1180Test::RefInverseDCT(DCTELEM *block)
  217. {
  218.   int x,y,u,v;
  219.   double tmp, tmp2;
  220.   double res[8][8];  
  221.   DCTELEM (*blk)[8] =  (DCTELEM(*)[8])block;
  222.  
  223.   for (y=0; y<8; y++) {
  224.     for (x=0; x<8; x++) {
  225.       tmp = 0.0;
  226.       for (v=0; v<8; v++) {
  227.         tmp2 = 0.0;
  228.         for (u=0; u<8; u++) {
  229.           tmp2 += (double) blk[v][u] * coslu[x][u];
  230.         }
  231.         tmp += coslu[y][v] * tmp2;
  232.       }
  233.       res[y][x] = tmp;
  234.     }
  235.   }
  236.   
  237.   for (v=0; v<8; v++) {
  238.     for (u=0; u<8; u++) {
  239.       tmp = res[v][u];
  240.       if (tmp < 0.0) {
  241.         x = - ((int) (0.5 - tmp));
  242.       } else {
  243.         x = (int) (tmp + 0.5);
  244.       }
  245.       blk[v][u] = (DCTELEM) x;
  246.     }
  247.   }
  248. }
  249.  
  250. /* Routine to initialise the cosine lookup table */
  251. void CIEEE1180Test::DCTInit()
  252. {
  253.   int a,b;
  254.   double tmp;
  255.   
  256.   for(a=0;a<8;a++)
  257.     for(b=0;b<8;b++) {
  258.       tmp = cos((double)((a+a+1)*b) * (3.14159265358979323846 / 16.0));
  259.       if(b==0)
  260.         tmp /= sqrt(2.0);
  261.       coslu[a][b] = tmp * 0.5;
  262.     }
  263.  
  264. }
  265. /* Pseudo-random generator specified by IEEE 1180 */
  266. long CIEEE1180Test::IEEERand(long L, long H)
  267. {
  268.   long i,j;
  269.   double x;
  270.  
  271.   randx = (randx * 1103515245) + 12345;
  272.   i = randx & 0x7ffffffe;
  273.   x = ((double) i) / z;
  274.   x *= (L+H+1);
  275.   j = (long)x;
  276.   return j-L;
  277. }
  278.  
  279.  
  280. bool CIEEE1180Test::Meets(double val, double limit)
  281. {
  282.   return (fabs(val) <= limit);
  283. }
  284.