#pragma prototyped
#define FDP_PRIVATE 1
#include <fdp.h>
#include <grid.h>
#include <options.h>
#include <macros.h>
typedef struct _block {
cell* mem;
cell* cur;
cell* endp;
struct _block* next;
} block_t;
static block_t*
newBlock (int size)
{
block_t* newb;
newb = GNEW(block_t);
newb->next = 0;
newb->mem = N_GNEW(size,cell);
newb->endp = newb->mem + size;
newb->cur = newb->mem;
return newb;
}
static void
freeBlock (block_t* b)
{
if (b) {
block_t* next = b->next;
free (b->mem);
free (b);
freeBlock (next);
}
}
struct _grid {
Dt_t* data;
block_t* cellMem;
block_t* cellCur;
int listSize;
node_list* listMem;
node_list* listCur;
};
static cell*
getCell (Grid* g)
{
cell* cp;
block_t* bp = g->cellCur;
if (bp->cur == bp->endp) {
if (bp->next == 0) {
bp->next = newBlock (2*(bp->endp - bp->mem));
}
bp = g->cellCur = bp->next;
bp->cur = bp->mem;
}
cp = bp->cur++;
return cp;
}
#ifndef offsetof
#define offsetof(typ,fld) ((int)(&(((typ*)0)->fld)))
#endif
#define max(a,b) ((a)<(b)?(b):(a))
static int
ijcmpf (Dt_t* d, gridpt* p1, gridpt* p2, Dtdisc_t* disc)
{
int diff;
NOTUSED(d);
NOTUSED(disc);
if ((diff = (p1->i - p2->i))) return diff;
else return (p1->j - p2->j);
}
static Grid* _grid;
static void*
newCell (Dt_t* d, void* obj, Dtdisc_t* disc)
{
cell* cellp = (cell*)obj;
cell* newp;
NOTUSED(disc);
newp = getCell (_grid);
newp->p.i = cellp->p.i;
newp->p.j = cellp->p.j;
newp->nodes = 0;
return newp;
}
static node_list*
newNode (Grid* g, Agnode_t* n, node_list* nxt)
{
node_list* newp;
newp = g->listCur++;
newp->node = n;
newp->next = nxt;
return newp;
}
static Dtdisc_t gridDisc = {
offsetof (cell, p),
sizeof (gridpt),
offsetof(cell,link),
(Dtmake_f)newCell,
NIL(Dtfree_f),
(Dtcompar_f)ijcmpf,
NIL(Dthash_f),
NIL(Dtmemory_f),
NIL(Dtevent_f)
} ;
Grid*
mkGrid (int cellHint)
{
Grid* g;
g = GNEW(Grid);
_grid = g;
g->data = dtopen (&gridDisc, Dtoset);
g->listMem = 0;
g->listSize = 0;
g->cellMem = newBlock (cellHint);
return g;
}
void
adjustGrid (Grid* g, int nnodes)
{
int nsize;
if (nnodes > g->listSize) {
nsize = max (nnodes, 2*(g->listSize));
if (g->listMem) free (g->listMem);
g->listMem = N_GNEW (nsize,node_list);
g->listSize = nsize;
}
}
void
clearGrid (Grid* g)
{
dtclear (g->data);
g->listCur = g->listMem;
g->cellCur = g->cellMem;
g->cellCur->cur = g->cellCur->mem;
}
void
delGrid (Grid* g)
{
dtclose (g->data);
freeBlock (g->cellMem);
free (g->listMem);
free (g);
}
void
addGrid (Grid* g, int i, int j, Agnode_t* n)
{
cell* cellp;
cell key;
key.p.i = i;
key.p.j = j;
cellp = dtinsert (g->data, &key);
cellp->nodes = newNode (g, n, cellp->nodes);
if (Verbose >= 3) {
fprintf (stderr, "grid(%d,%d): %s\n", i, j, n->name);
}
}
typedef int(*walkfn_t)(Dt_t*,Void_t*,Void_t*);
void
walkGrid (Grid* g, int(*walkf)(Dt_t*,cell*,Grid*))
{
dtwalk (g->data, (walkfn_t)walkf, g);
}
cell*
findGrid (Grid* g, int i, int j)
{
cell key;
key.p.i = i;
key.p.j = j;
return ((cell*)dtsearch (g->data, &key));
}
int
gLength (cell* p)
{
int len = 0;
node_list* nodes = p->nodes;
while (nodes) {
len++;
nodes = nodes->next;
}
return len;
}