diff --git a/MMS24-25.c b/MMS24-25.c index 09da683..e2ea698 100644 --- a/MMS24-25.c +++ b/MMS24-25.c @@ -11,19 +11,35 @@ * https://git.beimgraben.net/MMS-2024-25/MMS-Loesung-2024-25.git */ +// Standard Libraries #include -#include +#include #include +#include // For variadic functions +#include // For checking if a file exists +// Header File for this implementation #include "MMS24-25.h" -#include "math.h" + +// Preprocessor Definitions in case they are not defined +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +#ifndef NULL +#define NULL 0 +#endif // #region Error Handling and Debugging void _error(char *fmt, ...) { fprintf(stderr, "< \x1B[31;4;1mERROR\x1B[0m : \x1B[34m'"); + // Pass the arguments to the vfprintf function va_list args; va_start(args, fmt); + // Write to stderr so that the output does not interfere with the output vfprintf(stderr, fmt, args); va_end(args); @@ -34,6 +50,21 @@ void _error(char *fmt, ...) { #endif } +void _mem_error(char *fmt, ...) { + fprintf(stderr, "< \x1B[31;4;1mMEM_ERROR\x1B[0m : \x1B[34m'"); + + // Pass the arguments to the vfprintf function + va_list args; + va_start(args, fmt); + // Write to stderr so that the output does not interfere with the output + vfprintf(stderr, fmt, args); + va_end(args); + + fprintf(stderr, "'\x1B[0m >\n"); + + exit(EXIT_FAILURE); +} + void _debug(char *fmt, ...) { fprintf(stderr, "[ \x1B[37;4;1mDEBUG\x1B[0m ] \x1B[34m'"); @@ -58,6 +89,11 @@ void _warn(char *fmt, ...) { // #endregion // #region Aufgabe 1 + +/* + * Interpolates a line between two points (x1, y1) and (x2, y2) and returns + * the y-coordinate of the point on the line at xq. + */ double interpolateLine( double dX1, double dY1, @@ -66,6 +102,10 @@ double interpolateLine( double dXq ) { if (dX2 == dX1) + /* + * If the two x-coordinates are equal, the line is either vertical or + * could have any slope. In this case, we cannot interpolate the line. + */ _error("interpolateLine: dX1 and dX2 must differ!"); double y = dY1 * ( @@ -74,15 +114,19 @@ double interpolateLine( (dXq - dX1) / (dX2 - dX1) ); - #ifdef _DEBUG_ - // DEBUG: print the parameters and result - _debug("interpolateLine(%lf, %lf, %lf, %lf, %lf) -> %lf\n", - dX1,dY1,dX2,dY2,dXq,y); - #endif +#ifdef _DEBUG_ + // DEBUG: print the parameters and result + _debug("interpolateLine(%lf, %lf, %lf, %lf, %lf) -> %lf", + dX1,dY1,dX2,dY2,dXq,y); +#endif return y; } +/* + * Rescales an array of double values so that the minimum value is dMin and + * the difference between any two values is scaled by dFactor. + */ void rescaleDoubleArray( double *pdIn, int iLen, @@ -90,14 +134,21 @@ void rescaleDoubleArray( double dFactor, double *pdOut ) { - /* Rescale an array of double values, so that the following rules apply: + /* + * Rescale an array of double values, so that the following rules apply: * Given $ |pdIn| = |pdOut| = iLen $ it should be, that: - * $ min(pdIn) > dMin $, as well as + * $ min(pdIn) = dMin $, as well as * \[ \forall i, j \in (0,\dots,iLen-1): * (pdOut_i - pdOut_j) = (pdIn_i - pdIn_j) *dFactor \], * which naturally results from: - * $ pdOut_i = pdIn_i *dFactor + dMin $ + * $ pdOut_i = pdIn_i *dFactor + (dMin - min(pdIn)) $. */ + + if (iLen == 0) { + _warn("rescaleDoubleArray: iLen is 0"); + return; + } + // First find the old minimum double dOldMin = pdIn[0]; for (int i = 1; i < iLen; i++) { @@ -108,6 +159,11 @@ void rescaleDoubleArray( // Calculate the offset double dOffset = dMin - dOldMin; +#ifdef _DEBUG_ + _debug("rescaleDoubleArray: dOldMin = %lf", dOldMin); + _debug("rescaleDoubleArray: dOffset = %lf", dOffset); +#endif + // Rescale the array for (int i = 0; i < iLen; i++) { pdOut[i] = pdIn[i] * dFactor + dOffset; @@ -119,30 +175,47 @@ double *generateSineValues( int iNumSamplesPerPeriod, double dAmp ) { - /* Generate an array of `iNumValues` double value, so that the values + /* + * Generate an array of `iNumValues` double value, so that the values * represent the Y-coordinates of a sine curve of which one full period * occupies `iNumSamplesPerPeriod` values. */ + // Check for invalid input if (iNumSamplesPerPeriod == 0) + /* + * This is a fatal error, since we cannot generate a sine wave without + * a period + */ _error("*generateSineValues: iNumSamplesPerPeriod must be non-0!"); if (iNumSamplesPerPeriod < 0) + /* + * This would result in a flipped sine wave; Wont lead to a fatal error + * but is still invalid; Warn the user. + */ _warn("*generateSineValues: iNumSamplesPerPeriod is less than 0!"); if (iNumValues < 0) + /* + * It is not possible to generate a negative number of values; This is + * a fatal error. + */ _error("*generateSineValues: iNumValues must be equal to or greater than 0!"); if (iNumValues == 0) + /* + * This would result in an empty array; Won't lead to a fatal error but + * is still invalid; Warn the user. + */ _warn("*generateSineValues: iNumValues is 0!"); - // Initialize the output array double *sineArray = NULL; sineArray = (double*) malloc(sizeof(double) * iNumValues); if (sineArray == NULL) - _error("*generateSineValues: Failed to allocate memory for Sine Array\n"); + _mem_error("*generateSineValues: Failed to allocate memory for Sine Array"); for (int i=0; i= 0 && !(statBuffer.st_mode & S_IFDIR)); +} + void writeDoubleArray(double *pdOut, int iLen, char *pcOutName) { - // Write a list of double values to a file + /* + * Write an array of double values to a file with the name `pcOutName`. + * Each value is separated by a linebreak. + */ + + // Check if the path is NULL + if (pcOutName == NULL) + _error("writeDoubleArray: pcOutName is NULL"); + + // Check if the path is a valid file + if (!isValidFile(pcOutName)) + _error("writeDoubleArray: '%s' is not a valid file", pcOutName); + FILE *file = fopen(pcOutName, "w"); + if (file == NULL) - _error("writeDoubleArray: Error while opening file '%s'.\n", pcOutName); + _error("writeDoubleArray: Error while opening file '%s'.", pcOutName); if (pdOut == NULL) - _error("writeDoubleArray: pdOut is NULL\n"); + _error("writeDoubleArray: pdOut is NULL"); if (iLen == 0) - _warn("writeDoubleArray: iLen is 0\n"); + _warn("writeDoubleArray: iLen is 0"); for (int i = 0; i < iLen; i++) { fprintf(file, "%f\n", pdOut[i]); diff --git a/Makefile b/Makefile index c14a28a..bf8468c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC=gcc SOURCE_FILE=MMS24-25.c -OPTS=-lm -D _DEBUG_ +OPTS=-lm all: clean tests run