This commit is contained in:
Maximilian Eibl 2025-04-09 10:22:44 +02:00
commit 96ff5392c8
330 changed files with 28300 additions and 0 deletions

11
exercise1/.clang-format Normal file
View File

@ -0,0 +1,11 @@
---
BasedOnStyle: LLVM
---
Language: Cpp
AllowShortFunctionsOnASingleLine: Empty
DerivePointerAlignment: false
PointerAlignment: Left
ColumnLimit: 120
TabWidth: 4
IndentWidth: 2
...

20
exercise1/.clangd Normal file
View File

@ -0,0 +1,20 @@
InlayHints:
Enabled: No
ParameterNames: Yes
DeducedTypes: No
---
CompileFlags:
Add:
- -Wall
- -Wno-unused-function
- -Wno-unused-variable
---
If:
PathMatch: [.*\.c, .*\.h]
CompileFlags:
Add: [-std=c11]
---
If:
PathMatch: [.*\.cpp, .*\.hpp]
CompileFlags:
Add: [-std=c++20]

5
exercise1/.ctests Normal file
View File

@ -0,0 +1,5 @@
task1_py
task1_c
task1_cpp
task2
task3

View File

@ -0,0 +1,5 @@
info_python.txt
info_c.txt
info_cpp.txt
task2.main.cpp
task3.cpp

16
exercise1/.gitattributes vendored Normal file
View File

@ -0,0 +1,16 @@
## source: https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.h text
*.hpp text
*.c text
*.cpp text
*.py text
*.ipynb text
*.md text
*.txt text
*.csv text

360
exercise1/.gitignore vendored Normal file
View File

@ -0,0 +1,360 @@
# custom
*.csv
*.png
build
doc
.cache
.vscode
.idea
# https://github.com/github/gitignore/blob/main/CMake.gitignore
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
# ttps://github.com/github/gitignore/blob/main/C.gitignore
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# https://github.com/github/gitignore/blob/main/C%2B%2B.gitignore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# source: https://github.com/github/gitignore/blob/main/Python.gitignore
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# jetbrain IDEs: https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# VSCODE source: https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix

4
exercise1/.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "modules"]
path = modules
url = https://sgit.iue.tuwien.ac.at/360050/modules
branch = main

59
exercise1/CMakeLists.txt Normal file
View File

@ -0,0 +1,59 @@
cmake_minimum_required(VERSION 3.20)
# define project metadata
project(exercise3 LANGUAGES CXX C
DESCRIPTION "exercise1"
HOMEPAGE_URL "https://sgit.iue.tuwien.ac.at/360050/exercise1")
# setting required language standards
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
set(CMAKE_C_EXTENSIONS OFF)
# misc settings
# avoid ctest dashboard targets
set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1)
# generate a compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# make all symbols visible on windows (which is default on unix)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# options
option(BUILD_TESTING "enable testing with ctest" ON)
# testing
include(CTest)
# get/setup dependencies
include_directories(modules)
# include own targets
find_package(Python3 COMPONENTS Interpreter REQUIRED)
add_test(NAME task1_py COMMAND ${Python3_EXECUTABLE} task1.test.py WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(task1_c task1.test.c)
add_test(NAME task1_c COMMAND task1_c WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(task1_cpp task1.test.cpp)
add_test(NAME task1_cpp COMMAND task1_cpp WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_custom_target(task1)
add_dependencies(task1 task1_c task1_cpp)
add_executable(task2 task2.cpp)
add_test(NAME task2 COMMAND task2 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set_property(TEST task2 PROPERTY PROPERTY_REGULAR_EXPRESSION "6633")
add_executable(task3 task3.cpp task3.test.cpp)
add_test(NAME task3 COMMAND task3 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})

19
exercise1/README.md Normal file
View File

@ -0,0 +1,19 @@
# Hausübung 1 (3 Punkte)
**Ausgabe**: Donnerstag 7. März 2024, vormittags.
**Abgabe bis**: Montag 18. März 2024, Ende des Tages.
**Abgabe via**: git-Repository mit dem Namen **`exercise1`** auf unserem git-Server https://sgit.iue.tuwien.ac.at
Details zum Abgabeprozess via `git` finden Sie hier: https://sgit.iue.tuwien.ac.at/360050/git
# Aufgabenstellung
In dieser Hausübung werden folgende Themen erstmalig einfliessen:
- Konfiguration der benötigten Werkzeuge
- Implementierung/Kompilierung/Ausführen eines lauffähigen Programms
- Einfache Funktionen (ohne Bedingungen/Verzweigungen) mit Fundamentalen Typen als Parameter und Rückgabewert
**Die genaue Beschreibung und Anforderungen finden Sie in [`main.ipynb`](main.ipynb) und im Quellcode.**

View File

@ -0,0 +1 @@
-Imodules

View File

@ -0,0 +1,4 @@
os: Windows 11 10.0.22631
py: CPython 3.12.2
np: numpy 1.26.4
mpl: matplotlib 3.8.3

204
exercise1/main.ipynb Normal file
View File

@ -0,0 +1,204 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 1: Konfigurieren und Testen der eigenen Umgebung (1 Punkt)\n",
"\n",
"1. Konfigurieren Sie Ihr eigenes System: https://sgit.iue.tuwien.ac.at/360050/setup\n",
"\n",
"2. Nachdem Sie Ihre Konfiguration abgeschlossen haben, testen Sie Ihre Konfiguration indem Sie folgenden drei mitgelieferte Tests ausführen:\n",
"\n",
"\t- [task1.test.py](task1.test.py) testet die Python-Konfiguration. \n",
"\t- [task1.test.c](task1.test.c) testet die C-Konfiguration.\n",
"\t- [task1.test.cpp](task1.test.cpp) testet die C++-Konfiguration."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Kompilieren/Ausführen \n",
"\n",
"Mittels manueller Aufrufe (`gcc/g++/python`):\n",
"```shell\n",
"# prepare folder\n",
"mkdir build\n",
"# compile for task1\n",
"gcc -Imodules -std=c11 -g task1.test.c -o build/task1_c.exe\n",
"g++ -Imodules -std=c++20 -g task1.test.cpp -o build/task1_cpp.exe\n",
"# run tests for task1\n",
"python task1.test.py # produces \"info_python.txt\"\n",
"./build/task1_c.exe # produces \"info_c.txt\"\n",
"./build/task1_cpp.exe # produces \"info_cpp.txt\"\n",
"```\n",
"\n",
"Alternativ mittels *CMake* (optional):\n",
"```shell\n",
"# prepare compilation\n",
"cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug\n",
"# compile for task1\n",
"cmake --build build --config Debug --target task1\n",
"# run tests for task1\n",
"ctest --test-dir build -C Debug -R task1\n",
"```\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 2: Ein eigenes kleines C++-Programm (1 Punkt)\n",
"\n",
"Erstellen Sie ein lauffähiges *Ein-Dateien-Programm* das folgende Struktur aufweist:\n",
"\n",
"- Einbinden benötigter Header-Dateien aus der Standardbibliothek, z.B.:\n",
"\t```cpp\n",
"\t#include <iostream> // std::cout|endl\n",
"\t#include <...>\n",
"\t```\n",
"- Definition/Implementierung einer eigenen Funktion, z.B.:\n",
"\t```cpp\n",
"\tint sum(...){\n",
"\t ...\n",
"\t}\n",
"\t``` \n",
"- Definition/Implementierung einer `main`-Funktion (Einstiegspunkt für jedes lauffähige Programm), die Ihre selbest geschriebene Funktion verwendet und die berechneten Ergebnisse in der Konsole ausgibt, z.B.:\n",
"\t```cpp\n",
"\tint main(){\n",
"\t ...\n",
"\t auto res = sum(...)\t\n",
"\t std::cout << res << std::endl;\n",
"\t return 0;\n",
"\t}\n",
"\t``` "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Eine genaue Beschreibung und Anforderungen finden Sie in [task2.main.cpp](task2.main.cpp)\n",
"- Ihre Implementierung erfolgt ebenfalls in [task2.main.cpp](task2.main.cpp)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Kompilieren/Ausführen \n",
"\n",
"Mittels manueller Aufrufe (`gcc/g++/python`):\n",
"```shell\n",
"# prepare folder\n",
"mkdir build\n",
"# compile for task2\n",
"g++ -std=c++20 -g task2.main.cpp -o build/task2.exe\n",
"# run test (your output will be parsed when graded)\n",
"./build/task2.exe\n",
"```\n",
"\n",
"Alternativ mittels *CMake* (optional):\n",
"```shell\n",
"# prepare compilation\n",
"cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug\n",
"# compile for task2\n",
"cmake --build build --config Debug --target task2\n",
"# run tests for task2\n",
"ctest --test-dir build -C Debug -R task2\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 3: Einfache Funktionen ohne Verzweigungen (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Implementieren Sie folgende Funktionen:\n",
"\n",
"```cpp\n",
"double add(double x, double y, double z);\n",
"double mul(double x, double y, double z);\n",
"double frac(double x, double y);\n",
"double mean(double x, double y, double z);\n",
"double squared(double x);\n",
"double cubed(double x);\n",
"double eval(double x, double a, double b, double c);\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklarationen und eine genaue Beschreibung und Anforderungen finden Sie in [`task3.hpp`](task3.hpp)\n",
"- Ihre Implementierung erfolgt in [`task3.cpp`](task3.cpp)\n",
"- Die zugeordneten Tests finden Sie in [`task3.test.cpp`](task3.test.cpp)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Kompilieren/Ausführen \n",
"\n",
"Mittels manueller Aufrufe (`gcc/g++/python`):\n",
"```shell\n",
"# prepare folder\n",
"mkdir build\n",
"# compile for task3\n",
"g++ -std=c++20 -g task3.cpp task3.test.cpp -o build/task3.exe\n",
"# run test\n",
"./build/task3.exe\n",
"```\n",
"\n",
"Alternativ mittels *CMake* (optional):\n",
"```shell\n",
"# prepare compilation\n",
"cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug\n",
"# compile for task3\n",
"cmake --build build --config Debug --target task3\n",
"# run tests for task3\n",
"ctest --test-dir build -C Debug -R task3\n",
"```"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.6.15"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

1
exercise1/modules Submodule

@ -0,0 +1 @@
Subproject commit b8ce24c87fc76396de465b2573e19909fd10cf13

27
exercise1/task1.test.c Normal file
View File

@ -0,0 +1,27 @@
/// @file
/// @brief Task1: tests (support for C11 standard)
#include <assert.h> // assert
#include <stdio.h> // FILE
#include <stdlib.h> // EXIT_FAILURE|EXIT_SUCCESS
#include "iue-io/ccsv.h" // https://sgit.iue.tuwien.ac.at/360050/modules
int main(void) {
FILE* stream = fopen("info_c.txt", "w");
if (stream == NULL)
return EXIT_FAILURE;
fprintf(stream, "This compilation unit was compiled\n");
fprintf(stream, " - on %s at %s\n", __DATE__, __TIME__);
fprintf(stream, " - using the C language standard %li\n", __STDC_VERSION__);
fprintf(stream, " - the main-function was present in this file: %s\n", __FILE__);
fclose(stream);
assert(__STDC_VERSION__ >= 201112L);
printf("task1.test.c: all asserts passed\n");
return EXIT_SUCCESS;
}

35
exercise1/task1.test.cpp Normal file
View File

@ -0,0 +1,35 @@
/// @file
/// @brief Task1: tests (support for C++20 standard)
#include <cassert> // assert
#include <filesystem> // std::filesystem::path
#include <fstream> // std::ofstream
#include <iostream> // std::cout|endl
#include <sstream> // std::istringstream
#include <version> // https://en.cppreference.com/w/cpp/utility/feature_test
#include "iue-io/csv.hpp" // https://sgit.iue.tuwien.ac.at/360050/modules
int main() {
std::ostringstream oss;
oss << "This compilation unit was compiled" << std::endl;
oss << " - on " << __DATE__ << " at " << __TIME__ << std::endl;
oss << " - using the C++ language standard " << __cplusplus << std::endl;
oss << " - the main-function was present in this file: " << __FILE__ << std::endl;
std::filesystem::path filename = "info_cpp.txt";
std::ofstream ofs(filename);
ofs.exceptions(std::ios::failbit);
ofs << oss.str();
assert(__cplusplus >= 202002L);
assert(__cpp_lib_filesystem >= 201703L);
assert(__cpp_concepts >= 201907L);
std::cout << "task1.test.cpp: all asserts passed" << std::endl;
return 0;
}

49
exercise1/task1.test.py Normal file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
""" Task1: tests (support for python, numpy and matplotlib) """
import platform
def os_info():
""" Collects basic info on the operating system and logs it to a file 'os_info.txt'. """
os_type = platform.system()
os_rel = platform.release()
os_ver = platform.version()
return f"os: {os_type} {os_rel} {os_ver}\n"
def python_info():
""" Obtains information on Python installation in use and logs it to a file 'python_info.txt'. """
python_ver = platform.python_version()
python_impl = platform.python_implementation()
return f"py: {python_impl} {python_ver}\n"
import numpy
def numpy_info():
""" Obtains information on the numpy package in use and logs it to a file 'numpy_info.txt'. """
numpy_name = numpy.__name__
numpy_ver = numpy.__version__
return f"np: {numpy_name} {numpy_ver}\n"
import matplotlib
def matplotlib_info():
""" Obtains information on the matplotlib package in use and logs it to a file 'matplotlib_info.txt'. """
matplotlib_name = matplotlib.__name__
matplotlib_ver = matplotlib.__version__
return f"mpl: {matplotlib_name} {matplotlib_ver}\n"
import unittest
import os
class Test(unittest.TestCase):
def test_python_env(self):
with open("info_python.txt", "w") as f:
f.write(os_info())
f.write(python_info())
f.write(numpy_info())
f.write(matplotlib_info())
if __name__ == '__main__':
unittest.main()

25
exercise1/task2.cpp Normal file
View File

@ -0,0 +1,25 @@
/// @file
/// @brief Task2: "single-file" excutable C++ program
#include <iostream>
/// @brief Calculate the sum of two integer values
/// @param a first integer value
/// @param b second integer value
/// @return Sum of the two integer values
int sum(int a, int b) {
return a + b;
}
/// @brief main function (entry point) conducting the following tasks in this order
/// - create two local variables holding the integer values 33 and 6600
/// - call your function 'sum' and provide the prepared variables as arguments to the call
/// - capture the result of your function call in a local variable and print it to the console
int main() {
int a = 33;
int b = 6600;
int result = sum(a, b);
std::cout << "The sum of " << a << " and " << b << " is " << result << std::endl;
}

65
exercise1/task3.cpp Normal file
View File

@ -0,0 +1,65 @@
/// @file
/// @brief Task3: implementation
#include "task3.hpp" // add|mul|frac|mean|squared|cubed|eval
/// @todo Include standard library headers as needed
/// @brief Calculates the sum of three values
/// @param x 1st value
/// @param y 2nd value
/// @param z 3rd value
/// @return Sum of the three values
double add(double x, double y, double z) {
return x+y+z;
}
/// @brief Calculates the product of three values
/// @param x 1st value
/// @param y 2nd value
/// @param z 3rd value
/// @return Product of the three values
double mul(double x, double y, double z) {
return x*y*z;
}
/// @brief Calculates the fraction of two values
/// @param x 1st value
/// @param y 2nd value
/// @return Fraction of x divided by y
double frac(double x, double y) {
return x/y;
}
/// @brief Calculates the average (arithmetic mean) of three values
/// @param x 1st value
/// @param y 2nd value
/// @param z 3rd value
/// @return Average of the three values
double mean(double x, double y, double z) {
return (x+y+z)/3;
}
/// @brief Calculates the square of a value
/// @param x Value
/// @return Square of x
double squared(double x) {
return x*x;
}
/// @brief Calculates the third power of a value
/// @param x Value
/// @return Cube of x
double cubed(double x) {
return x*x*x;
}
/// @brief Evaluates a polynomial 'f(x) = a*x^2 + b*x + c'
/// @param x Variable
/// @param a Coefficient
/// @param b Coefficient
/// @param c Coefficient
/// @return Value of the polynomial at x
double eval(double x, double a, double b, double c) {
return a*x*x + b*x + c;
}

49
exercise1/task3.hpp Normal file
View File

@ -0,0 +1,49 @@
/// @file
/// @brief Task3: function declarations
#pragma once
/// @brief Calculates the sum of three values
/// @param x 1st value
/// @param y 2nd value
/// @param z 3rd value
/// @return Sum of the three values
double add(double x, double y, double z);
/// @brief Calculates the product of three values
/// @param x 1st value
/// @param y 2nd value
/// @param z 3rd value
/// @return Product of the three values
double mul(double x, double y, double z);
/// @brief Calculates the fraction of two values
/// @param x 1st value
/// @param y 2nd value
/// @return Fraction of x divided by y
double frac(double x, double y);
/// @brief Calculates the average (arithmetic mean) of three values
/// @param x 1st value
/// @param y 2nd value
/// @param z 3rd value
/// @return Average of the three values
double mean(double x, double y, double z);
/// @brief Calculates the square of a value
/// @param x Value
/// @return Square of x
double squared(double x);
/// @brief Calculates the third power of a value
/// @param x Value
/// @return Cube of x
double cubed(double x);
/// @brief Evaluates a polynomial 'f(x) = a*x^2 + b*x + c'
/// @param x Variable
/// @param a Coefficient
/// @param b Coefficient
/// @param c Coefficient
/// @return Value of the polynomial at x
double eval(double x, double a, double b, double c);

44
exercise1/task3.test.cpp Normal file
View File

@ -0,0 +1,44 @@
/// @file
/// @brief Test for Task3
#include "task3.hpp" // add|mul|frac|mean|squared|cubed|eval
#include <cassert> // assert
#include <cmath> // std::abs
#include <iostream> // std::cout|endl
int main() {
{ // testing function 'add'
double res = add(1, 2, -3);
assert(std::abs(res - 0.0) < 1e-7);
}
{ // testing function 'mul'
double res = mul(2, 3, 4);
assert(std::abs(res - 24.0) < 1e-7);
}
{ // testing function 'frac'
double res = frac(1, 3);
assert(std::abs(res - 1.0 / 3.0) < 1e-7);
}
{ // testing function 'mean'
double res = mean(10, 90, -10);
assert(std::abs(res - 30.0) < 1e-7);
}
{ // testing function 'squared'
double res = squared(3);
assert(std::abs(res - 9.0) < 1e-7);
}
{ // testing function 'cubed'
double res = cubed(3);
assert(std::abs(res - 27.0) < 1e-7);
}
{ // testing function 'cubed'
double res = eval(10.0, 3, -30, 77);
assert(std::abs(res - 77) < 1e-7);
}
std::cout << "task3.test.cpp: all asserts passed" << std::endl;
return 0;
}

10
exercise10/.clang-format Normal file
View File

@ -0,0 +1,10 @@
---
BasedOnStyle: LLVM
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
ColumnLimit: 120
TabWidth: 4
IndentWidth: 2
...

25
exercise10/.clangd Normal file
View File

@ -0,0 +1,25 @@
# debug: clangd --check=modules/iue-io/ccsv.h
# debug: clangd --check=task1.hpp
# debug: clangd --check=task1.test.cpp
InlayHints:
Enabled: No
ParameterNames: Yes
DeducedTypes: No
---
CompileFlags:
Add:
# - --target=x86_64-w64-windows-gnu
# - --target=x86_64-pc-linux-gnu
- -Wall
- -Wno-unused-function
- -Wno-unused-variable
---
If:
PathMatch: [.*\.c, .*\.h]
CompileFlags:
Add: [-std=c11]
---
If:
PathMatch: [.*\.cpp, .*\.hpp]
CompileFlags:
Add: [-std=c++20]

3
exercise10/.ctests Normal file
View File

@ -0,0 +1,3 @@
task1
task2
task3

View File

@ -0,0 +1,3 @@
task1.main.c
task2.c
task3.main.c

16
exercise10/.gitattributes vendored Normal file
View File

@ -0,0 +1,16 @@
## source: https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.h text
*.hpp text
*.c text
*.cpp text
*.py text
*.ipynb text
*.md text
*.txt text
*.csv text

358
exercise10/.gitignore vendored Normal file
View File

@ -0,0 +1,358 @@
# custom
build
doc
.cache
.vscode
.idea
# https://github.com/github/gitignore/blob/main/CMake.gitignore
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
# ttps://github.com/github/gitignore/blob/main/C.gitignore
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# https://github.com/github/gitignore/blob/main/C%2B%2B.gitignore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# source: https://github.com/github/gitignore/blob/main/Python.gitignore
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# jetbrain IDEs: https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# VSCODE source: https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix

4
exercise10/.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "modules"]
path = modules
url = https://sgit.iue.tuwien.ac.at/360050/modules
branch = main

71
exercise10/CMakeLists.txt Normal file
View File

@ -0,0 +1,71 @@
cmake_minimum_required(VERSION 3.20)
# define project metadata
project(exercise10 LANGUAGES C
DESCRIPTION "exercise10"
HOMEPAGE_URL "https://sgit.iue.tuwien.ac.at/360050/exercise10")
# setting required language standards
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
set(CMAKE_C_EXTENSIONS OFF)
# misc settings
# avoid ctest dashboard targets
set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1)
# generate a compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# make all symbols visible on windows (which is default on unix)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# options
option(BUILD_TESTING "enable testing with ctest" ON)
# testing
include(CTest)
# find math library and link to all targets
find_library(MATH_LIBRARY m)
link_libraries(${MATH_LIBRARY})
# get/setup dependencies
include_directories(modules)
# include own targets
add_executable(task1 task1.main.c)
target_link_libraries(task1 PRIVATE ${MATH_LIBRARY})
add_test(NAME task1 COMMAND task1 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set_property(TEST task1 PROPERTY PASS_REGULAR_EXPRESSION ".*10.*")
add_executable(task2 task2.c task2.test.c)
target_link_libraries(task2 PRIVATE ${MATH_LIBRARY})
add_test(NAME task2 COMMAND task2 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(task3_main task2.c task3.main.c)
add_test(NAME task3_popt_fail COMMAND task3_main --left rrev4x4.csv --right matrix4x2.csv WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_test(NAME task3_inpath_fail COMMAND task3_main --left hui.csv --right matrix4x2.csv --out result.csv WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_test(NAME task3_dims_fail COMMAND task3_main --left matrix4x2.csv --right rrev4x4.csv --out result.csv WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_test(NAME task3_outpath_fail COMMAND task3_main --left rrev4x4.csv --right matrix4x2.csv --out hui/result.csv WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_test(NAME task3_csv_fail COMMAND task3_main --left rrev4x4.csv --right invalid.csv --out matrix4x2_rrow.csv WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_test(NAME task3_rrow COMMAND task3_main --left rrev4x4.csv --right matrix4x2.csv --out matrix4x2_rrow.csv WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_test(NAME task3_rcol COMMAND task3_main --left matrix4x2.csv --right rcol2x2.csv --out matrix4x2_rcols.csv WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(task3_test task3.test.c)
add_test(NAME task3_test COMMAND task3_test WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set_tests_properties(task3_popt_fail task3_inpath_fail task3_dims_fail task3_outpath_fail task3_csv_fail PROPERTIES WILL_FAIL TRUE)
set_tests_properties(task3_test PROPERTIES DEPENDS task3_rrow)
set_tests_properties(task3_test PROPERTIES DEPENDS task3_rcol)
add_custom_target(task3)
add_dependencies(task3 task3_test task3_main)

19
exercise10/README.md Normal file
View File

@ -0,0 +1,19 @@
# Hausübung 10 (3 Punkte)
**Ausgabe**: Donnerstag 6. Juni 2024, vormittags.
**Abgabe bis**: Montag 17. Juni 2024, Ende des Tages.
**Abgabe via**: git-Repository mit dem Namen **`exercise10`** auf unserem git-Server https://sgit.iue.tuwien.ac.at
Details zum Abgabeprozess via `git` finden Sie hier: https://sgit.iue.tuwien.ac.at/360050/git
# Aufgabenstellung
In dieser Hausübung werden folgende Themen erstmalig einfliessen:
- C: Kommandozeilen-Optionen
- C: Speicherung multidimensionaler (hier zweidimensional) Felder in einem kontinuierlichen Speicherbereich (hier *row-major*-Ordnung)
- C: Matrixoperationen basierend auf einer *row-major*-Ordnung
**Die genaue Beschreibung und Anforderungen finden Sie in [`main.ipynb`](main.ipynb) und im Quellcode.**

View File

@ -0,0 +1 @@
-Imodules

5
exercise10/invalid.csv Normal file
View File

@ -0,0 +1,5 @@
// matrix4x2.csv: a 4x2 matrix, not using '#' to indicate comments, non float data
not-a-number;11;12
not-a-number;21;22
not-a-number;31;32
not-a-number;41;42
1 // matrix4x2.csv: a 4x2 matrix, not using '#' to indicate comments, non float data
2 not-a-number;11;12
3 not-a-number;21;22
4 not-a-number;31;32
5 not-a-number;41;42

203
exercise10/main.ipynb Normal file
View File

@ -0,0 +1,203 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 1: Ein eigenes kleines C-Programm (*row-major layout*) (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Erstellen Sie in [`task1.main.c`](task1.main.c) ein lauffähiges Ein-Dateien-Programm das folgende Struktur aufweist:\n",
"\n",
"- Einbinden benötigter Header-Dateien aus der Standardbibliothek, z.B.:\n",
"\t```c\n",
"\t#include <limits.h> // INT_MAX\n",
"\t#include <stdio.h> // printf\n",
"\t...\n",
"\t```\n",
"- Definition/Implementierung einer eigenen Funktion, z.B.:\n",
"\t```cpp\n",
"\tsize_t func(...) {\n",
"\t ...\n",
"\t}\n",
"\t``` \n",
"- Definition/Implementierung einer `main`-Funktion, die Ihre selbst geschriebene Funktion verwendet, z.B.:\n",
"\t```cpp\n",
"\tint main(){\n",
"\t ...\t\n",
"\t int res = func(...);\n",
"\t ...\t\n",
"\t return 0;\n",
"\t}\n",
"\t``` \n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Eine genaue Beschreibung und Anforderungen finden Sie in [`task1.main.c`](task1.main.c)\n",
"- Ihre Implementierung erfolgt ebenfalls in [`task1.main.c`](task1.main.c)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 2: Funktionalität für zweidimensionale Felder mit kontinuierlichem Speicherlayout (hier: *row-major order*) (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Gegeben ist eine Struktur `struct Matrix`, die eine *M x N*-Matrix mit kontinuierlichem Speicherlayout darstellt, ebenso gegeben sind drei yugehörige Funktionen:<>\n",
"```c\n",
"struct Matrix {\n",
" double* data; ///< pointer to a dynamically allocated contiguous memory block of size m*n\n",
" size_t m; ///< number of rows (first dimension)\n",
" size_t n; ///< number of colmns (second dimension)\n",
"};\n",
"\n",
"struct Matrix matrix_init(size_t m, size_t n, const double *data);\n",
"void matrix_print(const struct Matrix* mat);\n",
"void matrix_clear(struct Matrix* mat);\n",
"```\n",
"Sie implementieren weitere vier Funktionen, die die Funktionalität erweitern:\n",
"\n",
"```c\n",
"// todo: implement\n",
"struct Matrix matrix_zeros(size_t m, size_t n);\n",
"struct Matrix matrix_identity(size_t n);\n",
"void matrix_transpose(struct Matrix* mat);\n",
"void matrix_mult(const struct Matrix* a, const struct Matrix* b, struct Matrix* c);\n",
"```\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Strukturen/Funktionen und eine genaue Beschreibung und Anforderungen finden Sie in [`task2.h`](task2.h)\n",
"- Ihre Implementierung erfolgt in [`task2.c`](task2.c)\n",
"- Die zugeordneten Tests finden Sie in [`task2.test.c`](task2.test.c) "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 3: Kommandozeilen-Programm Matrix/Matrix-Multiplikation (1 Punkt)\n",
"\n",
"Sie implementieren ein Programm, das \n",
"\n",
"- zwei Matrizen aus zwei `.csv`-Dateien einließt, \n",
"- das Produkt der Matrizen berechnet (Matrix/Matrix-Multiplikation), und\n",
"- das Ergebnis wiederum als `.csv`-Datei speichert.\n",
"\n",
"Die Dateinamen werden mittels der Kommandozeile übergeben.\n",
"\n",
"Das Programm bricht in folgenden Sitationen ab:\n",
"\n",
"- unzureichende Argumente\n",
"- invalide Dateipfade\n",
"- Fehler beim Einlesen der Dateien\n",
"- inkompatible Matrix-Dimensionen"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklaration und eine genaue Beschreibung und Anforderungen finden Sie in [`task3.main.c`](task3.main.c)\n",
"- Ihre Implementierung erfolgt ebenfalls in [`task3.main.c`](task3.main.c)\n",
"- Getestet wird Ihr Programm, indem es mit verschiedenen Parametern in der Kommandozeile aufgerufen wird (siehe auch [`CMakeLists.txt`](CMakeLists.txt) und im nächsten Abschnitt).\n",
"- Nachfolgend werden die Ausgabedateien der letzten beiden Aufrufe mit den Tests in [`task3.test.c`](task3.test.c) überprüft."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Kompilieren/Testen\n",
"\n",
"So testen Sie Ihre Implementierung (direkter Aufruf von `gcc`):\n",
"\n",
"```shell\n",
"# prepare\n",
"mkdir build\n",
"# compile\n",
"gcc -g -std=c11 task1.main.c -o build/task1 -lm\n",
"gcc -g -Imodules -std=c11 task2.c task2.test.c -o build/task2 -lm\n",
"gcc -g -Imodules -std=c11 task2.c task3.main.c -o build/task3_main -lm\n",
"gcc -g -Imodules -std=c11 task3.test.c -o build/task3_test -lm\n",
"\n",
"# run tests\n",
"./build/task1\n",
"./build/task2\t\n",
"./build/task3_main --left rrev4x4.csv --right matrix4x2.csv # expect runtime fail: invalid arguments\n",
"./build/task3_main --left hui.csv --right matrix4x2.csv --out result.csv # expect runtime fail: invalid input filename\n",
"./build/task3_main --left matrix4x2.csv --right rrev4x4.csv --out result.csv # expect runtime fail: invalid matrix dimensions\n",
"./build/task3_main --left rrev4x4.csv --right matrix4x2.csv --out hui/result.csv # expect runtime fail: invalid output filename\n",
"./build/task3_main --left rrev4x4.csv --right invalid.csv --out matrix4x2_rrow.csv # expect runtime fail: invalid line in invalid.csv\n",
"./build/task3_main --left rrev4x4.csv --right matrix4x2.csv --out matrix4x2_rrow.csv # expected succeed and to generate matrix4x2_rrow.csv\n",
"./build/task3_main --left matrix4x2.csv --right rcol2x2.csv --out matrix4x2_rcols.csv # expected succeed and to generate matrix4x2_rcols.csv\n",
"./build/task3_test # tests the contents of the generated files matrix4x2_rrow.csv and matrix4x2_rcols.csv\n",
"```\n",
"\n",
"Alternativ (mittels CMake-Configuration):\n",
"\n",
"```shell\n",
"# prepare\n",
"cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug # Windows\n",
"cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -D CMAKE_C_FLAGS=\"-fsanitize=address\" # Linux\n",
"# compile\n",
"cmake --build build --config Debug --target task1\n",
"cmake --build build --config Debug --target task2\n",
"cmake --build build --config Debug --target task3\n",
"cmake --build build --config Debug # all\n",
"# run tests\n",
"ctest --test-dir build -C Debug -R task1 --verbose\n",
"ctest --test-dir build -C Debug -R task2 --verbose\n",
"ctest --test-dir build -C Debug -R task3 --verbose\n",
"ctest --test-dir build -C Debug # all\n",
"``` \n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.6.15"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

5
exercise10/matrix4x2.csv Normal file
View File

@ -0,0 +1,5 @@
# matrix4x2.csv: a 4x2 matrix
11;12
21;22
31;32
41;42
1 # matrix4x2.csv: a 4x2 matrix
2 11;12
3 21;22
4 31;32
5 41;42

View File

@ -0,0 +1,4 @@
1.200000000000000000e+001;1.100000000000000000e+001
2.200000000000000000e+001;2.100000000000000000e+001
3.200000000000000000e+001;3.100000000000000000e+001
4.200000000000000000e+001;4.100000000000000000e+001
1 1.200000000000000000e+001 1.100000000000000000e+001
2 2.200000000000000000e+001 2.100000000000000000e+001
3 3.200000000000000000e+001 3.100000000000000000e+001
4 4.200000000000000000e+001 4.100000000000000000e+001

View File

@ -0,0 +1,4 @@
4.100000000000000000e+001;4.200000000000000000e+001
3.100000000000000000e+001;3.200000000000000000e+001
2.100000000000000000e+001;2.200000000000000000e+001
1.100000000000000000e+001;1.200000000000000000e+001
1 4.100000000000000000e+001 4.200000000000000000e+001
2 3.100000000000000000e+001 3.200000000000000000e+001
3 2.100000000000000000e+001 2.200000000000000000e+001
4 1.100000000000000000e+001 1.200000000000000000e+001

1
exercise10/modules Submodule

@ -0,0 +1 @@
Subproject commit 33515ac3ade8381f1336333051f85c7f63c8705c

3
exercise10/rcol2x2.csv Normal file
View File

@ -0,0 +1,3 @@
# rcol2x2: reverses column order if right multiplied with any Mx2 matrix
0; 1
1; 0
1 # rcol2x2: reverses column order if right multiplied with any Mx2 matrix
2 0; 1
3 1; 0

5
exercise10/rrev4x4.csv Normal file
View File

@ -0,0 +1,5 @@
# rrev4x4.csv: reverses row order if left multiplied to a 4xN matrix
0; 0; 0; 1
0; 0; 1; 0
0; 1; 0; 0
1; 0; 0; 0
1 # rrev4x4.csv: reverses row order if left multiplied to a 4xN matrix
2 0; 0; 0; 1
3 0; 0; 1; 0
4 0; 1; 0; 0
5 1; 0; 0; 0

67
exercise10/task1.main.c Normal file
View File

@ -0,0 +1,67 @@
/// @file
/// @brief Task1: "single-file" executable C program
/// @todo Include C standard library headers, as needed
/// @todo Implement a function 'max_column_sum' according to the description below:
/// The function receives a "m x n"-matrix holding signed integer values stored in a contiguous block of memory using
/// row-major layout. Specifically it receives these arguments
/// - number of rows m
/// - number of columns n
/// - pointer to a contiguous block of memory containing m*n signed integer values
/// - row-major storage order is used, access of element (i,j) -> data[j + n*i]
/// The function then calculates the maximum column sum, i.e. the maximum sum of values in one column of the matrix, and
/// returns this value.
/// @todo Implement a 'main' function conducting the following tasks in this order:
/// - construct three local variables containing the following values:
/// - an integer value for the number of rows: 2
/// - an integer value for the number of columns: 4
/// - an array of integer values to be interpreted as a 2x4 matrix in row-major layout containing these values:
/// {5, -2, -12, 4, 1, 3, -5, 6}
/// - use your function to calculate the maximum column sum of the 2x4 matrix specified by your three local variables
/// - print the result to the console
/// @file
/// @brief Task1: "single-file" executable C program
#include <stdio.h>
/// Function to calculate the maximum column sum of a matrix
int max_column_sum(int m, int n, int data[]) {
int max_sum = data[0]; // Initialize with first element
// Loop through each column
for (int j = 1; j < n; j++) {
int current_sum = 0;
// Loop through each row in the current column
for (int i = 0; i < m; i++) {
// Calculate sum of elements in current column
current_sum += data[j + n * i];
}
// Update max_sum if current sum is greater
if (current_sum > max_sum) {
max_sum = current_sum;
}
}
return max_sum;
}
int main() {
// Define matrix dimensions
int rows = 2;
int cols = 4;
// Define matrix data in row-major order
int data[] = {5, -2, -12, 4, 1, 3, -5, 6};
// Calculate maximum column sum
int max_column_sum_value = max_column_sum(rows, cols, data);
// Print the result
printf("Maximum column sum: %d\n", max_column_sum_value);
return 0;
}

102
exercise10/task2.c Normal file
View File

@ -0,0 +1,102 @@
/// @file
/// @brief Task2: function definitions
#include "task2.h" // struct Matrix, matrix_mult
#include <stddef.h> // size_t
#include <stdio.h> // printf
#include <stdlib.h> // malloc, free
/// @todo Include C standard library headers as needed
/// @note This implementation is provided as declared and specified in task2.h
struct Matrix matrix_init(size_t m, size_t n, const double* data) {
struct Matrix res = {.data = malloc(sizeof(double) * m * n), .m = m, .n = n};
double* A = res.data;
for (size_t i = 0; i != m * n; ++i)
A[i] = data[i];
return res;
}
/// @note This implementation is provided as declared and specified in task2.h
void matrix_print(const struct Matrix* mat) {
size_t M = mat->m;
size_t N = mat->n;
const double* A = mat->data;
for (size_t m = 0; m != M; ++m) {
for (size_t n = 0; n != N; ++n)
printf("%lf ", A[n + N * m]);
printf("\n");
}
printf("\n");
}
/// @note This implementation is provided as declared and specified in task2.h
void matrix_clear(struct Matrix* mat) {
free(mat->data);
mat->m = 0;
mat->n = 0;
}
/// @brief Initializes an matrix with zeros
/// @param m first dimension of the matrix
/// @param n first dimension of the matrix
struct Matrix matrix_zeros(size_t m, size_t n){
double* data = malloc(sizeof(double) * m * n);
for (size_t i = 0; i != m * n; ++i)
data[i] = 0;
return matrix_init(m, n, data);
}
/// @brief Initializes a square identity matrix
/// @param n dimension of the identity matrix
struct Matrix matrix_identity(size_t n){
double* data = malloc(sizeof(double) * n * n);
for (size_t i = 0; i != n; ++i)
for (size_t j = 0; j != n; ++j)
data[j + n * i] = i == j ? 1 : 0;
return matrix_init(n, n, data);
}
/// @brief Transposes a matrix
/// @param mat Matrix to be transposed
/// @note this function might swap/replace the block of memory owned by the matrix
void matrix_transpose(struct Matrix* mat){
size_t m = mat->m;
size_t n = mat->n;
double* data = malloc(sizeof(double) * m * n);
for (size_t i = 0; i != m; ++i)
for (size_t j = 0; j != n; ++j)
data[i + m * j] = mat->data[j + n * i];
free(mat->data);
mat->data = data;
mat->m = n;
mat->n = m;
}
/// @brief Performs a matrix-matrix mutliplication: a*b = c
/// @a first matrix (left factor)
/// @b second matrix (right factor)
/// @c Result of the multiplication is stored in this Matrix:
/// - the dimensions of this matrix must be 'a.m x b.n' when calling this function
/// - the values will be overwritten with the result of the multiplication
void matrix_mult(const struct Matrix* a, const struct Matrix* b, struct Matrix* c){
size_t m = a->m;
size_t n = a->n;
size_t p = b->n;
double* data = malloc(sizeof(double) * m * p);
for (size_t i = 0; i != m; ++i)
for (size_t j = 0; j != p; ++j){
double sum = 0;
for (size_t k = 0; k != n; ++k)
sum += a->data[k + n * i] * b->data[j + p * k];
data[j + p * i] = sum;
}
free(c->data);
c->data = data;
c->m = m;
c->n = p;
}

51
exercise10/task2.h Normal file
View File

@ -0,0 +1,51 @@
/// @file
/// @brief Task2: Structure definitions and function declarations
#pragma once
#include <stddef.h> // size_t
/// @brief Two-dimensional matrix with 'm' rows and 'n' columns.
/// @note: the values ares stored in a contiguous block in memory in row-major layout
/// @note: row-major storage order is used, access of element (i,j) -> data[j + n*i]
struct Matrix {
double* data; ///< pointer to a dynamically allocated contiguous memory block fitting m*n values
size_t m; ///< number of rows (first dimension)
size_t n; ///< number of columns (second dimension)
};
/// @brief Initalize a matrix from the values in a buffer
/// @param m first dimension of the matrix
/// @param n second dimension of the matrix
/// @param data contiguous memory holding the values to copy (in row-major format)
struct Matrix matrix_init(size_t m, size_t n, const double* data);
/// @brief Prints a Matrix to the console
/// @param mat Matrix to be printed
void matrix_print(const struct Matrix* mat);
/// @brief Resets a matrix (deallocates memory and sets its size to 0 x 0)
/// @param mat Matrix to be reset
void matrix_clear(struct Matrix* mat);
/// @brief Initializes an matrix with zeros
/// @param m first dimension of the matrix
/// @param n first dimension of the matrix
struct Matrix matrix_zeros(size_t m, size_t n);
/// @brief Initializes a square identity matrix
/// @param n dimension of the identity matrix
struct Matrix matrix_identity(size_t n);
/// @brief Transposes a matrix
/// @param mat Matrix to be transposed
/// @note this function might swap/replace the block of memory owned by the matrix
void matrix_transpose(struct Matrix* mat);
/// @brief Performs a matrix-matrix mutliplication: a*b = c
/// @a first matrix (left factor)
/// @b second matrix (right factor)
/// @c Result of the multiplication is stored in this Matrix:
/// - the dimensions of this matrix must be 'a.m x b.n' when calling this function
/// - the values will be overwritten with the result of the multiplication
void matrix_mult(const struct Matrix* a, const struct Matrix* b, struct Matrix* c);

220
exercise10/task2.test.c Normal file
View File

@ -0,0 +1,220 @@
/// @file
/// @brief Task2: tests
#include "task2.h" // struct Matrix, matrix_mult
#include "modules/iue-num/numerics.h" // iuenum_isclose
#include <assert.h> // assert
#include <stdbool.h> // bool, true, false
#include <stdio.h> // printf
// helper function
bool isclose(const struct Matrix* a, const struct Matrix* b) {
if (a->m != b->m)
return false;
if (a->n != b->n)
return false;
for (size_t i = 0; i != a->m; ++i)
for (size_t j = 0; j != a->n; ++j)
if (!iuenum_isclose(a->data[j + a->n * i], b->data[j + b->n * i]))
return false;
return true;
}
int main() {
{ // testing 'matrix_zeros' for 3x3
struct Matrix mat = matrix_zeros(3, 3);
double data[3][3] = {
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
};
struct Matrix expected = matrix_init(3, 3, &data[0][0]);
assert(isclose(&mat, &expected));
matrix_clear(&mat);
matrix_clear(&expected);
}
{ // testing 'matrix_zeros' for 4x3
struct Matrix mat = matrix_zeros(4, 3);
double data[4][3] = {
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
};
struct Matrix expected = matrix_init(4, 3, &data[0][0]);
assert(isclose(&mat, &expected));
matrix_clear(&mat);
matrix_clear(&expected);
}
{ // testing 'matrix_identity' for 3x3
double data_expected[3][3] = {
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
};
struct Matrix expected = matrix_init(3, 3, &data_expected[0][0]);
struct Matrix mat = matrix_identity(3);
// matrix_print(&mat);
assert(isclose(&mat, &expected));
// matrix_print(&expected);
matrix_clear(&mat);
matrix_clear(&expected);
}
{ // testing 'matrix_identity' for 4x4
double data_expected[4][4] = {
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
};
struct Matrix expected = matrix_init(4, 4, &data_expected[0][0]);
struct Matrix mat = matrix_identity(4);
// matrix_print(&mat);
assert(isclose(&mat, &expected));
// matrix_print(&expected);
matrix_clear(&mat);
matrix_clear(&expected);
}
{ // testing 'matrix_transpose' of a 3x3 identity
struct Matrix mat = matrix_identity(3);
double data_expected[3][3] = {
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
};
struct Matrix expected = matrix_init(3, 3, &data_expected[0][0]);
// matrix_print(&mat);
matrix_transpose(&mat);
// matrix_print(&mat);
// matrix_print(&expected);
assert(isclose(&mat, &expected));
matrix_clear(&mat);
matrix_clear(&expected);
}
{ // testing 'matrix_transpose' for 4x2
double data[4][2] = {
{11, 12},
{21, 22},
{31, 32},
{41, 42},
};
struct Matrix mat = matrix_init(4, 2, &data[0][0]);
double data_expected[2][4] = {
{11, 21, 31, 41},
{12, 22, 32, 42},
};
struct Matrix expected = matrix_init(2, 4, &data_expected[0][0]);
// matrix_print(&mat);
matrix_transpose(&mat);
// matrix_print(&mat);
// matrix_print(&expected);
assert(isclose(&mat, &expected));
matrix_clear(&mat);
matrix_clear(&expected);
}
{ // testing 'matrix_mult' using a left multiplty with a row permuting matrix
double data[4][2] = {
{11, 12},
{21, 22},
{31, 32},
{41, 42},
};
struct Matrix mat = matrix_init(4, 2, &data[0][0]);
double data_permute[4][4] = {
{0, 0, 0, 1},
{0, 0, 1, 0},
{0, 1, 0, 0},
{1, 0, 0, 0},
};
struct Matrix permute = matrix_init(4, 4, &data_permute[0][0]);
double data_expected[4][2] = {
{41, 42},
{31, 32},
{21, 22},
{11, 12},
};
struct Matrix expected = matrix_init(4, 2, &data_expected[0][0]);
struct Matrix product = matrix_zeros(permute.m, mat.n);
// matrix_print(&permute);
// matrix_print(&mat);
matrix_mult(&permute, &mat, &product); // left multiply with permuation matrix
// matrix_print(&product);
assert(isclose(&product, &expected));
matrix_clear(&mat);
matrix_clear(&expected);
matrix_clear(&permute);
matrix_clear(&product);
}
{ // testing 'matrix_mult' using a right multiplty with a column permuting matrix
double data[4][2] = {
{11, 12},
{21, 22},
{31, 32},
{41, 42},
};
struct Matrix mat = matrix_init(4, 2, &data[0][0]);
double data_permute[2][2] = {
{0, 1},
{1, 0},
};
struct Matrix permute = matrix_init(2, 2, &data_permute[0][0]);
double data_expected[4][2] = {
{12, 11},
{22, 21},
{32, 31},
{42, 41},
};
struct Matrix expected = matrix_init(4, 2, &data_expected[0][0]);
struct Matrix product = matrix_zeros(mat.m, permute.n);
// matrix_print(&permute);
// matrix_print(&mat);
matrix_mult(&mat, &permute, &product); // right multiply with permuation matrix
// matrix_print(&product);
assert(isclose(&product, &expected));
matrix_clear(&mat);
matrix_clear(&expected);
matrix_clear(&permute);
matrix_clear(&product);
}
printf("task2.test.c: all asserts passed\n");
return 0;
}

196
exercise10/task3.main.c Normal file
View File

@ -0,0 +1,196 @@
/// @file
/// @brief Task3: program with command line options
/// @todo Include header from modules/iue-*, as needed
/// e.g. #include "iue-po/cpo.h"
/// e.g. #include "iue-io/ccsv.h"
/// @todo Include header of task2, if needed
// #include "task2.h"
/// @todo Include C standard library headers, as needed
/// e.g. #include <stdlib.h> // EXIT_FAILURE, EXIT_SUCCESS
/// @todo Implement an executable program which the following top-level description:
/// 1. reads two matrices 'L', and 'R' from two separate .csv-files
/// 2. calculates the matrix product LR (i.e. a matrix-matrix multiplication)
/// 3. stores the resulting matrix in a third .csv-file
/// Detailed Requirements:
/// 1. All .csv-files which are involved need to be compatible with
/// the format supported by 'iueio_savetxt' and 'iueio_loadtxt' from the header 'iue-io/ccsv.h'
/// using ';' as delimiter and '#' as comment
/// 2. The program needs to support the following three mandatory command line arguments in arbitrary order:
/// --left relative filepath to the 'L' matrix
/// --right relative filepath to the 'R' matrix
/// --out relative filepath for the produced result
/// 3. The program prints an error message to stderr, terminates, and returns EXIT_FAILURE if
/// a) If any of the mandatory arguments is missing
/// b) If any of the provided filepaths is not valid
/// c) If any of the provided files cannot be parsed successfully
/// d) If the dimension of the provided matrices are not compatible
/// 4. If the program finishes without any issue, it returns EXIT_SUCCESS
///
/// Implementation hints/valid assumtions for this exercise:
/// - you do not need to support empty .csv-files
/// - you can always assume that all rows in a .csv-file have the same length
/// @file
/// @brief Task3: program with command line options
#include "modules/iue-io/ccsv.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define DELIM ';'
#define COMMENT '#'
// Function to multiply two matrices
double** multiply_matrices(double** L, size_t L_rows, size_t L_cols, double** R, size_t R_rows, size_t R_cols, size_t* out_rows, size_t* out_cols) {
if (L_cols != R_rows) {
return NULL; // Incompatible dimensions
}
*out_rows = L_rows;
*out_cols = R_cols;
double** result = malloc(L_rows * sizeof(double*));
for (size_t i = 0; i < L_rows; ++i) {
result[i] = malloc(R_cols * sizeof(double));
for (size_t j = 0; j < R_cols; ++j) {
result[i][j] = 0.0;
for (size_t k = 0; k < L_cols; ++k) {
result[i][j] += L[i][k] * R[k][j];
}
}
}
return result;
}
int main(int argc, char* argv[]) {
char* left_filepath = NULL;
char* right_filepath = NULL;
char* out_filepath = NULL;
bool left_set = false;
bool right_set = false;
bool out_set = false;
// Parse command line arguments
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--left") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "Missing argument for --left\n");
return EXIT_FAILURE;
}
left_filepath = argv[i + 1];
left_set = true;
i++;
} else if (strcmp(argv[i], "--right") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "Missing argument for --right\n");
return EXIT_FAILURE;
}
right_filepath = argv[i + 1];
right_set = true;
i++;
} else if (strcmp(argv[i], "--out") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "Missing argument for --out\n");
return EXIT_FAILURE;
}
out_filepath = argv[i + 1];
out_set = true;
i++;
}
}
// Check for missing mandatory arguments
if (!left_set || !right_set || !out_set) {
fprintf(stderr,
"Missing mandatory arguments. Usage: %s --left <left_file.csv> --right <right_file.csv> --out "
"<output_file.csv>\n",
argv[0]);
return EXIT_FAILURE;
}
// Load matrices from files
struct Table left_table = {NULL, 0};
struct Table right_table = {NULL, 0};
if (iueio_loadtxt(left_filepath, &left_table, DELIM, COMMENT) != 0) {
fprintf(stderr, "Error loading file %s\n", left_filepath);
return EXIT_FAILURE;
}
if (iueio_loadtxt(right_filepath, &right_table, DELIM, COMMENT) != 0) {
fprintf(stderr, "Error loading file %s\n", right_filepath);
return EXIT_FAILURE;
}
// Check if the matrices are compatible
//if (left_table.n == 0 || right_table.n == 0 || left_table.rows[0].n != right_table.rows[0].n) {
// fprintf(stderr, "Incompatible dimensions\n");
// return EXIT_FAILURE;
//}
// Convert tables to matrices
size_t L_rows = left_table.n;
size_t L_cols = left_table.rows[0].n;
double** L = malloc(L_rows * sizeof(double*));
for (size_t i = 0; i < L_rows; ++i) {
L[i] = malloc(L_cols * sizeof(double));
for (size_t j = 0; j < L_cols; ++j) {
L[i][j] = left_table.rows[i].values[j];
}
}
size_t R_rows = right_table.n;
size_t R_cols = right_table.rows[0].n;
double** R = malloc(R_rows * sizeof(double*));
for (size_t i = 0; i < R_rows; ++i) {
R[i] = malloc(R_cols * sizeof(double));
for (size_t j = 0; j < R_cols; ++j) {
R[i][j] = right_table.rows[i].values[j];
}
}
// Multiply matrices
size_t out_rows, out_cols;
double** result = multiply_matrices(L, L_rows, L_cols, R, R_rows, R_cols, &out_rows, &out_cols);
if (result == NULL) {
fprintf(stderr, "Incompatible dimensions\n");
return EXIT_FAILURE;
}
// Convert result to table
struct Table out_table = {NULL, 0};
for (size_t i = 0; i < out_rows; ++i) {
table_append_copy(&out_table, result[i], out_cols);
}
// Save result to file
if (iueio_savetxt(out_filepath, &out_table, DELIM, "", COMMENT) != 0) {
fprintf(stderr, "Error saving file %s\n", out_filepath);
return EXIT_FAILURE;
}
// Free memory
for (size_t i = 0; i < L_rows; ++i) {
free(L[i]);
}
free(L);
for (size_t i = 0; i < R_rows; ++i) {
free(R[i]);
}
free(R);
for (size_t i = 0; i < out_rows; ++i) {
free(result[i]);
}
free(result);
table_clear(&left_table);
table_clear(&right_table);
table_clear(&out_table);
return EXIT_SUCCESS;
}

88
exercise10/task3.test.c Normal file
View File

@ -0,0 +1,88 @@
/// @file
/// @brief Task3: tests of output files generated by other tests/commands using command line arguments for task3_main
#include "modules/iue-io/ccsv.h" // iueio_loadtxt
#include "modules/iue-num/numerics.h" // iuenum_isclose
#include <assert.h> // assert
#include <stdbool.h> // bool, true, false
#include <stdio.h> // printf
bool isclose(const struct Table* a, const struct Table* b) {
if (a->n != b->n)
return false;
for (size_t r = 0; r != a->n; ++r) {
if (a->rows[r].n != a->rows[r].n)
return false;
for (size_t c = 0; c != a->rows[r].n; ++c)
if (!iuenum_isclose(a->rows[r].values[c], b->rows[r].values[c]))
return false;
}
return true;
}
int main() {
{ // testing result of this command:
// "./build/task3_main --left rrev4x4.csv --right matrix4x2.csv --out matrix4x2_rrow.csv"
double data_expected[4][2] = {
{41, 42},
{31, 32},
{21, 22},
{11, 12},
};
struct Table expected = {NULL, 0};
table_append_copy(&expected, data_expected[0], 2);
table_append_copy(&expected, data_expected[1], 2);
table_append_copy(&expected, data_expected[2], 2);
table_append_copy(&expected, data_expected[3], 2);
const char filepath[] = "matrix4x2_rrow.csv";
struct Table table = {NULL, 0};
if (iueio_loadtxt(filepath, &table, ';', '#') != 0) {
fprintf(stderr, "error loading file %s\n", filepath);
exit(EXIT_FAILURE);
}
assert(isclose(&table, &expected));
table_clear(&table);
table_clear(&expected);
}
{ // testing result of this command:
// "./build/task3_main --left matrix4x2.csv --right rcol2x2.csv --out matrix4x2_rcols.csv"
double data_expected[4][2] = {
{12, 11},
{22, 21},
{32, 31},
{42, 41},
};
struct Table expected = {NULL, 0};
table_append_copy(&expected, data_expected[0], 2);
table_append_copy(&expected, data_expected[1], 2);
table_append_copy(&expected, data_expected[2], 2);
table_append_copy(&expected, data_expected[3], 2);
const char filepath[] = "matrix4x2_rcols.csv";
struct Table table = {NULL, 0};
if (iueio_loadtxt(filepath, &table, ';', '#') != 0) {
fprintf(stderr, "error loading file %s\n", filepath);
exit(EXIT_FAILURE);
}
assert(isclose(&table, &expected));
table_clear(&table);
table_clear(&expected);
}
printf("task3.test.c: all asserts passed\n");
return 0;
}

11
exercise2/.clang-format Normal file
View File

@ -0,0 +1,11 @@
---
BasedOnStyle: LLVM
---
Language: Cpp
AllowShortFunctionsOnASingleLine: Empty
DerivePointerAlignment: false
PointerAlignment: Left
ColumnLimit: 120
TabWidth: 4
IndentWidth: 2
...

25
exercise2/.clangd Normal file
View File

@ -0,0 +1,25 @@
# debug: clangd --check=modules/iue-io/ccsv.h
# debug: clangd --check=task1.hpp
# debug: clangd --check=task1.test.cpp
InlayHints:
Enabled: No
ParameterNames: Yes
DeducedTypes: No
---
CompileFlags:
Add:
# - --target=x86_64-w64-windows-gnu
# - --target=x86_64-pc-linux-gnu
- -Wall
- -Wno-unused-function
- -Wno-unused-variable
---
If:
PathMatch: [.*\.c, .*\.h]
CompileFlags:
Add: [-std=c11]
---
If:
PathMatch: [.*\.cpp, .*\.hpp]
CompileFlags:
Add: [-std=c++20]

3
exercise2/.ctests Normal file
View File

@ -0,0 +1,3 @@
task1
task2
task3

View File

@ -0,0 +1,3 @@
task1.main.cpp
task2.cpp
task3.cpp

16
exercise2/.gitattributes vendored Normal file
View File

@ -0,0 +1,16 @@
## source: https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.h text
*.hpp text
*.c text
*.cpp text
*.py text
*.ipynb text
*.md text
*.txt text
*.csv text

358
exercise2/.gitignore vendored Normal file
View File

@ -0,0 +1,358 @@
# custom
build
doc
.cache
.vscode
.idea
# https://github.com/github/gitignore/blob/main/CMake.gitignore
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
# ttps://github.com/github/gitignore/blob/main/C.gitignore
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# https://github.com/github/gitignore/blob/main/C%2B%2B.gitignore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# source: https://github.com/github/gitignore/blob/main/Python.gitignore
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# jetbrain IDEs: https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# VSCODE source: https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix

42
exercise2/CMakeLists.txt Normal file
View File

@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 3.20)
# define project metadata
project(exercise2 LANGUAGES CXX
DESCRIPTION "exercise2"
HOMEPAGE_URL "https://sgit.iue.tuwien.ac.at/360050/exercise2")
# setting required language standards
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)
# misc settings
# avoid ctest dashboard targets
set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1)
# generate a compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# make all symbols visible on windows (which is default on unix)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# options
option(BUILD_TESTING "enable testing with ctest" ON)
# testing
include(CTest)
# include own targets
add_executable(task1 task1.main.cpp)
add_test(NAME task1 COMMAND task1 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set_property(TEST task1 PROPERTY PROPERTY_REGULAR_EXPRESSION "-1024")
add_executable(task2 task2.cpp task2.test.cpp)
add_test(NAME task2 COMMAND task2 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(task3 task3.cpp task3.test.cpp)
add_test(NAME task3 COMMAND task3 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})

20
exercise2/README.md Normal file
View File

@ -0,0 +1,20 @@
# Hausübung 2 (3 Punkte)
**Ausgabe**: Donnerstag 14. März 2024, vormittags.
**Abgabe bis**: Montag 08. April 2024, Ende des Tages.
**Abgabe via**: git-Repository mit dem Namen **`exercise2`** auf unserem git-Server https://sgit.iue.tuwien.ac.at
Details zum Abgabeprozess via `git` finden Sie hier: https://sgit.iue.tuwien.ac.at/360050/git
# Aufgabenstellung
In dieser Hausübung werden folgende Themen erstmalig einfließen:
- Bedingungen/Verzweigungen
- Schleifen
- Übergabe/Rückgabe/Manipulation von Sequenzen in Form eines `std::vector<int>` und `std::vector<double>`
- Übergabe und Rückgabewerte mehrerer Werte mittels `std::tuple<double,double,double>` und `std::tuple<double,double>`
**Die genaue Beschreibung und Anforderungen finden Sie in [`main.ipynb`](main.ipynb) und im Quellcode.**

View File

@ -0,0 +1 @@
-Imodules

2
exercise2/gitblah-sHB2 Normal file
View File

@ -0,0 +1,2 @@
2024-04-08T09:19:08+02:00 | b8f93888363b8ac94476d28a5f7e0b85485a23ec | who has two thumbs and is a genius? not this guy!
2024-04-08T09:17:30+02:00 | 0d8d68a4679f8e4b48027a25da4280ec914cb6ab | Fingers crossed!

192
exercise2/main.ipynb Normal file
View File

@ -0,0 +1,192 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Cheatsheets\n",
"\n",
"- [exercise1](https://sgit.iue.tuwien.ac.at/360050/cheatsheet/raw/branch/master/exercise1.pdf)\n",
"- [exercise2](https://sgit.iue.tuwien.ac.at/360050/cheatsheet/raw/branch/master/exercise2.pdf)\n",
"\n",
"## Aufgabe 1: Ein eigenes kleines C++-Programm (*vector in/ scalar out*) (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Erstellen Sie in [`task1.main.cpp`](task1.main.cpp) ein lauffähiges Ein-Dateien-Programm das folgende Struktur aufweist:\n",
"\n",
"- Einbinden benötigter Header-Dateien aus der Standardbibliothek, z.B.:\n",
"\t```cpp\n",
"\t#include <iostream> // std::cout, std::endl\n",
"\t#include <...>\n",
"\t```\n",
"- Definition/Implementierung einer eigenen Funktion, z.B.:\n",
"\t```cpp\n",
"\tint func(...){\n",
"\t ...\n",
"\t}\n",
"\t``` \n",
"- Definition/Implementierung einer `main`-Funktion (Einstiegspunkt für jedes lauffähige Programm), die Ihre selbst geschriebene Funktion verwendet und die berechneten Ergebnisse in der Konsole ausgibt, z.B.:\n",
"\t```cpp\n",
"\tint main(){\n",
"\t ...\n",
"\t auto res = func(...)\t\n",
"\t std::cout << res << std::endl;\n",
"\t return 0;\n",
"\t}\n",
"\t``` \n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Eine genaue Beschreibung und Anforderungen finden Sie in [`task1.main.cpp`](task1.main.cpp)\n",
"- Ihre Implementierung erfolgt ebenfalls in [`task1.main.cpp`](task1.main.cpp)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 2: Funktion mit Sequenzen von Werten als Parameter (`std::vector`), internen Verzweigungen (`if`/`else`), und mehreren Rückgabewerten (`std::tuple`) (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Implementieren Sie die folgenden Funktionen:\n",
"\n",
"```cpp\n",
"// type aliases\n",
"using Vector = std::vector<double>;\n",
"using Tuple2 = std::tuple<double,double>;\n",
"\n",
"int count_gt(Vector data, double ref);\n",
"int count_lt(Vector data, double ref);\n",
"\n",
"Vector select_gt(Vector data, double ref);\n",
"Vector select_lt(Vector data, double ref);\n",
"Vector select_gt_and_lt(Vector data, double lower, double upper);\n",
"\n",
"double mean(Vector data);\n",
"double median(Vector data);\n",
"\n",
"Tuple2 minmax(Vector data);\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklarationen und eine genaue Beschreibung und Anforderungen finden Sie in [`task2.hpp`](task2.hpp)\n",
"- Ihre Implementierung erfolgt in [`task2.cpp`](task2.cpp)\n",
"- Die zugeordneten Tests finden Sie in [`task2.test.cpp`](task2.test.cpp)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 3: Kapselung einer Berechnung mittels einer Funktion mit mehreren Rückgabewerten (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Sie kapseln die Berechnung der Lösungen zu einer quadratischen Gleichung $ax^2 + bx + c = 0$ in einer Funktion.\n",
"\n",
"\n",
"Implementieren Sie folgenden beiden Funktionen (überladener Funktionsname):\n",
"\n",
"```cpp\n",
"std::tuple<double, double> solve_quadratic_equation(double a, double b, double c);\n",
"std::tuple<double, double> solve_quadratic_equation(std::tuple<double, double, double> abc);\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklaration und eine genaue Beschreibung und Anforderungen finden Sie in [`task3.hpp`](task3.hpp)\n",
"- Ihre Implementierung erfolgt in [`task3.cpp`](task3.cpp)\n",
"- Die zugeordneten Tests finden Sie in [`task3.test.cpp`](task3.test.cpp)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Kompilieren/Testen\n",
"\n",
"So testen Sie Ihre Implementierung (direkter Aufruf von `g++`):\n",
"\n",
"```shell\n",
"# prepare\n",
"mkdir build\n",
"# compile\n",
"g++ -g -std=c++20 task1.main.cpp -o build/task1.exe\n",
"g++ -g -std=c++20 task2.cpp task2.test.cpp -o build/task2.exe\n",
"g++ -g -std=c++20 task3.cpp task3.test.cpp -o build/task3.exe\n",
"# run tests \n",
"./build/task1.exe\n",
"./build/task2.exe\n",
"./build/task3.exe\n",
"```\n",
"\n",
"Alternativ (mittels CMake-Configuration):\n",
"\n",
"```shell\n",
"# prepare\n",
"cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug\n",
"# compile \n",
"cmake --build build --config Debug --target task1\n",
"cmake --build build --config Debug --target task2\n",
"cmake --build build --config Debug --target task3\n",
"# run tests \n",
"ctest --test-dir build -C Debug -R task1\n",
"ctest --test-dir build -C Debug -R task2\n",
"ctest --test-dir build -C Debug -R task3\n",
"```\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.6.15"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

33
exercise2/task1.main.cpp Normal file
View File

@ -0,0 +1,33 @@
/// @file
/// @brief Task1: "single-file" excutable C++ program
/// @todo Include standard library headers as needed
#include <iostream>
#include <vector>
/// @brief Find the minimum value in a sequence of integer values
/// @param data Sequence of values stored in a std::vector<int> (assertion: sequence is not empty )
/// @return Minimum value in the sequence
int min(const std::vector<int>& data) {
int min = data[0];
for (int i = 1; i < data.size(); i++) {
if (data[i] < min) {
min = data[i];
}
}
return min;
}
/// @brief main function (entry point) conducting the following tasks in this order:
/// - create and prepare a local variable of type std::vector<int>
/// holding a sequence of 5 values in this order: -10, 20, 100, -1024, 2048
/// - call your function 'min' and provide the prepared variable as argument to the call
/// - capture the result of your function call in a local variable and print it to the console
int main() {
std::vector<int> data = {-10, 20, 100, -1024, 2048};
int min_value = min(data);
std::cout << "The minimum value is: " << min_value << std::endl;
return 0;
}

117
exercise2/task2.cpp Normal file
View File

@ -0,0 +1,117 @@
#include "task2.hpp" // count_gt|count_lt|select_gt|select_lt|select_gt_and_lt|mean|median|minmax
#include <algorithm>
/// @todo Include standard library headers as needed
/// @brief Counts how many values in a sequence are greater than (gt) a reference value
/// @param data Sequence of values
/// @param ref Reference value
/// @return Number of values in the sequence, which are greater than than ref
int count_gt(std::vector<double> data, double ref) {
int count = 0;
for (int i = 0; i < data.size(); i++) {
if (data[i] > ref) {
count++;
}
}
return count;
}
/// @brief Counts how many values in a sequence are less than (lt) a reference value
/// @param data Sequence of values
/// @param ref Reference value
/// @return Number of values in the sequence, which are less than than ref
int count_lt(std::vector<double> data, double ref) {
int count = 0;
for (int i = 0; i < data.size(); i++) {
if (data[i] < ref) {
count++;
}
}
return count;
}
/// @brief Selects values from a sequence which are greater than (gt) a reference value
/// @param data Sequence of values
/// @param ref Reference value
/// @return Sequence of selected (copied) values in the order of occurence in the original sequence
std::vector<double> select_gt(std::vector<double> data, double ref) {
std::vector<double> selected;
for (int i = 0; i < data.size(); i++) {
if (data[i] > ref) {
selected.push_back(data[i]);
}
}
return selected;
}
/// @brief Selects values from a sequence which are less than (lt) a reference value
/// @param data Sequence of values
/// @param ref Reference value
/// @return Sequence of selected (copied) values in the order of occurence in the original sequence
std::vector<double> select_lt(std::vector<double> data, double ref) {
std::vector<double> selected;
for (int i = 0; i < data.size(); i++) {
if (data[i] < ref) {
selected.push_back(data[i]);
}
}
return selected;
}
/// @brief Selects values from a sequence which are bounded by two reference values
/// @param data Sequence of values
/// @param lower Lower bound
/// @param upper Upper bound
/// @return Sequence of selected (copied) values in the order of occurence in the original sequence
std::vector<double> select_gt_and_lt(std::vector<double> data, double lower, double upper) {
std::vector<double> selected;
for (int i = 0; i < data.size(); i++) {
if (data[i] > lower && data[i] < upper) {
selected.push_back(data[i]);
}
}
return selected;
}
/// @brief Calculates the mean for a sequence of values
/// @param data Sequence of values; assertion: data.size() >= 1
/// @return Mean value (arithmetic mean)
double mean(std::vector<double> data) {
double sum = 0;
for (int i = 0; i < data.size(); i++) {
sum += data[i];
}
return sum / data.size();
}
/// @brief Calculate the median for a sequence of numbers
/// @param data Sequence of values; assertion: data.size() >= 1
/// @return Median value:
/// - if the length of the sequence is odd, the median value is "the middle value", else
/// - if the length of the sequence is even, the median value is the avarage of the "two middle values"
double median(std::vector<double> data) {
std::sort(data.begin(), data.end());
if (data.size() % 2 == 0) {
return (data[data.size() / 2 - 1] + data[data.size() / 2]) / 2;
} else {
return data[data.size() / 2];
}
}
/// @brief Finds the minimum and maximum value
/// @param data Sequence of values; assertion: data.size() >= 1
/// @return Tuple with the minimum and maximum value (in this order)
std::tuple<double, double> minmax(std::vector<double> data) {
double min = data[0];
double max = data[0];
for (int i = 1; i < data.size(); i++) {
if (data[i] < min) {
min = data[i];
}
if (data[i] > max) {
max = data[i];
}
}
return std::make_tuple(min, max);
}

55
exercise2/task2.hpp Normal file
View File

@ -0,0 +1,55 @@
/// @file
/// @brief Task2: function declarations
#pragma once
#include <tuple> // std::tuple
#include <vector> // std::vector
/// @brief Counts how many values in a sequence are greater than (gt) a reference value
/// @param data Sequence of values
/// @param ref Reference value
/// @return Number of values in the sequence, which are greater than than ref
int count_gt(std::vector<double> data, double ref);
/// @brief Counts how many values in a sequence are less than (lt) a reference value
/// @param data Sequence of values
/// @param ref Reference value
/// @return Number of values in the sequence, which are less than than ref
int count_lt(std::vector<double> data, double ref);
/// @brief Selects values from a sequence which are greater than (gt) a reference value
/// @param data Sequence of values
/// @param ref Reference value
/// @return Sequence of selected (copied) values in the order of occurence in the original sequence
std::vector<double> select_gt(std::vector<double> data, double ref);
/// @brief Selects values from a sequence which are less than (lt) a reference value
/// @param data Sequence of values
/// @param ref Reference value
/// @return Sequence of selected (copied) values in the order of occurence in the original sequence
std::vector<double> select_lt(std::vector<double> data, double ref);
/// @brief Selects values from a sequence which are bounded by two reference values
/// @param data Sequence of values
/// @param lower Lower bound
/// @param upper Upper bound
/// @return Sequence of selected (copied) values in the order of occurence in the original sequence
std::vector<double> select_gt_and_lt(std::vector<double> data, double lower, double upper);
/// @brief Calculates the mean for a sequence of values
/// @param data Sequence of values; assertion: data.size() >= 1
/// @return Mean value (arithmetic mean)
double mean(std::vector<double> data);
/// @brief Calculate the median for a sequence of numbers
/// @param data Sequence of values; assertion: data.size() >= 1
/// @return Median value:
/// - if the length of the sequence is odd, the median value is "the middle value", else
/// - if the length of the sequence is even, the median value is the avarage of the "two middle values"
double median(std::vector<double> data);
/// @brief Finds the minimum and maximum value
/// @param data Sequence of values; assertion: data.size() >= 1
/// @return Tuple with the minimum and maximum value (in this order)
std::tuple<double, double> minmax(std::vector<double> data);

112
exercise2/task2.test.cpp Normal file
View File

@ -0,0 +1,112 @@
/// @file
/// @brief Test for Task2
#include "task2.hpp" // count_gt|count_lt|select_gt|select_lt|select_gt_and_lt|mean|median|minmax
#include <cassert> // assert
#include <iostream> // std::cout|endl
int main() {
{ // testing function 'count_gt'
int res = count_gt({1.0, 2.0, 3.0, 4.0}, 2.0);
assert(res == 2);
}
{ // testing function 'count_gt'
int res = count_gt({-4.0, -2.0, -2.0, -1.0}, -2.0);
assert(res == 1);
}
{ // testing function 'count_lt'
int res = count_lt({-4.0, -2.0, -2.0, -1.0}, -1.0);
assert(res == 3);
}
{ // testing function 'count_lt'
int res = count_lt({2.0, 2.0, 2.0, 2.0}, 3.0);
assert(res == 4);
}
{ // testing function 'select_lt'
std::vector<double> res = select_lt({2.0, 2.0, 2.0, 2.0}, 3.0);
std::vector<double> expected = {2.0, 2.0, 2.0, 2.0};
assert(res == expected);
}
{ // testing function 'select_lt'
std::vector<double> res = select_lt({1.0, 2.0, 3.0, 4.0}, 4.0);
std::vector<double> expected = {1.0, 2.0, 3.0};
assert(res == expected);
}
{ // testing function 'select_gt'
std::vector<double> res = select_gt({2.0, 2.0, 2.0, 2.0}, 2.0);
std::vector<double> expected = {};
assert(res == expected);
}
{ // testing function 'select_gt'
std::vector<double> res = select_gt({1.0, 2.0, 3.0, 4.0}, 2.0);
std::vector<double> expected = {3.0, 4.0};
assert(res == expected);
}
{ // testing function 'select_gt_and_lt'
std::vector<double> res = select_gt_and_lt({-3.0, 2.0, -3.0, -2.0, 4.0, 1.0, -1.0, -4.0}, -3.0, 3.0);
std::vector<double> expected = {2.0, -2.0, 1.0, -1.0};
assert(res == expected);
}
{ // testing function 'mean'
double res = mean({1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 0.0});
double expected = 3.0;
assert(std::abs(res - expected) < 1e-7);
}
{ // testing function 'mean'
double res = mean({-3.0, -2.0, -1.0, 1.0, 2.0, 3.0});
double expected = 0.0;
assert(std::abs(res - expected) < 1e-7);
}
{ // testing function 'median'
double res = median({3.0});
double expected = 3.0;
assert(std::abs(res - expected) < 1e-7);
}
{ // testing function 'median'
double res = median({2.0, 3.0});
double expected = 2.5;
assert(std::abs(res - expected) < 1e-7);
}
{ // testing function 'median'
double res = median({3.0, 2.0, 3.0, 2.0});
double expected = 2.5;
assert(std::abs(res - expected) < 1e-7);
}
{ // testing function 'median'
double res = median({3.0, 3.0, 3.0, -1.0, 4.0});
double expected = 3.0;
assert(std::abs(res - expected) < 1e-7);
}
{ // testing function 'minmax'
std::tuple<double, double> res = minmax({300.0, 100.0});
std::tuple<double, double> expected = {100.0, 300.0};
assert(res == expected);
}
{ // testing function 'minmax'
std::tuple<double, double> res = minmax({-1.0, -2.0, -3.0, 4.0, 20.0, 12.0});
std::tuple<double, double> expected = {-3.0, 20.0};
assert(res == expected);
}
std::cout << "task2.test.cpp: all asserts passed" << std::endl;
return 0;
}

33
exercise2/task3.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "task3.hpp" // solve_quadratic_equation
#include <valarray>
/// @brief Calculates the real solutions of the quadratic equation a*x^2 + b*x + c = 0.
/// @param a coefficient; assertion: 'a' is a non-zero value
/// @param b coefficient
/// @param c coefficient
/// @return The two real solutions (order: ascending).
/// If no real solutions exists, the tuple contains two quiet NaNs.
std::tuple<double, double> solve_quadratic_equation(double a, double b, double c){
double x1, x2;
double d = b*b - 4*a*c;
if(d < 0){
x1 = NAN;
x2 = NAN;
}else{
x1 = (-b - sqrt(d))/(2*a);
x2 = (-b + sqrt(d))/(2*a);
}
return std::make_tuple(x1, x2);
}
/// @brief Calculates the real solutions of the quadratic equation a*x^2 + b*x + c = 0.
/// @param abc coefficients; assertion: first coefficient 'a' is a non-zero value
/// @return The two real solutions (order: ascending).
/// If no real solutions exists, the tuple contains two quiet NaNs.
std::tuple<double, double> solve_quadratic_equation(std::tuple<double, double, double> abc){
double a = std::get<0>(abc);
double b = std::get<1>(abc);
double c = std::get<2>(abc);
return solve_quadratic_equation(a, b, c);
}

20
exercise2/task3.hpp Normal file
View File

@ -0,0 +1,20 @@
/// @file
/// @brief Task3: function declarations
#pragma once
#include <tuple> // std::tuple
/// @brief Calculates the real solutions of the quadratic equation a*x^2 + b*x + c = 0.
/// @param a coefficient; assertion: 'a' is a non-zero value
/// @param b coefficient
/// @param c coefficient
/// @return The two real solutions (order: ascending).
/// If no real solutions exists, the tuple contains two quiet NaNs.
std::tuple<double, double> solve_quadratic_equation(double a, double b, double c);
/// @brief Calculates the real solutions of the quadratic equation a*x^2 + b*x + c = 0.
/// @param abc coefficients; assertion: first coefficient 'a' is a non-zero value
/// @return The two real solutions (order: ascending).
/// If no real solutions exists, the tuple contains two quiet NaNs.
std::tuple<double, double> solve_quadratic_equation(std::tuple<double, double, double> abc);

54
exercise2/task3.test.cpp Normal file
View File

@ -0,0 +1,54 @@
/// @file
/// @brief Test for Task3
#include "task3.hpp" // solve_quadratic_equation
#include <cassert> // assert
#include <cmath> // NAN
#include <iostream> // std::cout|endl
int main() {
{ // testing function overloads 'solve_quadratic_equation'
auto [s1, s2] = solve_quadratic_equation(1.0, 3.0, 2.0);
assert(std::abs(s1 - (-2.0)) < 1e-7);
assert(std::abs(s2 - (-1.0)) < 1e-7);
}
{ // testing function overloads 'solve_quadratic_equation'
std::tuple<double, double, double> coefficients = {1.0, 3.0, 2.0};
auto [s1, s2] = solve_quadratic_equation(coefficients);
assert(std::abs(s1 - (-2.0)) < 1e-7);
assert(std::abs(s2 - (-1.0)) < 1e-7);
}
{ // testing function overloads 'solve_quadratic_equation'
auto [s1, s2] = solve_quadratic_equation(1.0, 2.0, 5.0);
assert(std::isnan(s1));
assert(std::isnan(s2));
}
{ // testing function overloads 'solve_quadratic_equation'
std::tuple<double, double, double> coefficients = {1.0, 2.0, 5.0};
auto [s1, s2] = solve_quadratic_equation(coefficients);
assert(std::isnan(s1));
assert(std::isnan(s2));
}
{ // testing function overloads 'solve_quadratic_equation'
auto [s1, s2] = solve_quadratic_equation(2.0, 1.0, -3.0);
assert(std::abs(s1 - (-1.5)) < 1e-7);
assert(std::abs(s2 - (1.0)) < 1e-7);
}
{ // testing function overloads 'solve_quadratic_equation'
std::tuple<double, double, double> coefficients = {2.0, 1.0, -3.0};
auto [s1, s2] = solve_quadratic_equation(coefficients);
assert(std::abs(s1 - (-1.5)) < 1e-7);
assert(std::abs(s2 - (1.0)) < 1e-7);
}
std::cout << "task3.test.cpp: all asserts passed" << std::endl;
return 0;
}

10
exercise3/.clang-format Normal file
View File

@ -0,0 +1,10 @@
---
BasedOnStyle: LLVM
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
ColumnLimit: 120
TabWidth: 4
IndentWidth: 2
...

25
exercise3/.clangd Normal file
View File

@ -0,0 +1,25 @@
# debug: clangd --check=modules/iue-io/ccsv.h
# debug: clangd --check=task1.hpp
# debug: clangd --check=task1.test.cpp
InlayHints:
Enabled: No
ParameterNames: Yes
DeducedTypes: No
---
CompileFlags:
Add:
# - --target=x86_64-w64-windows-gnu
# - --target=x86_64-pc-linux-gnu
- -Wall
- -Wno-unused-function
- -Wno-unused-variable
---
If:
PathMatch: [.*\.c, .*\.h]
CompileFlags:
Add: [-std=c11]
---
If:
PathMatch: [.*\.cpp, .*\.hpp]
CompileFlags:
Add: [-std=c++20]

4
exercise3/.ctests Normal file
View File

@ -0,0 +1,4 @@
task1
task2
task3_cpp
task3_py

View File

@ -0,0 +1,4 @@
task1.main.cpp
task2.cpp
task3.cpp
task3.py

16
exercise3/.gitattributes vendored Normal file
View File

@ -0,0 +1,16 @@
## source: https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.h text
*.hpp text
*.c text
*.cpp text
*.py text
*.ipynb text
*.md text
*.txt text
*.csv text

360
exercise3/.gitignore vendored Normal file
View File

@ -0,0 +1,360 @@
# custom
*.csv
*.png
build
doc
.cache
.vscode
.idea
# https://github.com/github/gitignore/blob/main/CMake.gitignore
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
# ttps://github.com/github/gitignore/blob/main/C.gitignore
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# https://github.com/github/gitignore/blob/main/C%2B%2B.gitignore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# source: https://github.com/github/gitignore/blob/main/Python.gitignore
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# jetbrain IDEs: https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# VSCODE source: https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix

4
exercise3/.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "modules"]
path = modules
url = https://sgit.iue.tuwien.ac.at/360050/modules
branch = main

54
exercise3/CMakeLists.txt Normal file
View File

@ -0,0 +1,54 @@
cmake_minimum_required(VERSION 3.20)
# define project metadata
project(exercise3 LANGUAGES CXX
DESCRIPTION "exercise3"
HOMEPAGE_URL "https://sgit.iue.tuwien.ac.at/360050/exercise3")
# setting required language standards
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)
# misc settings
# avoid ctest dashboard targets
set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1)
# generate a compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# make all symbols visible on windows (which is default on unix)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# options
option(BUILD_TESTING "enable testing with ctest" ON)
# testing
include(CTest)
# get/setup dependencies
include_directories(modules)
# include own targets
add_executable(task1 task1.main.cpp)
add_test(NAME task1 COMMAND task1 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set_property(TEST task1 PROPERTY PASS_REGULAR_EXPRESSION "45")
add_executable(task2 task2.cpp task2.test.cpp)
add_test(NAME task2 COMMAND task2 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(task3_cpp task2.cpp task3.cpp task3.test.cpp)
add_test(NAME task3_cpp COMMAND task3_cpp WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
find_package(Python3 COMPONENTS Interpreter REQUIRED)
add_test(NAME task3_py COMMAND ${Python3_EXECUTABLE} task3.test.py WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set_tests_properties(task3_py PROPERTIES DEPENDS task3_cpp)
add_custom_target(task3)
add_dependencies(task3 task3_cpp)

29
exercise3/README.md Normal file
View File

@ -0,0 +1,29 @@
# Hausübung 3 (3 Punkte)
**Ausgabe**: Donnerstag 21. März 2024, vormittags.
**Abgabe bis**: Montag 15. April 2024, Ende des Tages.
**Abgabe via**: git-Repository mit dem Namen **`exercise3`** auf unserem git-Server https://sgit.iue.tuwien.ac.at
Details zum Abgabeprozess via `git` finden Sie hier: https://sgit.iue.tuwien.ac.at/360050/git
# Aufgabenstellung
In dieser Hausübung werden folgende Themen erstmalig einfliessen:
- Vektoren von Vektoren, hier beschränkt auf folgende Typen:
```cpp
std::vector<std::vector<double>>
std::vector<std::vector<int>>
```
- Uebergabe von aufrufbaren Objekten, mittels `std::function` hier beschränkt auf folgenden Typ:
```cpp
std::function<double(double)>
```
- Numerische Integration und Differenzierung
- Einbinden und Nutzung einer [lokalen Bibilothek](https://sgit.iue.tuwien.ac.at/360050/modules/src/branch/main/iue-io/csv.hpp) zum Schreiben von `.csv`-Dateien sowie Plotten der geschrieben Daten mit Python/Matplotlib.
**Die genaue Beschreibung und Anforderungen finden Sie in [`main.ipynb`](main.ipynb) und im Quellcode.**

View File

@ -0,0 +1 @@
-Imodules

248
exercise3/main.ipynb Normal file
View File

@ -0,0 +1,248 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 1: Ein eigenes kleines C++-Programm (*vector of vectors*) (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Erstellen Sie in [`task1.main.cpp`](task1.main.cpp) ein lauffähiges Ein-Dateien-Programm das folgende Struktur aufweist:\n",
"\n",
"- Einbinden benötigter Header-Dateien aus der Standardbibliothek, z.B.:\n",
"\t```cpp\n",
"\t#include <iostream> // std::cout, std::endl\n",
"\t#include <...>\n",
"\t```\n",
"- Definition/Implementierung einer eigenen Funktion, z.B.:\n",
"\t```cpp\n",
"\tint sum(...){\n",
"\t ...\n",
"\t}\n",
"\t``` \n",
"- Definition/Implementierung einer `main`-Funktion (Einstiegspunkt für jedes lauffähige Programm), die Ihre selbest geschriebene Funktion verwendet und die berechneten Ergebnisse in der Konsole ausgibt, z.B.:\n",
"\t```cpp\n",
"\tint main(){\n",
"\t ...\n",
"\t auto res = sum(...)\t\n",
"\t std::cout << res << std::endl;\n",
"\t return 0;\n",
"\t}\n",
"\t``` \n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Eine genaue Beschreibung und Anforderungen finden Sie in [`task1.main.cpp`](task1.main.cpp)\n",
"- Ihre Implementierung erfolgt ebenfalls in [`task1.main.cpp`](task1.main.cpp)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 2: Mathematische Funktionen abtasten, numerische Integration und Differenzierung (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Sie implementieren Funktionen, die\n",
"\n",
"- ein Intervall $[a,b]$ mittels $N$ Stellen gleichabständig abstasten -> $\\mathbf{x} = \\left[ x_1, x_2, ... , x_N \\right]$,\n",
"- eine Funktion $f(x)$ für die diskreten Werte im Intervall evaluieren -> $\\mathbf{y} = \\left[ f(x_1), f(x_2), ... , f(x_N) \\right]$,\n",
"- anhand der diskreten Wertepaare ($\\mathbf{x}, \\mathbf{y}$) die Ableitung approximieren:\n",
"\t- Vorwärts-Differenz an der ersten Stelle: $f'(x_1) \\approx \\frac{y_2 - y_1}{x_2 - x_1}$,\n",
"\t- Rückwarts-Differenz an der letzten Stelle: $f'(x_N) \\approx \\frac{y_N - y_{N-1}}{x_N - x_{N-1}}$,\n",
"\t- Zentrale-Differenz für alle anderen Stellen $f'(x_i) \\approx \\frac{y_{i+1} - y_{i-1} }{x_{i+1} - x_{i-1}}$, und\n",
"- anhand der diskreten Wertepaare ($\\mathbf{x}, \\mathbf{y}$) die Stammfunktion approximieren:\n",
"\t- Integrationskonstante an der ersten Stelle: $F(x_1) = C$\n",
"\t- Trapezregel für alle anderen Stellen: $F(x_i) \\approx C + \\sum_{2}^{i} \\left[ 0.5 \\cdot \\left(y_{i}+y_{i-1}\\right) \\cdot \\left(x_i - x_{i-1}\\right) \\right]$."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Implementieren Sie die folgenden vier Funktionen:\n",
"\n",
"```cpp\n",
"using Vector = std::vector<double>;\n",
"using Callable = std::function<double(double)>;\n",
"\n",
"Vector range(double start, double end, unsigned int N);\n",
"Vector sample(Vector values, Callable func);\n",
"Vector numdiff(Vector x, Vector y);\n",
"Vector numint(Vector x, Vector y, double C);\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklarationen und eine genaue Beschreibung und Anforderungen finden Sie in [`task2.hpp`](task2.hpp)\n",
"- Ihre Implementierung erfolgt in [`task2.cpp`](task2.cpp)\n",
"- Die zugeordneten Tests finden Sie in [`task2.test.cpp`](task2.test.cpp)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 3: Diskrete Funktionswerte abspeichern und plotten (1 Punkt)\n",
"\n",
"Sie implementieren eine Funktion in C++ die eine `.csv`-Datei mit diskreten Funktionswerten erzeugt:\n",
"- verwenden Sie Ihre in Aufgabe 2 entwickelten Funktionen zum Abtasten und numerisch Integrieren/Differenzieren\n",
"- verwenden Sie die bereitgestellte Funktion [`iue::io::savetxt`](https://sgit.iue.tuwien.ac.at/360050/modules/src/commit/7b31b845bf2d1297553a8565ba6ca2474305394a/iue-io/csv.hpp#L20) zum Schreiben der `.csv`-Datei\n",
"\n",
"Ebenso implementieren Sie eine Funktion in Python, um die Funktionswerten in der von Ihnen erzeugten `.csv`-Datei zu plotten:\n",
"- verwenden Sie [numpy.loadtxt](https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html) zum Lesen der `.csv`-Datei\n",
"- verwenden Sie [`Matplotlib`](https://matplotlib.org/stable/tutorials/pyplot.html) zum Plotten der eingelesenen Daten"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Implementieren Sie folgende Funktion (**C++**):\n",
"\n",
"```cpp\n",
"\n",
"using Filename = std::filesystem::path;\n",
"using Callable = std::function<double(double)>;\n",
"\n",
"void sample_to_csv(Filename filepath, \n",
" char del, \n",
" char comments, \n",
" Callable func, \n",
" double start, \n",
" double end, \n",
" unsigned int N);\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklaration und eine genaue Beschreibung und Anforderungen finden Sie in [`task3.hpp`](task3.hpp)\n",
"- Ihre Implementierung erfolgt in [`task3.cpp`](task3.cpp)\n",
"- Die zugeordneten Tests finden Sie in [`task3.test.cpp`](task3.test.cpp)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Implementieren Sie zudem folgende Funktion (**Python**):\n",
"\n",
"```py\n",
"def plot_discrete_function(csvfile, delimiter, comments, pngfile):\n",
"\tpass # todo: implement\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Ihre Implementierung erfolgt in [`task3.py`](task3.py)\n",
"- Die zugeordneten Tests finden Sie in [`task3.test.py`](task3.test.py)\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Die final erzeugten Plots könnten z.B. so aussehen:\n",
"\n",
"![images/task3_plot_sin.png](images/task3_plot_sin.png) \n",
"![images/test3_plot_cos.png](images/task3_plot_cos.png)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Kompilieren/Testen\n",
"\n",
"So testen Sie Ihre Implementierung (direkter Aufruf von `g++` und `python`):\n",
"\n",
"```shell\n",
"# prepare\n",
"mkdir build\n",
"# compile\n",
"g++ -g -std=c++20 task1.main.cpp -o build/task1.exe\n",
"g++ -g -std=c++20 task2.cpp task2.test.cpp -o build/task2.exe\n",
"g++ -g -Imodules -std=c++20 task2.cpp task3.cpp task3.test.cpp -o build/task3.exe\n",
"\n",
"# run tests\n",
"./build/task1.exe\n",
"./build/task2.exe\n",
"./build/task3.exe\n",
"python task3.test.py\n",
"```\n",
"\n",
"Alternativ (mittels CMake-Configuration):s\n",
"\n",
"```shell\n",
"# prepare\n",
"cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug\n",
"# compile\n",
"cmake --build build --config Debug --target task1\n",
"cmake --build build --config Debug --target task2\n",
"cmake --build build --config Debug --target task3\n",
"cmake --build build --config Debug # all\n",
"# run tests\n",
"ctest --test-dir build -C Debug -R task1 \n",
"ctest --test-dir build -C Debug -R task2 \n",
"ctest --test-dir build -C Debug -R task3 \n",
"ctest --test-dir build -C Debug # all\n",
"``` \n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.6.15"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

1
exercise3/modules Submodule

@ -0,0 +1 @@
Subproject commit b8ce24c87fc76396de465b2573e19909fd10cf13

38
exercise3/task1.main.cpp Normal file
View File

@ -0,0 +1,38 @@
/// @file
/// @brief Task1: "single-file" excutable C++ program
#include <iostream>
#include <vector>
/// @brief Calculate the sum of all integer values in a std::vector<std::vector<int>>
/// @param data A vector of vectors containing the values to be summed
/// @return Sum of all values in data
double sum(const std::vector<std::vector<int>>& data) {
double sum = 0;
for (const auto& row : data) {
for (const auto& value : row) {
sum += value;
}
}
return sum;
}
/// @brief main function (entry point for executable) conducting the following tasks in this order
/// - create and prepare a local variable of type std::vector<std::vector<int>>
/// holding 9 int values in this arrangement:
/// 1, 2, 3
/// 4, 5, 6
/// 7, 8, 9
/// - call your function 'sum' and provide the prepared variable as argument to the call
/// - capture the result of your function call in a local variable and print it to the console
int main() {
std::vector<std::vector<int>> data = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
double result = sum(data);
std::cout << "Sum: " << result << std::endl;
return 0;
}

71
exercise3/task2.cpp Normal file
View File

@ -0,0 +1,71 @@
/// @file
/// @brief Task2: implementation
#include "task2.hpp"
/// @todo Include standard library headers as needed
#include <cassert> // assert
#include <functional> // std::function
#include <vector> // std::vector
#include <cmath> // std::abs
/// @brief Creates a sequence of equidistant values in a given interval (inclusive).
/// @param start Start of the interval
/// @param end End of the interval
/// @param N Number of values; assumption: N >= 2
/// @return Sequence of equidistant values in increasing order
std::vector<double> range(double start, double end, unsigned int N) {
assert(N >= 2);
std::vector<double> values(N);
double step = (end - start) / (N - 1);
for (unsigned int i = 0; i < N; ++i) {
values[i] = start + i * step;
}
return values;
}
/// @brief Evaluates a one-dimensional scalar function at the provided discrete locations
/// @param values Sequence of discrete locations
/// @param func Callable with a signature compatible with f(double) -> double
/// @return Sequence of function values
std::vector<double> sample(std::vector<double> values, std::function<double(double)> func) {
std::vector<double> results(values.size());
for (unsigned int i = 0; i < values.size(); ++i) {
results[i] = func(values[i]);
}
return results;
}
/// @brief Performs a numerical differentiation using a combined forward/center/backward difference scheme
/// @param x Discrete sequence of locations; assumption: two or more values, ascending, and equally spaced
/// @param y Discrete sequence of function values; assumption: same size as 'x'
/// @return Sequence of function values of the numerical derivative
std::vector<double> numdiff(std::vector<double> x, std::vector<double> y) {
assert(x.size() == y.size());
assert(x.size() >= 2);
std::vector<double> derivative(x.size());
double h = x[1] - x[0];
derivative[0] = (y[1] - y[0]) / h;
for (unsigned int i = 1; i < x.size() - 1; ++i) {
derivative[i] = (y[i + 1] - y[i - 1]) / (2 * h);
}
derivative[x.size() - 1] = (y[x.size() - 1] - y[x.size() - 2]) / h;
return derivative;
}
/// @brief Performs a numerical integration using the trapezoidal rule
/// @param x Discrete sequence of locations; assumption: two or more values, ascending, and equally spaced
/// @param y Discrete sequence of function values; assumption: same size as 'x'
/// @param C Constant of integration
/// @return Sequence of function values of the numerical antiderivative
std::vector<double> numint(std::vector<double> x, std::vector<double> y, double C) {
assert(x.size() == y.size());
assert(x.size() >= 2);
std::vector<double> integral(x.size());
double h = x[1] - x[0];
integral[0] = C;
for (unsigned int i = 1; i < x.size(); ++i) {
integral[i] = integral[i - 1] + (y[i - 1] + y[i]) * h / 2;
}
return integral;
}

34
exercise3/task2.hpp Normal file
View File

@ -0,0 +1,34 @@
/// @file
/// @brief Task2: function declarations
#pragma once
#include <functional> // std::function
#include <vector> // std::vector
/// @brief Creates a sequence of equidistant values in a given interval (inclusive).
/// @param start Start of the interval
/// @param end End of the interval
/// @param N Number of values; assumption: N >= 2
/// @return Sequence of equidistant values in increasing order
std::vector<double> range(double start, double end, unsigned int N);
/// @brief Evaluates a one-dimensional scalar function at the provided discrete locations
/// @param values Sequence of discrete locations
/// @param func Callable with a signature compatible with f(double) -> double
/// @return Sequence of function values
std::vector<double> sample(std::vector<double> values, std::function<double(double)> func);
/// @brief Performs a numerical differentiation using a combined forward/center/backward difference scheme
/// @param x Discrete sequence of locations; assumption: two or more values, ascending, and equally spaced
/// @param y Discrete sequence of function values; assumption: same size as 'x'
/// @return Sequence of function values of the numerical derivative
std::vector<double> numdiff(std::vector<double> x, std::vector<double> y);
/// @brief Performs a numerical integration using the trapezoidal rule
/// @param x Discrete sequence of locations; assumption: two or more values, ascending, and equally spaced
/// @param y Discrete sequence of function values; assumption: same size as 'x'
/// @param C Constant of integration
/// @return Sequence of function values of the numerical antiderivative
std::vector<double> numint(std::vector<double> x, std::vector<double> y, double C);

97
exercise3/task2.test.cpp Normal file
View File

@ -0,0 +1,97 @@
/// @file
/// @brief Task2: tests
#include "task2.hpp"
#include <cassert> // assert
#include <cmath> // std::abs|sin
#include <iostream> // std::cout|endl
#include <vector> // std::vector
namespace help {
/// @brief only to disambiguate the 'sin'-overloads from cmath
double sin(double value) { return std::sin(value); }
/// @brief only to disambiguate the 'cos'-overloads from cmath
double cos(double value) { return std::cos(value); }
} // namespace help
int main() {
{ // testing function 'range'
std::vector<double> x = range(0, 10, 11);
double dx = x[1] - x[0];
assert(std::abs(dx - 1.0) < 1e-7);
for (unsigned int i = 1; i != x.size(); ++i)
assert(std::abs(x[i] - x[i - 1] - dx) < 1e-7);
}
{ // testing functions 'range' and 'sample'
std::vector<double> x = range(2, 10, 6);
std::vector<double> f = sample(x, help::sin);
for (unsigned int i = 0; i != x.size(); ++i)
assert(std::abs(f[i] - help::sin(x[i])) < 1e-7);
}
{ // testing functions 'range' and 'sample'
std::vector<double> x = range(0, 5, 6);
std::vector<double> f = sample(x, help::cos);
for (unsigned int i = 0; i != x.size(); ++i)
assert(std::abs(f[i] - help::cos(x[i])) < 1e-7);
}
{ // testing function 'numdiff'
std::vector<double> x = {0, 1, 2, 3, 4};
std::vector<double> f = {0, 1, 1, 1, 0.5};
std::vector<double> df = numdiff(x, f);
assert(std::abs(df[0] - 1.0) < 1e-7);
assert(std::abs(df[1] - 0.5) < 1e-7);
assert(std::abs(df[2] - 0.0) < 1e-7);
assert(std::abs(df[3] + 0.25) < 1e-7);
assert(std::abs(df[4] + 0.5) < 1e-7);
}
{ // testing function 'numdiff'
double s = 2.0;
std::vector<double> x = {0*s, 1*s, 2*s, 3*s, 4*s};
std::vector<double> f = {0, 1, 1, 1, 0.5};
std::vector<double> df = numdiff(x, f);
assert(std::abs(df[0] - 1.00/s) < 1e-7);
assert(std::abs(df[1] - 0.50/s) < 1e-7);
assert(std::abs(df[2] - 0.00/s) < 1e-7);
assert(std::abs(df[3] + 0.25/s) < 1e-7);
assert(std::abs(df[4] + 0.50/s) < 1e-7);
}
{ // testing function 'numint'
std::vector<double> x = {0, 1, 2, 3, 4};
std::vector<double> f = {0, 1, 1, 1, 0};
std::vector<double> F = numint(x, f, 0.0);
assert(std::abs(F[0] - 0.0) < 1e-7);
assert(std::abs(F[1] - (F[0] + 0.5)) < 1e-7);
assert(std::abs(F[2] - (F[1] + 1.0)) < 1e-7);
assert(std::abs(F[3] - (F[2] + 1.0)) < 1e-7);
assert(std::abs(F[4] - (F[3] + 0.5)) < 1e-7);
}
{ // testing function 'numint'
double s = 2.0;
std::vector<double> x = {0*s, 1*s, 2*s, 3*s, 4*s, 5*s};
std::vector<double> f = {0, 1, 1, 1, 0, -1};
std::vector<double> F = numint(x, f, 10.0);
assert(std::abs(F[0] - 10.0) < 1e-7);
assert(std::abs(F[1] - (F[0] + 0.5*s)) < 1e-7);
assert(std::abs(F[2] - (F[1] + 1.0*s)) < 1e-7);
assert(std::abs(F[3] - (F[2] + 1.0*s)) < 1e-7);
assert(std::abs(F[4] - (F[3] + 0.5*s)) < 1e-7);
assert(std::abs(F[5] - (F[4] - 0.5*s)) < 1e-7);
}
std::cout << "task2.test.cpp: all asserts passed" << std::endl;
return 0;
}

45
exercise3/task3.cpp Normal file
View File

@ -0,0 +1,45 @@
/// @file
/// @brief Task3: implementation
#include "task3.hpp" // sample_to_csv
#include "iue-io/csv.hpp" // iue::io::savetxt
#include "task2.hpp" // range|sample|numint|numdiff
/// @todo Include standard library headers as needed
#include <functional> // std::function
#include <vector> // std::vector
/// @brief This function
/// - samples a one-dimensional scalar function (f) in a provided interval and resolution,
// - approximates its derivative (df) and antiderivative (F) numerically, and
/// - produces a csv-file holding the discrete values in this form:
/// - csv-column layout: x, f, F, df
/// @param filepath
/// @param del Delimiter
/// @param comment Character designating a line as a comment
/// @param func Callable with a signature compatible with f(double) -> double
/// @param start Start of the interval
/// @param end End of the interval
/// @param N Number of values; assumption: N >= 2
void sample_to_csv(std::filesystem::path filepath, char del, char comments, std::function<double(double)> func,
double start, double end, unsigned int N) {
// Create a sequence of equidistant values in the interval [start, end]
std::vector<double> x = range(start, end, N);
// Sample the function 'func' at the locations 'x'
std::vector<double> f = sample(x, func);
// Approximate the derivative of 'f' at the locations 'x'
std::vector<double> df = numdiff(x, f);
// Approximate the antiderivative of 'f' at the locations 'x'
std::vector<double> F = numint(x, f, 0.0);
// Create a matrix holding the discrete values of 'x', 'f', 'F', and 'df'
std::vector<std::vector<double>> data(N, std::vector<double>(4));
for (unsigned int i = 0; i < N; ++i) {
data[i][0] = x[i];
data[i][1] = f[i];
data[i][2] = F[i];
data[i][3] = df[i];
}
// Save the matrix to a csv-file
iue::io::savetxt(filepath, data, del);
}

22
exercise3/task3.hpp Normal file
View File

@ -0,0 +1,22 @@
/// @file
/// @brief Task3: function declarations
#pragma once
#include <filesystem> // std::filesystem::path
#include <functional> // std::function
/// @brief This function
/// - samples a one-dimensional scalar function (f) in a provided interval and resolution,
// - approximates its derivative (df) and antiderivative (F) numerically, and
/// - produces a csv-file holding the discrete values in this form:
/// - csv-column layout: x, f, F, df
/// @param filepath
/// @param del Delimiter
/// @param comment Character designating a line as a comment
/// @param func Callable with a signature compatible with f(double) -> double
/// @param start Start of the interval
/// @param end End of the interval
/// @param N Number of values; assumption: N >= 2
void sample_to_csv(std::filesystem::path filepath, char del, char comments, std::function<double(double)> func,
double start, double end, unsigned int N);

50
exercise3/task3.py Normal file
View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
""" Task3: implementation """
import numpy as np
import matplotlib.pyplot as plt
def plot_discrete_function(csvfile, delimiter, comments, pngfile):
"""
Reads a csv-file containing discretized value of a function (f), its derivative (df) and antiderivative (F)
and plots all three functions over the discrete value of the interval (x).
Expected csv-column layout:
x, f, F, df
Requirements for the plot:
- axis labels
- a legend for the plotted data records
Implementation hints:
- use numpy.loadtxt(...) for loading the data from the csvfile
- use Matplotlib for plotting
Parameters
----------
csvfile : string
Name of the csv-file containing the discrete function
delimiter: character
Charater used to delimit individual values in the rows
comments: character
Charater (when used as first character in a row) denoting comment lines
pngfile : string
Name of the file where the plot is saved
"""
# load data from csv file
data = np.loadtxt(csvfile, delimiter=delimiter, comments=comments)
x = data[:, 0]
f = data[:, 1]
F = data[:, 2]
df = data[:, 3]
# plot the data
plt.plot(x, f, label='f')
plt.plot(x, F, label='F')
plt.plot(x, df, label='df')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.savefig(pngfile)
plt.close('all')

59
exercise3/task3.test.cpp Normal file
View File

@ -0,0 +1,59 @@
/// @file
/// @brief Task3: tests
#include "task3.hpp"
#include "iue-io/csv.hpp"
#include <cassert> // assert
#include <cmath> // std::sin
#include <filesystem> // std::filesystem::remove
#include <iostream> // std::cout|endl
#include <numbers> // std::numbers::pi
int main() {
{
auto f = [](double x) { return cos(x); };
auto df = [](double x) { return -sin(x); };
auto F = [](double x) { return sin(x) - (sin(0)); };
std::filesystem::path filename = "test.task3.cos.csv";
std::filesystem::remove(filename);
sample_to_csv(filename, ';', '#', f, 0, 2 * std::numbers::pi, 18);
auto table = iue::io::loadtxt(filename, ';', '#');
assert(table.size() == 18);
for (unsigned int r = 0; r != table.size(); ++r) {
assert(table[r].size() == 4);
assert(std::abs(f(table[r][0]) - table[r][1]) < 0.2);
assert(std::abs(F(table[r][0]) - table[r][2]) < 0.2);
assert(std::abs(df(table[r][0]) - table[r][3]) < 0.2);
}
}
{
auto f = [](double x) { return sin(x); };
auto df = [](double x) { return cos(x); };
auto F = [](double x) { return -cos(x) - (-cos(0)); };
std::filesystem::path filename = "test.task3.sin.csv";
std::filesystem::remove(filename);
sample_to_csv(filename, ';', '#', f, 0, 2 * std::numbers::pi, 360);
auto table = iue::io::loadtxt(filename, ';', '#');
assert(table.size() == 360);
for (unsigned int r = 0; r != table.size(); ++r) {
assert(table[r].size() == 4);
assert(std::abs(f(table[r][0]) - table[r][1]) < 0.01);
assert(std::abs(F(table[r][0]) - table[r][2]) < 0.01);
assert(std::abs(df(table[r][0]) - table[r][3]) < 0.01);
}
}
std::cout << "task3.test.cpp: all asserts passed" << std::endl;
return 0;
}

39
exercise3/task3.test.py Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env python3
""" Task3: tests """
import os
import unittest
import matplotlib.pyplot as plt
import task3
class Test(unittest.TestCase):
def test_plot_sin(self):
figname = "test.task3.sin.png"
if os.path.isfile(figname):
os.remove(figname)
plt.close('all')
task3.plot_discrete_function("test.task3.sin.csv",";","#",figname)
plt.close('all')
self.assertTrue(os.path.isfile(figname))
def test_plot_cos(self):
figname = "test.task3.cos.png"
if os.path.isfile(figname):
os.remove(figname)
plt.close('all')
task3.plot_discrete_function("test.task3.cos.csv",";","#",figname)
plt.close('all')
self.assertTrue(os.path.isfile(figname))
if __name__ == "__main__":
unittest.main()

10
exercise4/.clang-format Normal file
View File

@ -0,0 +1,10 @@
---
BasedOnStyle: LLVM
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
ColumnLimit: 120
TabWidth: 4
IndentWidth: 2
...

25
exercise4/.clangd Normal file
View File

@ -0,0 +1,25 @@
# debug: clangd --check=modules/iue-io/ccsv.h
# debug: clangd --check=task1.hpp
# debug: clangd --check=task1.test.cpp
InlayHints:
Enabled: No
ParameterNames: Yes
DeducedTypes: No
---
CompileFlags:
Add:
# - --target=x86_64-w64-windows-gnu
# - --target=x86_64-pc-linux-gnu
- -Wall
- -Wno-unused-function
- -Wno-unused-variable
---
If:
PathMatch: [.*\.c, .*\.h]
CompileFlags:
Add: [-std=c11]
---
If:
PathMatch: [.*\.cpp, .*\.hpp]
CompileFlags:
Add: [-std=c++20]

3
exercise4/.ctests Normal file
View File

@ -0,0 +1,3 @@
task1
task2
task3

View File

@ -0,0 +1,3 @@
task1.main.cpp
task2.cpp
task3.cpp

16
exercise4/.gitattributes vendored Normal file
View File

@ -0,0 +1,16 @@
## source: https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.h text
*.hpp text
*.c text
*.cpp text
*.py text
*.ipynb text
*.md text
*.txt text
*.csv text

360
exercise4/.gitignore vendored Normal file
View File

@ -0,0 +1,360 @@
# custom
*.csv
*.png
build
doc
.cache
.vscode
.idea
# https://github.com/github/gitignore/blob/main/CMake.gitignore
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
# ttps://github.com/github/gitignore/blob/main/C.gitignore
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# https://github.com/github/gitignore/blob/main/C%2B%2B.gitignore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# source: https://github.com/github/gitignore/blob/main/Python.gitignore
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# jetbrain IDEs: https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# VSCODE source: https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix

4
exercise4/.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "modules"]
path = modules
url = https://sgit.iue.tuwien.ac.at/360050/modules
branch = main

50
exercise4/CMakeLists.txt Normal file
View File

@ -0,0 +1,50 @@
cmake_minimum_required(VERSION 3.20)
# define project metadata
project(exercise4 LANGUAGES CXX
DESCRIPTION "exercise4"
HOMEPAGE_URL "https://sgit.iue.tuwien.ac.at/360050/exercise4")
# setting required language standards
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)
# misc settings
# avoid ctest dashboard targets
set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1)
# generate a compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# make all symbols visible on windows (which is default on unix)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# options
option(BUILD_TESTING "enable testing with ctest" ON)
# testing
include(CTest)
# get/setup dependencies
include_directories(modules)
# include own targets
add_executable(task1 task1.main.cpp)
add_test(NAME task1 COMMAND task1 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set_property(TEST task1 PROPERTY PASS_REGULAR_EXPRESSION "(-112|-1\\.120000e\\+02)")
set_property(TEST task1 PROPERTY PASS_REGULAR_EXPRESSION "(-221|-2\\.110000e\\+02)")
set_property(TEST task1 PROPERTY PASS_REGULAR_EXPRESSION "(42|4\\.200000e\\+01)")
set_property(TEST task1 PROPERTY PASS_REGULAR_EXPRESSION "(-23|-2\\.300000e\\+01)")
add_executable(task2 task2.cpp task2.misc.cpp task2.test.cpp)
add_test(NAME task2 COMMAND task2 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(task3 task2.cpp task2.misc.cpp task3.cpp task3.misc.cpp task3.test.cpp)
add_test(NAME task3 COMMAND task3 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})

19
exercise4/README.md Normal file
View File

@ -0,0 +1,19 @@
# Hausübung 4 (3 Punkte)
**Ausgabe**: Dienstag 16. April 2024, vormittags (Ursprünglich Donnerstag 11. April 2024).
**Abgabe bis**: Montag 29. April 2024, Ende des Tages. (Ursprünglich Montag 22. April)
**Abgabe via**: git-Repository mit dem Namen **`exercise4`** auf unserem git-Server https://sgit.iue.tuwien.ac.at
Details zum Abgabeprozess via `git` finden Sie hier: https://sgit.iue.tuwien.ac.at/360050/git
# Aufgabenstellung
In dieser Hausübung werden folgende Themen erstmalig einfliessen:
- Klassen mit ausschließlich öffentlichen Member Variablen (ohne benutzerdefinierte Konstruktoren)
- Member Funktionen
- Nutzung von selbst implementierter Funktionalität in einem separaten Anwendungskontext
**Die genaue Beschreibung und Anforderungen finden Sie in [`main.ipynb`](main.ipynb) und im Quellcode.**

View File

@ -0,0 +1 @@
-Imodules

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 116 KiB

265
exercise4/images/trains.svg Normal file
View File

@ -0,0 +1,265 @@
<svg preserveAspectRatio='xMidYMid meet' version='1.1' xmlns='http://www.w3.org/2000/svg' viewbox='-16.9557 -3.85356 800 34.6821 ' height='34.682081' width='800.000000'>
<g>
<polygon fill='none' stroke='black' stroke-width='1' points='1.54143,30.8285 1.54143,19.2678 0,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='18.1118,16.9557 16.185,14.6435 20.0385,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='41.6185,30.8285 41.6185,19.2678 40.0771,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='58.1888,16.9557 56.262,14.6435 60.1156,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='81.6956,30.8285 81.6956,19.2678 80.1541,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='98.2659,16.9557 96.3391,14.6435 100.193,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='121.773,30.8285 121.773,19.2678 120.231,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='138.343,16.9557 136.416,14.6435 140.27,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='161.85,30.8285 161.85,19.2678 160.308,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='178.42,16.9557 176.493,14.6435 180.347,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='201.927,30.8285 201.927,19.2678 200.385,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='218.497,16.9557 216.57,14.6435 220.424,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='242.004,30.8285 242.004,19.2678 240.462,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='258.574,16.9557 256.647,14.6435 260.501,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='282.081,30.8285 282.081,19.2678 280.539,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='298.651,16.9557 296.724,14.6435 300.578,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='322.158,30.8285 322.158,19.2678 320.617,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='338.728,16.9557 336.802,14.6435 340.655,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='362.235,30.8285 362.235,19.2678 360.694,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='378.805,16.9557 376.879,14.6435 380.732,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='402.312,30.8285 402.312,19.2678 400.771,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='418.882,16.9557 416.956,14.6435 420.809,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='442.389,30.8285 442.389,19.2678 440.848,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='458.96,16.9557 457.033,14.6435 460.886,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='482.466,30.8285 482.466,19.2678 480.925,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='499.037,16.9557 497.11,14.6435 500.963,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='522.543,30.8285 522.543,19.2678 521.002,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='539.114,16.9557 537.187,14.6435 541.04,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='562.62,30.8285 562.62,19.2678 561.079,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='579.191,16.9557 577.264,14.6435 581.118,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='602.697,30.8285 602.697,19.2678 601.156,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='619.268,16.9557 617.341,14.6435 621.195,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='642.775,30.8285 642.775,19.2678 641.233,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='659.345,16.9557 657.418,14.6435 661.272,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='682.852,30.8285 682.852,19.2678 681.31,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='699.422,16.9557 697.495,14.6435 701.349,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='722.929,30.8285 722.929,19.2678 721.387,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='739.499,16.9557 737.572,14.6435 741.426,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='763.006,30.8285 763.006,19.2678 761.464,25.0482 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='779.576,16.9557 777.649,14.6435 781.503,14.6435 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='1.54143,30.8285 38.5356,30.8285 38.5356,19.2678 1.54143,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='16.9557,19.2678 19.2678,19.2678 19.2678,15.4143 16.9557,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='30.8285,19.2678 38.5356,19.2678 38.5356,11.5607 30.8285,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='41.6185,30.8285 78.6127,30.8285 78.6127,19.2678 41.6185,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='57.0328,19.2678 59.3449,19.2678 59.3449,15.4143 57.0328,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='70.9056,19.2678 78.6127,19.2678 78.6127,11.5607 70.9056,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='81.6956,30.8285 118.69,30.8285 118.69,19.2678 81.6956,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='97.1098,19.2678 99.422,19.2678 99.422,15.4143 97.1098,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='110.983,19.2678 118.69,19.2678 118.69,11.5607 110.983,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='121.773,30.8285 158.767,30.8285 158.767,19.2678 121.773,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='137.187,19.2678 139.499,19.2678 139.499,15.4143 137.187,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='151.06,19.2678 158.767,19.2678 158.767,11.5607 151.06,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='161.85,30.8285 198.844,30.8285 198.844,19.2678 161.85,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='177.264,19.2678 179.576,19.2678 179.576,15.4143 177.264,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='191.137,19.2678 198.844,19.2678 198.844,11.5607 191.137,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='201.927,30.8285 238.921,30.8285 238.921,19.2678 201.927,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='217.341,19.2678 219.653,19.2678 219.653,15.4143 217.341,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='231.214,19.2678 238.921,19.2678 238.921,11.5607 231.214,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='242.004,30.8285 278.998,30.8285 278.998,19.2678 242.004,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='257.418,19.2678 259.73,19.2678 259.73,15.4143 257.418,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='271.291,19.2678 278.998,19.2678 278.998,11.5607 271.291,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='282.081,30.8285 319.075,30.8285 319.075,19.2678 282.081,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='297.495,19.2678 299.807,19.2678 299.807,15.4143 297.495,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='311.368,19.2678 319.075,19.2678 319.075,11.5607 311.368,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='322.158,30.8285 359.152,30.8285 359.152,19.2678 322.158,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='337.572,19.2678 339.884,19.2678 339.884,15.4143 337.572,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='351.445,19.2678 359.152,19.2678 359.152,11.5607 351.445,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='362.235,30.8285 399.229,30.8285 399.229,19.2678 362.235,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='377.649,19.2678 379.961,19.2678 379.961,15.4143 377.649,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='391.522,19.2678 399.229,19.2678 399.229,11.5607 391.522,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='402.312,30.8285 439.306,30.8285 439.306,19.2678 402.312,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='417.726,19.2678 420.039,19.2678 420.039,15.4143 417.726,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='431.599,19.2678 439.306,19.2678 439.306,11.5607 431.599,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='442.389,30.8285 479.383,30.8285 479.383,19.2678 442.389,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='457.803,19.2678 460.116,19.2678 460.116,15.4143 457.803,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='471.676,19.2678 479.383,19.2678 479.383,11.5607 471.676,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='482.466,30.8285 519.461,30.8285 519.461,19.2678 482.466,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='497.881,19.2678 500.193,19.2678 500.193,15.4143 497.881,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='511.753,19.2678 519.461,19.2678 519.461,11.5607 511.753,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='522.543,30.8285 559.538,30.8285 559.538,19.2678 522.543,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='537.958,19.2678 540.27,19.2678 540.27,15.4143 537.958,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='551.83,19.2678 559.538,19.2678 559.538,11.5607 551.83,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='562.62,30.8285 599.615,30.8285 599.615,19.2678 562.62,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='578.035,19.2678 580.347,19.2678 580.347,15.4143 578.035,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='591.908,19.2678 599.615,19.2678 599.615,11.5607 591.908,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='602.697,30.8285 639.692,30.8285 639.692,19.2678 602.697,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='618.112,19.2678 620.424,19.2678 620.424,15.4143 618.112,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='631.985,19.2678 639.692,19.2678 639.692,11.5607 631.985,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='642.775,30.8285 679.769,30.8285 679.769,19.2678 642.775,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='658.189,19.2678 660.501,19.2678 660.501,15.4143 658.189,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='672.062,19.2678 679.769,19.2678 679.769,11.5607 672.062,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='682.852,30.8285 719.846,30.8285 719.846,19.2678 682.852,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='698.266,19.2678 700.578,19.2678 700.578,15.4143 698.266,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='712.139,19.2678 719.846,19.2678 719.846,11.5607 712.139,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='722.929,30.8285 759.923,30.8285 759.923,19.2678 722.929,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='738.343,19.2678 740.655,19.2678 740.655,15.4143 738.343,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='752.216,19.2678 759.923,19.2678 759.923,11.5607 752.216,11.5607 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='763.006,30.8285 800,30.8285 800,19.2678 763.006,19.2678 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='778.42,19.2678 780.732,19.2678 780.732,15.4143 778.42,15.4143 '/>
<polygon fill='none' stroke='black' stroke-width='1' points='792.293,19.2678 800,19.2678 800,11.5607 792.293,11.5607 '/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='5.780347'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='10.404624'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='16.955684'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='25.433526'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='33.911368'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='16.955684'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='19.267823'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='21.579961'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='45.857418'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='50.481696'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='57.032755'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='65.510597'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='73.988439'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='57.032755'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='59.344894'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='61.657033'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='85.934489'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='90.558767'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='97.109827'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='105.587669'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='114.065511'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='97.109827'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='99.421965'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='101.734104'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='126.011561'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='130.635838'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='137.186898'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='145.664740'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='154.142582'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='137.186898'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='139.499037'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='141.811175'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='166.088632'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='170.712909'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='177.263969'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='185.741811'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='194.219653'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='177.263969'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='179.576108'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='181.888247'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='206.165703'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='210.789981'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='217.341040'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='225.818882'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='234.296724'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='217.341040'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='219.653179'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='221.965318'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='246.242775'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='250.867052'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='257.418112'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='265.895954'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='274.373796'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='257.418112'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='259.730250'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='262.042389'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='286.319846'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='290.944123'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='297.495183'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='305.973025'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='314.450867'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='297.495183'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='299.807322'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='302.119461'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='326.396917'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='331.021195'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='337.572254'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='346.050096'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='354.527938'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='337.572254'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='339.884393'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='342.196532'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='366.473988'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='371.098266'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='377.649326'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='386.127168'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='394.605010'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='377.649326'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='379.961464'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='382.273603'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='406.551060'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='411.175337'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='417.726397'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='426.204239'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='434.682081'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='417.726397'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='420.038536'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='422.350674'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='446.628131'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='451.252408'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='457.803468'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='466.281310'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='474.759152'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='457.803468'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='460.115607'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='462.427746'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='486.705202'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='491.329480'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='497.880539'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='506.358382'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='514.836224'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='497.880539'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='500.192678'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='502.504817'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='526.782274'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='531.406551'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='537.957611'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='546.435453'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='554.913295'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='537.957611'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='540.269750'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='542.581888'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='566.859345'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='571.483622'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='578.034682'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='586.512524'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='594.990366'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='578.034682'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='580.346821'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='582.658960'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='606.936416'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='611.560694'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='618.111753'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='626.589595'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='635.067437'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='618.111753'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='620.423892'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='622.736031'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='647.013487'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='651.637765'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='658.188825'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='666.666667'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='675.144509'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='658.188825'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='660.500963'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='662.813102'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='687.090559'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='691.714836'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='698.265896'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='706.743738'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='715.221580'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='698.265896'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='700.578035'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='702.890173'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='727.167630'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='731.791908'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='738.342967'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='746.820809'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='755.298651'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='738.342967'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='740.655106'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='742.967245'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='767.244701'/>
<circle fill='none' stroke='black' r='1.926782' cy='32.755299' stroke-width='1' cx='771.868979'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='778.420039'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='786.897881'/>
<circle fill='none' stroke='black' r='3.853565' cy='30.828516' stroke-width='1' cx='795.375723'/>
<circle fill='none' stroke='black' r='0.770713' cy='13.102119' stroke-width='1' cx='778.420039'/>
<circle fill='none' stroke='black' r='1.541426' cy='10.019268' stroke-width='1' cx='780.732177'/>
<circle fill='none' stroke='black' r='3.853565' cy='3.853565' stroke-width='1' cx='783.044316'/>
<polygon fill='none' stroke='black' stroke-width='1' points='0,34.6821 800,34.6821 800,0 0,0 '/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 28 KiB

256
exercise4/main.ipynb Normal file
View File

@ -0,0 +1,256 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 1: Ein eigenes kleines C++-Programm (*coordinate rotation*) (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Erstellen Sie in [`task1.main.cpp`](task1.main.cpp) ein lauffähiges Ein-Dateien-Programm das folgende Struktur aufweist:\n",
"\n",
"- Einbinden benötigter Header-Dateien aus der Standardbibliothek, z.B.:\n",
"\t```cpp\n",
"\t#include <array> // std::array\n",
"\t#include <cmath> // std::sin, std::cos\n",
"\t#include <iostream> // std::cout, std::endl\n",
"\t#include <numbers> // std::numbers::pi\n",
"\t...\n",
"\t```\n",
"- Definition/Implementierung einer eigenen Funktion in einem eignene Namensraum, z.B.:\n",
"\t```cpp\n",
"\tnamespace task1 {\n",
"\n",
"\tusing Coord = std::array<double, 2>;\n",
"\n",
"\tCoord rotate_counter_clockwise(Coord coord, double angle) {\n",
"\t\t...\n",
"\t}\n",
"\t``` \n",
"- Definition/Implementierung einer `main`-Funktion, die Ihre selbst geschriebene Funktion verwendet und die berechneten Ergebnisse in der Konsole ausgibt, z.B.:\n",
"\t```cpp\n",
"\tint main(){\n",
"\t ...\n",
"\t auto [xrot, yrot] = rotate_counter_clockwise(...)\t\n",
"\t std::cout << xrot << \" \" << yrot << std::endl;\n",
"\t return 0;\n",
"\t}\n",
"\t``` \n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Eine genaue Beschreibung und Anforderungen finden Sie in [`task1.main.cpp`](task1.main.cpp)\n",
"- Ihre Implementierung erfolgt ebenfalls in [`task1.main.cpp`](task1.main.cpp)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 2: Member Funktionen und Klassen-Invarianten (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Gegeben ist die Definition dreier Klassen `BBox`, `Cirlce` und `Triangle`. Die Klassen sind sog. `aggregate`-Klassen und weisen u.A. folgende Eigenschaften auf:\n",
"\n",
"- Ausschließlich öffentliche Member-Variablen\n",
"- Keine benutzerdefinierten Konstruktoren\n",
"- Parameterlose Konstruktion möglich, z.B. `Aggregate aggregate = {};`\n",
"- Listen-Initialisierung ist möglich, z.B. `Aggregate aggregate = { value1, valu2 };`\n",
"- Struktuierte Zuweisung ist möglich, z.B. `const auto& [m1, m2] = aggregate;`\n",
"\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Implementieren Sie die folgenden Member-Funktionen:\n",
"\n",
"```cpp\n",
"namespace task2 {\n",
"\n",
"using Vec2d = std::array<double, 2>;\n",
"\n",
"/// @brief Axis-aligned bounding box\n",
"struct BBox {\n",
" Vec2d min; ///< coord of bottom left corner\n",
" Vec2d max; ///< coord of top right corner\n",
" BBox scale(const Vec2d& org, double s) const; // todo\n",
" BBox translate(const Vec2d& offset) const; // todo\n",
" bool check_invariants() const; // todo\n",
"};\n",
"\n",
"/// @brief Circle\n",
"struct Circle {\n",
" Vec2d c; ///< coordinate of the center of the circle\n",
" double r; ///< radius of the circle\n",
" BBox bbox() const; // todo\n",
" Circle scale(const Vec2d& org, double s) const; // todo\n",
" Circle rotate(const Vec2d& org, double angle) const; // todo\n",
" Circle translate(const Vec2d& offset) const; // todo\n",
" bool check_invariants() const; // todo\n",
"};\n",
"\n",
"/// @brief Triangle\n",
"struct Triangle {\n",
" std::array<Vec2d, 3> abc; ///< three corner points of the triangle\n",
" BBox bbox() const; // todo\n",
" Triangle scale(const Vec2d& org, double s) const; // todo\n",
" Triangle rotate(const Vec2d& org, double angle) const;// todo\n",
" Triangle translate(const Vec2d& offset) const; // todo\n",
" bool check_invariants() const; // todo\n",
"};\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklarationen und eine genaue Beschreibung und Anforderungen finden Sie in [`task2.hpp`](task2.hpp)\n",
"- Ihre Implementierung erfolgt in [`task2.cpp`](task2.cpp)\n",
"- Die zugeordneten Tests finden Sie in [`task2.test.cpp`](task2.test.cpp)\n",
"- In [`task2.misc.hpp`](task2.misc.hpp)/[`task2.misc.cpp`](task2.misc.cpp) sind Hilfsfunktionen zum Ausgeben und Vergleichen der drei Klassen gegeben (diese werden bei den Tests verwendet, stehen Ihnen aber auch für Ihre Implementierung zur Verfügung).\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 3: Nutzung von bereitgestellter Funktionalität sowie der Implementierung aus Aufgabe 2 zum Erstellen einer eigenen `.svg`-Grafik (1 Punkt)\n",
"\n",
"Sie sollten die Funktionalität, die Sie in Aufgabe 2 implementiert haben (Skalieren/Verschieben/Rotieren) nun selbst nutzen um eine `.svg`-Grafik zu erstellen.\n",
"\n",
"Nutzen Sie die bereitgestellte Funktion `task3::render_wrapper` um die `.svg`-Grafik zu generieren: Sie können die Typen aus Aufgabe 2 (`BBox/Circle/Triangle`) direkt übergeben:\n",
"\n",
"```cpp\n",
"// std::vector<task2::BBox> boxes = [ ... ]\n",
"// std::vector<task2::Circle> circles = [ ... ]\n",
"// std::vector<task2::Triangle> triangles = [ ... ]\n",
"task3::render_wrapper(\"myimage.svg\", boxes, triangles, triangles);\n",
"```\n",
"\n",
"Es gibt keine Vorgaben, lediglich, dass die erstellte Grafik mindestens 20 Elemente (Boxen/Kreise/Dreiecke) enthalten muss. \n",
"\n",
"Hier ein Beispiel wie so etwas aussehen kann \n",
"\n",
"- horizontal verschobene und skalierte \"Häuser\" mit \"Himmel\" aus zufällig angeordneten Kreisen:\n",
"\n",
"\t![images/dusty_nikolaus_city.svg](images/dusty_nikolaus_city.svg)\n",
"\n",
"- horizontal verschobene \"Lokomotiven\"\n",
"\n",
"\t![images/trains.svg](images/trains.svg)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Implementieren Sie folgende Funktion:\n",
"\n",
"```cpp\n",
"\n",
"namespace task3 {\n",
"\n",
"int render_something(std::filesystem::path filepath); // todo\n",
"\n",
"}\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklaration und eine genaue Beschreibung und Anforderungen finden Sie in [`task3.hpp`](task3.hpp)\n",
"- Ihre Implementierung erfolgt in [`task3.cpp`](task3.cpp)\n",
"- Die zugeordneten Tests finden Sie in [`task3.test.cpp`](task3.test.cpp)\n",
"- In [`task3.misc.hpp`](task3.misc.hpp)/[`task3.misc.cpp`](task3.misc.cpp) finden Sie die oben erwähnte Hilfsfunktion `task3::render_wrapper`.\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Kompilieren/Testen\n",
"\n",
"So testen Sie Ihre Implementierung (direkter Aufruf von `g++` und `python`):\n",
"\n",
"```shell\n",
"# prepare\n",
"mkdir build\n",
"# compile\n",
"g++ -g -std=c++20 task1.main.cpp -o build/task1\n",
"g++ -g -Imodules -std=c++20 task2.cpp task2.misc.cpp task2.test.cpp -o build/task2\n",
"g++ -g -Imodules -std=c++20 task2.cpp task2.misc.cpp task3.cpp task3.misc.cpp task3.test.cpp -o build/task3\n",
"\n",
"# run tests\n",
"./build/task1\n",
"./build/task2\n",
"./build/task3\n",
"```\n",
"\n",
"Alternativ (mittels CMake-Configuration):s\n",
"\n",
"```shell\n",
"# prepare\n",
"cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug\n",
"# compile\n",
"cmake --build build --config Debug --target task1\n",
"cmake --build build --config Debug --target task2\n",
"cmake --build build --config Debug --target task3\n",
"cmake --build build --config Debug # all\n",
"# run tests\n",
"ctest --test-dir build -C Debug -R task1 \n",
"ctest --test-dir build -C Debug -R task2 \n",
"ctest --test-dir build -C Debug -R task3 \n",
"ctest --test-dir build -C Debug # all\n",
"``` \n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.6.15"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

1
exercise4/modules Submodule

@ -0,0 +1 @@
Subproject commit df348de23a73810279468501510b754bc622797f

43
exercise4/task1.main.cpp Normal file
View File

@ -0,0 +1,43 @@
/// @file
/// @brief Task1: "single-file" excutable C++ program
/// @todo Include standard library headers as needed
#include <array> // std::array
#include <cmath>
#include <iostream>
namespace task1 {
using Coord = std::array<double, 2>;
/// @todo Implement a function 'rotate_counter_clockwise' according to the description below:
/// - the function receives a two-dimensional coordinate in form of a 'std::array<double, 2>'
/// - the function receives a rotation angle (in radians) in form of a 'double'
/// - the function rotates the coordinate counter clockwise around the origin
/// - the function returns the rotated coordinate as a std::array<double, 2>
std::array<double, 2> rotate_counter_clockwise(const Coord& coord, double angle) {
std::array<double, 2> rotated_coord = {0, 0};
rotated_coord[0] = coord[0] * cos(angle) - coord[1] * sin(angle);
rotated_coord[1] = coord[0] * sin(angle) + coord[1] * cos(angle);
return rotated_coord;
}
} // namespace task1
/// @todo Implement a main function conducting the following tasks in this order:
/// - Create two coordinates (local variables):
/// - std::array<double, 2> coord1 = {112,211};
/// - std::array<double, 2> coord2 = {-42,23};
/// - Use your 'rotate_counter_clockwise' function to rotate both coordinate by 180 degrees
/// - Print the resulting rotated coordinates to the console
/// - Hint: the expected coordinates after rotating 180 degrees are
/// - std::array<double, 2> coord1_rotated = {-112,-211};
/// - std::array<double, 2> coord2_rotated = {42,-23};
int main() {
std::array<double, 2> coord1 = {112, 211};
std::cout << "Original coord1: " << coord1[0] << ", " << coord1[1] << std::endl;
std::array<double, 2> coord1_rotated = task1::rotate_counter_clockwise(coord1, std::numbers::pi_v<double>);
std::cout << "Rotated coord1: " << coord1_rotated[0] << ", " << coord1_rotated[1] << std::endl;
return 0;
}

171
exercise4/task2.cpp Normal file
View File

@ -0,0 +1,171 @@
/// @file
/// @brief Task2: member function definitions/implementations
#include "task2.hpp" // task2::Vec2, task2::BBox, task2::Circle, task2::Triangle
#include "task2.misc.hpp" // task2::operator<<, task2::isnan, task2::isclose
#include "modules/iue-num/numerics.hpp" // iue::num::isclose
/// @todo Include standard library headers as needed
namespace task2 {
/// ==================================== Bounding Box =================================================
/// @todo Implement the missing member functions for bounding box as declared and specified in task2.hpp
/// @todo implement member function 'BBox::scale'
BBox BBox::scale(const Vec2d& org, double s) const {
BBox scaled_box = *this;
scaled_box.min[0] = org[0] + s * (min[0] - org[0]);
scaled_box.min[1] = org[1] + s * (min[1] - org[1]);
scaled_box.max[0] = org[0] + s * (max[0] - org[0]);
scaled_box.max[1] = org[1] + s * (max[1] - org[1]);
return scaled_box;
}
/// @todo implement member function 'BBox::translate'
BBox BBox::translate(const Vec2d& offset) const {
BBox translated_box = *this;
translated_box.min[0] += offset[0];
translated_box.min[1] += offset[1];
translated_box.max[0] += offset[0];
translated_box.max[1] += offset[1];
return translated_box;
}
/// @todo implement member function 'BBox::check_invariants'
bool BBox::check_invariants() const {
if (std::isnan(min[0]) || std::isnan(min[1]) || std::isnan(max[0]) || std::isnan(max[1])) {
return false;
}
if (min[0] > max[0] || min[1] > max[1]) {
return false;
}
if (iue::num::isclose(min[0], max[0]) && iue::num::isclose(min[1], max[1])) {
return false;
}
return true;
}
/// ==================================== Circle ================================================
/// @todo Implement the missing member functions for Circle as declared and specified in task2.hpp
/// @todo implement member function 'Circle::bbox'
BBox Circle::bbox() const {
BBox box = {{c[0] - r, c[1] - r}, {c[0] + r, c[1] + r}};
return box;
}
/// @todo implement member function 'Circle::scale'
Circle Circle::scale(const Vec2d& org, double s) const {
Circle scaled_circle = *this;
scaled_circle.c[0] = org[0] + s * (c[0] - org[0]);
scaled_circle.c[1] = org[1] + s * (c[1] - org[1]);
scaled_circle.r *= s;
return scaled_circle;
}
/// @todo implement member function 'Circle::rotate'
Circle Circle::rotate(const Vec2d& org, double angle) const {
Circle rotated_circle = *this;
double x = c[0] - org[0];
double y = c[1] - org[1];
rotated_circle.c[0] = org[0] + x * cos(angle) - y * sin(angle);
rotated_circle.c[1] = org[1] + x * sin(angle) + y * cos(angle);
return rotated_circle;
}
/// @todo implement member function 'Circle::translate'
Circle Circle::translate(const Vec2d& offset) const {
Circle translated_circle = *this;
translated_circle.c[0] += offset[0];
translated_circle.c[1] += offset[1];
return translated_circle;
}
/// @todo implement member function 'Circle::check_invariants'
bool Circle::check_invariants() const {
if (std::isnan(c[0]) || std::isnan(c[1]) || std::isnan(r)) {
return false;
}
if (r < 0) {
return false;
}
return true;
}
/// ==================================== Triangle ================================================
/// @todo Implement the missing member functions for Triangle as declared and specified in task2.hpp
/// @todo implement member function 'Triangle::bbox'
BBox Triangle::bbox() const {
BBox box = {{abc[0][0], abc[0][1]}, {abc[0][0], abc[0][1]}};
for (int i = 1; i < 3; i++) {
if (abc[i][0] < box.min[0]) {
box.min[0] = abc[i][0];
}
if (abc[i][0] > box.max[0]) {
box.max[0] = abc[i][0];
}
if (abc[i][1] < box.min[1]) {
box.min[1] = abc[i][1];
}
if (abc[i][1] > box.max[1]) {
box.max[1] = abc[i][1];
}
}
return box;
}
/// @todo implement member function 'Triangle::scale'
Triangle Triangle::scale(const Vec2d& org, double s) const {
Triangle scaled_triangle = *this;
for (int i = 0; i < 3; i++) {
scaled_triangle.abc[i][0] = org[0] + s * (abc[i][0] - org[0]);
scaled_triangle.abc[i][1] = org[1] + s * (abc[i][1] - org[1]);
}
return scaled_triangle;
}
/// @todo implement member function 'Triangle::rotate'
Triangle Triangle::rotate(const Vec2d& org, double angle) const {
Triangle rotated_triangle = *this;
for (int i = 0; i < 3; i++) {
double x = abc[i][0] - org[0];
double y = abc[i][1] - org[1];
rotated_triangle.abc[i][0] = org[0] + x * cos(angle) - y * sin(angle);
rotated_triangle.abc[i][1] = org[1] + x * sin(angle) + y * cos(angle);
}
return rotated_triangle;
}
/// @todo implement member function 'Triangle::translate'
Triangle Triangle::translate(const Vec2d& offset) const {
Triangle translated_triangle = *this;
for (int i = 0; i < 3; i++) {
translated_triangle.abc[i][0] += offset[0];
translated_triangle.abc[i][1] += offset[1];
}
return translated_triangle;
}
/// @todo implement member function 'Triangle::bbox'
bool Triangle::check_invariants() const {
if (std::isnan(abc[0][0]) || std::isnan(abc[0][1]) || std::isnan(abc[1][0]) || std::isnan(abc[1][1]) || std::isnan(abc[2][0]) || std::isnan(abc[2][1])) {
return false;
}
if (iue::num::isclose(abc[0][0], abc[1][0]) && iue::num::isclose(abc[0][1], abc[1][1])) {
return false;
}
if (iue::num::isclose(abc[0][0], abc[2][0]) && iue::num::isclose(abc[0][1], abc[2][1])) {
return false;
}
if (iue::num::isclose(abc[1][0], abc[2][0]) && iue::num::isclose(abc[1][1], abc[2][1])) {
return false;
}
return true;
}
} // namespace task2

87
exercise4/task2.hpp Normal file
View File

@ -0,0 +1,87 @@
/// @file
/// @brief Task2: class definitions with member function declarations
#pragma once
#include <array> // std::array
namespace task2 {
using Vec2d = std::array<double, 2>;
/// @brief Axis-aligned bounding box
struct BBox {
Vec2d min; ///< coord of bottom left corner
Vec2d max; ///< coord of top right corner
/// @brief Scales the bounding box (relative to a reference coordinate)
/// @param org Reference coordinate
/// @param s Scaling factor
BBox scale(const Vec2d& org, double s) const;
/// @brief Translates the line
/// @param offset Translation vector
BBox translate(const Vec2d& offset) const;
/// @brief Checks if all invariants are fullfilled
/// @return false if any invariant is violated, true otherwise
/// Invariants:
/// - no coordinate is NAN
/// - the individual coordinates of 'min' are less or equal the respective coordinates in 'max'
/// - 'min' is not close to 'max' (use iue::num::isclose to check)
bool check_invariants() const;
};
/// @brief Circle
struct Circle {
Vec2d c; ///< coordinate of the center of the circle
double r; ///< radius of the circle
/// @brief Generates the minimum axis-aligned bounding box containing this circle
/// @return axis-aligned bounding box
BBox bbox() const;
/// @brief Scales the circle center (relative to a reference coordinate), and the radius with a scalar value
/// @param org Reference coordinate
/// @param s Scaling factor
Circle scale(const Vec2d& org, double s) const;
/// @brief Rotates the circle center (relative to a reference coordinate) counter clockwise
/// @param org Reference coordinate
/// @param angle Rotation angle (in radians)
Circle rotate(const Vec2d& org, double angle) const;
/// @brief Translates the circle center
/// @param offset Translation vector
Circle translate(const Vec2d& offset) const;
/// @brief Checks if all invariants are fullfilled
/// @return false if any invariant is violated, true otherwise
/// @note Invariants: radius is non-negative and no coordinate is NAN
bool check_invariants() const;
};
/// @brief Triangle
struct Triangle {
std::array<Vec2d, 3> abc; ///< three corner points of the triangle
/// @brief Generates the minimum axis-aligned bounding box containing this triangle
/// @return axis-aligned bounding box
BBox bbox() const;
/// @brief Scales the triangle (relative to a reference coordinate)
/// @param org Reference coordinate
/// @param s Scaling factor
Triangle scale(const Vec2d& org, double s) const;
/// @brief Rotates the triangle (relative to a reference coordinate) counter clockwise
/// @param org Reference coordinate
/// @param angle Rotation angle (in radians)
Triangle rotate(const Vec2d& org, double angle) const;
/// @brief Translates the line
/// @param offset Translation vector
Triangle translate(const Vec2d& offset) const;
/// @brief Checks if all invariants are fullfilled
/// @return false if any invariant is violated, true otherwise
/// Invariants:
/// - no coordinate is NAN
/// - none of the corner points are close to each other (use iue::num::isclose to check)
bool check_invariants() const;
};
} // namespace task2

Some files were not shown because too many files have changed in this diff Show More