home *** CD-ROM | disk | FTP | other *** search
- /*
- * IEEE1180Test.cpp
- *
- * Copyright (C) Alberto Vigata - July 2000 - ultraflask@yahoo.com
- *
- * This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
- *
- * FlasKMPEG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * FlasKMPEG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
- #include <stdio.h>
- #include <malloc.h>
- #include <memory.h>
- #include <crtdbg.h>
- #include <math.h>
- #include "IEEE1180Test.h"
-
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
-
- CIEEE1180Test::CIEEE1180Test()
- {
- m_nProgress = 0;
- }
-
- CIEEE1180Test::~CIEEE1180Test()
- {
-
- }
- /*time $1 -256 255 1 10000
- time $1 -5 5 1 10000
- time $1 -300 300 1 10000
-
- time $1 -256 255 -1 10000
- time $1 -5 5 -1 10000
- time $1 -300 300 -1 10000
- */
- #define PROGRESS_STEPS 6L
-
- bool CIEEE1180Test::IsIEEE1180( void (* TestIdct)(DCTELEM *block) )
- {
- bool meet=true;
-
- // Initialize random generator variables
- randx = 1;
- z = (double) 0x7fffffff;
-
-
- meet = meet && DoTest( -256, 255, 1, 10000, TestIdct );
- m_nProgress += 110/PROGRESS_STEPS;
- meet = meet && DoTest( -5, 5, 1, 10000, TestIdct );
- m_nProgress += 110/PROGRESS_STEPS;
- meet = meet && DoTest( -300, 300, 1, 10000, TestIdct );
- m_nProgress += 110/PROGRESS_STEPS;
-
- meet = meet && DoTest( -256, 255, 1, 10000, TestIdct );
- m_nProgress += 110/PROGRESS_STEPS;
- meet = meet && DoTest( -5, 5, 1, 10000, TestIdct );
- m_nProgress += 110/PROGRESS_STEPS;
- meet = meet && DoTest( -300, 300, 1, 10000, TestIdct );
- m_nProgress += 110/PROGRESS_STEPS;
-
- return meet;
- }
-
- bool CIEEE1180Test::DoTest(long minpix, long maxpix, long sign, long niters, void (* TestIdct)(DCTELEM *block))
- {
- long curiter;
- int i, j;
- double max, total;
- bool meet=true;
- bool partmeet;
- DCTELEM block[DCTSIZE2]; /* random source data */
- DCTELEM refcoefs[DCTSIZE2]; /* coefs from reference FDCT */
- DCTELEM refout[DCTSIZE2]; /* output from reference IDCT */
-
- __declspec(align(16))
- DCTELEM testout[DCTSIZE2]; /* output from test IDCT */
-
- // Intialize errors vector acumulators
- for(i=0; i<DCTSIZE2; i++)
- sumerrs[i] = 0;
- for(i=0; i<DCTSIZE2; i++)
- sumsqerrs[i] = 0;
- for(i=0; i<DCTSIZE2; i++)
- maxerr[i] = 0;
-
- DCTInit();
-
- /* Loop once per generated random-data block */
-
- for (curiter = 0; curiter < niters; curiter++) {
-
- /* generate a pseudo-random block of data */
- for (i = 0; i < DCTSIZE2; i++)
- block[i] = (DCTELEM) (IEEERand(-minpix,maxpix) * sign);
-
- /* perform reference FDCT */
- memcpy(refcoefs, block, sizeof(DCTELEM)*DCTSIZE2);
- RefForwardDCT(refcoefs );
- /* clip */
- for (i = 0; i < DCTSIZE2; i++) {
- if (refcoefs[i] < -2048) refcoefs[i] = -2048;
- else if (refcoefs[i] > 2047) refcoefs[i] = 2047;
- }
-
- /* perform reference IDCT */
- memcpy(refout, refcoefs, sizeof(DCTELEM)*DCTSIZE2);
- RefInverseDCT(refout);
- /* clip */
- for (i = 0; i < DCTSIZE2; i++) {
- if (refout[i] < -256) refout[i] = -256;
- else if (refout[i] > 255) refout[i] = 255;
- }
-
- /* perform test IDCT */
- memcpy(testout, refcoefs, sizeof(DCTELEM)*DCTSIZE2);
- TestIdct(testout);
- /* clip */
- for (i = 0; i < DCTSIZE2; i++) {
- if (testout[i] < -256) testout[i] = -256;
- else if (testout[i] > 255) testout[i] = 255;
- }
-
- /* accumulate error stats */
- for (i = 0; i < DCTSIZE2; i++) {
- register int err = testout[i] - refout[i];
- sumerrs[i] += err;
- sumsqerrs[i] += err * err;
- if (err < 0) err = -err;
- if (maxerr[i] < err) maxerr[i] = err;
- }
-
- if (curiter % 100 == 99) {
- fprintf(stderr, ".");
- fflush(stderr);
- }
- }
- fprintf(stderr, "\r\r\n");
-
- #define UpdateResultsStr() (m_strResults += m_pTmpStr)
- /* print results */
- sprintf(m_pTmpStr, "IEEE test conditions: -L = %ld, +H = %ld, sign = %ld, #iters = %ld\r\r\n",
- minpix, maxpix, sign, niters);
- UpdateResultsStr();
-
-
- sprintf(m_pTmpStr, "Peak absolute values of errors:\r\r\n");
- for (i = 0, j = 0; i < DCTSIZE2; i++) {
- if (j < maxerr[i]) j = maxerr[i];
- {
- sprintf(m_pTmpStr, "%4d", maxerr[i]);
- UpdateResultsStr();
- }
-
- if ((i%DCTSIZE) == DCTSIZE-1){ sprintf(m_pTmpStr, "\r\r\n"); UpdateResultsStr(); }
- }
-
- meet = (partmeet=Meets((double) j, 1.0)) &&meet;
- sprintf(m_pTmpStr, "Worst peak error = %d (%s spec limit 1)\r\r\n\r\n", j,
- partmeet?"Meets":"Does NOT Meet");
- UpdateResultsStr();
-
- sprintf(m_pTmpStr, "Mean square errors:\r\n");
- UpdateResultsStr();
-
- max = total = 0.0;
- for (i = 0; i < DCTSIZE2; i++) {
- double err = (double) sumsqerrs[i] / ((double) niters);
- total += (double) sumsqerrs[i];
- if (max < err) max = err;
- sprintf(m_pTmpStr," %8.4f", err );
- UpdateResultsStr();
- if ((i%DCTSIZE) == DCTSIZE-1){ sprintf(m_pTmpStr, "\r\n"); UpdateResultsStr(); }
- }
-
- meet = (partmeet=Meets(max, 0.06)) &&meet;
- sprintf(m_pTmpStr, "Worst pmse = %.6f (%s spec limit 0.06)\r\n", max, partmeet?"Meets":"Does NOT Meet");
- UpdateResultsStr();
- total /= (double) (64*niters);
-
- meet = (partmeet=Meets(total, 0.02)) &&meet;
- sprintf(m_pTmpStr, "Overall mse = %.6f (%s spec limit 0.02)\r\n\r\n", total, partmeet?"Meets":"Does NOT Meet");
- UpdateResultsStr();
-
- sprintf(m_pTmpStr, "Mean errors:\r\n");
- UpdateResultsStr();
-
- max = total = 0.0;
- for (i = 0; i < DCTSIZE2; i++) {
- double err = (double) sumerrs[i] / ((double) niters);
- total += (double) sumerrs[i];
- sprintf(m_pTmpStr," %8.4f", err);
- UpdateResultsStr();
- if (err < 0.0) err = -err;
- if (max < err) max = err;
- if ((i%DCTSIZE) == DCTSIZE-1) { sprintf(m_pTmpStr,"\r\n"); UpdateResultsStr(); }
- }
-
- meet = (partmeet=Meets(max, 0.015)) &&meet;
- sprintf(m_pTmpStr, "Worst mean error = %.6f (%s spec limit 0.015)\r\n", max, partmeet?"Meets":"Does NOT Meet");
- UpdateResultsStr();
-
-
- total /= (double) (64*niters);
-
- meet = (partmeet=Meets(total, 0.0015)) &&meet;
- sprintf(m_pTmpStr,"Overall mean error = %.6f (%s spec limit 0.0015)\r\n\r\n", total, partmeet?"Meets":"Does NOT Meet");
- UpdateResultsStr();
-
- /* test for 0 input giving 0 output */
- memset(testout, 0, sizeof(DCTELEM)*DCTSIZE2);
- TestIdct(testout);
- for (i = 0, j=0; i < DCTSIZE2; i++) {
- if (testout[i]) {
- sprintf(m_pTmpStr, "Position %d of IDCT(0) = %d (FAILS)\r\n", i, testout[i]);
- UpdateResultsStr();
- j++;
- }
- }
- sprintf(m_pTmpStr, "%d elements of IDCT(0) were not zero\r\n\r\n\r\n", j);
- UpdateResultsStr();
- if( j )
- meet = false;
-
- return meet;
- }
-
- void CIEEE1180Test::RefForwardDCT(DCTELEM *block)
- {
- int x,y,u,v;
- double tmp, tmp2;
- double res[8][8];
- DCTELEM (*blk)[8] = (DCTELEM(*)[8])block;
-
- for (v=0; v<8; v++) {
- for (u=0; u<8; u++) {
- tmp = 0.0;
- for (y=0; y<8; y++) {
- tmp2 = 0.0;
- for (x=0; x<8; x++) {
- tmp2 += (double) blk[y][x] * coslu[x][u];
- }
- tmp += coslu[y][v] * tmp2;
- }
- res[v][u] = tmp;
- }
- }
-
- for (v=0; v<8; v++) {
- for (u=0; u<8; u++) {
- tmp = res[v][u];
- if (tmp < 0.0) {
- x = - ((int) (0.5 - tmp));
- } else {
- x = (int) (tmp + 0.5);
- }
- blk[v][u] = (DCTELEM) x;
- }
- }
- }
-
- void CIEEE1180Test::RefInverseDCT(DCTELEM *block)
- {
- int x,y,u,v;
- double tmp, tmp2;
- double res[8][8];
- DCTELEM (*blk)[8] = (DCTELEM(*)[8])block;
-
- for (y=0; y<8; y++) {
- for (x=0; x<8; x++) {
- tmp = 0.0;
- for (v=0; v<8; v++) {
- tmp2 = 0.0;
- for (u=0; u<8; u++) {
- tmp2 += (double) blk[v][u] * coslu[x][u];
- }
- tmp += coslu[y][v] * tmp2;
- }
- res[y][x] = tmp;
- }
- }
-
- for (v=0; v<8; v++) {
- for (u=0; u<8; u++) {
- tmp = res[v][u];
- if (tmp < 0.0) {
- x = - ((int) (0.5 - tmp));
- } else {
- x = (int) (tmp + 0.5);
- }
- blk[v][u] = (DCTELEM) x;
- }
- }
- }
-
- /* Routine to initialise the cosine lookup table */
- void CIEEE1180Test::DCTInit()
- {
- int a,b;
- double tmp;
-
- for(a=0;a<8;a++)
- for(b=0;b<8;b++) {
- tmp = cos((double)((a+a+1)*b) * (3.14159265358979323846 / 16.0));
- if(b==0)
- tmp /= sqrt(2.0);
- coslu[a][b] = tmp * 0.5;
- }
-
- }
- /* Pseudo-random generator specified by IEEE 1180 */
- long CIEEE1180Test::IEEERand(long L, long H)
- {
- long i,j;
- double x;
-
- randx = (randx * 1103515245) + 12345;
- i = randx & 0x7ffffffe;
- x = ((double) i) / z;
- x *= (L+H+1);
- j = (long)x;
- return j-L;
- }
-
-
- bool CIEEE1180Test::Meets(double val, double limit)
- {
- return (fabs(val) <= limit);
- }
-