home *** CD-ROM | disk | FTP | other *** search
- // IEEE1180Test.cpp: implementation of the CIEEE1180Test class.
- //
- //////////////////////////////////////////////////////////////////////
-
- #include <stdio.h>
- #include <malloc.h>
- #include <memory.h>
- #include <crtdbg.h>
- #include <math.h>
- #include "IEEE1180Test.h"
-
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
-
- CIEEE1180Test::CIEEE1180Test()
- {
-
- }
-
- 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
- */
- 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 );
- meet = meet && DoTest( -5, 5, 1, 10000, TestIdct );
- meet = meet && DoTest( -300, 300, 1, 10000, TestIdct );
-
- meet = meet && DoTest( -256, 255, 1, 10000, TestIdct );
- meet = meet && DoTest( -5, 5, 1, 10000, TestIdct );
- meet = meet && DoTest( -300, 300, 1, 10000, TestIdct );
-
- 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;
- DCTELEM block[DCTSIZE2]; /* random source data */
- DCTELEM refcoefs[DCTSIZE2]; /* coefs from reference FDCT */
- DCTELEM refout[DCTSIZE2]; /* output from reference IDCT */
- 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, "\n");
-
- /* print results */
- _RPT4(_CRT_WARN, "IEEE test conditions: -L = %ld, +H = %ld, sign = %ld, #iters = %ld\n",
- minpix, maxpix, sign, niters);
-
- _RPT0(_CRT_WARN, "Peak absolute values of errors:\n");
- for (i = 0, j = 0; i < DCTSIZE2; i++) {
- if (j < maxerr[i]) j = maxerr[i];
- _RPT1(_CRT_WARN, "%4d", maxerr[i]);
- if ((i%DCTSIZE) == DCTSIZE-1) _RPT0(_CRT_WARN, "\n");
- }
- _RPT2(_CRT_WARN, "Worst peak error = %d (%d spec limit 1)\n\n", j,
- meet = Meets((double) j, 1.0) && meet);
-
- _RPT0(_CRT_WARN, "Mean square errors:\n");
- 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;
- _RPT1(_CRT_WARN," %8.4f", err );
- if ((i%DCTSIZE) == DCTSIZE-1) _RPT0(_CRT_WARN, "\n");
- }
-
- _RPT2(_CRT_WARN, "Worst pmse = %.6f (%d spec limit 0.06)\n", max, meet = Meets(max, 0.06)&&meet);
- total /= (double) (64*niters);
-
- _RPT2(_CRT_WARN, "Overall mse = %.6f (%d spec limit 0.02)\n\n", total, meet = Meets(total, 0.02) && meet);
-
- _RPT0(_CRT_WARN, "Mean errors:\n");
- max = total = 0.0;
- for (i = 0; i < DCTSIZE2; i++) {
- double err = (double) sumerrs[i] / ((double) niters);
- total += (double) sumerrs[i];
- printf(" %8.4f", err);
- if (err < 0.0) err = -err;
- if (max < err) max = err;
- if ((i%DCTSIZE) == DCTSIZE-1) printf("\n");
- }
- _RPT2(_CRT_WARN, "Worst mean error = %.6f (%d spec limit 0.015)\n", max, meet = Meets(max, 0.015)&&meet);
- total /= (double) (64*niters);
- _RPT2(_CRT_WARN,"Overall mean error = %.6f (%d spec limit 0.0015)\n\n", total, meet= Meets(total, 0.0015)&&meet);
-
- /* 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]) {
- _RPT2(_CRT_WARN, "Position %d of IDCT(0) = %d (FAILS)\n", i, testout[i]);
- j++;
- }
- }
- _RPT1(_CRT_WARN, "%d elements of IDCT(0) were not zero\n\n\n", j);
- 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);
- }
-