All but DFT confirmed

This commit is contained in:
Frederik Beimgraben 2025-01-12 00:10:12 +01:00
parent 5b65a43431
commit f1783f7ce8
4 changed files with 571 additions and 122 deletions

View File

@ -11,17 +11,16 @@
* https://git.beimgraben.net/MMS-2024-25/MMS-Loesung-2024-25.git * 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 <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include "MMS24-25.h"
#include "math.h"
// #region Error Handling and Debugging // #region Error Handling and Debugging
void _error(char *fmt, ...) { void _error(char *fmt, ...) {
fprintf(stderr, "<\x1B[31;1m ERROR \x1B[0m: \x1B[34m'"); fprintf(stderr, "< \x1B[31;4;1mERROR\x1B[0m : \x1B[34m'");
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -36,7 +35,7 @@ void _error(char *fmt, ...) {
} }
void _debug(char *fmt, ...) { void _debug(char *fmt, ...) {
fprintf(stderr, "[\x1B[31;1m DEBUG \x1B[0m] \x1B[34m'"); fprintf(stderr, "[ \x1B[37;4;1mDEBUG\x1B[0m ] \x1B[34m'");
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -47,7 +46,7 @@ void _debug(char *fmt, ...) {
} }
void _warn(char *fmt, ...) { void _warn(char *fmt, ...) {
fprintf(stderr, "[\x1B[33;1m WARN \x1B[0m] \x1B[34m'"); fprintf(stderr, "[ \x1B[33;4;1mWARN\x1B[0m ] \x1B[34m'");
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -69,9 +68,9 @@ double interpolateLine(
if (dX2 == dX1) if (dX2 == dX1)
_error("interpolateLine: dX1 and dX2 must differ!"); _error("interpolateLine: dX1 and dX2 must differ!");
double y = dY1 *( double y = dY1 * (
(dX2 - dXq) / (dX2 - dX1) (dX2 - dXq) / (dX2 - dX1)
) + dY2 *( ) + dY2 * (
(dXq - dX1) / (dX2 - dX1) (dXq - dX1) / (dX2 - dX1)
); );
@ -99,8 +98,19 @@ void rescaleDoubleArray(
* which naturally results from: * which naturally results from:
* $ pdOut_i = pdIn_i *dFactor + dMin $ * $ pdOut_i = pdIn_i *dFactor + dMin $
*/ */
// First find the old minimum
double dOldMin = pdIn[0];
for (int i = 1; i < iLen; i++) {
if (pdIn[i] < dOldMin)
dOldMin = pdIn[i];
}
// Calculate the offset
double dOffset = dMin - dOldMin;
// Rescale the array
for (int i = 0; i < iLen; i++) { for (int i = 0; i < iLen; i++) {
pdOut[i] = pdIn[i] *dFactor + dMin; pdOut[i] = pdIn[i] * dFactor + dOffset;
} }
} }
@ -129,13 +139,13 @@ double *generateSineValues(
// Initialize the output array // Initialize the output array
double *sineArray = NULL; double *sineArray = NULL;
sineArray = (double*) malloc(sizeof(double) *iNumValues); sineArray = (double*) malloc(sizeof(double) * iNumValues);
if (sineArray == NULL) if (sineArray == NULL)
_error("*generateSineValues: Failed to allocate memory for Sine Array\n"); _error("*generateSineValues: Failed to allocate memory for Sine Array\n");
for (int i=0; i<iNumValues;i++){ for (int i=0; i<iNumValues;i++){
sineArray[i] = dAmp*sin(((2*M_PI)/iNumSamplesPerPeriod) *i); sineArray[i] = dAmp * sin(((2*M_PI)/iNumSamplesPerPeriod) * i);
} }
return sineArray; return sineArray;
@ -147,6 +157,12 @@ void writeDoubleArray(double *pdOut, int iLen, char *pcOutName) {
if (file == NULL) if (file == NULL)
_error("writeDoubleArray: Error while opening file '%s'.\n", pcOutName); _error("writeDoubleArray: Error while opening file '%s'.\n", pcOutName);
if (pdOut == NULL)
_error("writeDoubleArray: pdOut is NULL\n");
if (iLen == 0)
_warn("writeDoubleArray: iLen is 0\n");
for (int i = 0; i < iLen; i++) { for (int i = 0; i < iLen; i++) {
fprintf(file, "%f\n", pdOut[i]); fprintf(file, "%f\n", pdOut[i]);
} }
@ -204,16 +220,58 @@ MMSignal *createSignal() {
return signal; return signal;
} }
LocalExtrema* copyLocalExtrema(LocalExtrema *pexIn) {
if (pexIn == NULL)
return NULL;
LocalExtrema *localExtrema = (LocalExtrema*) malloc(sizeof(LocalExtrema));
if (localExtrema == NULL)
_error("copyLocalExtrema: Failed to allocate memory for localExtrema\n");
localExtrema->iNumLocalExtrema = pexIn->iNumLocalExtrema;
localExtrema->piLocalExtremaPos = (int*) malloc(sizeof(int) *pexIn->iNumLocalExtrema);
if (localExtrema->piLocalExtremaPos == NULL)
_error("copyLocalExtrema: Failed to allocate memory for localExtrema->piLocalExtremaPos\n");
for (int i = 0; i < pexIn->iNumLocalExtrema; i++) {
localExtrema->piLocalExtremaPos[i] = pexIn->piLocalExtremaPos[i];
}
return localExtrema;
}
Extrema* copyExtrema(Extrema *pexIn) {
if (pexIn == NULL)
return NULL;
Extrema *extrema = (Extrema*) malloc(sizeof(Extrema));
if (extrema == NULL)
_error("copyExtrema: Failed to allocate memory for extrema\n");
extrema->iGlobalMinPos = pexIn->iGlobalMinPos;
extrema->iGlobalMaxPos = pexIn->iGlobalMaxPos;
extrema->pexLocalMax = copyLocalExtrema(pexIn->pexLocalMax);
extrema->pexLocalMin = copyLocalExtrema(pexIn->pexLocalMin);
return extrema;
}
MMSignal *createSignalFromSignal(MMSignal *pmmsIn) { MMSignal *createSignalFromSignal(MMSignal *pmmsIn) {
MMSignal *signal = createSignal(); MMSignal *signal = createSignal();
// Initialize and copy the values (deep copy) if (pmmsIn->pdValues != NULL) {
signal->pdValues = (double*) malloc(sizeof(double) *pmmsIn->iNumValues); // Initialize and copy the values (deep copy)
if (signal->pdValues == NULL) signal->pdValues = (double*) malloc(sizeof(double) *pmmsIn->iNumValues);
_error("createSignalFromSignal: Failed to allocate memory for signal->pdValues\n"); if (signal->pdValues == NULL)
_error("createSignalFromSignal: Failed to allocate memory for signal->pdValues\n");
for (int i = 0; i < pmmsIn->iNumValues; i++) { for (int i = 0; i < pmmsIn->iNumValues; i++) {
signal->pdValues[i] = pmmsIn->pdValues[i]; signal->pdValues[i] = pmmsIn->pdValues[i];
}
} else {
_warn("createSignalFromSignal: pmmsIn->pdValues is NULL\n");
signal->pdValues = NULL;
} }
// Copy shallow items // Copy shallow items
@ -224,38 +282,13 @@ MMSignal *createSignalFromSignal(MMSignal *pmmsIn) {
signal->dMedian = pmmsIn->dMedian; signal->dMedian = pmmsIn->dMedian;
// Deep copy of Extrema // Deep copy of Extrema
signal->pexExtrema = (Extrema*) malloc(sizeof(Extrema)); if (pmmsIn->pexExtrema == NULL) {
if (signal->pexExtrema == NULL) _warn("createSignalFromSignal: pmmsIn->pexExtrema is NULL\n");
_error("createSignalFromSignal: Failed to allocate memory for signal->pexExtrema\n"); signal->pexExtrema = NULL;
return signal;
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)); signal->pexExtrema = copyExtrema(pmmsIn->pexExtrema);
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; return signal;
} }
@ -312,6 +345,9 @@ MMSignal *createSignalFromFile(char *pcInName) {
} }
void writeMMSignal(char *pcInName, MMSignal *pmmsIn) { void writeMMSignal(char *pcInName, MMSignal *pmmsIn) {
if (pmmsIn->pdValues == NULL)
_error("writeMMSignal: pmmsIn->pdValues is NULL\n");
writeDoubleArray( writeDoubleArray(
pmmsIn->pdValues, pmmsIn->pdValues,
pmmsIn->iNumValues, pmmsIn->iNumValues,
@ -319,13 +355,32 @@ void writeMMSignal(char *pcInName, MMSignal *pmmsIn) {
); );
} }
void deleteLocalExtrema(LocalExtrema *pexIn) {
if (pexIn == NULL)
return;
free(pexIn->piLocalExtremaPos);
free(pexIn);
}
void deleteExtrema(Extrema *pexIn) {
if (pexIn == NULL)
return;
deleteLocalExtrema(pexIn->pexLocalMax);
deleteLocalExtrema(pexIn->pexLocalMin);
free(pexIn);
}
void deleteSignal(MMSignal *pmmsIn) { void deleteSignal(MMSignal *pmmsIn) {
free(pmmsIn->pdValues); if (pmmsIn == NULL)
free(pmmsIn->pexExtrema->pexLocalMax->piLocalExtremaPos); return;
free(pmmsIn->pexExtrema->pexLocalMax);
free(pmmsIn->pexExtrema->pexLocalMin->piLocalExtremaPos); if (pmmsIn->pdValues != NULL)
free(pmmsIn->pexExtrema->pexLocalMin); free(pmmsIn->pdValues);
free(pmmsIn->pexExtrema);
deleteExtrema(pmmsIn->pexExtrema);
free(pmmsIn); free(pmmsIn);
} }
// #endregion // #endregion
@ -335,24 +390,31 @@ double calculateArea(double *pdIn, int iLen) {
double area = 0; double area = 0;
// #FIXME: Which one should we use according to the task? // #FIXME: Which one should we use according to the task?
for (int i = 0; i < iLen-1; i++) { for (int i = 0; i < iLen; i++) {
area += (pdIn[i] + pdIn[i+1]) / 2; /* Alternative would be:
* area += (pdIn[i] + pdIn[i+1]) / 2;
* with i < iLen-1
* Which one to use is up to the implemention.
*/
area += pdIn[i];
} }
return area; return area;
} }
double calculateMean(double *pdIn, int iLen) { double calculateMean(double *pdIn, int iLen) {
double mean = 0; /* Here the above defined function `calculateArea` is used to calculate the mean, since:
* \[ mean(pdIn) = \frac{1}{ |pdIn| } \sum_{i=1}^{ |pdIn| } x_i
for (int i = 0; i < iLen; i++) { * = \frac{area(x)}{ |pdIn| } \]
mean += pdIn[i]; */
} return calculateArea(pdIn, iLen) / iLen;
return mean / iLen;
} }
double calculateStddev(double *pdIn, int iLen) { double calculateStddev(double *pdIn, int iLen) {
/* The standard deviation is calculated as follows:
* \[ stddev(pdIn) = \sqrt{ \frac{1}{ |pdIn| } \sum_{i=1}^{ |pdIn| } (x_i - mean(pdIn))^2 } \]
*/
double mean = calculateMean(pdIn, iLen); double mean = calculateMean(pdIn, iLen);
double stdDev = 0; double stdDev = 0;
@ -363,26 +425,41 @@ double calculateStddev(double *pdIn, int iLen) {
return sqrt(stdDev / iLen); return sqrt(stdDev / iLen);
} }
double calculateMedian(double *pdIn, int iLen) {
/* The median is calculated as follows:
* \[ median(pdIn) = \begin{cases}
* pdIn_{\frac{|pdIn|}{2}} & \text{if } |pdIn| \text{ is even} \\
* \frac{pdIn_{\frac{|pdIn|}{2}} + pdIn_{\frac{|pdIn|}{2}+1}}{2} & \text{if } |pdIn| \text{ is odd}
* \end{cases} \]
*/
if (iLen % 2 == 0) {
return pdIn[iLen/2];
} else {
return (pdIn[iLen/2] + pdIn[iLen/2+1]) / 2;
}
}
LocalExtrema *initLocalExtrema(int iLen) {
LocalExtrema *localExtrema = (LocalExtrema*) malloc(sizeof(LocalExtrema));
if (localExtrema == NULL)
_error("initLocalExtrema: Failed to allocate memory for localExtrema\n");
localExtrema->iNumLocalExtrema = 0;
localExtrema->piLocalExtremaPos = (int*) malloc(sizeof(int) *iLen);
if (localExtrema->piLocalExtremaPos == NULL)
_error("initLocalExtrema: Failed to allocate memory for localExtrema->piLocalExtremaPos\n");
return localExtrema;
}
Extrema *initExtrema(double *pdIn, int iLen) { Extrema *initExtrema(double *pdIn, int iLen) {
Extrema *extrema = (Extrema*) malloc(sizeof(Extrema)); Extrema *extrema = (Extrema*) malloc(sizeof(Extrema));
if (extrema == NULL) if (extrema == NULL)
_error("initExtrema: Failed to allocate memory for extrema\n"); _error("initExtrema: Failed to allocate memory for extrema\n");
extrema->pexLocalMax = (LocalExtrema*) malloc(sizeof(LocalExtrema)); extrema->pexLocalMax = initLocalExtrema(iLen);
if (extrema->pexLocalMax == NULL) extrema->pexLocalMin = initLocalExtrema(iLen);
_error("initExtrema: Failed to allocate memory for extrema->pexLocalMax\n");
extrema->pexLocalMin = (LocalExtrema*) malloc(sizeof(LocalExtrema));
if (extrema->pexLocalMin == NULL)
_error("initExtrema: Failed to allocate memory for extrema->pexLocalMin\n");
extrema->pexLocalMax->piLocalExtremaPos = (int*) malloc(sizeof(int) *iLen);
if (extrema->pexLocalMax->piLocalExtremaPos == NULL)
_error("initExtrema: Failed to allocate memory for extrema->pexLocalMax->piLocalExtremaPos\n");
extrema->pexLocalMin->piLocalExtremaPos = (int*) malloc(sizeof(int) *iLen);
if (extrema->pexLocalMin->piLocalExtremaPos == NULL)
_error("initExtrema: Failed to allocate memory for extrema->pexLocalMin->piLocalExtremaPos\n");
extrema->iGlobalMaxPos = 0; extrema->iGlobalMaxPos = 0;
extrema->iGlobalMinPos = 0; extrema->iGlobalMinPos = 0;
@ -390,14 +467,6 @@ Extrema *initExtrema(double *pdIn, int iLen) {
return extrema; return extrema;
} }
void deleteExtrema(Extrema *pexIn) {
free(pexIn->pexLocalMax->piLocalExtremaPos);
free(pexIn->pexLocalMax);
free(pexIn->pexLocalMin->piLocalExtremaPos);
free(pexIn->pexLocalMin);
free(pexIn);
}
void initMMSignalFeatures(MMSignal *pmmsIn) { void initMMSignalFeatures(MMSignal *pmmsIn) {
pmmsIn->dArea = 0; pmmsIn->dArea = 0;
pmmsIn->dMean = 0; pmmsIn->dMean = 0;
@ -409,7 +478,13 @@ void initMMSignalFeatures(MMSignal *pmmsIn) {
Histogram *initHistogram(double *pdIn, int iLen, int iNumBins) { Histogram *initHistogram(double *pdIn, int iLen, int iNumBins) {
Histogram *histogram = (Histogram*) malloc(sizeof(Histogram)); Histogram *histogram = (Histogram*) malloc(sizeof(Histogram));
if (histogram == NULL) if (histogram == NULL)
_error("initHistogram: Failed to allocate memory for histogram\n"); _error("initHistogram: Failed to allocate memory for histogram");
if (iNumBins == 0)
_error("initHistogram: iNumBins must be non-0");
if (iLen == 0)
_warn("initHistogram: iLen is 0\n");
histogram->dIntervalMin = pdIn[0]; histogram->dIntervalMin = pdIn[0];
histogram->dIntervalMax = pdIn[0]; histogram->dIntervalMax = pdIn[0];
@ -420,26 +495,61 @@ Histogram *initHistogram(double *pdIn, int iLen, int iNumBins) {
histogram->dIntervalMax = pdIn[i]; histogram->dIntervalMax = pdIn[i];
} }
#ifdef _DEBUG_
_debug("initHistogram: histogram->dIntervalMin = %lf", histogram->dIntervalMin);
_debug("initHistogram: histogram->dIntervalMax = %lf", histogram->dIntervalMax);
#endif
histogram->dBinWidth = (histogram->dIntervalMax - histogram->dIntervalMin) / iNumBins; histogram->dBinWidth = (histogram->dIntervalMax - histogram->dIntervalMin) / iNumBins;
histogram->iNumBins = iNumBins; histogram->iNumBins = iNumBins;
#ifdef _DEBUG_
_debug("initHistogram: histogram->dBinWidth = %lf", histogram->dBinWidth);
#endif
if (histogram->dBinWidth == 0)
histogram->dBinWidth = 1;
histogram->pdBinValues = (double*) malloc(sizeof(double) *iNumBins); histogram->pdBinValues = (double*) malloc(sizeof(double) *iNumBins);
if (histogram->pdBinValues == NULL) if (histogram->pdBinValues == NULL)
_error("initHistogram: Failed to allocate memory for histogram->pdBinValues\n"); _error("initHistogram: Failed to allocate memory for histogram->pdBinValues");
for (int i = 0; i < iNumBins; i++) { for (int i = 0; i < iNumBins; i++) {
histogram->pdBinValues[i] = 0; histogram->pdBinValues[i] = 0;
} }
for (int i = 0; i < iLen; i++) {
int bin = floor((pdIn[i] - histogram->dIntervalMin) / histogram->dBinWidth);
if (bin == iNumBins)
bin--;
histogram->pdBinValues[bin]++;
}
for (int i = 0; i < iNumBins; i++) {
histogram->pdBinValues[i] /= iLen;
}
#ifdef _DEBUG_
// DEBUG: print the parameters and result
_debug("initHistogram(%lf, %lf, %lf, %d)",
histogram->dIntervalMin,histogram->dIntervalMax,histogram->dBinWidth,histogram->iNumBins);
for (int i = 0; i < histogram->iNumBins; i++) {
_debug("initHistogram: histogram->pdBinValues[%d] = %lf", i, histogram->pdBinValues[i]);
}
#endif
return histogram; return histogram;
} }
void deleteHistogram(Histogram *phIn) { void deleteHistogram(Histogram *phIn) {
if (phIn == NULL)
return;
free(phIn->pdBinValues); free(phIn->pdBinValues);
free(phIn); free(phIn);
} }
// #FIXME: Check if this checks out
double calculateEntropy(Histogram *phisIn) { double calculateEntropy(Histogram *phisIn) {
double entropy = 0; double entropy = 0;
@ -457,40 +567,49 @@ double calculateEntropy(Histogram *phisIn) {
// #region Aufgabe 3 // #region Aufgabe 3
MMSignal *convoluteSignals(MMSignal *pmmsInA, MMSignal *pmmsInB) { MMSignal *convoluteSignals(MMSignal *pmmsInA, MMSignal *pmmsInB) {
MMSignal *signal = createSignal(); // Calculate output length
int iOutLen = pmmsInA->iNumValues + pmmsInB->iNumValues - 1;
if (pmmsInA->iNumValues != pmmsInB->iNumValues) double *pdOut = (double*) malloc(sizeof(double) *iOutLen);
_error("convoluteSignals: Signals must have the same length\n"); if (pdOut == NULL)
_error("convoluteSignals: Failed to allocate memory for pdOut\n");
signal->pdValues = (double*) malloc(sizeof(double) *pmmsInA->iNumValues); for (int i = 0; i < iOutLen; i++) {
if (signal->pdValues == NULL) pdOut[i] = 0;
_error("convoluteSignals: Failed to allocate memory for signal->pdValues\n");
for (int i = 0; i < pmmsInA->iNumValues; i++) {
signal->pdValues[i] = pmmsInA->pdValues[i] * pmmsInB->pdValues[i];
} }
signal->iNumValues = pmmsInA->iNumValues; for (int i = 0; i < pmmsInA->iNumValues; i++) {
for (int j = 0; j < pmmsInB->iNumValues; j++) {
pdOut[i+j] += pmmsInA->pdValues[i] * pmmsInB->pdValues[j];
}
}
MMSignal *signal = createSignalFromDoubleArray(iOutLen, pdOut);
initMMSignalFeatures(signal);
return signal; return signal;
} }
// #FIXME: Check if this checks out // #FIXME: Check if this checks out
MMSignal *getPascalLine(int iLinenum) { MMSignal *getPascalLine(int iLinenum) {
MMSignal *signal = createSignal(); if (iLinenum <= 0)
_error("getPascalLine: iLinenum must be greater than 0\n");
signal->pdValues = (double*) malloc(sizeof(double) *iLinenum); // Calculate a kernel signal using pascales triangle without using the factorial
if (signal->pdValues == NULL) double *pdValues = NULL;
_error("getPascalLine: Failed to allocate memory for signal->pdValues\n"); pdValues = (double*) malloc(sizeof(double) * iLinenum);
if (pdValues == NULL)
_error("getPascalLine: Failed to allocate memory for pdValues\n");
signal->pdValues[0] = 1; for (int i = 0; i < iLinenum; i++) {
signal->pdValues[iLinenum-1] = 1; pdValues[i] = 1;
for (int j = i-1; j > 0; j--) {
for (int i = 1; i < iLinenum-1; i++) { pdValues[j] = pdValues[j] + pdValues[j-1];
signal->pdValues[i] = signal->pdValues[i-1] *(iLinenum-i) / i; }
} }
signal->iNumValues = iLinenum; MMSignal *signal = createSignalFromDoubleArray(iLinenum, pdValues);
initMMSignalFeatures(signal);
return signal; return signal;
} }
@ -498,10 +617,12 @@ MMSignal *getPascalLine(int iLinenum) {
// #endregion // #endregion
// #region Aufgabe 4 // #region Aufgabe 4
void computeDFT(int iLen, void computeDFT(
double *pdRealIn, double *pdImgIn, int iLen,
double *pdRealOut, double *pdImgOut, double *pdRealIn, double *pdImgIn,
int iDirection /*-1,1*/) { double *pdRealOut, double *pdImgOut,
int iDirection
) {
// Check the value of iDirection // Check the value of iDirection
if (iDirection != -1 && iDirection != 1) if (iDirection != -1 && iDirection != 1)
_error("computeDFT: iDirection must be either -1 or 1\n"); _error("computeDFT: iDirection must be either -1 or 1\n");
@ -509,9 +630,21 @@ void computeDFT(int iLen,
for (int k = 0; k < iLen; k++) { for (int k = 0; k < iLen; k++) {
pdRealOut[k] = 0; pdRealOut[k] = 0;
pdImgOut[k] = 0; pdImgOut[k] = 0;
// Compute the sum for the k-th output element
for (int n = 0; n < iLen; n++) { for (int n = 0; n < iLen; n++) {
pdRealOut[k] += pdRealIn[n] * cos(2*M_PI *k *n / iLen) + iDirection * pdImgIn[n] * sin(2*M_PI *k *n / iLen); double angle = iDirection * 2.0 * M_PI * k * n / iLen;
pdImgOut[k] += -iDirection * pdRealIn[n] * sin(2*M_PI *k *n / iLen) + pdImgIn[n] * cos(2*M_PI *k *n / iLen); double cosTerm = cos(angle);
double sinTerm = sin(angle);
pdRealOut[k] += pdRealIn[n] * cosTerm - pdImgIn[n] * sinTerm;
pdImgOut[k] += pdRealIn[n] * sinTerm + pdImgIn[n] * cosTerm;
}
// Normalize the output
if (iDirection == -1) {
pdRealOut[k] /= iLen;
pdImgOut[k] /= iLen;
} }
} }
} }

View File

@ -91,6 +91,6 @@ void computeDFT(int iLen,
double *pdRealIn, double *pdImgIn, double *pdRealIn, double *pdImgIn,
double *pdRealOut, double *pdImgOut, double *pdRealOut, double *pdImgOut,
int iDirection /*-1,1*/); int iDirection /*-1,1*/);
void convertCart2Polar(double *pdRealIn, double *pdImgIn,double *pdRadiusOut, double *pdAngleOut, int iLen); void convertCart2Polar(double *pdRealIn, double *pdImgIn, double *pdRadiusOut, double *pdAngleOut, int iLen);
void convertPolar2Cart(double *pdRadiusIn, double *pdAngleIn, double *pdRealOut, double *pdImgOut,int iLen); void convertPolar2Cart(double *pdRadiusIn, double *pdAngleIn, double *pdRealOut, double *pdImgOut, int iLen);
#endif #endif

View File

@ -1,6 +1,6 @@
CC=gcc CC=gcc
SOURCE_FILE=MMS24-25.c SOURCE_FILE=MMS24-25.c
OPTS=-lm -D _TESTS_NONSTOP OPTS=-lm -D _DEBUG_
all: clean tests run all: clean tests run
@ -11,4 +11,4 @@ tests:
$(CC) tests.c $(SOURCE_FILE) -o tests $(OPTS) $(CC) tests.c $(SOURCE_FILE) -o tests $(OPTS)
run: run:
./tests ./tests

320
tests.c
View File

@ -44,8 +44,8 @@ void error(const char* fmt, ...) {
void testInterpolation() { void testInterpolation() {
info("testInterpolation"); info("testInterpolation");
double dRangeMin = -3; double dRangeMin = -1;
double dRangeMax = 3; double dRangeMax = 1;
double dRangeStep = 0.33; double dRangeStep = 0.33;
for (double dX1=dRangeMin;dX1<dRangeMax;dX1+=dRangeStep) { for (double dX1=dRangeMin;dX1<dRangeMax;dX1+=dRangeStep) {
@ -117,6 +117,8 @@ void testSineAndReadWriteDoubleArraySingle(int nValues, int dPLen, double dAmp)
info("use `plot \"%s\", \"%s\" with lines` to view.", fileName, fileName); info("use `plot \"%s\", \"%s\" with lines` to view.", fileName, fileName);
free(fileName); free(fileName);
free(pdSineValues);
free(pdReadValues);
} }
void testSineAndReadWriteDoubleArray() { void testSineAndReadWriteDoubleArray() {
@ -130,9 +132,323 @@ void testSineAndReadWriteDoubleArray() {
success("testSineAndWriteDoubleArray"); success("testSineAndWriteDoubleArray");
} }
void testCreateSignalWithDefault() {
info("testCreateSignalWithDefault");
MMSignal *signal = createSignalWithDefault(10, M_PI);
if (signal->iNumValues != 10) {
error("Failed to create signal with 10 values: %d != 10", signal->iNumValues);
}
for (int i=0; i<10; i++) {
if (signal->pdValues[i] != M_PI) {
error("Failed to create signal with default value 0 at index %d: %lf != 0", i, signal->pdValues[i]);
}
}
success("testCreateSignalWithDefault");
deleteSignal(signal);
}
void testCreateSignalFromDoubleArray() {
info("testCreateSignalFromDoubleArray");
double pdValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
MMSignal *signal = createSignalFromDoubleArray(10, pdValues);
if (signal->iNumValues != 10) {
error("Failed to create signal with 10 values: %d != 10", signal->iNumValues);
}
for (int i=0; i<10; i++) {
if (signal->pdValues[i] != pdValues[i]) {
error("Failed to create signal with default value 0 at index %d: %lf != 0", i, signal->pdValues[i]);
}
}
success("testCreateSignalFromDoubleArray");
deleteSignal(signal);
}
void testCreateSignalFromFile() {
info("testCreateSignalFromFile");
double pdValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
char* fileName = "testCreateSignalFromFile.results.txt";
writeDoubleArray(pdValues, 10, fileName);
MMSignal *signal = createSignalFromFile(fileName);
if (signal->iNumValues != 10) {
error("Failed to create signal with 10 values: %d != 10", signal->iNumValues);
}
for (int i=0; i<10; i++) {
if (signal->pdValues[i] != pdValues[i]) {
error("Failed to create signal with default value 0 at index %d: %lf != 0", i, signal->pdValues[i]);
}
}
success("testCreateSignalFromFile");
deleteSignal(signal);
}
void testWriteMMSignal() {
info("testWriteMMSignal");
double pdValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
char* fileName = "testWriteMMSignal.results.txt";
MMSignal *signal = createSignalFromDoubleArray(10, pdValues);
writeMMSignal(fileName, signal);
MMSignal *readSignal = createSignalFromFile(fileName);
if (signal->iNumValues != readSignal->iNumValues) {
error("Failed to read the correct number of values: %d != %d", signal->iNumValues, readSignal->iNumValues);
}
for (int i=0; i<10; i++) {
if (signal->pdValues[i] != readSignal->pdValues[i]) {
error("Failed to read the correct value at index %d: %lf != %lf", i, signal->pdValues[i], readSignal->pdValues[i]);
}
}
deleteSignal(signal);
deleteSignal(readSignal);
success("testWriteMMSignal");
}
void testCalculateArea() {
info("testCalculateArea");
double pdValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
double dArea = calculateArea(pdValues, 10);
if (round(dArea*1e6) != 55e6) {
error("Failed to calculate the correct area: %lf != 55", dArea);
}
success("testCalculateArea");
}
void testCalculateMean() {
info("testCalculateMean");
double pdValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
double dMean = calculateMean(pdValues, 10);
if (round(dMean*1e6) != 5.5e6) {
error("Failed to calculate the correct mean: %lf != 5.5", dMean);
}
success("testCalculateMean");
}
void testCalculateStdDev() {
info("testCalculateStdDev");
double pdValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
double dStdDev = calculateStddev(pdValues, 10);
if (round(dStdDev*1e6) != 2.872281e6) {
error("Failed to calculate the correct standard deviation: %lf != 2.872281", dStdDev);
}
success("testCalculateStdDev");
}
void testCalculateMedian() {
info("testCalculateMedian");
double pdValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
double dMedian = calculateMedian(pdValues, 10);
if (dMedian != 6) {
error("Failed to calculate the correct median: %lf != 5.5", dMedian);
}
success("testCalculateMedian");
}
void testCalculateEntropy() {
info("testCalculateEntropy");
double pdValues[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Histogram *histogram = initHistogram(pdValues, 11, 11);
double dEntropy = calculateEntropy(histogram);
if (round(dEntropy*1e6) != 3.459432e6) { // Should be log2(1/11) = 3.459432
error("Failed to calculate the correct entropy: %lf != 3.459432", dEntropy);
}
success("testCalculateEntropy");
}
void testConvoluteSignals() {
info("testConvoluteSignals");
double pdValues1[] = {1, 2, 3, 4, 5};
double pdValues2[] = {1, 2, 3, 4, 5};
MMSignal *signal1 = createSignalFromDoubleArray(5, pdValues1);
MMSignal *signal2 = createSignalFromDoubleArray(5, pdValues2);
MMSignal *signal3 = convoluteSignals(signal1, signal2);
if (signal3->iNumValues != 9) {
error("Failed to calculate the correct number of values: %d != 9", signal3->iNumValues);
}
double pdExpectedValues[] = {1, 4, 10, 20, 35, 44, 46, 40, 25};
for (int i=0; i<9; i++) {
if (signal3->pdValues[i] != pdExpectedValues[i]) {
error("Failed to calculate the correct value at index %d: %lf != %lf", i, signal3->pdValues[i], pdExpectedValues[i]);
}
}
success("testConvoluteSignals");
}
void testGetPascalLine() {
info("testGetPascalLine");
// For 5
MMSignal *signal = getPascalLine(5);
if (signal->iNumValues != 5) {
error("Failed to calculate the correct number of values: %d != 5", signal->iNumValues);
}
double pdExpectedValues[] = {1, 4, 6, 4, 1};
for (int i=0; i<5; i++) {
if (signal->pdValues[i] != pdExpectedValues[i]) {
error("Failed to calculate the correct value at index %d: %lf != %lf", i, signal->pdValues[i], pdExpectedValues[i]);
}
}
// For 1
signal = getPascalLine(1);
if (signal->iNumValues != 1) {
error("Failed to calculate the correct number of values: %d != 1", signal->iNumValues);
}
if (signal->pdValues[0] != 1) {
error("Failed to calculate the correct value at index 0: %lf != 1", signal->pdValues[0]);
}
// For 11
signal = getPascalLine(11);
if (signal->iNumValues != 11) {
error("Failed to calculate the correct number of values: %d != 11", signal->iNumValues);
}
double pdExpectedValues11[] = {1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1};
for (int i=0; i<11; i++) {
if (signal->pdValues[i] != pdExpectedValues11[i]) {
error("Failed to calculate the correct value at index %d: %lf != %lf", i, signal->pdValues[i], pdExpectedValues11[i]);
}
}
success("testGetPascalLine");
}
void testComputeDFT() {
info("testComputeDFT");
double pdRealIn[] = {1, 2, 3, 4, 5};
double pdImgIn[] = {1, 2, 3, 4, 5};
double pdRealOut[5];
double pdImgOut[5];
computeDFT(5, pdRealIn, pdImgIn, pdRealOut, pdImgOut, 1);
for (int i=0; i<5; i++) {
if (pdImgOut[i] < 0) {
printf("%lf - %lfi\n", pdRealOut[i], -pdImgOut[i]);
} else {
printf("%lf + %lfi\n", pdRealOut[i], pdImgOut[i]);
}
}
success("testComputeDFT");
}
void testConvertCart2Polar() {
// convertCart2Polar(double *pdRealIn, double *pdImgIn, double *pdRadiusOut, double *pdAngleOut, int iLen)
info("testConvertCart2Polar");
double pdRealIn[] = {1, 0, 1, -1, 0};
double pdImgIn[] = {0, 1, 1, 0, -1};
double pdRadiusOut[5];
double pdAngleOut[5];
convertCart2Polar(pdRealIn, pdImgIn, pdRadiusOut, pdAngleOut, 5);
for (int i=0; i<5; i++) {
printf("%lf + %lfi -> r=%lf / θ=%lfπ\n", pdRealIn[i], pdImgIn[i], pdRadiusOut[i], pdAngleOut[i] / M_PI);
}
success("testConvertCart2Polar");
}
void testConvertPolar2Cart() {
// convertPolar2Cart(double *pdRadiusIn, double *pdAngleIn, double *pdRealOut, double *pdImgOut, int iLen)
info("testConvertPolar2Cart");
double pdRadiusIn[] = {1, 1, 1, 1, 1};
double pdAngleIn[] = {0, M_PI/2, M_PI, 3*M_PI/2, 2*M_PI};
double pdRealOut[5];
double pdImgOut[5];
convertPolar2Cart(pdRadiusIn, pdAngleIn, pdRealOut, pdImgOut, 5);
for (int i=0; i<5; i++) {
printf("r=%lf / θ=%lfπ -> %lf + %lfi\n", pdRadiusIn[i], pdAngleIn[i] / M_PI, pdRealOut[i], pdImgOut[i]);
}
success("testConvertPolar2Cart");
}
int main (int iArgC, char** ppcArgV){ int main (int iArgC, char** ppcArgV){
testInterpolation(); testInterpolation();
testSineAndReadWriteDoubleArray(); testSineAndReadWriteDoubleArray();
testCreateSignalWithDefault();
testCreateSignalFromDoubleArray();
testCreateSignalFromFile();
testWriteMMSignal();
testCalculateArea();
testCalculateMean();
testCalculateStdDev();
testCalculateMedian();
testCalculateEntropy();
testConvoluteSignals();
testGetPascalLine();
testComputeDFT();
testConvertCart2Polar();
testConvertPolar2Cart();
return 0; return 0;
} }