ex35 bits
This commit is contained in:
parent
fcf1c92608
commit
3fc7adac10
57
lcthw-remnants-2/ex35.c
Normal file
57
lcthw-remnants-2/ex35.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include <stdio.h>
|
||||
|
||||
typedef enum {
|
||||
TYPE_INT,
|
||||
TYPE_FLOAT,
|
||||
TYPE_STRING,
|
||||
} VariantType;
|
||||
|
||||
struct Variant {
|
||||
VariantType type;
|
||||
union {
|
||||
int as_integer;
|
||||
float as_float;
|
||||
char *as_string;
|
||||
} data;
|
||||
};
|
||||
|
||||
typedef struct Variant Variant;
|
||||
|
||||
void Variant_print(Variant *var)
|
||||
{
|
||||
switch(var->type) {
|
||||
case TYPE_INT:
|
||||
printf("INT: %d\n", var->data.as_integer);
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
printf("FLOAT: %f\n", var->data.as_float);
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
printf("STRING: %s\n", var->data.as_string);
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN TYPE: %d", var->type);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Variant a_int = {.type = TYPE_INT, .data.as_integer = 100};
|
||||
Variant a_float = {.type = TYPE_FLOAT, .data.as_float = 100.34};
|
||||
Variant a_string = {.type = TYPE_STRING, .data.as_string = "YO DUDE!"};
|
||||
|
||||
Variant_print(&a_int);
|
||||
Variant_print(&a_float);
|
||||
Variant_print(&a_string);
|
||||
|
||||
// here's how you access them
|
||||
a_int.data.as_integer = 200;
|
||||
a_float.data.as_float = 2.345;
|
||||
a_string.data.as_string = "Hi there.";
|
||||
|
||||
Variant_print(&a_int);
|
||||
Variant_print(&a_float);
|
||||
Variant_print(&a_string);
|
||||
|
||||
return 0;
|
||||
}
|
140
lcthw-remnants-2/liblcthw/src/lcthw/radixmap.c
Normal file
140
lcthw-remnants-2/liblcthw/src/lcthw/radixmap.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Based on code by Andre Reinald then heavily modified by Zed A. Shaw
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <lcthw/radixmap.h>
|
||||
#include <lcthw/dbg.h>
|
||||
|
||||
RadixMap *RadixMap_create(size_t max)
|
||||
{
|
||||
RadixMap *map = calloc(sizeof(RadixMap), 1);
|
||||
check_mem(map);
|
||||
|
||||
map->contents = calloc(sizeof(RMElement), max + 1);
|
||||
check_mem(map->contents);
|
||||
|
||||
map->temp = calloc(sizeof(RMElement), max + 1);
|
||||
check_mem(map->temp);
|
||||
|
||||
map->max = max;
|
||||
map->end = 0;
|
||||
|
||||
return map;
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RadixMap_destroy(RadixMap *map)
|
||||
{
|
||||
if(map) {
|
||||
free(map->contents);
|
||||
free(map->temp);
|
||||
free(map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define ByteOf(x,y) (((uint8_t *)x)[y])
|
||||
|
||||
static inline void radix_sort(short offset, uint64_t max, uint64_t *source, uint64_t *dest)
|
||||
{
|
||||
uint64_t count[256] = {0};
|
||||
uint64_t *cp = NULL;
|
||||
uint64_t *sp = NULL;
|
||||
uint64_t *end = NULL;
|
||||
uint64_t s = 0;
|
||||
uint64_t c = 0;
|
||||
|
||||
// count occurences of every byte value
|
||||
for(sp = source, end = source + max; sp < end; sp++) {
|
||||
count[ByteOf(sp, offset)]++;
|
||||
}
|
||||
|
||||
// transform count into index by summing elements and storing into same array
|
||||
for(s = 0, cp = count, end = count + 256; cp < end; cp++) {
|
||||
c = *cp;
|
||||
*cp = s;
|
||||
s += c;
|
||||
}
|
||||
|
||||
// fill dest with the right values in the right place
|
||||
for(sp = source, end = source + max; sp < end; sp++) {
|
||||
cp = count + ByteOf(sp, offset);
|
||||
dest[*cp] = *sp;
|
||||
++(*cp);
|
||||
}
|
||||
}
|
||||
|
||||
void RadixMap_sort(RadixMap *map)
|
||||
{
|
||||
uint64_t *source = &map->contents[0].raw;
|
||||
uint64_t *temp = &map->temp[0].raw;
|
||||
|
||||
radix_sort(0, map->end, source, temp);
|
||||
radix_sort(1, map->end, temp, source);
|
||||
radix_sort(2, map->end, source, temp);
|
||||
radix_sort(3, map->end, temp, source);
|
||||
}
|
||||
|
||||
RMElement *RadixMap_find(RadixMap *map, uint32_t to_find)
|
||||
{
|
||||
int low = 0;
|
||||
int high = map->end - 1;
|
||||
RMElement *data = map->contents;
|
||||
|
||||
while(low <= high) {
|
||||
int middle = low + (high - low)/2;
|
||||
uint32_t key = data[middle].data.key;
|
||||
|
||||
if(to_find < key) {
|
||||
high = middle - 1;
|
||||
} else if(to_find > key) {
|
||||
low = middle + 1;
|
||||
} else {
|
||||
return &data[middle];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value)
|
||||
{
|
||||
check(key < UINT32_MAX, "Key can't be equal to UINT32_MAX.");
|
||||
|
||||
RMElement element = {.data = {.key = key, .value = value}};
|
||||
check(map->end + 1 < map->max, "RadixMap is full.");
|
||||
|
||||
map->contents[map->end++] = element;
|
||||
|
||||
RadixMap_sort(map);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int RadixMap_delete(RadixMap *map, RMElement *el)
|
||||
{
|
||||
check(map->end > 0, "There is nothing to delete.");
|
||||
check(el != NULL, "Can't delete a NULL element.");
|
||||
|
||||
el->data.key = UINT32_MAX;
|
||||
|
||||
if(map->end > 1) {
|
||||
// don't bother resorting a map of 1 length
|
||||
RadixMap_sort(map);
|
||||
}
|
||||
|
||||
map->end--;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
35
lcthw-remnants-2/liblcthw/src/lcthw/radixmap.h
Normal file
35
lcthw-remnants-2/liblcthw/src/lcthw/radixmap.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef lcthw_radixmap_h
|
||||
#define lcthw_radixmap_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union RMElement {
|
||||
uint64_t raw;
|
||||
struct {
|
||||
uint32_t key;
|
||||
uint32_t value;
|
||||
} data;
|
||||
} RMElement;
|
||||
|
||||
typedef struct RadixMap {
|
||||
size_t max;
|
||||
size_t end;
|
||||
uint32_t counter;
|
||||
RMElement *contents;
|
||||
RMElement *temp;
|
||||
} RadixMap;
|
||||
|
||||
|
||||
RadixMap *RadixMap_create(size_t max);
|
||||
|
||||
void RadixMap_destroy(RadixMap *map);
|
||||
|
||||
void RadixMap_sort(RadixMap *map);
|
||||
|
||||
RMElement *RadixMap_find(RadixMap *map, uint32_t key);
|
||||
|
||||
int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value);
|
||||
|
||||
int RadixMap_delete(RadixMap *map, RMElement *el);
|
||||
|
||||
#endif
|
105
lcthw-remnants-2/liblcthw/tests/lcthw/radixmap_tests.c
Normal file
105
lcthw-remnants-2/liblcthw/tests/lcthw/radixmap_tests.c
Normal file
@ -0,0 +1,105 @@
|
||||
#include "../minunit.h"
|
||||
#include <stdint.h>
|
||||
#include <lcthw/radixmap.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
static int make_random(RadixMap *map)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
for(i = 0; i < map->max - 1; i++) {
|
||||
uint32_t key = (uint32_t)(rand() | (rand() << 16));
|
||||
check(RadixMap_add(map, key, i) == 0, "Failed to add key %u", key);
|
||||
}
|
||||
|
||||
return i;
|
||||
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_order(RadixMap *map)
|
||||
{
|
||||
RMElement d1, d2;
|
||||
unsigned int i = 0;
|
||||
|
||||
// only signal errors if any (should not be)
|
||||
for(i = 0; map->end > 0 && i < map->end-1; i++) {
|
||||
d1 = map->contents[i];
|
||||
d2 = map->contents[i+1];
|
||||
|
||||
if(d1.data.key > d2.data.key) {
|
||||
debug("FAIL:i=%u, key: %u, value: %u, equals max? %d\n", i, d1.data.key, d1.data.value,
|
||||
d2.data.key == UINT32_MAX);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_search(RadixMap *map)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
RMElement *d = NULL;
|
||||
RMElement *found = NULL;
|
||||
|
||||
for(i = map->end / 2; i < map->end; i++) {
|
||||
d = &map->contents[i];
|
||||
found = RadixMap_find(map, d->data.key);
|
||||
check(found != NULL, "Didn't find %u at %u.", d->data.key, i);
|
||||
check(found->data.key == d->data.key, "Got the wrong result: %p:%u looking for %u at %u",
|
||||
found, found->data.key, d->data.key, i);
|
||||
}
|
||||
|
||||
return 1;
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
// test for big number of elements
|
||||
static char *test_operations()
|
||||
{
|
||||
size_t N = 200;
|
||||
|
||||
RadixMap *map = RadixMap_create(N);
|
||||
mu_assert(map != NULL, "Failed to make the map.");
|
||||
mu_assert(make_random(map), "Didn't make a random fake radix map.");
|
||||
|
||||
RadixMap_sort(map);
|
||||
mu_assert(check_order(map), "Failed to properly sort the RadixMap.");
|
||||
|
||||
mu_assert(test_search(map), "Failed the search test.");
|
||||
mu_assert(check_order(map), "RadixMap didn't stay sorted after search.");
|
||||
|
||||
while(map->end > 0) {
|
||||
RMElement *el = RadixMap_find(map, map->contents[map->end / 2].data.key);
|
||||
mu_assert(el != NULL, "Should get a result.");
|
||||
|
||||
size_t old_end = map->end;
|
||||
|
||||
mu_assert(RadixMap_delete(map, el) == 0, "Didn't delete it.");
|
||||
mu_assert(old_end - 1 == map->end, "Wrong size after delete.");
|
||||
|
||||
// test that the end is now the old value, but uint32 max so it trails off
|
||||
mu_assert(check_order(map), "RadixMap didn't stay sorted after delete.");
|
||||
}
|
||||
|
||||
RadixMap_destroy(map);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *all_tests()
|
||||
{
|
||||
mu_suite_start();
|
||||
srand(time(NULL));
|
||||
|
||||
mu_run_test(test_operations);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_TESTS(all_tests);
|
Loading…
Reference in New Issue
Block a user