split code into multiple files
[calc.git] / stack.c
diff --git a/stack.c b/stack.c
new file mode 100644 (file)
index 0000000..5c203ed
--- /dev/null
+++ b/stack.c
@@ -0,0 +1,241 @@
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+#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: */