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.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
+59
View File
@@ -0,0 +1,59 @@
cmake_minimum_required(VERSION 3.20)
# define project metadata
project(exercise8 LANGUAGES C
DESCRIPTION "exercise8"
HOMEPAGE_URL "https://sgit.iue.tuwien.ac.at/360050/exercise8")
# 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
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 "8")
add_executable(task2 task2.c task2.test.c
task2.test.c
task2.h
task2.c)
target_link_libraries(task2 PRIVATE ${MATH_LIBRARY})
add_test(NAME task2 COMMAND task2 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(task3 task2.c task3.c task3.test.c)
target_link_libraries(task3 PRIVATE ${MATH_LIBRARY})
add_test(NAME task3 COMMAND task3 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
+19
View File
@@ -0,0 +1,19 @@
# Hausübung 8 (3 Punkte)
**Ausgabe**: Donnerstag 16. Mai 2024, vormittags.
**Abgabe bis**: Montag 27. Mai 2024, Ende des Tages.
**Abgabe via**: git-Repository mit dem Namen **`exercise8`** 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:
- Sprache C: Kompilierbefehle
- Sprache C: Strukturen und Funktionen
- Sprache C: Übergabe von Feldern an Funktionen
**Die genaue Beschreibung und Anforderungen finden Sie in [`main.ipynb`](main.ipynb) und im Quellcode.**
+1
View File
@@ -0,0 +1 @@
-Imodules
+187
View File
@@ -0,0 +1,187 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgabe 1: Ein eigenes kleines C-Programm (*array as function parameter*) (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 <stdbool.h> // bool, true, false\n",
"\t#include <stdio.h> // printf\n",
"\t...\n",
"\t```\n",
"- Definition/Implementierung einer eigenen Funktion, z.B.:\n",
"\t```cpp\n",
"\tint task1_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 = task1_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: Reimplementierung von C++ Funktionalität in C (1 Punkt)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Sie reimplementieren die Funktionalität zweier Klassen, die Sie schon in Hausübung 4 (C++) implementiert:\n",
"\n",
"- [`exercise4::task2::BBox`](https://sgit.iue.tuwien.ac.at/360050/exercise4/src/commit/2e408ac941971e07971485282ef086d22cb0d974/task2.hpp#L13) \n",
"- [`exercise4::task2::Circle`](https://sgit.iue.tuwien.ac.at/360050/exercise4/src/commit/2e408ac941971e07971485282ef086d22cb0d974/task2.hpp#L35)\n",
"\n",
"Diesmal verwenden Sie die Sprache C:\n",
"\n",
"- Statt Memberfunktionen kommen freie Funktionen zum Einsatz\n",
"- Funktionsüberladungen werden durch Postfixe/Präfixe bei den Funktionsnamen realisiert\n",
"- Typen aus der C++ Standardbibliothek (hier z.B. `std::array<double, 2>` ) werden durch eigene Typen ersetzt\n",
"- Funktionalität aus der C++ Standardbibliothek (z.B. `std::cout`) wird mit entsprechender Funktionalität aus der C Standardbibliothek ( `printf` ) ersetzt."
]
},
{
"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: Übergabe von Feldern von Strukturen an Funktionen (1 Punkt)\n",
"\n",
"Sie implementieren zwei Funktionen an die ein Feld von Strukturen (aus Aufgabe 2) übergeben wird:"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"vscode": {
"languageId": "c"
}
},
"source": [
"```c\n",
"// todo: implement\n",
"unsigned int task3_count_inside(const struct BBox* box, const struct Circle circles[], unsigned int size);\n",
"\n",
"// todo: implement\n",
"struct BBox task3_common_bbox(const struct Circle circles[], unsigned int size);\n",
"```"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"- Die vorgegebenen Deklaration und eine genaue Beschreibung und Anforderungen finden Sie in [`task3.h`](task3.h)\n",
"- Ihre Implementierung erfolgt ebenfalls in [`task3.c`](task3.c)\n",
"- Die zugeordneten Tests finden Sie in [`task3.test.c`](task3.test.c)"
]
},
{
"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.c task3.test.c -o build/task3 -lm\n",
"\n",
"# run tests\n",
"./build/task1\n",
"./build/task2\n",
"./build/task3\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",
"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
}
+1
Submodule exercise8/modules added at 63b4f08052
+44
View File
@@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdbool.h>
bool isprime(unsigned int num) {
// Handle edge cases (0, 1, and even numbers greater than 2)
if (num <= 1 || num % 2 == 0 && num > 2) {
return false;
}
// Efficiently check divisibility only up to the square root of num
for (unsigned int i = 3; i * i <= num; i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
int count_primes(unsigned int values[], int size) {
int count = 0;
for (int i = 0; i < size; i++) {
if (isprime(values[i])) {
count++;
}
}
return count;
}
int main() {
unsigned int arr1[] = {1, 20, 21, 43, 32, 42, 2344, 42433, 6, 2, 0, 22, 45, 47, 1033, 1247};
int size1 = sizeof(arr1) / sizeof(arr1[0]);
unsigned int arr2[] = {21, 22, 44, 33, 7, 3, 1, 23, 46, 48, 1034, 1248};
int size2 = sizeof(arr2) / sizeof(arr2[0]);
int primes1 = count_primes(arr1, size1);
int primes2 = count_primes(arr2, size2);
int total_primes = primes1 + primes2;
printf("Total number of primes: %d\n", total_primes);
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
/// @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;
}
/// @todo Implement function 'matrix_zeros' as declared and specified in task2.h
struct Matrix matrix_zeros(size_t m, size_t n) { return (struct Matrix){.data = NULL, .m = 0, .n = 0}; }
/// @todo Implement function 'matrix_identity' as declared and specified in task2.h
struct Matrix matrix_identity(size_t n) { return (struct Matrix){.data = NULL, .m = 0, .n = 0}; }
/// @todo Implement function 'matrix_transpose' as declared and specified in task2.h
void matrix_transpose(struct Matrix* a) {}
/// @todo Implement function 'matrix_mult' as declared and specified in task2.h
void matrix_mult(const struct Matrix* a, const struct Matrix* b, struct Matrix* c) {}
+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 "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;
}
+54
View File
@@ -0,0 +1,54 @@
#include "task3.h" // task3_count_inside, task3_common_bbox
#include "task2.h" // struct Vec2d, struct BBox, struct Circle
#include <stdbool.h> // for bool (true/false)
/// @brief Count the number of Circles fully contained inside a bounding box
/// @param box Bounding box
/// @param circles Array of Circles
/// @param size Length of the 'circles' array
/// @return Number of circles fully contained inside 'box'
unsigned int task3_count_inside(const struct BBox* box, const struct Circle circles[], unsigned int size) {
unsigned int count = 0;
for (unsigned int i = 0; i < size; i++) {
const struct Circle* circle = &circles[i];
// Check if circle center is within box boundaries
bool inside_x = (circle->c.x - circle->r >= box->min.x) && (circle->c.x + circle->r <= box->max.x);
bool inside_y = (circle->c.y - circle->r >= box->min.y) && (circle->c.y + circle->r <= box->max.y);
if (inside_x && inside_y) {
count++;
}
}
return count;
}
/// @brief Generates the smallest bounding box containing a sequence of circles
/// @param circles Array of Circles
/// @param size Length of the 'circles' array (Assertion: size >= 1)
/// @return Smallest bounding box containing all circles
struct BBox task3_common_bbox(const struct Circle circles[], unsigned int size) {
struct BBox res;
// Initialize with first circle's data (assuming at least one circle)
res.min.x = circles[0].c.x - circles[0].r;
res.min.y = circles[0].c.y - circles[0].r;
res.max.x = circles[0].c.x + circles[0].r;
res.max.y = circles[0].c.y + circles[0].r;
for (unsigned int i = 1; i < size; i++) {
const struct Circle* circle = &circles[i];
// Update minimum bounds if circle's center falls outside current box
if (circle->c.x - circle->r < res.min.x) {
res.min.x = circle->c.x - circle->r;
}
if (circle->c.y - circle->r < res.min.y) {
res.min.y = circle->c.y - circle->r;
}
// Update maximum bounds if circle's edge falls outside current box
if (circle->c.x + circle->r > res.max.x) {
res.max.x = circle->c.x + circle->r;
}
if (circle->c.y + circle->r > res.max.y) {
res.max.y = circle->c.y + circle->r;
}
}
return res;
}
+19
View File
@@ -0,0 +1,19 @@
/// @file
/// @brief Task3: structure and function declarations
#pragma once
#include "task2.h" // struct Vec2d, struct BBox, struct Circle
/// @brief Count the number of Circles fully contained inside a bounding box
/// @param box Bounding box
/// @param circles Array of Circles
/// @param size Length of the 'circles' array
/// @return Number of circles fully contained inside 'box'
unsigned int task3_count_inside(const struct BBox* box, const struct Circle circles[], unsigned int size);
/// @brief Generates the smallest bounding box containing a sequence of circles
/// @param circles Array of Circles
/// @param size Length of the 'circles' array (Assertion: size >= 1)
/// @return Smallest bounding box containing all circles
struct BBox task3_common_bbox(const struct Circle circles[], unsigned int size);
+68
View File
@@ -0,0 +1,68 @@
/// @file
/// @brief Task3: tests
#include "task3.h" // task3_count_inside, task3_common_bbox
#include "task2.h" // struct Vec2d, struct BBox, struct Cirlce
#include "iue-num/numerics.h" // iuenum_isclose
#include <assert.h> // assert
#include <stdio.h> // printf
bool detail_isclose_vec2d(struct Vec2d a, struct Vec2d b) {
if (!iuenum_isclose(a.x, b.x))
return false;
if (!iuenum_isclose(a.y, b.y))
return false;
return true;
}
bool detail_isclose_bbox(const struct BBox* a, const struct BBox* b) {
if (!detail_isclose_vec2d(a->min, b->min))
return false;
if (!detail_isclose_vec2d(a->max, b->max))
return false;
return true;
}
int main() {
{ // testing 'task3_count_inside'
struct Vec2d min = {-1.6, -0.6};
struct Vec2d max = {3.6, 2.6};
struct BBox box = {min, max};
struct Circle c1 = {{0.0, 1.0}, 1.5};
struct Circle c2 = {{1.0, 1.0}, 1.5};
struct Circle c3 = {{2.0, 1.0}, 1.5};
struct Circle c4 = {{3.0, 1.0}, 1.5};
struct Circle c5 = {{4.0, 1.0}, 1.5};
struct Circle circles[5] = {c1, c2, c3, c4, c5};
unsigned int res = task3_count_inside(&box, circles, 5);
assert(res == 3);
}
{ // testing 'task3_common_bbox'
struct Circle c1 = {{0.0, 1.0}, 1.5};
struct Circle c2 = {{1.0, 1.0}, 1.5};
struct Circle c3 = {{2.0, 1.0}, 1.5};
struct Circle circles[3] = {c1, c2, c3};
struct BBox res = task3_common_bbox(circles, 3);
struct Vec2d exp_min = {-1.5, -0.5};
struct Vec2d exp_max = {3.5, 2.5};
struct BBox exp_box = {exp_min, exp_max};
assert(detail_isclose_bbox(&res,&exp_box));
}
printf("task3.test.c: all asserts passed\n");
return 0;
}