Generate a Simple FFT
This SPIRAL script will generate a simple FFT of size 4. You can copy and paste it into the SPIRAL window to see the results.
opts := SpiralDefaults;
transform := DFT(4);
ruletree := RandomRuleTree(transform, opts);
icode := CodeRuleTree(ruletree, opts);
PrintCode("DFT4", icode, opts);
Let’s walk through it line by line, sometimes using other commands to look deeper into what is happening.
Set the controlling options.
spiral> opts := SpiralDefaults;
<Spiral options record>
spiral>
Sets the opts
variable to the default set of options for SPIRAL. Later examples will set specific option values
to modify the default behavior.
Specify the transform.
spiral> transform := DFT(4);
DFT(4, 1)
spiral> pm(transform);
[ [ 1, 1, 1, 1 ],
[ 1, E(4), -1, -E(4) ],
[ 1, -1, 1, -1 ],
[ 1, -E(4), -1, E(4) ] ]
spiral>
DFT()
creates a transform object for a discrete fourier transform of specified size.pm()
– print matrix – is a handy utility to print the matrix representation of a transform.Generate a tree of breakdown rules.
spiral> ruletree := RandomRuleTree(transform, opts);
DFT_HW_CT( DFT(4, 1),
DFT_Base( DFT(2, 1) ),
DFT_Base( DFT(2, 1) ) )
spiral>
Builds the tree of smaller transforms that define the FFT.
RandomRuleTree()
randomly picks one of potentially very many valid rule trees.
Generate code.
spiral> icode := CodeRuleTree(ruletree, opts);
program(
chain(
func(TVoid, "init", [ ],
chain()
),
func(TVoid, "transform", [ Y, X ],
decl([ t57, t58, t59, t60, t61, t62, t63, t64 ],
chain(
assign(t57, add(deref(X), deref(add(X, V(4))))),
assign(t58, add(deref(add(X, V(1))), deref(add(X, V(5))))),
assign(t59, sub(deref(X), deref(add(X, V(4))))),
assign(t60, sub(deref(add(X, V(1))), deref(add(X, V(5))))),
assign(t61, add(deref(add(X, V(2))), deref(add(X, V(6))))),
assign(t62, add(deref(add(X, V(3))), deref(add(X, V(7))))),
assign(t63, sub(deref(add(X, V(2))), deref(add(X, V(6))))),
assign(t64, sub(deref(add(X, V(3))), deref(add(X, V(7))))),
assign(deref(Y), add(t57, t61)),
assign(deref(add(Y, V(1))), add(t58, t62)),
assign(deref(add(Y, V(4))), sub(t57, t61)),
assign(deref(add(Y, V(5))), sub(t58, t62)),
assign(deref(add(Y, V(2))), sub(t59, t64)),
assign(deref(add(Y, V(3))), add(t60, t63)),
assign(deref(add(Y, V(6))), add(t59, t64)),
assign(deref(add(Y, V(7))), sub(t60, t63))
)
)
)
)
)
spiral>
Creates the abstract code.
Produce the compileable C code.
spiral> PrintCode("DFT4", icode, opts);
/*
* This code was generated by Spiral 8.0.0, www.spiral.net
*/
#include <include/omega64.h>
void init_DFT4() {
}
void DFT4(double *Y, double *X) {
double t57, t58, t59, t60, t61, t62, t63, t64;
t57 = (*(X) + *((X + 4)));
t58 = (*((X + 1)) + *((X + 5)));
t59 = (*(X) - *((X + 4)));
t60 = (*((X + 1)) - *((X + 5)));
t61 = (*((X + 2)) + *((X + 6)));
t62 = (*((X + 3)) + *((X + 7)));
t63 = (*((X + 2)) - *((X + 6)));
t64 = (*((X + 3)) - *((X + 7)));
*(Y) = (t57 + t61);
*((Y + 1)) = (t58 + t62);
*((Y + 4)) = (t57 - t61);
*((Y + 5)) = (t58 - t62);
*((Y + 2)) = (t59 - t64);
*((Y + 3)) = (t60 + t63);
*((Y + 6)) = (t59 + t64);
*((Y + 7)) = (t60 - t63);
}
spiral>
PrintCode()
generates the C code.