/* bitset.c - bitsets
 *
 ****************************************************************
 * Copyright (C) 1998, 2000 Thomas Lord
 * 
 * See the file "COPYING" for further information about
 * the copyright and warranty status of this work.
 */



#include "hackerlab/bugs/panic.h"
#include "hackerlab/mem/mem.h"
#include "hackerlab/bitsets/bitset.h"


/************************************************************************
 *(h1 "Flat Bitsets"
 *	:includes ("hackerlab/bitset/bitset.h"))
 *
 * |subset|
 * |flat bitset|
 * 
 * A "bitset" (or "flat bitset") is a packed array whose elements are
 * each 1 bit.  A bitset can be considered a finite, ordered set of
 * numbered entities.
 *
 * The type `bitset_subset' is a bitset small enough to fit in a
 * variable of type `void *'.  (See xref:"Portability Assumptions in
 * the Hackerlab C Library".
 *
 * The type `bitset' is pointer to `bitset_subset'.  Bitset functions
 * generally operate on a pair of values: the `size' (measured in
 * bits, an integer of type `bit_t') and the `set' (a pointer of type
 * `bitset_subset *').  
 * 
 * |ranges (in bitset functions)| Some functions operate on an
 * arbitrary subsequence of a bitset.  Their arguments include a
 * starting bit (`from'), and an ending bit (`to'); these have names
 * that end in the suffix `_range'.  When a function operates on a
 * range of bits, the range is specified as a half-open interval.  For
 * example,
 * 
 * 	bitset_clear_range (bits, from, to)
 * 
 * changes the bits numbered:
 *
 *	from ... to - 1
 *
 * and the bit numbered `to' is unaffected.  This permits bit addresses
 * to be used similarly to pointers:  a range of `n' bits beginning
 * at bit `pos' is:
 * 
 * 	pos, pos + n
 *
 * Bitsets are ordinarily allocated in sizes rounded up to the
 * nearest `sizeof (bitset_subset)'.  Operations on bitsets, however,
 * are precise: they modify only the bits in a bitset and no others.
 * For that reason, it is safe to operate on a bitset with `N'
 * elements as if it had only `M' elements (with `M < N').  Bits
 * `M..N-1' will be unaffected.
 */
/*(menu)
 */

/*(include-documentation "bitset.h")
 */


/* bitset_access(B,N,OP)
 *
 * Apply OP to the subset of bitset `B' containing element `N' and to
 * a singleton subset containing a 1-bit in the position where element
 * `N' resides.
 */
#define bitset_access(B,N,OP) 	((B)[bitset_which_subset(N)] OP ((bitset_subset)1 << ((N) & bitset_subset_mask)))


/************************************************************************
 *(h2 "Allocating and Freeing Bitsets")
 * 
 */


/*(c bitset_alloc)
 * bitset bitset_alloc (alloc_limits limits, bit_t size);
 * 
 * Allocate an empty bitset large enough to hold `size' members.
 *
 * Allocation is performed by `lim_malloc' using `limits'.  See
 * xref:"Allocation With Limitations".
 */
bitset
bitset_alloc (alloc_limits limits, bit_t size)
{
  bitset b;
  b = (bitset) lim_malloc (limits, sizeof_bitset (size));
  bitset_clear (size, b);
  return b;
}

/*(c bitset_free)
 * void bitset_free (alloc_limits limits, bitset a);
 * 
 * Free the bitset `a'.
 * 
 * Deallocation is performed by `lim_free' using `limits'.  See
 * xref:"Allocation With Limitations".
 */
void
bitset_free (alloc_limits limits, bitset a)
{
  lim_free (limits, a);
}


/*(c bitset_dup)
 * bitset bitset_dup (alloc_limits limits, bit_t size, bitset a);
 * 
 * Allocate a copy of bitset `a' which has `size' members.
 *
 * Allocation is performed by `lim_malloc' using `limits'.  See
 * xref:"Allocation With Limitations".
 */
bitset
bitset_dup (alloc_limits limits, bit_t size, bitset a)
{
  bitset cs;

  cs = lim_malloc (limits, sizeof_bitset (size));
  bitset_assign (size, cs, a);
  return cs;
}





/************************************************************************
 *(h2 "Tests on Bitsets")
 * 
 * 
 * 
 */



/*(c bitset_is_member)
 * int bitset_is_member (bitset b, bit_t n);
 * 
 * Return bit `n' of bitset `b' (either 0 or 1).
 */
int
bitset_is_member (bitset b, bit_t n)
{
  return !!bitset_access((b), (n), &);
}


/*(c bitset_is_equal)
 * int bitset_is_equal (bit_t size, bitset a, bitset b);
 * 
 * Compare two bitsets for equality.  Both bitsets have `size'
 * members.  Return 1 if they are equal, 0 otherwise.
 */
int
bitset_is_equal (bit_t size, bitset a, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;

  if (!size)
    return 1;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);

  if ((a[x] & last_bitset_subset_mask) != (b[x] & last_bitset_subset_mask))
    return 0;

  while (x--)
    {
      if (a[x] != b[x])
	return 0;
    }

  return 1;
}


/*(c bitset_is_subset)
 * int bitset_is_subset (bit_t size, bitset a, bitset b);
 * 
 * Return 1 if bitset `b' is a subset of bitset `a', 0 otherwise.
 */
int
bitset_is_subset (bit_t size, bitset a, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  bitset_subset a_bits;
  bitset_subset b_bits;

  if (!size)
    return 1;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);

  a_bits = (a[x] & last_bitset_subset_mask);
  b_bits = (b[x] & last_bitset_subset_mask);
  if ((a_bits | b_bits) != a_bits)
    return 0;

  while (x-- && ((a[x] | b[x]) == a[x]))
    ;

  return x == -1;
}


/*(c bitset_is_empty)
 * int bitset_is_empty (bit_t size, bitset a);
 * 
 * Return 1 if bitset `a' has no members.
 */
int
bitset_is_empty (bit_t size, bitset a)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;

  if (!size)
    return 1;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);

  if (a[x] & last_bitset_subset_mask)
    return 0;

  while (x-- && !a[x])
    ;

  return x == -1;
}


/*(c bitset_is_empty_range)
 * int bitset_is_empty_range (bitset a, bit_t from, bit_t to);
 * 
 * Return 1 if bitset `a' has no members in the closed 
 * interval `[from ... to-1]'.
 */
int
bitset_is_empty_range (bitset a, bit_t from, bit_t to)
{
  bit_t first_subset;
  bitset_subset first_bitset_subset_mask;
  bit_t last_subset;
  bitset_subset last_bitset_subset_mask;
  bit_t x;

  if (to <= from)
    return 1;

  --to;
  
  first_subset = bitset_which_subset (from);
  last_subset = bitset_which_subset (to);
  
  first_bitset_subset_mask = ~(bitset_subset)0 << bitset_which_bit (from);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - (1 + bitset_which_bit (to)));

  if (first_subset == last_subset)
    return !(a[first_subset] & first_bitset_subset_mask & last_bitset_subset_mask);

  if (a[first_subset] & first_bitset_subset_mask)
    return 0;

  if (a[last_subset] & last_bitset_subset_mask)
    return 0;

  for (x = first_subset + 1; x < last_subset; ++x)
    if (a[x])
      return 0;

  return 1;
}



/*(c bitset_is_full)
 * int bitset_is_full (bit_t size, bitset a);
 * 
 * Return 1 if bitset `a' is filled (all ones).
 */
int
bitset_is_full (bit_t size, bitset a)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;

  if (!size)
    return 1;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);

  if ((a[x] & last_bitset_subset_mask) != last_bitset_subset_mask)
    return 0;

  while (x-- && (a[x] == (bitset_subset)-1L))
    ;

  return x == -1;
}


/*(c bitset_is_full_range)
 * int bitset_is_full_range (bitset a, bit_t from, bit_t to);
 * 
 * Return 1 if bitset `a' is filled in the closed 
 * interval `[from .. to-1]'.
 */
int
bitset_is_full_range (bitset a, bit_t from, bit_t to)
{
  bit_t first_subset;
  bitset_subset first_bitset_subset_mask;
  bit_t last_subset;
  bitset_subset last_bitset_subset_mask;
  bit_t x;

  if (to <= from)
    return 1;

  first_subset = bitset_which_subset (from);
  last_subset = bitset_which_subset (to);
  first_bitset_subset_mask = ~(((bitset_subset)1 << (from & bitset_subset_mask)) - 1);
  last_bitset_subset_mask = (((bitset_subset)1 << (to & bitset_subset_mask)) - 1);

  if (first_subset == last_subset)
    return (   (a[first_subset] & first_bitset_subset_mask & last_bitset_subset_mask)
	    == (first_bitset_subset_mask & last_bitset_subset_mask));

  if ((a[first_subset] & first_bitset_subset_mask) != first_bitset_subset_mask)
    return 0;

  if ((a[last_subset] & last_bitset_subset_mask) != last_bitset_subset_mask)
    return 0;

  for (x = first_subset + 1; x < last_subset - 1; ++x)
    if (a[x] != (bitset_subset)-1L)
      return 0;

  return 1;
}


/************************************************************************
 *(h2 "Set Operations")
 * 
 * 
 * 
 */


/*(c bitset_adjoin)
 * void bitset_adjoin (bitset b, bit_t n);
 * 
 * Set bit `n' of bitset `b' to 1.
 */
void
bitset_adjoin (bitset b, bit_t n)
{
  bitset_access((b), (n), |=);
}


/*(c bitset_remove)
 * void bitset_remove (bitset b, bit_t n);
 * 
 * Set bit `n' of bitset `b' to 0.
 */
void
bitset_remove (bitset b, bit_t n)
{
  bitset_access((b), (n), &= ~);
}


/*(c bitset_toggle)
 * void bitset_toggle (bitset b, bit_t n);
 * 
 * If bit `n' of bitset `b' is 1, set it to 0;  if 0,
 * set it to 1.
 */
void
bitset_toggle (bitset b, bit_t n)
{
  bitset_access((b), (n), ^= );
}


/*(c bitset_clear)
 * void bitset_clear (bit_t size, bitset b);
 * 
 * Clear all bits of bitset `b'.
 */
void
bitset_clear (bit_t size, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);
  b[x] &= ~last_bitset_subset_mask;
  mem_set ((char *)b, 0, x * sizeof (bitset_subset));
}



/*(c bitset_clear_range)
 * void bitset_clear_range (bitset b, bit_t from, bit_t to);
 * 
 * Clear the bits `from .. to - 1' of bitset `b'.
 */
void
bitset_clear_range (bitset b, bit_t from, bit_t to)
{
  bitset bp;

  while ((from < to) && (from % bits_per_subset))
    {
      bitset_remove (b, from);
      ++from;
    }

  bp = b + bitset_which_subset (from);
  while (from + bits_per_subset < to)
    {
      *bp = (bitset_subset)0;
      ++bp;
      from += bits_per_subset;
    }

  while (from < to)
    {
      bitset_remove (b, from);
      ++from;
    }
}


/*(c bitset_fill)
 * void bitset_fill (bit_t size, bitset b);
 * 
 * Set all bits of bitset `b'.
 */
void
bitset_fill (bit_t size, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);
  b[x] |= last_bitset_subset_mask;
  mem_set ((t_uchar *)b, 0xff, x * sizeof (bitset_subset));
}


/*(c bitset_fill_range)
 * void bitset_fill_range (bitset b, bit_t from, bit_t to);
 * 
 * Set the bits `from .. to - 1' of bitset `b'.
 */
void
bitset_fill_range (bitset b, bit_t from, bit_t to)
{
  bitset bp;

  while ((from < to) && (from % bits_per_subset))
    {
      bitset_adjoin (b, from);
      ++from;
    }

  bp = b + bitset_which_subset (from);
  while (from + bits_per_subset < to)
    {
      *bp = ~(bitset_subset)0;
      ++bp;
      from += bits_per_subset;
    }

  while (from < to)
    {
      bitset_adjoin (b, from);
      ++from;
    }
}


/*(c bitset_complement)
 * void bitset_complement (bit_t size, bitset b);
 * 
 * Toggle all bits in bitset `b'.
 */
void
bitset_complement (bit_t size, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);

  b[x] = ((b[x] & ~last_bitset_subset_mask) | (~b[x] & last_bitset_subset_mask));

  while (x--)
    {
      *b = ~*b;
      ++b;
    }
}


/*(c bitset_assign)
 * void bitset_assign (bit_t size, bitset a, bitset b);
 * 
 * Copy bitset `b' to bitset `a'.
 */
void
bitset_assign (bit_t size, bitset a, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);

  a[x] = (a[x] & ~last_bitset_subset_mask) | (b[x] & last_bitset_subset_mask);

  while (x--)
    a[x] = b[x];
}


/*(c bitset_union)
 * void bitset_union (bit_t size, bitset a, bitset b);
 * 
 * Add all elements of bitset `b' to bitset `a'.
 */
void
bitset_union (bit_t size, bitset a, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);
  a[x] |= (b[x] & last_bitset_subset_mask);

  while (x--)
    a[x] |= b[x];
}


/*(c bitset_intersection)
 * void bitset_intersection (bit_t size, bitset a, bitset b);
 * 
 * Remove from bitset `a' all alements that are not also in bitset
 * `b'.
 */
void
bitset_intersection (bit_t size, bitset a, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);
  a[x] = (a[x] & ~last_bitset_subset_mask) | ((a[x] & b[x]) & last_bitset_subset_mask);

  while (x--)
    a[x] &= b[x];
}


/*(c bitset_difference)
 * void bitset_difference (bit_t size, bitset a, bitset b);
 * 
 * Remove from bitset `a' all alements that are in bitset `b'.
 */
void
bitset_difference (bit_t size, bitset a, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);
  a[x] = (a[x] & ~last_bitset_subset_mask) | ((a[x] & ~b[x]) & last_bitset_subset_mask);

  while (x--)
    a[x] &= ~ b[x];
}


/*(c bitset_revdifference)
 * void bitset_revdifference (bit_t size, bitset a, bitset b);
 * 
 * Set all bits in `a' that are set in bitset `b' but not in `a';
 * clear all other bits of bitset `a'.
 *
 * This is similar to `bitset_difference (size, b, a)' except that
 * the result is assigned to bitset `a' instead of bitset `b'.
 */
void
bitset_revdifference (bit_t size, bitset a, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);
  a[x] = (a[x] & ~last_bitset_subset_mask) | ((~a[x] & b[x]) & last_bitset_subset_mask);

  while (x--)
    a[x] = ~a[x] & b[x];
}


/*(c bitset_xor)
 * void bitset_xor (bit_t size, bitset a, bitset b);
 * 
 * Toggle all bits in bitset `a' that are set in bitset `b'.
 */
void
bitset_xor (bit_t size, bitset a, bitset b)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  
  if (!size)
    return;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);
  a[x] ^= (b[x] & last_bitset_subset_mask);

  while (x--)
    a[x] ^= b[x];
}


/************************************************************************
 *(h2 "Population Size")
 * 
 * 
 * 
 */


/* 
 * (define l (let loop ((x 0) (l '())) (if (eq? x 256) l (loop (+ x 1) (cons x l)))))
 * (define lb (map (lambda (n) (number->string n 2)) l))
 * (define lc (map string->list lb))
 * (define ln (map (lambda (l) (map (lambda (c) (if (eq? c #\1) 1 0)) l)) lc))
 * (define lt (map (lambda (l) (apply + l)) ln))
 */
static int bitset_byte_populations[256] = 
{
  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};


/*(c bitset_population)
 * bit_t bitset_population (bit_t size, bitset a);
 * 
 * Return the number of bits set in bitset `a'.
 */
bit_t
bitset_population (bit_t size, bitset a)
{
  bit_t x;
  bit_t bits_in_last_subset;
  bitset_subset last_bitset_subset_mask;
  bitset_subset a_subset;
  bit_t total;
  
  if (!size)
    return 0;

  x = bitset_numb_subsets(size) - 1;
  bits_in_last_subset = (size - bits_per_subset * x);
  last_bitset_subset_mask = ~(bitset_subset)0 >> (bits_per_subset - bits_in_last_subset);
  total = 0;
  a_subset = a[x] & last_bitset_subset_mask;
  while (a_subset)
    {
      total += bitset_byte_populations[a_subset & 0xff];
      a_subset >>= 8;
    }
  while (x--)
    {
      a_subset = a[x];
      while (a_subset)
	{
	  total += bitset_byte_populations[a_subset & 0xff];
	  a_subset >>= 8;
	}
    }
  return total;
}     



/*(c bitset_population_range)
 * bit_t bitset_population (bitset a, bit_t from, bit_t to);
 * 
 * Return the number of bits set in bitset `a' couning only
 * members in the closed interval `[from .. to-1]'.
 */
bit_t
bitset_population_range (bitset a, bit_t from, bit_t to)
{
  bit_t first_subset;
  bit_t first_subset_offset;
  bit_t overcount;
  bit_t count_error;


  if (to <= from)
    return 0;

  first_subset = bitset_which_subset (from);
  first_subset_offset = first_subset * bits_per_subset;
  overcount = bitset_population (to - first_subset_offset, a + first_subset);
  count_error = bitset_population (from - first_subset_offset, a + first_subset);
  return overcount - count_error;
}


/************************************************************************
 *(h2 "First Bit Set -- First Bit Clear")
 * 
 * 
 * 
 */

static int bitset_byte_ffs[256] =
{
  -1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};


/* static bit_t subset_ffs (bitset_subset a);
 * 
 * Return the address of the first bit set in a bitset_subset.
 * For bitset_subset 0, return -1.
 */
static bit_t
subset_ffs (bitset_subset a)
{
  bit_t offset;
  bit_t x;

  if (!a)
    return -1;

  offset = 0;
  x = sizeof (a);
  while (x--)
    {
      bit_t q;
      q = bitset_byte_ffs [a & 0xff];
      if (q >= 0)
	return q + offset;
      offset += 8;
      a >>= 8;
    }

  while (1)
    panic ("not reached");
}


/*(c bitset_ffs)
 * bit_t bitset_ffs (bit_t size, bitset b);
 * 
 * Return the (bit) address of the first bit set in bitset `b'.
 * Return -1 if no bit is set.
 */
bit_t
bitset_ffs (bit_t size, bitset b)
{
  bit_t offset;
  bit_t x;
  bit_t bound;
  
  offset = 0;
  x = 0;
  bound = bitset_numb_subsets(size);

  while (x < bound)
    {
      bit_t fs;

      fs = subset_ffs (b[x]);

      if (fs >= 0)
	{
	  bit_t answer;
	  answer = offset + fs;
	  return (answer < size) ? answer : -1;
	}

      offset += bits_per_subset;
      ++x;
    }
  return -1;
}


/*(c bitset_ffs_range)
 * bit_t bitset_ffs_range (bitset b, bit_t from, bit_t to);
 * 
 * Return the (bit) address of the first bit set in bitset `b'
 * in the range `from .. to-1'.  Return -1 if no bit is set.
 */
bit_t
bitset_ffs_range (bitset b, bit_t from, bit_t to)
{
  bit_t n_bits;
  bit_t first_subset_skip;
  bit_t f;
  bit_t answer;

  n_bits = to - from;
  first_subset_skip = (from % bits_per_subset);
  if (first_subset_skip)
    {
      bitset_subset s;
      bit_t first_in_s;

      s = b[bitset_which_subset (from)];
      s &= ~(((bitset_subset)1 << first_subset_skip) - 1);
      first_in_s = subset_ffs (s);
      if (first_in_s != -1)
	{
	  answer = first_in_s + from - first_subset_skip;
	  return (answer < (from + n_bits)) ? answer : -1;
	}
      from += bits_per_subset - first_subset_skip;
      n_bits -= bits_per_subset - first_subset_skip;
    }
  f = bitset_ffs (n_bits, b + bitset_which_subset (from));
  if (f < 0)
    return f;
  answer = from + f;
  return (answer < (from + n_bits)) ? answer : -1;
}




static int bitset_byte_ffc[256] =
{
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, -1
};


/* static bit_t subset_ffc (bitset_subset a);
 * 
 * Return the address of the first bit set in a subset.
 * For bitset_subset 0, return -1.
 */
static bit_t
subset_ffc (bitset_subset a)
{
  bit_t offset;
  bit_t x;

  if (a == (bitset_subset)-1L)
    return -1;

  offset = 0;
  x = sizeof (a);
  while (x--)
    {
      bit_t q;
      q = bitset_byte_ffc [a & 0xff];
      if (q >= 0)
	return q + offset;
      offset += 8;
      a >>= 8;
    }

  while (1)
    panic ("not reached");
}

/*(c bitset_ffc)
 * bit_t bitset_ffc (bit_t size, bitset b);
 *
 * Return the (bit) address of the first bit clear in bitset `b'.
 * Return -1 if no bit is clear.
 */
bit_t
bitset_ffc (bit_t size, bitset b)
{
  bit_t offset;
  bit_t x;
  bit_t bound;
  
  offset = 0;
  x = 0;
  bound = bitset_numb_subsets(size);

  while (x < bound)
    {
      bit_t fs;

      fs = subset_ffc (b[x]);

      if (fs >= 0)
	{
	  bit_t answer;
	  answer = offset + fs;
	  return (answer < size) ? answer : -1;
	}

      offset += bits_per_subset;
      ++x;
    }
  return -1;
}


/*(c bitset_ffc_range)
 * bit_t bitset_ffc_range (bitset b, bit_t from, bit_t to);
 * 
 * Return the (bit) address of the first bit clear in bitset `b'
 * in the range `from .. to-1'.  Return -1 if no bit is set.
 */
bit_t
bitset_ffc_range (bitset b, bit_t from, bit_t to)
{
  bit_t n_bits;
  bit_t first_subset_skip;
  bit_t f;
  bit_t answer;

  n_bits = to - from;
  first_subset_skip = (from % bits_per_subset);
  if (first_subset_skip)
    {
      bitset_subset s;
      bit_t first_in_s;

      s = b[bitset_which_subset (from)];
      s |= (((bitset_subset)1 << first_subset_skip) - 1);
      first_in_s = subset_ffc (s);
      if (first_in_s != -1)
	{
	  answer = first_in_s + from - first_subset_skip;
	  return (answer < (from + n_bits)) ? answer : -1;
	}
      from += bits_per_subset - first_subset_skip;
      n_bits -= bits_per_subset - first_subset_skip;
    }
  f = bitset_ffc (n_bits, b + bitset_which_subset (from));
  if (f < 0)
    return f;
  answer = from + f;
  return (answer < (from + n_bits)) ? answer : -1;
}

