xschem/src/hash_iterator.c

192 lines
6.8 KiB
C

/* File: hash_iterator.c
*
* This file is part of XSCHEM,
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
* simulation.
* Copyright (C) 1998-2023 Stefan Frederik Schippers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xschem.h"
void init_inst_iterator(Iterator_ctx *ctx, double x1, double y1, double x2, double y2)
{
ctx->instflag = NULL;
dbg(3, "init_inst_iterator(): instances=%d\n", xctx->instances);
if(xctx->instances) {
my_realloc(_ALLOC_ID_, &ctx->instflag, xctx->instances*sizeof(unsigned short));
memset(ctx->instflag, 0, xctx->instances*sizeof(unsigned short));
}
/* calculate square 4 1st corner of drawing area */
ctx->x1a = (int)floor(x1 / BOXSIZE) ;
ctx->y1a = (int)floor(y1 / BOXSIZE) ;
/* calculate square 4 2nd corner of drawing area */
ctx->x2a = (int)floor(x2 / BOXSIZE);
ctx->y2a = (int)floor(y2 / BOXSIZE);
ctx->i = ctx->x1a;
ctx->j = ctx->y1a;
ctx->tmpi = ctx->i % NBOXES; if(ctx->tmpi < 0) ctx->tmpi += NBOXES;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj += NBOXES;
ctx->counti = 0;
ctx->instanceptr = xctx->inst_spatial_table[ctx->tmpi][ctx->tmpj];
ctx->countj = 0;
}
Instentry *inst_iterator_next(Iterator_ctx *ctx)
{
Instentry *ptr;
/* dbg(3, "inst_iterator_next(): instances=%d\n", xctx->instances); */
while(1) {
while(ctx->instanceptr) {
ptr = ctx->instanceptr;
ctx->instanceptr = ctx->instanceptr->next;
if(!ctx->instflag[ptr->n]) {
ctx->instflag[ptr->n]=1;
return ptr;
}
}
if(ctx->j < ctx->y2a && ctx->countj++ < NBOXES) {
ctx->j++;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj+=NBOXES;
ctx->instanceptr = xctx->inst_spatial_table[ctx->tmpi][ctx->tmpj];
} else if(ctx->i < ctx->x2a && ctx->counti++ < NBOXES) {
ctx->i++;
ctx->j = ctx->y1a;
ctx->countj = 0;
ctx->tmpi = ctx->i % NBOXES; if(ctx->tmpi < 0) ctx->tmpi += NBOXES;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj += NBOXES;
ctx->instanceptr = xctx->inst_spatial_table[ctx->tmpi][ctx->tmpj];
} else {
my_free(_ALLOC_ID_, &ctx->instflag);
return NULL;
}
}
}
void init_wire_iterator(Iterator_ctx *ctx, double x1, double y1, double x2, double y2)
{
ctx->wireflag = NULL;
dbg(3, "init_wire_iterator(): wires=%d\n", xctx->wires);
if(xctx->wires) {
my_realloc(_ALLOC_ID_, &ctx->wireflag, xctx->wires*sizeof(unsigned short));
memset(ctx->wireflag, 0, xctx->wires*sizeof(unsigned short));
}
/* calculate square 4 1st corner of drawing area */
ctx->x1a = (int)floor(x1 / BOXSIZE) ;
ctx->y1a = (int)floor(y1 / BOXSIZE) ;
/* calculate square 4 2nd corner of drawing area */
ctx->x2a = (int)floor(x2 / BOXSIZE);
ctx->y2a = (int)floor(y2 / BOXSIZE);
ctx->i = ctx->x1a;
ctx->j = ctx->y1a;
ctx->tmpi = ctx->i % NBOXES; if(ctx->tmpi < 0) ctx->tmpi += NBOXES;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj += NBOXES;
ctx->counti = 0;
ctx->wireptr = xctx->wire_spatial_table[ctx->tmpi][ctx->tmpj];
ctx->countj = 0;
}
Wireentry *wire_iterator_next(Iterator_ctx *ctx)
{
Wireentry *ptr;
/* dbg(3, "wire_iterator_next(): wires=%d\n", xctx->wires); */
while(1) {
while(ctx->wireptr) {
ptr = ctx->wireptr;
ctx->wireptr = ctx->wireptr -> next;
if(!ctx->wireflag[ptr->n]) {
ctx->wireflag[ptr->n]=1;
return ptr;
}
}
if(ctx->j < ctx->y2a && ctx->countj++ < NBOXES) {
ctx->j++;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj += NBOXES;
ctx->wireptr = xctx->wire_spatial_table[ctx->tmpi][ctx->tmpj];
} else if(ctx->i < ctx->x2a && ctx->counti++ < NBOXES) {
ctx->i++;
ctx->j = ctx->y1a;
ctx->countj = 0;
ctx->tmpi = ctx->i % NBOXES; if(ctx->tmpi < 0) ctx->tmpi += NBOXES;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj += NBOXES;
ctx->wireptr = xctx->wire_spatial_table[ctx->tmpi][ctx->tmpj];
} else {
my_free(_ALLOC_ID_, &ctx->wireflag);
return NULL;
}
}
}
void init_object_iterator(Iterator_ctx *ctx, double x1, double y1, double x2, double y2)
{
ctx->objectflag = NULL;
dbg(3, "init_object_iterator(): objects=%d\n", xctx->n_hash_objects);
if(xctx->n_hash_objects) {
my_realloc(_ALLOC_ID_, &ctx->objectflag, xctx->n_hash_objects * sizeof(unsigned short));
memset(ctx->objectflag, 0, xctx->n_hash_objects * sizeof(unsigned short));
}
/* calculate square 4 1st corner of drawing area */
ctx->x1a = (int)floor(x1 / BOXSIZE) ;
ctx->y1a = (int)floor(y1 / BOXSIZE) ;
/* calculate square 4 2nd corner of drawing area */
ctx->x2a = (int)floor(x2 / BOXSIZE);
ctx->y2a = (int)floor(y2 / BOXSIZE);
ctx->i = ctx->x1a;
ctx->j = ctx->y1a;
ctx->tmpi = ctx->i % NBOXES; if(ctx->tmpi < 0) ctx->tmpi += NBOXES;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj += NBOXES;
ctx->counti = 0;
ctx->objectptr = xctx->object_spatial_table[ctx->tmpi][ctx->tmpj];
ctx->countj = 0;
}
Objectentry *object_iterator_next(Iterator_ctx *ctx)
{
Objectentry *ptr;
/* dbg(3, "object_iterator_next(): obhjects=%d\n", xctx->n_hash_objects); */
while(1) {
while(ctx->objectptr) {
ptr = ctx->objectptr;
ctx->objectptr = ctx->objectptr->next;
if(!ctx->objectflag[ptr->n]) {
ctx->objectflag[ptr->n] = 1;
return ptr;
}
}
if(ctx->j < ctx->y2a && ctx->countj++ < NBOXES) {
ctx->j++;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj += NBOXES;
ctx->objectptr = xctx->object_spatial_table[ctx->tmpi][ctx->tmpj];
} else if(ctx->i < ctx->x2a && ctx->counti++ < NBOXES) {
ctx->i++;
ctx->j = ctx->y1a;
ctx->countj = 0;
ctx->tmpi = ctx->i % NBOXES; if(ctx->tmpi < 0) ctx->tmpi += NBOXES;
ctx->tmpj = ctx->j % NBOXES; if(ctx->tmpj < 0) ctx->tmpj += NBOXES;
ctx->objectptr = xctx->object_spatial_table[ctx->tmpi][ctx->tmpj];
} else {
my_free(_ALLOC_ID_, &ctx->objectflag);
return NULL;
}
}
}