X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=stack.c;fp=stack.c;h=5c203edfdd54a0a940be9a0432bf49b14d589d6d;hb=a24bd5195f9990159a974c98751f1473f29b9fa4;hp=0000000000000000000000000000000000000000;hpb=a70d1cdb22b2aa77a34d483403a182e335babf8e;p=calc.git diff --git a/stack.c b/stack.c new file mode 100644 index 0000000..5c203ed --- /dev/null +++ b/stack.c @@ -0,0 +1,241 @@ +#include +#include +#include + +#include "alloc.h" +#include "debug.h" +#include "format.h" +#include "parser.h" + +#include "stack.h" + +/* global variables */ + +int stack_size = 0; +double *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; +} + +double length () +{ + return stack_size; +} + +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; +} + +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; +} + +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 > 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; +} + +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; +} + +void show (void) +{ + int i; + fprintf (stdout, "stack:"); + for (i = 0; i < stack_size; i++) { + fprintf (stdout, " "); + fprintf (stdout, minform, stack[i]); + } + fprintf (stdout, "\n"); +} + +/* stack functions */ + +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)); + return 0; + } + ret = stack[0]; + for (i = 1; i < stack_size; i++) { + if (stack[i] > ret) { + ret = stack[i]; + } + } + 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)); + return 0; + } + for (i = 0; i < stack_size; i++) { + ret += stack[i]; + } + return ret / stack_size; +} + +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)); + return 0; + } + ret = stack[0]; + for (i = 1; i < stack_size; i++) { + if (stack[i] < ret) { + ret = stack[i]; + } + } + 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; + } + } +} + +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; + } + 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)); + return 0; + } + for (i = 0; i < stack_size; i++) { + ret *= stack[i]; + } + 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)); + return 0; + } + for (i = 0; i < stack_size; i++) { + ret += stack[i]; + } + 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)); + return 0; + } + m = mean (); + for (i = 0; i < stack_size; i++) { + ret += (stack[i] - m) * (stack[i] - m); + } + return ret / stack_size; +} + +/* vim: set ts=4 sw=4 et: */