gentests.c

来自「realview22.rar」· C语言 代码 · 共 330 行

C
330
字号
/*
 * $Copyright: 
 * ----------------------------------------------------------------
 * This confidential and proprietary software may be used only as
 * authorised by a licensing agreement from ARM Limited
 *   (C) COPYRIGHT 2000,2002 ARM Limited
 *       ALL RIGHTS RESERVED
 * The entire notice above must be reproduced on all authorised
 * copies and copies may only be made to the extent permitted
 * by a licensing agreement from ARM Limited.
 * ----------------------------------------------------------------
 * File:     gentests.c,v
 * Revision: 1.9
 * ----------------------------------------------------------------
 * $
 *
 * Create the test vectors required for the FFT
 * Ideally compile this file natively (eg using 'cl' or 'gcc')
 *  as it takes a long time to generate the tables
 *
 */

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "testfft.h"

#define MAXTESTS 50
tFFTTest LFFTTests[MAXTESTS];
static int nLFFTTests=0;

void generate_test(FILE *fp, int N, int type, int flags);
void parabola(tFFTTest *FFTTest, comp s, comp b, comp c);
void sinewave(tFFTTest *FFTTest, comp s, int k1, int k2);
void normalise(tFFTTest *FFTTest);
void output(FILE *fp, comp *in, int N, int nTest, char *name);
void output_tests(FILE *fp, int N);

int main(int argc, char **argv) {
  int N;
  char path[256];
  FILE *fp;
  
  /* set defaults */
  N=1024;

  /* read command line arguments */
  if (--argc>0) {
    N = atoi(*(++argv)); 
  } else {
    printf("Please enter the FFT size to test:\n");
    scanf("%d", &N);
    if (N==0) N=2048;
  }
  printf("FFT size to test = %d\n", N);
  
  /* formulate filename */
  sprintf(path, "t%06d.c", N);
        
  printf("Output file = %s\n", path);
  fp = fopen(path, "wt");
  if (fp == NULL) {
    printf ("Couldn't open file %s for output.\n", path);
    exit (1);
  }
        
  fprintf(fp, "/*\n");
  fprintf(fp, " * Copyright (C) ARM Limited 1998-2002. All rights reserved.\n");
  fprintf(fp, " *\n");
  fprintf(fp, " * t%06d.c\n", N);
  fprintf(fp, " *\n");
  fprintf(fp, " * Tests for FFT's of size N=%d\n", N);
  fprintf(fp, " */\n");
  fprintf(fp, "\n");
  fprintf(fp, "#include \"testfft.h\"\n\n");
  
  /* generate real parabola and sinewave test patterns */
  generate_test(fp, N, 0, FFT_real);
  generate_test(fp, N, 1, FFT_real);
  
  /* generate complex parabola and sinewave test patterns */
  generate_test(fp, N, 0, 0);
  generate_test(fp, N, 1, 0);

  output_tests(fp, N);
  printf ("Tests created\n");
  return 0;
}

/* N = number of points in FFT to test (need not be a power of 2)
 * type = the type of shape to test
 *        0 => parabola input shape (accuracy test)
 *        1 => sinwave input shape (maximum abs value test)
 * flags = direction and type
 *        FFT_real
 *        FFT_inverse => test FFT in the inverse direction
 * The range of the test input is scaled to absolute value of 1
 * on each scalar.
 */

void generate_test(FILE *fp, int N, int type, int flags) {
  tFFTTest *FFTTest;
  int nTest;
  comp s;
  
  assert(nLFFTTests<MAXTESTS);
  nTest = nLFFTTests++;
  FFTTest = &LFFTTests[nTest];
  
  printf("Creating test N=%d type=%d flags=%d\n", N, type, flags);
  
  FFTTest->N = N;
  FFTTest->flags = flags;
  FFTTest->in  = (comp*)malloc(N*sizeof(comp));
  FFTTest->out = (comp*)malloc(N*sizeof(comp));
  
  assert(FFTTest->in);
  assert(FFTTest->out);
  
  s.x = 1.0;
  s.y = 0.3;
  if (flags & FFT_real) s.y=0;
  
  if (type==0) {
    /* parabola */
    comp b, c;
    
    FFTTest->name="parabola-complex";
    b.x = (real)N*(real)4/(real)3;
    b.y = b.x * 0.3;
    c.x = (real)N*(real)4/(real)9;
    c.y = c.x * 0.7;
    if (flags & FFT_real) {
      FFTTest->name="parabola-real";
      b.y=0;
      c.y=0;
    }
    parabola(FFTTest, s, b, c);
  }
  
  if (type==1) {
    /* sinewave */
    if (flags & FFT_real) {
      FFTTest->name="sinewave-real";
      sinewave(FFTTest, s, 3, 3);
    } else {
      FFTTest->name="sinewave-complex";
      sinewave(FFTTest, s, 3, N-3);
    }
  }
  
  normalise(FFTTest);
  output(fp, FFTTest->in, N, nTest, "in");
  output(fp, FFTTest->out, N, nTest, "out");
  free(FFTTest->in);
  free(FFTTest->out);
}

/* Take the FFT of the parabola:
 *
 * x[k] = s*(k*k + b*k + c)
 *
 * if x[k]=1 then X=FFT(x) has
 *  X[0] = N
 *  X[k] = 0 (k!=0)
 *
 * if x[k]=k then X=FFT(x) has
 *  X[0] = N*(N-1)/2
 *  X[k] = N/(w^k-1) (k!=0)
 *
 * if x[k]=k*k then X=FFT(x) has
 *  X[0] = N*(N-1)*(2N-1)/6
 *  X[k] = N/(w^k-1) * (N-2-2/(w^k-1)) (k!=0)
 *
 * if x[k]= s*(k*k + b*k + c) then X=FFT(x) has
 *  X[k] = (-s*N/2) 2/(1-w^k) * (N-2+b + 2/(1-w^k))
 *
 */

void parabola(tFFTTest *FFTTest, comp s, comp b, comp c) {
  real x,y,n1,n2,t;
  int k;
  int N=FFTTest->N;
  comp *in =FFTTest->in;
  comp *out=FFTTest->out;
  
  /* t = - 2*pi/N */
  t = -(real)8*atan(1.0)/(real)N;
  
  /* write the input parabola */
  for (k=0; k<N; k++) {
    x = k*k + b.x*k + c.x;
    y = 0   + b.y*k + c.y;
    in[k].x = x*s.x - y*s.y;
    in[k].y = x*s.y + y*s.x;
  }
  
  /* write the output transformed data
   * NB if w = cos(t) + i*sin(t)  then
   * 2/(1-w^k) = 1 + i*[sin(kt)/(1-cos(kt))]
   */
  
  n1 = (real)(N-1)/(real)2;
  n2 = (real)(2*N-1)/(real)3;
  x = ((n2 + b.x)*n1 + c.x)*(real)N;
  y = (( 0 + b.y)*n1 + c.y)*(real)N;
  out[0].x = x*s.x - y*s.y;
  out[0].y = x*s.y + y*s.x;
  
  for (k=1; k<N; k++) {
    real x1,y1,wi;
    real ang = (real)k*t;
    
    wi = sin(ang)/((real)1-cos(ang));
    x1 = (real)(N-1) + b.x;
    y1 = b.y + wi;
    x = x1 - y1*wi;
    y = y1 + x1*wi;
    wi = (-(real)(N/2));
    out[k].x = wi*(x*s.x - y*s.y);
    out[k].y = wi*(x*s.y + y*s.x);
  }
}

/* Take FFT of the sinewave:
 *
 * x[k] = s*(exp(i*k*k1*t) + exp(-i*k*k2*t))
 *
 * where t=2*pi/N is the angle to FFT by. Then,
 *
 * X[k] = s * N * ( (k==k1) + (k==N-k2) )
 */

void sinewave(tFFTTest *FFTTest, comp s, int k1, int k2) {
  real x,y,t;
  int k;
  int N=FFTTest->N;
  comp *in =FFTTest->in;
  comp *out=FFTTest->out;
  
  /* t = 2*pi/N */
  t = (real)8*atan(1.0)/(real)N;
  
  /* range k1 and k2 bins */
  while (k1<0) k1+=N;
  while (k1>=N) k1-=N;
  while (k2<=0) k2+=N;
  while (k2>N) k2-=N;
  
  /* write the input sinewave */
  for (k=0; k<N; k++) {
    real ang = k*t;
    
    x = cos(ang*k1) + cos(ang*k2);
    y = sin(ang*k1) - sin(ang*k2);
    in[k].x = x*s.x - y*s.y;
    in[k].y = x*s.y + y*s.x;
  }
  
  /* write the output transformed data */
  for (k=0; k<N; k++) {
    out[k].x = 0;
    out[k].y = 0;
  }
  out[k1].x += s.x*N;
  out[k1].y += s.y*N;
  out[N-k2].x += s.x*N;
  out[N-k2].y += s.y*N;
}

/* Normalise the input to the range -1...+1 */

void normalise(tFFTTest *FFTTest) {
  real max=0;
  real *in  = (real *)FFTTest->in;
  real *out = (real *)FFTTest->out;
  int N = 2*FFTTest->N;
  int i;
  
  for (i=0; i<N; i++) {
    real r=in[i];
    if (r<0) r=-r;
    if (r>max) max=r;
  }
  max = 1/max;
  for (i=0; i<N; i++) {
    in[i] *= max;
    out[i] *= max;
  }
}

/* output the FFTTest arrays to the C file */

void output(FILE *fp, comp *in, int N, int nTest, char *name) {
  int k;
  
  fprintf(fp, "static const comp ffttest_%d_%d_%s[%d] = {\n",
    N, nTest, name, N
  );
  for (k=0; k<N-1; k++) {
    fprintf(fp, "  { %.18lf, %.18lf },\n", in[k].x, in[k].y);
  }
  fprintf(fp, "  { %.18lf, %.18lf }\n};\n\n", in[k].x, in[k].y);
}

/* write the test structure */

void output_tests(FILE *fp, int N) {
  int i;
  
  fprintf(fp, "static const tFFTTest FFTTest_%d[%d]={\n", N, nLFFTTests);
  for (i=0; i<nLFFTTests; ) {
    tFFTTest *FFTTest = &LFFTTests[i];

    fprintf(fp, "  { %d, \"%s\", (comp*)ffttest_%d_%d_in, "
      "(comp*)ffttest_%d_%d_out, %d }",
      FFTTest->N, FFTTest->name, N, i, N, i, FFTTest->flags);
    i++;
    if (i<nLFFTTests) fprintf(fp, ",");
    fprintf(fp, "\n");
  }
  fprintf(fp, "};\n\n");
  fprintf(fp, "extern const tFFTTests FFTTests_%d;\n", N);
  fprintf(fp, "const tFFTTests FFTTests_%d = {\n", N);
  fprintf(fp, " %d, %d, (tFFTTest*)FFTTest_%d\n", nLFFTTests, N, N);
  fprintf(fp, "};\n");
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?