home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
pctech
/
hlsrc.arc
/
HLFLOAT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-09-09
|
9KB
|
403 lines
/*+
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);
}