Fast Fourier transform: Difference between revisions

m
→‎{{header|REXX}}: added/changed comments and whitespace, changed indentations.
(→‎{{header|C}}: added apple platform library usage)
m (→‎{{header|REXX}}: added/changed comments and whitespace, changed indentations.)
Line 2,202:
<br>('''cos'''ine &nbsp; and &nbsp; reduce radians to a unit circle).
 
A normalization of radians function &nbsp' ('''r2r''') &nbsp; has been included here, as well as the constant &nbsp; '''pi'''.
 
This REXX program also adds zero values &nbsp; if &nbsp; the number of data points in the list doesn't exactly equal to a
<br>power of two. &nbsp; This is known as &nbsp; ''zero-padding''.
<lang rexx>/*REXX pgmprogram performs a fast Fourier transform (FFT) on a set of complex numbers. */
numeric digits length( pi() ) - 1 /*limited by the PI function result. */
arg data /*ARG verb uppercases the DATA from CL.*/
if data='' then data=1 1 1 1 0 /*Not specified? Then use the default.*/
size=words(data); pad=left('',6) /*PAD: for indenting and padding SAYs.*/
do p=0 until 2**p>=size ; end /*number of args exactly a power of 2? */
do j=size+1 to 2**p;data=data 0; end /*add zeroes to DATA 'til a power of 2.*/
size=words(data); ph=p%2; call hdr /*╔═════════════════════════════╗╔═══════════════════════════╗*/
/* [↓] TRANSLATE allows I & J*/ /*║ Numbers in data can be in ║*/
do j=0 for size /*║ seven formats: real ║*/
_=translate( word(data,j+1), 'J', "I") /*║ real,imag ║*/
parse var _ #.1.j '' $ 1 ' ",'" #.2.j /*║ ,imag ║*/
if $=='J' then parse var #.1.j #2.j ,"J" #.1.j /*║ nnnJ ║*/
"J" #.1.j /*║ nnnj ║*/
do m=1 for 2; #.m.j= word(#.m.j 0, 1) /*║ nnnI ║*/
end /*m*/ /*omitted part? [↑] ommited part?*/ /*║ nnni ║*/
/*╚═════════════════════════════╝╚═══════════════════════════╝*/
say pad "' FFT in "' center(j+1, 7) pad fmt(#.1.j) fmt(#.2.j,' "i'")
end /*j*/
say
tran=pi()*2 / 2**p; !.=0; hp=2**p %2; A=2**(p-ph); ptr=A; dbl=1
say
do p-ph; halfPtr=ptr%2
do i=halfPtr by ptr to A-halfPtr; _=i-halfPtr; !.i=!._+dbl
end /*i*/
dbl=dbl*2; ptr=halfPtr
end /*p-ph*/
 
do j=0 to 2**p%4; cmp.j=cos(j*tran); _=hp - j; cmp._= -cmp.j
_=hp + j; cmp._= -cmp.j
end /*j*/
B=2**ph
do i=0 end for A; / q=i *p*/ B
 
do i=0 for A; do j=0 for B; h=q+j; q _=!.j*B+!.i; * Bif _<=h then iterate
do j=0 for B; h=q+j; parse value _=! #.j*B+!1.i;_ if#.1.h #.2._<= #.2.h then iteratewith #.1.h #.1._ #.2.h #.2._
end /*j*/ /* [↑] swap two sets of values. */
parse value #.1._ #.1.h #.2._ #.2.h with #.1.h #.1._ #.2.h #.2._
end /*j*/ end /* [↑] swap two sets of values.i*/
dbl=1
end /*i*/
do p ; w=hp % dbl
 
dbl=1; do pk=0 for dbl ; Lb=w * k ; wLh=hpLb + 2**p % dbl4
do kj=0 for w for dbl ; Lb a=wj * kdbl * 2 + k ; b= ; Lh=Lba + 2**p % 4dbl
r=#.1.a; i=#.2.a ; do jc1=0 for wcmp.Lb * #.1.b ; ac4=j * dblcmp.Lb * #.2 + k ; .b= a + dbl
r=#.1.a; i=#.2.a ; c1 c2=cmp.LbLh * #.12.b ; c4c3=cmp.LbLh * #.21.b
#.1.a=r + c1 - c2 c2=cmp.Lh * ; #.2.b ; a=i + c3=cmp.Lh *+ #.1.bc4
#.1.ab=r +- c1 -+ c2 ; #.2.ab=i +- c3 +- c4
end #.1.b=r - c1 + c2 ; #.2.b=i - c3 - c4/*j*/
end end /*jk*/
end /*k*/dbl=dbl+dbl
end dbl=dbl+dbl /*p*/
end /*p*/
call hdr
do i=0 for size
say pad " FFT out " center(i+1,7) pad fmt(#.1.i) fmt(#.2.i,'j')
end /*i*/ /*numbers are shown with 10 digs /*[↑] #s are shown with 10 decimal digs*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*────────────────────────────────────────────────────────────────────────────*/
cos: procedure; parse arg x; q=r2r(x)**2; z=1; _=1; p=1 /*bare bones COS. */
do k=2 by 2; _=-_*q/(k*(k-1)); z=z+_; if z=p then leave; p=z; end; return z
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*────────────────────────────────────────────────────────────────────────────*/
fmt: procedure; parse arg y,j; y=y/1 /*transformsprettifies complex numbers for looksshow. */
if abs(y) < '1e-'digits()%4 then y=0; if y=0 & j\=='' then return ''
y=format(y, , 10); if pos(.,y)\==0 then y=strip(y, 'T', 0)
y=strip(y, , .); if y>=0 then y=' 'y; return left(y || j, 12)
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*────────────────────────────────────────────────────────────────────────────*/
hdr: _='───data─── num real─part imaginary─part'; say pad _
say pad translate(_, " "copies('═',256), " "xrange()); return
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*────────────────────────────────────────────────────────────────────────────*/
pi: return 3.1415926535897932384626433832795028841971693993751058209749445923078164062862
pi: return 3.141592653589793238462643383279502884197169399375105820974944592308
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*────────────────────────────────────────────────────────────────────────────*/
r2r: return arg(1) // ( pi()*2 ) /*reduce the radians to a unit circle. */</lang>
'''output''' &nbsp; when using the default input of: &nbsp; <tt> 1 &nbsp; 1 &nbsp; 1 &nbsp; 1 &nbsp; 0 </tt>
<pre>