# include "util.h"
# include "table.h"

COORD tab_vect(d) UINT d; {
      UINT i;
      COORD v = (COORD) MALLOC ( (d) * sizeof *v);
      for (i = 0; i < d; i++) v[i] = 0;
      return v;
      }

static union st * new_subtable(n) UINT n; {
      return (union st *) MALLOC (n * sizeof (union st));
      }

static TABLE int_tab_new(d,n) UINT d,n; {
      TABLE t = (TABLE) MALLOC (sizeof *t);
      t -> dimension = d;
      t -> extent = n;
      t -> subtable = new_subtable(n);
      return t;
      }

TABLE tab_new(d) UINT d; { return int_tab_new(d,0); }

static UINT int_tab_get(t,v,d) TABLE t; COORD v; UINT d;{
      UINT i;
      if (d == 0) return t -> extent;
      if (t -> subtable == (union st *) 0) return 0;
      i = v[d-1];
      if (d == 1) {
           return i < t->extent ? t -> subtable[i].i : 0;
	   }
      else {
           return i < t->extent ? int_tab_get(t -> subtable[i].t,v,d-1) : 0;
           }
      }

UINT tab_get(t,v) TABLE t; COORD v; {return int_tab_get(t,v,t->dimension);}

VOID zfill(subt, start, end) union st * subt; UINT start, end; {
      for (; start < end; start++) subt[start].i = 0;
      }

TABLE tab_put(t,v,a) TABLE t; COORD v; UINT a;{
      UINT d = t -> dimension;
      UINT i;
      
      if (d == 0) {
         t -> extent = a;
	 return t;
         }
      
      /* First be sure that the subtable is big enough */
      i = v[d-1];

      if (t -> extent <= i) {
           UINT k = 2 * i + 1;
	   UINT j = k;
	   union st * newst = new_subtable(j);
	   zfill(newst, t -> extent ,j);
	   for (j = 0; j < t -> extent; j++) 
	       newst[j].i = t -> subtable[j].i;
	   FREE (t -> subtable);  
	   t -> subtable = newst;
	   t -> extent = k;
           }
      
      if (d == 1) {
           t -> subtable[i].i = a;
	   }
      else {
           /* If there is no table, make one */
           if (t -> subtable[i].i == 0) {
	      TABLE s = int_tab_new(d-1, v[d-2]+1);
	      zfill(s -> subtable, 0, v[d-2]+1);
	      t -> subtable[i].t = s;
	      }
           t -> subtable[i].t = tab_put(t -> subtable[i].t, v, a);
           }
      return t;
      }
