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

  1. /* 
  2.  *  IEEE1180Test.cpp 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - July 2000 - ultraflask@yahoo.com
  5.  *
  6.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  7.  *    
  8.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2, or (at your option)
  11.  *  any later version.
  12.  *   
  13.  *  FlasKMPEG is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *   
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with GNU Make; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  *
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <malloc.h>
  26. #include <memory.h>
  27. #include <crtdbg.h>
  28. #include <math.h>
  29. #include "IEEE1180Test.h"
  30.  
  31. //////////////////////////////////////////////////////////////////////
  32. // Construction/Destruction
  33. //////////////////////////////////////////////////////////////////////
  34.  
  35. CIEEE1180Test::CIEEE1180Test()
  36. {
  37.   m_nProgress = 0;
  38. }
  39.  
  40. CIEEE1180Test::~CIEEE1180Test()
  41. {
  42.  
  43. }
  44. /*time $1 -256 255 1 10000
  45. time $1 -5 5     1 10000
  46. time $1 -300 300 1 10000
  47.  
  48. time $1 -256 255 -1 10000
  49. time $1 -5 5     -1 10000
  50. time $1 -300 300 -1 10000
  51. */
  52. #define PROGRESS_STEPS 6L
  53.  
  54. bool CIEEE1180Test::IsIEEE1180( void (* TestIdct)(DCTELEM *block) )
  55. {
  56.   bool meet=true;
  57.  
  58.   // Initialize random generator variables
  59.   randx = 1;
  60.   z = (double) 0x7fffffff;
  61.  
  62.  
  63.   meet = meet && DoTest( -256, 255, 1, 10000, TestIdct );
  64.   m_nProgress += 110/PROGRESS_STEPS;
  65.   meet = meet && DoTest( -5,     5, 1, 10000, TestIdct );
  66.   m_nProgress += 110/PROGRESS_STEPS;
  67.   meet = meet && DoTest( -300, 300, 1, 10000, TestIdct );
  68.   m_nProgress += 110/PROGRESS_STEPS;
  69.  
  70.   meet = meet && DoTest( -256, 255, 1, 10000, TestIdct );
  71.   m_nProgress += 110/PROGRESS_STEPS;
  72.   meet = meet && DoTest( -5,     5, 1, 10000, TestIdct );
  73.   m_nProgress += 110/PROGRESS_STEPS;
  74.   meet = meet && DoTest( -300, 300, 1, 10000, TestIdct );
  75.   m_nProgress += 110/PROGRESS_STEPS;
  76.  
  77.   return meet;
  78. }
  79.  
  80. bool CIEEE1180Test::DoTest(long minpix, long maxpix, long sign, long niters, void (* TestIdct)(DCTELEM *block))
  81. {
  82.   long curiter;
  83.   int i, j;
  84.   double max, total;
  85.   bool meet=true;
  86.   bool partmeet;
  87.   DCTELEM   block[DCTSIZE2];    /* random source data */
  88.   DCTELEM   refcoefs[DCTSIZE2]; /* coefs from reference FDCT */
  89.   DCTELEM   refout[DCTSIZE2];    /* output from reference IDCT */
  90.  
  91.   __declspec(align(16))
  92.   DCTELEM   testout[DCTSIZE2]; /* output from test IDCT */
  93.  
  94.   // Intialize errors vector acumulators
  95.   for(i=0; i<DCTSIZE2; i++)
  96.     sumerrs[i] = 0;
  97.   for(i=0; i<DCTSIZE2; i++)
  98.     sumsqerrs[i] = 0;
  99.   for(i=0; i<DCTSIZE2; i++)
  100.     maxerr[i] = 0;
  101.  
  102.   DCTInit();
  103.  
  104.   /* Loop once per generated random-data block */
  105.  
  106.   for (curiter = 0; curiter < niters; curiter++) {
  107.  
  108.     /* generate a pseudo-random block of data */
  109.     for (i = 0; i < DCTSIZE2; i++)
  110.       block[i] = (DCTELEM) (IEEERand(-minpix,maxpix) * sign);
  111.  
  112.     /* perform reference FDCT */
  113.     memcpy(refcoefs, block, sizeof(DCTELEM)*DCTSIZE2);
  114.     RefForwardDCT(refcoefs );
  115.     /* clip */
  116.     for (i = 0; i < DCTSIZE2; i++) {
  117.       if (refcoefs[i] < -2048) refcoefs[i] = -2048;
  118.       else if (refcoefs[i] > 2047) refcoefs[i] = 2047;
  119.     }
  120.  
  121.     /* perform reference IDCT */
  122.     memcpy(refout, refcoefs, sizeof(DCTELEM)*DCTSIZE2);
  123.     RefInverseDCT(refout);
  124.     /* clip */
  125.     for (i = 0; i < DCTSIZE2; i++) {
  126.       if (refout[i] < -256) refout[i] = -256;
  127.       else if (refout[i] > 255) refout[i] = 255;
  128.     }
  129.  
  130.     /* perform test IDCT */
  131.     memcpy(testout, refcoefs, sizeof(DCTELEM)*DCTSIZE2);
  132.     TestIdct(testout);
  133.     /* clip */
  134.     for (i = 0; i < DCTSIZE2; i++) {
  135.       if (testout[i] < -256) testout[i] = -256;
  136.       else if (testout[i] > 255) testout[i] = 255;
  137.     }
  138.  
  139.     /* accumulate error stats */
  140.     for (i = 0; i < DCTSIZE2; i++) {
  141.       register int err = testout[i] - refout[i];
  142.       sumerrs[i] += err;
  143.       sumsqerrs[i] += err * err;
  144.       if (err < 0) err = -err;
  145.       if (maxerr[i] < err) maxerr[i] = err;
  146.     }
  147.  
  148.     if (curiter % 100 == 99) {
  149.       fprintf(stderr, ".");
  150.       fflush(stderr);
  151.     }
  152.   }
  153.   fprintf(stderr, "\r\r\n");
  154.  
  155. #define UpdateResultsStr() (m_strResults += m_pTmpStr)
  156.   /* print results */
  157.   sprintf(m_pTmpStr, "IEEE test conditions: -L = %ld, +H = %ld, sign = %ld, #iters = %ld\r\r\n",
  158.      minpix, maxpix, sign, niters);
  159.   UpdateResultsStr();
  160.  
  161.  
  162.   sprintf(m_pTmpStr, "Peak absolute values of errors:\r\r\n");
  163.   for (i = 0, j = 0; i < DCTSIZE2; i++) {
  164.     if (j < maxerr[i]) j = maxerr[i];
  165.     {
  166.       sprintf(m_pTmpStr, "%4d", maxerr[i]);
  167.       UpdateResultsStr();
  168.     }
  169.  
  170.     if ((i%DCTSIZE) == DCTSIZE-1){ sprintf(m_pTmpStr,  "\r\r\n");   UpdateResultsStr(); }
  171.   }
  172.  
  173.   meet = (partmeet=Meets((double) j, 1.0)) &&meet;
  174.   sprintf(m_pTmpStr, "Worst peak error = %d  (%s spec limit 1)\r\r\n\r\n", j,
  175.      partmeet?"Meets":"Does NOT Meet");
  176.   UpdateResultsStr();
  177.  
  178.   sprintf(m_pTmpStr, "Mean square errors:\r\n");
  179.   UpdateResultsStr();
  180.  
  181.   max = total = 0.0;
  182.   for (i = 0; i < DCTSIZE2; i++) {
  183.     double err = (double) sumsqerrs[i]  / ((double) niters);
  184.     total += (double) sumsqerrs[i];
  185.     if (max < err) max = err;
  186.     sprintf(m_pTmpStr," %8.4f", err );
  187.     UpdateResultsStr();
  188.       if ((i%DCTSIZE) == DCTSIZE-1){ sprintf(m_pTmpStr, "\r\n");   UpdateResultsStr(); }
  189.   }
  190.  
  191.   meet = (partmeet=Meets(max, 0.06)) &&meet;
  192.   sprintf(m_pTmpStr, "Worst pmse = %.6f  (%s spec limit 0.06)\r\n", max, partmeet?"Meets":"Does NOT Meet");
  193.   UpdateResultsStr();
  194.   total /= (double) (64*niters);
  195.  
  196.   meet = (partmeet=Meets(total, 0.02)) &&meet;
  197.   sprintf(m_pTmpStr, "Overall mse = %.6f  (%s spec limit 0.02)\r\n\r\n", total, partmeet?"Meets":"Does NOT Meet");
  198.   UpdateResultsStr();
  199.  
  200.   sprintf(m_pTmpStr, "Mean errors:\r\n");
  201.   UpdateResultsStr();
  202.  
  203.   max = total = 0.0;
  204.   for (i = 0; i < DCTSIZE2; i++) {
  205.     double err = (double) sumerrs[i]  / ((double) niters);
  206.     total += (double) sumerrs[i];
  207.     sprintf(m_pTmpStr," %8.4f", err);
  208.     UpdateResultsStr();
  209.     if (err < 0.0) err = -err;
  210.     if (max < err) max = err;
  211.     if ((i%DCTSIZE) == DCTSIZE-1) { sprintf(m_pTmpStr,"\r\n");   UpdateResultsStr(); }
  212.   }
  213.  
  214.   meet = (partmeet=Meets(max, 0.015)) &&meet;
  215.   sprintf(m_pTmpStr, "Worst mean error = %.6f  (%s spec limit 0.015)\r\n", max, partmeet?"Meets":"Does NOT Meet");
  216.   UpdateResultsStr();
  217.  
  218.  
  219.   total /= (double) (64*niters);
  220.  
  221.   meet = (partmeet=Meets(total, 0.0015)) &&meet;
  222.   sprintf(m_pTmpStr,"Overall mean error = %.6f  (%s spec limit 0.0015)\r\n\r\n", total, partmeet?"Meets":"Does NOT Meet");
  223.   UpdateResultsStr();
  224.  
  225.   /* test for 0 input giving 0 output */
  226.   memset(testout, 0, sizeof(DCTELEM)*DCTSIZE2);
  227.   TestIdct(testout);
  228.   for (i = 0, j=0; i < DCTSIZE2; i++) {
  229.     if (testout[i]) {
  230.       sprintf(m_pTmpStr, "Position %d of IDCT(0) = %d (FAILS)\r\n", i, testout[i]);
  231.       UpdateResultsStr();
  232.       j++;
  233.     }
  234.   }
  235.   sprintf(m_pTmpStr, "%d elements of IDCT(0) were not zero\r\n\r\n\r\n", j);
  236.   UpdateResultsStr();
  237.   if( j )
  238.     meet = false;
  239.  
  240.   return meet;
  241. }
  242.  
  243. void CIEEE1180Test::RefForwardDCT(DCTELEM *block)
  244. {
  245.   int x,y,u,v;
  246.   double tmp, tmp2;
  247.   double  res[8][8];
  248.   DCTELEM (*blk)[8] =  (DCTELEM(*)[8])block;
  249.   
  250.   for (v=0; v<8; v++) {
  251.     for (u=0; u<8; u++) {
  252.       tmp = 0.0;
  253.       for (y=0; y<8; y++) {
  254.         tmp2 = 0.0;
  255.         for (x=0; x<8; x++) {
  256.           tmp2 += (double) blk[y][x] * coslu[x][u];
  257.         }
  258.         tmp += coslu[y][v] * tmp2;
  259.       }
  260.       res[v][u] = tmp;
  261.     }
  262.   }
  263.   
  264.   for (v=0; v<8; v++) {
  265.     for (u=0; u<8; u++) {
  266.       tmp = res[v][u];
  267.       if (tmp < 0.0) {
  268.         x = - ((int) (0.5 - tmp));
  269.       } else {
  270.         x = (int) (tmp + 0.5);
  271.       }
  272.       blk[v][u] = (DCTELEM) x;
  273.     }
  274.   }
  275. }
  276.  
  277. void CIEEE1180Test::RefInverseDCT(DCTELEM *block)
  278. {
  279.   int x,y,u,v;
  280.   double tmp, tmp2;
  281.   double res[8][8];  
  282.   DCTELEM (*blk)[8] =  (DCTELEM(*)[8])block;
  283.  
  284.   for (y=0; y<8; y++) {
  285.     for (x=0; x<8; x++) {
  286.       tmp = 0.0;
  287.       for (v=0; v<8; v++) {
  288.         tmp2 = 0.0;
  289.         for (u=0; u<8; u++) {
  290.           tmp2 += (double) blk[v][u] * coslu[x][u];
  291.         }
  292.         tmp += coslu[y][v] * tmp2;
  293.       }
  294.       res[y][x] = tmp;
  295.     }
  296.   }
  297.   
  298.   for (v=0; v<8; v++) {
  299.     for (u=0; u<8; u++) {
  300.       tmp = res[v][u];
  301.       if (tmp < 0.0) {
  302.         x = - ((int) (0.5 - tmp));
  303.       } else {
  304.         x = (int) (tmp + 0.5);
  305.       }
  306.       blk[v][u] = (DCTELEM) x;
  307.     }
  308.   }
  309. }
  310.  
  311. /* Routine to initialise the cosine lookup table */
  312. void CIEEE1180Test::DCTInit()
  313. {
  314.   int a,b;
  315.   double tmp;
  316.   
  317.   for(a=0;a<8;a++)
  318.     for(b=0;b<8;b++) {
  319.       tmp = cos((double)((a+a+1)*b) * (3.14159265358979323846 / 16.0));
  320.       if(b==0)
  321.         tmp /= sqrt(2.0);
  322.       coslu[a][b] = tmp * 0.5;
  323.     }
  324.  
  325. }
  326. /* Pseudo-random generator specified by IEEE 1180 */
  327. long CIEEE1180Test::IEEERand(long L, long H)
  328. {
  329.   long i,j;
  330.   double x;
  331.  
  332.   randx = (randx * 1103515245) + 12345;
  333.   i = randx & 0x7ffffffe;
  334.   x = ((double) i) / z;
  335.   x *= (L+H+1);
  336.   j = (long)x;
  337.   return j-L;
  338. }
  339.  
  340.  
  341. bool CIEEE1180Test::Meets(double val, double limit)
  342. {
  343.   return (fabs(val) <= limit);
  344. }
  345.