Merge pull request #754 from lbutler/getclosedlink-remove-recursion

Remove recursion in getclosedlink
This commit is contained in:
Lew Rossman
2023-09-15 11:01:39 -04:00
committed by GitHub
2 changed files with 37 additions and 14 deletions

View File

@@ -47,4 +47,5 @@ This document describes the changes and updates that have been made in version 2
- `EN_STATUS_REPORT` can now be used with `EN_getoption` and `EN_setoption` to get or set the type of status report that EPANET will generate (`EN_NO_REPORT`, `EN_NORMAL_REPORT` or `EN_FULL_REPORT`). - `EN_STATUS_REPORT` can now be used with `EN_getoption` and `EN_setoption` to get or set the type of status report that EPANET will generate (`EN_NO_REPORT`, `EN_NORMAL_REPORT` or `EN_FULL_REPORT`).
- A possible parser error that could result in a Trace Node ID in an input file not being recognized was fixed. - A possible parser error that could result in a Trace Node ID in an input file not being recognized was fixed.
- Additional API functions for enabling/disabling controls and rules were added. - Additional API functions for enabling/disabling controls and rules were added.
- Updated the internal function `getclosedlink` in report.c to use a loop instead of recursion to prevent a stack overflow during the analysis of very large disconnections.

View File

@@ -45,7 +45,7 @@ static void writeenergy(Project *);
static int writeresults(Project *); static int writeresults(Project *);
static int disconnected(Project *); static int disconnected(Project *);
static void marknodes(Project *, int, int *, char *); static void marknodes(Project *, int, int *, char *);
static void getclosedlink(Project *, int, char *); static void getclosedlink(Project *, int, char *, int *);
static void writelimits(Project *, int, int); static void writelimits(Project *, int, int);
static int checklimits(Report *, double *, int, int); static int checklimits(Report *, double *, int, int);
static char *fillstr(char *, char, int); static char *fillstr(char *, char, int);
@@ -1287,7 +1287,7 @@ int disconnected(Project *pr)
clocktime(rpt->Atime, time->Htime)); clocktime(rpt->Atime, time->Htime));
writeline(pr, pr->Msg); writeline(pr, pr->Msg);
} }
getclosedlink(pr, j, marked); getclosedlink(pr, j, marked, nodelist);
} }
// Free allocated memory // Free allocated memory
@@ -1350,11 +1350,12 @@ void marknodes(Project *pr, int m, int *nodelist, char *marked)
} }
} }
void getclosedlink(Project *pr, int i, char *marked) void getclosedlink(Project *pr, int i, char *marked, int *stack)
/* /*
**---------------------------------------------------------------- **----------------------------------------------------------------
** Input: i = junction index ** Input: i = junction index
** marked[] = marks nodes already examined ** marked[] = marks nodes already examined
** stack[] = stack to hold nodes to examine
** Output: None. ** Output: None.
** Purpose: Determines if a closed link connects to junction i. ** Purpose: Determines if a closed link connects to junction i.
**---------------------------------------------------------------- **----------------------------------------------------------------
@@ -1365,22 +1366,43 @@ void getclosedlink(Project *pr, int i, char *marked)
int j, k; int j, k;
Padjlist alink; Padjlist alink;
int top = 0;
// Mark the current junction as examined and push onto stack
marked[i] = 2; marked[i] = 2;
for (alink = net->Adjlist[i]; alink != NULL; alink = alink->next) stack[top] = i;
{
while (top >= 0) {
i = stack[top--];
alink = net->Adjlist[i];
// Iterate through each link adjacent to the current node
while (alink != NULL) {
k = alink->link; k = alink->link;
j = alink->node; j = alink->node;
if (marked[j] == 2) continue;
if (marked[j] == 1) // Skip nodes that have already been examined
{ if (marked[j] == 2) {
alink = alink->next;
continue;
}
// If a closed link is found, return and display a warning message
if (marked[j] == 1) {
sprintf(pr->Msg, WARN03c, net->Link[k].ID); sprintf(pr->Msg, WARN03c, net->Link[k].ID);
writeline(pr, pr->Msg); writeline(pr, pr->Msg);
return; return;
} }
else getclosedlink(pr, j, marked);
// Mark the node as examined and push it onto the stack
marked[j] = 2;
stack[++top] = j;
alink = alink->next;
} }
} }
}
void writelimits(Project *pr, int j1, int j2) void writelimits(Project *pr, int j1, int j2)
/* /*
**-------------------------------------------------------------- **--------------------------------------------------------------