home *** CD-ROM | disk | FTP | other *** search
- /*+
- Name: HLFLOAT.C
- Author: Kent J. Quirk
- (c) Copyright 1988 Ziff Communications Co.
- Date: April 1988
- Abstract: Performs a floating point benchmark by generating a
- waveform using Fourier synthesis, then running an FFT
- over the waveform to generate Fourier Components, and
- finally regenerating the waveform using the derived
- parameters.
- History: 09-Sep-88 kjq Version 1.00
- -*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <conio.h>
- #include <float.h>
- #include <math.h>
- #include <graph.h>
-
- #include "hl.h"
- #include "hltimes.h"
-
- extern int *colorlist;
-
- /* Macros for complex number manipulation */
- #define C_MULT(a,b) (a.x * (b.x + b.y) + a.y * (b.x + b.y))
- #define C_ADD(r,a,b) r.x = a.x + b.x; r.y = a.y + b.y
- #define C_SUB(r,a,b) r.x = a.x - b.x; r.y = a.y - b.y
- typedef struct complex COMPLEX;
-
- COMPLEX *data;
- #define PI2 6.283185
-
- /***** b i t r e v ****
- Given an integer and a number of bits, this reverses the bits
- in the integer. For example, the integer 5 (0101) reverses to
- the integer 10 (1010) with 4-bit numbers, but reverses to 160
- (10100000) with 8-bit numbers.
- This is useful in the FFT algorithm, since the values are processed
- by the "butterfly" algorithm.
- ***********************/
- unsigned int bitrev(in, nbits)
- unsigned int in;
- int nbits;
- {
- int out = 0;
- while (nbits--) /* for each bit on the input */
- {
- out <<= 1; /* make a place for an output bit */
- if (in & 1) /* if the low bit in input is set */
- out |= 1; /* set the output bit */
- in >>= 1; /* and rotate the input */
- }
- return(out);
- }
-
- /**** f f t ****
- Abstract: Performs an n-point complex FFT
- Parameters: COMPLEX array[] -- a pointer to an array of COMPLEX
- numbers containing the data to be transformed.
- int N -- the number of points to be processed
- int NU -- the number of bits in N (ex: N=1024 -> NU=10)
- Returns: Nothing, but array[] is changed to contain the FFT data.
- Comments: NU could easily be calculated from N.
- ****************************/
- void fft(array, N, NU)
- COMPLEX array[];
- int N;
- int NU;
- {
- int n2, i, l, k, NU1;
- double p, c, s;
- COMPLEX t;
-
- n2 = N/2;
- NU1 = NU - 1;
- k = 0;
- for (l=0; l<NU; l++)
- {
- while (k<N)
- {
- for (i=0; i<n2; i++)
- {
- p = (double)bitrev(k/(1 << NU1), NU);
- p = PI2 * p/(double)N;
- c = cos(p);
- s = sin(p);
- t.x = array[k+n2].x * c + array[k+n2].y * s;
- t.y = array[k+n2].y * c - array[k+n2].x * s;
- C_SUB(array[k+n2], array[k], t);
- C_ADD(array[k], array[k], t);
- k++;
- }
- k += n2;
- }
- k = 0;
- NU1--;
- n2 /= 2;
- }
-
- for (k=0; k<N; k++)
- {
- i = bitrev(k, NU);
- if (i > k)
- {
- t = array[k];
- array[k] = array[i];
- array[i] = t;
- }
- }
- }
-
- /**** l o g 2 ****
- Abstract: Given a number n, this calculates the integer log base 2 of n
- Parameters: An integer n.
- Returns: The integer log base 2 of n -- log2(1024) == 10
- ****************************/
- int log2(n)
- unsigned int n;
- {
- int i = 0;
- for (i = 0; n > 1; i++)
- n >>= 1;
- return(i);
- }
-
-
- /**** u s a g e ****
- Abstract: Prints usage info and exits
- Parameters: None
- Returns: Never
- ****************************/
- void usage()
- {
- printf("Usage: HLFLOAT [-nNBITS] [-q|-t|-m|-s] [-r] [-f] [-g] [-?]\n");
- printf(" where NBITS is the number of bits in the FFT\n");
- printf(" (example: 7 is 128 points, 9 is 512 points)\n");
- printf(" Other options choose data set: -q is squarewave,\n");
- printf(" -t is triangle, -s sinewave, -m mixture of two sines\n");
- printf(" -r toggles addition of random factor to the data\n");
- printf(" -h toggles hi-freq filter; filters everything above the\n");
- printf(" tenth harmonic before reconstructing the inverse FFT.\n");
- printf(" -b sets batch mode; no wait for user keypress.\n");
- printf(" Defaults: -n11, Squarewave waveform, -f and -r ON, -b OFF");
- printf(" -g prevents use of graphics mode.\n");
- printf(" Note: This could take a long time on a machine without");
- printf(" an 80x87 math coprocessor.");
- exit(1);
- }
-
- #define SQUAREWAVE 0
- #define TRIANGLEWAVE 1
- #define SINEWAVE 2
- #define LFSQUAREWAVE 3
-
-
- TIME_REC timerec[] = {
- { 0L, "Total: Floating Point" },
- { 0L, "Forward FFT, 2048 points" },
- { 0L, "Reverse FFT, 2048 points" },
- { 0L, "Total Time including graphics" },
- { -1L, "HLFLOAT" }
- };
-
- int main(argc, argv)
- int argc;
- char *argv[];
- {
- int nbits = 11; /* default to 2048-point run */
- int npts = 1 << nbits;
- int i;
- double d;
- double xsc, ysc;
- long ffttime;
- struct videoconfig config;
- int dataset = SQUAREWAVE;
- int random = 1, hf_filter = 1, batch = 0, bench = 0;
- int program = -1;
- int graphics = 1;
- char *filename = NULL;
-
- for (i=1; i<argc; i++)
- {
- if (argv[i][0] != '-')
- usage();
-
- switch(tolower(argv[i][1])) {
- case 'n':
- nbits = atoi(argv[i]+2);
- npts = 1 << nbits;
- break;
- case 'q':
- dataset = SQUAREWAVE;
- break;
- case 's':
- dataset = SINEWAVE;
- break;
- case 't':
- dataset = TRIANGLEWAVE;
- break;
- case 'm':
- dataset = LFSQUAREWAVE;
- break;
- case 'r':
- random = !random;
- break;
- case 'h':
- hf_filter = !hf_filter;
- break;
- case 'a':
- batch = 1;
- break;
- case 'b':
- bench = 1;
- break;
- case 'g':
- graphics = 0;
- break;
- case 'f':
- filename = argv[i]+2;
- break;
- case 'p':
- program = atoi(argv[i]+2);
- break;
- default:
- case '?':
- usage();
- break;
- }
- }
-
- if (argc == 1)
- random = hf_filter = 1; /* if no args, use specials */
-
- if ((data = malloc(sizeof(COMPLEX) * (npts+1))) == NULL)
- {
- printf("Unable to allocate space for %d points!\n", npts);
- exit(1);
- }
-
- d = PI2/npts;
- if (graphics)
- {
- if (!init_video((struct videoconfig far *)&config))
- {
- printf("Unable to use graphics.\n");
- graphics = 0;
- }
- }
- else
- printf("Not using graphics.\n");
-
- if (graphics)
- {
- ysc = (double)config.numypixels / -3.0; /* invert the axes */
- xsc = (double)config.numxpixels / (double)npts;
- if (xsc < 2.0)
- {
- i = 1 << log2(config.numxpixels);
- xsc = (double)i / (double)npts;
- }
-
- _setcolor(colorlist[15]); /* force white */
- _moveto(0,0);
- _lineto(0,config.numypixels);
- _setlogorg(0, config.numypixels/2);
- _moveto(0,0);
- _lineto(config.numxpixels, 0);
-
- _settextcolor(colorlist[15]);
- _outtext("Data...");
- }
- else
- printf("Data...");
-
- start_timer(0);
- for (i=0; i<npts; i++)
- {
- switch (dataset) {
- case SQUAREWAVE:
- data[i].x = (i > npts/2) ? -1.0 : 1.0;
- break;
- case SINEWAVE:
- data[i].x = sin((double)i * d);
- break;
- case TRIANGLEWAVE:
- data[i].x = 1.0 - 2.0 * modf(2*(double)i/(double)npts, &d);
- break;
- case LFSQUAREWAVE:
- data[i].x = sin((double)i * d) + sin(11.0*i * d)/3.0;
- break;
- }
- data[i].y = 0.0;
- if (random)
- data[i].x += (double)rand()/200000.0;
-
- }
-
- if (graphics)
- {
- _setcolor(colorlist[2]);
- _moveto(0, (int)(ysc*data[0].x));
- for (d=1.0; d<(float)npts; d += 1.0)
- _lineto((int)(xsc*d), (int)(ysc*data[(int)d].x));
-
- _settextcolor(colorlist[2]);
- _outtext("FFT...");
- }
- else
- printf("FFT...");
-
- start_timer(1);
- fft(data, npts, nbits); /* convert it */
- stop_timer();
- ffttime = timerec[1].ticks = get_timer(1);
-
- if (graphics)
- {
- if (hf_filter)
- {
- _settextcolor(colorlist[3]);
- _outtext("filtered...");
- }
-
- for (i=0; i<=npts/2; i++)
- {
- d = cabs(data[i]);
- if (hf_filter && ((i > 10) || (i == 0)))
- {
- _setcolor(colorlist[2]);
- data[i].x = data[i].y = 0.0; /* HF, DC Filter */
- data[npts-i].x = data[npts-i].y = 0.0; /* on both ends */
- }
- else
- _setcolor(colorlist[3]);
-
- _moveto((int)(xsc*i), (int)(2.0*ysc*d/npts)); /* make bigger */
- _lineto((int)(xsc*i), 0);
- _moveto((int)(xsc*(npts-i)), (int)(2.0*ysc*d/npts));
- _lineto((int)(xsc*(npts-i)), 0);
- }
-
- _settextcolor(colorlist[4]);
- _outtext("Reverse...");
- }
- else
- printf("Reverse...");
-
- start_timer(1);
- fft(data, npts, nbits); /* and convert it back */
- stop_timer();
- ffttime += timerec[2].ticks = get_timer(1);
-
- if (graphics)
- {
- _setcolor(colorlist[4]);
- _moveto(0, (int)(ysc*data[0].x/npts));
- for (i=1; i<npts; i++)
- _lineto((int)(xsc*i), (int)(ysc*data[i].x/-npts));
-
- stop_timer();
- _settextcolor(colorlist[15]);
- _outtext("Done.\nTest complete -- press any key...");
- if (!batch)
- getch();
- _setvideomode(_DEFAULTMODE);
- }
- else
- {
- stop_timer();
- printf("Done.\n");
- }
-
- timerec[3].ticks = get_timer(0);
- timerec[0].ticks = timerec[1].ticks + timerec[2].ticks;
-
- sprintf(timerec[1].desc, "Forward FFT, %d Points", npts);
- sprintf(timerec[2].desc, "Reverse FFT, %d Points", npts);
-
- if ((!bench) && (!batch))
- {
- printf("FFT: %d points\n", npts);
- for (i=0; timerec[i].ticks != -1; i++)
- printf("%s secs: %s\n", time_secs(timerec[i].ticks),
- timerec[i].desc);
- }
-
- if ((filename != NULL) && (program != -1))
- {
- opentime(filename);
- for (i=0; ; i++)
- {
- savetime(program, i, &timerec[i]);
- if (timerec[i].ticks == -1)
- break;
- }
- closetime();
- }
-
- return(0);
- }
-