home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / fft < prev    next >
Text File  |  1989-03-12  |  25KB  |  1,047 lines

  1. Subject:  v18i020:  General Fast Foufier Transform package
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Peter Valkenburg <cs.vu.nl!valke>
  7. Posting-number: Volume 18, Issue 20
  8. Archive-name: fft
  9.  
  10. The packages included below perform fast fourier transformations on an
  11. arbitrary number of real or complex samples.  It uses a generalized version
  12. of the well-known Cooley-Tukey algorithm, meaning that it will also work
  13. for a number of samples that is not a power of 2.
  14.  
  15. Since I didn't bother to squeeze out the very last machine cycle, you are
  16. not advised to use this in real-time applications.  However, the recursive
  17. algorithm used is very neat.
  18.  
  19. Enjoy.
  20.  
  21.             Peter Valkenburg (valke@cs.vu.nl).
  22. --------------------------------------------------------------------------------
  23. WARNING:  This package shows serious deficiencies if used in SDI-systems or
  24. AEGIS-alikes.  So all of you defense-people: HANDS-OFF!
  25. --------------------------------------------------------------------------------
  26.  
  27. ----------cut here--------------------------------------------------------------
  28. #!/bin/sh
  29. : This is a shar archive.  Extract with sh, not csh.
  30. : This archive ends with exit, so do not worry about trailing junk.
  31. : --------------------------- cut here --------------------------
  32. PATH=/bin:/usr/bin:/usr/ucb
  33. if test -f 'fft'
  34. then    echo Removing   'fft'
  35.     rm 'fft'
  36. fi
  37. if test -d 'fft'
  38. then    :
  39. else    echo Creating   'fft'
  40.     mkdir 'fft'
  41. fi
  42. chmod 'u=rwx,g=rx,o=rx' 'fft'
  43. echo Extracting 'fft/README'
  44. sed 's/^X//' > 'fft/README' << '+ END-OF-FILE ''fft/README'
  45. XThis directory contains the packages realfft(3) and fft(3) that do Cooley-Tukey
  46. Xfast Fourier transform on an arbitrary number of real or complex samples,
  47. Xrespectively.
  48. X
  49. XThe package was tested on 4.[12] bsd & Sun Release 3.5, but it should work on
  50. Xany UNIX system featuring sin(3M) and malloc(3).
  51. X
  52. XContents:
  53. X    complex.h    - include file (for users of fft(3) routines).
  54. X    fft        - manual and source of fft(3).
  55. X    realfft        - manual and source of realfft(3).
  56. X    example        - example of how to use realfft(3).
  57. X
  58. XSee the README's in fft/, realfft/ and example/ to find out how to compile and
  59. Xuse things.
  60. + END-OF-FILE fft/README
  61. chmod 'u=rw,g=r,o=r' 'fft/README'
  62. set `wc -c 'fft/README'`
  63. count=$1
  64. case $count in
  65. 585)    :;;
  66. *)    echo 'Bad character count in ''fft/README' >&2
  67.         echo 'Count should be 585' >&2
  68. esac
  69. if test -f 'fft/complex'
  70. then    echo Removing   'fft/complex'
  71.     rm 'fft/complex'
  72. fi
  73. if test -d 'fft/complex'
  74. then    :
  75. else    echo Creating   'fft/complex'
  76.     mkdir 'fft/complex'
  77. fi
  78. chmod 'u=rwx,g=rx,o=rx' 'fft/complex'
  79. echo Extracting 'fft/complex/Makefile'
  80. sed 's/^X//' > 'fft/complex/Makefile' << '+ END-OF-FILE ''fft/complex/Makefile'
  81. XLTYPE=A18
  82. XTARGET=fft.a
  83. XCFLAGS=-O
  84. XPREFLAGS=
  85. XIDIRS=-I../
  86. XLLIBS=
  87. X
  88. XLINT=lint -uhbaxpc
  89. XCTAGS=ctags
  90. XPRINT=@pr -t
  91. X
  92. XCFILES=\
  93. X    fourier.c\
  94. X    ft.c\
  95. X    w.c
  96. XHFILES=\
  97. X    /usr/include/math.h\
  98. X    ../complex.h\
  99. X    w.h
  100. XOBJECTS=\
  101. X    fourier.o\
  102. X    ft.o\
  103. X    w.o
  104. X
  105. X.SUFFIXES: .i
  106. X
  107. X$(TARGET):    $(OBJECTS)
  108. X    ar rv $@ $?
  109. X    ranlib $@
  110. X
  111. Xlint:
  112. X    $(LINT) $(PREFLAGS) $(IDIRS) $(CFILES) $(LLIBS) -lc
  113. X
  114. Xtags:    $(HFILES) $(CFILES)
  115. X    $(CTAGS) $(HFILES) $(CFILES)
  116. X
  117. Xprint:    fft.man
  118. X    $(PRINT) fft.man tech complex.h w.h $(CFILES)
  119. X
  120. Xfft.man:    fft.3
  121. X    @nroff -man fft.3 > fft.man
  122. X
  123. X.c.o:
  124. X    $(CC) $(CFLAGS) -c $(IDIRS) $<
  125. X
  126. X.c.i:
  127. X    $(CC) $(CFLAGS) -P $(IDIRS) $<
  128. X
  129. X.c.s:
  130. X    $(CC) $(CFLAGS) -S $(IDIRS) $<
  131. X
  132. Xfourier.o:\
  133. X    ../complex.h\
  134. X    w.h
  135. X
  136. Xft.o:\
  137. X    ../complex.h\
  138. X    w.h
  139. X
  140. Xw.o:\
  141. X    ../complex.h\
  142. X    w.h\
  143. X    /usr/include/math.h\
  144. + END-OF-FILE fft/complex/Makefile
  145. chmod 'u=rw,g=r,o=r' 'fft/complex/Makefile'
  146. set `wc -c 'fft/complex/Makefile'`
  147. count=$1
  148. case $count in
  149. 741)    :;;
  150. *)    echo 'Bad character count in ''fft/complex/Makefile' >&2
  151.         echo 'Count should be 741' >&2
  152. esac
  153. echo Extracting 'fft/complex/README'
  154. sed 's/^X//' > 'fft/complex/README' << '+ END-OF-FILE ''fft/complex/README'
  155. XThis fft(3) package does Cooley-Tukey fast Fourier transform on an arbitrary
  156. Xnumber of complex samples.
  157. X
  158. XHow to make the stuff:
  159. X    make        - create library "fft.a"
  160. X    make fft.man    - nroff manual page "fft.3" into "fft.man"
  161. X    make print    - print source, "tech" and "fft.man"
  162. X
  163. XFile "tech" contains a short description of the functions and variables in the
  164. Ximplementation.
  165. X
  166. XPrograms using fft(3), should include "../complex.h" and be loaded (ld(1)) with
  167. Xlibraries "fft.a" and "/usr/lib/libm.a".  The package also uses malloc(3) of
  168. Xthe standard C-library.
  169. + END-OF-FILE fft/complex/README
  170. chmod 'u=rw,g=r,o=r' 'fft/complex/README'
  171. set `wc -c 'fft/complex/README'`
  172. count=$1
  173. case $count in
  174. 544)    :;;
  175. *)    echo 'Bad character count in ''fft/complex/README' >&2
  176.         echo 'Count should be 544' >&2
  177. esac
  178. echo Extracting 'fft/complex/fft.3'
  179. sed 's/^X//' > 'fft/complex/fft.3' << '+ END-OF-FILE ''fft/complex/fft.3'
  180. X.TH FFT 3
  181. X.SH NAME
  182. Xfft, rft \- forward and reverse complex fourier transform
  183. X.SH SYNOPSIS
  184. X.nf
  185. X#include "complex.h"
  186. X
  187. Xfft (in, n, out)
  188. XCOMPLEX *in;
  189. Xunsigned n;
  190. XCOMPLEX *out;
  191. X
  192. Xrft (in, n, out)
  193. XCOMPLEX *in;
  194. Xunsigned n;
  195. XCOMPLEX *out;
  196. X
  197. Xc_re (c)
  198. XCOMPLEX c;
  199. X
  200. Xc_im (c)
  201. XCOMPLEX c;
  202. X.fi
  203. X.SH DESCRIPTION
  204. X.I
  205. XFft
  206. Xand
  207. X.I rft
  208. Xperform, respectively, forward and reverse discrete
  209. Xfast fourier transform on the
  210. X.I n
  211. X(an arbitrary number) complex
  212. Xsamples of array
  213. X.IR in .
  214. XThe result is placed in
  215. X.IR out .
  216. X.br
  217. XThe functions are a recursive implementation of the Cooley-Tukey algorithm.
  218. XBoth use O
  219. X.RI ( n
  220. X*
  221. X.RI ( p1
  222. X+ .. +
  223. X.IR pk ))
  224. Xoperations, where
  225. X.I pi
  226. Xis the
  227. X.IR i -th
  228. Xfactor in the
  229. Xprime-decomposition of size
  230. X.I k
  231. Xof
  232. X.IR n .
  233. X.br
  234. XBoth functions compute a sine/cosine table internally.
  235. XThis table is not recomputed on successive calls with the same
  236. X.IR n .
  237. X
  238. X.I C_re
  239. Xand
  240. X.I c_im
  241. Xare C preprocessor defines that yield the real and imaginary
  242. Xparts of
  243. X.IR c ,
  244. Xrespectively.
  245. XThey are used to assign and inspect arrays
  246. X.I in
  247. Xand
  248. X.IR out .
  249. X.SH FILES
  250. Xfft.a \- library containing fft and rft.
  251. X.br
  252. X/usr/lib/libm.a \- library used by fft.a.
  253. X.SH DIAGNOSTICS
  254. X.I Fft
  255. Xand
  256. X.I rft
  257. Xreturn -1 if allocating space for the internal table fails, else 0.
  258. X.SH BUGS
  259. XThe original contents of
  260. X.I in
  261. Xare destroyed.
  262. X
  263. XThe transform isn't optimized for interesting special cases of
  264. X.IR n ,
  265. Xe.g.\&
  266. X.I n
  267. Xis a power of 2, although it will work in O
  268. X.RI ( n
  269. X* 2log
  270. X.RI ( n )).
  271. X
  272. XThe error for a forward-reverse sequence is about 10e-13 for
  273. X.I n
  274. X= 1024.
  275. X.SH AUTHOR
  276. XPeter Valkenburg (valke@cs.vu.nl).
  277. + END-OF-FILE fft/complex/fft.3
  278. chmod 'u=rw,g=r,o=r' 'fft/complex/fft.3'
  279. set `wc -c 'fft/complex/fft.3'`
  280. count=$1
  281. case $count in
  282. 1548)    :;;
  283. *)    echo 'Bad character count in ''fft/complex/fft.3' >&2
  284.         echo 'Count should be 1548' >&2
  285. esac
  286. echo Extracting 'fft/complex/fourier.c'
  287. sed 's/^X//' > 'fft/complex/fourier.c' << '+ END-OF-FILE ''fft/complex/fourier.c'
  288. X/*
  289. X * "fourier.c", Pjotr '87.
  290. X */
  291. X
  292. X#include    <complex.h>
  293. X#include    "w.h"
  294. X
  295. X/*
  296. X * Recursive (reverse) complex fast Fourier transform on the n
  297. X * complex samples of array in, with the Cooley-Tukey method.
  298. X * The result is placed in out.  The number of samples, n, is arbitrary.
  299. X * The algorithm costs O (n * (r1 + .. + rk)), where k is the number
  300. X * of factors in the prime-decomposition of n (also the maximum
  301. X * depth of the recursion), and ri is the i-th primefactor.
  302. X */
  303. XFourier (in, n, out)
  304. XCOMPLEX *in;
  305. Xunsigned n;
  306. XCOMPLEX *out;
  307. X{
  308. X    unsigned r;
  309. X    unsigned radix ();
  310. X
  311. X    if ((r = radix (n)) < n)
  312. X        split (in, r, n / r, out);
  313. X    join (in, n / r, n, out);
  314. X}
  315. X
  316. X/*
  317. X * Give smallest possible radix for n samples.
  318. X * Determines (in a rude way) the smallest primefactor of n.
  319. X */
  320. Xstatic unsigned radix (n)
  321. Xunsigned n;
  322. X{
  323. X    unsigned r;
  324. X
  325. X    if (n < 2)
  326. X        return 1;
  327. X
  328. X    for (r = 2; r < n; r++)
  329. X        if (n % r == 0)
  330. X            break;
  331. X    return r;
  332. X}
  333. X
  334. X/*
  335. X * Split array in of r * m samples in r parts of each m samples,
  336. X * such that in [i] goes to out [(i % r) * m + (i / r)].
  337. X * Then call for each part of out Fourier, so the r recursively
  338. X * transformed parts will go back to in.
  339. X */
  340. Xstatic split (in, r, m, out)
  341. XCOMPLEX *in;
  342. Xregister unsigned r, m;
  343. XCOMPLEX *out;
  344. X{
  345. X    register unsigned k, s, i, j;
  346. X
  347. X    for (k = 0, j = 0; k < r; k++)
  348. X        for (s = 0, i = k; s < m; s++, i += r, j++)
  349. X            out [j] = in [i];
  350. X
  351. X    for (k = 0; k < r; k++, out += m, in += m)
  352. X        Fourier (out, m, in);
  353. X}
  354. X
  355. X/*
  356. X * Sum the n / m parts of each m samples of in to n samples in out.
  357. X *            r - 1
  358. X * Out [j] becomes  sum  in [j % m] * W (j * k).  Here in is the k-th
  359. X *            k = 0   k           n         k
  360. X * part of in (indices k * m ... (k + 1) * m - 1), and r is the radix.
  361. X * For k = 0, a complex multiplication with W (0) is avoided.
  362. X */
  363. Xstatic join (in, m, n, out)
  364. XCOMPLEX *in;
  365. Xregister unsigned m, n;
  366. XCOMPLEX *out;
  367. X{
  368. X    register unsigned i, j, jk, s;
  369. X
  370. X    for (s = 0; s < m; s++)
  371. X        for (j = s; j < n; j += m) {
  372. X            out [j] = in [s];
  373. X            for (i = s + m, jk = j; i < n; i += m, jk += j)
  374. X                c_add_mul (out [j], in [i], W (n, jk));
  375. X        }
  376. X}
  377. + END-OF-FILE fft/complex/fourier.c
  378. chmod 'u=rw,g=r,o=r' 'fft/complex/fourier.c'
  379. set `wc -c 'fft/complex/fourier.c'`
  380. count=$1
  381. case $count in
  382. 2046)    :;;
  383. *)    echo 'Bad character count in ''fft/complex/fourier.c' >&2
  384.         echo 'Count should be 2046' >&2
  385. esac
  386. echo Extracting 'fft/complex/ft.c'
  387. sed 's/^X//' > 'fft/complex/ft.c' << '+ END-OF-FILE ''fft/complex/ft.c'
  388. X/*
  389. X * "ft.c", Pjotr '87.
  390. X */
  391. X
  392. X#include    <complex.h>
  393. X#include    "w.h"
  394. X
  395. X/*
  396. X * Forward Fast Fourier Transform on the n samples of complex array in.
  397. X * The result is placed in out.  The number of samples, n, is arbitrary.
  398. X * The W-factors are calculated in advance.
  399. X */
  400. Xint fft (in, n, out)
  401. XCOMPLEX *in;
  402. Xunsigned n;
  403. XCOMPLEX *out;
  404. X{
  405. X    unsigned i;
  406. X
  407. X    for (i = 0; i < n; i++)
  408. X        c_conj (in [i]);
  409. X    
  410. X    if (W_init (n) == -1)
  411. X        return -1;
  412. X
  413. X    Fourier (in, n, out);
  414. X
  415. X    for (i = 0; i < n; i++) {
  416. X        c_conj (out [i]);
  417. X        c_realdiv (out [i], n);
  418. X    }
  419. X
  420. X    return 0;
  421. X}
  422. X
  423. X/*
  424. X * Reverse Fast Fourier Transform on the n complex samples of array in.
  425. X * The result is placed in out.  The number of samples, n, is arbitrary.
  426. X * The W-factors are calculated in advance.
  427. X */
  428. Xrft (in, n, out)
  429. XCOMPLEX *in;
  430. Xunsigned n;
  431. XCOMPLEX *out;
  432. X{
  433. X    if (W_init (n) == -1)
  434. X        return -1;
  435. X
  436. X    Fourier (in, n, out);
  437. X
  438. X    return 0;
  439. X}
  440. + END-OF-FILE fft/complex/ft.c
  441. chmod 'u=rw,g=r,o=r' 'fft/complex/ft.c'
  442. set `wc -c 'fft/complex/ft.c'`
  443. count=$1
  444. case $count in
  445. 865)    :;;
  446. *)    echo 'Bad character count in ''fft/complex/ft.c' >&2
  447.         echo 'Count should be 865' >&2
  448. esac
  449. echo Extracting 'fft/complex/tech'
  450. sed 's/^X//' > 'fft/complex/tech' << '+ END-OF-FILE ''fft/complex/tech'
  451. X    Short technical description of functions in the fft(3) package
  452. X
  453. X
  454. X"ft.c"
  455. XThe entry-points:
  456. X    fft    - Forward Complex Fast Fourier Transform
  457. X    rft    - Reverse Complex Fast Fourier Transform
  458. X
  459. X"fourier.c"
  460. XRecursive implementation of the Cooley-Tukey algorithm:
  461. X    Fourier    - top level call
  462. X    radix    - determine radix for a number of samples
  463. X    split    - split samples in groups, and recursively call Fourier
  464. X    join    - join (add) groups of samples into a new group
  465. X
  466. X"complex.h"
  467. XManipulation of complex numbers:
  468. X    COMPLEX    - type for complex numbers
  469. X    c_re    - real part of complex number
  470. X    c_im    - imaginary part of complex number
  471. X    c_add_mul - multiply and add complex numbers
  472. X    c_conj    - convert a complex number into its conjugate
  473. X    c_realdiv - divide a complex by a real number
  474. X
  475. X"w.h"
  476. XW-factors:
  477. X    W    - give previously calculated W-factor
  478. X
  479. X"w.c"
  480. XComputation of W-factors:
  481. X    W_factors - array of W-factors
  482. X    Nfactors - number of factors in W_factors
  483. X    W_init    - prepare W-factors array
  484. + END-OF-FILE fft/complex/tech
  485. chmod 'u=rw,g=r,o=r' 'fft/complex/tech'
  486. set `wc -c 'fft/complex/tech'`
  487. count=$1
  488. case $count in
  489. 951)    :;;
  490. *)    echo 'Bad character count in ''fft/complex/tech' >&2
  491.         echo 'Count should be 951' >&2
  492. esac
  493. echo Extracting 'fft/complex/w.c'
  494. sed 's/^X//' > 'fft/complex/w.c' << '+ END-OF-FILE ''fft/complex/w.c'
  495. X/*
  496. X * "w.c", Pjotr '87.
  497. X */
  498. X
  499. X#include    <complex.h>
  500. X#include    "w.h"
  501. X#include    <math.h>
  502. X
  503. XCOMPLEX *W_factors = 0;        /* array of W-factors */
  504. Xunsigned Nfactors = 0;        /* number of entries in W-factors */
  505. X
  506. X/*
  507. X * W_init puts Wn ^ k (= e ^ (2pi * i * k / n)) in W_factors [k], 0 <= k < n.
  508. X * If n is equal to Nfactors then nothing is done, so the same W_factors
  509. X * array can used for several transforms of the same number of samples.
  510. X * Notice the explicit calculation of sines and cosines, an iterative approach
  511. X * introduces substantial errors.
  512. X */
  513. Xint W_init (n)
  514. Xunsigned n;
  515. X{
  516. X    char *malloc ();
  517. X#    define pi    3.1415926535897932384626434
  518. X    unsigned k;
  519. X
  520. X    if (n == Nfactors)
  521. X        return 0;
  522. X    if (Nfactors != 0 && W_factors != 0)
  523. X        free ((char *) W_factors);
  524. X    if ((Nfactors = n) == 0)
  525. X        return 0;
  526. X    if ((W_factors = (COMPLEX *) malloc (n * sizeof (COMPLEX))) == 0)
  527. X        return -1;
  528. X
  529. X    for (k = 0; k < n; k++) {
  530. X        c_re (W_factors [k]) = cos (2 * pi * k / n);
  531. X        c_im (W_factors [k]) = sin (2 * pi * k / n);
  532. X    }
  533. X
  534. X    return 0;
  535. X}
  536. + END-OF-FILE fft/complex/w.c
  537. chmod 'u=rw,g=r,o=r' 'fft/complex/w.c'
  538. set `wc -c 'fft/complex/w.c'`
  539. count=$1
  540. case $count in
  541. 996)    :;;
  542. *)    echo 'Bad character count in ''fft/complex/w.c' >&2
  543.         echo 'Count should be 996' >&2
  544. esac
  545. echo Extracting 'fft/complex/w.h'
  546. sed 's/^X//' > 'fft/complex/w.h' << '+ END-OF-FILE ''fft/complex/w.h'
  547. X/*
  548. X * "w.h", Pjotr '87.
  549. X */
  550. X
  551. Xextern COMPLEX *W_factors;
  552. Xextern unsigned Nfactors;
  553. X
  554. X/*
  555. X * W gives the (already computed) Wn ^ k (= e ^ (2pi * i * k / n)).
  556. X * Notice that the powerseries of Wn has period Nfactors.
  557. X */
  558. X#define    W(n, k)        (W_factors [((k) * (Nfactors / (n))) % Nfactors])
  559. + END-OF-FILE fft/complex/w.h
  560. chmod 'u=rw,g=r,o=r' 'fft/complex/w.h'
  561. set `wc -c 'fft/complex/w.h'`
  562. count=$1
  563. case $count in
  564. 283)    :;;
  565. *)    echo 'Bad character count in ''fft/complex/w.h' >&2
  566.         echo 'Count should be 283' >&2
  567. esac
  568. echo Extracting 'fft/complex.h'
  569. sed 's/^X//' > 'fft/complex.h' << '+ END-OF-FILE ''fft/complex.h'
  570. X/*
  571. X * "complex.h", Pjotr '87.
  572. X */
  573. X
  574. Xtypedef struct {
  575. X        double re, im;
  576. X    } COMPLEX;
  577. X#define        c_re(c)        ((c).re)
  578. X#define        c_im(c)        ((c).im)
  579. X
  580. X/*
  581. X * C_add_mul adds product of c1 and c2 to c.
  582. X */
  583. X#define    c_add_mul(c, c1, c2)    { COMPLEX C1, C2; C1 = (c1); C2 = (c2); \
  584. X                  c_re (c) += C1.re * C2.re - C1.im * C2.im; \
  585. X                  c_im (c) += C1.re * C2.im + C1.im * C2.re; }
  586. X
  587. X/*
  588. X * C_conj substitutes c by its complex conjugate.
  589. X */
  590. X#define c_conj(c)        { c_im (c) = -c_im (c); }
  591. X
  592. X/*
  593. X * C_realdiv divides complex c by real.
  594. X */
  595. X#define    c_realdiv(c, real)    { c_re (c) /= (real); c_im (c) /= (real); }
  596. + END-OF-FILE fft/complex.h
  597. chmod 'u=rw,g=r,o=r' 'fft/complex.h'
  598. set `wc -c 'fft/complex.h'`
  599. count=$1
  600. case $count in
  601. 583)    :;;
  602. *)    echo 'Bad character count in ''fft/complex.h' >&2
  603.         echo 'Count should be 583' >&2
  604. esac
  605. if test -f 'fft/example'
  606. then    echo Removing   'fft/example'
  607.     rm 'fft/example'
  608. fi
  609. if test -d 'fft/example'
  610. then    :
  611. else    echo Creating   'fft/example'
  612.     mkdir 'fft/example'
  613. fi
  614. chmod 'u=rwx,g=rx,o=rx' 'fft/example'
  615. echo Extracting 'fft/example/README'
  616. sed 's/^X//' > 'fft/example/README' << '+ END-OF-FILE ''fft/example/README'
  617. XAn example of realfft(3) usage is in example.c.  It contains two fourier
  618. Xtransforms on real data.
  619. X
  620. XCompile with:
  621. X    cc example.c ../real/realfft.a ../complex/fft.a -lm
  622. + END-OF-FILE fft/example/README
  623. chmod 'u=rw,g=r,o=r' 'fft/example/README'
  624. set `wc -c 'fft/example/README'`
  625. count=$1
  626. case $count in
  627. 166)    :;;
  628. *)    echo 'Bad character count in ''fft/example/README' >&2
  629.         echo 'Count should be 166' >&2
  630. esac
  631. echo Extracting 'fft/example/example.c'
  632. sed 's/^X//' > 'fft/example/example.c' << '+ END-OF-FILE ''fft/example/example.c'
  633. X/*
  634. X * Test for realfft(3).
  635. X */
  636. X
  637. X#define        N    8
  638. X#define     pi    3.1415926535897932384626434
  639. X
  640. Xdouble sin (), cos ();
  641. Xchar *malloc ();
  642. X
  643. Xmain ()
  644. X{
  645. X    unsigned i, j;
  646. X
  647. X    double in [N], out [N];
  648. X
  649. X    printf ("Example #1:\n");
  650. X    for (i = 0; i < N; i++)
  651. X        in [i] = i;
  652. X    printsamp (in, N);
  653. X
  654. X    realfft (in, N, out);
  655. X    printf ("After a fast fft\n");
  656. X    printampl (out, N);
  657. X
  658. X    /* check */
  659. X    printf ("A reverse slow ft gives:\n");
  660. X    srft (out, N, in);
  661. X    printsamp (in, N);
  662. X
  663. X    printf ("And the reverse fast ft yields:\n");
  664. X    realrft (out, N, in);
  665. X    printsamp (in, N);
  666. X
  667. X    printf ("\n\nExample #2\n");
  668. X    for (i = 0; i < N; i++) {
  669. X        in [i] = 0;
  670. X        for (j = 0; j <= N / 2; j++)
  671. X            in [i] += cos (2 * pi * i * j / N) +
  672. X                  sin (2 * pi * i * j / N);
  673. X    }
  674. X    printsamp (in, N);
  675. X
  676. X    realfft (in, N, out);
  677. X    printf ("After a forward fast ft:\n");
  678. X    printampl (out, N);
  679. X
  680. X    /* check */
  681. X    printf ("A reverse slow ft yields:\n");
  682. X    srft (out, N, in);
  683. X    printsamp (in, N);
  684. X
  685. X    printf ("And a reverse fast ft gives:\n");
  686. X    realrft (out, N, in);
  687. X    printsamp (in, N);
  688. X}
  689. X
  690. Xprintampl (ampl, n)
  691. Xdouble *ampl;
  692. Xunsigned n;
  693. X{
  694. X    unsigned i;
  695. X
  696. X    printf ("Amplitudes\n");
  697. X
  698. X    if (n == 0)
  699. X        return;
  700. X
  701. X    printf ("%f (dc)\n", ampl [0]);
  702. X    for (i = 1; i < (n + 1) / 2; i++)
  703. X        printf ("%f, %f (%u-th harmonic)\n", ampl [2 * i - 1],
  704. X                             ampl [2 * i], i);
  705. X    if (n % 2 == 0)
  706. X        printf ("%f (Nyquist)\n", ampl [n - 1]);
  707. X
  708. X    printf ("\n");
  709. X}
  710. X
  711. Xprintsamp (samp, n)
  712. Xdouble *samp;
  713. Xunsigned n;
  714. X{
  715. X    unsigned i;
  716. X    printf ("Samples\n");
  717. X
  718. X    for (i = 0; i < n; i++)
  719. X        printf ("%f\n", samp [i]);
  720. X    
  721. X    printf ("\n");
  722. X}
  723. X
  724. X/*
  725. X * Slow reverse fourier transform.  In [0] contains dc, in [n - 1] Nyquist.
  726. X * This is just a gimmick to compare with realfft(3).
  727. X */
  728. Xsrft (in, n, out)
  729. Xdouble *in;
  730. Xunsigned n;
  731. Xdouble *out;
  732. X{
  733. X    unsigned i, j;
  734. X
  735. X    for (i = 0; i < n; i++) {
  736. X        out [i] = in [0];            /* dc */
  737. X        for (j = 1; j < (n + 1) / 2; j++)    /* j-th harmonic */
  738. X            out [i] += in [2 * j - 1] * cos (2 * pi * i * j / n) +
  739. X                   in [2 * j] * sin (2 * pi * i * j / n);
  740. X        if (n % 2 == 0)                /* Nyquist */
  741. X            out [i] += in [n - 1] * cos (2 * pi * i * j / n);
  742. X    }
  743. X}
  744. + END-OF-FILE fft/example/example.c
  745. chmod 'u=rw,g=r,o=r' 'fft/example/example.c'
  746. set `wc -c 'fft/example/example.c'`
  747. count=$1
  748. case $count in
  749. 2026)    :;;
  750. *)    echo 'Bad character count in ''fft/example/example.c' >&2
  751.         echo 'Count should be 2026' >&2
  752. esac
  753. if test -f 'fft/real'
  754. then    echo Removing   'fft/real'
  755.     rm 'fft/real'
  756. fi
  757. if test -d 'fft/real'
  758. then    :
  759. else    echo Creating   'fft/real'
  760.     mkdir 'fft/real'
  761. fi
  762. chmod 'u=rwx,g=rx,o=rx' 'fft/real'
  763. echo Extracting 'fft/real/Makefile'
  764. sed 's/^X//' > 'fft/real/Makefile' << '+ END-OF-FILE ''fft/real/Makefile'
  765. XLTYPE=A18
  766. XTARGET=realfft.a
  767. XCFLAGS=-O
  768. XPREFLAGS=
  769. XIDIRS=-I../
  770. XLLIBS=
  771. X
  772. XLINT=lint -uhbaxc
  773. XCTAGS=ctags
  774. XPRINT=@pr -t
  775. X
  776. XCFILES=\
  777. X    realfft.c
  778. XHFILES=\
  779. X    ../complex.h
  780. XOBJECTS=\
  781. X    realfft.o
  782. X
  783. X.SUFFIXES: .i
  784. X
  785. X$(TARGET):    $(OBJECTS)
  786. X    ar rv $@ $?
  787. X    ranlib $@
  788. X
  789. Xlint:
  790. X    $(LINT) $(PREFLAGS) $(IDIRS) $(CFILES) $(LLIBS) -lc
  791. X
  792. Xtags:    $(HFILES) $(CFILES)
  793. X    $(CTAGS) $(HFILES) $(CFILES)
  794. X
  795. Xprint:    realfft.man
  796. X    $(PRINT) realfft.man $(CFILES)
  797. X
  798. Xrealfft.man:    realfft.3
  799. X    @nroff -man realfft.3 > realfft.man
  800. X
  801. X.c.o:
  802. X    $(CC) $(CFLAGS) -c $(IDIRS) $<
  803. X
  804. X.c.i:
  805. X    $(CC) $(CFLAGS) -P $(IDIRS) $<
  806. X
  807. X.c.s:
  808. X    $(CC) $(CFLAGS) -S $(IDIRS) $<
  809. X
  810. Xrealfft.o:\
  811. X    ../complex.h
  812. + END-OF-FILE fft/real/Makefile
  813. chmod 'u=rw,g=r,o=r' 'fft/real/Makefile'
  814. set `wc -c 'fft/real/Makefile'`
  815. count=$1
  816. case $count in
  817. 611)    :;;
  818. *)    echo 'Bad character count in ''fft/real/Makefile' >&2
  819.         echo 'Count should be 611' >&2
  820. esac
  821. echo Extracting 'fft/real/README'
  822. sed 's/^X//' > 'fft/real/README' << '+ END-OF-FILE ''fft/real/README'
  823. XThis realfft(3) package does Cooley-Tukey fast Fourier transform on an arbitrary
  824. Xnumber of real samples.  It uses fft(3) for the actual complex transform.
  825. X
  826. XHow to make the stuff:
  827. X    make        - create library "realfft.a"
  828. X    make fft.man    - nroff manual page "realfft.3" into "realfft.man"
  829. X    make print    - print source and "realfft.man"
  830. X
  831. XPrograms using realfft(3), should be loaded (ld(1)) with libraries "realfft.a",
  832. X"../complex/fft.a" and "/usr/lib/libm.a".  The package also uses malloc(3) of
  833. Xthe standard C-library.
  834. + END-OF-FILE fft/real/README
  835. chmod 'u=rw,g=r,o=r' 'fft/real/README'
  836. set `wc -c 'fft/real/README'`
  837. count=$1
  838. case $count in
  839. 508)    :;;
  840. *)    echo 'Bad character count in ''fft/real/README' >&2
  841.         echo 'Count should be 508' >&2
  842. esac
  843. echo Extracting 'fft/real/realfft.3'
  844. sed 's/^X//' > 'fft/real/realfft.3' << '+ END-OF-FILE ''fft/real/realfft.3'
  845. X.TH REALFFT 3
  846. X.SH NAME
  847. Xrealfft, realrft \- forward and reverse real fourier transform
  848. X.SH SYNOPSIS
  849. X.nf
  850. Xrealfft (in, n, out)
  851. Xdouble *in;
  852. Xunsigned n;
  853. Xdouble *out;
  854. X
  855. Xrealrft (in, n, out)
  856. Xdouble *in;
  857. Xunsigned n;
  858. Xdouble *out;
  859. X.fi
  860. X.SH DESCRIPTION
  861. X.I Realfft
  862. Xand
  863. X.I realrft
  864. Xperform, respectively, forward and reverse discrete
  865. Xfast fourier transform on the
  866. X.I n
  867. X(an arbitrary number) reals
  868. Xof array
  869. X.IR in .
  870. XThe result (also
  871. X.I n
  872. Xreals) is placed in array
  873. X.IR out .
  874. XThe original contents of
  875. X.I in
  876. Xare not disturbed.
  877. X
  878. XThe format of the
  879. X.I out
  880. Xarray of
  881. X.I realfft
  882. Xand the
  883. X.I in
  884. Xarray of
  885. X.I realrft
  886. Xis as follows:
  887. XThe cosine component of the dc frequency is under index 0
  888. Xand the
  889. X.IR i -th
  890. Xharmonic's cosine and sine are under, respectively, index
  891. X2 *
  892. X.I i
  893. X- 1 and 2 *
  894. X.IR i .
  895. XIf
  896. X.I n
  897. Xis even then the cosine component of the
  898. XNyquist frequency is under index
  899. X.I n
  900. X- 1.
  901. XNote that the dc and Nyquist sine components need not be passed, since they
  902. Xare always 0.
  903. X
  904. XThe actual transform is done by
  905. X.IR fft (3)
  906. Xin complex space.
  907. X.SH "SEE ALSO"
  908. Xfft(3)
  909. X.SH FILES
  910. Xrealfft.a \- contains realfft and realrft.
  911. X.br
  912. Xfft.a \- library used by realfft.a.
  913. X.br
  914. X/usr/lib/libm.a \- library used by fft.a.
  915. X.SH DIAGNOSTICS
  916. X.I Realfft
  917. Xand
  918. X.I realrft
  919. Xreturn -1 if routines in
  920. X.IR fft (3)
  921. Xfail, else 0.
  922. X.SH BUGS
  923. XThe error for a forward-reverse sequence is about 1e-13 for
  924. X.I n
  925. X= 1024.
  926. X.SH AUTHOR
  927. XPeter Valkenburg (valke@cs.vu.nl)
  928. + END-OF-FILE fft/real/realfft.3
  929. chmod 'u=rw,g=r,o=r' 'fft/real/realfft.3'
  930. set `wc -c 'fft/real/realfft.3'`
  931. count=$1
  932. case $count in
  933. 1391)    :;;
  934. *)    echo 'Bad character count in ''fft/real/realfft.3' >&2
  935.         echo 'Count should be 1391' >&2
  936. esac
  937. echo Extracting 'fft/real/realfft.c'
  938. sed 's/^X//' > 'fft/real/realfft.c' << '+ END-OF-FILE ''fft/real/realfft.c'
  939. X/*
  940. X * "realfft.c", Pjotr '87
  941. X */
  942. X
  943. X/*
  944. X * Bevat funkties realfft en realrft die resp. forward en reverse fast fourier
  945. X * transform op reele samples doen.  Gebruikt pakket fft(3).
  946. X */
  947. X
  948. X#include    <complex.h>
  949. X
  950. Xchar *malloc ();
  951. X
  952. X/*
  953. X * Reele forward fast fourier transform van n samples van in naar
  954. X * amplitudes van out.
  955. X * De cosinus komponent van de dc komt in out [0], dan volgen in
  956. X * out [2 * i - 1] en out [2 * i] steeds resp. de cosinus en sinus
  957. X * komponenten van de i-de harmonische.  Bij een even aantal samples
  958. X * bevat out [n - 1] de cosinus komponent van de Nyquist frequentie. 
  959. X * Extraatje: Na afloop is in onaangetast.
  960. X */
  961. Xrealfft (in, n, out)
  962. Xdouble *in;
  963. Xunsigned n;
  964. Xdouble *out;
  965. X{
  966. X    COMPLEX *c_in, *c_out;
  967. X    unsigned i;
  968. X
  969. X    if (n == 0 ||
  970. X        (c_in = (COMPLEX *) malloc (n * sizeof (COMPLEX))) == 0 ||
  971. X        (c_out = (COMPLEX *) malloc (n * sizeof (COMPLEX))) == 0)
  972. X        return;
  973. X    
  974. X    for (i = 0; i < n; i++) {
  975. X        c_re (c_in [i]) = in [i];
  976. X        c_im (c_in [i]) = 0;
  977. X    }
  978. X
  979. X    fft (c_in, n, c_out);
  980. X
  981. X    out [0] = c_re (c_out [0]);        /* cos van dc */
  982. X    for (i = 1; i < (n + 1) / 2; i++) {    /* cos/sin i-de harmonische */
  983. X        out [2 * i - 1] = c_re (c_out [i]) * 2;
  984. X        out [2 * i] = c_im (c_out [i]) * -2;
  985. X    }
  986. X    if (n % 2 == 0)                /* cos van Nyquist */
  987. X        out [n - 1] = c_re (c_out [n / 2]);
  988. X
  989. X    free ((char *) c_in);
  990. X    free ((char *) c_out);
  991. X}
  992. X
  993. X/*
  994. X * Reele reverse fast fourier transform van amplitudes van in naar
  995. X * n samples van out.
  996. X * De cosinus komponent van de dc staat in in [0], dan volgen in
  997. X * in [2 * i - 1] en in [2 * i] steeds resp. de cosinus en sinus
  998. X * komponenten van de i-de harmonische.  Bij een even aantal samples
  999. X * bevat in [n - 1] de cosinus komponent van de Nyquist frequentie. 
  1000. X * Extraatje: Na afloop is in onaangetast.
  1001. X */
  1002. Xrealrft (in, n, out)
  1003. Xdouble *in;
  1004. Xunsigned n;
  1005. Xdouble *out;
  1006. X{
  1007. X    COMPLEX *c_in, *c_out;
  1008. X    unsigned i;
  1009. X
  1010. X    if (n == 0 ||
  1011. X        (c_in = (COMPLEX *) malloc (n * sizeof (COMPLEX))) == 0 ||
  1012. X        (c_out = (COMPLEX *) malloc (n * sizeof (COMPLEX))) == 0)
  1013. X        return;
  1014. X    
  1015. X    c_re (c_in [0]) = in [0];        /* dc */
  1016. X    c_im (c_in [0]) = 0;
  1017. X    for (i = 1; i < (n + 1) / 2; i++) {    /* geconj. symm. harmonischen */
  1018. X        c_re (c_in [i]) = in [2 * i - 1] / 2;
  1019. X        c_im (c_in [i]) = in [2 * i] / -2;
  1020. X        c_re (c_in [n - i]) = in [2 * i - 1] / 2;
  1021. X        c_im (c_in [n - i]) = in [2 * i] / 2;
  1022. X    }
  1023. X    if (n % 2 == 0) {            /* Nyquist */
  1024. X        c_re (c_in [n / 2]) = in [n - 1];
  1025. X        c_im (c_in [n / 2]) = 0;
  1026. X    }
  1027. X
  1028. X    rft (c_in, n, c_out);
  1029. X
  1030. X    for (i = 0; i < n; i++)
  1031. X        out [i] = c_re (c_out [i]);
  1032. X
  1033. X    free ((char *) c_in);
  1034. X    free ((char *) c_out);
  1035. X}
  1036. + END-OF-FILE fft/real/realfft.c
  1037. chmod 'u=rw,g=r,o=r' 'fft/real/realfft.c'
  1038. set `wc -c 'fft/real/realfft.c'`
  1039. count=$1
  1040. case $count in
  1041. 2503)    :;;
  1042. *)    echo 'Bad character count in ''fft/real/realfft.c' >&2
  1043.         echo 'Count should be 2503' >&2
  1044. esac
  1045. exit 0
  1046.  
  1047.