3x faster table_read() on big data
This commit is contained in:
parent
6c22c47975
commit
1aaa48a75b
123
src/editprop.c
123
src/editprop.c
|
|
@ -608,6 +608,129 @@ void set_inst_prop(int i)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define is_a_digit(c) ((c) >= '0' && (c) <= '9')
|
||||
#define is_a_space(c) ((c) == ' ' || (c) == '\t')
|
||||
|
||||
/* fast convert (decimal) string to float */
|
||||
float my_atof(const char *p)
|
||||
{
|
||||
static const float p10[]={
|
||||
1e-1f, 1e-2f, 1e-3f, 1e-4f, 1e-5f, 1e-6f, 1e-7f, 1e-8f
|
||||
};
|
||||
int frac;
|
||||
float sign, value, scale;
|
||||
|
||||
/* skip initial spaces */
|
||||
while(is_a_space(*p)) p++;
|
||||
/* sign */
|
||||
sign = 1.0;
|
||||
if(*p == '-') {
|
||||
sign = -1.0;
|
||||
p++;
|
||||
} else if(*p == '+') {
|
||||
p++;
|
||||
}
|
||||
/* Get digits */
|
||||
for(value = 0.0; is_a_digit(*p); p++) {
|
||||
value = value * 10.0f + (*p - '0');
|
||||
}
|
||||
/* get fractional part */
|
||||
if(*p == '.') {
|
||||
int cnt = 0;
|
||||
p++;
|
||||
while (is_a_digit(*p)) {
|
||||
if(cnt >= 17) continue; /* after 17 skip additional fractional digits */
|
||||
value += (*(p++) - '0') * p10[cnt++];
|
||||
}
|
||||
}
|
||||
/* Exponent */
|
||||
frac = 0;
|
||||
scale = 1.0;
|
||||
if((*p == 'e') || (*p == 'E')) {
|
||||
unsigned int exponent;
|
||||
/* Exponent sign */
|
||||
p++;
|
||||
if(*p == '-') {
|
||||
frac = 1;
|
||||
p++;
|
||||
} else if(*p == '+') p++;
|
||||
/* Get digits of exponent, if any. */
|
||||
for(exponent = 0; is_a_digit(*p); p += 1) {
|
||||
exponent = exponent * 10 + (*p - '0');
|
||||
}
|
||||
if(exponent > 38) exponent = 38;
|
||||
/* Calculate scaling factor. */
|
||||
while (exponent >= 12) { scale *= 1E12f; exponent -= 12; }
|
||||
while (exponent >= 4) { scale *= 1E4f; exponent -= 4; }
|
||||
while (exponent > 0) { scale *= 10.0f; exponent -= 1; }
|
||||
}
|
||||
return sign * (frac ? (value / scale) : (value * scale));
|
||||
}
|
||||
|
||||
/* fast convert (decimal) string to double */
|
||||
double my_atod(const char *p)
|
||||
{
|
||||
static const double p10[]={
|
||||
1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9,
|
||||
1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18
|
||||
};
|
||||
int frac;
|
||||
double sign, value, scale;
|
||||
|
||||
/* skip initial spaces */
|
||||
while(is_a_space(*p)) p++;
|
||||
/* sign */
|
||||
sign = 1.0;
|
||||
if(*p == '-') {
|
||||
sign = -1.0;
|
||||
p++;
|
||||
} else if(*p == '+') {
|
||||
p++;
|
||||
}
|
||||
/* Get digits */
|
||||
for(value = 0.0; is_a_digit(*p); p++) {
|
||||
value = value * 10.0 + (*p - '0');
|
||||
}
|
||||
/* get fractional part */
|
||||
if(*p == '.') {
|
||||
int cnt = 0;
|
||||
p++;
|
||||
while (is_a_digit(*p)) {
|
||||
if(cnt >= 17) continue; /* after 17 skip additional fractional digits */
|
||||
value += (*(p++) - '0') * p10[cnt++];
|
||||
}
|
||||
}
|
||||
/* Exponent */
|
||||
frac = 0;
|
||||
scale = 1.0;
|
||||
if((*p == 'e') || (*p == 'E')) {
|
||||
unsigned int exponent;
|
||||
/* Exponent sign */
|
||||
p++;
|
||||
if(*p == '-') {
|
||||
frac = 1;
|
||||
p++;
|
||||
} else if(*p == '+') p++;
|
||||
/* Get digits of exponent, if any. */
|
||||
for(exponent = 0; is_a_digit(*p); p += 1) {
|
||||
exponent = exponent * 10 + (*p - '0');
|
||||
}
|
||||
if(exponent > 308) exponent = 308;
|
||||
/* Calculate scaling factor. */
|
||||
while (exponent >= 50) { scale *= 1E50; exponent -= 50; }
|
||||
while (exponent >= 8) { scale *= 1E8; exponent -= 8; }
|
||||
while (exponent > 0) { scale *= 10.0; exponent -= 1; }
|
||||
}
|
||||
return sign * (frac ? (value / scale) : (value * scale));
|
||||
}
|
||||
|
||||
/* super fast count # of lines (and bytes) in a file */
|
||||
int count_lines_bytes(int fd, size_t *lines, size_t *bytes)
|
||||
{
|
||||
|
|
|
|||
39
src/save.c
39
src/save.c
|
|
@ -383,20 +383,20 @@ static void read_binary_block(FILE *fd)
|
|||
if(ac) {
|
||||
for(v = 0; v < xctx->graph_nvars; v += 2) { /*AC analysis: calculate magnitude */
|
||||
if( v == 0 ) /* sweep var */
|
||||
xctx->graph_values[v][offset + p] = (float)sqrt( tmp[v] * tmp[v] + tmp[v + 1] * tmp[v + 1]);
|
||||
xctx->graph_values[v][offset + p] = (SPICE_DATA)sqrt( tmp[v] * tmp[v] + tmp[v + 1] * tmp[v + 1]);
|
||||
else /* magnitude */
|
||||
/* avoid 0 for dB calculations */
|
||||
if(tmp[v] == 0.0 && tmp[v + 1] == 0.0) xctx->graph_values[v][offset + p] = 1e-35f;
|
||||
else xctx->graph_values[v][offset + p] =
|
||||
(float)sqrt(tmp[v] * tmp[v] + tmp[v + 1] * tmp[v + 1]);
|
||||
(SPICE_DATA)sqrt(tmp[v] * tmp[v] + tmp[v + 1] * tmp[v + 1]);
|
||||
/* AC analysis: calculate phase */
|
||||
if(tmp[v] == 0.0 && tmp[v + 1] == 0.0) xctx->graph_values[v + 1] [offset + p] = 0.0;
|
||||
else xctx->graph_values[v + 1] [offset + p] =
|
||||
(float)(atan2(tmp[v + 1], tmp[v]) * 180.0 / XSCH_PI);
|
||||
(SPICE_DATA)(atan2(tmp[v + 1], tmp[v]) * 180.0 / XSCH_PI);
|
||||
}
|
||||
}
|
||||
else for(v = 0; v < xctx->graph_nvars; v++) {
|
||||
xctx->graph_values[v][offset + p] = (float)tmp[v];
|
||||
xctx->graph_values[v][offset + p] = (SPICE_DATA)tmp[v];
|
||||
}
|
||||
}
|
||||
my_free(_ALLOC_ID_, &tmp);
|
||||
|
|
@ -761,6 +761,8 @@ int table_read(const char *f)
|
|||
{
|
||||
int res = 0;
|
||||
FILE *fd;
|
||||
int ufd;
|
||||
size_t lines, bytes;
|
||||
char *line = NULL, *line_ptr, *line_save;
|
||||
const char *line_tok;
|
||||
|
||||
|
|
@ -768,6 +770,12 @@ int table_read(const char *f)
|
|||
dbg(0, "table_read(): must clear current data file before loading new\n");
|
||||
return 0;
|
||||
}
|
||||
/* quick inspect file and get upper bound of number of data lines */
|
||||
ufd = open(f, O_RDONLY);
|
||||
if(ufd < 0) goto err;
|
||||
count_lines_bytes(ufd, &lines, &bytes);
|
||||
close(ufd);
|
||||
|
||||
int_hash_init(&xctx->graph_raw_table, HASHSIZE);
|
||||
fd = fopen(f, fopen_read_mode);
|
||||
if(fd) {
|
||||
|
|
@ -803,28 +811,37 @@ int table_read(const char *f)
|
|||
field = 0;
|
||||
while( (line_tok = strtok_r(line_ptr, " \t\n", &line_save)) ) {
|
||||
line_ptr = NULL;
|
||||
dbg(1,"%s ", line_tok);
|
||||
/* dbg(1,"%s ", line_tok); */
|
||||
if(nline == 0) { /* header line */
|
||||
my_realloc(_ALLOC_ID_, &xctx->graph_names, (field + 1) * sizeof(char *));
|
||||
xctx->graph_names[field] = NULL;
|
||||
my_strcat(_ALLOC_ID_, &xctx->graph_names[field], line_tok);
|
||||
int_hash_lookup(&xctx->graph_raw_table, xctx->graph_names[field], field, XINSERT_NOREPLACE);
|
||||
xctx->graph_nvars = field + 1;
|
||||
} else { /* data line */
|
||||
my_realloc(_ALLOC_ID_, &xctx->graph_values[field], (npoints + 1) * sizeof(SPICE_DATA));
|
||||
xctx->graph_values[field][npoints] = (float)atof(line_tok);
|
||||
if(field >= xctx->graph_nvars) break;
|
||||
#if SPICE_DATA == float
|
||||
xctx->graph_values[field][npoints] = (SPICE_DATA)my_atof(line_tok);
|
||||
#else
|
||||
xctx->graph_values[field][npoints] = (SPICE_DATA)my_atod(line_tok);
|
||||
#endif
|
||||
|
||||
}
|
||||
field++;
|
||||
xctx->graph_nvars = field;
|
||||
}
|
||||
if(nline) { /* skip header line for npoints calculation*/
|
||||
npoints++;
|
||||
dataset_points++;
|
||||
}
|
||||
xctx->graph_npoints[xctx->graph_datasets - 1] = dataset_points;
|
||||
dbg(1, "\n");
|
||||
/* dbg(1, "\n"); */
|
||||
nline++;
|
||||
if(nline == 1) {
|
||||
int f;
|
||||
xctx->graph_values = my_calloc(_ALLOC_ID_, xctx->graph_nvars + 1, sizeof(SPICE_DATA *));
|
||||
for(f = 0; f <= xctx->graph_nvars; f++) { /* one extra column for wave expressions */
|
||||
my_realloc(_ALLOC_ID_, &xctx->graph_values[f], lines * sizeof(SPICE_DATA));
|
||||
}
|
||||
}
|
||||
clear:
|
||||
my_free(_ALLOC_ID_, &line);
|
||||
|
|
@ -842,8 +859,6 @@ int table_read(const char *f)
|
|||
dbg(0, "Table file data read: %s\n", f);
|
||||
dbg(0, "points=%d, vars=%d, datasets=%d\n",
|
||||
xctx->graph_allpoints, xctx->graph_nvars, xctx->graph_datasets);
|
||||
/* allocate extra column for custom calculated data (expressions) */
|
||||
my_realloc(_ALLOC_ID_, &xctx->graph_values[xctx->graph_nvars], npoints * sizeof(SPICE_DATA));
|
||||
} else {
|
||||
dbg(0, "table_read(): no useful data found\n");
|
||||
}
|
||||
|
|
@ -1312,7 +1327,7 @@ int plot_raw_custom_data(int sweep_idx, int first, int last, const char *expr)
|
|||
} /* switch(...) */
|
||||
} /* if(stackptr2 > 0) */
|
||||
} /* for(i = 0; i < stackptr1; i++) */
|
||||
y[p] = (float)stack2[0];
|
||||
y[p] = (SPICE_DATA)stack2[0];
|
||||
} /* for(p = first ...) */
|
||||
ravg_store(0, 0, 0, 0, 0.0); /* clear data */
|
||||
return xctx->graph_nvars;
|
||||
|
|
|
|||
|
|
@ -1399,6 +1399,8 @@ extern double round_to_n_digits(double x, int n);
|
|||
extern double floor_to_n_digits(double x, int n);
|
||||
extern double ceil_to_n_digits(double x, int n);
|
||||
extern int count_lines_bytes(int fd, size_t *lines, size_t *bytes);
|
||||
extern double my_atod(const char *p);
|
||||
extern float my_atof(const char *p);
|
||||
extern const char *subst_token(const char *s, const char *tok, const char *new_val);
|
||||
extern void new_prop_string(int i, const char *old_prop,int fast, int dis_uniq_names);
|
||||
extern void hash_name(char *token, int remove);
|
||||
|
|
|
|||
Loading…
Reference in New Issue