From 3559b26cba4b13ce35a27aed478b3a5e0433be31 Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Sun, 12 Feb 2023 14:42:53 +0100 Subject: [PATCH] new type tab_t and rebuild of stack --- calc.c | 2 +- program.c | 10 +-- program.h | 4 +- stack.c | 195 ++++++++++++++++++++---------------------------------- stack.h | 5 +- tabular.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++ tabular.h | 31 +++++++++ 7 files changed, 289 insertions(+), 138 deletions(-) create mode 100644 tabular.c create mode 100644 tabular.h diff --git a/calc.c b/calc.c index 4ef05d7..7cc1c3f 100644 --- a/calc.c +++ b/calc.c @@ -1,6 +1,6 @@ /* depend: */ /* cflags: */ -/* linker: alloc.o debug.o element.o format.o parser.o program.o stack.o storage.o -lm -lreadline */ +/* linker: alloc.o debug.o element.o format.o parser.o program.o stack.o storage.o tabular.o -lm -lreadline */ #include #include diff --git a/program.c b/program.c index 3c94986..97f9929 100644 --- a/program.c +++ b/program.c @@ -6,6 +6,7 @@ #include "parser.h" #include "stack.h" #include "storage.h" +#include "tabular.h" #include "program.h" @@ -54,7 +55,7 @@ void prog (int id, element_t *root) free ((programs + n)->storage); } if ((programs + n)->stack) { - free ((programs + n)->stack); + free_tab ((programs + n)->stack); } if ((programs + n)->root) { delelement ((programs + n)->root); @@ -72,7 +73,6 @@ void prog (int id, element_t *root) (programs + n)->storage = NULL; (programs + n)->storage_size = 0; (programs + n)->stack = NULL; - (programs + n)->stack_size = 0; (programs + n)->root = dupelement (root); } @@ -115,7 +115,6 @@ double call (int id, int nbargs, element_t **args) tmp.storage = storage; tmp.storage_size = storage_size; tmp.stack = stack; - tmp.stack_size = stack_size; /* change context */ answer = 0; @@ -124,7 +123,6 @@ double call (int id, int nbargs, element_t **args) argument = NULL; argument_size = 0; stack = (programs + n)->stack; - stack_size = (programs + n)->stack_size; if (nbargs > 0) { argument = (double *) callocordie (nbargs, sizeof (double)); for (i = 0, l = 0; i < nbargs; l++) { @@ -146,7 +144,6 @@ double call (int id, int nbargs, element_t **args) free (argument); } (programs + n)->stack = stack; - (programs + n)->stack_size = stack_size; /* restore context */ answer = tmp.answer; @@ -155,7 +152,6 @@ double call (int id, int nbargs, element_t **args) argument = tmp.argument; argument_size = tmp.argument_size; stack = tmp.stack; - stack_size = tmp.stack_size; return ret; } @@ -246,7 +242,7 @@ void del (int id) free ((programs + n)->storage); } if ((programs + n)->stack) { - free ((programs + n)->stack); + free_tab ((programs + n)->stack); } if ((programs + n)->root) { delelement ((programs + n)->root); diff --git a/program.h b/program.h index 8fdca14..65382d9 100644 --- a/program.h +++ b/program.h @@ -2,6 +2,7 @@ #define __PROGRAM_H__ #include "element.h" +#include "tabular.h" /* global variables */ @@ -18,8 +19,7 @@ typedef struct _workspace_t { double *argument; int argument_size; element_t *root; - double *stack; - int stack_size; + tab_t *stack; char *string; } workspace_t; diff --git a/stack.c b/stack.c index 5c203ed..829f8aa 100644 --- a/stack.c +++ b/stack.c @@ -1,106 +1,63 @@ -#include #include -#include -#include "alloc.h" #include "debug.h" #include "format.h" #include "parser.h" +#include "tabular.h" #include "stack.h" /* global variables */ -int stack_size = 0; -double *stack = NULL; +tab_t * stack = NULL; /* stack management */ double get (int n) { - double ret = 0; - if ((n <= 0) || (n > stack_size)) { - VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size)); - } else { - ret = stack[n - 1]; - } - return ret; + return get_tab (stack, n); } double length () { - return stack_size; + return size_tab (stack); } double pop () { - double ret = 0; - if (stack_size > 0) { - ret = stack[--stack_size]; - double *tmp = (double *) callocordie (stack_size, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - free (stack); - stack = tmp; - } else { - VERBOSE (WARNING, fprintf (stdout, "error stack empty\n")); - } - return ret; + return pop_tab (stack, -1); } double push (double val) { - double *tmp = (double *) callocordie (stack_size + 1, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - if (stack) { - free (stack); - } - stack = tmp; - stack[stack_size++] = val; - return val; + return push_tab (stack, -1, val); } double put (int n, double val) { - if (n <= 0) { - VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size)); - return 0; + if (n > size_tab (stack)) { + stack = resize_tab (stack, n); } - if (n > stack_size) { - double *tmp = (double *) callocordie (n, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - free (stack); - stack = tmp; - stack_size = n; - } - stack[n - 1] = val; - return val; + return set_tab (stack, n, val); } double set (int nbops, element_t **ops) { int i; - if (stack) { - free (stack); - } - stack = NULL; - stack_size = 0; - if (nbops != 0) { - stack = (double *) callocordie (nbops, sizeof (double)); - for (i = 0; i < nbops; i++) { - stack[i] = evaluate_element (ops[i], 0); - } - stack_size = nbops; - } - return stack_size; + stack = resize_tab (stack, nbops); + for (i = 0; i < nbops; i++) { + set_tab (stack, i + 1, evaluate_element (ops[i], 0)); + } + return size_tab (stack); } void show (void) { - int i; + int i, n = size_tab (stack); fprintf (stdout, "stack:"); - for (i = 0; i < stack_size; i++) { + for (i = 0; i < n; i++) { fprintf (stdout, " "); - fprintf (stdout, minform, stack[i]); + fprintf (stdout, minform, get_tab (stack, i + 1)); } fprintf (stdout, "\n"); } @@ -110,15 +67,16 @@ void show (void) double max () { double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + int i, n = size_tab (stack); + if (n < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", n)); return 0; } - ret = stack[0]; - for (i = 1; i < stack_size; i++) { - if (stack[i] > ret) { - ret = stack[i]; + ret = get_tab (stack, 1); + for (i = 1; i < n; i++) { + double cur = get_tab (stack, i + 1); + if (cur > ret) { + ret = cur; } } return ret; @@ -127,29 +85,30 @@ double max () double mean () { double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + int i, n = size_tab (stack); + if (n < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", n)); return 0; } - for (i = 0; i < stack_size; i++) { - ret += stack[i]; + for (i = 0; i < n; i++) { + ret += get_tab (stack, i + 1); } - return ret / stack_size; + return ret / n; } double min () { double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + int i, n = size_tab (stack); + if (n < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", n)); return 0; } - ret = stack[0]; - for (i = 1; i < stack_size; i++) { - if (stack[i] < ret) { - ret = stack[i]; + ret = get_tab (stack, 1); + for (i = 1; i < n; i++) { + double cur = get_tab (stack, i + 1); + if (cur < ret) { + ret = cur; } } return ret; @@ -157,53 +116,39 @@ double min () void order () { - int i, j; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return; - } - for (i = 0; i < stack_size - 1; i++) { - int done = 0; - for (j = 0; j < stack_size - 1; j++) { - if (stack[j] > stack[j + 1]) { - double tmp = stack[j]; - stack[j] = stack[j + 1]; - stack[j + 1] = tmp; - done = 1; - } - } - if (done == 0) { - break; - } + int n = size_tab (stack); + if (n < 3) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", n)); + } else { + order_tab (stack); } } double median () { double ret = 0; - if (stack_size < 3) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; + int n = size_tab (stack); + if (n < 3) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", n)); + } else { + tab_t *tmp = copy_tab (stack); + order_tab (tmp); + ret = get_tab (tmp, (n - 1) / 2 + 1); + free_tab (tmp); } - double *tmp = (double *) callocordie (stack_size, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - order (); - ret = stack[(stack_size - 1)/ 2]; - memcpy (stack, tmp, stack_size * sizeof (double)); - free (tmp); return ret; } double prod () { double ret = 1; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + int i, n = size_tab (stack); + if (n < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", n)); return 0; } - for (i = 0; i < stack_size; i++) { - ret *= stack[i]; + for (i = 0; i < n; i++) { + ret *= get_tab (stack, i + 1); } return ret; } @@ -211,13 +156,13 @@ double prod () double sum () { double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + int i, n = size_tab (stack); + if (n < 1) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", n)); return 0; } - for (i = 0; i < stack_size; i++) { - ret += stack[i]; + for (i = 0; i < n; i++) { + ret += get_tab (stack, i + 1); } return ret; } @@ -225,17 +170,17 @@ double sum () double variance () { double ret = 0; - double m = 0; - int i; - if (stack_size < 2) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); + int i, n = size_tab (stack); + if (n < 2) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", n)); return 0; } - m = mean (); - for (i = 0; i < stack_size; i++) { - ret += (stack[i] - m) * (stack[i] - m); + double m = mean (); + for (i = 0; i < n; i++) { + double x = get_tab (stack, i + 1); + ret += (x - m) * (x - m); } - return ret / stack_size; + return ret / n; } /* vim: set ts=4 sw=4 et: */ diff --git a/stack.h b/stack.h index e3f0c44..90460ab 100644 --- a/stack.h +++ b/stack.h @@ -2,12 +2,11 @@ #define __STACK_H__ #include "element.h" +#include "tabular.h" /* global variables */ -extern int stack_size; - -extern double *stack; +extern tab_t *stack; /* stack management */ diff --git a/tabular.c b/tabular.c new file mode 100644 index 0000000..0252a8e --- /dev/null +++ b/tabular.c @@ -0,0 +1,180 @@ +#include +#include +#include +#include + +#include "debug.h" +#include "alloc.h" + +#include "tabular.h" + +/* management function */ + +/* allocate a tab of N elements */ + +tab_t *alloc_tab (int nb) +{ + tab_t *tab = (tab_t *) callocordie (1, sizeof (tab_t)); + if (nb > 0) { + tab->data = (double *) callocordie (nb, sizeof (double)); + tab->size = nb; + } + return (tab); +} + +/* resize a tab to size N */ + +tab_t *resize_tab (tab_t *tab, int nb) +{ + double *tmp = NULL; + tab = (tab) ? tab : (tab_t *) callocordie (1, sizeof (tab_t)); + nb = (nb > 0) ? nb : 0; + if (nb > 0) { + tmp = (double *) callocordie (nb, sizeof (double)); + memcpy (tmp, tab->data, ((tab->size < nb) ? tab->size : nb) * sizeof (double)); + } + free (tab->data); + tab->data = tmp; + tab->size = nb; + return tab; +} + +/* copy a tab */ + +tab_t *copy_tab (tab_t *tab) +{ + tab_t *new = alloc_tab (tab->size); + memcpy (new->data, tab->data, tab->size * sizeof (double)); + return new; +} + +/* free a tab */ + +void free_tab (tab_t *tab) +{ + if (tab) { + if (tab->data) { + free (tab->data); + } + free (tab); + } +} + +/* get table size */ + +int size_tab (tab_t *tab) +{ + int ret = 0; + if (tab) { + ret = tab->size; + } + return ret; +} + +/* set an element into a tab at position id [1..N] */ + +double set_tab (tab_t *tab, int id, double val) +{ + double ret = NAN; + if ((!tab) || (id < 1) || (id > tab->size)) { + VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0)); + } else { + ret = tab->data[id - 1] = val; + } + return ret; +} + +/* get an element from a tab at position id [1..N] */ + +double get_tab (tab_t *tab, int id) +{ + double ret = NAN; + if ((!tab) || (id < 1) || (id > tab->size)) { + VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0)); + } else { + ret = tab->data[id - 1]; + } + return ret; +} + +/* push an element into a tab at position id [1.. N](-1 means end) resulting to a tab of N+1 elements */ + +double push_tab (tab_t *tab, int id, double val) +{ + double ret = NAN; + if ((!tab) || (((id < 1) || (id > tab->size + 1)) && (id != -1))) { + VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0)); + } else { + + /* special case for inserting an element at the end */ + id = (id == -1) ? tab->size + 1 : id; + + /* create larger tab */ + double *tmp = (double *) callocordie (tab->size + 1, sizeof (double)); + memcpy (tmp, tab->data, (id - 1) * sizeof (double)); + ret = tmp[id - 1] = val; + memcpy (tmp + id , tab->data + id - 1, (tab->size - id + 1) * sizeof (double)); + + /* update structure */ + free (tab->data); + tab->data = tmp; + tab->size++; + } + return ret; +} + +/* pop an element from a tab at position id [1.. N](-1 means last) resulting to a tab of N-1 elements */ + +double pop_tab (tab_t *tab, int id) +{ + double ret = NAN; + if ((!tab) || (((id < 1) || (id > tab->size)) && (id != -1))) { + VERBOSE (WARNING, fprintf (stdout, "error out of bounds (%d/%d)\n", id, (tab) ? tab->size : 0)); + } else { + ret = tab->data[id - 1]; + + /* special case for inserting an element at the end */ + id = (id == -1) ? tab->size : id; + + /* create larger tab */ + double *tmp = (double *) callocordie (tab->size - 1, sizeof (double)); + memcpy (tmp, tab->data, (id - 1) * sizeof (double)); + memcpy (tmp + id - 1, tab->data + id, (tab->size - id) * sizeof (double)); + + /* update structure */ + free (tab->data); + tab->data = tmp; + tab->size--; + } + return ret; +} + +/* sort tab */ + +void order_tab (tab_t *tab) +{ + int i, j; + if ((!tab) || (tab->size < 3)) { + VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", tab->size)); + return; + } + + /* buble sort */ + for (i = 0; i < tab->size - 1; i++) { + int done = 0; + for (j = 0; j < tab->size - 1; j++) { + double tab_j = tab->data[j]; + double tab_jp1 = tab->data[j + 1]; + if (tab_j > tab_jp1) { + tab->data[j] = tab_jp1; + tab->data[j + 1] = tab_j; + done = 1; + } + } + if (done == 0) { + break; + } + } +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/tabular.h b/tabular.h new file mode 100644 index 0000000..d5c03a6 --- /dev/null +++ b/tabular.h @@ -0,0 +1,31 @@ +#ifndef __TABULAR_H__ +#define __TABULAR_H__ + +#include "debug.h" +#include "alloc.h" + +#include "tabular.h" + +/* tabular type */ + +typedef struct { + double *data; + int size; +} tab_t; + +/* management function */ + +tab_t *alloc_tab (int nb); +tab_t *resize_tab (tab_t *tab, int nb); +tab_t *copy_tab (tab_t *tab); +void free_tab (tab_t *tab); +int size_tab (tab_t *tab); +double set_tab (tab_t *tab, int id, double val); +double get_tab (tab_t *tab, int id); +double push_tab (tab_t *tab, int id, double val); +double pop_tab (tab_t *tab, int id); +void order_tab (tab_t *tab); + +#endif /* __TABULAR_H__ */ + +/* vim: set ts=4 sw=4 et: */ -- 2.30.2