mirror of https://github.com/golang/go.git
211 lines
3.7 KiB
C
211 lines
3.7 KiB
C
// Copyright 2013 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
#include <u.h>
|
|
#include <libc.h>
|
|
#include "go.h"
|
|
|
|
enum {
|
|
WORDSIZE = sizeof(uint32),
|
|
WORDBITS = 32,
|
|
WORDMASK = WORDBITS - 1,
|
|
WORDSHIFT = 5,
|
|
};
|
|
|
|
static uintptr
|
|
bvsize(uintptr n)
|
|
{
|
|
return ((n + WORDBITS - 1) / WORDBITS) * WORDSIZE;
|
|
}
|
|
|
|
int32
|
|
bvbits(Bvec *bv)
|
|
{
|
|
return bv->n;
|
|
}
|
|
|
|
int32
|
|
bvwords(Bvec *bv)
|
|
{
|
|
return (bv->n + WORDBITS - 1) / WORDBITS;
|
|
}
|
|
|
|
Bvec*
|
|
bvalloc(int32 n)
|
|
{
|
|
Bvec *bv;
|
|
uintptr nbytes;
|
|
|
|
if(n < 0)
|
|
fatal("bvalloc: initial size is negative\n");
|
|
nbytes = sizeof(Bvec) + bvsize(n);
|
|
bv = malloc(nbytes);
|
|
if(bv == nil)
|
|
fatal("bvalloc: malloc failed\n");
|
|
memset(bv, 0, nbytes);
|
|
bv->n = n;
|
|
return bv;
|
|
}
|
|
|
|
/* difference */
|
|
void
|
|
bvandnot(Bvec *dst, Bvec *src1, Bvec *src2)
|
|
{
|
|
int32 i, w;
|
|
|
|
if(dst->n != src1->n || dst->n != src2->n)
|
|
fatal("bvand: lengths %d, %d, and %d are not equal", dst->n, src1->n, src2->n);
|
|
for(i = 0, w = 0; i < dst->n; i += WORDBITS, w++)
|
|
dst->b[w] = src1->b[w] & ~src2->b[w];
|
|
}
|
|
|
|
int
|
|
bvcmp(Bvec *bv1, Bvec *bv2)
|
|
{
|
|
uintptr nbytes;
|
|
|
|
if(bv1->n != bv2->n)
|
|
fatal("bvequal: lengths %d and %d are not equal", bv1->n, bv2->n);
|
|
nbytes = bvsize(bv1->n);
|
|
return memcmp(bv1->b, bv2->b, nbytes);
|
|
}
|
|
|
|
void
|
|
bvcopy(Bvec *dst, Bvec *src)
|
|
{
|
|
memmove(dst->b, src->b, bvsize(dst->n));
|
|
}
|
|
|
|
Bvec*
|
|
bvconcat(Bvec *src1, Bvec *src2)
|
|
{
|
|
Bvec *dst;
|
|
int32 i;
|
|
|
|
dst = bvalloc(src1->n + src2->n);
|
|
for(i = 0; i < src1->n; i++)
|
|
if(bvget(src1, i))
|
|
bvset(dst, i);
|
|
for(i = 0; i < src2->n; i++)
|
|
if(bvget(src2, i))
|
|
bvset(dst, i + src1->n);
|
|
return dst;
|
|
}
|
|
|
|
int
|
|
bvget(Bvec *bv, int32 i)
|
|
{
|
|
if(i < 0 || i >= bv->n)
|
|
fatal("bvget: index %d is out of bounds with length %d\n", i, bv->n);
|
|
return (bv->b[i>>WORDSHIFT] >> (i&WORDMASK)) & 1;
|
|
}
|
|
|
|
// bvnext returns the smallest index >= i for which bvget(bv, i) == 1.
|
|
// If there is no such index, bvnext returns -1.
|
|
int
|
|
bvnext(Bvec *bv, int32 i)
|
|
{
|
|
uint32 w;
|
|
|
|
// Jump i ahead to next word with bits.
|
|
if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) {
|
|
i &= ~WORDMASK;
|
|
i += WORDBITS;
|
|
while(i < bv->n && bv->b[i>>WORDSHIFT] == 0)
|
|
i += WORDBITS;
|
|
}
|
|
if(i >= bv->n)
|
|
return -1;
|
|
|
|
// Find 1 bit.
|
|
w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK);
|
|
while((w&1) == 0) {
|
|
w>>=1;
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int
|
|
bvisempty(Bvec *bv)
|
|
{
|
|
int32 i;
|
|
|
|
for(i = 0; i < bv->n; i += WORDBITS)
|
|
if(bv->b[i>>WORDSHIFT] != 0)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
bvnot(Bvec *bv)
|
|
{
|
|
int32 i, w;
|
|
|
|
for(i = 0, w = 0; i < bv->n; i += WORDBITS, w++)
|
|
bv->b[w] = ~bv->b[w];
|
|
}
|
|
|
|
/* union */
|
|
void
|
|
bvor(Bvec *dst, Bvec *src1, Bvec *src2)
|
|
{
|
|
int32 i, w;
|
|
|
|
if(dst->n != src1->n || dst->n != src2->n)
|
|
fatal("bvor: lengths %d, %d, and %d are not equal", dst->n, src1->n, src2->n);
|
|
for(i = 0, w = 0; i < dst->n; i += WORDBITS, w++)
|
|
dst->b[w] = src1->b[w] | src2->b[w];
|
|
}
|
|
|
|
/* intersection */
|
|
void
|
|
bvand(Bvec *dst, Bvec *src1, Bvec *src2)
|
|
{
|
|
int32 i, w;
|
|
|
|
if(dst->n != src1->n || dst->n != src2->n)
|
|
fatal("bvor: lengths %d, %d, and %d are not equal", dst->n, src1->n, src2->n);
|
|
for(i = 0, w = 0; i < dst->n; i += WORDBITS, w++)
|
|
dst->b[w] = src1->b[w] & src2->b[w];
|
|
}
|
|
|
|
void
|
|
bvprint(Bvec *bv)
|
|
{
|
|
int32 i;
|
|
|
|
print("#*");
|
|
for(i = 0; i < bv->n; i++)
|
|
print("%d", bvget(bv, i));
|
|
}
|
|
|
|
void
|
|
bvreset(Bvec *bv, int32 i)
|
|
{
|
|
uint32 mask;
|
|
|
|
if(i < 0 || i >= bv->n)
|
|
fatal("bvreset: index %d is out of bounds with length %d\n", i, bv->n);
|
|
mask = ~(1 << (i % WORDBITS));
|
|
bv->b[i / WORDBITS] &= mask;
|
|
}
|
|
|
|
void
|
|
bvresetall(Bvec *bv)
|
|
{
|
|
memset(bv->b, 0x00, bvsize(bv->n));
|
|
}
|
|
|
|
void
|
|
bvset(Bvec *bv, int32 i)
|
|
{
|
|
uint32 mask;
|
|
|
|
if(i < 0 || i >= bv->n)
|
|
fatal("bvset: index %d is out of bounds with length %d\n", i, bv->n);
|
|
mask = 1U << (i % WORDBITS);
|
|
bv->b[i / WORDBITS] |= mask;
|
|
}
|