X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=tabular.c;fp=tabular.c;h=0252a8e8ec1bf82aad5e3f6a723db40644fe35de;hb=3559b26cba4b13ce35a27aed478b3a5e0433be31;hp=0000000000000000000000000000000000000000;hpb=a24bd5195f9990159a974c98751f1473f29b9fa4;p=calc.git 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: */