Commit 5be95032 authored by Nicolas Denoyelle's avatar Nicolas Denoyelle

working tleaf

parent b8a35329
......@@ -2,6 +2,6 @@ AM_CFLAGS = -Wall -Werror -pedantic
lib_LTLIBRARIES = libexcit.la
libexcit_la_SOURCES = excit.c slice.c prod.c cons.c repeat.c hilbert2d.c range.c
libexcit_la_SOURCES = excit.c slice.c prod.c cons.c repeat.c hilbert2d.c range.c tleaf.c
include_HEADERS = excit.h
......@@ -300,3 +300,4 @@ struct excit_func_table_s excit_cons_func_table = {
cons_it_rank,
cons_it_pos
};
......@@ -7,6 +7,7 @@
#include "repeat.h"
#include "hilbert2d.h"
#include "range.h"
#include "tleaf.h"
#define CASE(val) case val: return #val; break
......@@ -47,8 +48,8 @@ int excit_set_dimension(excit_t it, ssize_t dimension)
{
if (!it)
return -EXCIT_EINVAL;
/* if (it->type != EXCIT_USER) */
/* return -EXCIT_ENOTSUP; */
if (it->type != EXCIT_USER)
return -EXCIT_ENOTSUP;
it->dimension = dimension;
return EXCIT_SUCCESS;
}
......
......@@ -15,6 +15,7 @@ enum excit_type_e {
EXCIT_HILBERT2D, /*!< Hilbert space filing curve */
EXCIT_PRODUCT, /*!< Iterator over the catesian product of iterators */
EXCIT_SLICE, /*!< Iterator using another iterator to index a third */
EXCIT_TLEAF, /*!< Iterator on tree leaves with all leaves at same depth */
EXCIT_USER, /*!< User-defined iterator */
EXCIT_TYPE_MAX /*!< Guard */
};
......@@ -396,8 +397,9 @@ int excit_slice_init(excit_t it, excit_t src, excit_t indexer);
enum tleaf_it_policy_e {
ROUND_ROBIN, /* Iterate on tree leaves in a round-robin fashion */
SCATTER /* Iterate on tree leaves such spreading as much as possible */
TLEAF_POLICY_ROUND_ROBIN, /* Iterate on tree leaves in a round-robin fashion */
TLEAF_POLICY_SCATTER, /* Iterate on tree leaves such spreading as much as possible */
TLEAF_POLICY_USER /* Policy is a user defined policy */
};
......@@ -405,11 +407,19 @@ enum tleaf_it_policy_e {
* Initialize a tleaf iterator by giving its depth, levels arity and iteration policy.
* "it": a tleaf iterator
* "depth": the total number of levels of the tree, including leaves
* "arity": For each level, the number of children attached to a node. Leaves have no children, hence last level arity must be 0.
* "iter_policy": A policy for iteration on leaves.
* "offset": Offset on output. Usually 0.
* "stride": Stride applied at eache level for indexing. Usually 1. If NULLm it is set to one at each level..
*/
int excit_tleaf_init(excit_t it, const ssize_t depth, const ssize_t* arity, const enum tleaf_it_policy_e iter_policy, const ssize_t offset, const_ssize_t* strides);
* "arity": An array of size (depth-1). For each level, the number of children attached to a node. Leaves have no children, hence last level arity is ignored.
* "policy": A policy for iteration on leaves.
* "user_policy": If policy is TLEAF_POLICY_USER, then this argument must be an array of size (depth-1) providing the order (from 0 to (depth-2)) in wich levels are walked
* when resolving indexes. Underneath, a product iterator of range iterator returns indexes on last levels upon iterator queries. This set of indexes is then
* computed to a single leaf index. For instance TLEAF_POLICY_ROUND_ROBIN is obtained from walking from leaves to root whereas TLEAF_POLICY_SCATTER is
* obtained from walking from root to leaves.
*/
int excit_tleaf_init(excit_t it,
const ssize_t depth,
const ssize_t *arities,
const enum tleaf_it_policy_e policy,
const ssize_t *user_policy);
int tleaf_it_split_at_level(const excit_t it, const ssize_t level, const ssize_t n, excit_t *out);
#endif
......@@ -11,3 +11,4 @@ struct hilbert2d_it_s {
extern struct excit_func_table_s excit_hilbert2d_func_table;
#endif //EXCIT_HILBERT2D_H
......@@ -12,3 +12,4 @@ struct prod_it_s {
extern struct excit_func_table_s excit_prod_func_table;
#endif //EXCIT_PROD_H
......@@ -171,7 +171,6 @@ error:
for (; i < n; i++)
excit_free(results[i]);
return err;
>>>>>>> master
}
int excit_range_init(excit_t it, ssize_t first, ssize_t last, ssize_t step)
......@@ -182,7 +181,6 @@ int excit_range_init(excit_t it, ssize_t first, ssize_t last, ssize_t step)
return -EXCIT_EINVAL;
it->dimension = 1;
range_it = (struct range_it_s *)it->data;
>>>>>>> master
range_it->first = first;
range_it->v = first;
range_it->last = last;
......@@ -203,3 +201,4 @@ struct excit_func_table_s excit_range_func_table = {
range_it_rank,
range_it_pos
};
......@@ -13,3 +13,4 @@ struct range_it_s {
extern struct excit_func_table_s excit_range_func_table;
#endif //EXCIT_RANGE_H
#include <stdlib.h>
#include <stdio.h>
#include "dev/excit.h"
#include "tleaf.h"
typedef struct tleaf_it_s* tleaf_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;
struct excit_func_table_s excit_tleaf_func_table = {
tleaf_it_alloc,
tleaf_it_free,
tleaf_it_copy,
tleaf_it_next,
tleaf_it_peek,
tleaf_it_size,
tleaf_it_rewind,
tleaf_it_split,
tleaf_it_nth,
tleaf_it_rank,
tleaf_it_pos
};
data_it->depth = 0;
data_it->arities = NULL;
data_it->order = NULL;
data_it->buf = NULL;
data_it->levels = NULL;
return EXCIT_SUCCESS;
}
#define EXCIT_DATA(it, data_it) \
if(it == NULL) { return EXCIT_EINVAL; } \
do{ \
int err = excit_get_data(it, (void**)(&data_it)); \
if(err != EXCIT_SUCCESS) { \
return err; \
} \
} while(0); \
if(data_it == NULL){ \
return EXCIT_EINVAL; \
}
int tleaf_it_alloc(excit_t it)
static void tleaf_it_free(excit_t it)
{
tleaf_it data_it;
EXCIT_DATA(it, data_it);
excit_set_dimension(it, 1);
data_it->cur = 0;
data_it->offset=0;
data_it->strides=NULL;
data_it->nleaves=NULL;
data_it->depth = 0;
data_it->arity = NULL;
data_it->policy = ROUND_ROBIN;
return EXCIT_SUCCESS;
if (it == NULL || it->data == NULL)
return;
struct tleaf_it_s *data_it = it->data;
if (data_it->arities != NULL)
free(data_it->arities);
if (data_it->order != NULL)
free(data_it->order);
if (data_it->buf != NULL)
free(data_it->buf);
if (data_it->levels)
excit_free(data_it->levels);
}
void tleaf_it_free(excit_t it)
static int excit_tleaf_init_with_it(excit_t it,
const ssize_t depth,
const ssize_t *arities,
const enum tleaf_it_policy_e policy,
const ssize_t *user_policy, excit_t levels)
{
if(it == NULL){ return; }
tleaf_it data_it;
excit_get_data(it, (void**)(&data_it));
if(data_it == NULL){ return; }
if(data_it->arity != NULL) free(data_it->arity);
if(data_it->nleaves != NULL) free(data_it->nleaves);
if(data_it->strides != NULL) free(data_it->strides);
free(data_it->arity);
return;
int err = EXCIT_SUCCESS;
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct tleaf_it_s *data_it = it->data;
ssize_t i;
data_it->depth = depth - 1;
/* Set order according to policy */
data_it->order = malloc(sizeof(*data_it->order) * data_it->depth);
if (data_it->order == NULL) {
perror("malloc");
err = -EXCIT_ENOMEM;
goto error;
}
switch (policy) {
case TLEAF_POLICY_ROUND_ROBIN:
for (i = 0; i < data_it->depth; i++)
data_it->order[i] = data_it->depth - i - 1;
break;
case TLEAF_POLICY_SCATTER:
for (i = 0; i < data_it->depth; i++)
data_it->order[i] = i;
break;
case TLEAF_POLICY_USER:
for (i = 0; i < data_it->depth; i++)
data_it->order[i] = user_policy[i];
break;
default:
err = -EXCIT_EINVAL;
goto error_with_levels;
}
/* Set order inverse */
data_it->order_inverse =
malloc(sizeof(*data_it->order_inverse) * data_it->depth);
if (data_it->order_inverse == NULL) {
perror("malloc");
err = -EXCIT_ENOMEM;
goto error_with_order;
}
for (i = 0; i < data_it->depth; i++)
data_it->order_inverse[data_it->order[i]] = i;
/* Set levels arity */
data_it->arities = malloc(sizeof(*data_it->arities) * data_it->depth);
if (data_it->arities == NULL) {
perror("malloc");
err = -EXCIT_ENOMEM;
goto error_with_order_inverse;
}
for (i = 0; i < data_it->depth; i++)
data_it->arities[i] = arities[i];
/* Set storage buffer for output of product iterator */
data_it->buf = malloc(sizeof(*data_it->buf) * data_it->depth);
if (data_it->buf == NULL) {
perror("malloc");
err = -EXCIT_ENOMEM;
goto error_with_arity;
}
/* Set product iterator if not provided */
if (levels == NULL) {
data_it->levels = excit_alloc(EXCIT_PRODUCT);
if (data_it->levels == NULL) {
err = -EXCIT_ENOMEM;
goto error_with_buf;
}
for (i = 0; i < data_it->depth; i++) {
excit_t level = excit_alloc(EXCIT_RANGE);
if (level == NULL) {
err = -EXCIT_ENOMEM;
goto error_with_levels;
}
err = excit_range_init(level, 0, arities[i] - 1, 1);
if (err != EXCIT_SUCCESS)
goto error_with_levels;
err = excit_product_add(data_it->levels, level);
if (err != EXCIT_SUCCESS)
goto error_with_levels;
}
} else {
data_it->levels = levels;
}
return EXCIT_SUCCESS;
error_with_levels:
excit_free(data_it->levels);
data_it->levels = NULL;
error_with_buf:
free(data_it->buf);
data_it->buf = NULL;
error_with_arity:
free(data_it->arities);
data_it->arities = NULL;
error_with_order_inverse:
free(data_it->order_inverse);
data_it->order_inverse = NULL;
error_with_order:
free(data_it->order);
data_it->order = NULL;
error:
return err;
}
int excit_tleaf_init(excit_t it,
const ssize_t depth,
const ssize_t* arities,
const ssize_t *arities,
const enum tleaf_it_policy_e policy,
const ssize_t offset,
const ssize_t* strides)
const ssize_t *user_policy)
{
int err = EXCIT_SUCCESS;
tleaf_it data_it;
EXCIT_DATA(it, data_it);
data_it->arity = malloc(sizeof(*data_it->arity) * depth);
if(data_it->arity == NULL){
perror("malloc");
err = EXCIT_ENOMEM;
goto error;
}
data_it->sttrides = malloc(sizeof(*data_it->strides) * depth);
if(data_it->strides == NULL){
perror("malloc");
err = EXCIT_ENOMEM;
goto error_with_arity;
}
ssize_t i, nleaves = 1;
data_it->depth = depth;
data_it->offset = offset;
data_it->policy = policy;
data_it->strides[0] = 1;
data_it->arity[depth-1] = 1;
data_it->nleaves[depth-1] = 1;
for(i=0; i<depth-1; i++){
data_it->arity[i] = arities[i];
data_it->strides[i+1] = strides ? strides[i+1] : 1;
data_it->nleaves[depth-i-2] = data_it->nleaves[depth-i-1] * arities[depth-i-1];
}
return EXCIT_SUCCESS;
error_with_arity:
free(data_it->arity);
error:
return err;
return excit_tleaf_init_with_it(it, depth, arities, policy, user_policy,
NULL);
}
int tleaf_it_size(const excit_t it, ssize_t *size)
static int tleaf_it_size(const excit_t it, ssize_t *size)
{
if(size == NULL){ return EXCIT_EINVAL; }
tleaf_it data_it;
EXCIT_DATA(it, data_it);
*size = data_it->nleaves{0};
return EXCIT_SUCCESS;
}
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
int tleaf_it_rewind(excit_t it)
{
tleaf_it data_it;
EXCIT_DATA(it, data_it);
data_it->cur=0;
return EXCIT_SUCCESS;
struct tleaf_it_s *data_it = it->data;
return excit_size(data_it->levels, size);
}
int tleaf_it_copy(excit_t dst_it, const excit_t src_it)
static int tleaf_it_rewind(excit_t it)
{
tleaf_it dst, src;
int err;
//check ptr
if(src_it == NULL || dst_it == NULL){ return EXCIT_EINVAL; }
err = excit_get_data(dst_it, (void**)(&dst));
if(err != EXCIT_SUCCESS) return err;
err = excit_get_data(src_it, (void**)(&src));
if(err != EXCIT_SUCCESS) return err;
if(dst == NULL || src == NULL) return EXCIT_EINVAL;
//actual copy
err = excit_tleaf_init(dst_it, src->depth, src->arity, src->policy, src->offset, src->strides);
if(err != EXCIT_SUCCESS) return err;
dst->cur = src->cur;
return EXCIT_SUCCESS;
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct tleaf_it_s *data_it = it->data;
return excit_rewind(data_it->levels);
}
int tleaf_it_pos(const excit_t it, ssize_t* value)
static int tleaf_it_copy(excit_t dst_it, const excit_t src_it)
{
tleaf_it data_it;
EXCIT_DATA(it, data_it);
*value = data_it->cur;
if(data_it->cur >= data_it->nleaves[0]){ return EXCIT_STOPIT; }
return EXCIT_SUCCESS;
if (src_it == NULL || dst_it == NULL)
return -EXCIT_EINVAL;
int err = EXCIT_SUCCESS;
struct tleaf_it_s *dst = dst_it->data;
struct tleaf_it_s *src = src_it->data;
/* dst is initialised, then wipe it */
if (dst->buf != NULL) {
free(dst->buf);
free(dst->arities);
free(dst->order);
free(dst->order_inverse);
excit_free(dst->levels);
}
/* dst is not initialized (anymore) */
excit_t levels = excit_alloc(EXCIT_PRODUCT);
if (levels == NULL)
return -EXCIT_ENOMEM;
err = src_it->func_table->copy(levels, src->levels);
if (err != EXCIT_SUCCESS)
goto error_with_levels;
err =
excit_tleaf_init_with_it(dst_it, src->depth + 1, src->arities,
TLEAF_POLICY_USER, src->order, levels);
if (err != EXCIT_SUCCESS)
goto error_with_levels;
return EXCIT_SUCCESS;
error_with_levels:
excit_free(levels);
return err;
}
int tleaf_it_nth_round_robin(const tleaf_it it, const ssize_t n, ssize_t* value)
static int tleaf_it_pos(const excit_t it, ssize_t *value)
{
//no check performed here
*value = n * it->stride + it->offset;
return EXCIT_SUCCESS;
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct tleaf_it_s *data_it = it->data;
return excit_pos(data_it->levels, value);
}
int tleaf_it_nth_scatter(const tleaf_it it, ssize_t c, ssize_t* value)
static ssize_t tleaf_it_value(struct tleaf_it_s *it, const int inverse)
{
//no check performed here
ssize_t depth = 0;
ssize_t arity = 0;
ssize_t r = 0;
ssize_t n = it->nleaves[0];
ssize_t pos = 0;
for(depth = 0; depth < (it->depth-1); depth++){
arity = it->arity[depth];
r = c % arity;
n = n / arity;
pos += n*r;
c = c / arity;
}
*value = pos * it->stride + it->offset;
return EXCIT_SUCCESS;
}
ssize_t i, acc = 1, val = 0;
ssize_t *order = inverse ? it->order_inverse : it->order;
static ssize_t tleaf_real_index_to_structure_index(tleaf_it it, const ssize_t n){
ssize_t i;
for (i = 0; i < it->depth; i++) {
val += acc * it->buf[order[i]];
acc *= it->arities[order[i]];
}
return val;
}
int tleaf_it_nth(const excit_t it, ssize_t n, ssize_t *indexes)
{
if(indexes == NULL)
return EXCIT_EINVAL;
tleaf_it data_it;
EXCIT_DATA(it, data_it);
if(n < 0 || n >= data_it->nleaves[0])
return EXCIT_EDOM;
int err = EXCIT_SUCCESS;
switch(data_it->policy){
case ROUND_ROBIN:
err = tleaf_it_nth_round_robin(data_it, n, indexes);
break;
case SCATTER:
err = tleaf_it_nth_scatter(data_it, n, indexes);
break;
default:
err = EXCIT_EINVAL;
break;
}
/* Compute here transformed index */
return err;
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct tleaf_it_s *data_it = it->data;
int err = excit_nth(data_it->levels, n, data_it->buf);
if (err != EXCIT_SUCCESS)
return err;
*indexes = tleaf_it_value(data_it, 0);
return EXCIT_SUCCESS;
}
int tleaf_it_peek(const excit_t it, ssize_t* value)
int tleaf_it_peek(const excit_t it, ssize_t *value)
{
tleaf_it data_it;
EXCIT_DATA(it, data_it);
if(data_it->cur >= data_it->nleaves[0]){ return EXCIT_STOPIT; }
return tleaf_it_nth(it, data_it->cur, value);
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct tleaf_it_s *data_it = it->data;
int err = excit_peek(data_it->levels, data_it->buf);
if (err != EXCIT_SUCCESS)
return err;
*value = tleaf_it_value(data_it, 0);
return EXCIT_SUCCESS;
}
int tleaf_it_next(excit_t it, ssize_t* indexes)
int tleaf_it_next(excit_t it, ssize_t *indexes)
{
tleaf_it data_it;
EXCIT_DATA(it, data_it);
int err = tleaf_it_peek(it, indexes);
if(err == EXCIT_SUCCESS){
data_it->cur++;
}
return err;
}
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct tleaf_it_s *data_it = it->data;
int err = excit_next(data_it->levels, data_it->buf);
static ssize_t tleaf_structure_index_to_real_index(tleaf_it it, const ssize_t n){
ssize_t i;
if (err != EXCIT_SUCCESS)
return err;
*indexes = tleaf_it_value(data_it, 0);
return EXCIT_SUCCESS;
}
int tleaf_it_rank(const excit_t it,
const ssize_t *indexes,
ssize_t *n)
int tleaf_it_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
{
// the function nth is symmetric
tleaf_it data_it;
EXCIT_DATA(it, data_it);
/* check that indexes is a possible output index */
/* transform back and compute transformed index rank */
int err = EXCIT_SUCCESS;
switch(data_it->policy){
case ROUND_ROBIN:
err = tleaf_it_nth_round_robin(data_it, *indexes, n);
break;
case SCATTER:
err = tleaf_it_nth_scatter(data_it, *indexes, n);
break;
default:
err = EXCIT_EINVAL;
break;
}
return tleaf_it_nth(it, (*indexes / it->stride) - data_it->offset, n);
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct tleaf_it_s *data_it = it->data;
int err = excit_nth(data_it->levels, *indexes, data_it->buf);
if (err != EXCIT_SUCCESS)
return err;
*n = tleaf_it_value(data_it, 1);
return EXCIT_SUCCESS;
}
int tleaf_it_split(const excit_t it, ssize_t n, excit_t *results){
// Split is done on a level which arity is a multiple of n.
// From root to nleaves[0], the first matching levels is used for the split.
if(n<0 || (n>0 && results==NULL))
return EXCIT_EINVAL;
if(n==0 || results==NULL)
return EXCIT_SUCCESS;
tleaf_it data_it;
EXCIT_DATA(it, data_it);
if(n > data_it->nleaves[0] || data_it->nleaves[0]%n != 0)
return EXCIT_EDOM;
ssize_t i = 0;
int split = 0;
ssize_t depth = data_it->depth;
ssize_t offset = data_it->offset;
ssize_t stride = data_it->stride;
enum tleaf_it_policy_e policy = data_it->policy;
ssize_t* arities = malloc(sizeof(*arities) * depth);
if(arities == NULL){
perror("malloc");
return EXCIT_ENOMEM;
}
for(i=0; i<data_it->depth; i++){
if(! split && data_it->arity[i] % n == 0){
arities[i] = data_it->arity[i]/n;
split=1;
stride *= arities[i]
} else {
arities[i] = data_it->arity[i];
}
}
int err;
for(i=0; i<n; i++){
results[i] = excit_alloc_user(&excit_tleaf_func_table, sizeof(*data_it));
err = excit_get_data(results[i], (void**)(&data_it));
if(err != EXCIT_SUCCESS || data_it == NULL) {
while(i--){ excit_free(results[i]); }
return err;
}
excit_tleaf_init(results[i], depth, arities, policy, data_it->nleaves[0]*i + data_it->offset);
}
free(arities);
return EXCIT_SUCCESS;
int tleaf_it_split_at_level(const excit_t it, const ssize_t level,
const ssize_t n, excit_t *out)
{
ssize_t i;
if (out == NULL)
return EXCIT_SUCCESS;
if (it == NULL || it->data == NULL)
return -EXCIT_EINVAL;
struct tleaf_it_s *data_it = it->data;
if (data_it->arities[level] % n != 0)
return -EXCIT_EINVAL;
int err = EXCIT_SUCCESS;
excit_t *levels = malloc(sizeof(*levels) * n);
if (levels == NULL) {
err = -EXCIT_ENOMEM;
goto error;
}
err = excit_product_split_dim(data_it->levels, level, n, levels);
if (err != EXCIT_SUCCESS)
goto error_with_levels;
ssize_t *arities = malloc(sizeof(*arities) * data_it->depth);
if (arities == NULL) {
err = -EXCIT_ENOMEM;
goto error_with_levels_initialized;
}
for (i = 0; i < data_it->depth; i++)
arities[i] = data_it->arities[i];
/* arities[level] /= n; */
for (i = 0; i < n; i++) {
err = excit_tleaf_init_with_it(out[i],
data_it->depth + 1,
arities,
TLEAF_POLICY_USER,
data_it->order, levels[i]);
if (err != EXCIT_SUCCESS)
goto error_with_arity;
}
free(levels);
free(arities);
return EXCIT_SUCCESS;
error_with_arity:
free(arities);
error_with_levels_initialized:
for (i = 0; i < n; i++)
excit_free(levels[i]);
error_with_levels:
free(levels);