You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
3.8 KiB
189 lines
3.8 KiB
18 years ago
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "templates.h"
|
||
|
|
||
|
typedef unsigned long ul;
|
||
|
|
||
|
#define SIZE (sizeof(ul) * 8)
|
||
|
#define ROUND_DOWN(x) ((x) & ~(SIZE-1))
|
||
|
#define ROUND_UP(x) ROUND_DOWN((x) + (SIZE-1))
|
||
|
#define NEXT_UP(x) ROUND_DOWN((x) + SIZE)
|
||
|
#define NEXT_DOWN(x) ROUND_DOWN((x) - 1)
|
||
|
|
||
|
#define SETBIT(s,p) \
|
||
|
assert( (bits[(s)/SIZE] & (p)) == (setp ? 0 : (p)) ); \
|
||
|
if (setp) bits[(s)/SIZE] |= (p); \
|
||
|
else bits[(s)/SIZE] &= ~(p)
|
||
|
|
||
|
#define GETBIT(s) (bits[ROUND_DOWN(s)/SIZE] & (1ul << (NEXT_UP(s) - s - 1)))
|
||
|
|
||
|
size_t count_free_bits_back(ul *bits, size_t s) {
|
||
|
size_t cnt = 0;
|
||
|
ul w = ROUND_DOWN(s) / SIZE;
|
||
|
size_t add = s % SIZE;
|
||
|
ul off = (~0ul) << (SIZE - add);
|
||
|
ul H, d;
|
||
|
|
||
|
while ((bits[w] & off) == 0) {
|
||
|
cnt += add;
|
||
|
add = SIZE;
|
||
|
off = ~0ul;
|
||
|
if (w == 0)
|
||
|
return cnt;
|
||
|
w--;
|
||
|
}
|
||
|
|
||
|
H = add;
|
||
|
add = 0;
|
||
|
while ((d = (H - add) / 2) > 0) {
|
||
|
ul offM = (off >> d) & off;
|
||
|
if (bits[w] & offM) {
|
||
|
off = offM;
|
||
|
H = H - d;
|
||
|
} else {
|
||
|
add = H - d;
|
||
|
}
|
||
|
}
|
||
|
cnt += add;
|
||
|
return cnt;
|
||
|
}
|
||
|
|
||
|
size_t count_free_bits_after(ul *bits, size_t s, size_t end) {
|
||
|
size_t cnt = 0;
|
||
|
ul w = ROUND_DOWN(s) / SIZE;
|
||
|
size_t add = SIZE - s % SIZE;
|
||
|
ul off = (~0ul) >> (SIZE - add);
|
||
|
ul H, d;
|
||
|
|
||
|
end /= SIZE;
|
||
|
|
||
|
while ((bits[w] & off) == 0) {
|
||
|
cnt += add;
|
||
|
add = SIZE;
|
||
|
off = ~0ul;
|
||
|
w++;
|
||
|
if (w == end)
|
||
|
return cnt;
|
||
|
}
|
||
|
|
||
|
H = add;
|
||
|
add = 0;
|
||
|
while ((d = (H - add) / 2) > 0) {
|
||
|
ul offM = off << d;
|
||
|
if (bits[w] & offM) {
|
||
|
off = offM;
|
||
|
H = H - d;
|
||
|
} else {
|
||
|
add = H - d;
|
||
|
}
|
||
|
}
|
||
|
cnt += add;
|
||
|
return cnt;
|
||
|
}
|
||
|
|
||
|
void find_long_freebits(ul *bits, size_t s, ul *start, size_t *size) {
|
||
|
ul clen = 0;
|
||
|
ul bstart = 0, blen = 0;
|
||
|
ul i, k;
|
||
|
|
||
|
for (i = 0; i < s; i++) {
|
||
|
if (bits[i] == 0) {
|
||
|
clen++;
|
||
|
} else {
|
||
|
if (clen > blen) {
|
||
|
bstart = i - clen;
|
||
|
blen = clen;
|
||
|
}
|
||
|
clen = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (blen == 0) return;
|
||
|
|
||
|
bstart *= SIZE; blen *= SIZE;
|
||
|
k = count_free_bits_back(bits, bstart);
|
||
|
bstart -= k; blen += k;
|
||
|
|
||
|
blen += count_free_bits_after(bits, bstart + blen, s*SIZE);
|
||
|
|
||
|
*start = bstart; *size = blen;
|
||
|
}
|
||
|
|
||
|
void mark_bits(ul *bits, ul s, size_t size, int setp) {
|
||
|
ul e = s+size;
|
||
|
|
||
|
ul rds = ROUND_DOWN(s);
|
||
|
ul nus = rds + SIZE;
|
||
|
ul rue = ROUND_UP(e);
|
||
|
|
||
|
ul patl = (~0UL) >> (s % SIZE);
|
||
|
ul patr = (~0UL) << (rue - e);
|
||
|
|
||
|
assert(size > 0);
|
||
|
|
||
|
/* bits[s1..e1] get touched, but bits[s1], bits[e1] only partially
|
||
|
*
|
||
|
* if s1 == e1, then bits[s1] get touched from [s%SIZE, e%SIZE)
|
||
|
* else
|
||
|
* bits[s1] gets touched from [s%SIZE, SIZE)
|
||
|
* bits[s2..e1) get reset completely
|
||
|
* bits[e1] gets touched from [0, e%SIZE)
|
||
|
*/
|
||
|
|
||
|
if (nus >= e) {
|
||
|
/* ROUND_DOWN(s) <= s < e <= NEXT_UP(s) */
|
||
|
SETBIT(rds, patl & patr);
|
||
|
} else {
|
||
|
/* ROUND_DOWN(s) <= s < NEXT_UP(s) <= NEXT_DOWN(e) < e */
|
||
|
ul rde = ROUND_DOWN(e);
|
||
|
|
||
|
SETBIT(rds, patl);
|
||
|
SETBIT(rde, patr);
|
||
|
while (nus < rde) {
|
||
|
SETBIT(nus, ~0UL);
|
||
|
nus += SIZE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void print_bits(ul *bits, ul s) {
|
||
|
ul i;
|
||
|
putchar(' ');
|
||
|
for (i = 0; i < s * SIZE; i++) {
|
||
|
putchar( GETBIT(i) ? '1' : '0' );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef TESTBIN
|
||
|
|
||
|
#define X 2
|
||
|
int main(void) {
|
||
|
ul memory[X];
|
||
|
ul l, r;
|
||
|
ul k = 5;
|
||
|
|
||
|
memset(memory, 0, sizeof(memory));
|
||
|
for (l = 0; l < X*SIZE; l += k) {
|
||
|
for (r = 1; l+(r*r) < X*SIZE; r++) {
|
||
|
|
||
|
printf("%lu %lu (%lu %lu", l, r*r,
|
||
|
(unsigned long) count_free_bits_back(memory, X*SIZE), (unsigned long) X*SIZE);
|
||
|
mark_bits(memory, l, r*r, 1);
|
||
|
printf("; %lu %lu %lu; %lu %lu %lu;): ",
|
||
|
(unsigned long) count_free_bits_back(memory, X*SIZE) + l + r*r,
|
||
|
(unsigned long) count_free_bits_after(memory, l + r*r, X*SIZE) + l + r*r,
|
||
|
(unsigned long) X*SIZE,
|
||
|
(unsigned long) count_free_bits_back(memory, l),
|
||
|
(unsigned long) count_free_bits_after(memory, 0, X*SIZE),
|
||
|
l);
|
||
|
print_bits(memory, X);
|
||
|
printf("\n");
|
||
|
|
||
|
mark_bits(memory, l, r*r, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|