/* $Id: set.h,v 1.3 2009/01/27 15:40:22 potyra Exp $ 
 *
 * Copyright (C) 2008-2009 FAUcc Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#define set_declare(name, count) \
typedef unsigned char name ## _set[(count + 7) / 8];		\
								\
extern int							\
name ## _set_is_element(unsigned char *set, unsigned int n);	\
extern int							\
name ## _set_find_forward(unsigned char *set);			\
extern void							\
name ## _set_add(unsigned char *set, unsigned int n);		\
extern void							\
name ## _set_remove(unsigned char *set, unsigned int n);	\
extern void							\
name ## _set_or(unsigned char *dst, unsigned char *src);	\
extern void							\
name ## _set_and(unsigned char *dst, unsigned char *src);	\
extern void							\
name ## _set_and_comp(unsigned char *dst, unsigned char *src);	\
extern void							\
name ## _set_cp(unsigned char *dst, unsigned char *src);	\
extern void							\
name ## _set_empty(unsigned char *set);				\
extern void							\
name ## _set_fill(unsigned char *set);

#define set_implement(name, count) \
int								\
name ## _set_is_element(unsigned char *set, unsigned int n)	\
{								\
	return (set[n / 8] >> (n % 8)) & 1;			\
}								\
								\
int								\
name ## _set_find_forward(unsigned char *set)			\
{								\
	unsigned int n;						\
	unsigned int m;						\
								\
	for (n = 0; ; n++) {					\
		if (n == (count + 7) / 8) {			\
			return -1;				\
		}						\
		if (set[n]) {					\
			for (m = 0; ; m++) {			\
				if (set[n] & (1 << m)) {	\
					return n * 8 + m;	\
				}				\
			}					\
		}						\
	}							\
}								\
								\
void								\
name ## _set_add(unsigned char *set, unsigned int n)		\
{								\
	set[n / 8] |= 1 << (n % 8);				\
}								\
								\
void								\
name ## _set_remove(unsigned char *set, unsigned int n)		\
{								\
	set[n / 8] &= ~(1 << (n % 8));				\
}								\
								\
void								\
name ## _set_or(unsigned char *dst, unsigned char *src)		\
{								\
	unsigned int n;						\
								\
	for (n = 0; n < (count + 7) / 8; n++) {			\
		dst[n] |= src[n];				\
	}							\
}								\
								\
void								\
name ## _set_and(unsigned char *dst, unsigned char *src)	\
{								\
	unsigned int n;						\
								\
	for (n = 0; n < (count + 7) / 8; n++) {			\
		dst[n] &= src[n];				\
	}							\
}								\
								\
void								\
name ## _set_and_comp(unsigned char *dst, unsigned char *src)	\
{								\
	unsigned int n;						\
								\
	for (n = 0; n < (count + 7) / 8; n++) {			\
		dst[n] &= ~src[n];				\
	}							\
}								\
								\
void								\
name ## _set_cp(unsigned char *dst, unsigned char *src)		\
{								\
	unsigned int n;						\
								\
	for (n = 0; n < (count + 7) / 8; n++) {			\
		dst[n] = src[n];				\
	}							\
}								\
								\
void								\
name ## _set_empty(unsigned char *set)				\
{								\
	unsigned int i;						\
								\
	for (i = 0; i < (count + 7) / 8; i++) {			\
		set[i] = 0;					\
	}							\
}								\
								\
void								\
name ## _set_fill(unsigned char *set)				\
{								\
	unsigned int i;						\
								\
	for (i = 0; i < (count + 7) / 8; i++) {			\
		set[i] = -1;					\
	}							\
}
