This commit is contained in:
2025-04-09 10:22:44 +02:00
commit 96ff5392c8
330 changed files with 28300 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
---
BasedOnStyle: LLVM
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
ColumnLimit: 120
TabWidth: 4
IndentWidth: 2
...
+25
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
View File
@@ -0,0 +1,3 @@
task1
task2
task3
+3
View File
@@ -0,0 +1,3 @@
task1.main.c
task2.c
task3.main.c
+16
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
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
View File
@@ -0,0 +1,4 @@
[submodule "modules"]
path = modules
url = https://sgit.iue.tuwien.ac.at/360050/modules
branch = main
+71
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
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.**
+1
View File
@@ -0,0 +1 @@
-Imodules
+5
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
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
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
+4
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
+4
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
Submodule exercise10/modules added at 33515ac3ad
+3
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
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
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
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
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
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
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
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;
}