#lang racket
(require "math.rkt"
racket/unsafe/ops
"unsafe-ops-utils.rkt")
(define fft-forward -1.0)
(define fft-backward +1.0)
(define (fft-bitreverse-order data)
(let ((n (unsafe-vector-length data)))
(for/fold ((j 0))
((i (in-range (unsafe-fx- n 1))))
(let ((k (unsafe-fxquotient n 2)))
(when (unsafe-fx< i j)
(let ((tmp (unsafe-vector-ref data i)))
(unsafe-vector-set! data i (unsafe-vector-ref data j))
(unsafe-vector-set! data j tmp)))
(let loop ()
(when (unsafe-fx<= k j)
(set! j (unsafe-fx- j k))
(set! k (unsafe-fxquotient k 2))
(loop)))
(unsafe-fx+ j k)))
(void)))
(define (fft-binary-logn n)
(with-fixed (n)
(let ((binary-logn
(let loop ((k 1)
(l 0))
(if (unsafe-fx>= k n)
l
(loop (unsafe-fx* k 2) (unsafe-fx+ l 1))))))
(if (unsafe-fx= n (unsafe-fxlshift 1 binary-logn))
binary-logn
#f))))
(define (fft-complex-radix2-forward data)
(fft-complex-radix2-transform data fft-forward))
(define (fft-complex-radix2-backward data)
(fft-complex-radix2-transform data fft-backward))
(define (fft-complex-radix2-inverse data)
(fft-complex-radix2-backward data)
(let* ((n (unsafe-vector-length data))
(norm (unsafe-fl/ 1.0 (unsafe-fx->fl n))))
(for ((i (in-range n)))
(let* ((datum (unsafe-vector-ref data i))
(datum-real (real-part datum))
(datum-imag (imag-part datum)))
(unsafe-vector-set!
data i
(make-rectangular
(unsafe-fl* norm datum-real)
(unsafe-fl* norm datum-imag)))))))
(define (fft-complex-radix2-transform data sign)
(with-float (sign)
(let* ((n (vector-length data))
(logn (fft-binary-logn n)))
(unless logn
(error 'fft-complex-radix2-transform
"vector length (~a) is not a power of 2"
n))
(unless (unsafe-fx= n 1)
(fft-bitreverse-order data)
(for/fold ((dual 1))
((bit (in-range logn)))
(let* ((w-real 1.0)
(w-imag 0.0)
(theta (unsafe-fl/
(unsafe-fl* sign 2*pi)
(unsafe-fl* 2.0 (unsafe-fx->fl dual))))
(s (unsafe-flsin theta))
(t (unsafe-flsin (unsafe-fl/ theta 2.0)))
(s2 (unsafe-fl* 2.0 (unsafe-fl* t t))))
(for ((b (in-range 0 n (unsafe-fx* 2 dual))))
(let* ((i b)
(j (unsafe-fx+ b dual))
(wd (unsafe-vector-ref data j)))
(unsafe-vector-set!
data j (- (unsafe-vector-ref data i) wd))
(unsafe-vector-set!
data i (+ (unsafe-vector-ref data i) wd))))
(for ((a (in-range 1 dual)))
(let ((tmp-real
(unsafe-fl-
(unsafe-fl- w-real (unsafe-fl* s w-imag))
(unsafe-fl* s2 w-real)))
(tmp-imag
(unsafe-fl-
(unsafe-fl+ w-imag (unsafe-fl* s w-real))
(unsafe-fl* s2 w-imag))))
(set! w-real tmp-real)
(set! w-imag tmp-imag))
(for ((b (in-range 0 n (unsafe-fx* 2 dual))))
(let* ((i (unsafe-fx+ b a))
(j (unsafe-fx+ (unsafe-fx+ b a) dual))
(z1 (unsafe-vector-ref data j))
(z1-real (real-part z1))
(z1-imag (imag-part z1)))
(with-float (z1-real z1-imag)
(let ((wd (make-rectangular
(unsafe-fl-
(unsafe-fl* w-real z1-real)
(unsafe-fl* w-imag z1-imag))
(unsafe-fl+
(unsafe-fl* w-real z1-imag)
(unsafe-fl* w-imag z1-real)))))
(unsafe-vector-set!
data j (- (unsafe-vector-ref data i) wd))
(unsafe-vector-set!
data i (+ (unsafe-vector-ref data i) wd)))))))
(unsafe-fx* dual 2))))
(void))))
(define (fft-complex-radix2-dif-forward data)
(fft-complex-radix2-dif-transform data fft-forward))
(define (fft-complex-radix2-dif-backward data)
(fft-complex-radix2-dif-transform data fft-backward))
(define (fft-complex-radix2-dif-inverse data)
(fft-complex-radix2-dif-backward data)
(let* ((n (unsafe-vector-length data))
(norm (unsafe-fl/ 1.0 (unsafe-fx->fl n))))
(for ((i (in-range n)))
(let* ((datum (unsafe-vector-ref data i))
(datum-real (real-part datum))
(datum-imag (imag-part datum)))
(unsafe-vector-set!
data i
(make-rectangular
(unsafe-fl* norm datum-real)
(unsafe-fl* norm datum-imag)))))))
(define (fft-complex-radix2-dif-transform data sign)
(with-float (sign)
(let* ((n (vector-length data))
(logn (fft-binary-logn n)))
(unless logn
(error 'fft-complex-radix2-transform
"vector length (~a) is not a power of 2"
n))
(unless (unsafe-fx= n 1)
(for/fold ((dual (unsafe-fxquotient n 2)))
((bit (in-range logn)))
(let* ((w-real 1.0)
(w-imag 0.0)
(theta (unsafe-fl/
(unsafe-fl* sign 2*pi)
(unsafe-fl* 2.0 (unsafe-fx->fl dual))))
(s (unsafe-flsin theta))
(t (unsafe-flsin (unsafe-fl/ theta 2.0)))
(s2 (unsafe-fl* 2.0 (unsafe-fl* t t))))
(for ((b (in-range dual)))
(for ((a (in-range 0 n (unsafe-fx* 2 dual))))
(let* ((i (unsafe-fx+ b a))
(j (unsafe-fx+ (unsafe-fx+ b a) dual))
(t1 (+ (unsafe-vector-ref data i)
(unsafe-vector-ref data j)))
(t2 (- (unsafe-vector-ref data i)
(unsafe-vector-ref data j)))
(t2-real (real-part t2))
(t2-imag (imag-part t2)))
(with-float (t2-real t2-imag)
(unsafe-vector-set!
data i t1)
(unsafe-vector-set!
data j
(make-rectangular
(unsafe-fl-
(unsafe-fl* w-real t2-real)
(unsafe-fl* w-imag t2-imag))
(unsafe-fl+
(unsafe-fl* w-real t2-imag)
(unsafe-fl* w-imag t2-real)))))))
(let ((tmp-real
(unsafe-fl-
(unsafe-fl- w-real (unsafe-fl* s w-imag))
(unsafe-fl* s2 w-real)))
(tmp-imag
(unsafe-fl-
(unsafe-fl+ w-imag (unsafe-fl* s w-real))
(unsafe-fl* s2 w-imag))))
(set! w-real tmp-real)
(set! w-imag tmp-imag)))
(unsafe-fxquotient dual 2)))
(fft-bitreverse-order data))
(void))))
(define (fft-complex-factorize n)
(fft-factorize n '(7 6 5 4 3 2)))
(define (fft-factorize n implemented-subtransforms)
(with-fixed (n)
(if (unsafe-fx= n 1)
'(1)
(let ((ntest n)
(factors '()))
(let outer-loop ()
(unless (or (null? implemented-subtransforms)
(unsafe-fx= ntest 0))
(let ((factor (car implemented-subtransforms)))
(let inner-loop ()
(when (unsafe-fx= (unsafe-fxmodulo ntest factor) 0)
(set! factors (append factors (list factor)))
(set! ntest (unsafe-fxquotient ntest factor))
(inner-loop)))
(set! implemented-subtransforms
(cdr implemented-subtransforms)))
(outer-loop)))
(let ((factor 2))
(let loop ()
(when (and (not (unsafe-fx= ntest 1))
(unsafe-fx= (unsafe-fxmodulo ntest factor) 0))
(set! factors (append factors (list factor)))
(set! ntest (unsafe-fxquotient ntest factor))
(loop))))
(let ((factor 3))
(let outer-loop ()
(unless (unsafe-fx= ntest 1)
(let inner-loop ()
(unless (unsafe-fx= (unsafe-fxmodulo ntest factor) 0)
(set! factor (unsafe-fx+ factor 2))
(inner-loop)))
(set! factors (append factors (list factor)))
(set! ntest (unsafe-fxquotient ntest factor))
(outer-loop))))
factors))))
(struct fft-complex-wavetable
(n
nf
factors
twiddle
trig))
(define fft-complex-wavetable-hash (make-hasheq))
(define (get-fft-complex-wavetable n)
(with-fixed (n)
(hash-ref! fft-complex-wavetable-hash n
(make-fft-complex-wavetable n))))
(define (make-fft-complex-wavetable n)
(let* ((factors (fft-complex-factorize n))
(nf (length factors))
(twiddle (make-vector nf))
(trig (make-vector n)))
(let ((d-theta (unsafe-fl/ (unsafe-fl- 0.0 2*pi)
(unsafe-fx->fl n)))
(t 0)
(product 1)
(product-1 0)
(q 0))
(for ((factor (in-list factors))
(i (in-naturals)))
(unsafe-vector-set! twiddle i t)
(set! product-1 product) (set! product (unsafe-fx* product factor))
(set! q (unsafe-fxquotient n product))
(for ((j (in-range 1 factor)))
(let ((m 0))
(for ((k (in-range 1 (unsafe-fx+ q 1))))
(set! m (unsafe-fx+ m (unsafe-fx* j product-1)))
(set! m (unsafe-fxmodulo m n))
(let ((theta
(unsafe-fl* d-theta
(unsafe-fx->fl m)))) (unsafe-vector-set!
trig t (make-rectangular
(unsafe-flcos theta) (unsafe-flsin theta))))
(set! t (unsafe-fx+ t 1)))))))
(fft-complex-wavetable
n nf factors twiddle trig)))
(struct fft-complex-workspace
(n
scratch))
(define (make-fft-complex-workspace n)
(fft-complex-workspace n (make-vector n)))
(define (fft-complex-forward
data
#:workspace
(workspace (make-fft-complex-workspace (vector-length data))))
(fft-complex-transform data fft-forward #:workspace workspace))
(define (fft-complex-backward
data
#:workspace
(workspace (make-fft-complex-workspace (vector-length data))))
(fft-complex-transform data fft-backward #:workspace workspace))
(define (fft-complex-inverse
data
#:workspace
(workspace (make-fft-complex-workspace (vector-length data))))
(fft-complex-transform data fft-backward #:workspace workspace)
(let* ((n (unsafe-vector-length data))
(norm (unsafe-fl/ 1.0 (unsafe-fx->fl n))))
(for ((i (in-range n)))
(let* ((datum (unsafe-vector-ref data i))
(datum-real (real-part datum))
(datum-imag (imag-part datum)))
(unsafe-vector-set!
data i
(make-rectangular
(unsafe-fl* norm datum-real)
(unsafe-fl* norm datum-imag)))))))
(define (fft-complex-transform
data sign
#:workspace
(workspace (make-fft-complex-workspace (vector-length data))))
(let ((n (vector-length data)))
(unless (unsafe-fx= n (fft-complex-workspace-n workspace))
(error 'fft-complex-transform
"workspace does not match length of data, ~a"
n))
(let* ((wavetable (get-fft-complex-wavetable n))
(nf (fft-complex-wavetable-nf wavetable))
(factors (fft-complex-wavetable-factors wavetable))
(twiddle (fft-complex-wavetable-twiddle wavetable))
(trig (fft-complex-wavetable-trig wavetable))
(scratch (fft-complex-workspace-scratch workspace))
(state 0)
(in data)
(out scratch)
(product 1)
(q 0))
(unless (unsafe-fx= n 1)
(for ((factor (in-list factors))
(i (in-naturals)))
(set! product (unsafe-fx* product factor))
(set! q (unsafe-fxquotient n product))
(if (unsafe-fx= state 0)
(begin
(set! in data)
(set! out scratch)
(set! state 1))
(begin
(set! in scratch)
(set! out data)
(set! state 0)))
(cond ((unsafe-fx= factor 2)
(let ((twiddle1 (unsafe-vector-ref twiddle i)))
(fft-complex-pass-2
in out sign product n
trig twiddle1)))
((unsafe-fx= factor 3)
(let* ((twiddle1 (unsafe-vector-ref twiddle i))
(twiddle2 (unsafe-fx+ twiddle1 q)))
(fft-complex-pass-3
in out sign product n
trig twiddle1 twiddle2)))
((unsafe-fx= factor 4)
(let* ((twiddle1 (unsafe-vector-ref twiddle i))
(twiddle2 (unsafe-fx+ twiddle1 q))
(twiddle3 (unsafe-fx+ twiddle2 q)))
(fft-complex-pass-4
in out sign product n
trig twiddle1 twiddle2 twiddle3)))
((unsafe-fx= factor 5)
(let* ((twiddle1 (unsafe-vector-ref twiddle i))
(twiddle2 (unsafe-fx+ twiddle1 q))
(twiddle3 (unsafe-fx+ twiddle2 q))
(twiddle4 (unsafe-fx+ twiddle3 q)))
(fft-complex-pass-5
in out sign product n trig
twiddle1 twiddle2 twiddle3 twiddle4)))
((unsafe-fx= factor 6)
(let* ((twiddle1 (unsafe-vector-ref twiddle i))
(twiddle2 (unsafe-fx+ twiddle1 q))
(twiddle3 (unsafe-fx+ twiddle2 q))
(twiddle4 (unsafe-fx+ twiddle3 q))
(twiddle5 (unsafe-fx+ twiddle4 q)))
(fft-complex-pass-6
in out sign product n trig
twiddle1 twiddle2 twiddle3 twiddle4 twiddle5)))
((unsafe-fx= factor 7)
(let* ((twiddle1 (unsafe-vector-ref twiddle i))
(twiddle2 (unsafe-fx+ twiddle1 q))
(twiddle3 (unsafe-fx+ twiddle2 q))
(twiddle4 (unsafe-fx+ twiddle3 q))
(twiddle5 (unsafe-fx+ twiddle4 q))
(twiddle6 (unsafe-fx+ twiddle5 q)))
(fft-complex-pass-7
in out sign product n trig
twiddle1 twiddle2 twiddle3 twiddle4 twiddle5 twiddle6)))
(else
(let ((twiddle1 (unsafe-vector-ref twiddle i)))
(fft-complex-pass-n
in out sign factor product n
trig twiddle1)))))
(when (unsafe-fx= state 1)
(for ((i (in-range n)))
(unsafe-vector-set! data i (unsafe-vector-ref scratch i))))))))
(define (fft-complex-pass-2 in out sign product n
trig twiddle)
(let* ((i 0)
(j 0)
(factor 2)
(m (unsafe-fxquotient n factor))
(q (unsafe-fxquotient n product))
(product-1 (unsafe-fxquotient product factor))
(jump (unsafe-fx* (unsafe-fx- factor 1) product-1)))
(for ((k (in-range q)))
(let ((w-real 1.0)
(w-imag 0.0))
(unless (= k 0)
(if (= sign fft-forward)
(begin
(set! w-real (real-part (vector-ref trig (+ twiddle (- k 1)))))
(set! w-imag (imag-part (vector-ref trig (+ twiddle (- k 1))))))
(begin
(set! w-real (real-part (vector-ref trig (+ twiddle (- k 1)))))
(set! w-imag (- (imag-part (vector-ref trig (+ twiddle (- k 1)))))))))
(for ((k1 (in-range product-1)))
(let* ((z0 (unsafe-vector-ref in i))
(z0-real (real-part z0))
(z0-imag (imag-part z0))
(z1 (unsafe-vector-ref in (unsafe-fx+ i m)))
(z1-real (real-part z1))
(z1-imag (imag-part z1)))
(with-float (z0-real z0-imag z1-real z1-imag)
(let ( (x0-real (unsafe-fl+ z0-real z1-real))
(x0-imag (unsafe-fl+ z0-imag z1-imag))
(x1-real (unsafe-fl- z0-real z1-real))
(x1-imag (unsafe-fl- z0-imag z1-imag)))
(unsafe-vector-set!
out j (make-rectangular x0-real x0-imag))
(unsafe-vector-set!
out (+ j product-1)
(make-rectangular
(unsafe-fl- (unsafe-fl* w-real x1-real) (unsafe-fl* w-imag x1-imag))
(unsafe-fl+ (unsafe-fl* w-real x1-imag) (unsafe-fl* w-imag x1-real))))))
(set! i (unsafe-fx+ i 1))
(set! j (unsafe-fx+ j 1))))
(set! j (unsafe-fx+ j jump))))))
(define (fft-complex-pass-3 in out sign product n
trig twiddle1 twiddle2)
(define tau (unsafe-fl/ (unsafe-flsqrt 3.0) 2.0))
(let* ((i 0)
(j 0)
(factor 3)
(m (unsafe-fxquotient n factor))
(q (unsafe-fxquotient n product))
(p-1 (unsafe-fxquotient product factor))
(jump (unsafe-fx* (unsafe-fx- factor 1) p-1)))
(for ((k (in-range q)))
(let ((w1-real 1.0)
(w1-imag 0.0)
(w2-real 1.0)
(w2-imag 0.0))
(unless (unsafe-fx= k 0)
(let ((tw1 (unsafe-vector-ref trig (unsafe-fx+ twiddle1 (unsafe-fx- k 1))))
(tw2 (unsafe-vector-ref trig (unsafe-fx+ twiddle2 (unsafe-fx- k 1)))))
(if (= sign fft-forward)
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (imag-part tw1))
(set! w2-real (real-part tw2))
(set! w2-imag (imag-part tw2)))
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (- (imag-part tw1)))
(set! w2-real (real-part tw2))
(set! w2-imag (- (imag-part tw2)))))))
(for ((k1 (in-range p-1)))
(let* ((z0 (unsafe-vector-ref in i))
(z0-real (real-part z0))
(z0-imag (imag-part z0))
(z1 (unsafe-vector-ref in (unsafe-fx+ i m)))
(z1-real (real-part z1))
(z1-imag (imag-part z1))
(z2 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 2 m))))
(z2-real (real-part z2))
(z2-imag (imag-part z2)))
(with-float (z0-real z0-imag z1-real z1-imag z2-real z2-imag)
(let* ( (t1-real (unsafe-fl+ z1-real z2-real))
(t1-imag (unsafe-fl+ z1-imag z2-imag))
(t2-real (unsafe-fl- z0-real (unsafe-fl/ t1-real 2.0)))
(t2-imag (unsafe-fl- z0-imag (unsafe-fl/ t1-imag 2.0)))
(t3-real (* sign tau (unsafe-fl- z1-real z2-real)))
(t3-imag (* sign tau (unsafe-fl- z1-imag z2-imag)))
(x0-real (unsafe-fl+ z0-real t1-real))
(x0-imag (unsafe-fl+ z0-imag t1-imag))
(x1-real (unsafe-fl- t2-real t3-imag))
(x1-imag (unsafe-fl+ t2-imag t3-real))
(x2-real (unsafe-fl+ t2-real t3-imag))
(x2-imag (unsafe-fl- t2-imag t3-real)))
(vector-set!
out j (make-rectangular x0-real x0-imag))
(vector-set!
out (unsafe-fx+ j p-1)
(make-rectangular
(unsafe-fl- (unsafe-fl* w1-real x1-real)
(unsafe-fl* w1-imag x1-imag))
(unsafe-fl+ (unsafe-fl* w1-real x1-imag)
(unsafe-fl* w1-imag x1-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 2 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w2-real x2-real)
(unsafe-fl* w2-imag x2-imag))
(unsafe-fl+ (unsafe-fl* w2-real x2-imag)
(unsafe-fl* w2-imag x2-real))))))
(set! i (unsafe-fx+ i 1))
(set! j (unsafe-fx+ j 1))))
(set! j (unsafe-fx+ j jump))))))
(define (fft-complex-pass-4 in out sign product n
trig twiddle1 twiddle2 twiddle3)
(let* ((i 0)
(j 0)
(factor 4)
(m (unsafe-fxquotient n factor))
(q (unsafe-fxquotient n product))
(p-1 (unsafe-fxquotient product factor))
(jump (unsafe-fx* (unsafe-fx- factor 1) p-1)))
(for ((k (in-range q)))
(let ((w1-real 1.0)
(w1-imag 0.0)
(w2-real 1.0)
(w2-imag 0.0)
(w3-real 1.0)
(w3-imag 0.0))
(unless (unsafe-fx= k 0)
(let ((tw1 (unsafe-vector-ref trig (unsafe-fx+ twiddle1 (unsafe-fx- k 1))))
(tw2 (unsafe-vector-ref trig (unsafe-fx+ twiddle2 (unsafe-fx- k 1))))
(tw3 (unsafe-vector-ref trig (unsafe-fx+ twiddle3 (unsafe-fx- k 1)))))
(if (= sign fft-forward)
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (imag-part tw1))
(set! w2-real (real-part tw2))
(set! w2-imag (imag-part tw2))
(set! w3-real (real-part tw3))
(set! w3-imag (imag-part tw3)))
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (- (imag-part tw1)))
(set! w2-real (real-part tw2))
(set! w2-imag (- (imag-part tw2)))
(set! w3-real (real-part tw3))
(set! w3-imag (- (imag-part tw3)))))))
(for ((k1 (in-range p-1)))
(let* ((z0 (unsafe-vector-ref in i))
(z0-real (real-part z0))
(z0-imag (imag-part z0))
(z1 (unsafe-vector-ref in (unsafe-fx+ i m)))
(z1-real (real-part z1))
(z1-imag (imag-part z1))
(z2 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 2 m))))
(z2-real (real-part z2))
(z2-imag (imag-part z2))
(z3 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 3 m))))
(z3-real (real-part z3))
(z3-imag (imag-part z3)))
(with-float (z0-real z0-imag z1-real z1-imag
z2-real z2-imag z3-real z3-imag)
(let* ( (t1-real (unsafe-fl+ z0-real z2-real))
(t1-imag (unsafe-fl+ z0-imag z2-imag))
(t2-real (unsafe-fl+ z1-real z3-real))
(t2-imag (unsafe-fl+ z1-imag z3-imag))
(t3-real (unsafe-fl- z0-real z2-real))
(t3-imag (unsafe-fl- z0-imag z2-imag))
(t4-real (* sign (unsafe-fl- z1-real z3-real)))
(t4-imag (* sign (unsafe-fl- z1-imag z3-imag)))
(x0-real (unsafe-fl+ t1-real t2-real))
(x0-imag (unsafe-fl+ t1-imag t2-imag))
(x1-real (unsafe-fl- t3-real t4-imag))
(x1-imag (unsafe-fl+ t3-imag t4-real))
(x2-real (unsafe-fl- t1-real t2-real))
(x2-imag (unsafe-fl- t1-imag t2-imag))
(x3-real (unsafe-fl+ t3-real t4-imag))
(x3-imag (unsafe-fl- t3-imag t4-real)))
(vector-set!
out j (make-rectangular x0-real x0-imag))
(vector-set!
out (unsafe-fx+ j p-1)
(make-rectangular
(unsafe-fl- (unsafe-fl* w1-real x1-real)
(unsafe-fl* w1-imag x1-imag))
(unsafe-fl+ (unsafe-fl* w1-real x1-imag)
(unsafe-fl* w1-imag x1-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 2 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w2-real x2-real)
(unsafe-fl* w2-imag x2-imag))
(unsafe-fl+ (unsafe-fl* w2-real x2-imag)
(unsafe-fl* w2-imag x2-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 3 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w3-real x3-real)
(unsafe-fl* w3-imag x3-imag))
(unsafe-fl+ (unsafe-fl* w3-real x3-imag)
(unsafe-fl* w3-imag x3-real))))))
(set! i (unsafe-fx+ i 1))
(set! j (unsafe-fx+ j 1))))
(set! j (unsafe-fx+ j jump))))))
(define (fft-complex-pass-5 in out sign product n trig
twiddle1 twiddle2 twiddle3 twiddle4)
(define sqrt-5-by-4 (unsafe-fl/ (unsafe-flsqrt 5.0) 4.0))
(define sin-2pi-by-5 (unsafe-flsin (unsafe-fl/ 2*pi 5.0)))
(define sin-2pi-by-10 (unsafe-flsin (unsafe-fl/ 2*pi 10.0)))
(let* ((i 0)
(j 0)
(factor 5)
(m (unsafe-fxquotient n factor))
(q (unsafe-fxquotient n product))
(p-1 (unsafe-fxquotient product factor))
(jump (unsafe-fx* (unsafe-fx- factor 1) p-1)))
(for ((k (in-range q)))
(let ((w1-real 1.0)
(w1-imag 0.0)
(w2-real 1.0)
(w2-imag 0.0)
(w3-real 1.0)
(w3-imag 0.0)
(w4-real 1.0)
(w4-imag 0.0))
(unless (unsafe-fx= k 0)
(let ((tw1 (unsafe-vector-ref trig (unsafe-fx+ twiddle1 (unsafe-fx- k 1))))
(tw2 (unsafe-vector-ref trig (unsafe-fx+ twiddle2 (unsafe-fx- k 1))))
(tw3 (unsafe-vector-ref trig (unsafe-fx+ twiddle3 (unsafe-fx- k 1))))
(tw4 (unsafe-vector-ref trig (unsafe-fx+ twiddle4 (unsafe-fx- k 1)))))
(if (= sign fft-forward)
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (imag-part tw1))
(set! w2-real (real-part tw2))
(set! w2-imag (imag-part tw2))
(set! w3-real (real-part tw3))
(set! w3-imag (imag-part tw3))
(set! w4-real (real-part tw4))
(set! w4-imag (imag-part tw4)))
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (- (imag-part tw1)))
(set! w2-real (real-part tw2))
(set! w2-imag (- (imag-part tw2)))
(set! w3-real (real-part tw3))
(set! w3-imag (- (imag-part tw3)))
(set! w4-real (real-part tw4))
(set! w4-imag (- (imag-part tw4)))))))
(for ((k1 (in-range p-1)))
(let* ((z0 (unsafe-vector-ref in i))
(z0-real (real-part z0))
(z0-imag (imag-part z0))
(z1 (unsafe-vector-ref in (unsafe-fx+ i m)))
(z1-real (real-part z1))
(z1-imag (imag-part z1))
(z2 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 2 m))))
(z2-real (real-part z2))
(z2-imag (imag-part z2))
(z3 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 3 m))))
(z3-real (real-part z3))
(z3-imag (imag-part z3))
(z4 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 4 m))))
(z4-real (real-part z4))
(z4-imag (imag-part z4)))
(with-float (z0-real z0-imag z1-real z1-imag
z2-real z2-imag z3-real z3-imag
z4-real z4-imag)
(let* ( (t1-real (unsafe-fl+ z1-real z4-real))
(t1-imag (unsafe-fl+ z1-imag z4-imag))
(t2-real (unsafe-fl+ z2-real z3-real))
(t2-imag (unsafe-fl+ z2-imag z3-imag))
(t3-real (unsafe-fl- z1-real z4-real))
(t3-imag (unsafe-fl- z1-imag z4-imag))
(t4-real (unsafe-fl- z2-real z3-real))
(t4-imag (unsafe-fl- z2-imag z3-imag))
(t5-real (unsafe-fl+ t1-real t2-real))
(t5-imag (unsafe-fl+ t1-imag t2-imag))
(t6-real (unsafe-fl* sqrt-5-by-4 (unsafe-fl- t1-real t2-real)))
(t6-imag (unsafe-fl* sqrt-5-by-4 (unsafe-fl- t1-imag t2-imag)))
(t7-real (unsafe-fl- z0-real (unsafe-fl/ t5-real 4.0)))
(t7-imag (unsafe-fl- z0-imag (unsafe-fl/ t5-imag 4.0)))
(t8-real (unsafe-fl+ t7-real t6-real))
(t8-imag (unsafe-fl+ t7-imag t6-imag))
(t9-real (unsafe-fl- t7-real t6-real))
(t9-imag (unsafe-fl- t7-imag t6-imag))
(t10-real (* sign (unsafe-fl+ (unsafe-fl* sin-2pi-by-5 t3-real)
(unsafe-fl* sin-2pi-by-10 t4-real))))
(t10-imag (* sign (unsafe-fl+ (unsafe-fl* sin-2pi-by-5 t3-imag)
(unsafe-fl* sin-2pi-by-10 t4-imag))))
(t11-real (* sign (unsafe-fl- (unsafe-fl* sin-2pi-by-10 t3-real)
(unsafe-fl* sin-2pi-by-5 t4-real))))
(t11-imag (* sign (unsafe-fl- (unsafe-fl* sin-2pi-by-10 t3-imag)
(unsafe-fl* sin-2pi-by-5 t4-imag))))
(x0-real (unsafe-fl+ z0-real t5-real))
(x0-imag (unsafe-fl+ z0-imag t5-imag))
(x1-real (unsafe-fl- t8-real t10-imag))
(x1-imag (unsafe-fl+ t8-imag t10-real))
(x2-real (unsafe-fl- t9-real t11-imag))
(x2-imag (unsafe-fl+ t9-imag t11-real))
(x3-real (unsafe-fl+ t9-real t11-imag))
(x3-imag (unsafe-fl- t9-imag t11-real))
(x4-real (unsafe-fl+ t8-real t10-imag))
(x4-imag (unsafe-fl- t8-imag t10-real)))
(vector-set!
out j (make-rectangular x0-real x0-imag))
(vector-set!
out (unsafe-fx+ j p-1)
(make-rectangular
(unsafe-fl- (unsafe-fl* w1-real x1-real)
(unsafe-fl* w1-imag x1-imag))
(unsafe-fl+ (unsafe-fl* w1-real x1-imag)
(unsafe-fl* w1-imag x1-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 2 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w2-real x2-real)
(unsafe-fl* w2-imag x2-imag))
(unsafe-fl+ (unsafe-fl* w2-real x2-imag)
(unsafe-fl* w2-imag x2-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 3 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w3-real x3-real)
(unsafe-fl* w3-imag x3-imag))
(unsafe-fl+ (unsafe-fl* w3-real x3-imag)
(unsafe-fl* w3-imag x3-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 4 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w4-real x4-real)
(unsafe-fl* w4-imag x4-imag))
(unsafe-fl+ (unsafe-fl* w4-real x4-imag)
(unsafe-fl* w4-imag x4-real))))))
(set! i (unsafe-fx+ i 1))
(set! j (unsafe-fx+ j 1))))
(set! j (unsafe-fx+ j jump))))))
(define (fft-complex-pass-6 in out sign product n trig
twiddle1 twiddle2 twiddle3
twiddle4 twiddle5)
(let* ((i 0)
(j 0)
(factor 6)
(m (unsafe-fxquotient n factor))
(q (unsafe-fxquotient n product))
(p-1 (unsafe-fxquotient product factor))
(jump (unsafe-fx* (unsafe-fx- factor 1) p-1))
(tau (unsafe-fl/ (unsafe-flsqrt 3.0) 2.0)))
(for ((k (in-range q)))
(let ((w1-real 1.0)
(w1-imag 0.0)
(w2-real 1.0)
(w2-imag 0.0)
(w3-real 1.0)
(w3-imag 0.0)
(w4-real 1.0)
(w4-imag 0.0)
(w5-real 1.0)
(w5-imag 0.0))
(unless (unsafe-fx= k 0)
(let ((tw1 (unsafe-vector-ref trig (unsafe-fx+ twiddle1 (unsafe-fx- k 1))))
(tw2 (unsafe-vector-ref trig (unsafe-fx+ twiddle2 (unsafe-fx- k 1))))
(tw3 (unsafe-vector-ref trig (unsafe-fx+ twiddle3 (unsafe-fx- k 1))))
(tw4 (unsafe-vector-ref trig (unsafe-fx+ twiddle4 (unsafe-fx- k 1))))
(tw5 (unsafe-vector-ref trig (unsafe-fx+ twiddle5 (unsafe-fx- k 1)))))
(if (= sign fft-forward)
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (imag-part tw1))
(set! w2-real (real-part tw2))
(set! w2-imag (imag-part tw2))
(set! w3-real (real-part tw3))
(set! w3-imag (imag-part tw3))
(set! w4-real (real-part tw4))
(set! w4-imag (imag-part tw4))
(set! w5-real (real-part tw5))
(set! w5-imag (imag-part tw5)))
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (- (imag-part tw1)))
(set! w2-real (real-part tw2))
(set! w2-imag (- (imag-part tw2)))
(set! w3-real (real-part tw3))
(set! w3-imag (- (imag-part tw3)))
(set! w4-real (real-part tw4))
(set! w4-imag (- (imag-part tw4)))
(set! w5-real (real-part tw5))
(set! w5-imag (- (imag-part tw5)))))))
(for ((k1 (in-range p-1)))
(let* ((z0 (unsafe-vector-ref in i))
(z0-real (real-part z0))
(z0-imag (imag-part z0))
(z1 (unsafe-vector-ref in (unsafe-fx+ i m)))
(z1-real (real-part z1))
(z1-imag (imag-part z1))
(z2 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 2 m))))
(z2-real (real-part z2))
(z2-imag (imag-part z2))
(z3 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 3 m))))
(z3-real (real-part z3))
(z3-imag (imag-part z3))
(z4 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 4 m))))
(z4-real (real-part z4))
(z4-imag (imag-part z4))
(z5 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 5 m))))
(z5-real (real-part z5))
(z5-imag (imag-part z5)))
(with-float (z0-real z0-imag z1-real z1-imag
z2-real z2-imag z3-real z3-imag
z4-real z4-imag z5-real z5-imag)
(let* ( (ta1-real (unsafe-fl+ z2-real z4-real))
(ta1-imag (unsafe-fl+ z2-imag z4-imag))
(ta2-real (unsafe-fl- z0-real (unsafe-fl/ ta1-real 2.0)))
(ta2-imag (unsafe-fl- z0-imag (unsafe-fl/ ta1-imag 2.0)))
(ta3-real (unsafe-fl* (* sign tau) (unsafe-fl- z2-real z4-real)))
(ta3-imag (unsafe-fl* (* sign tau) (unsafe-fl- z2-imag z4-imag)))
(a0-real (unsafe-fl+ z0-real ta1-real))
(a0-imag (unsafe-fl+ z0-imag ta1-imag))
(a1-real (unsafe-fl- ta2-real ta3-imag))
(a1-imag (unsafe-fl+ ta2-imag ta3-real))
(a2-real (unsafe-fl+ ta2-real ta3-imag))
(a2-imag (unsafe-fl- ta2-imag ta3-real))
(tb1-real (unsafe-fl+ z5-real z1-real))
(tb1-imag (unsafe-fl+ z5-imag z1-imag))
(tb2-real (unsafe-fl- z3-real (unsafe-fl/ tb1-real 2.0)))
(tb2-imag (unsafe-fl- z3-imag (unsafe-fl/ tb1-imag 2.0)))
(tb3-real (unsafe-fl* (* sign tau) (unsafe-fl- z5-real z1-real)))
(tb3-imag (unsafe-fl* (* sign tau) (unsafe-fl- z5-imag z1-imag)))
(b0-real (unsafe-fl+ z3-real tb1-real))
(b0-imag (unsafe-fl+ z3-imag tb1-imag))
(b1-real (unsafe-fl- tb2-real tb3-imag))
(b1-imag (unsafe-fl+ tb2-imag tb3-real))
(b2-real (unsafe-fl+ tb2-real tb3-imag))
(b2-imag (unsafe-fl- tb2-imag tb3-real))
(x0-real (unsafe-fl+ a0-real b0-real))
(x0-imag (unsafe-fl+ a0-imag b0-imag))
(x4-real (unsafe-fl+ a1-real b1-real))
(x4-imag (unsafe-fl+ a1-imag b1-imag))
(x2-real (unsafe-fl+ a2-real b2-real))
(x2-imag (unsafe-fl+ a2-imag b2-imag))
(x3-real (unsafe-fl- a0-real b0-real))
(x3-imag (unsafe-fl- a0-imag b0-imag))
(x1-real (unsafe-fl- a1-real b1-real))
(x1-imag (unsafe-fl- a1-imag b1-imag))
(x5-real (unsafe-fl- a2-real b2-real))
(x5-imag (unsafe-fl- a2-imag b2-imag)))
(vector-set!
out j (make-rectangular x0-real x0-imag))
(vector-set!
out (unsafe-fx+ j p-1)
(make-rectangular
(unsafe-fl- (unsafe-fl* w1-real x1-real)
(unsafe-fl* w1-imag x1-imag))
(unsafe-fl+ (unsafe-fl* w1-real x1-imag)
(unsafe-fl* w1-imag x1-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 2 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w2-real x2-real)
(unsafe-fl* w2-imag x2-imag))
(unsafe-fl+ (unsafe-fl* w2-real x2-imag)
(unsafe-fl* w2-imag x2-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 3 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w3-real x3-real)
(unsafe-fl* w3-imag x3-imag))
(unsafe-fl+ (unsafe-fl* w3-real x3-imag)
(unsafe-fl* w3-imag x3-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 4 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w4-real x4-real)
(unsafe-fl* w4-imag x4-imag))
(unsafe-fl+ (unsafe-fl* w4-real x4-imag)
(unsafe-fl* w4-imag x4-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 5 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w5-real x5-real)
(unsafe-fl* w5-imag x5-imag))
(unsafe-fl+ (unsafe-fl* w5-real x5-imag)
(unsafe-fl* w5-imag x5-real))))))
(set! i (unsafe-fx+ i 1))
(set! j (unsafe-fx+ j 1))))
(set! j (unsafe-fx+ j jump))))))
(define (fft-complex-pass-7 in out sign product n trig
twiddle1 twiddle2 twiddle3
twiddle4 twiddle5 twiddle6)
(define c1 (unsafe-flcos (unsafe-fl/ (unsafe-fl* 1.0 2*pi) 7.0)))
(define c2 (unsafe-flcos (unsafe-fl/ (unsafe-fl* 2.0 2*pi) 7.0)))
(define c3 (unsafe-flcos (unsafe-fl/ (unsafe-fl* 3.0 2*pi) 7.0)))
(define s1 (unsafe-flsin (unsafe-fl/ (unsafe-fl* 1.0 2*pi) 7.0)))
(define s2 (unsafe-flsin (unsafe-fl/ (unsafe-fl* 2.0 2*pi) 7.0)))
(define s3 (unsafe-flsin (unsafe-fl/ (unsafe-fl* 3.0 2*pi) 7.0)))
(let* ((i 0)
(j 0)
(factor 7)
(m (unsafe-fxquotient n factor))
(q (unsafe-fxquotient n product))
(p-1 (unsafe-fxquotient product factor))
(jump (unsafe-fx* (unsafe-fx- factor 1) p-1))
(tau (unsafe-fl/ (unsafe-flsqrt 3.0) 2.0)))
(for ((k (in-range q)))
(let ((w1-real 1.0)
(w1-imag 0.0)
(w2-real 1.0)
(w2-imag 0.0)
(w3-real 1.0)
(w3-imag 0.0)
(w4-real 1.0)
(w4-imag 0.0)
(w5-real 1.0)
(w5-imag 0.0)
(w6-real 1.0)
(w6-imag 0.0))
(unless (unsafe-fx= k 0)
(let ((tw1 (unsafe-vector-ref trig (unsafe-fx+ twiddle1 (unsafe-fx- k 1))))
(tw2 (unsafe-vector-ref trig (unsafe-fx+ twiddle2 (unsafe-fx- k 1))))
(tw3 (unsafe-vector-ref trig (unsafe-fx+ twiddle3 (unsafe-fx- k 1))))
(tw4 (unsafe-vector-ref trig (unsafe-fx+ twiddle4 (unsafe-fx- k 1))))
(tw5 (unsafe-vector-ref trig (unsafe-fx+ twiddle5 (unsafe-fx- k 1))))
(tw6 (unsafe-vector-ref trig (unsafe-fx+ twiddle6 (unsafe-fx- k 1)))))
(if (= sign fft-forward)
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (imag-part tw1))
(set! w2-real (real-part tw2))
(set! w2-imag (imag-part tw2))
(set! w3-real (real-part tw3))
(set! w3-imag (imag-part tw3))
(set! w4-real (real-part tw4))
(set! w4-imag (imag-part tw4))
(set! w5-real (real-part tw5))
(set! w5-imag (imag-part tw5))
(set! w6-real (real-part tw6))
(set! w6-imag (imag-part tw6)))
(begin
(set! w1-real (real-part tw1))
(set! w1-imag (- (imag-part tw1)))
(set! w2-real (real-part tw2))
(set! w2-imag (- (imag-part tw2)))
(set! w3-real (real-part tw3))
(set! w3-imag (- (imag-part tw3)))
(set! w4-real (real-part tw4))
(set! w4-imag (- (imag-part tw4)))
(set! w5-real (real-part tw5))
(set! w5-imag (- (imag-part tw5)))
(set! w6-real (real-part tw6))
(set! w6-imag (- (imag-part tw6)))))))
(for ((k1 (in-range p-1)))
(let* ((z0 (unsafe-vector-ref in i))
(z0-real (real-part z0))
(z0-imag (imag-part z0))
(z1 (unsafe-vector-ref in (unsafe-fx+ i m)))
(z1-real (real-part z1))
(z1-imag (imag-part z1))
(z2 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 2 m))))
(z2-real (real-part z2))
(z2-imag (imag-part z2))
(z3 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 3 m))))
(z3-real (real-part z3))
(z3-imag (imag-part z3))
(z4 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 4 m))))
(z4-real (real-part z4))
(z4-imag (imag-part z4))
(z5 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 5 m))))
(z5-real (real-part z5))
(z5-imag (imag-part z5))
(z6 (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* 6 m))))
(z6-real (real-part z6))
(z6-imag (imag-part z6)))
(with-float (z0-real z0-imag z1-real z1-imag
z2-real z2-imag z3-real z3-imag
z4-real z4-imag z5-real z5-imag
z6-real z6-imag)
(let* ( (t0-real (unsafe-fl+ z1-real z6-real))
(t0-imag (unsafe-fl+ z1-imag z6-imag))
(t1-real (unsafe-fl- z1-real z6-real))
(t1-imag (unsafe-fl- z1-imag z6-imag))
(t2-real (unsafe-fl+ z2-real z5-real))
(t2-imag (unsafe-fl+ z2-imag z5-imag))
(t3-real (unsafe-fl- z2-real z5-real))
(t3-imag (unsafe-fl- z2-imag z5-imag))
(t4-real (unsafe-fl+ z4-real z3-real))
(t4-imag (unsafe-fl+ z4-imag z3-imag))
(t5-real (unsafe-fl- z4-real z3-real))
(t5-imag (unsafe-fl- z4-imag z3-imag))
(t6-real (unsafe-fl+ t2-real t0-real))
(t6-imag (unsafe-fl+ t2-imag t0-imag))
(t7-real (unsafe-fl+ t5-real t3-real))
(t7-imag (unsafe-fl+ t5-imag t3-imag))
(b0-real (unsafe-fl+ z0-real (unsafe-fl+ t6-real t4-real)))
(b0-imag (unsafe-fl+ z0-imag (unsafe-fl+ t6-imag t4-imag)))
(cb1 (unsafe-fl- (unsafe-fl/ (unsafe-fl+ (unsafe-fl+ c1 c2) c3) 3.0) 1.0))
(b1-real (unsafe-fl* cb1 (unsafe-fl+ t6-real t4-real)))
(b1-imag (unsafe-fl* cb1 (unsafe-fl+ t6-imag t4-imag)))
(cb2 (unsafe-fl/ (unsafe-fl- (unsafe-fl- (unsafe-fl* 2.0 c1) c2) c3) 3.0))
(b2-real (unsafe-fl* cb2 (unsafe-fl- t0-real t4-real)))
(b2-imag (unsafe-fl* cb2 (unsafe-fl- t0-imag t4-imag)))
(cb3 (unsafe-fl/ (unsafe-fl+ (unsafe-fl- c1 (unsafe-fl* 2.0 c2)) c3) 3.0))
(b3-real (unsafe-fl* cb3 (unsafe-fl- t4-real t2-real)))
(b3-imag (unsafe-fl* cb3 (unsafe-fl- t4-imag t2-imag)))
(cb4 (unsafe-fl/ (unsafe-fl- (unsafe-fl+ c1 c2) (unsafe-fl* 2.0 c3)) 3.0))
(b4-real (unsafe-fl* cb4 (unsafe-fl- t2-real t0-real)))
(b4-imag (unsafe-fl* cb4 (unsafe-fl- t2-imag t0-imag)))
(cb5 (* (- sign) (unsafe-fl/ (unsafe-fl- (unsafe-fl+ s1 s2) s3) 3.0)))
(b5-real (unsafe-fl* cb5 (unsafe-fl+ t7-real t1-real)))
(b5-imag (unsafe-fl* cb5 (unsafe-fl+ t7-imag t1-imag)))
(cb6 (* (- sign) (unsafe-fl/ (unsafe-fl+ (unsafe-fl- (unsafe-fl* 2.0 s1) s2) s3) 3.0)))
(b6-real (unsafe-fl* cb6 (unsafe-fl- t1-real t5-real)))
(b6-imag (unsafe-fl* cb6 (unsafe-fl- t1-imag t5-imag)))
(cb7 (* (- sign) (unsafe-fl/ (unsafe-fl- (unsafe-fl- s1 (unsafe-fl* 2.0 s2)) s3) 3.0)))
(b7-real (unsafe-fl* cb7 (unsafe-fl- t5-real t3-real)))
(b7-imag (unsafe-fl* cb7 (unsafe-fl- t5-imag t3-imag)))
(cb8 (* (- sign) (unsafe-fl/ (unsafe-fl+ (unsafe-fl+ s1 s2) (unsafe-fl* 2.0 s3)) 3.0)))
(b8-real (unsafe-fl* cb8 (unsafe-fl- t3-real t1-real)))
(b8-imag (unsafe-fl* cb8 (unsafe-fl- t3-imag t1-imag)))
(T0-real (unsafe-fl+ b0-real b1-real))
(T0-imag (unsafe-fl+ b0-imag b1-imag))
(T1-real (unsafe-fl+ b2-real b3-real))
(T1-imag (unsafe-fl+ b2-imag b3-imag))
(T2-real (unsafe-fl- b4-real b3-real))
(T2-imag (unsafe-fl- b4-imag b3-imag))
(T3-real (unsafe-fl- (- b2-real) b4-real))
(T3-imag (unsafe-fl- (- b2-imag) b4-imag))
(T4-real (unsafe-fl+ b6-real b7-real))
(T4-imag (unsafe-fl+ b6-imag b7-imag))
(T5-real (unsafe-fl- b8-real b7-real))
(T5-imag (unsafe-fl- b8-imag b7-imag))
(T6-real (unsafe-fl- (- b8-real) b6-real))
(T6-imag (unsafe-fl- (- b8-imag) b6-imag))
(T7-real (unsafe-fl+ T0-real T1-real))
(T7-imag (unsafe-fl+ T0-imag T1-imag))
(T8-real (unsafe-fl+ T0-real T2-real))
(T8-imag (unsafe-fl+ T0-imag T2-imag))
(T9-real (unsafe-fl+ T0-real T3-real))
(T9-imag (unsafe-fl+ T0-imag T3-imag))
(T10-real (unsafe-fl+ T4-real b5-real))
(T10-imag (unsafe-fl+ T4-imag b5-imag))
(T11-real (unsafe-fl+ T5-real b5-real))
(T11-imag (unsafe-fl+ T5-imag b5-imag))
(T12-real (unsafe-fl+ T6-real b5-real))
(T12-imag (unsafe-fl+ T6-imag b5-imag))
(x0-real b0-real)
(x0-imag b0-imag)
(x1-real (unsafe-fl+ T7-real T10-imag))
(x1-imag (unsafe-fl- T7-imag T10-real))
(x2-real (unsafe-fl+ T9-real T12-imag))
(x2-imag (unsafe-fl- T9-imag T12-real))
(x3-real (unsafe-fl- T8-real T11-imag))
(x3-imag (unsafe-fl+ T8-imag T11-real))
(x4-real (unsafe-fl+ T8-real T11-imag))
(x4-imag (unsafe-fl- T8-imag T11-real))
(x5-real (unsafe-fl- T9-real T12-imag))
(x5-imag (unsafe-fl+ T9-imag T12-real))
(x6-real (unsafe-fl- T7-real T10-imag))
(x6-imag (unsafe-fl+ T7-imag T10-real)))
(vector-set!
out j (make-rectangular x0-real x0-imag))
(vector-set!
out (unsafe-fx+ j p-1)
(make-rectangular
(unsafe-fl- (unsafe-fl* w1-real x1-real)
(unsafe-fl* w1-imag x1-imag))
(unsafe-fl+ (unsafe-fl* w1-real x1-imag)
(unsafe-fl* w1-imag x1-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 2 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w2-real x2-real)
(unsafe-fl* w2-imag x2-imag))
(unsafe-fl+ (unsafe-fl* w2-real x2-imag)
(unsafe-fl* w2-imag x2-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 3 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w3-real x3-real)
(unsafe-fl* w3-imag x3-imag))
(unsafe-fl+ (unsafe-fl* w3-real x3-imag)
(unsafe-fl* w3-imag x3-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 4 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w4-real x4-real)
(unsafe-fl* w4-imag x4-imag))
(unsafe-fl+ (unsafe-fl* w4-real x4-imag)
(unsafe-fl* w4-imag x4-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 5 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w5-real x5-real)
(unsafe-fl* w5-imag x5-imag))
(unsafe-fl+ (unsafe-fl* w5-real x5-imag)
(unsafe-fl* w5-imag x5-real))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* 6 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w6-real x6-real)
(unsafe-fl* w6-imag x6-imag))
(unsafe-fl+ (unsafe-fl* w6-real x6-imag)
(unsafe-fl* w6-imag x6-real))))))
(set! i (unsafe-fx+ i 1))
(set! j (unsafe-fx+ j 1))))
(set! j (unsafe-fx+ j jump))))))
(define (fft-complex-pass-n in out sign factor product n
trig twiddle)
(let* ((i 0)
(j 0)
(m (unsafe-fxquotient n factor))
(q (unsafe-fxquotient n product))
(p-1 (unsafe-fxquotient product factor))
(jump (unsafe-fx* (unsafe-fx- factor 1) p-1)))
(for ((i (in-range m)))
(unsafe-vector-set! out i (unsafe-vector-ref in i)))
(for ((e (in-range 1 (unsafe-fx+ (unsafe-fxquotient
(unsafe-fx- factor 1) 2) 1))))
(for ((i (in-range 0 m)))
(let* ((idx (unsafe-fx+ i (unsafe-fx* e m)))
(idxc (unsafe-fx+ i (unsafe-fx* (unsafe-fx- factor e) m)))
(z0 (unsafe-vector-ref in idx))
(z1 (unsafe-vector-ref in idxc)))
(unsafe-vector-set! out idx (+ z0 z1))
(unsafe-vector-set! out idxc (- z0 z1)))))
(for ((i (in-range m)))
(unsafe-vector-set! in i (unsafe-vector-ref out i)))
(for ((e1 (in-range 1 (unsafe-fx+ (unsafe-fxquotient
(unsafe-fx- factor 1) 2) 1))))
(for ((i (in-range m)))
(let ((z0 (unsafe-vector-ref in i))
(z1 (unsafe-vector-ref out (unsafe-fx+ i (unsafe-fx* e1 m)))))
(unsafe-vector-set! in i (+ z0 z1)))))
(for ((e (in-range 1 (unsafe-fx+ (unsafe-fxquotient
(unsafe-fx- factor 1) 2) 1))))
(let ((idx (unsafe-fx* e q))
(idx-step (unsafe-fx* e q))
(w-real 1.0)
(w-imag 0.0)
(em (unsafe-fx* e m))
(ecm (unsafe-fx* (unsafe-fx- factor e) m)))
(for ((i (in-range m)))
(unsafe-vector-set! in (unsafe-fx+ i em) (unsafe-vector-ref out i))
(unsafe-vector-set! in (unsafe-fx+ i ecm) (unsafe-vector-ref out i)))
(for ((e1 (in-range 1 (unsafe-fx+ (unsafe-fxquotient
(unsafe-fx- factor 1) 2) 1))))
(if (unsafe-fx= idx 0)
(begin
(set! w-real 1.0)
(set! w-imag 0.0))
(let ((tw (unsafe-vector-ref trig (unsafe-fx+
twiddle (unsafe-fx- idx 1)))))
(if (= sign fft-forward)
(begin
(set! w-real (real-part tw))
(set! w-imag (imag-part tw)))
(begin
(set! w-real (real-part tw))
(set! w-imag (- (imag-part tw)))))))
(for ((i (in-range m)))
(let* ((xp (unsafe-vector-ref
out (unsafe-fx+ i (unsafe-fx* e1 m))))
(xp-real (real-part xp))
(xp-imag (imag-part xp))
(xm (unsafe-vector-ref
out (unsafe-fx+ i (unsafe-fx*
(unsafe-fx- factor e1) m))))
(xm-real (real-part xm))
(xm-imag (imag-part xm)))
(with-float (xp-real xp-imag xm-real xm-imag)
(let* ((ap (unsafe-fl* w-real xp-real))
(am (unsafe-fl* w-imag xm-imag))
(sum-real (unsafe-fl- ap am))
(sumc-real (unsafe-fl+ ap am))
(bp (unsafe-fl* w-real xp-imag))
(bm (unsafe-fl* w-imag xm-real))
(sum-imag (unsafe-fl+ bp bm))
(sumc-imag (unsafe-fl- bp bm))
(z0 (unsafe-vector-ref in (unsafe-fx+ i em)))
(z0-real (real-part z0))
(z0-imag (imag-part z0))
(z1 (unsafe-vector-ref in (unsafe-fx+ i ecm)))
(z1-real (real-part z1))
(z1-imag (imag-part z1)))
(with-float (z0-real z0-imag z1-real z1-imag)
(unsafe-vector-set!
in (unsafe-fx+ i em)
(make-rectangular (unsafe-fl+ z0-real sum-real)
(unsafe-fl+ z0-imag sum-imag)))
(unsafe-vector-set!
in (unsafe-fx+ i ecm)
(make-rectangular (unsafe-fl+ z1-real sumc-real)
(unsafe-fl+ z1-imag sumc-imag))))))))
(set! idx (unsafe-fx+ idx idx-step))
(set! idx (unsafe-fxmodulo idx (unsafe-fx* factor q))))))
(set! i 0)
(set! j 0)
(for ((k1 (in-range p-1)))
(unsafe-vector-set! out k1 (unsafe-vector-ref in k1)))
(for ((e1 (in-range 1 factor)))
(for ((k1 (in-range p-1)))
(unsafe-vector-set!
out (unsafe-fx+ k1 (unsafe-fx* e1 p-1))
(unsafe-vector-ref in (unsafe-fx+ k1 (unsafe-fx* e1 m))))))
(set! i p-1)
(set! j product)
(for ((k (in-range 1 q)))
(for ((k1 (in-range p-1)))
(unsafe-vector-set! out j (unsafe-vector-ref in i))
(set! i (unsafe-fx+ i 1))
(set! j (unsafe-fx+ j 1)))
(set! j (unsafe-fx+ j jump)))
(set! i p-1)
(set! j product)
(for ((k (in-range 1 q)))
(for ((k1 (in-range p-1)))
(for ((e1 (in-range 1 factor)))
(let* ((x (unsafe-vector-ref in (unsafe-fx+ i (unsafe-fx* e1 m))))
(x-real (real-part x))
(x-imag (imag-part x)))
(with-float (x-real x-imag)
(let ((w-real 1.0)
(w-imag 0.0))
(let ((tw (unsafe-vector-ref
trig
(unsafe-fx+ twiddle (unsafe-fx-
(unsafe-fx+
(unsafe-fx*
(unsafe-fx- e1 1) q) k) 1)))))
(if (= sign fft-forward)
(begin
(set! w-real (real-part tw))
(set! w-imag (imag-part tw)))
(begin
(set! w-real (real-part tw))
(set! w-imag (- (imag-part tw))))))
(vector-set!
out (unsafe-fx+ j (unsafe-fx* e1 p-1))
(make-rectangular
(unsafe-fl- (unsafe-fl* w-real x-real)
(unsafe-fl* w-imag x-imag))
(unsafe-fl+ (unsafe-fl* w-real x-imag)
(unsafe-fl* w-imag x-real))))))))
(set! i (unsafe-fx+ i 1))
(set! j (unsafe-fx+ j 1)))
(set! j (unsafe-fx+ j jump)))))
(define (dft-complex-forward data)
(dft-complex-transform data fft-forward))
(define (dft-complex-backward data)
(dft-complex-transform data fft-backward))
(define (dft-complex-inverse data)
(let ((result (dft-complex-backward data)))
(let* ((n (unsafe-vector-length result))
(norm (unsafe-fl/ 1.0 (unsafe-fx->fl n))))
(for ((i (in-range n)))
(let* ((datum (unsafe-vector-ref result i))
(datum-real (real-part datum))
(datum-imag (imag-part datum)))
(unsafe-vector-set!
result i
(make-rectangular
(unsafe-fl* norm datum-real)
(unsafe-fl* norm datum-imag))))))
result))
(define (dft-complex-transform data sign)
(with-float (sign)
(let* ((n (vector-length data))
(d-theta (unsafe-fl/ (unsafe-fl* sign 2*pi)
(unsafe-fx->fl n))))
(build-vector
n
(lambda (i)
(let-values
(((sum-real sum-imag exponent)
(for/fold ((sum-real 0.0)
(sum-imag 0.0)
(exponent 0))
((datum (in-vector data)))
(let* ((theta (unsafe-fl* d-theta (unsafe-fx->fl exponent)))
(w-real (unsafe-flcos theta))
(w-imag (unsafe-flsin theta))
(datum-real (real-part datum))
(datum-imag (imag-part datum)))
(with-float (datum-real datum-imag)
(values
(unsafe-fl+ sum-real
(unsafe-fl- (unsafe-fl* w-real datum-real)
(unsafe-fl* w-imag datum-imag)))
(unsafe-fl+ sum-imag
(unsafe-fl+ (unsafe-fl* w-real datum-imag)
(unsafe-fl* w-imag datum-real)))
(unsafe-fxmodulo (unsafe-fx+ exponent i) n)))))))
(make-rectangular sum-real sum-imag)))))))
(provide
fft-forward
fft-backward
(rename-out
(fft-complex-forward unchecked-fft-complex-forward)
(fft-complex-backward unchecked-fft-complex-backward)
(fft-complex-inverse unchecked-fft-complex-inverse)
(fft-complex-transform unchecked-fft-complex-transform)
(fft-complex-radix2-forward unchecked-fft-complex-radix2-forward)
(fft-complex-radix2-backward unchecked-fft-complex-radix2-backward)
(fft-complex-radix2-inverse unchecked-fft-complex-radix2-inverse)
(fft-complex-radix2-transform unchecked-fft-complex-radix2-transform)
(fft-complex-radix2-dif-forward unchecked-fft-complex-radix2-dif-forward)
(fft-complex-radix2-dif-backward unchecked-fft-complex-radix2-dif-backward)
(fft-complex-radix2-dif-inverse unchecked-fft-complex-radix2-dif-inverse)
(fft-complex-radix2-dif-transform unchecked-fft-complex-radix2-dif-transform)
(dft-complex-forward unchecked-dft-complex-forward)
(dft-complex-backward unchecked-dft-complex-backward)
(dft-complex-inverse unchecked-dft-complex-inverse)
(dft-complex-transform unchecked-dft-complex-transform)))
(provide/contract
(fft-complex-workspace?
(-> any/c boolean?))
(make-fft-complex-workspace
(-> exact-positive-integer? fft-complex-workspace?))
(fft-complex-forward
(->* ((vectorof complex?))
(#:workspace fft-complex-workspace?)
void?))
(fft-complex-backward
(->* ((vectorof complex?))
(#:workspace fft-complex-workspace?)
void?))
(fft-complex-inverse
(->* ((vectorof complex?))
(#:workspace fft-complex-workspace?)
void?))
(fft-complex-transform
(->* ((vectorof complex?) (one-of/c -1.0 1.0))
(#:workspace fft-complex-workspace?)
void?))
(fft-complex-radix2-forward
(-> (vectorof complex?) void?))
(fft-complex-radix2-backward
(-> (vectorof complex?) void?))
(fft-complex-radix2-inverse
(-> (vectorof complex?) void?))
(fft-complex-radix2-transform
(-> (vectorof complex?) (one-of/c -1.0 1.0) void?))
(fft-complex-radix2-dif-forward
(-> (vectorof complex?) void?))
(fft-complex-radix2-dif-backward
(-> (vectorof complex?) void?))
(fft-complex-radix2-dif-inverse
(-> (vectorof complex?) void?))
(fft-complex-radix2-dif-transform
(-> (vectorof complex?) (one-of/c -1.0 1.0) void?))
(dft-complex-forward
(-> (vectorof complex?) (vectorof complex?)))
(dft-complex-backward
(-> (vectorof complex?) (vectorof complex?)))
(dft-complex-inverse
(-> (vectorof complex?) (vectorof complex?)))
(dft-complex-transform
(-> (vectorof complex?) (one-of/c -1.0 1.0) (vectorof complex?))))