/* This file is part of GNU Pies. Copyright (C) 2008-2019 Sergey Poznyakoff GNU Pies 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 3, or (at your option) any later version. GNU Pies 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 GNU Pies. If not, see . */ #include "pies.h" #ifndef CHAR_BIT # define CHAR_BIT 8 #endif #define BITS_PER_WORD (sizeof(unsigned)*CHAR_BIT) #define WORDSIZE(n) (((n) + BITS_PER_WORD - 1) / BITS_PER_WORD) #define SETBIT(x, i) ((x)[(i)/BITS_PER_WORD] |= (1<<((i) % BITS_PER_WORD))) #define CLRBIT(x, i) ((x)[(i)/BITS_PER_WORD] &= ~(1<<((i) % BITS_PER_WORD))) #define BITISSET(x, i) (((x)[(i)/BITS_PER_WORD] & (1<<((i) % BITS_PER_WORD))) != 0) void TC (unsigned *R, int n) { register int rowsize; register unsigned mask; register unsigned *rowj; register unsigned *rp; register unsigned *rend; register unsigned *ccol; unsigned *relend; unsigned *cword; unsigned *rowi; rowsize = WORDSIZE (n) * sizeof (unsigned); relend = (unsigned *) ((char *) R + (n * rowsize)); cword = R; mask = 1; rowi = R; while (rowi < relend) { ccol = cword; rowj = R; while (rowj < relend) { if (*ccol & mask) { rp = rowi; rend = (unsigned *) ((char *) rowj + rowsize); while (rowj < rend) *rowj++ |= *rp++; } else { rowj = (unsigned *) ((char *) rowj + rowsize); } ccol = (unsigned *) ((char *) ccol + rowsize); } mask <<= 1; if (mask == 0) { mask = 1; cword++; } rowi = (unsigned *) ((char *) rowi + rowsize); } } struct pies_depmap { size_t nrows; /* Number of rows (== number of mapped elements) */ size_t rowlen; /* Length of a row in words */ unsigned r[1]; /* Data rows */ }; pies_depmap_t depmap_alloc (size_t count) { size_t size = (count + BITS_PER_WORD - 1) / BITS_PER_WORD; pies_depmap_t dmap = grecs_zalloc (sizeof (*dmap) - 1 + count * size * sizeof (unsigned)); dmap->nrows = count; dmap->rowlen = size; return dmap; } /* Return size of a depmap row in bytes */ static inline size_t depmap_row_size (pies_depmap_t dpm) { return dpm->rowlen * sizeof (unsigned); } pies_depmap_t depmap_copy (pies_depmap_t dpm) { pies_depmap_t copy = depmap_alloc (dpm->nrows); memcpy (copy->r, dpm->r, dpm->nrows * depmap_row_size (dpm)); return copy; } static unsigned * depmap_rowptr (pies_depmap_t dmap, size_t row) { return dmap->r + dmap->rowlen * row; } void depmap_set (pies_depmap_t dmap, size_t row, size_t col) { unsigned *rptr = depmap_rowptr (dmap, row); SETBIT (rptr, col); } void depmap_clear (pies_depmap_t dmap, size_t row, size_t col) { unsigned *rptr = depmap_rowptr (dmap, row); CLRBIT (rptr, col); } int depmap_isset (pies_depmap_t dmap, size_t row, size_t col) { unsigned *rptr = depmap_rowptr (dmap, row); return BITISSET (rptr, col); } void depmap_tc (pies_depmap_t dmap) { TC (dmap->r, dmap->nrows); } struct pies_depmap_pos { enum pies_depmap_direction dir; size_t coord[2]; }; size_t depmap_next (pies_depmap_t dmap, pies_depmap_pos_t pos) { for (pos->coord[pos->dir]++; pos->coord[pos->dir] < dmap->nrows; pos->coord[pos->dir]++) if (depmap_isset (dmap, pos->coord[0], pos->coord[1])) break; return pos->coord[pos->dir] == dmap->nrows ? (size_t) -1 : pos->coord[pos->dir]; } size_t depmap_first (pies_depmap_t dmap, enum pies_depmap_direction dir, size_t coord, pies_depmap_pos_t *ppos) { pies_depmap_pos_t pos = grecs_malloc (sizeof *pos); *ppos = pos; pos->dir = dir; pos->coord[!pos->dir] = coord; pos->coord[pos->dir] = -1; return depmap_next (dmap, pos); } void depmap_end (pies_depmap_pos_t pos) { grecs_free (pos); } /* Remove nth row and column from the map */ void depmap_remove (pies_depmap_t dmap, size_t n) { if (n < dmap->nrows - 1) { size_t i, j; /* Remove nth row */ memmove (depmap_rowptr (dmap, n), depmap_rowptr (dmap, n + 1), (dmap->nrows - n - 1) * depmap_row_size (dmap)); /* Renumber all columns j >= n: j = j - 1 */ for (i = 0; i < dmap->nrows; i++) for (j = n; j < dmap->nrows - 1; j++) (depmap_isset (dmap, i, j + 1) ? depmap_set : depmap_clear) (dmap, i, j); } dmap->nrows--; }