Last active
November 2, 2025 14:07
-
-
Save Luiz-Monad/55c62cffcdcb0d796e6fabeba686690a to your computer and use it in GitHub Desktop.
FFT APL
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
| Its kind of easy to implement DFT in APL! | |
| FFT β { βΊ = 1 : β΅ | |
| f β * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| T β X β΄β¨ 2 ,β¨ NΓ·2 | |
| EvenOdd β β Β¨ βͺ βΏ T | |
| Y1 β {βΊ + f Γ β΅} / EvenOdd | |
| Y2 β {βΊ - f Γ β΅} / EvenOdd | |
| (βΊ-1)β βΊβΊ β΅ | |
| } | |
| β I loved APL! | |
| β The circular function is beautiful : Negative exponent in alpha (first parameter) gives you complex numbers! (http://www.jsoftware.com/papers/satn40.htm) | |
| β Generally, I hate working with arrays in C, itβs very cumbersome. But in APL, arrays are beautiful. | |
| β But the coolest part is the implementation of the diadic trigonometric functions. | |
| β This language is so good for simple mathematics, now I know why such a beautiful language didnβt work in the boring 'real life'. | |
| β Yesterday, I was studying the Fourier transform, then they mentioned APL, and then I had a dream. | |
| β Hum, letβs implement it! | |
| β Decimation-in-time radix-2 (CooleyβTukey) | |
| β EqI: | |
| β $X_k = \sum_{n=0}^{N-1} x_n e^{ \frac{ -2 \pi i }{N} nk }$ (fig0) | |
| β Iβm not going to include all the intermediary steps, watch this video ( https://www.youtube.com/watch?v=htCj9exbGo0 ), I ignored the 'C' nonsense because it didnβt help, also ( https://www.youtube.com/watch?v=1mVbZLHLaf0 ) helps too. | |
| β Separate into even and odd. | |
| β $X_k = \sum_{m=0}^{N/2-1} x_{2m} e^{ \frac{ -2 \pi i }{N} (2m)k } + \sum_{m=0}^{N/2-1} x_{2m+1} e^{ \frac{ -2 \pi i }{N} (2m+1)k }$ (fig1) | |
| β Extract common factor. | |
| β EqII: | |
| β $e^{ \frac{ -2 \pi i }{N} k }$ (fig2) | |
| β But first, letβs convert the common factor to APL. (APL is read from right to left and has no operator precedence, except for parentheses) | |
| β e^{ \frac{ -2 \pi i }{N} k } | |
| * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| β Letβs test with k=1 and N=32 | |
| 0.980785JΒ―0.19509 | |
| β Exactly what Wolfram tells us ( https://www.wolframalpha.com/input/?i=e%5E(+(-2+%5Cpi+i)+%2F(32)) ) | |
| β βΒ―1 is the same as β2Οi. | |
| β -2Ο is Β―2Γβ1. | |
| β β is the natural logarithm. | |
| β β is the circular trigonometric function. β1 is Ο. | |
| β Oh, I never noticed this before in Mathematics, makes totally sense! (the circular function is so beautiful and much more useful than the traditional sin/cos/arc functions in Math) | |
| β What we got so far. | |
| β $X_k = \sum_{m=0}^{N/2-1} x_{2m} e^{ \frac{ -2 \pi i }{N} (2m)k } + \sum_{m=0}^{N/2-1} x_{2m+1} e^{ \frac{ -2 \pi i }{N} (2m+1)k }$ (fig3) | |
| β Extracting common factor. | |
| β EqIII: | |
| β $X_k = \sum_{m=0}^{N/2-1} x_{2m} e^{ \frac{ -2 \pi i }{N/2} mk } + e^{ \frac{ -2 \pi i }{N} k } \sum_{m=0}^{N/2-1} x_{2m+1} e^{ \frac{ -2 \pi i }{N/2} mk }$ (fig4) | |
| β Letβs simplify (replacing from Eq I). | |
| β $X_k = Even_k + e^{ \frac{ -2 \pi i }{N} k } Odd_k $ (fig5) | |
| β Even_k and Odd_k are recursive FFTs themselves (recursion and FP, take that, divide and conquer!) | |
| β Now we only have simple equations and array accesses, nice! | |
| β As per Nyquist theorem, we know that we only need half of the periodicity as the function will repeat values. | |
| β $Even_{k+\frac{N}{2}} = Even_k$ (fig6) (Odd is exactly the same) | |
| β So N canβ be reduced to N/2. | |
| β The equations take the following form. | |
| β EqIV: | |
| β $\newline X_k = Even_k + factor * Odd_k \: for \, 1 <= k <= N/2 | |
| β \newline X_k = Even_{k-N/2} + factor * Odd_{(k-N/2)} \: for \, N/2 <= k <= N $ (fig7) | |
| β $Even_k$ and $Odd_k$ are recursive calls in EqI, as they were replaced in EqIII. | |
| β Now letβs use symmetry ( https://youtu.be/1mVbZLHLaf0?t=516 ) | |
| β So plugging $k+\frac{N}{2}$ into EqII and knowing the symmetry (tiddle factor). | |
| β $e^{ \frac{ -2 \pi i }{N} (k+\frac{N}{2}) }$ (fig8) | |
| β The equation becomes: | |
| β EqV: | |
| β $-e^{ \frac{ -2 \pi i }{N} k }$ (fig9) | |
| β Replacing EqV back into EqIV. | |
| β $\newline X_k = Even_k + factor * Odd_k | |
| β \newline X_k = Even_k - factor * Odd_k$ (fig10) | |
| β Now we can plug it into APL: | |
| β the factor | |
| f β * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| β the recursion | |
| T β FFT k-NΓ·2 | |
| β equation | |
| β O[k] β T[k] + f Γ T[k+NΓ·2] β even | |
| β O[k+NΓ·2] β T[k] - f Γ T[k+NΓ·2] β odd | |
| β Letβs test it. | |
| X β β³8 | |
| s β 8 | |
| N β 8 | |
| k β 1 | |
| f β * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| T[k] + f Γ T[k+NΓ·2] | |
| 4.53553JΒ―3.53553 | |
| T[k] - f Γ T[k+NΓ·2] | |
| Β―2.53553J3.53553 | |
| β Perfect! ( https://www.wolframalpha.com/input/?i=1%2B(e%5E(+(+-2+%5Cpi+i+)%2F(8)+1+))*5 ) | |
| β Now letβs write to use APLβs array primitives. | |
| β First, we need to split the sequence into odd and even and then apply the function recursively. | |
| β Reshape X to be NΓ·2 rows per 2 cols matrix. | |
| T β X β΄β¨ 2 ,β¨ NΓ·2 | |
| β then apply columns into FFT. | |
| FFT β {β΅} β dummy | |
| Even β FFT 1β·[2]T β or T[;1] | |
| Odd β FFT 2β·[2]T β or T[;2] | |
| β combined | |
| EvenOdd β Even Odd | |
| β Then execute the summation of k. | |
| β βΊ is even, β΅ is odd | |
| β βΊ β T[k] β β΅ β T[k+NΓ·2] | |
| β for every row do the thing inside {}. | |
| β We just replaced the variables | |
| Y1 β {βΊ + f Γ β΅} / EvenOdd | |
| Y2 β {βΊ - f Γ β΅} / EvenOdd | |
| β The final result is Y1 Y2 combined. | |
| Y β Y1 Y2 | |
| β The result is 4 complex numbers for Y1 and 4 more for Y2. | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β β2.41421JΒ―1.41421 5.82843JΒ―2.82843 9.24264JΒ―4.24264 12.6569JΒ―5.65685β | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β βΒ―0.414214J1.41421 0.171573J2.82843 0.757359J4.24264 1.34315J5.65685β | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β Letβs create a shortcut now. | |
| β Apply reduce to union then map FFT with dieresis. | |
| EvenOdd β FFT Β¨ βͺ βΏ T | |
| β Letβs fix a mistake, f should be the term from EqII and k is a parameter. | |
| β We also need the index given. | |
| omg β { * (βΒ―1) Γ Β―2 Γ β΅Γ·N } | |
| EvenOdd β FFT Β¨ βͺ βΏ T | |
| Ix β { β΅ (β³β΄β΅ β΄β¨ β΄β΅) } Β¨ EvenOdd | |
| Y1 β { βΊ + β΅ Γ omg β΅ } / {β΅ Ix} Β¨ EvenOdd | |
| Y2 β { βΊ - β΅ Γ omg β΅ } / {β΅ Ix} Β¨ EvenOdd | |
| β So far | |
| X β β³8 | |
| s β 8 | |
| N β 8 | |
| k β 1 | |
| omg β { * (βΒ―1) Γ Β―2 Γ β΅Γ·N } | |
| T β X β΄β¨ 2 ,β¨ NΓ·2 | |
| FFT β {β΅} | |
| EvenOdd β FFT Β¨ βͺ βΏ T | |
| Y1 β { βΊ + β΅ Γ omg k } / EvenOdd | |
| Y2 β { βΊ - β΅ Γ omg k } / EvenOdd | |
| β Now just to build the recursion. | |
| FFT β { βΊ = 1 : β΅ | |
| f β * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| T β X β΄β¨ 2 ,β¨ NΓ·2 | |
| EvenOdd β β Β¨ βͺ βΏ T | |
| Y1 β {βΊ + f Γ β΅} / EvenOdd | |
| Y2 β {βΊ - f Γ β΅} / EvenOdd | |
| (βΊ-1)β βΊβΊ β΅ | |
| } | |
| β Todo: butterfly optimization. | |
| β Todo: using matrices instead of iteration ( https://youtu.be/1mVbZLHLaf0?t=3348 ). | |
| β Todo: more optimization after reading this ( http://cnx.org/contents/ulXtQbN7@15/Implementing-FFTs-in-Practice ). |
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
| [Math/APL] (warning: walls of text and equations) | |
| I loved APL ! | |
| The circular function is beautiful : Exponential negativo em alpha (primeiro parametro) te dΓ‘ numeros complexos ! ( http://www.jsoftware.com/papers/satn40.htm ) | |
| Geralmente eu odeio trabalhar com arrays em C, Γ© muito cumbersome. Mas em APL arrays sΓ£o lindos. | |
| Mas o mais legal mesmo Γ© a implementaΓ§Γ£o das funΓ§Γ΅es trigonometricas diadicas. | |
| This language is so good for simple mathematics, now I know why such a beaultiful language didn't work in the boring 'real life'. | |
| Ontem estava estudando a transformada de Fourier, dai falaram de APL, dai eu tive um sonho. | |
| Hum, lets implement it ! | |
| β Decimation-in-time radix-2 ( CooleyβTukey ) | |
| β EqI: | |
| β $X_k = \sum_{n=0}^{N-1} x_n e^{ \frac{ -2 \pi i }{N} nk }$ (fig0) | |
| β Eu nΓ£o vou colocar todos os passos intermediarios, assista esse video ( https://www.youtube.com/watch?v=htCj9exbGo0 ), I ignored the 'C' bullshit because it didn't help, also ( https://www.youtube.com/watch?v=1mVbZLHLaf0 ) helps too. | |
| β Separar entre pares e impares. | |
| β $X_k = \sum_{m=0}^{N/2-1} x_{2m} e^{ \frac{ -2 \pi i }{N} (2m)k } + \sum_{m=0}^{N/2-1} x_{2m+1} e^{ \frac{ -2 \pi i }{N} (2m+1)k }$ (fig1) | |
| β Extrair fator comum. | |
| β EqII: | |
| β $e^{ \frac{ -2 \pi i }{N} k }$ (fig2) | |
| β Mas antes vamos converter o fator comum para APL. (APL se le da direita para esquerda e nΓ£o tem precedencia de operador, exceto parens) | |
| β e^{ \frac{ -2 \pi i }{N} k } | |
| * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| β Lets test with k=1 and N=32 | |
| 0.980785JΒ―0.19509 | |
| β Exactly what Wolfram tell us ( https://www.wolframalpha.com/input/?i=e%5E(+(-2+%5Cpi+i)+%2F(32)) ) | |
| β βΒ―1 Γ© o mesmo que β2Οi. | |
| β -2Ο Γ© Β―2Γβ1. | |
| β β Γ© o logaritimo natural. | |
| β β Γ© a funΓ§Γ£o circular trigonometrica. β1 Γ© Ο. | |
| β Oh, eu nunca tinha percebido isto antes na Matematica, makes totally sense! (proof left as an exercise for the reader) | |
| β What we got so far. | |
| β $X_k = \sum_{m=0}^{N/2-1} x_{2m} e^{ \frac{ -2 \pi i }{N} (2m)k } + \sum_{m=0}^{N/2-1} x_{2m+1} e^{ \frac{ -2 \pi i }{N} (2m+1)k }$ (fig3) | |
| β Extracting commom factor. | |
| β EqIII: | |
| β $X_k = \sum_{m=0}^{N/2-1} x_{2m} e^{ \frac{ -2 \pi i }{N/2} mk } + e^{ \frac{ -2 \pi i }{N} k } \sum_{m=0}^{N/2-1} x_{2m+1} e^{ \frac{ -2 \pi i }{N/2} mk }$ (fig4) | |
| β Lets simplify (replacing from Eq I). | |
| β $X_k = Even_k + e^{ \frac{ -2 \pi i }{N} k } Odd_k $ (fig5) | |
| β Even_k and Odd_k are recursive FFTs themselves (recursion and FP, take that, divide and conquer!) | |
| β Now we only have simple equations, and array accesses, nice! | |
| β As per niquist theorem we know that we only need half of the periodicity as the function will repeat values. | |
| β $Even_{k+\frac{N}{2}} = Even_k$ (fig6) (Odd is exactly the same) | |
| β EntΓ£o o N pode ser reduzido para N/2. | |
| β As equaΓ§Γ΅es ficam da seguinte forma. | |
| β EqIV: | |
| β $\newline X_k = Even_k + factor * Odd_k \: for \, 1 <= k <= N/2 | |
| β \newline X_k = Even_{k-N/2} + factor * Odd_{(k-N/2)} \: for \, N/2 <= k <= N $ (fig7) | |
| β $Even_k$ e $Odd_k$ sΓ£o recursive calls em EqI, pois foi substituidos em EqIII. | |
| β Agora vamos usar a simetria ( https://youtu.be/1mVbZLHLaf0?t=516 ) | |
| β EntΓ£o plugando $k+\frac{N}{2}$ na EqII e sabendo da simetria (tiddle factor). | |
| β $e^{ \frac{ -2 \pi i }{N} (k+\frac{N}{2}) }$ (fig8) | |
| β A equaΓ§Γ£o fica: | |
| β EqV: | |
| β $-e^{ \frac{ -2 \pi i }{N} k }$ (fig9) | |
| β Substituindo devolta EqV em EqIV. | |
| β $\newline X_k = Even_k + factor * Odd_k | |
| β \newline X_k = Even_k - factor * Odd_k$ (fig10) | |
| β Agora podemos enfiar em APL: | |
| β the factor | |
| f β * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| β the recursion | |
| T β FFT k-NΓ·2 | |
| β equation | |
| β O[k] β T[k] + f Γ T[k+NΓ·2] β even | |
| β O[k+NΓ·2] β T[k] - f Γ T[k+NΓ·2] β odd | |
| β Lets test it. | |
| X β β³8 | |
| s β 8 | |
| N β 8 | |
| k β 1 | |
| f β * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| T[k] + f Γ T[k+NΓ·2] | |
| 4.53553JΒ―3.53553 | |
| T[k] - f Γ T[k+NΓ·2] | |
| Β―2.53553J3.53553 | |
| β Perfect! ( https://www.wolframalpha.com/input/?i=1%2B(e%5E(+(+-2+%5Cpi+i+)%2F(8)+1+))*5 ) | |
| Agora vamos escrever para usar os primitivos de array de APL. | |
| β Primeiro precisamos cortar a sequencia em impar e par e depois aplicar a function recursivamente. | |
| β Reshape X to be NΓ·2 rows per 2 cols matrix. | |
| T β X β΄β¨ 2 ,β¨ NΓ·2 | |
| β then apply columns into FFT. | |
| FFT β {β΅} β dummy | |
| Even β FFT 1β·[2]T β or T[;1] | |
| Odd β FFT 2β·[2]T β or T[;2] | |
| β combined | |
| EvenOdd β Even Odd | |
| β Dai executa a somatoria de k. | |
| β βΊ is even, β΅ is odd | |
| β βΊ β T[k] β β΅ β T[k+NΓ·2] | |
| β for every row do thing inside {}. | |
| β we just replaced the variables | |
| Y1 β {βΊ + f Γ β΅} / EvenOdd | |
| Y2 β {βΊ - f Γ β΅} / EvenOdd | |
| β The final result is Y1 Y2 combined. | |
| Y β Y1 Y2 | |
| β O resultado sΓ£o 4 numeros complexos para Y1 e mais 4 para Y2. | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β β2.41421JΒ―1.41421 5.82843JΒ―2.82843 9.24264JΒ―4.24264 12.6569JΒ―5.65685β | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β βΒ―0.414214J1.41421 0.171573J2.82843 0.757359J4.24264 1.34315J5.65685β | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β Vamos fazer um curto circuito agora. | |
| β apply reduce to union then and map FFT with dieresis. | |
| EvenOdd β FFT Β¨ βͺ βΏ T | |
| β Lets fix a mistake, f deveria ser o termo da EqII e o k Γ© parametro. | |
| β We also need the index given | |
| omg β { * (βΒ―1) Γ Β―2 Γ β΅Γ·N } | |
| EvenOdd β FFT Β¨ βͺ βΏ T | |
| Ix β { β΅ (β³β΄β΅ β΄β¨ β΄β΅) } Β¨ EvenOdd | |
| Y1 β { βΊ + β΅ Γ omg β΅ } / {β΅ Ix} Β¨ EvenOdd | |
| Y2 β { βΊ - β΅ Γ omg β΅ } / {β΅ Ix} Β¨ EvenOdd | |
| β So far | |
| X β β³8 | |
| s β 8 | |
| N β 8 | |
| k β 1 | |
| omg β { * (βΒ―1) Γ Β―2 Γ β΅Γ·N } | |
| T β X β΄β¨ 2 ,β¨ NΓ·2 | |
| FFT β {β΅} | |
| EvenOdd β FFT Β¨ βͺ βΏ T | |
| Y1 β { βΊ + β΅ Γ omg k } / EvenOdd | |
| Y2 β { βΊ - β΅ Γ omg k } / EvenOdd | |
| β Agora sΓ³ construir a recursao. | |
| FFT β { βΊ = 1 : β΅ | |
| f β * (βΒ―1) Γ Β―2 Γ kΓ·N | |
| T β X β΄β¨ 2 ,β¨ NΓ·2 | |
| EvenOdd β β Β¨ βͺ βΏ T | |
| Y1 β {βΊ + f Γ β΅} / EvenOdd | |
| Y2 β {βΊ - f Γ β΅} / EvenOdd | |
| (βΊ-1)β βΊβΊ β΅ | |
| } | |
| β Todo: butterfly optimization. | |
| β Todo: using matrices instead of iteration ( https://youtu.be/1mVbZLHLaf0?t=3348 ) . | |
| β Todo: more optimization after reading this ( http://cnx.org/contents/ulXtQbN7@15/Implementing-FFTs-in-Practice ) | |
| Tudo porque eu estava estudando Quantum Physics e precisei de reestudar Calculo, este video aqui foi a inspiraΓ§Γ£o ( https://www.youtube.com/watch?v=r18Gi8lSkfM ). (There's crazy people like me studying Calculus for fun) (Why study only one thing when you can study 2 or 3 things at the same time) | |
| Proximo episodio: Eigenvalues ! just kidding |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment