diff --git a/VERSION b/VERSION index d7e92369..333b030a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.646 +8.3.647 diff --git a/resis/ResMakeRes.c b/resis/ResMakeRes.c index 73fe0b99..d41d1c5b 100644 --- a/resis/ResMakeRes.c +++ b/resis/ResMakeRes.c @@ -125,7 +125,7 @@ ResCalcEastWest(tile, pendingList, doneList, resList) resNode **pendingList, **doneList; resResistor **resList; { - int height; + int count, height; bool merged; TileType ttype; Breakpoint *p1, *p2, *p3; @@ -134,6 +134,8 @@ ResCalcEastWest(tile, pendingList, doneList, resList) resNode *currNode; float rArea; resInfo *info = (resInfo *)TiGetClientPTR(tile); + HashTable BreakTable; + HashEntry *he; merged = FALSE; height = TOP(tile) - BOTTOM(tile); @@ -163,21 +165,38 @@ ResCalcEastWest(tile, pendingList, doneList, resList) ttype = TiGetTypeExact(tile); /* Re-sort nodes left to right. */ + count = ResSortBreaks(&info->breakList, TRUE); - ResSortBreaks(&info->breakList, TRUE); + /* For long lists (defined as >= 16 entries), make a hash table of + * the node pointer conversions so that each node can be updated + * as we walk the list, instead of walking the rest of the list in + * a nested loop for each entry. + */ + if (count >= 16) + HashInit(&BreakTable, HT_DEFAULTSIZE, HT_CLIENTKEYS); /* * Eliminate breakpoints with the same X coordinate and merge * their nodes. */ - p2= info->breakList; + p2 = info->breakList; /* Add extra left area to leftmost node */ p2->br_this->rn_float.rn_area += height * (p2->br_loc.p_x - LEFT(tile)); while (p2->br_next != NULL) { + /* Has the node been recorded as needing to be replaced? */ + if (count >= 16) + { + while (TRUE) + { + he = HashLookOnly(&BreakTable, (char *)p2->br_this); + if (!he) break; + p2->br_this = (resNode *)HashGetValue(he); + } + } p1 = p2; p2 = p2->br_next; if (p2->br_loc.p_x == p1->br_loc.p_x) @@ -215,25 +234,38 @@ ResCalcEastWest(tile, pendingList, doneList, resList) /* * Was the node used in another info or breakpoint? * If so, replace the old node with the new one. + * + * Short lists: Walk the list to the end and change + * nodes on the fly. + * Long lists: Record the change to be made in the + * hash table so that it can be executed as each list + * entry is encountered. */ - - p3 = p2->br_next; - while (p3 != NULL) + if (count >= 16) { - if (p3->br_this == currNode) - p3->br_this = p2->br_this; - - p3 = p3->br_next; + he = HashFind(&BreakTable, (char *)currNode); + HashSetValue(he, (char *)p2->br_this); } - } + else + { + p3 = p2->br_next; + while (p3 != NULL) + { + if (p3->br_this == currNode) + p3->br_this = p2->br_this; - /* - * If the X coordinates don't match, make a resistor between - * the breakpoints. - */ + p3 = p3->br_next; + } + } + } - else - { + /* + * If the X coordinates don't match, make a resistor between + * the breakpoints. + */ + + else + { resistor = (resResistor *)mallocMagic((unsigned)sizeof(resResistor)); resistor->rr_nextResistor = (*resList); resistor->rr_lastResistor = NULL; @@ -276,6 +308,8 @@ ResCalcEastWest(tile, pendingList, doneList, resList) } } + if (count >= 16) HashKill(&BreakTable); + p2->br_this->rn_float.rn_area += height * (RIGHT(tile) - p2->br_loc.p_x); freeMagic((char *)p2); info->breakList = NULL; @@ -301,7 +335,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) resNode **pendingList, **doneList; resResistor **resList; { - int width; + int count, width; bool merged; TileType ttype; Breakpoint *p1, *p2, *p3; @@ -310,6 +344,8 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) resNode *currNode; float rArea; resInfo *info = (resInfo *)TiGetClientPTR(tile); + HashTable BreakTable; + HashEntry *he; merged = FALSE; width = RIGHT(tile) - LEFT(tile); @@ -329,7 +365,15 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) } /* Re-sort nodes south to north. */ - ResSortBreaks(&info->breakList, FALSE); + count = ResSortBreaks(&info->breakList, FALSE); + + /* For long lists (defined as >= 16 entries), make a hash table of + * the node pointer conversions so that each node can be updated + * as we walk the list, instead of walking the rest of the list in + * a nested loop for each entry. + */ + if (count >= 16) + HashInit(&BreakTable, HT_DEFAULTSIZE, HT_CLIENTKEYS); /* Simplified split tile handling */ if (IsSplit(tile)) @@ -353,6 +397,16 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) p2->br_this->rn_float.rn_area += width * (p2->br_loc.p_y - BOTTOM(tile)); while (p2->br_next != NULL) { + /* Has the node been recorded as needing to be replaced? */ + if (count >= 16) + { + while (TRUE) + { + he = HashLookOnly(&BreakTable, (char *)p2->br_this); + if (!he) break; + p2->br_this = (resNode *)HashGetValue(he); + } + } p1 = p2; p2 = p2->br_next; if (p1->br_loc.p_y == p2->br_loc.p_y) @@ -390,14 +444,28 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) /* * Was the node used in another info or breakpoint? * If so, replace the old node with the new one. + * + * Short lists: Walk the list to the end and change + * nodes on the fly. + * Long lists: Record the change to be made in the + * hash table so that it can be executed as each list + * entry is encountered. */ - p3 = p2->br_next; - while (p3 != NULL) + if (count >= 16) { - if (p3->br_this == currNode) - p3->br_this = p2->br_this; + he = HashFind(&BreakTable, (char *)currNode); + HashSetValue(he, (char *)p2->br_this); + } + else + { + p3 = p2->br_next; + while (p3 != NULL) + { + if (p3->br_this == currNode) + p3->br_this = p2->br_this; - p3 = p3->br_next; + p3 = p3->br_next; + } } } @@ -1093,12 +1161,14 @@ MergeSortBreaks(Breakpoint *list, int xsort) * bottleneck. * * Results: - * None + * Return the length of the list (maximum truncated at 16) so that + * the calling routine can determine if this is a long or a short + * linked list and treat it accordingly. * *------------------------------------------------------------------------- */ -void +int ResSortBreaks(masterlist, xsort) Breakpoint **masterlist; int xsort; @@ -1113,7 +1183,7 @@ ResSortBreaks(masterlist, xsort) if (count > 16) { *masterlist = MergeSortBreaks(*masterlist, xsort); - return; + return count; } } @@ -1154,5 +1224,6 @@ ResSortBreaks(masterlist, xsort) } } } + return count; } diff --git a/resis/resis.h b/resis/resis.h index 85af3961..f25f510d 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -543,7 +543,7 @@ extern void ResCheckExtNodes(); extern void ResSortByGate(); extern void ResFixDevName(); extern void ResWriteLumpFile(); -extern void ResSortBreaks(); +extern int ResSortBreaks(); extern Plane *extResPrepSubstrate(); /* C99 compat */