bitf.h: Add sz_nbits to get the maximum bitfield for a given size

parent 7b192f32
......@@ -71,6 +71,104 @@ bitf_sz(size_t bits)
return (sz);
}
/*
* for a given size, get the maximum number of bits we can fit
*
* This turns out quite hard to do. We basically have a geometric series
*
* S = sum_{n = 0}^{\infty}{ar^n}
*
* closed form: S = a / 1 - r
*
* here a = sizeof(struct bitf) + ceil(bits / 64) * 64
* r = 1/64
*
* this function approximates bitf_sz:
*/
#if 0
static inline double
bsz(size_t bits)
{
double a;
const double r = 1.0 / wbits;
a = sizeof(struct bitf) * 8 + bits;
return ((a / (1.0 - r) / 8.0));
}
#endif
/*
* so this function is an attempt to reverse it, but it only returns a first
* estimation
*/
static inline size_t
sz_nbits_est(size_t sz) {
double a;
const double r = 1.0 / wbits;
size_t ret;
a = (((double)sz - sizeof(struct bitf)) * 8) * (1.0 - r);
ret = (typeof(ret))a;
ret &= ~(((size_t)1 << wsz) - 1);
return (ret);
}
/*
* ... and to get the best value, we need to narrow it down numerically
*
* this isually hits the right result after 5 iterations
*/
static inline size_t
sz_nbits(const size_t sz)
{
size_t trysz;
size_t d, hi, lo; // in units of bitf_words() / bitf_word_t
assert(sz >= bitf_sz1(1));
assert(sz < (size_t)1 << 62); // otherwise overflow
lo = sz_nbits_est(sz) / wbits;
trysz = bitf_sz(lo * wbits);
if (trysz > sz) {
d = bitf_words((trysz - sz) * 8);
hi = lo;
if (lo > d)
lo -= d;
}
else {
// trysz <= sz
d = bitf_words(((sz - trysz) + 1) * 8);
hi = lo + d;
}
// opportunistic: right at first shot
if (bitf_sz(lo * wbits) <= sz &&
bitf_sz(lo * wbits + 1) > sz)
goto out;
while (bitf_sz(lo * wbits) <= sz &&
bitf_sz(hi * wbits) > sz &&
hi - lo > 1) {
d = (hi + lo) / 2;
if (bitf_sz(d * wbits) <= sz)
lo = d;
else if (bitf_sz(d * wbits) > sz)
hi = d;
else
assert(0); //lint !e506 const val
}
out:
assert(bitf_sz(lo * wbits) <= sz);
assert(bitf_sz(lo * wbits + 1) > sz);
return (lo * wbits);
}
// pointer to word from bits
#define bitf_word(bitf, bit) \
(assert((bitf)->magic == BITF_MAGIC), \
......
......@@ -2211,6 +2211,24 @@ t_bitf(void)
free(mem);
}
static void
t_sz_nbits(void)
{
size_t u, v, sz;
for (u = 6; u < 32; u++)
(void) sz_nbits((size_t)1 << u);
for (sz = 64; sz < 128; sz++)
(void) sz_nbits(sz);
for (u = 7; u < 61; u++)
for (v = ((size_t)1 << u) - 32;
v < ((size_t)1 << u) + 128;
v += 8)
(void) sz_nbits(v);
}
static size_t
malloc_sz(struct slashmap *map, size_t size)
{
......@@ -2872,6 +2890,7 @@ int main(void)
assert(log2up(SIZE_MAX) == sizeof(size_t) * 8);
assert(log2down(SIZE_MAX) == sizeof(size_t) * 8 - 1);
t_bitf();
t_sz_nbits();
t_buddy(1 << 15);
t_buddy((1 << 15) - 1);
t_buddy((1 << 15) + 63);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment