From c5de0c21c9669849780908b9dc851d78bdaba6eb Mon Sep 17 00:00:00 2001 From: h_vogt Date: Sun, 9 Dec 2012 13:08:43 +0100 Subject: [PATCH] findvec(), use hash tables for the vector search patch originally provided by Bill Swartz, 2010 reduces vector search time from O(n) to O(1) --- src/frontend/plotting/plotting.c | 3 +- src/frontend/vectors.c | 74 ++++++++++++++++++++++++++++---- src/include/ngspice/plot.h | 3 ++ 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/frontend/plotting/plotting.c b/src/frontend/plotting/plotting.c index 8410a898a..51fa9d0a2 100644 --- a/src/frontend/plotting/plotting.c +++ b/src/frontend/plotting/plotting.c @@ -6,7 +6,8 @@ struct plot constantplot = { "Constant values", Spice_Build_Date, "constants", - "const", NULL, NULL, NULL, NULL, NULL, NULL, TRUE, 0 + "const", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + TRUE, FALSE, 0 }; struct plot *plot_cur = &constantplot; diff --git a/src/frontend/vectors.c b/src/frontend/vectors.c index c7a3d7be5..e250540b0 100644 --- a/src/frontend/vectors.c +++ b/src/frontend/vectors.c @@ -19,6 +19,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include "dimens.h" #include "../misc/misc_time.h" #include "vectors.h" +#include "ngspice/dstring.h" #include "plotting/plotting.h" #ifdef XSPICE @@ -28,13 +29,46 @@ struct dvec *EVTfindvec(char *node); #endif +static void +vec_rebuild_lookup_table(struct plot *pl) +{ + int cnt; /* count entries */ + struct dvec *d; /* dynamic vector */ + NGHASHPTR lookup_p; /* lookup table for speed */ + SPICE_DSTRING dbuf; /* dynamic buffer */ + char *lower_name; /* lower case name */ + + if (pl->pl_lookup_table) { + nghash_empty(pl->pl_lookup_table, NULL, NULL); + } else { + cnt = 0; + for (d = pl->pl_dvecs; d; d = d->v_next) + cnt++; + pl->pl_lookup_table = nghash_init(cnt); + /* allow multiple entries */ + nghash_unique(pl->pl_lookup_table, FALSE); + } + lookup_p = pl->pl_lookup_table; + spice_dstring_init(&dbuf); + for (d = pl->pl_dvecs; d; d = d->v_next) { + spice_dstring_reinit(&dbuf); + lower_name = spice_dstring_append_lower(&dbuf, d->v_name, -1); + nghash_insert(lookup_p, lower_name, d); + } + spice_dstring_free(&dbuf); + pl->pl_lookup_valid = TRUE; +} + + /* Find a named vector in a plot. We are careful to copy the vector if * v_link2 is set, because otherwise we will get screwed up. */ static struct dvec * findvec(char *word, struct plot *pl) { + SPICE_DSTRING dbuf; /* dynamic buffer */ + char *lower_name; /* lower case name */ + char *node_name; struct dvec *d, *newv = NULL, *end = NULL, *v; - char buf[BSIZE_SP]; if (pl == NULL) return (NULL); @@ -115,15 +149,37 @@ findvec(char *word, struct plot *pl) return (newv); } - for (d = pl->pl_dvecs; d; d = d->v_next) - if (cieq(word, d->v_name) && (d->v_flags & VF_PERMANENT)) + if (!pl->pl_lookup_valid) + vec_rebuild_lookup_table(pl); + + spice_dstring_init(&dbuf); + lower_name = spice_dstring_append_lower(&dbuf, word, -1); + + for (d = nghash_find(pl->pl_lookup_table, lower_name); + d; + d = nghash_find_again(pl->pl_lookup_table, lower_name)) + { + if (d->v_flags & VF_PERMANENT) break; - if (!d) { - (void) sprintf(buf, "v(%s)", word); - for (d = pl->pl_dvecs; d; d = d->v_next) - if (cieq(buf, d->v_name) && (d->v_flags & VF_PERMANENT)) - break; } + + if (!d) { + spice_dstring_reinit(&dbuf); + spice_dstring_append(&dbuf, "v(", -1); + spice_dstring_append_lower(&dbuf, word, -1); + node_name = spice_dstring_append_char(&dbuf, ')'); + + for (d = nghash_find(pl->pl_lookup_table, node_name); + d; + d = nghash_find_again(pl->pl_lookup_table, node_name)) + { + if (d->v_flags & VF_PERMANENT) + break; + } + } + + spice_dstring_free(&dbuf); + #ifdef XSPICE /* gtri - begin - Add processing for getting event-driven vector */ @@ -728,6 +784,7 @@ vec_new(struct dvec *d) if (plot_cur == NULL) { fprintf(cp_err, "vec_new: Internal Error: no cur plot\n"); } + plot_cur->pl_lookup_valid = FALSE; if ((d->v_flags & VF_PERMANENT) && (plot_cur->pl_scale == NULL)) plot_cur->pl_scale = d; if (!d->v_plot) @@ -791,6 +848,7 @@ vec_free_x(struct dvec *v) /* Now we have to take this dvec out of the plot list. */ if (pl != NULL) { + pl->pl_lookup_valid = FALSE; if (pl->pl_dvecs == v) { pl->pl_dvecs = v->v_next; } else { diff --git a/src/include/ngspice/plot.h b/src/include/ngspice/plot.h index 12810abdc..5347a3a98 100644 --- a/src/include/ngspice/plot.h +++ b/src/include/ngspice/plot.h @@ -4,6 +4,7 @@ #include "ngspice/wordlist.h" #include "ngspice/bool.h" #include "ngspice/dvec.h" +#include "ngspice/hash.h" struct ccom; @@ -17,10 +18,12 @@ struct plot { struct dvec *pl_dvecs; /* The data vectors in this plot. */ struct dvec *pl_scale; /* The "scale" for the rest of the vectors. */ struct plot *pl_next; /* List of plots. */ + NGHASHPTR pl_lookup_table; /* for quick lookup of vectors */ wordlist *pl_commands; /* Commands to execute for this plot. */ struct variable *pl_env; /* The 'environment' for this plot. */ struct ccom *pl_ccom; /* The ccom struct for this plot. */ bool pl_written; /* Some or all of the vecs have been saved. */ + bool pl_lookup_valid; /* vector lookup table valid */ int pl_ndims; /* Number of dimensions */ } ;