...
 
Commits (6)
......@@ -2,6 +2,6 @@ AM_CFLAGS = -Wall -Werror -pedantic
lib_LTLIBRARIES = libexcit.la
libexcit_la_SOURCES = excit.c composition.c prod.c cons.c repeat.c hilbert2d.c range.c tleaf.c
libexcit_la_SOURCES = excit.c composition.c prod.c cons.c repeat.c hilbert2d.c range.c index.c tleaf.c
include_HEADERS = excit.h
......@@ -151,12 +151,15 @@ static int cons_it_peek(const excit_t data, ssize_t *indexes)
int n = it->n;
if (indexes) {
circular_fifo_dump(&it->fifo, indexes);
err = excit_peek(it->it, indexes + dim * (n - 1));
if (err)
return err;
circular_fifo_dump(&it->fifo, indexes);
} else
err = excit_peek(it->it, NULL);
if (err)
return err;
return EXCIT_SUCCESS;
}
......@@ -167,9 +170,11 @@ static int cons_it_next(excit_t data, ssize_t *indexes)
int dim = it->it->dimension;
int n = it->n;
if (indexes) {
circular_fifo_dump(&it->fifo, indexes);
if (indexes) {
err = excit_next(it->it, indexes + dim * (n - 1));
if (err)
return err;
circular_fifo_dump(&it->fifo, indexes);
} else
err = excit_next(it->it, NULL);
if (err)
......
......@@ -7,6 +7,7 @@
#include "repeat.h"
#include "hilbert2d.h"
#include "range.h"
#include "index.h"
#include "tleaf.h"
#define CASE(val) case val: return #val; break
......@@ -14,6 +15,7 @@
const char *excit_type_name(enum excit_type_e type)
{
switch (type) {
CASE(EXCIT_INDEX);
CASE(EXCIT_RANGE);
CASE(EXCIT_CONS);
CASE(EXCIT_REPEAT);
......@@ -100,6 +102,9 @@ excit_t excit_alloc(enum excit_type_e type)
excit_t it = NULL;
switch (type) {
case EXCIT_INDEX:
ALLOC_EXCIT(index);
break;
case EXCIT_RANGE:
ALLOC_EXCIT(range);
break;
......
......@@ -31,6 +31,11 @@
enum excit_type_e {
/*!< Tag for invalid iterators */
EXCIT_INVALID,
/*!<
* Iterator over an array of indexes.
* If indexes are uniques, the iterator is made inversible (see excit_rank()).
*/
EXCIT_INDEX,
/*!<
* Iterator over a range of values.
* See function excit_range_init for further details on iterator
......@@ -383,6 +388,11 @@ int excit_skip(excit_t it);
*/
int excit_cyclic_next(excit_t it, ssize_t *indexes, int *looped);
/*
* Initialize an index iterator with a set of indexes.
*/
int excit_index_init(excit_t it, const ssize_t len, const ssize_t *index);
/*
* Initializes a range iterator to iterate from first to last (included) by step.
* "it": a range iterator.
......
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dev/excit.h"
#include "index.h"
static int comp_index_val(const void *a_ptr, const void *b_ptr)
{
const struct index_s *a = a_ptr;
const struct index_s *b = b_ptr;
if (a->sorted_value < b->sorted_value)
return -1;
if (a->sorted_value > b->sorted_value)
return 1;
return 0;
}
static struct index_s *make_index(const ssize_t len, const ssize_t *values)
{
ssize_t i;
struct index_s *index = malloc((len) * sizeof(*index));
if (index == NULL)
return NULL;
for (i = 0; i < len; i++) {
index[i].sorted_value = values[i];
index[i].sorted_index = i;
}
qsort(index, len, sizeof(*index), comp_index_val);
for (i = 0; i < len; i++)
index[i].value = values[i];
return index;
}
static inline struct index_s *copy_index(const ssize_t len,
const struct index_s *x)
{
struct index_s *index = malloc((len) * sizeof(*index));
if (index == NULL)
return NULL;
memcpy(index, x, (len) * sizeof(*x));
return index;
}
static inline struct index_s *search_index(const ssize_t val, const ssize_t len,
const struct index_s *x)
{
struct index_s key = { 0, val, 0 };
return bsearch(&key, x, len, sizeof(*x), comp_index_val);
}
static inline ssize_t search_index_pos(const ssize_t val, const ssize_t len,
const struct index_s *x)
{
struct index_s *found = search_index(val, len, x);
if (found == NULL)
return -1;
return found->sorted_index;
}
/******************************************************************************/
static int index_it_alloc(excit_t it)
{
it->dimension = 1;
struct index_it_s *data_it = it->data;
data_it->pos = 0;
data_it->len = 0;
data_it->inversible = 0;
data_it->index = NULL;
return EXCIT_SUCCESS;
}
static void index_it_free(excit_t it)
{
struct index_it_s *data_it = it->data;
if (data_it->index != NULL)
free(data_it->index);
}
static int index_it_size(const excit_t it, ssize_t *size)
{
struct index_it_s *data_it = it->data;
*size = data_it->len;
return EXCIT_SUCCESS;
}
static int index_it_rewind(excit_t it)
{
struct index_it_s *data_it = it->data;
data_it->pos = 0;
return EXCIT_SUCCESS;
}
static int index_it_copy(excit_t dst_it, const excit_t src_it)
{
int err = EXCIT_SUCCESS;
struct index_it_s *dst = dst_it->data;
struct index_it_s *src = src_it->data;
dst->pos = src->pos;
dst->len = src->len;
if (src->len == 0)
return EXCIT_SUCCESS;
if (src->index != NULL) {
dst->index = copy_index(src->len, src->index);
if (dst->index == NULL) {
err = -EXCIT_ENOMEM;
goto exit_with_values;
}
}
return EXCIT_SUCCESS;
exit_with_values:
free(dst->index);
dst->index = NULL;
return err;
}
static int index_it_pos(const excit_t it, ssize_t *value)
{
if (value == NULL)
return EXCIT_SUCCESS;
struct index_it_s *data_it = it->data;
*value = data_it->pos;
if (data_it->pos >= data_it->len)
return EXCIT_STOPIT;
return EXCIT_SUCCESS;
}
static int index_it_nth(const excit_t it, ssize_t n, ssize_t *indexes)
{
struct index_it_s *data_it = it->data;
if (n < 0 || n >= data_it->len)
return -EXCIT_EDOM;
if (indexes)
*indexes = data_it->index[n].value;
return EXCIT_SUCCESS;
}
static int index_it_peek(const excit_t it, ssize_t *value)
{
struct index_it_s *data_it = it->data;
if (data_it->pos >= data_it->len)
return EXCIT_STOPIT;
if (value)
*value = data_it->index[data_it->pos].value;
return EXCIT_SUCCESS;
}
static int index_it_next(excit_t it, ssize_t *indexes)
{
struct index_it_s *data_it = it->data;
if (data_it->pos >= data_it->len)
return EXCIT_STOPIT;
if (indexes)
*indexes = data_it->index[data_it->pos].value;
data_it->pos++;
return EXCIT_SUCCESS;
}
static int index_it_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
{
struct index_it_s *data_it = it->data;
if (!data_it->inversible)
return -EXCIT_ENOTSUP;
if (indexes == NULL)
return EXCIT_SUCCESS;
if (*indexes < data_it->index[0].sorted_value
|| *indexes >= data_it->index[data_it->len - 1].sorted_value)
return -EXCIT_EDOM;
if (n != NULL)
*n = search_index_pos(*indexes, data_it->len, data_it->index);
return EXCIT_SUCCESS;
}
int excit_index_init(excit_t it, const ssize_t len, const ssize_t *index)
{
ssize_t i;
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct index_it_s *data_it = it->data;
data_it->len = len;
data_it->index = make_index(len, index);
if (data_it->index == NULL)
return -EXCIT_ENOMEM;
// Check for duplicates
data_it->inversible = 1;
for (i = 1; i < len; i++)
if (data_it->index[i].sorted_value ==
data_it->index[i - 1].sorted_value) {
data_it->inversible = 0;
break;
}
return EXCIT_SUCCESS;
}
struct excit_func_table_s excit_index_func_table = {
index_it_alloc,
index_it_free,
index_it_copy,
index_it_next,
index_it_peek,
index_it_size,
index_it_rewind,
NULL,
index_it_nth,
index_it_rank,
index_it_pos
};
#ifndef EXCIT_INDEX_H
#define EXCIT_INDEX_H
struct index_s {
ssize_t value;
ssize_t sorted_value;
ssize_t sorted_index;
};
struct index_it_s {
ssize_t pos;
ssize_t len;
struct index_s *index;
int inversible;
};
extern struct excit_func_table_s excit_index_func_table;
#endif //EXCIT_INDEX_H
#include <string.h>
#include "dev/excit.h"
#include "prod.h"
......@@ -7,6 +8,7 @@ static int prod_it_alloc(excit_t data)
it->count = 0;
it->its = NULL;
it->buff = NULL;
return EXCIT_SUCCESS;
}
......@@ -18,6 +20,7 @@ static void prod_it_free(excit_t data)
for (ssize_t i = 0; i < it->count; i++)
excit_free(it->its[i]);
free(it->its);
free(it->buff);
}
}
......@@ -29,6 +32,12 @@ static int prod_it_copy(excit_t dst, const excit_t src)
result->its = (excit_t *) malloc(it->count * sizeof(excit_t));
if (!result->its)
return -EXCIT_ENOMEM;
result->buff = (ssize_t *) malloc(src->dimension * sizeof(ssize_t));
if (!result->buff){
free(result->its);
return -EXCIT_ENOMEM;
}
ssize_t i;
for (i = 0; i < it->count; i++) {
......@@ -184,11 +193,8 @@ static inline int prod_it_peeknext_helper(excit_t data, ssize_t *indexes,
return -EXCIT_EINVAL;
looped = next;
for (i = it->count - 1; i > 0; i--) {
if (indexes) {
offset -= it->its[i]->dimension;
next_indexes = indexes + offset;
} else
next_indexes = NULL;
offset -= it->its[i]->dimension;
next_indexes = it->buff + offset;
if (looped)
err = excit_cyclic_next(it->its[i], next_indexes,
&looped);
......@@ -197,17 +203,17 @@ static inline int prod_it_peeknext_helper(excit_t data, ssize_t *indexes,
if (err)
return err;
}
if (indexes) {
offset -= it->its[i]->dimension;
next_indexes = indexes + offset;
} else
next_indexes = NULL;
offset -= it->its[i]->dimension;
next_indexes = it->buff + offset;
if (looped)
err = excit_next(it->its[0], next_indexes);
else
err = excit_peek(it->its[0], next_indexes);
if (err)
return err;
if(indexes)
memcpy(indexes, it->buff, data->dimension * sizeof(ssize_t));
return EXCIT_SUCCESS;
}
......@@ -288,6 +294,8 @@ int excit_product_add_copy(excit_t it, excit_t added_it)
int excit_product_add(excit_t it, excit_t added_it)
{
int err = EXCIT_SUCCESS;
if (!it || it->type != EXCIT_PRODUCT || !it->data || !added_it)
return -EXCIT_EINVAL;
......@@ -295,14 +303,30 @@ int excit_product_add(excit_t it, excit_t added_it)
ssize_t mew_count = prod_it->count + 1;
excit_t *new_its =
(excit_t *) realloc(prod_it->its, mew_count * sizeof(excit_t));
(excit_t *) realloc(prod_it->its, mew_count * sizeof(excit_t));
if (!new_its)
return -EXCIT_ENOMEM;
ssize_t *new_buff =
realloc(prod_it->buff,
(added_it->dimension + it->dimension) * sizeof(ssize_t));
if (!new_buff){
err = -EXCIT_ENOMEM;
goto exit_with_new_its;
}
prod_it->its = new_its;
prod_it->buff = new_buff;
prod_it->its[prod_it->count] = added_it;
prod_it->count = mew_count;
it->dimension += added_it->dimension;
return EXCIT_SUCCESS;
exit_with_new_its:
free(new_its);
return err;
}
struct excit_func_table_s excit_prod_func_table = {
......
......@@ -6,6 +6,7 @@
struct prod_it_s {
ssize_t count;
ssize_t* buff;
excit_t *its;
};
......
......@@ -13,8 +13,6 @@ static int tleaf_init_with_it(excit_t it,
static int tleaf_it_alloc(excit_t it)
{
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
it->dimension = 1;
struct tleaf_it_s *data_it = it->data;
......@@ -123,7 +121,7 @@ static ssize_t tleaf_it_value(struct tleaf_it_s *it)
return val;
}
int tleaf_it_nth(const excit_t it, ssize_t n, ssize_t *indexes)
static int tleaf_it_nth(const excit_t it, ssize_t n, ssize_t *indexes)
{
struct tleaf_it_s *data_it = it->data;
int err = excit_nth(data_it->levels, n, data_it->buf);
......@@ -135,7 +133,7 @@ int tleaf_it_nth(const excit_t it, ssize_t n, ssize_t *indexes)
return EXCIT_SUCCESS;
}
int tleaf_it_peek(const excit_t it, ssize_t *value)
static int tleaf_it_peek(const excit_t it, ssize_t *value)
{
struct tleaf_it_s *data_it = it->data;
int err = excit_peek(data_it->levels, data_it->buf);
......@@ -147,7 +145,7 @@ int tleaf_it_peek(const excit_t it, ssize_t *value)
return EXCIT_SUCCESS;
}
int tleaf_it_next(excit_t it, ssize_t *indexes)
static int tleaf_it_next(excit_t it, ssize_t *indexes)
{
struct tleaf_it_s *data_it = it->data;
int err = excit_next(data_it->levels, data_it->buf);
......@@ -160,7 +158,7 @@ int tleaf_it_next(excit_t it, ssize_t *indexes)
return EXCIT_SUCCESS;
}
int tleaf_it_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
static int tleaf_it_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
{
ssize_t size;
int err;
......@@ -190,7 +188,7 @@ int tleaf_it_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
return EXCIT_SUCCESS;
}
int tleaf_it_make_levels(struct tleaf_it_s *tleaf, const excit_t *indexes,
static int tleaf_it_make_levels(struct tleaf_it_s *tleaf, const excit_t *indexes,
ssize_t *order, excit_t *levels)
{
ssize_t i;
......@@ -370,7 +368,7 @@ int excit_tleaf_init(excit_t it,
user_policy, NULL, NULL);
}
int tleaf_split_levels(excit_t levels, const ssize_t depth, const ssize_t n,
static int tleaf_split_levels(excit_t levels, const ssize_t depth, const ssize_t n,
excit_t **out)
{
*out = malloc(sizeof(**out) * n);
......
......@@ -6,6 +6,7 @@ AM_LDFLAGS = ../src/libexcit.la
LIBHSOURCES = excit_test.h
LIBCSOURCES = excit_test.c
excit_index_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_index.c
excit_range_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_range.c
excit_product_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_product.c
excit_repeat_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_repeat.c
......@@ -14,7 +15,7 @@ excit_tleaf_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_tleaf.c
excit_hilbert2d_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_hilbert2d.c
excit_composition_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_composition.c
UNIT_TESTS = excit_range excit_product excit_repeat excit_cons excit_hilbert2d excit_composition excit_tleaf
UNIT_TESTS = excit_range excit_product excit_repeat excit_cons excit_hilbert2d excit_composition excit_index excit_tleaf
# all tests
check_PROGRAMS = $(UNIT_TESTS)
......
#include <assert.h>
#include <stdlib.h>
#include <sys/time.h>
#include "excit.h"
#include "excit_test.h"
#define NTESTS 1
#define MAX_LEN 4096
#define MIN_LEN 16
static void rand_seed(void)
{
struct timeval tv;
unsigned int us;
gettimeofday(&tv, NULL);
us = (unsigned int)(1000000 * tv.tv_sec + tv.tv_usec);
srand(us);
}
static void shuffle(const ssize_t len, ssize_t *x)
{
ssize_t i, swap, rnd;
for (i = 0; i < len; i++) {
swap = x[i];
rnd = rand() % (len - i);
x[i] = x[i + rnd];
x[i + rnd] = swap;
}
}
static ssize_t *make_unique_index(const ssize_t len)
{
ssize_t i;
ssize_t *index = malloc(len * sizeof(*index));
assert(index != NULL);
for (i = 0; i < len; i++)
index[i] = i;
shuffle(len, index);
return index;
}
static ssize_t *make_index(const ssize_t len)
{
ssize_t i;
ssize_t *index = malloc(len * sizeof(*index));
assert(index != NULL);
for (i = 0; i < len; i++)
index[i] = rand() % len;
return index;
}
void run_tests(const ssize_t len, const ssize_t *index)
{
ssize_t i = 0;
excit_t it;
while (synthetic_tests[i]) {
it = excit_alloc(EXCIT_INDEX);
assert(it != NULL);
assert(excit_index_init(it, len, index) == EXCIT_SUCCESS);
synthetic_tests[i] (it);
excit_free(it);
i++;
}
}
int main(int argc, char *argv[])
{
ssize_t n = NTESTS;
rand_seed();
while (n--) {
ssize_t len = MIN_LEN + rand() % (MAX_LEN - MIN_LEN);
ssize_t *uind = make_unique_index(len);
run_tests(len, uind);
free(uind);
ssize_t *ind = make_index(len);
run_tests(len, ind);
free(ind);
}
return 0;
}
......@@ -107,11 +107,12 @@ void test_peek(excit_t it1)
excit_dimension_test(it1, &dim1);
ssize_t *indexes1, *indexes2;
ssize_t *indexes1, *indexes2, *indexes3;
ssize_t buff_dim = dim1 * sizeof(ssize_t);
indexes1 = (ssize_t *) malloc(buff_dim);
indexes2 = (ssize_t *) malloc(buff_dim);
indexes3 = (ssize_t *) malloc(buff_dim);
while (excit_next(it1, indexes1) == ES) {
assert(excit_peek(it2, indexes2) == ES);
......@@ -119,11 +120,17 @@ void test_peek(excit_t it1)
assert(excit_next(it2, indexes2) == ES);
assert(memcmp(indexes1, indexes2, buff_dim) == 0);
}
memset(indexes2, 1, buff_dim);
memset(indexes3, 1, buff_dim);
assert(excit_peek(it2, indexes2) == EXCIT_STOPIT);
assert(! memcmp(indexes2, indexes3, buff_dim));
assert(excit_next(it2, indexes2) == EXCIT_STOPIT);
assert(! memcmp(indexes2, indexes3, buff_dim));
free(indexes1);
free(indexes2);
free(indexes3);
excit_free(it2);
}
......