Commit a97d5c7c authored by Nicolas Denoyelle's avatar Nicolas Denoyelle

split files and add tleaf iterator

parent 4e08270a
......@@ -2,6 +2,6 @@ AM_CFLAGS = -Wall -Werror -pedantic
lib_LTLIBRARIES = libexcit.la
libexcit_la_SOURCES = excit.c excit.h
libexcit_la_SOURCES = excit.c tleaf.c range.c slice.c repeat.c prod.c cons.c hilbert2d.c
include_HEADERS = excit.h
#include "cons.h"
#define EXCIT_DATA(data, it) \
if(data == NULL) { return EXCIT_EINVAL; } \
do{ \
int err = excit_get_data(data, (void**)(&it)); \
if(err != EXCIT_SUCCESS) { return err; } \
} while(0); \
if(it == NULL){ return EXCIT_EINVAL; }
static void circular_fifo_add(struct circular_fifo_s *fifo, ssize_t elem)
{
if (fifo->size == fifo->length) {
fifo->start = (fifo->start + 1) % fifo->length;
fifo->end = (fifo->end + 1) % fifo->length;
} else {
fifo->end = (fifo->end + 1) % fifo->length;
fifo->size++;
}
fifo->buffer[fifo->end] = elem;
}
static void circular_fifo_dump(const struct circular_fifo_s *fifo,
ssize_t *vals)
{
ssize_t i;
ssize_t j;
for (i = 0, j = fifo->start; i < fifo->size; i++) {
vals[i] = fifo->buffer[j];
j = (j + 1) % fifo->length;
}
}
struct excit_func_table_s excit_cons_func_table = {
cons_it_alloc,
cons_it_free,
cons_it_copy,
cons_it_next,
cons_it_peek,
cons_it_size,
cons_it_rewind,
cons_it_split,
cons_it_nth,
cons_it_rank,
cons_it_pos
};
int cons_it_alloc(excit_t data)
{
struct cons_it_s *it;
EXCIT_DATA(data, it);
it->it = NULL;
it->n = 0;
it->fifo.length = 0;
it->fifo.start = 0;
it->fifo.end = -1;
it->fifo.size = 0;
it->fifo.buffer = NULL;
return EXCIT_SUCCESS;
}
void cons_it_free(excit_t data)
{
struct cons_it_s *it;
if(data == NULL) { return ; }
int err = excit_get_data(data, (void**)(&it));
if(err != EXCIT_SUCCESS) { return; }
if(it == NULL){ return; }
excit_free(it->it);
free(it->fifo.buffer);
}
int cons_it_copy(excit_t ddst, const excit_t dsrc)
{
struct cons_it_s *dst;
EXCIT_DATA(ddst, dst);
const struct cons_it_s *src;
EXCIT_DATA(dsrc, src);
excit_t copy = excit_dup(src->it);
if (!copy)
return -EXCIT_EINVAL;
dst->it = copy;
dst->n = src->n;
dst->fifo.length = src->fifo.length;
dst->fifo.start = src->fifo.start;
dst->fifo.end = src->fifo.end;
dst->fifo.size = src->fifo.size;
dst->fifo.buffer =
(ssize_t *) malloc(src->fifo.length * sizeof(ssize_t));
if (!dst->fifo.buffer) {
excit_free(copy);
return -EXCIT_ENOMEM;
}
for (int i = 0; i < dst->fifo.length; i++)
dst->fifo.buffer[i] = src->fifo.buffer[i];
return EXCIT_SUCCESS;
}
int cons_it_size(const excit_t data, ssize_t *size)
{
const struct cons_it_s *it;
EXCIT_DATA(data, it);
ssize_t tmp_size = 0;
int err = excit_size(it->it, &tmp_size);
if (err)
return err;
*size = tmp_size - (it->n - 1);
return EXCIT_SUCCESS;
}
int cons_it_split(const excit_t data, ssize_t n, excit_t *results)
{
ssize_t size;
int err = cons_it_size(data, &size);
if (err)
return err;
if (size < n)
return -EXCIT_EDOM;
if (!results)
return EXCIT_SUCCESS;
excit_t range = excit_alloc(EXCIT_RANGE);
if (!range)
return -EXCIT_ENOMEM;
err = excit_range_init(range, 0, size - 1, 1);
if (err)
goto error1;
err = excit_split(range, n, results);
if (err)
goto error1;
int i;
for (i = 0; i < n; i++) {
excit_t tmp, tmp2;
tmp = excit_dup(data);
if (!tmp)
goto error2;
tmp2 = results[i];
results[i] = excit_alloc(EXCIT_SLICE);
if (!results[i]) {
excit_free(tmp2);
goto error2;
}
err = excit_slice_init(results[i], tmp, tmp2);
if (err) {
excit_free(tmp2);
goto error2;
}
}
excit_free(range);
return EXCIT_SUCCESS;
error2:
for (; i >= 0; i--)
excit_free(results[i]);
error1:
excit_free(range);
return err;
}
int cons_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
{
ssize_t size;
int err = cons_it_size(data, &size);
if (err)
return err;
if (n < 0 || n >= size)
return -EXCIT_EDOM;
const struct cons_it_s *it;
EXCIT_DATA(data, it);
int dim = excit_get_dimension(it->it);
if (indexes) {
for (int i = 0; i < it->n; i++) {
err = excit_nth(it->it, n + i, indexes + dim * i);
if (err)
return err;
}
}
return EXCIT_SUCCESS;
}
int cons_it_rank(const excit_t data, const ssize_t *indexes, ssize_t *n)
{
const struct cons_it_s *it;
EXCIT_DATA(data, it);
ssize_t inner_n, inner_n_tmp;
int err = excit_rank(it->it, indexes, &inner_n);
if (err)
return err;
int dim = excit_get_dimension(it->it);
for (int i = 1; i < it->n; i++) {
err = excit_rank(it->it, indexes + dim * i, &inner_n_tmp);
if (err)
return err;
if (inner_n_tmp != inner_n + 1)
return -EXCIT_EINVAL;
inner_n = inner_n_tmp;
}
if (n)
*n = inner_n - (it->n - 1);
return EXCIT_SUCCESS;
}
int cons_it_pos(const excit_t data, ssize_t *n)
{
ssize_t inner_n;
const struct cons_it_s *it;
EXCIT_DATA(data, it);
int err = excit_pos(it->it, &inner_n);
if (err)
return err;
if (n)
*n = inner_n - (it->n - 1);
return EXCIT_SUCCESS;
}
int cons_it_peek(const excit_t data, ssize_t *indexes)
{
const struct cons_it_s *it;
EXCIT_DATA(data, it);
int err;
int dim = excit_get_dimension(it->it);
int n = it->n;
if (indexes) {
circular_fifo_dump(&it->fifo, indexes);
err = excit_peek(it->it, indexes + dim * (n - 1));
} else
err = excit_peek(it->it, NULL);
if (err)
return err;
return EXCIT_SUCCESS;
}
int cons_it_next(excit_t data, ssize_t *indexes)
{
struct cons_it_s *it;
EXCIT_DATA(data, it);
int err;
int dim = excit_get_dimension(it->it);
int n = it->n;
if (indexes) {
circular_fifo_dump(&it->fifo, indexes);
err = excit_next(it->it, indexes + dim * (n - 1));
} else
err = excit_next(it->it, NULL);
if (err)
return err;
if (indexes)
for (int i = dim * (n - 1); i < dim * n; i++)
circular_fifo_add(&it->fifo, indexes[i]);
return EXCIT_SUCCESS;
}
int cons_it_rewind(excit_t data)
{
struct cons_it_s *it;
EXCIT_DATA(data, it);
int err = excit_rewind(it->it);
if (err)
return err;
it->fifo.start = 0;
it->fifo.end = -1;
it->fifo.size = 0;
for (int i = 0; i < it->n - 1; i++) {
int err;
err =
excit_next(it->it, it->fifo.buffer + excit_get_dimension(it->it) * i);
if (err)
return err;
it->fifo.size += excit_get_dimension(it->it);
it->fifo.end += excit_get_dimension(it->it);
}
return EXCIT_SUCCESS;
}
int excit_cons_init(excit_t it, excit_t src, ssize_t n)
{
ssize_t src_size;
int err;
if (!it || !src || n <= 0)
return -EXCIT_EINVAL;
err = excit_size(src, &src_size);
if (err)
return err;
if (src_size < n)
return -EXCIT_EINVAL;
struct cons_it_s *cons_it;
EXCIT_DATA(it, cons_it);
free(cons_it->fifo.buffer);
excit_free(cons_it->it);
excit_set_dimension(it, excit_get_dimension(src) * n);
cons_it->it = src;
cons_it->n = n;
cons_it->fifo.length = excit_get_dimension(src) * (n - 1);
cons_it->fifo.buffer =
(ssize_t *) malloc(cons_it->fifo.length * sizeof(ssize_t));
if (!cons_it->fifo.buffer)
return -EXCIT_ENOMEM;
err = cons_it_rewind(it);
if (err) {
free(cons_it->fifo.buffer);
return err;
}
return EXCIT_SUCCESS;
}
#ifndef CONS_H
#define CONS_H
#include "excit.h"
struct circular_fifo_s {
ssize_t length;
ssize_t start;
ssize_t end;
ssize_t size;
ssize_t *buffer;
};
struct cons_it_s {
excit_t it;
ssize_t n;
struct circular_fifo_s fifo;
};
int cons_it_alloc(excit_t data);
void cons_it_free(excit_t data);
int cons_it_copy(excit_t ddst, const excit_t dsrc);
int cons_it_size(const excit_t data, ssize_t *size);
int cons_it_split(const excit_t data, ssize_t n, excit_t *results);
int cons_it_nth(const excit_t data, ssize_t n, ssize_t *indexes);
int cons_it_rank(const excit_t data, const ssize_t *indexes, ssize_t *n);
int cons_it_pos(const excit_t data, ssize_t *n);
int cons_it_peek(const excit_t data, ssize_t *indexes);
int cons_it_next(excit_t data, ssize_t *indexes);
int cons_it_rewind(excit_t data);
extern struct excit_func_table_s excit_cons_func_table;
#endif
#include <stdlib.h>
#include <excit.h>
#include "excit.h"
#include "slice.h"
#include "range.h"
#include "repeat.h"
#include "prod.h"
#include "cons.h"
#include "hilbert2d.h"
#include "tleaf.h"
#define CASE(val) case val: return #val; break;
const char * excit_type_name(enum excit_type_e type)
{
switch (type) {
CASE(EXCIT_RANGE)
CASE(EXCIT_CONS)
CASE(EXCIT_REPEAT)
CASE(EXCIT_HILBERT2D)
CASE(EXCIT_PRODUCT)
CASE(EXCIT_SLICE)
CASE(EXCIT_USER)
CASE(EXCIT_TYPE_MAX)
default:
return NULL;
}
switch (type) {
CASE(EXCIT_RANGE)
CASE(EXCIT_CONS)
CASE(EXCIT_REPEAT)
CASE(EXCIT_HILBERT2D)
CASE(EXCIT_PRODUCT)
CASE(EXCIT_SLICE)
CASE(EXCIT_TLEAF)
CASE(EXCIT_USER)
CASE(EXCIT_TYPE_MAX)
default:
return NULL;
}
}
const char * excit_error_name(enum excit_error_e err)
{
switch (err) {
CASE(EXCIT_SUCCESS)
CASE(EXCIT_STOPIT)
CASE(EXCIT_ENOMEM)
CASE(EXCIT_EINVAL)
CASE(EXCIT_EDOM)
CASE(EXCIT_ENOTSUP)
CASE(EXCIT_ERROR_MAX)
default:
return NULL;
}
switch (err) {
CASE(EXCIT_SUCCESS)
CASE(EXCIT_STOPIT)
CASE(EXCIT_ENOMEM)
CASE(EXCIT_EINVAL)
CASE(EXCIT_EDOM)
CASE(EXCIT_ENOTSUP)
CASE(EXCIT_ERROR_MAX)
default:
return NULL;
}
}
#undef CASE
struct excit_s {
struct excit_func_table_s *func_table;
ssize_t dimension;
enum excit_type_e type;
void *data;
struct excit_func_table_s *func_table;
ssize_t dimension;
enum excit_type_e type;
void *data;
};
int excit_set_dimension(excit_t it, ssize_t dimension)
{
if (!it)
return -EXCIT_EINVAL;
if (it->type != EXCIT_USER)
return -EXCIT_ENOTSUP;
it->dimension = dimension;
return EXCIT_SUCCESS;
if (!it)
return -EXCIT_EINVAL;
/* if (it->type != EXCIT_USER) */
/* return -EXCIT_ENOTSUP; */
it->dimension = dimension;
return EXCIT_SUCCESS;
}
int excit_get_data(excit_t it, void **data)
{
if (!it)
return -EXCIT_EINVAL;
if (it->type != EXCIT_USER)
return -EXCIT_ENOTSUP;
*data = it->data;
return EXCIT_SUCCESS;
}
int excit_set_func_table(excit_t it, struct excit_func_table_s *func_table)
{
if (!it)
return -EXCIT_EINVAL;
it->func_table = func_table;
return EXCIT_SUCCESS;
}
int excit_get_func_table(excit_t it, struct excit_func_table_s **func_table)
{
if (!it)
return -EXCIT_EINVAL;
*func_table = it->func_table;
return EXCIT_SUCCESS;
}
/*--------------------------------------------------------------------*/
struct slice_it_s {
excit_t src;
excit_t indexer;
};
static int slice_it_alloc(excit_t data)
{
struct slice_it_s *it = (struct slice_it_s *) data->data;
it->src = NULL;
it->indexer = NULL;
return EXCIT_SUCCESS;
}
static void slice_it_free(excit_t data)
{
struct slice_it_s *it = (struct slice_it_s *) data->data;
excit_free(it->src);
excit_free(it->indexer);
}
static int slice_it_copy(excit_t dst, const excit_t src)
{
const struct slice_it_s *it = (const struct slice_it_s *) src->data;
struct slice_it_s *result = (struct slice_it_s *) dst->data;
result->src = excit_dup(it->src);
if (!result->src)
return -EXCIT_ENOMEM;
result->indexer = excit_dup(it->indexer);
if (!result->indexer) {
excit_free(it->src);
return -EXCIT_ENOMEM;
}
return EXCIT_SUCCESS;
}
static int slice_it_next(excit_t data, ssize_t *indexes)
{
struct slice_it_s *it = (struct slice_it_s *) data->data;
ssize_t n;
int err = excit_next(it->indexer, &n);
if (err)
return err;
return excit_nth(it->src, n, indexes);
}
static int slice_it_peek(const excit_t data, ssize_t *indexes)
{
const struct slice_it_s *it = (const struct slice_it_s *)data->data;
ssize_t n;
int err = excit_peek(it->indexer, &n);
if (err)
return err;
return excit_nth(it->src, n, indexes);
}
static int slice_it_size(const excit_t data, ssize_t *size)
{
const struct slice_it_s *it = (const struct slice_it_s *)data->data;
return excit_size(it->indexer, size);
}
static int slice_it_rewind(excit_t data)
{
struct slice_it_s *it = (struct slice_it_s *) data->data;
return excit_rewind(it->indexer);
}
static int slice_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
{
const struct slice_it_s *it = (const struct slice_it_s *)data->data;
ssize_t p;
int err = excit_nth(it->indexer, n, &p);
if (err)
return err;
return excit_nth(it->src, p, indexes);
}
static int slice_it_rank(const excit_t data, const ssize_t *indexes, ssize_t *n)
{
const struct slice_it_s *it = (const struct slice_it_s *)data->data;
ssize_t inner_n;
int err = excit_rank(it->src, indexes, &inner_n);
if (err)
return err;
return excit_rank(it->indexer, &inner_n, n);
}
static int slice_it_pos(const excit_t data, ssize_t *n)
{
const struct slice_it_s *it = (const struct slice_it_s *)data->data;
return excit_pos(it->indexer, n);
}
static int slice_it_split(const excit_t data, ssize_t n, excit_t *results)
{
const struct slice_it_s *it = (const struct slice_it_s *)data->data;
int err = excit_split(it->indexer, n, results);
if (err)
return err;
if (!results)
return EXCIT_SUCCESS;
for (int i = 0; i < n; i++) {
excit_t tmp;
excit_t tmp2;
tmp = results[i];
results[i] = excit_alloc(EXCIT_SLICE);
if (!results[i]) {
excit_free(tmp);
err = -EXCIT_ENOMEM;
goto error;
}
tmp2 = excit_dup(it->src);
if (!tmp2) {
excit_free(tmp);
err = -EXCIT_ENOMEM;
goto error;
}
err = excit_slice_init(results[i], tmp, tmp2);
if (err) {
excit_free(tmp);
excit_free(tmp2);
goto error;
}
}
return EXCIT_SUCCESS;
error:
for (int i = 0; i < n; i++)
excit_free(results[i]);
return err;
}
static struct excit_func_table_s excit_slice_func_table = {
slice_it_alloc,
slice_it_free,
slice_it_copy,
slice_it_next,
slice_it_peek,
slice_it_size,
slice_it_rewind,
slice_it_split,
slice_it_nth,
slice_it_rank,
slice_it_pos
};
int excit_slice_init(excit_t it, excit_t src, excit_t indexer)
{
if (!it || it->type != EXCIT_SLICE || !src || !indexer
|| indexer->dimension != 1)
return -EXCIT_EINVAL;
struct slice_it_s *slice_it = (struct slice_it_s *) it->data;
ssize_t size_src;
ssize_t size_indexer;
int err = excit_size(src, &size_src);
if (err)
return err;
err = excit_size(indexer, &size_indexer);
if (err)
return err;
if (size_indexer > size_src)
return -EXCIT_EDOM;
slice_it->src = src;
slice_it->indexer = indexer;
it->dimension = src->dimension;
return EXCIT_SUCCESS;
}
/*--------------------------------------------------------------------*/
struct prod_it_s {
ssize_t count;
excit_t *its;
};
static int prod_it_alloc(excit_t data)
{
struct prod_it_s *it = (struct prod_it_s *) data->data;
it->count = 0;
it->its = NULL;
return EXCIT_SUCCESS;
}
static void prod_it_free(excit_t data)
{
struct prod_it_s *it = (struct prod_it_s *) data->data;
if (it->its) {
for (ssize_t i = 0; i < it->count; i++)
excit_free(it->its[i]);
free(it->its);
}
}
static int prod_it_copy(excit_t dst, const excit_t src)
{
const struct prod_it_s *it = (const struct prod_it_s *)src->data;
struct prod_it_s *result = (struct prod_it_s *) dst->data;
result->its = (excit_t *) malloc(it->count * sizeof(excit_t));
if (!result->its)
return -EXCIT_ENOMEM;
ssize_t i;
for (i = 0; i < it->count; i++) {
result->its[i] = excit_dup(it->its[i]);
if (!result->its[i]) {
i--;
goto error;
}
}
result->count = it->count;
return EXCIT_SUCCESS;
error:
while (i >= 0) {
free(result->its[i]);
i--;
}
free(result->its);
return -EXCIT_ENOMEM;
}
static int prod_it_rewind(excit_t data)
{
struct prod_it_s *it = (struct prod_it_s *) data->data;
for (ssize_t i = 0; i < it->count; i++) {
int err = excit_rewind(it->its[i]);
if (err)
return err;
}
return EXCIT_SUCCESS;