aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2020-11-14 21:54:32 +0100
committerJulian T <julian@jtle.dk>2020-11-14 21:54:32 +0100
commitccf8359ed3a061cdff335b39ddb27a36b296e1d9 (patch)
tree3fc972ebd64f7d91b887c3c57b8b2a6ff6633de5
parent8d2aa424ff3de8601b0c051c824eb7638a60185b (diff)
Adds fft assignment, and fft implementation
-rw-r--r--sem5/sig/mm13/fft.c182
-rw-r--r--sem5/sig/mm13/python_solution.ipynb208
2 files changed, 390 insertions, 0 deletions
diff --git a/sem5/sig/mm13/fft.c b/sem5/sig/mm13/fft.c
new file mode 100644
index 0000000..dd93399
--- /dev/null
+++ b/sem5/sig/mm13/fft.c
@@ -0,0 +1,182 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <complex.h>
+#include <math.h>
+
+// Needed for option parsing
+#include <unistd.h>
+#include <string.h>
+
+#define MAX_FILE_SIZE 10000
+
+typedef uint16_t index_t;
+typedef complex double val_t;
+
+// Make a better version of this
+index_t reverse_bits(index_t i, unsigned fft_size)
+{
+ unsigned n = fft_size;
+ index_t reverse = 0;
+
+ while (n--) {
+ reverse <<= 1;
+ reverse |= i & 1;
+ i >>= 1;
+ }
+
+ return reverse;
+}
+
+val_t twiddle(index_t N, int k)
+{
+ val_t in = (2 * M_PI)/(double)N;
+ val_t res = cexp(-in * k * I);
+ return res;
+}
+
+void butterfly_single(val_t *buf, index_t a, index_t b, val_t twid)
+{
+ val_t common = twid * buf[b];
+
+ buf[b] = buf[a] - common;
+ buf[a] += common;
+}
+
+void butterfly(val_t *buf, unsigned depth, index_t n, index_t N)
+{
+ if (n == 2) {
+ butterfly_single(buf, 0, 1, twiddle(N, 0));
+ return;
+ }
+
+ n = n/2;
+ index_t step = pow(2, depth);
+
+ for (index_t i = 0; i < n; i++) {
+ butterfly_single(buf, i, i + n, twiddle(N, i * step));
+ }
+}
+
+void fft_inplace_recur(val_t *buf, unsigned depth, index_t n, index_t N)
+{
+ if (n > 2) {
+ index_t split = n/2;
+ fft_inplace_recur(buf, depth+1, split, N);
+ fft_inplace_recur(buf+split, depth+1, split, N);
+ }
+
+ butterfly(buf, depth, n, N);
+}
+
+val_t *fft(val_t *buf, size_t input_size, size_t N)
+{
+ // Check if power of two
+ if ((N & (N - 1)) != 0) {
+ fprintf(stderr, "FFT size %lu must be power of two\n", N);
+ return NULL;
+ }
+
+ val_t *tmpbuf = (val_t *) malloc(sizeof(val_t) * N);
+
+ // Reverse bits
+ int least = input_size < N ? input_size : N;
+ for (int i = 0; i < least; i++) {
+ index_t reverse = reverse_bits(i, log2(N));
+ tmpbuf[i] = buf[reverse];
+ }
+
+ // Padding
+ for (int i = 0; i < (int)N - least; i++) {
+ tmpbuf[i + least ] = 0;
+ }
+
+ fft_inplace_recur(tmpbuf, 0, N, N);
+ return tmpbuf;
+}
+
+void printhelp(char *prog) {
+ printf("Usage: %s [options]\n", prog);
+ puts("Options:");
+ puts(" -h This help screen");
+ puts(" -o <FILE> Write output to file");
+ puts(" -i <FILE> Read from file");
+ puts(" -f <SIZE> FFT size, must be power of two");
+ puts("");
+ printf("FILE should not have more than %d lines, with line seperated values.\n", MAX_FILE_SIZE);
+ puts("FILE will default to stdin/stdout");
+}
+
+int main(int argc, char **argv)
+{
+ int opt;
+ int optfft = -1;
+ char *input = NULL;
+ char *output = NULL;
+
+ while ((opt = getopt(argc, argv, "hi:o:f:")) != -1) {
+ switch(opt) {
+ case 'o':
+ output = strdup(optarg);
+ break;
+ case 'i':
+ input = strdup(optarg);
+ break;
+ case 'f':
+ optfft = strtol(optarg, NULL, 10);
+ break;
+ case 'h':
+ default:
+ printhelp(argv[0]);
+ return 0;
+ }
+ }
+
+ if (optfft == -1) {
+ fprintf(stderr, "FFT not specified\n");
+ printhelp(argv[0]);
+ return 1;
+ }
+
+ // Allocate storage
+ val_t *buf = (val_t *) malloc(sizeof(val_t) * MAX_FILE_SIZE);
+ if (buf == NULL) {
+ printf("Could not allocate mega array\n");
+ return 1;
+ }
+
+ FILE *f = stdin;
+ if (input != NULL) {
+ f = fopen(input, "r");
+ if (f == NULL) {
+ printf("Could not open file %s\n", input);
+ return 1;
+ }
+ }
+
+ double val;
+ int length;
+ for (length = 0; fscanf(f, "%lf\n", &val) != EOF; length++) {
+ buf[length] = (val_t) val;
+ //printf("Val: %lf + j%lf\n", creal(buf[ii]), cimag(buf[ii]));
+ }
+
+ val_t *res = fft(buf, length, optfft);
+ if (res == NULL) {
+ fprintf(stderr, "Error calculating fft\n");
+ return 1;
+ }
+
+ f = stdout;
+ if (output != NULL) {
+ f = fopen(output, "w");
+ if (f == NULL) {
+ printf("Could not open file %s\n", input);
+ return 1;
+ }
+ }
+
+ for (int ii = 0; ii < optfft; ii++) {
+ fprintf(f, "%lf%+lfj\n", creal(res[ii]), cimag(res[ii]));
+ }
+}
diff --git a/sem5/sig/mm13/python_solution.ipynb b/sem5/sig/mm13/python_solution.ipynb
new file mode 100644
index 0000000..c748080
--- /dev/null
+++ b/sem5/sig/mm13/python_solution.ipynb
@@ -0,0 +1,208 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from scipy.io import loadmat\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "dataorig = loadmat(\"signal.mat\")\n",
+ "dataorig = dataorig[\"s\"]\n",
+ "np.savetxt(\"signal.txt\", dataorig)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Opgave 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([229.889581 +0.j , 283.940097 -3.840915j,\n",
+ " 253.027989+10.126097j, ..., 267.103152+32.035438j,\n",
+ " 253.027989-10.126097j, 283.940097 +3.840915j])"
+ ]
+ },
+ "execution_count": 45,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Genereret med ./a.out -i signal.txt -f 1024 -o output1.txt\n",
+ "fft = np.loadtxt(\"output1.txt\", dtype=complex)\n",
+ "fft"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 46,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[<matplotlib.lines.Line2D at 0x7fbbdf0b6af0>]"
+ ]
+ },
+ "execution_count": 46,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 432x288 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "step = 8000/len(fft)\n",
+ "x = np.arange(len(fft)) * step\n",
+ "plt.plot(x, np.abs(fft))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Opgave 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 47,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[<matplotlib.lines.Line2D at 0x7fbbdf0233d0>]"
+ ]
+ },
+ "execution_count": 47,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 432x288 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "step = 8000/len(fft)\n",
+ "x = np.arange(len(fft)) * step\n",
+ "plt.xlim(0, 100)\n",
+ "plt.plot(x, np.abs(fft))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Opgave 3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 42,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Genereret med ./a.out -i signal.txt -f 8192 -o output2.txt\n",
+ "fft = np.loadtxt(\"output2.txt\", dtype=complex)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[<matplotlib.lines.Line2D at 0x7fbbdf336880>]"
+ ]
+ },
+ "execution_count": 44,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 432x288 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "step = 8000/len(fft)\n",
+ "x = np.arange(len(fft)) * step\n",
+ "plt.xlim(0, 100)\n",
+ "plt.plot(x, np.abs(fft))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}