All but DFT confirmed
This commit is contained in:
parent
5b65a43431
commit
f1783f7ce8
347
MMS24-25.c
347
MMS24-25.c
@ -11,17 +11,16 @@
|
||||
* 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>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MMS24-25.h"
|
||||
#include "math.h"
|
||||
|
||||
// #region Error Handling and Debugging
|
||||
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_start(args, fmt);
|
||||
@ -36,7 +35,7 @@ void _error(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_start(args, fmt);
|
||||
@ -47,7 +46,7 @@ void _debug(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_start(args, fmt);
|
||||
@ -69,9 +68,9 @@ double interpolateLine(
|
||||
if (dX2 == dX1)
|
||||
_error("interpolateLine: dX1 and dX2 must differ!");
|
||||
|
||||
double y = dY1 *(
|
||||
double y = dY1 * (
|
||||
(dX2 - dXq) / (dX2 - dX1)
|
||||
) + dY2 *(
|
||||
) + dY2 * (
|
||||
(dXq - dX1) / (dX2 - dX1)
|
||||
);
|
||||
|
||||
@ -99,8 +98,19 @@ void rescaleDoubleArray(
|
||||
* which naturally results from:
|
||||
* $ 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++) {
|
||||
pdOut[i] = pdIn[i] *dFactor + dMin;
|
||||
pdOut[i] = pdIn[i] * dFactor + dOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,13 +139,13 @@ double *generateSineValues(
|
||||
|
||||
// Initialize the output array
|
||||
double *sineArray = NULL;
|
||||
sineArray = (double*) malloc(sizeof(double) *iNumValues);
|
||||
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);
|
||||
sineArray[i] = dAmp * sin(((2*M_PI)/iNumSamplesPerPeriod) * i);
|
||||
}
|
||||
|
||||
return sineArray;
|
||||
@ -147,6 +157,12 @@ void writeDoubleArray(double *pdOut, int iLen, char *pcOutName) {
|
||||
if (file == NULL)
|
||||
_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++) {
|
||||
fprintf(file, "%f\n", pdOut[i]);
|
||||
}
|
||||
@ -204,9 +220,47 @@ MMSignal *createSignal() {
|
||||
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 *signal = createSignal();
|
||||
|
||||
if (pmmsIn->pdValues != NULL) {
|
||||
// Initialize and copy the values (deep copy)
|
||||
signal->pdValues = (double*) malloc(sizeof(double) *pmmsIn->iNumValues);
|
||||
if (signal->pdValues == NULL)
|
||||
@ -215,6 +269,10 @@ MMSignal *createSignalFromSignal(MMSignal *pmmsIn) {
|
||||
for (int i = 0; i < pmmsIn->iNumValues; i++) {
|
||||
signal->pdValues[i] = pmmsIn->pdValues[i];
|
||||
}
|
||||
} else {
|
||||
_warn("createSignalFromSignal: pmmsIn->pdValues is NULL\n");
|
||||
signal->pdValues = NULL;
|
||||
}
|
||||
|
||||
// Copy shallow items
|
||||
signal->iNumValues = pmmsIn->iNumValues;
|
||||
@ -224,38 +282,13 @@ MMSignal *createSignalFromSignal(MMSignal *pmmsIn) {
|
||||
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];
|
||||
if (pmmsIn->pexExtrema == NULL) {
|
||||
_warn("createSignalFromSignal: pmmsIn->pexExtrema is NULL\n");
|
||||
signal->pexExtrema = NULL;
|
||||
return signal;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
signal->pexExtrema = copyExtrema(pmmsIn->pexExtrema);
|
||||
|
||||
return signal;
|
||||
}
|
||||
@ -312,6 +345,9 @@ MMSignal *createSignalFromFile(char *pcInName) {
|
||||
}
|
||||
|
||||
void writeMMSignal(char *pcInName, MMSignal *pmmsIn) {
|
||||
if (pmmsIn->pdValues == NULL)
|
||||
_error("writeMMSignal: pmmsIn->pdValues is NULL\n");
|
||||
|
||||
writeDoubleArray(
|
||||
pmmsIn->pdValues,
|
||||
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) {
|
||||
if (pmmsIn == NULL)
|
||||
return;
|
||||
|
||||
if (pmmsIn->pdValues != NULL)
|
||||
free(pmmsIn->pdValues);
|
||||
free(pmmsIn->pexExtrema->pexLocalMax->piLocalExtremaPos);
|
||||
free(pmmsIn->pexExtrema->pexLocalMax);
|
||||
free(pmmsIn->pexExtrema->pexLocalMin->piLocalExtremaPos);
|
||||
free(pmmsIn->pexExtrema->pexLocalMin);
|
||||
free(pmmsIn->pexExtrema);
|
||||
|
||||
deleteExtrema(pmmsIn->pexExtrema);
|
||||
|
||||
free(pmmsIn);
|
||||
}
|
||||
// #endregion
|
||||
@ -335,24 +390,31 @@ double calculateArea(double *pdIn, int iLen) {
|
||||
double area = 0;
|
||||
|
||||
// #FIXME: Which one should we use according to the task?
|
||||
for (int i = 0; i < iLen-1; i++) {
|
||||
area += (pdIn[i] + pdIn[i+1]) / 2;
|
||||
for (int i = 0; i < iLen; i++) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
double calculateMean(double *pdIn, int iLen) {
|
||||
double mean = 0;
|
||||
|
||||
for (int i = 0; i < iLen; i++) {
|
||||
mean += pdIn[i];
|
||||
}
|
||||
|
||||
return mean / iLen;
|
||||
/* Here the above defined function `calculateArea` is used to calculate the mean, since:
|
||||
* \[ mean(pdIn) = \frac{1}{ |pdIn| } \sum_{i=1}^{ |pdIn| } x_i
|
||||
* = \frac{area(x)}{ |pdIn| } \]
|
||||
*/
|
||||
return calculateArea(pdIn, iLen) / 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 stdDev = 0;
|
||||
|
||||
@ -363,26 +425,41 @@ double calculateStddev(double *pdIn, int 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 *extrema = (Extrema*) malloc(sizeof(Extrema));
|
||||
if (extrema == NULL)
|
||||
_error("initExtrema: Failed to allocate memory for extrema\n");
|
||||
|
||||
extrema->pexLocalMax = (LocalExtrema*) malloc(sizeof(LocalExtrema));
|
||||
if (extrema->pexLocalMax == NULL)
|
||||
_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->pexLocalMax = initLocalExtrema(iLen);
|
||||
extrema->pexLocalMin = initLocalExtrema(iLen);
|
||||
|
||||
extrema->iGlobalMaxPos = 0;
|
||||
extrema->iGlobalMinPos = 0;
|
||||
@ -390,14 +467,6 @@ Extrema *initExtrema(double *pdIn, int iLen) {
|
||||
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) {
|
||||
pmmsIn->dArea = 0;
|
||||
pmmsIn->dMean = 0;
|
||||
@ -409,7 +478,13 @@ void initMMSignalFeatures(MMSignal *pmmsIn) {
|
||||
Histogram *initHistogram(double *pdIn, int iLen, int iNumBins) {
|
||||
Histogram *histogram = (Histogram*) malloc(sizeof(Histogram));
|
||||
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->dIntervalMax = pdIn[0];
|
||||
@ -420,26 +495,61 @@ Histogram *initHistogram(double *pdIn, int iLen, int iNumBins) {
|
||||
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->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);
|
||||
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++) {
|
||||
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;
|
||||
}
|
||||
|
||||
void deleteHistogram(Histogram *phIn) {
|
||||
if (phIn == NULL)
|
||||
return;
|
||||
|
||||
free(phIn->pdBinValues);
|
||||
free(phIn);
|
||||
}
|
||||
|
||||
// #FIXME: Check if this checks out
|
||||
double calculateEntropy(Histogram *phisIn) {
|
||||
double entropy = 0;
|
||||
|
||||
@ -457,40 +567,49 @@ double calculateEntropy(Histogram *phisIn) {
|
||||
// #region Aufgabe 3
|
||||
|
||||
MMSignal *convoluteSignals(MMSignal *pmmsInA, MMSignal *pmmsInB) {
|
||||
MMSignal *signal = createSignal();
|
||||
// Calculate output length
|
||||
int iOutLen = pmmsInA->iNumValues + pmmsInB->iNumValues - 1;
|
||||
|
||||
if (pmmsInA->iNumValues != pmmsInB->iNumValues)
|
||||
_error("convoluteSignals: Signals must have the same length\n");
|
||||
double *pdOut = (double*) malloc(sizeof(double) *iOutLen);
|
||||
if (pdOut == NULL)
|
||||
_error("convoluteSignals: Failed to allocate memory for pdOut\n");
|
||||
|
||||
signal->pdValues = (double*) malloc(sizeof(double) *pmmsInA->iNumValues);
|
||||
if (signal->pdValues == NULL)
|
||||
_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];
|
||||
for (int i = 0; i < iOutLen; i++) {
|
||||
pdOut[i] = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// #FIXME: Check if this checks out
|
||||
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);
|
||||
if (signal->pdValues == NULL)
|
||||
_error("getPascalLine: Failed to allocate memory for signal->pdValues\n");
|
||||
// Calculate a kernel signal using pascales triangle without using the factorial
|
||||
double *pdValues = NULL;
|
||||
pdValues = (double*) malloc(sizeof(double) * iLinenum);
|
||||
if (pdValues == NULL)
|
||||
_error("getPascalLine: Failed to allocate memory for pdValues\n");
|
||||
|
||||
signal->pdValues[0] = 1;
|
||||
signal->pdValues[iLinenum-1] = 1;
|
||||
|
||||
for (int i = 1; i < iLinenum-1; i++) {
|
||||
signal->pdValues[i] = signal->pdValues[i-1] *(iLinenum-i) / i;
|
||||
for (int i = 0; i < iLinenum; i++) {
|
||||
pdValues[i] = 1;
|
||||
for (int j = i-1; j > 0; j--) {
|
||||
pdValues[j] = pdValues[j] + pdValues[j-1];
|
||||
}
|
||||
}
|
||||
|
||||
signal->iNumValues = iLinenum;
|
||||
MMSignal *signal = createSignalFromDoubleArray(iLinenum, pdValues);
|
||||
initMMSignalFeatures(signal);
|
||||
|
||||
return signal;
|
||||
}
|
||||
@ -498,10 +617,12 @@ MMSignal *getPascalLine(int iLinenum) {
|
||||
// #endregion
|
||||
|
||||
// #region Aufgabe 4
|
||||
void computeDFT(int iLen,
|
||||
void computeDFT(
|
||||
int iLen,
|
||||
double *pdRealIn, double *pdImgIn,
|
||||
double *pdRealOut, double *pdImgOut,
|
||||
int iDirection /*-1,1*/) {
|
||||
int iDirection
|
||||
) {
|
||||
// Check the value of iDirection
|
||||
if (iDirection != -1 && iDirection != 1)
|
||||
_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++) {
|
||||
pdRealOut[k] = 0;
|
||||
pdImgOut[k] = 0;
|
||||
|
||||
// Compute the sum for the k-th output element
|
||||
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);
|
||||
pdImgOut[k] += -iDirection * pdRealIn[n] * sin(2*M_PI *k *n / iLen) + pdImgIn[n] * cos(2*M_PI *k *n / iLen);
|
||||
double angle = iDirection * 2.0 * 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,6 +91,6 @@ void computeDFT(int iLen,
|
||||
double *pdRealIn, double *pdImgIn,
|
||||
double *pdRealOut, double *pdImgOut,
|
||||
int iDirection /*-1,1*/);
|
||||
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 convertCart2Polar(double *pdRealIn, double *pdImgIn, double *pdRadiusOut, double *pdAngleOut, int iLen);
|
||||
void convertPolar2Cart(double *pdRadiusIn, double *pdAngleIn, double *pdRealOut, double *pdImgOut, int iLen);
|
||||
#endif
|
||||
|
||||
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
||||
CC=gcc
|
||||
SOURCE_FILE=MMS24-25.c
|
||||
OPTS=-lm -D _TESTS_NONSTOP
|
||||
OPTS=-lm -D _DEBUG_
|
||||
|
||||
all: clean tests run
|
||||
|
||||
|
||||
320
tests.c
320
tests.c
@ -44,8 +44,8 @@ void error(const char* fmt, ...) {
|
||||
void testInterpolation() {
|
||||
info("testInterpolation");
|
||||
|
||||
double dRangeMin = -3;
|
||||
double dRangeMax = 3;
|
||||
double dRangeMin = -1;
|
||||
double dRangeMax = 1;
|
||||
double dRangeStep = 0.33;
|
||||
|
||||
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);
|
||||
|
||||
free(fileName);
|
||||
free(pdSineValues);
|
||||
free(pdReadValues);
|
||||
}
|
||||
|
||||
void testSineAndReadWriteDoubleArray() {
|
||||
@ -130,9 +132,323 @@ void testSineAndReadWriteDoubleArray() {
|
||||
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){
|
||||
testInterpolation();
|
||||
testSineAndReadWriteDoubleArray();
|
||||
testCreateSignalWithDefault();
|
||||
testCreateSignalFromDoubleArray();
|
||||
testCreateSignalFromFile();
|
||||
testWriteMMSignal();
|
||||
testCalculateArea();
|
||||
testCalculateMean();
|
||||
testCalculateStdDev();
|
||||
testCalculateMedian();
|
||||
testCalculateEntropy();
|
||||
testConvoluteSignals();
|
||||
testGetPascalLine();
|
||||
testComputeDFT();
|
||||
testConvertCart2Polar();
|
||||
testConvertPolar2Cart();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user