Initial commit
This commit is contained in:
168
generator/Blocks.h
Normal file
168
generator/Blocks.h
Normal file
@@ -0,0 +1,168 @@
|
||||
#ifndef BLOCKS_H
|
||||
#define BLOCKS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "ValueList.h"
|
||||
|
||||
struct BlockLevel {
|
||||
long* data;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
struct ValueList* list;
|
||||
};
|
||||
|
||||
struct Blocks {
|
||||
struct BlockLevel* levels;
|
||||
size_t depth;
|
||||
};
|
||||
|
||||
static int ilog2(unsigned long value) {
|
||||
int result = -1;
|
||||
while (value) value >>= 1, result++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static long blockInsert(struct Blocks* blocks, long value, size_t depth) {
|
||||
struct BlockLevel* level = blocks->levels + depth;
|
||||
|
||||
if (blocks->depth - 1 != depth) {
|
||||
if ((value = blockInsert(blocks, value, depth + 1)) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
level->data[level->size++] = value;
|
||||
if (level->size >= level->capacity) {
|
||||
level->size = 0;
|
||||
|
||||
if (depth == 0 || (value = valueListFind(level->list, level->data, level->capacity)) == -1) {
|
||||
value = valueListIntern(&level->list, level->data, level->capacity);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long blockFindR(struct Blocks* blocks, long value, long offset, size_t depth) {
|
||||
struct BlockLevel* level = &blocks->levels[depth];
|
||||
struct ValueList* current;
|
||||
size_t i, bits = 0;
|
||||
|
||||
for (i = depth + 1; i < blocks->depth; i++) {
|
||||
bits += ilog2(blocks->levels[i].capacity);
|
||||
}
|
||||
|
||||
current = level->list;
|
||||
while (offset--) current = current->next;
|
||||
|
||||
offset = (value >> bits) & ((unsigned long)level->capacity - 1);
|
||||
offset = current->data[offset];
|
||||
|
||||
if (depth != blocks->depth - 1)
|
||||
return blockFindR(blocks, value, offset, depth + 1);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static long blockFind(struct Blocks* blocks, long value) {
|
||||
size_t i, bits = 0;
|
||||
long offset;
|
||||
|
||||
for (i = 0; i < blocks->depth; i++) {
|
||||
bits += ilog2(blocks->levels[i].capacity);
|
||||
}
|
||||
|
||||
offset = value >> bits;
|
||||
return blockFindR(blocks, value, offset, 0);
|
||||
}
|
||||
|
||||
static void blockInit(struct Blocks* blocks, size_t depth, ...) {
|
||||
va_list args;
|
||||
|
||||
blocks->depth = 0;
|
||||
if (!(blocks->levels = malloc(sizeof(struct BlockLevel) * depth)))
|
||||
abort();
|
||||
|
||||
va_start(args, depth);
|
||||
|
||||
while (blocks->depth < depth) {
|
||||
struct BlockLevel* level = &blocks->levels[blocks->depth];
|
||||
|
||||
level->list = NULL;
|
||||
level->size = 0;
|
||||
level->capacity = va_arg(args, int);
|
||||
if (!(level->data = malloc(level->capacity * sizeof(long))))
|
||||
abort();
|
||||
blocks->depth++;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void blockDump(struct Blocks* blocks, size_t depth, FILE* out,
|
||||
const char* name, const char* type) {
|
||||
struct BlockLevel* level = &blocks->levels[depth];
|
||||
struct ValueList* current;
|
||||
size_t i, j, printed = 0;
|
||||
|
||||
fprintf(out, "static const %s %s[] = {\n ", type, name);
|
||||
current = level->list;
|
||||
for (current = level->list; current; current = current->next) {
|
||||
for (i = 0; i < level->capacity; i++) {
|
||||
if (printed++ >= 15) {
|
||||
fprintf(out, "\n ");
|
||||
printed = 1;
|
||||
}
|
||||
fprintf(out, "%ld, ", current->data[i]);
|
||||
}
|
||||
}
|
||||
fprintf(out, "\n};\n\n");
|
||||
}
|
||||
|
||||
static void blockAccess(struct Blocks* blocks, size_t depth, FILE* out,
|
||||
const char* var, const char* arg, const char* name) {
|
||||
struct BlockLevel* level = &blocks->levels[depth];
|
||||
long i, bits = 0, offset, mask;
|
||||
|
||||
for (i = depth + 1; i < blocks->depth; i++) {
|
||||
bits += ilog2(blocks->levels[i].capacity);
|
||||
}
|
||||
|
||||
offset = ilog2(blocks->levels[depth].capacity);
|
||||
mask = level->capacity - 1;
|
||||
|
||||
fprintf(out, " %s = (long)%s", var, name);
|
||||
if (depth) {
|
||||
if (offset) {
|
||||
fprintf(out, "[(%s<<%ld)", var, offset);
|
||||
} else {
|
||||
fprintf(out, "[%s", var);
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf(out, "[");
|
||||
|
||||
if (mask || !depth) {
|
||||
if (depth)
|
||||
fprintf(out, "+");
|
||||
|
||||
if (mask)
|
||||
fprintf(out, "(");
|
||||
|
||||
if (bits)
|
||||
fprintf(out, "(%s>>%ld)", arg, (long)bits);
|
||||
else
|
||||
fprintf(out, "%s", arg);
|
||||
|
||||
if (depth)
|
||||
fprintf(out, "&%ld", mask);
|
||||
|
||||
if (mask)
|
||||
fprintf(out, ")");
|
||||
}
|
||||
|
||||
fprintf(out, "];\n");
|
||||
}
|
||||
|
||||
#endif /* BLOCKS_H */
|
||||
Reference in New Issue
Block a user