From 21962c91316958d87b8ceba74d89588fc6c974c8 Mon Sep 17 00:00:00 2001 From: Frederik Beimgraben Date: Fri, 17 Jan 2025 20:08:38 +0100 Subject: [PATCH] Refactor finding local extrema for performance --- .gitignore | 4 +++- MMS24-25.c | 56 ++++++++++++++++++++++++++---------------------------- Makefile | 2 +- tests.c | 6 ++++++ 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index f4bc886..9cb28f0 100644 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,6 @@ main *results.txt -tests \ No newline at end of file +tests +*.numbered.* +*.old.* diff --git a/MMS24-25.c b/MMS24-25.c index d973c09..26a74e6 100644 --- a/MMS24-25.c +++ b/MMS24-25.c @@ -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; } /* diff --git a/Makefile b/Makefile index bf8468c..f1301eb 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC=gcc SOURCE_FILE=MMS24-25.c -OPTS=-lm +OPTS=-lm -D _DEBUG all: clean tests run diff --git a/tests.c b/tests.c index 9ad5137..3141940 100644 --- a/tests.c +++ b/tests.c @@ -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); }