mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-15 20:33:14 +01:00
656 lines
13 KiB
C
656 lines
13 KiB
C
/*_ vec.c Mon Oct 31 1994 */
|
|
/* Copyright (C) 1986-2000 by Digital Mars */
|
|
/* Written by Walter Bright */
|
|
/* Bit vector package */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#ifndef assert
|
|
#include <assert.h>
|
|
#endif
|
|
#include "vec.h"
|
|
#include "mem.h"
|
|
|
|
static int vec_count; /* # of vectors allocated */
|
|
static int vec_initcount = 0; /* # of times package is initialized */
|
|
|
|
#define VECMAX 20
|
|
static vec_t vecfreelist[VECMAX];
|
|
|
|
#if 1
|
|
#define MASK(b) (1 << ((b) & VECMASK))
|
|
#else
|
|
#define MASK(b) bmask[(b) & VECMASK]
|
|
static unsigned bmask[VECMASK + 1] =
|
|
{
|
|
1,2,4,8,0x10,0x20,0x40,0x80,
|
|
0x100,0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000,
|
|
#if __INTSIZE == 4
|
|
0x10000,0x20000,0x40000,0x80000,0x100000,0x200000,0x400000,0x800000,
|
|
0x1000000,0x2000000,0x4000000,0x8000000,
|
|
0x10000000,0x20000000,0x40000000,0x80000000
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
/**************************
|
|
* Initialize package.
|
|
*/
|
|
|
|
void vec_init()
|
|
{
|
|
assert(sizeof(vec_base_t)==2&&VECSHIFT==4||sizeof(vec_base_t)==4&&VECSHIFT== 5);
|
|
if (vec_initcount++ == 0)
|
|
vec_count = 0;
|
|
}
|
|
|
|
/**************************
|
|
* Terminate package.
|
|
*/
|
|
|
|
void vec_term()
|
|
{
|
|
if (--vec_initcount == 0)
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
if (vec_count != 0)
|
|
{
|
|
printf("vec_count = %d\n",vec_count);
|
|
assert(0);
|
|
}
|
|
#else
|
|
assert(vec_count == 0);
|
|
#endif
|
|
#if TERMCODE
|
|
int i;
|
|
for (i = 0; i < VECMAX; i++)
|
|
{ void **v;
|
|
void **vn;
|
|
|
|
for (v = (void **)vecfreelist[i]; v; v = vn)
|
|
{
|
|
vn = (void **)(*v);
|
|
mem_free(v);
|
|
}
|
|
vecfreelist[i] = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/********************************
|
|
* Allocate a vector given # of bits in it.
|
|
* Clear the vector.
|
|
*/
|
|
|
|
vec_t vec_calloc(unsigned numbits)
|
|
{ vec_t v;
|
|
int dim;
|
|
|
|
if (numbits == 0)
|
|
return (vec_t) NULL;
|
|
dim = (numbits + (VECBITS - 1)) >> VECSHIFT;
|
|
if (dim < VECMAX && (v = vecfreelist[dim]) != NULL)
|
|
{
|
|
vecfreelist[dim] = *(vec_t *)v;
|
|
v += 2;
|
|
switch (dim)
|
|
{
|
|
case 5: v[4] = 0;
|
|
case 4: v[3] = 0;
|
|
case 3: v[2] = 0;
|
|
case 2: v[1] = 0;
|
|
case 1: v[0] = 0;
|
|
break;
|
|
default: memset(v,0,dim * sizeof(vec_base_t));
|
|
break;
|
|
}
|
|
goto L1;
|
|
}
|
|
else
|
|
{
|
|
v = (vec_t) mem_calloc((dim + 2) * sizeof(vec_base_t));
|
|
}
|
|
if (v)
|
|
{
|
|
v += 2;
|
|
L1:
|
|
vec_dim(v) = dim;
|
|
vec_numbits(v) = numbits;
|
|
/*printf("vec_calloc(%d): v = %p vec_numbits = %d vec_dim = %d\n",
|
|
numbits,v,vec_numbits(v),vec_dim(v));*/
|
|
vec_count++;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
/********************************
|
|
* Allocate copy of existing vector.
|
|
*/
|
|
|
|
vec_t vec_clone(vec_t v)
|
|
{ vec_t vc;
|
|
int dim;
|
|
unsigned nbytes;
|
|
|
|
if (v)
|
|
{ dim = vec_dim(v);
|
|
nbytes = (dim + 2) * sizeof(vec_base_t);
|
|
if (dim < VECMAX && (vc = vecfreelist[dim]) != NULL)
|
|
{
|
|
vecfreelist[dim] = *(vec_t *)vc;
|
|
goto L1;
|
|
}
|
|
else
|
|
{
|
|
vc = (vec_t) mem_calloc(nbytes);
|
|
}
|
|
if (vc)
|
|
{
|
|
L1:
|
|
memcpy(vc,v - 2,nbytes);
|
|
vec_count++;
|
|
v = vc + 2;
|
|
}
|
|
else
|
|
v = NULL;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
/**************************
|
|
* Free a vector.
|
|
*/
|
|
|
|
void vec_free(vec_t v)
|
|
{
|
|
/*printf("vec_free(%p)\n",v);*/
|
|
if (v)
|
|
{ int dim = vec_dim(v);
|
|
|
|
v -= 2;
|
|
if (dim < VECMAX)
|
|
{
|
|
*(vec_t *)v = vecfreelist[dim];
|
|
vecfreelist[dim] = v;
|
|
}
|
|
else
|
|
mem_free(v);
|
|
vec_count--;
|
|
}
|
|
}
|
|
|
|
/**************************
|
|
* Realloc a vector to have numbits bits in it.
|
|
* Extra bits are set to 0.
|
|
*/
|
|
|
|
vec_t vec_realloc(vec_t v,unsigned numbits)
|
|
{ vec_t newv;
|
|
unsigned vbits;
|
|
|
|
/*printf("vec_realloc(%p,%d)\n",v,numbits);*/
|
|
if (!v)
|
|
return vec_calloc(numbits);
|
|
if (!numbits)
|
|
{ vec_free(v);
|
|
return NULL;
|
|
}
|
|
vbits = vec_numbits(v);
|
|
if (numbits == vbits)
|
|
return v;
|
|
newv = vec_calloc(numbits);
|
|
if (newv)
|
|
{ unsigned nbytes;
|
|
|
|
nbytes = (vec_dim(v) < vec_dim(newv)) ? vec_dim(v) : vec_dim(newv);
|
|
memcpy(newv,v,nbytes * sizeof(vec_base_t));
|
|
vec_clearextrabits(newv);
|
|
}
|
|
vec_free(v);
|
|
return newv;
|
|
}
|
|
|
|
/**************************
|
|
* Set bit b in vector v.
|
|
*/
|
|
|
|
#ifndef vec_setbit
|
|
|
|
#if _M_I86 && __INTSIZE == 4 && __SC__
|
|
__declspec(naked) void __pascal vec_setbit(unsigned b,vec_t v)
|
|
{
|
|
_asm
|
|
{
|
|
mov EAX,b-4[ESP]
|
|
mov ECX,v-4[ESP]
|
|
bts [ECX],EAX
|
|
ret 8
|
|
}
|
|
}
|
|
#else
|
|
void vec_setbit(unsigned b,vec_t v)
|
|
{
|
|
#ifdef DEBUG
|
|
if (!(v && b < vec_numbits(v)))
|
|
printf("vec_setbit(v = %p,b = %d): numbits = %d dim = %d\n",
|
|
v,b,v ? vec_numbits(v) : 0, v ? vec_dim(v) : 0);
|
|
#endif
|
|
assert(v && b < vec_numbits(v));
|
|
*(v + (b >> VECSHIFT)) |= MASK(b);
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/**************************
|
|
* Clear bit b in vector v.
|
|
*/
|
|
|
|
#ifndef vec_clearbit
|
|
|
|
#if _M_I86 && __INTSIZE == 4 && __SC__
|
|
__declspec(naked) void __pascal vec_clearbit(unsigned b,vec_t v)
|
|
{
|
|
_asm
|
|
{
|
|
mov EAX,b-4[ESP]
|
|
mov ECX,v-4[ESP]
|
|
btr [ECX],EAX
|
|
ret 8
|
|
}
|
|
}
|
|
#else
|
|
void vec_clearbit(unsigned b,vec_t v)
|
|
{
|
|
assert(v && b < vec_numbits(v));
|
|
*(v + (b >> VECSHIFT)) &= ~MASK(b);
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/**************************
|
|
* Test bit b in vector v.
|
|
*/
|
|
|
|
#ifndef vec_testbit
|
|
|
|
#if _M_I86 && __INTSIZE == 4 && __SC__
|
|
__declspec(naked) int __pascal vec_testbit(unsigned b,vec_t v)
|
|
{
|
|
_asm
|
|
{
|
|
mov EAX,v-4[ESP]
|
|
mov ECX,b-4[ESP]
|
|
test EAX,EAX
|
|
jz L1
|
|
bt [EAX],ECX
|
|
sbb EAX,EAX
|
|
L1: ret 8
|
|
}
|
|
}
|
|
#else
|
|
int vec_testbit(unsigned b,vec_t v)
|
|
{
|
|
if (!v)
|
|
return 0;
|
|
#ifdef DEBUG
|
|
if (b >= vec_numbits(v))
|
|
{ printf("vec_testbit(v = %p,b = %d): numbits = %d dim = %d\n",
|
|
v,b,vec_numbits(v),vec_dim(v));
|
|
b = (unsigned)-1;
|
|
}
|
|
#endif
|
|
assert(b < vec_numbits(v));
|
|
#if __I86__ >= 3 && __SC__
|
|
_asm
|
|
{
|
|
#if __INTSIZE == 4
|
|
mov EAX,b
|
|
mov ECX,v
|
|
bt [ECX],EAX
|
|
sbb EAX,EAX
|
|
#elif __COMPACT__ || __LARGE__ || __VCM__
|
|
mov AX,b
|
|
les BX,v
|
|
bt ES:[BX],AX
|
|
sbb AX,AX
|
|
#else
|
|
mov AX,b
|
|
mov CX,v
|
|
bt [CX],AX
|
|
sbb AX,AX
|
|
#endif
|
|
}
|
|
#ifdef DEBUG
|
|
{ int x = _AX;
|
|
assert((x != 0) == ((*(v + (b >> VECSHIFT)) & MASK(b)) != 0));
|
|
}
|
|
#endif
|
|
#else
|
|
return *(v + (b >> VECSHIFT)) & MASK(b);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/********************************
|
|
* Find first set bit starting from b in vector v.
|
|
* If no bit is found, return vec_numbits(v).
|
|
*/
|
|
|
|
unsigned vec_index(unsigned b,vec_t vec)
|
|
{ register unsigned starv;
|
|
register vec_t v,vtop;
|
|
unsigned bit;
|
|
|
|
if (!vec)
|
|
return 0;
|
|
v = vec;
|
|
if (b < vec_numbits(v))
|
|
{ vtop = &vec[vec_dim(v)];
|
|
bit = b & VECMASK;
|
|
if (bit != b) /* if not starting in first word */
|
|
v += b >> VECSHIFT;
|
|
starv = *v >> bit;
|
|
while (1)
|
|
{
|
|
while (starv)
|
|
{ if (starv & 1)
|
|
return b;
|
|
b++;
|
|
starv >>= 1;
|
|
}
|
|
b = (b + VECBITS) & ~VECMASK; /* round up to next word */
|
|
if (++v >= vtop)
|
|
break;
|
|
starv = *v;
|
|
}
|
|
}
|
|
return vec_numbits(vec);
|
|
}
|
|
|
|
/********************************
|
|
* Compute v1 &= v2.
|
|
*/
|
|
|
|
void vec_andass(vec_t v1,vec_t v2)
|
|
{ vec_t vtop;
|
|
|
|
if (v1)
|
|
{
|
|
assert(v2);
|
|
assert(vec_numbits(v1)==vec_numbits(v2));
|
|
vtop = &v1[vec_dim(v1)];
|
|
for (; v1 < vtop; v1++,v2++)
|
|
*v1 &= *v2;
|
|
}
|
|
else
|
|
assert(!v2);
|
|
}
|
|
|
|
/********************************
|
|
* Compute v1 = v2 & v3.
|
|
*/
|
|
|
|
void vec_and(vec_t v1,vec_t v2,vec_t v3)
|
|
{ vec_t vtop;
|
|
|
|
if (v1)
|
|
{
|
|
assert(v2 && v3);
|
|
assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
|
|
vtop = &v1[vec_dim(v1)];
|
|
for (; v1 < vtop; v1++,v2++,v3++)
|
|
*v1 = *v2 & *v3;
|
|
}
|
|
else
|
|
assert(!v2 && !v3);
|
|
}
|
|
|
|
/********************************
|
|
* Compute v1 ^= v2.
|
|
*/
|
|
|
|
void vec_xorass(vec_t v1,vec_t v2)
|
|
{ vec_t vtop;
|
|
|
|
if (v1)
|
|
{
|
|
assert(v2);
|
|
assert(vec_numbits(v1)==vec_numbits(v2));
|
|
vtop = &v1[vec_dim(v1)];
|
|
for (; v1 < vtop; v1++,v2++)
|
|
*v1 ^= *v2;
|
|
}
|
|
else
|
|
assert(!v2);
|
|
}
|
|
|
|
/********************************
|
|
* Compute v1 = v2 ^ v3.
|
|
*/
|
|
|
|
void vec_xor(vec_t v1,vec_t v2,vec_t v3)
|
|
{ vec_t vtop;
|
|
|
|
if (v1)
|
|
{
|
|
assert(v2 && v3);
|
|
assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
|
|
vtop = &v1[vec_dim(v1)];
|
|
for (; v1 < vtop; v1++,v2++,v3++)
|
|
*v1 = *v2 ^ *v3;
|
|
}
|
|
else
|
|
assert(!v2 && !v3);
|
|
}
|
|
|
|
/********************************
|
|
* Compute v1 |= v2.
|
|
*/
|
|
|
|
void vec_orass(vec_t v1,vec_t v2)
|
|
{ vec_t vtop;
|
|
|
|
if (v1)
|
|
{
|
|
#ifdef DEBUG
|
|
assert(v2);
|
|
assert(vec_numbits(v1)==vec_numbits(v2));
|
|
#endif
|
|
vtop = &v1[vec_dim(v1)];
|
|
#if __INTSIZE == 2 && __I86__ && (__COMPACT__ || __LARGE__ || __VCM__)
|
|
_asm
|
|
{
|
|
push DS
|
|
lds SI,v2
|
|
les DI,v1
|
|
mov CX,word ptr vtop
|
|
cmp CX,DI
|
|
jz L1
|
|
L2: mov AX,[SI]
|
|
add SI,2
|
|
or ES:[DI],AX
|
|
add DI,2
|
|
cmp DI,CX
|
|
jb L2
|
|
L1: pop DS
|
|
#if __SC__ <= 0x610
|
|
jmp Lret
|
|
#endif
|
|
}
|
|
#else
|
|
for (; v1 < vtop; v1++,v2++)
|
|
*v1 |= *v2;
|
|
#endif
|
|
}
|
|
else
|
|
assert(!v2);
|
|
}
|
|
|
|
/********************************
|
|
* Compute v1 = v2 | v3.
|
|
*/
|
|
|
|
void vec_or(vec_t v1,vec_t v2,vec_t v3)
|
|
{ vec_t vtop;
|
|
|
|
if (v1)
|
|
{
|
|
assert(v2 && v3);
|
|
assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
|
|
vtop = &v1[vec_dim(v1)];
|
|
for (; v1 < vtop; v1++,v2++,v3++)
|
|
*v1 = *v2 | *v3;
|
|
}
|
|
else
|
|
assert(!v2 && !v3);
|
|
}
|
|
|
|
/********************************
|
|
* Compute v1 -= v2.
|
|
*/
|
|
|
|
void vec_subass(vec_t v1,vec_t v2)
|
|
{ vec_t vtop;
|
|
|
|
if (v1)
|
|
{
|
|
assert(v2);
|
|
assert(vec_numbits(v1)==vec_numbits(v2));
|
|
vtop = &v1[vec_dim(v1)];
|
|
for (; v1 < vtop; v1++,v2++)
|
|
*v1 &= ~*v2;
|
|
}
|
|
else
|
|
assert(!v2);
|
|
}
|
|
|
|
/********************************
|
|
* Compute v1 = v2 - v3.
|
|
*/
|
|
|
|
void vec_sub(vec_t v1,vec_t v2,vec_t v3)
|
|
{ vec_t vtop;
|
|
|
|
if (v1)
|
|
{
|
|
assert(v2 && v3);
|
|
assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
|
|
vtop = &v1[vec_dim(v1)];
|
|
for (; v1 < vtop; v1++,v2++,v3++)
|
|
*v1 = *v2 & ~*v3;
|
|
}
|
|
else
|
|
assert(!v2 && !v3);
|
|
}
|
|
|
|
/****************
|
|
* Clear vector.
|
|
*/
|
|
|
|
void vec_clear(vec_t v)
|
|
{
|
|
if (v)
|
|
memset(v,0,sizeof(v[0]) * vec_dim(v));
|
|
}
|
|
|
|
/****************
|
|
* Set vector.
|
|
*/
|
|
|
|
void vec_set(vec_t v)
|
|
{
|
|
if (v)
|
|
{ memset(v,~0,sizeof(v[0]) * vec_dim(v));
|
|
vec_clearextrabits(v);
|
|
}
|
|
}
|
|
|
|
/***************
|
|
* Copy vector.
|
|
*/
|
|
|
|
void vec_copy(vec_t to,vec_t from)
|
|
{
|
|
if (to != from)
|
|
{
|
|
#ifdef DEBUG
|
|
if (!(to && from && vec_numbits(to) == vec_numbits(from)))
|
|
printf("to = x%lx, from = x%lx, numbits(to) = %d, numbits(from) = %d\n",
|
|
(long)to,(long)from,to ? vec_numbits(to) : 0, from ? vec_numbits(from): 0);
|
|
#endif
|
|
assert(to && from && vec_numbits(to) == vec_numbits(from));
|
|
memcpy(to,from,sizeof(to[0]) * vec_dim(to));
|
|
}
|
|
}
|
|
|
|
/****************
|
|
* Return 1 if vectors are equal.
|
|
*/
|
|
|
|
int vec_equal(vec_t v1,vec_t v2)
|
|
{
|
|
if (v1 == v2)
|
|
return 1;
|
|
assert(v1 && v2 && vec_numbits(v1) == vec_numbits(v2));
|
|
return !memcmp(v1,v2,sizeof(v1[0]) * vec_dim(v1));
|
|
}
|
|
|
|
/********************************
|
|
* Return 1 if (v1 & v2) == 0
|
|
*/
|
|
|
|
int vec_disjoint(vec_t v1,vec_t v2)
|
|
{ vec_t vtop;
|
|
|
|
assert(v1 && v2);
|
|
assert(vec_numbits(v1)==vec_numbits(v2));
|
|
vtop = &v1[vec_dim(v1)];
|
|
for (; v1 < vtop; v1++,v2++)
|
|
if (*v1 & *v2)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/*********************
|
|
* Clear any extra bits in vector.
|
|
*/
|
|
|
|
void vec_clearextrabits(vec_t v)
|
|
{ unsigned n;
|
|
|
|
assert(v);
|
|
n = vec_numbits(v);
|
|
if (n & VECMASK)
|
|
v[vec_dim(v) - 1] &= MASK(n) - 1;
|
|
}
|
|
|
|
/******************
|
|
* Write out vector.
|
|
*/
|
|
|
|
void vec_println(vec_t v)
|
|
{
|
|
#ifdef DEBUG
|
|
vec_print(v);
|
|
fputc('\n',stdout);
|
|
#endif
|
|
}
|
|
|
|
void vec_print(vec_t v)
|
|
{
|
|
#ifdef DEBUG
|
|
printf(" Vec %p, numbits %d dim %d",v,vec_numbits(v),vec_dim(v));
|
|
if (v)
|
|
{ fputc('\t',stdout);
|
|
for (unsigned i = 0; i < vec_numbits(v); i++)
|
|
fputc((vec_testbit(i,v)) ? '1' : '0',stdout);
|
|
}
|
|
#endif
|
|
}
|