From 27bb337a60fe9876ce328839aacd91908175b6d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Mar 2013 21:26:49 +0900 Subject: [PATCH] Use set_bits_t for holding set elements. set_bits_t is now 64 bits for x86_64 machines (in linux, anyway). This gave qfvis a huge speed boost: from ~815s to ~720s. Also, expose some of the set internals so custom set operators can be created. --- include/QF/set.h | 29 +++++++++--- libs/util/set.c | 96 +++++++++++++++++++-------------------- libs/util/test/test-set.c | 5 +- 3 files changed, 72 insertions(+), 58 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index a10b7dbcd..56dc4f6a2 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -31,15 +31,32 @@ #ifndef __QF_set_h #define __QF_set_h +#include "QF/qtypes.h" + /** \defgroup set Set handling \ingroup utils */ //@{ -#define DEFMAP_SIZE ((32 - sizeof (struct set_s *) \ - - sizeof (unsigned *) \ - - sizeof (int) - sizeof (unsigned))\ - / sizeof (unsigned)) +//FIXME other archs +#ifdef __x86_64__ +typedef uint64_t set_bits_t; +#else +typedef uint32_t set_bits_t; +#endif + +#define SET_DEFMAP_SIZE ((32 - sizeof (struct set_s *) \ + - sizeof (set_bits_t *) \ + - sizeof (int) - sizeof (unsigned))\ + / sizeof (set_bits_t)) +#define SET_BITS (sizeof (set_bits_t) * 8) +//NOTE: x is the element number, so size is x + 1 +#define SET_SIZE(x) (((x) + SET_BITS) & ~(SET_BITS - 1)) +#define SET_WORDS(s) ((s)->size / SET_BITS) +#define SET_ZERO ((set_bits_t) 0) +#define SET_ONE ((set_bits_t) 1) +#define SET_TEST_MEMBER(s, x) \ + ((s)->map[(x) / SET_BITS] & (SET_ONE << ((x) % SET_BITS))) /** Represent a set using a bitmap. @@ -50,10 +67,10 @@ */ typedef struct set_s { struct set_s *next; ///< private. for ALLOC - unsigned *map; ///< bitmap of set members + set_bits_t *map; ///< bitmap of set members int inverted; ///< if true, 0 indicates membership unsigned size; ///< number of representable members - unsigned defmap[DEFMAP_SIZE];///< backing store for small sets + set_bits_t defmap[SET_DEFMAP_SIZE];///< backing store for small sets } set_t; /** Represent the state of a scan through a set. diff --git a/libs/util/set.c b/libs/util/set.c index ad2e096ad..ee538c36d 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -45,8 +45,6 @@ #include "QF/mathlib.h" #include "QF/set.h" -#define BITS (sizeof (((set_t *) 0)->map[0]) * 8) - set_t *sets_freelist; set_iter_t *set_iters_freelist; @@ -92,16 +90,16 @@ set_delete (set_t *set) static void set_expand (set_t *set, unsigned x) { - unsigned *map = set->map; + set_bits_t *map = set->map; size_t size; if (x <= set->size) return; - size = (x + BITS) & ~(BITS - 1); + size = SET_SIZE (x); set->map = malloc (size / 8); memcpy (set->map, map, set->size / 8); - memset (set->map + set->size / BITS, 0, (size - set->size) / 8); + memset (set->map + SET_WORDS (set), 0, (size - set->size) / 8); set->size = size; if (map != set->defmap) free (map); @@ -123,7 +121,7 @@ _set_add (set_t *set, unsigned x) { if (x >= set->size) set_expand (set, x + 1); - set->map[x / BITS] |= 1 << (x % BITS); + set->map[x / SET_BITS] |= SET_ONE << (x % SET_BITS); } static inline void @@ -131,7 +129,7 @@ _set_remove (set_t *set, unsigned x) { if (x >= set->size) return; - set->map[x / BITS] &= ~(1 << (x % BITS)); + set->map[x / SET_BITS] &= ~(SET_ONE << (x % SET_BITS)); } set_t * @@ -169,7 +167,7 @@ _set_union (set_t *dst, const set_t *src) size = max (dst->size, src->size); set_expand (dst, size); - for (i = 0; i < src->size / BITS; i++) + for (i = 0; i < SET_WORDS (src); i++) dst->map[i] |= src->map[i]; return dst; } @@ -182,9 +180,9 @@ _set_intersection (set_t *dst, const set_t *src) size = max (dst->size, src->size); set_expand (dst, size); - for (i = 0; i < src->size / BITS; i++) + for (i = 0; i < SET_WORDS (src); i++) dst->map[i] &= src->map[i]; - for ( ; i < dst->size / BITS; i++) + for ( ; i < SET_WORDS (dst); i++) dst->map[i] = 0; return dst; } @@ -197,7 +195,7 @@ _set_difference (set_t *dst, const set_t *src) size = max (dst->size, src->size); set_expand (dst, size); - for (i = 0; i < src->size / BITS; i++) + for (i = 0; i < SET_WORDS (src); i++) dst->map[i] &= ~src->map[i]; return dst; } @@ -210,7 +208,7 @@ _set_reverse_difference (set_t *dst, const set_t *src) size = max (dst->size, src->size); set_expand (dst, size); - for (i = 0; i < src->size / BITS; i++) + for (i = 0; i < SET_WORDS (src); i++) dst->map[i] = ~dst->map[i] & src->map[i]; return dst; } @@ -286,9 +284,9 @@ set_assign (set_t *dst, const set_t *src) size = max (dst->size, src->size); set_expand (dst, size); dst->inverted = src->inverted; - for (i = 0; i < src->size / BITS; i++) + for (i = 0; i < SET_WORDS (src); i++) dst->map[i] = src->map[i]; - for ( ; i < dst->size / BITS; i++) + for ( ; i < SET_WORDS (dst); i++) dst->map[i] = 0; return dst; } @@ -299,7 +297,7 @@ set_empty (set_t *set) unsigned i; set->inverted = 0; - for (i = 0; i < set->size / BITS; i++) + for (i = 0; i < SET_WORDS (set); i++) set->map[i] = 0; return set; } @@ -310,7 +308,7 @@ set_everything (set_t *set) unsigned i; set->inverted = 1; - for (i = 0; i < set->size / BITS; i++) + for (i = 0; i < SET_WORDS (set); i++) set->map[i] = 0; return set; } @@ -320,7 +318,7 @@ _set_is_empty (const set_t *set) { unsigned i; - for (i = 0; i < set->size / BITS; i++) + for (i = 0; i < SET_WORDS (set); i++) if (set->map[i]) return 0; return 1; @@ -346,21 +344,21 @@ static int set_test_n_n (const set_t *s1, const set_t *s2) { unsigned i, end; - unsigned intersection = 0; - unsigned difference = 0; + set_bits_t intersection = 0; + set_bits_t difference = 0; - end = min (s1->size, s2->size) / BITS; + end = min (s1->size, s2->size) / SET_BITS; for (i = 0; i < end; i++) { - unsigned m1 = s1->map[i]; - unsigned m2 = s2->map[i]; + set_bits_t m1 = s1->map[i]; + set_bits_t m2 = s2->map[i]; intersection |= m1 & m2; difference |= m1 ^ m2; } - for ( ; i < s1->size / BITS; i++) { + for ( ; i < SET_WORDS (s1); i++) { difference |= s1->map[i]; } - for ( ; i < s2->size / BITS; i++) { + for ( ; i < SET_WORDS (s2); i++) { difference |= s2->map[i]; } return (difference != 0) | ((intersection != 0) << 1); @@ -370,22 +368,22 @@ static int set_test_n_i (const set_t *s1, const set_t *s2) { unsigned i, end; - unsigned intersection = 0; - unsigned difference = 0; + set_bits_t intersection = 0; + set_bits_t difference = 0; - end = min (s1->size, s2->size) / BITS; + end = min (s1->size, s2->size) / SET_BITS; for (i = 0; i < end; i++) { - unsigned m1 = s1->map[i]; - unsigned m2 = ~s2->map[i]; + set_bits_t m1 = s1->map[i]; + set_bits_t m2 = ~s2->map[i]; intersection |= m1 & m2; difference |= m1 ^ m2; } - for ( ; i < s1->size / BITS; i++) { + for ( ; i < SET_WORDS (s1); i++) { intersection |= s1->map[i]; difference |= ~s1->map[i]; } - for ( ; i < s2->size / BITS; i++) { + for ( ; i < SET_WORDS (s2); i++) { difference |= ~s2->map[i]; } return (difference != 0) | ((intersection != 0) << 1); @@ -395,21 +393,21 @@ static int set_test_i_n (const set_t *s1, const set_t *s2) { unsigned i, end; - unsigned intersection = 0; - unsigned difference = 0; + set_bits_t intersection = 0; + set_bits_t difference = 0; - end = min (s1->size, s2->size) / BITS; + end = min (s1->size, s2->size) / SET_BITS; for (i = 0; i < end; i++) { - unsigned m1 = ~s1->map[i]; - unsigned m2 = s2->map[i]; + set_bits_t m1 = ~s1->map[i]; + set_bits_t m2 = s2->map[i]; intersection |= m1 & m2; difference |= m1 ^ m2; } - for ( ; i < s1->size / BITS; i++) { + for ( ; i < SET_WORDS (s1); i++) { difference |= ~s1->map[i]; } - for ( ; i < s2->size / BITS; i++) { + for ( ; i < SET_WORDS (s2); i++) { intersection |= s2->map[i]; difference |= ~s2->map[i]; } @@ -420,21 +418,21 @@ static int set_test_i_i (const set_t *s1, const set_t *s2) { unsigned i, end; - unsigned intersection = 0; - unsigned difference = 0; + set_bits_t intersection = 0; + set_bits_t difference = 0; - end = min (s1->size, s2->size) / BITS; + end = min (s1->size, s2->size) / SET_BITS; for (i = 0; i < end; i++) { - unsigned m1 = ~s1->map[i]; - unsigned m2 = ~s2->map[i]; + set_bits_t m1 = ~s1->map[i]; + set_bits_t m2 = ~s2->map[i]; intersection |= m1 & m2; difference |= m1 ^ m2; } - for ( ; i < s1->size / BITS; i++) { + for ( ; i < SET_WORDS (s1); i++) { difference |= ~s1->map[i]; } - for ( ; i < s2->size / BITS; i++) { + for ( ; i < SET_WORDS (s2); i++) { intersection |= s2->map[i]; difference |= ~s2->map[i]; } @@ -478,13 +476,13 @@ set_is_subset (const set_t *set, const set_t *sub) { unsigned i, end; - end = min (set->size, sub->size) / BITS; + end = min (set->size, sub->size) / SET_BITS; if (set->inverted && sub->inverted) { for (i = 0; i < end; i++) { if (~sub->map[i] & set->map[i]) return 0; } - for ( ; i < set->size / BITS; i++) + for ( ; i < SET_WORDS (set); i++) if (set->map[i]) return 0; } else if (set->inverted) { @@ -500,7 +498,7 @@ set_is_subset (const set_t *set, const set_t *sub) if (sub->map[i] & ~set->map[i]) return 0; } - for ( ; i < sub->size / BITS; i++) + for ( ; i < SET_WORDS (sub); i++) if (sub->map[i]) return 0; } @@ -512,7 +510,7 @@ _set_is_member (const set_t *set, unsigned x) { if (x >= set->size) return 0; - return (set->map[x / BITS] & (1 << (x % BITS))) != 0; + return (set->map[x / SET_BITS] & (SET_ONE << (x % SET_BITS))) != 0; } int diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index bb24e8cd1..3771d9f0e 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -6,8 +6,7 @@ #include "QF/set.h" -#define SIZE (DEFMAP_SIZE * sizeof (unsigned) * 8) -#define BITS (sizeof (((set_t *) 0)->map[0]) * 8) +#define SIZE (SET_DEFMAP_SIZE * sizeof (set_bits_t) * 8) typedef set_t *(*setup_func) (void); typedef set_t *(*op_func) (set_t *s1, const set_t *s2); @@ -121,7 +120,7 @@ struct { {make_everything, 0, 0, check_size, SIZE, "{...}"}, {make_empty_invert, 0, 0, check_size, SIZE, "{...}"}, {make_everything_invert, 0, 0, check_size, SIZE, "{}"}, - {make_SIZE, 0, 0, check_size, SIZE + BITS, "{64}"}, + {make_SIZE, 0, 0, check_size, SIZE + SET_BITS, "{64}"}, {make_0_to_SIZEm1, 0, 0, check_size, SIZE, "{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"