#include "parser.h"
#include "stack.h"
#include "storage.h"
+#include "tabular.h"
#include "program.h"
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);
(programs + n)->storage = NULL;
(programs + n)->storage_size = 0;
(programs + n)->stack = NULL;
- (programs + n)->stack_size = 0;
(programs + n)->root = dupelement (root);
}
tmp.storage = storage;
tmp.storage_size = storage_size;
tmp.stack = stack;
- tmp.stack_size = stack_size;
/* change context */
answer = 0;
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++) {
free (argument);
}
(programs + n)->stack = stack;
- (programs + n)->stack_size = stack_size;
/* restore context */
answer = tmp.answer;
argument = tmp.argument;
argument_size = tmp.argument_size;
stack = tmp.stack;
- stack_size = tmp.stack_size;
return ret;
}
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);
-#include <malloc.h>
#include <stdio.h>
-#include <string.h>
-#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");
}
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;
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;
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;
}
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;
}
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: */
--- /dev/null
+#include <malloc.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#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: */