/* 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; } } }