C: 2020 day 24 - switch to 32 bits hash, rename some var/fct.

This commit is contained in:
2022-10-19 18:57:47 +02:00
parent abcc4af572
commit b4a2603c7b

View File

@@ -20,20 +20,21 @@
* one for the neighbours count. * one for the neighbours count.
* My first try with the Linux kernel hashtables implementation. * My first try with the Linux kernel hashtables implementation.
*/ */
typedef union coord { typedef union coord {
u64 val; u32 val; /* used for hash */
struct { struct {
s32 x, y; s16 x, y;
}; };
} coord_t; } coord_t;
typedef struct point { typedef struct point {
coord_t pos; coord_t pos;
int count; int count;
struct hlist_node coll; /* entry in hash table */ struct hlist_node hlist; /* entry in hash table */
} point_t; } point_t;
#define HBITS 11 /* in bits: 12 bits = 4096 */ #define HBITS 11 /* 11 bits: size is 2048 */
DEFINE_HASHTABLE(hasht_black, HBITS); /* current black tiles */ DEFINE_HASHTABLE(hasht_black, HBITS); /* current black tiles */
DEFINE_HASHTABLE(hasht_count, HBITS); /* count of neighbours */ DEFINE_HASHTABLE(hasht_count, HBITS); /* count of neighbours */
@@ -42,7 +43,7 @@ pool_t *pt_pool;
static __always_inline u32 hash(coord_t p) static __always_inline u32 hash(coord_t p)
{ {
return hash_64(p.val, HASH_BITS(hasht_black)); return hash_32(p.val, HASH_BITS(hasht_black));
} }
/** /**
@@ -51,7 +52,8 @@ static __always_inline u32 hash(coord_t p)
static point_t *find_point(struct hlist_head *head, coord_t p) static point_t *find_point(struct hlist_head *head, coord_t p)
{ {
point_t *point; point_t *point;
hlist_for_each_entry(point, head, coll) {
hlist_for_each_entry(point, head, hlist) {
if (point->pos.val == p.val) if (point->pos.val == p.val)
return point; return point;
} }
@@ -59,9 +61,9 @@ static point_t *find_point(struct hlist_head *head, coord_t p)
} }
/** /**
* add_point - add point in hasht_count hashtable (used to count neighbours) * add_neighbour - add point in hasht_count hashtable (used to count neighbours)
*/ */
static point_t *add_point(coord_t pos) static point_t *add_neighbour(coord_t pos)
{ {
point_t *new; point_t *new;
u32 h; u32 h;
@@ -71,7 +73,7 @@ static point_t *add_point(coord_t pos)
new = pool_get(pt_pool); new = pool_get(pt_pool);
new->pos.val = pos.val; new->pos.val = pos.val;
new->count = 0; new->count = 0;
hlist_add_head(&new->coll, &hasht_count[h]); hlist_add_head(&new->hlist, &hasht_count[h]);
} }
new->count++; new->count++;
return new; return new;
@@ -87,14 +89,14 @@ static point_t *init_point(coord_t pos)
h = hash(pos); h = hash(pos);
if ((new = find_point(&hasht_black[h], pos))) { if ((new = find_point(&hasht_black[h], pos))) {
hlist_del(&new->coll); hlist_del(&new->hlist);
pool_add(pt_pool, new); pool_add(pt_pool, new);
new = NULL; new = NULL;
} else { } else {
new = pool_get(pt_pool); new = pool_get(pt_pool);
new->pos.val = pos.val; new->pos.val = pos.val;
new->count = 0; new->count = 0;
hlist_add_head(&new->coll, &hasht_black[h]); hlist_add_head(&new->hlist, &hasht_black[h]);
} }
return new; return new;
} }
@@ -108,7 +110,7 @@ static int count_black()
int res = 0; int res = 0;
ulong bucket; ulong bucket;
hash_for_each(hasht_black, bucket, cur, coll) hash_for_each(hasht_black, bucket, cur, hlist)
res++; res++;
return res; return res;
} }
@@ -120,57 +122,46 @@ static const coord_t neighbours [] = {
}; };
/** /**
* count_neighbours - count hasht_black neighbours, result in hasht_next * life - do one day.
*/ */
static void count_neighbours() static void life()
{
point_t *cur;
u32 bucket;
hash_for_each(hasht_black, bucket, cur, coll) {
for (int i = 0; i < (int) ARRAY_SIZE(neighbours); ++i) {
coord_t neigh = cur->pos;
neigh.x += neighbours[i].x;
neigh.y += neighbours[i].y;
add_point(neigh);
}
}
}
/**
* adjust_neighbours - adjust hasht_next according to rules
*/
static void adjust_neighbours()
{ {
point_t *pt_cur, *pt_count; point_t *pt_cur, *pt_count;
u32 bucket; u32 bucket;
struct hlist_node *tmp; struct hlist_node *tmp;
/* 1) check hasht_black tiles (currently black) /* fill hasht_count hashtable with neighbours */
*/ hash_for_each(hasht_black, bucket, pt_cur, hlist) {
hash_for_each_safe(hasht_black, bucket, tmp, pt_cur, coll) { s16 x = pt_cur->pos.x, y = pt_cur->pos.y;
for (int i = 0; i < (int) ARRAY_SIZE(neighbours); ++i) {
coord_t neigh = {
.x = x + neighbours[i].x,
.y = y + neighbours[i].y,
};
add_neighbour(neigh);
}
}
/* check hasht_black tiles (currently black) */
hash_for_each_safe(hasht_black, bucket, tmp, pt_cur, hlist) {
int h = hash(pt_cur->pos); int h = hash(pt_cur->pos);
point_t *pt_count = find_point(&hasht_count[h], pt_cur->pos); point_t *pt_count = find_point(&hasht_count[h], pt_cur->pos);
if (!pt_count || pt_count->count > 2) { if (!pt_count || pt_count->count > 2) {
hash_del(&pt_cur->coll); hash_del(&pt_cur->hlist); /* black tile becomes white */
pool_add(pt_pool, pt_cur); pool_add(pt_pool, pt_cur);
} }
/* we do not want to re-consider this point in next loop /* we do not want to re-consider this point in next loop */
*/
if (pt_count) { if (pt_count) {
hash_del(&pt_count->coll); hash_del(&pt_count->hlist);
pool_add(pt_pool, pt_count); pool_add(pt_pool, pt_count);
} }
} }
/* 2) check remaining points in hasht_next (currently white) /* check remaining points in hasht_count (not in hasht_black => white) */
*/ hash_for_each_safe(hasht_count, bucket, tmp, pt_count, hlist) {
hash_for_each_safe(hasht_count, bucket, tmp, pt_count, coll) { hash_del(&pt_count->hlist);
hash_del(&pt_count->coll); if (pt_count->count == 2)
if (pt_count->count == 2) { hash_add(hasht_black, &pt_count->hlist, hash(pt_count->pos));
hash_add(hasht_black, &pt_count->coll, hash(pt_count->pos)); else
} else {
pool_add(pt_pool, pt_count); pool_add(pt_pool, pt_count);
}
} }
} }
@@ -213,7 +204,6 @@ int main(ac, av)
char **av; char **av;
{ {
int opt, part = 1; int opt, part = 1;
int res = 0;
while ((opt = getopt(ac, av, "d:p:")) != -1) { while ((opt = getopt(ac, av, "d:p:")) != -1) {
switch (opt) { switch (opt) {
@@ -227,16 +217,14 @@ int main(ac, av)
return usage(*av); return usage(*av);
} }
} }
pt_pool = pool_create("pool_points", 512, sizeof(point_t));
pt_pool = pool_create("pool_points", 2048, sizeof(point_t));
parse(); parse();
if (part == 2) { if (part == 2) {
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i)
count_neighbours(); life();
adjust_neighbours();
}
} }
res = count_black(); printf("%s : res=%d\n", *av, count_black());
printf("%s : res=%d\n", *av, res);
pool_destroy(pt_pool); pool_destroy(pt_pool);
exit (0); exit (0);
} }