Improvements, Bug fixes

This commit is contained in:
Frederik Beimgraben 2025-01-13 02:42:58 +01:00
parent a94a357f7a
commit a1bc592bca
3 changed files with 130 additions and 13 deletions

View File

@ -161,7 +161,7 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
*pos = '\0';
#ifdef _DEBUG_
#ifdef _DEBUG
_debug("getline: Read line '%s' with length %ld.", *lineptr, (pos - *lineptr));
#endif
@ -195,7 +195,7 @@ double interpolateLine(
(dXq - dX1) / (dX2 - dX1)
);
#ifdef _DEBUG_
#ifdef _DEBUG
// DEBUG: print the parameters and result
_debug("interpolateLine(%lf, %lf, %lf, %lf, %lf) -> %lf",
dX1,dY1,dX2,dY2,dXq,y);
@ -237,7 +237,7 @@ void rescaleDoubleArray(
// Calculate the offset
double dOffset = dMin - dOldMin;
#ifdef _DEBUG_
#ifdef _DEBUG
_debug("rescaleDoubleArray: dOldMin = %lf", dOldMin);
_debug("rescaleDoubleArray: dOffset = %lf", dOffset);
#endif
@ -475,6 +475,9 @@ MMSignal *createSignalFromSignal(MMSignal *pmmsIn) {
signal->pdValues[i] = pmmsIn->pdValues[i];
}
} else {
if (pmmsIn->iNumValues != 0)
_error("createSignalFromSignal: pmmsIn->pdValues is NULL while pmmsIn->iNumValues is not %d", pmmsIn->iNumValues);
_warn("createSignalFromSignal: pmmsIn->pdValues is NULL");
signal->pdValues = NULL;
}
@ -667,6 +670,21 @@ double calculateStddev(double *pdIn, int iLen) {
return sqrt(stdDev / iLen);
}
/*
* Compares two double values for the qsort function.
*/
int compareDoubles(const void* a, const void* b) {
int val_a = * ( (double*) a );
int val_b = * ( (double*) b );
if ( val_a == val_b )
return 0;
else if ( val_a < val_b )
return -1;
else
return 1;
}
/*
* Calculates the median of an array of double values `pdIn` of length `iLen`.
* The median is calculated as the middle value of the sorted array if the
@ -679,11 +697,28 @@ double calculateMedian(double *pdIn, int iLen) {
* \frac{pdIn_{\frac{|pdIn|}{2}} + pdIn_{\frac{|pdIn|}{2}+1}}{2} & \text{if } |pdIn| \text{ is odd}
* \end{cases} \]
*/
double *pdInSorted = NULL;
pdInSorted = (double*) malloc(sizeof(double) *iLen);
if (iLen == 0) {
_warn("calculateMedian: iLen is 0");
return 0;
}
if (pdInSorted == NULL)
_mem_error("calculateMedian: Failed to allocate memory for pdInSorted");
for (int i = 0; i < iLen; i++) {
pdInSorted[i] = pdIn[i];
}
// Sort the array using stdlib's qsort function
qsort(pdInSorted, iLen, sizeof(double), compareDoubles);
if (iLen % 2 == 0) {
return pdIn[iLen/2];
return (pdIn[iLen/2 - 1] + pdIn[iLen/2]) / 2;
} else {
return (pdIn[iLen/2] + pdIn[iLen/2+1]) / 2;
return pdIn[iLen/2];
}
}
@ -707,9 +742,14 @@ LocalExtrema *initLocalExtrema(int *piInPos, int iLen) {
return localExtrema;
}
int getMinMaxPos(double *pdIn, int iLen, int *iMinPos, int *iMaxPos) {
*iMaxPos = 0;
*iMinPos = 0;
void getMinMaxPos(double *pdIn, int iLen, int *iMinPos, int *iMaxPos) {
*iMaxPos = -1;
*iMinPos = -1;
if (iLen == 0) {
_warn("getMinMaxPos: iLen is 0");
return;
}
for (int i = 1; i < iLen; i++) {
if (pdIn[i] > pdIn[*iMaxPos])
@ -739,6 +779,10 @@ void findLocalExtremaFromArray(
if (pdIn[i] > pdIn[i-1] && pdIn[i] > pdIn[i+1]) {
iNumLocalMax++;
#ifdef _DEBUG
_debug("findLocalExtremaFromArray: Found local maximum at (%d, %lf)", i, pdIn[i]);
#endif
if (piLocalMaxPos == NULL)
piLocalMaxPos = (int*) malloc(sizeof(int) *iNumLocalMax);
else
@ -753,6 +797,10 @@ void findLocalExtremaFromArray(
if (pdIn[i] < pdIn[i-1] && pdIn[i] < pdIn[i+1]) {
iNumLocalMin++;
#ifdef _DEBUG
_debug("findLocalExtremaFromArray: Found local minimum at (%d, %lf)", i, pdIn[i]);
#endif
if (piLocalMinPos == NULL)
piLocalMinPos = (int*) malloc(sizeof(int) *iNumLocalMin);
else
@ -765,6 +813,11 @@ void findLocalExtremaFromArray(
}
}
#ifdef _DEBUG
_debug("findLocalExtremaFromArray: Found %d local maxima", iNumLocalMax);
_debug("findLocalExtremaFromArray: Found %d local minima", iNumLocalMin);
#endif
*ppexLocalMax = initLocalExtrema(piLocalMaxPos, iNumLocalMax);
*ppexLocalMin = initLocalExtrema(piLocalMinPos, iNumLocalMin);
}
@ -782,6 +835,13 @@ Extrema *initExtrema(double *pdIn, int iLen) {
// Get the global extrema
getMinMaxPos(pdIn, iLen, &extrema->iGlobalMinPos, &extrema->iGlobalMaxPos);
#ifdef _DEBUG
if (iLen > 0) {
_debug("initExtrema: Found global minimum at (%d, %lf)", extrema->iGlobalMinPos, pdIn[extrema->iGlobalMinPos]);
_debug("initExtrema: Found global maximum at (%d, %lf)", extrema->iGlobalMaxPos, pdIn[extrema->iGlobalMaxPos]);
}
#endif
// Initialize the local extrema
extrema->pexLocalMax = NULL;
extrema->pexLocalMin = NULL;
@ -831,7 +891,7 @@ Histogram *initHistogram(double *pdIn, int iLen, int iNumBins) {
histogram->dIntervalMax = pdIn[i];
}
#ifdef _DEBUG_
#ifdef _DEBUG
_debug("initHistogram: histogram->dIntervalMin = %lf", histogram->dIntervalMin);
_debug("initHistogram: histogram->dIntervalMax = %lf", histogram->dIntervalMax);
#endif
@ -839,7 +899,7 @@ Histogram *initHistogram(double *pdIn, int iLen, int iNumBins) {
histogram->dBinWidth = (histogram->dIntervalMax - histogram->dIntervalMin) / iNumBins;
histogram->iNumBins = iNumBins;
#ifdef _DEBUG_
#ifdef _DEBUG
_debug("initHistogram: histogram->dBinWidth = %lf", histogram->dBinWidth);
#endif
@ -866,7 +926,7 @@ Histogram *initHistogram(double *pdIn, int iLen, int iNumBins) {
histogram->pdBinValues[i] /= iLen;
}
#ifdef _DEBUG_
#ifdef _DEBUG
// DEBUG: print the parameters and result
_debug("initHistogram(%lf, %lf, %lf, %d)",
histogram->dIntervalMin,histogram->dIntervalMax,histogram->dBinWidth,histogram->iNumBins);
@ -914,6 +974,8 @@ double calculateEntropy(Histogram *phisIn) {
/*
* Convolve two signals `pmmsInA` and `pmmsInB` and return the result.
* Actually this should be named `convolveSignals` but the task specifies
* `convoluteSignals`.
*/
MMSignal *convoluteSignals(MMSignal *pmmsInA, MMSignal *pmmsInB) {
// Calculate output length

View File

@ -1,6 +1,6 @@
CC=gcc
SOURCE_FILE=MMS24-25.c
OPTS=-lm -std=c99
OPTS=-lm -std=c99 -D _DEBUG_
all: clean tests run

57
tests.c
View File

@ -289,10 +289,18 @@ void testCalculateMedian() {
double dMedian = calculateMedian(pdValues, 10);
if (dMedian != 6) {
if (dMedian != 5.5) {
error("Failed to calculate the correct median: %lf != 5.5", dMedian);
}
double pdValues2[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
dMedian = calculateMedian(pdValues2, 9);
if (dMedian != 5) {
error("Failed to calculate the correct median: %lf != 5", dMedian);
}
success("testCalculateMedian");
}
@ -385,6 +393,17 @@ void testGetPascalLine() {
success("testGetPascalLine");
}
void testApplyPascalConvForSeriesGT40() {
info("testApplyPascalForSeriesGT40");
MMSignal *signal = getPascalLine(40);
MMSignal *signal2 = convoluteSignals(signal, signal);
writeMMSignal("testApplyPascalForSeriesGT40.results.txt", signal2);
success("testApplyPascalForSeriesGT40");
}
void testComputeDFT() {
info("testComputeDFT");
@ -443,6 +462,40 @@ void testConvertPolar2Cart() {
success("testConvertPolar2Cart");
}
void testCalcExtrema() {
info("testCalcExtrema");
double pdValues[] = {1, 2, 1, 0, -1, -2, -1, 0, 1, 5};
Extrema *extrema = initExtrema(pdValues, 10);
if (extrema->pexLocalMax->iNumLocalExtrema != 1) {
error("Failed to calculate the correct number of local maxima: %d != 1", extrema->pexLocalMax->iNumLocalExtrema);
}
if (extrema->pexLocalMin->iNumLocalExtrema != 1) {
error("Failed to calculate the correct number of local minima: %d != 1", extrema->pexLocalMin->iNumLocalExtrema);
}
if (extrema->iGlobalMaxPos != 9) {
error("Failed to calculate the correct global maximum position: %d != 9", extrema->iGlobalMaxPos);
}
if (extrema->iGlobalMinPos != 5) {
error("Failed to calculate the correct global minimum position: %d != 4", extrema->iGlobalMinPos);
}
if (extrema->pexLocalMax->piLocalExtremaPos[0] != 1) {
error("Failed to calculate the correct local maximum position: %d != 9", extrema->pexLocalMax->piLocalExtremaPos[0]);
}
if (extrema->pexLocalMin->piLocalExtremaPos[0] != 5) {
error("Failed to calculate the correct local minimum position: %d != 4", extrema->pexLocalMin->piLocalExtremaPos[0]);
}
success("testCalcExtrema");
}
int main (int iArgC, char** ppcArgV){
testInterpolation();
testSineAndReadWriteDoubleArray();
@ -460,6 +513,8 @@ int main (int iArgC, char** ppcArgV){
testComputeDFT();
testConvertCart2Polar();
testConvertPolar2Cart();
testApplyPascalConvForSeriesGT40();
testCalcExtrema();
return 0;
}