259 lines
8.0 KiB
C
259 lines
8.0 KiB
C
/* =========================STYLE-GUIDELINES===========================
|
|
* All comments use MD-Syntax;
|
|
* Formulas are written in KaTeX/TeX Syntax.
|
|
* We adhere by the `kernel.org` style-guidelines.
|
|
* See: https://www.kernel.org/doc/html/v4.10/process/coding-style.html
|
|
* =============================AUTHORS================================
|
|
* Created by Frederik Beimgraben, Minh Dan Cam and Lea Hornberger in
|
|
* the winter term of 2024/25 at the faculty of computer science at
|
|
* Reutlingen University.
|
|
* After grading the full source code will be available at:
|
|
* https://git.beimgraben.net/MMS-2024-25/MMS-Loesung-2024-25.git
|
|
*/
|
|
|
|
#include "MMS24-25.h"
|
|
#include "math.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "MMS24-25.h"
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
void _error(char *fmt, ...) {
|
|
fprintf(stderr, "<\x1B[31;1m ERROR \x1B[0m: \x1B[34m'");
|
|
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
vfprintf(stderr, fmt, args);
|
|
va_end(args);
|
|
|
|
fprintf(stderr, "'\x1B[0m >\n");
|
|
|
|
#ifndef _TESTS_NONSTOP
|
|
exit(EXIT_FAILURE);
|
|
#endif
|
|
}
|
|
|
|
void _debug(char *fmt, ...) {
|
|
fprintf(stderr, "[\x1B[31;1m DEBUG \x1B[0m] \x1B[34m'");
|
|
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
vfprintf(stderr, fmt, args);
|
|
va_end(args);
|
|
|
|
fprintf(stderr, "'\x1B[0m\n");
|
|
}
|
|
|
|
void _warn(char *fmt, ...) {
|
|
fprintf(stderr, "[\x1B[33;1m WARN \x1B[0m] \x1B[34m'");
|
|
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
vfprintf(stderr, fmt, args);
|
|
va_end(args);
|
|
|
|
fprintf(stderr, "'\x1B[0m\n");
|
|
}
|
|
|
|
double interpolateLine(
|
|
double dX1,
|
|
double dY1,
|
|
double dX2,
|
|
double dY2,
|
|
double dXq
|
|
) {
|
|
if (dX2 == dX1)
|
|
_error("interpolateLine: dX1 and dX2 must differ!");
|
|
|
|
double y = dY1 *(
|
|
(dX2 - dXq) / (dX2 - dX1)
|
|
) + dY2 *(
|
|
(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
|
|
|
|
return y;
|
|
}
|
|
|
|
void rescaleDoubleArray(
|
|
double *pdIn,
|
|
int iLen,
|
|
double dMin,
|
|
double dFactor,
|
|
double *pdOut
|
|
) {
|
|
/* 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
|
|
* \[ \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 $
|
|
*/
|
|
for (int i = 0; i < iLen; i++) {
|
|
pdOut[i] = pdIn[i] *dFactor + dMin;
|
|
}
|
|
}
|
|
|
|
double *generateSineValues(
|
|
int iNumValues,
|
|
int iNumSamplesPerPeriod,
|
|
double dAmp
|
|
) {
|
|
/* 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.
|
|
*/
|
|
|
|
if (iNumSamplesPerPeriod == 0)
|
|
_error("*generateSineValues: iNumSamplesPerPeriod must be non-0!");
|
|
|
|
if (iNumSamplesPerPeriod < 0)
|
|
_warn("*generateSineValues: iNumSamplesPerPeriod is less than 0!");
|
|
|
|
if (iNumValues < 0)
|
|
_error("*generateSineValues: iNumValues must be equal to or greater than 0!");
|
|
|
|
if (iNumValues == 0)
|
|
_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");
|
|
|
|
for (int i=0; i<iNumValues;i++){
|
|
sineArray[i] = dAmp*sin(((2*M_PI)/iNumSamplesPerPeriod) *i);
|
|
}
|
|
|
|
return sineArray;
|
|
}
|
|
|
|
void writeDoubleArray(double *pdOut, int iLen, char *pcOutName) {
|
|
// Write a list of double values to a file
|
|
FILE *file = fopen(pcOutName, "w");
|
|
if (file == NULL)
|
|
_error("writeDoubleArray: Error while opening file '%s'.\n", pcOutName);
|
|
|
|
for (int i = 0; i < iLen; i++) {
|
|
fprintf(file, "%f\n", pdOut[i]);
|
|
}
|
|
|
|
fclose(file);
|
|
}
|
|
|
|
int readDoubleArray(char *pcInName, double **ppdIn) {
|
|
char *line = NULL;
|
|
size_t len = 0;
|
|
ssize_t read;
|
|
int i = 0;
|
|
|
|
*ppdIn = NULL;
|
|
|
|
FILE *file = fopen(pcInName, "r");
|
|
if (file == NULL)
|
|
_error("readDoubleArray: Error while opening file '%s'.\n", pcInName);
|
|
|
|
while ((read = getline(&line, &len, file)) != -1) {
|
|
if (*ppdIn == NULL) {
|
|
*ppdIn = (double*) malloc(sizeof(double));
|
|
} else {
|
|
*ppdIn = (double*) realloc(*ppdIn, sizeof(double) *(i+1));
|
|
}
|
|
|
|
if (*ppdIn == NULL)
|
|
_error("readDoubleArray: Failed to allocate or re-allocate memory for pdIn\n");
|
|
|
|
(*ppdIn)[i] = atof(line);
|
|
i++;
|
|
}
|
|
|
|
free(line);
|
|
fclose(file);
|
|
|
|
return i;
|
|
}
|
|
|
|
MMSignal *createSignal() {
|
|
MMSignal *signal = NULL;
|
|
signal = (MMSignal*) malloc(sizeof(MMSignal));
|
|
|
|
if (signal == NULL)
|
|
_error("createSignal: Failed to allocate memory for signal\n");
|
|
|
|
signal->pdValues = NULL;
|
|
signal->iNumValues = 0;
|
|
signal->dArea = 0;
|
|
signal->dMean = 0;
|
|
signal->dStdDev = 0;
|
|
signal->dMedian = 0;
|
|
signal->pexExtrema = NULL;
|
|
|
|
return signal;
|
|
}
|
|
|
|
MMSignal *createSignalFromSignal(MMSignal *pmmsIn) {
|
|
MMSignal *signal = createSignal();
|
|
|
|
// Initialize and copy the values (deep copy)
|
|
signal->pdValues = (double*) malloc(sizeof(double) *pmmsIn->iNumValues);
|
|
if (signal->pdValues == NULL)
|
|
_error("createSignalFromSignal: Failed to allocate memory for signal->pdValues\n");
|
|
|
|
for (int i = 0; i < pmmsIn->iNumValues; i++) {
|
|
signal->pdValues[i] = pmmsIn->pdValues[i];
|
|
}
|
|
|
|
// Copy shallow items
|
|
signal->iNumValues = pmmsIn->iNumValues;
|
|
signal->dArea = pmmsIn->dArea;
|
|
signal->dMean = pmmsIn->dMean;
|
|
signal->dStdDev = pmmsIn->dStdDev;
|
|
signal->dMedian = pmmsIn->dMedian;
|
|
|
|
// Deep copy of Extrema
|
|
signal->pexExtrema = (Extrema*) malloc(sizeof(Extrema));
|
|
if (signal->pexExtrema == NULL)
|
|
_error("createSignalFromSignal: Failed to allocate memory for signal->pexExtrema\n");
|
|
|
|
signal->pexExtrema->iGlobalMinPos = pmmsIn->pexExtrema->iGlobalMinPos;
|
|
signal->pexExtrema->iGlobalMaxPos = pmmsIn->pexExtrema->iGlobalMaxPos;
|
|
|
|
signal->pexExtrema->pexLocalMax = (LocalExtrema*) malloc(sizeof(LocalExtrema));
|
|
if (signal->pexExtrema->pexLocalMax == NULL)
|
|
_error("createSignalFromSignal: Failed to allocate memory for signal->pexExtrema->pexLocalMax\n");
|
|
|
|
signal->pexExtrema->pexLocalMax->iNumLocalExtrema = pmmsIn->pexExtrema->pexLocalMax->iNumLocalExtrema;
|
|
signal->pexExtrema->pexLocalMax->piLocalExtremaPos = (int*) malloc(sizeof(int) *pmmsIn->pexExtrema->pexLocalMax->iNumLocalExtrema);
|
|
if (signal->pexExtrema->pexLocalMax->piLocalExtremaPos == NULL)
|
|
_error("createSignalFromSignal: Failed to allocate memory for signal->pexExtrema->pexLocalMax->piLocalExtremaPos\n");
|
|
|
|
for (int i = 0; i < pmmsIn->pexExtrema->pexLocalMax->iNumLocalExtrema; i++) {
|
|
signal->pexExtrema->pexLocalMax->piLocalExtremaPos[i] = pmmsIn->pexExtrema->pexLocalMax->piLocalExtremaPos[i];
|
|
}
|
|
|
|
signal->pexExtrema->pexLocalMin = (LocalExtrema*) malloc(sizeof(LocalExtrema));
|
|
if (signal->pexExtrema->pexLocalMin == NULL)
|
|
_error("createSignalFromSignal: Failed to allocate memory for signal->pexExtrema->pexLocalMin\n");
|
|
|
|
signal->pexExtrema->pexLocalMin->iNumLocalExtrema = pmmsIn->pexExtrema->pexLocalMin->iNumLocalExtrema;
|
|
signal->pexExtrema->pexLocalMin->piLocalExtremaPos = (int*) malloc(sizeof(int) *pmmsIn->pexExtrema->pexLocalMin->iNumLocalExtrema);
|
|
if (signal->pexExtrema->pexLocalMin->piLocalExtremaPos == NULL)
|
|
_error("createSignalFromSignal: Failed to allocate memory for signal->pexExtrema->pexLocalMin->piLocalExtremaPos\n");
|
|
|
|
for (int i = 0; i < pmmsIn->pexExtrema->pexLocalMin->iNumLocalExtrema; i++) {
|
|
signal->pexExtrema->pexLocalMin->piLocalExtremaPos[i] = pmmsIn->pexExtrema->pexLocalMin->piLocalExtremaPos[i];
|
|
}
|
|
|
|
return signal;
|
|
}
|