From 57305119e05559c1c37e903aef89cd43f44c42c9 Mon Sep 17 00:00:00 2001 From: Julian T Date: Tue, 11 Feb 2020 11:48:53 +0100 Subject: Added embedded assignment and python assignments --- sem4/embedded/emb_m2/emb_m2.ino | 233 +++++++++++++++++++++++++ sem4/embedded/emb_m2/myfloat_red.h | 57 ++++++ sem4/hpp/pythonAB/opg_a_b.ipynb | 347 +++++++++++++++++++++++++++++++++++++ 3 files changed, 637 insertions(+) create mode 100644 sem4/embedded/emb_m2/emb_m2.ino create mode 100644 sem4/embedded/emb_m2/myfloat_red.h create mode 100644 sem4/hpp/pythonAB/opg_a_b.ipynb diff --git a/sem4/embedded/emb_m2/emb_m2.ino b/sem4/embedded/emb_m2/emb_m2.ino new file mode 100644 index 0000000..c6a6a07 --- /dev/null +++ b/sem4/embedded/emb_m2/emb_m2.ino @@ -0,0 +1,233 @@ +#include "myfloat_red.h" + +// Number of numbers +#define NN 100 +#define PRINT_PRECISION 10 + +#define NEXT_OPG(c) Serial.print("\nOpgave "); Serial.println(c++); +#define AND_OPG(c) Serial.print("and "); Serial.println(c++); + +unsigned int opg_count = 1; + +void printmydoubarr(myfloat_type *arr, size_t len) { + Serial.print("[ "); + for(size_t i = 0; i < len; i++) { + Serial.print(myfloat2double( &arr[i] ), PRINT_PRECISION); + Serial.print(" "); + } + Serial.println("]"); +} + +void printarr(double *arr, size_t len) { + Serial.print("[ "); + for(size_t i = 0; i < len; i++) { + Serial.print(arr[i], PRINT_PRECISION); + Serial.print(" "); + } + Serial.println("]"); +} + +unsigned long factorial(unsigned int n) { + unsigned long res = 1; + for(unsigned int i = 2; i <= n; i++) { + res *= i; + } + + return res; +} + +double sineTayler(double x, unsigned int n) { + double sum = 0; + + for(unsigned int i = 0; i <= n; i++) { + sum += ((double)pow(-1, i) / (double)factorial(2 * i + 1)) * (double)pow(x, 2 * i + 1); + } + + + return sum; +} + +#define TAU 1.57079632679 +// After some trial and error the best TAYLORN was 2 +#define TAYLORN 2 +double sine(double x) { + + // Works by finding value in specific -pi/2 to pi/2 period. + int period = x / TAU; + + // One cycle of sin takes 4 periods. + // If 0 just return the sine approx x + // If 1 do negative sine approx on x - TAU + // If 2 do negative sine approx x + // If 3 do sine approx on period x - TAU + x = abs(x - TAU*period); + + double res = 12; + + switch( abs(period % 4) ) { + case 0: + res = sineTayler(x, TAYLORN); + break; + case 1: + res = -sineTayler(x - TAU, TAYLORN); + break; + case 2: + res = -sineTayler(x, TAYLORN); + break; + case 3: + res = sineTayler(x - TAU, TAYLORN); + break; + } + // Remember to multiply with sign + int sign = period < 0 ? -1 : 1; + + // Should never return because all cases are handled + return res * sign; + +} + +void mean_rel_error(double *da, myfloat_type *mda, size_t len, double *sign) { + // Calculate and print the relative error using the formula + // X - x + // ----- Where x is the calculated value and X is the real value( As real as double gets ) + // X + double errorsum = 0; + Serial.print("Rel Err : [ "); + for(size_t i = 0; i < len; i++) { + //Serial.println(errorsum, PRINT_PRECISION); + // Make space for sign + if( sign[i] < 0 ) { + Serial.print(" "); + } + // Handle devide by 0 + double error = da[i] ? abs(da[i] - myfloat2double(&mda[i])) / abs(da[i]) : 0; + Serial.print(error, PRINT_PRECISION); + Serial.print(" "); + + // Save sum for mean + errorsum += error; + } + Serial.println("]"); + + // Calculate mean + double mean = errorsum / len; + Serial.print("Mean Err: "); Serial.println(mean, PRINT_PRECISION); +} + +void setup() { + Serial.begin(115200); + + NEXT_OPG(opg_count); + // OPG1. Create some doubles + double da[NN]; + for(int i = 0; i < NN; i++) { + da[i] = ((double)random(-5000, 5000)) / 1000.0; + } + Serial.print("Original: "); printarr(da, NN); + + NEXT_OPG(opg_count); + // OPG2. Convert to mda + myfloat_type mda[NN]; + for(int i = 0; i < NN; i++) { + doub2mydouble(da[i], &mda[i]); + } + + Serial.print("Mydoub : "); printmydoubarr(mda, NN); + + NEXT_OPG(opg_count); + // OPG3. Calculate the mean relative error + mean_rel_error(da, mda, NN, da); + + { + NEXT_OPG(opg_count); + // OPG4. Compute some stuff + double da2[NN]; + for(int i = 0; i < NN; i++) { + da2[i] = da[i] * da[i]; + } + Serial.print("Orig pow: "); printarr(da2, NN); + + NEXT_OPG(opg_count); + // OPG5. + myfloat_type mda2[NN]; + for(int i = 0; i < NN; i++) { + // This thing sometimes does weird stuff -4.06*(-4.06) -> -16.00 + mult_float(&mda[i], &mda[i], &mda2[i]); + } + Serial.print("Mda pow: "); printmydoubarr(mda2, NN); + + NEXT_OPG(opg_count); + // OPG6. Doing the mean error thing + mean_rel_error(da2, mda2, NN, da); + } + + { + // OPG7. Measure execution time + NEXT_OPG(opg_count); + double a = da[1]; + unsigned long begin = micros(); + for(int i = 1; i < NN; i++) { + a *= da[i]; + } + + unsigned long time1 = micros() - begin; + Serial.print("Exe time: "); Serial.println(time1); + Serial.print("a : "); Serial.println(a); + + NEXT_OPG(opg_count); + // Convert to myfloat + myfloat_type f1; + doub2mydouble(a, &f1); + + Serial.print("f1 : "); Serial.println(myfloat2double(&f1)); + + NEXT_OPG(opg_count); + // OPG8-9. + begin = micros(); + for(int i = 0; i < NN; i++) { + // Multiply + myfloat_type f; + mult_float(&f1, &mda[i], &f); + + // Copy back + memcpy(&f1, &f, sizeof(myfloat_type)); + } + + unsigned long time2 = micros() - begin; + Serial.print("Exe time: "); Serial.println(time2); + Serial.print("f1 : "); Serial.println(myfloat2double(&f1)); + Serial.println("Overflow"); + + NEXT_OPG(opg_count); + // OPG10. Difference relative to biggest result + + unsigned long absdiff = abs( time1 - time2 ); + Serial.print("Abs diff: "); Serial.println(absdiff); + double reldiff = (double)absdiff / max(abs(time1), abs(time2)); + Serial.print("Rel diff: "); Serial.println(reldiff); + } + + NEXT_OPG(opg_count); + // OPG11. Impl sine + // Hardest value should be TAU as it's the furthest from center. + unsigned long begin = micros(); + double res = sine(TAU); + unsigned long time1 = micros() - begin; + Serial.print("own sin : "); Serial.println(res, PRINT_PRECISION); + + begin = micros(); + double correct = sin(TAU); + unsigned long time2 = micros() - begin; + Serial.print("ard sin : "); Serial.println(correct, PRINT_PRECISION); + + double error = correct ? abs(correct - res) / abs(correct) : 0; + Serial.print("rel err : "); Serial.println(error, PRINT_PRECISION); + + Serial.print("\nown time: "); Serial.println(time1); + Serial.print("ard time: "); Serial.println(time2); + +} + +void loop() { + +} diff --git a/sem4/embedded/emb_m2/myfloat_red.h b/sem4/embedded/emb_m2/myfloat_red.h new file mode 100644 index 0000000..b553233 --- /dev/null +++ b/sem4/embedded/emb_m2/myfloat_red.h @@ -0,0 +1,57 @@ +/* + Low level precision floating point lib + Author: Henrik Schiøler +*/ + +//low precision floating pt type +typedef struct myfloat +{ + signed char mantissa; + signed char exponent; +} myfloat_type; + + +//convert from double to low precision type +void doub2mydouble(double arg, myfloat_type *res) +{ + int exponent; + double temp; + exponent = ceil(log(abs(arg))/log(2)); //base 2 logarithm + temp=arg*pow(2,7-exponent); + res->mantissa = (signed char)temp; + res->exponent = exponent-7; +} + +//convert from low precision type to double +double myfloat2double(myfloat_type *arg1) +{ + double res = (double)(arg1->mantissa) * pow(2,arg1->exponent); + return res; +} + +//multiply to low precision types +void mult_float(myfloat_type *arg1,myfloat_type *arg2,myfloat_type *result) +{ + int temp; + unsigned char sign; + + sign=0x80 & ((unsigned char)arg1-> mantissa ^ (unsigned char)arg2-> mantissa); //find sign of result + + char i=0; + temp = (int)(arg1-> mantissa) * (int)(arg2-> mantissa); + + temp = temp & 0x7f00; //take away sign from product + + while(abs(temp)>128) + { + i++; + temp=temp>>1; + } + + result->mantissa = (unsigned char) temp; + + result->mantissa = result->mantissa | sign; //add recorded sign + + result->exponent = arg1->exponent + arg2->exponent + i; + +} diff --git a/sem4/hpp/pythonAB/opg_a_b.ipynb b/sem4/hpp/pythonAB/opg_a_b.ipynb new file mode 100644 index 0000000..7214643 --- /dev/null +++ b/sem4/hpp/pythonAB/opg_a_b.ipynb @@ -0,0 +1,347 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Opgaver til python A og B kursus" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Opgave 1\n", + "\n", + "Make a function that can appproximate an integral using mid point integration:\n", + "\n", + "$$ \\int_a^b f(x) dx \\approx h \\cdot \\sum_{i=0}^{n-1} f(a + 1/2 h + ih)$$\n", + "\n", + "1. Make a Python function midpointint(f, a, b, n): that performs the mid point integration where f is a scalar function that can be evaluated as f(x).\n", + "2. Compute closed form solutions of $\\int_a^b f(x) dx$ for your favorite $f$ e.g. exp, sin, cos\n", + "3. Validate you implementation with the closed form solution" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def midpointint(f, a, b, n): \n", + " \"\"\" \n", + " Approximates int(a to b) f(x) dx using midpoint integration. \n", + " \"\"\" \n", + " h = (b-a)/n \n", + " \n", + " # Create a generator and sum it \n", + " gen = (f(a + 1/2 * h + i * h) for i in range(0, n-1)) \n", + " \n", + " return h * sum(gen)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "I like $f(x) = e^x$ so that is what we will do. With $a = 0, b = 10$.\n", + "\n", + "$$\\int_0^{10} e^x dx = e^{10} -1 \\approx 22025$$" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "21806.207938916818" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import math\n", + "f = lambda x: math.exp(x)\n", + "midpointint(f, 0, 10, 1000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Trying a $f(x) = sin(x)$ with in same interval.\n", + "\n", + "$$\\int_0^{10} sin(x) dx \\approx 1.8391$$" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1.8444773816015885" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = lambda x: math.sin(x)\n", + "midpointint(f, 0, 10, 1000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Opgave 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make a Python script, which defines and prints the following integer arrays:\n", + "\n", + "$$ D_1 = \\left[\\begin{matrix}\n", + " 1 & 0 & 1 \\\\\n", + " 0 & 2 & 0 \\\\\n", + " 1 & 0 & 1\n", + "\\end{matrix}\\right]$$\n", + "\n", + "$$ D_2 = \\left[\\begin{matrix}\n", + " 1 & 8 & 1 \\\\\n", + " 8 & 2 & 8 \\\\\n", + " 1 & 8 & 1\n", + "\\end{matrix}\\right]$$\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[1, 8, 1], [8, 2, 8], [1, 8, 1]]" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "D1 = [\n", + " [1, 0, 1],\n", + " [0, 2, 0],\n", + " [1, 0, 1]\n", + "]\n", + "D2 = [\n", + " [1, 8, 1],\n", + " [8, 2, 8],\n", + " [1, 8, 1]\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the script further compute the following:\n", + "\n", + "1. Make a list of tuples containing indices to matrix elements $(D_2)_{i,j}$ where $(D_2)_{i,j} > 1$. Print the list and validate that it is correct." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# This can be done using list comprehention\n", + "[(i, j) for (i, r) in enumerate(D2) for (j, c) in enumerate(r) if c > 1]" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)]" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Or generators\n", + "def gen():\n", + " for (i, r) in enumerate(D2):\n", + " for (j, c) in enumerate(r):\n", + " if c > 1:\n", + " yield (i, j)\n", + " \n", + "list(gen())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2. Make a new matrix as:\n", + "$$ F = \\left[\\begin{matrix}\n", + "D_2 & D_2 \\\\\n", + "D_2 & D_2\n", + "\\end{matrix}\\right]$$\n", + "Print **F** and the shape of **F** as a tuple.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(6, 6)\n" + ] + }, + { + "data": { + "text/plain": [ + "[[1, 8, 1, 1, 8, 1],\n", + " [8, 2, 8, 8, 2, 8],\n", + " [1, 8, 1, 1, 8, 1],\n", + " [1, 8, 1, 1, 8, 1],\n", + " [8, 2, 8, 8, 2, 8],\n", + " [1, 8, 1, 1, 8, 1]]" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Multiplying list concatinates it with itself.\n", + "\n", + "F = [2*r for r in D2] * 2\n", + "\n", + "# outer inner\n", + "print((len(F), len(F[0])))\n", + "F" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "3. Compute and print the sum of all elements of the **F** matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "152" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum((c for r in F for c in r))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "4. Use Python to determine and print the number of ‘1’, ‘2’ and ‘8’ values in **F**." + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1: 16, 2: 4, 8: 16\n" + ] + } + ], + "source": [ + "# Not very efficient because we loop multiple times.\n", + "count = lambda n: sum((1 for r in F for c in r if c == n))\n", + "\n", + "print(f\"1: {count(1)}, 2: {count(2)}, 8: {count(8)}\")" + ] + } + ], + "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.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} -- cgit v1.2.3