-
-
Notifications
You must be signed in to change notification settings - Fork 359
Added Cooley-Tukey in Common Lisp #786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Trashtalk217
merged 9 commits into
algorithm-archivists:master
from
0xJonas:cooley-tukey-lisp
Jan 1, 2021
Merged
Changes from 1 commit
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
91d5625
Added Cooley-Tukey in Lisp
0xJonas 7ada7da
Formatting and refactoring
0xJonas c72caaf
Update contents/cooley_tukey/code/clisp/fft.lisp
0xJonas 70822e9
Update contents/cooley_tukey/code/clisp/fft.lisp
0xJonas 9d0a5bb
Update contents/cooley_tukey/code/clisp/fft.lisp
0xJonas 2793edf
Update contents/cooley_tukey/code/clisp/fft.lisp
0xJonas 8426216
Update contents/cooley_tukey/code/clisp/fft.lisp
0xJonas e92bcb7
Update contents/cooley_tukey/code/clisp/fft.lisp
0xJonas e631b57
Updated line number
0xJonas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
|
||
(defun coefficient (time-index freq-index dft-len) | ||
"Calculates a single twiddle factor for the Fourier Transform." | ||
(exp (- (/ (* #c( 0 1) 2.0 pi time-index freq-index) | ||
dft-len)))) | ||
|
||
(defun dft (data) | ||
"Performs the Discrete Fourier Transform" | ||
(let ((dft-len (length data))) | ||
(loop for freq-index from 0 below dft-len collect | ||
(loop for time-index from 0 below dft-len sum | ||
(* (coefficient time-index freq-index dft-len) (elt data time-index)))))) | ||
|
||
(defun merge-sub-ffts (evens odds) | ||
"Combines the FFTs of the even and odd indices" | ||
0xJonas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(let* ((fft-length (+ (length evens) (length odds))) | ||
(indices (loop for i from 0 below (length odds) collect i)) | ||
(odd-terms (mapcar #'(lambda (v i) (* v (coefficient 1.0 i fft-length))) | ||
odds | ||
indices))) | ||
(concatenate 'list | ||
(mapcar #'+ evens odd-terms) | ||
(mapcar #'- evens odd-terms)))) | ||
|
||
(defun cooley-tukey-rec (data) | ||
"Performs the DFT using the recursive Cooley-Tukey method." | ||
(if (<= (length data) 1) | ||
Trashtalk217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
data | ||
(loop for i from 0 below (length data) | ||
if (evenp i) | ||
collect (elt data i) into evens | ||
else | ||
collect (elt data i) into odds | ||
finally | ||
(return (merge-sub-ffts (cooley-tukey-rec evens) | ||
(cooley-tukey-rec odds)))))) | ||
|
||
(defun reverse-bits (value num-bits) | ||
Trashtalk217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"Reverses the bits of a value" | ||
(if (= num-bits 1) | ||
value | ||
(let* ((num-low-bits (floor (/ num-bits 2))) | ||
(num-high-bits (- num-bits num-low-bits)) | ||
(bit-mask (- (expt 2 num-low-bits) 1)) | ||
(lower-half (logand value bit-mask)) | ||
(upper-half (ash value (- num-low-bits)))) | ||
(logior (ash (reverse-bits lower-half num-low-bits) num-high-bits) | ||
(reverse-bits upper-half num-high-bits))))) | ||
|
||
(defun bit-shuffle-indices (data) | ||
"Rearanges the elements in a list according to their bit-reversed indices." | ||
(loop | ||
with num-bits = (floor (log (length data) 2)) | ||
for i from 0 below (length data) | ||
collect (elt data (reverse-bits i num-bits)))) | ||
|
||
(defun butterfly (a b coeff) | ||
"Calculates a single butterfly." | ||
(values (+ a (* coeff b)) (- a (* coeff b)))) | ||
|
||
(defun butterfly-group (data start stride) | ||
"Calculates a single group of butterflies." | ||
(dotimes (i stride) | ||
(let* ((a-index (+ start i)) | ||
(b-index (+ start i stride)) | ||
(a (elt data a-index)) | ||
(b (elt data b-index)) | ||
(coeff (coefficient 1.0 i (* 2 stride)))) | ||
(multiple-value-bind (sum difference) (butterfly a b coeff) | ||
(setf (elt data a-index) sum) | ||
(setf (elt data b-index) difference))))) | ||
|
||
(defun cooley-tukey-tailrec (data stride) | ||
"Actual iterative implementation of the Cooley-Tukey method." | ||
Trashtalk217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(if (>= stride (length data)) | ||
data | ||
(progn | ||
(loop for i from 0 below (length data) by (* 2 stride) do | ||
(butterfly-group data i stride)) | ||
(cooley-tukey-tailrec data (* 2 stride))))) | ||
|
||
(defun cooley-tukey-iter (data) | ||
"Performs the DFT using the iterative Cooley-Tukey method." | ||
Trashtalk217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(cooley-tukey-tailrec (bit-shuffle-indices data) 1)) | ||
|
||
(defun approx-eql (list1 list2) | ||
(let ((diffs (mapcar #'(lambda (e1 e2) (abs (- e1 e2))) | ||
list1 | ||
list2))) | ||
(loop for d in diffs always (< d 1e-9)))) | ||
|
||
(defun test-fft (data) | ||
(let ((dft-result (dft data)) | ||
(rec-result (cooley-tukey-rec data)) | ||
(iter-result (cooley-tukey-iter data))) | ||
(format T "~&DFT and recursive Cooley-Tukey approx. equal: ~a" | ||
(approx-eql dft-result rec-result)) | ||
(format T "~&DFT and iterative Cooley-Tukey approx. equal: ~a" | ||
(approx-eql dft-result iter-result)) | ||
(format T "~&Recursive Cooley-Tukey and iterative Cooley-Tukey approx. equal: ~a" | ||
(approx-eql rec-result iter-result)))) | ||
|
||
(test-fft '(0.0 0.25 0.5 0.75 0.0 -0.25 -0.5 -0.75)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.