Refactor finding local extrema for performance

This commit is contained in:
Frederik Beimgraben 2025-01-17 20:08:38 +01:00
parent 4ac8f2d4be
commit 21962c9131
4 changed files with 37 additions and 31 deletions

2
.gitignore vendored
View File

@ -57,3 +57,5 @@ main
*results.txt
tests
*.numbered.*
*.old.*

View File

@ -748,19 +748,13 @@ double calculateMedian(double *pdIn, int iLen) {
/*
* Creates a new LocalExtrema struct
*/
LocalExtrema *initLocalExtrema(int *piInPos, int iLen) {
LocalExtrema *createLocalExtrema() {
LocalExtrema *localExtrema = (LocalExtrema*) malloc(sizeof(LocalExtrema));
if (localExtrema == NULL)
_mem_error("initLocalExtrema: Failed to allocate memory for localExtrema");
localExtrema->iNumLocalExtrema = iLen;
localExtrema->piLocalExtremaPos = (int*) malloc(sizeof(int) *iLen);
if (localExtrema->piLocalExtremaPos == NULL)
_mem_error("initLocalExtrema: Failed to allocate memory for localExtrema->piLocalExtremaPos");
for (int i = 0; i < iLen; i++) {
localExtrema->piLocalExtremaPos[i] = piInPos[i];
}
localExtrema->iNumLocalExtrema = 0;
localExtrema->piLocalExtremaPos = NULL;
return localExtrema;
}
@ -793,56 +787,60 @@ void findLocalExtremaFromArray(
LocalExtrema **ppexLocalMax,
LocalExtrema **ppexLocalMin
) {
int iNumLocalMax = 0;
int iNumLocalMin = 0;
int *piLocalMaxPos = NULL;
int *piLocalMinPos = NULL;
LocalExtrema *pexLocalMax = createLocalExtrema();
LocalExtrema *pexLocalMin = createLocalExtrema();
int **ppiLocalMaxPos = &pexLocalMax->piLocalExtremaPos;
int **ppiLocalMinPos = &pexLocalMin->piLocalExtremaPos;
int *iNumLocalMax = &pexLocalMax->iNumLocalExtrema;
int *iNumLocalMin = &pexLocalMin->iNumLocalExtrema;
for (int i = 1; i < iLen - 1; i++) {
if (pdIn[i] > pdIn[i-1] && pdIn[i] > pdIn[i+1]) {
iNumLocalMax++;
(*iNumLocalMax)++;
#ifdef _DEBUG
_debug("findLocalExtremaFromArray: Found local maximum at (%d, %lf)", i, pdIn[i]);
#endif
if (piLocalMaxPos == NULL)
piLocalMaxPos = (int*) malloc(sizeof(int) *iNumLocalMax);
if (*ppiLocalMaxPos == NULL)
*ppiLocalMaxPos = (int*) malloc(sizeof(int) * (*iNumLocalMax));
else
piLocalMaxPos = (int*) realloc(piLocalMaxPos, sizeof(int) *iNumLocalMax);
*ppiLocalMaxPos = (int*) realloc(*ppiLocalMaxPos, sizeof(int) * (*iNumLocalMax));
if (piLocalMaxPos == NULL)
if (*ppiLocalMaxPos == NULL)
_mem_error("findLocalExtremaFromArray: Failed to allocate memory for piLocalMaxPos");
piLocalMaxPos[iNumLocalMax-1] = i;
*ppiLocalMaxPos[(*iNumLocalMax)-1] = i;
}
if (pdIn[i] < pdIn[i-1] && pdIn[i] < pdIn[i+1]) {
iNumLocalMin++;
(*iNumLocalMin)++;
#ifdef _DEBUG
_debug("findLocalExtremaFromArray: Found local minimum at (%d, %lf)", i, pdIn[i]);
#endif
if (piLocalMinPos == NULL)
piLocalMinPos = (int*) malloc(sizeof(int) *iNumLocalMin);
if (*ppiLocalMinPos == NULL)
*ppiLocalMinPos = (int*) malloc(sizeof(int) * (*iNumLocalMin));
else
piLocalMinPos = (int*) realloc(piLocalMinPos, sizeof(int) *iNumLocalMin);
*ppiLocalMinPos = (int*) realloc(*ppiLocalMinPos, sizeof(int) * (*iNumLocalMin));
if (piLocalMinPos == NULL)
if (*ppiLocalMinPos == NULL)
_mem_error("findLocalExtremaFromArray: Failed to allocate memory for piLocalMinPos");
piLocalMinPos[iNumLocalMin-1] = i;
*ppiLocalMinPos[(*iNumLocalMin)-1] = i;
}
}
#ifdef _DEBUG
_debug("findLocalExtremaFromArray: Found %d local maxima", iNumLocalMax);
_debug("findLocalExtremaFromArray: Found %d local minima", iNumLocalMin);
_debug("findLocalExtremaFromArray: Found %d local maxima", *iNumLocalMax);
_debug("findLocalExtremaFromArray: Found %d local minima", *iNumLocalMin);
#endif
*ppexLocalMax = initLocalExtrema(piLocalMaxPos, iNumLocalMax);
*ppexLocalMin = initLocalExtrema(piLocalMinPos, iNumLocalMin);
*ppexLocalMax = pexLocalMax;
*ppexLocalMin = pexLocalMin;
}
/*

View File

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

View File

@ -469,6 +469,12 @@ void testCalcExtrema() {
Extrema *extrema = initExtrema(pdValues, 10);
info("*extrema: %p", extrema);
info("*extrema->pexLocalMax: %p", extrema->pexLocalMax);
info("*extrema->pexLocalMin: %p", extrema->pexLocalMin);
info("*extrema->pexLocalMax->piLocalExtremaPos: %p", extrema->pexLocalMax->piLocalExtremaPos);
info("*extrema->pexLocalMin->piLocalExtremaPos: %p", extrema->pexLocalMin->piLocalExtremaPos);
if (extrema->pexLocalMax->iNumLocalExtrema != 1) {
error("Failed to calculate the correct number of local maxima: %d != 1", extrema->pexLocalMax->iNumLocalExtrema);
}