GitLab maintenance scheduled for Today, 2019-04-24, from 12:00 to 13:00 CDT - Services will be unavailable during this time.

Commit 38875254 authored by Brice Videau's avatar Brice Videau

Merge branch 'tleaf' into 'master'

Tleaf

See merge request !5
parents 4fbca5f8 b290b70d
......@@ -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
......@@ -249,3 +249,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
......@@ -117,6 +118,9 @@ excit_t excit_alloc(enum excit_type_e type)
case EXCIT_SLICE:
ALLOC_EXCIT(slice);
break;
case EXCIT_TLEAF:
ALLOC_EXCIT(tleaf);
break;
default:
goto error;
}
......@@ -352,3 +356,4 @@ int excit_skip(excit_t it)
{
return excit_next(it, NULL);
}
......@@ -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 */
};
......@@ -52,16 +53,23 @@ typedef struct excit_s *excit_t;
******************************************************************************/
/*
* Sets the dimension of a user-defined iterator.
* "it": a user-defined iterator.
* Sets the dimension of a (user-defined) iterator.
* "it": a (user-defined) iterator.
* "dimension": the new dimension of the iterator.
* Returns EXCIT_SUCCESS or an error code.
*/
int excit_set_dimension(excit_t it, ssize_t dimension);
/*
* Gets the inner data pointer of a user-defined iterator.
* "it": a user-defined iterator.
* Gets the dimension of an iterator.
* "it": the iterator.
* Returns the dimension or -1 if it is NULL.
*/
ssize_t excit_get_dimension(excit_t it);
/*
* Gets the inner data pointer of a (user-defined) iterator.
* "it": a (user-defined) iterator.
* "data": a pointer to a pointer variable where the result will be written.
* Returns EXCIT_SUCCESS or an error code.
*/
......@@ -397,4 +405,37 @@ int excit_product_split_dim(const excit_t it, ssize_t dim, ssize_t n,
* Returns EXCIT_SUCCESS or an error code.
*/
int excit_slice_init(excit_t it, excit_t src, excit_t indexer);
enum tleaf_it_policy_e {
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 */
};
/*
* 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": 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. Arities are organized from root to leaves.
* "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);
/*
* Split a tree at a given level. The behaviour is different from the generic function excit_split for the split might be sparse.
* "it": a tleaf iterator.
* "level": The level to split.
* "n": The number of slices. n must divide the target level arity.
* "out": an array of n allocated tleaf iterators.
*/
int tleaf_it_split(const excit_t it, const ssize_t level, const ssize_t n, excit_t *out);
#endif
......@@ -216,3 +216,4 @@ struct excit_func_table_s excit_hilbert2d_func_table = {
hilbert2d_it_rank,
hilbert2d_it_pos
};
......@@ -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
......@@ -201,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
......@@ -152,3 +152,4 @@ error:
excit_free(results[i]);
return err;
}
......@@ -13,3 +13,4 @@ struct repeat_it_s {
extern struct excit_func_table_s excit_repeat_func_table;
#endif //EXCIT_REPEAT_H
......@@ -176,3 +176,4 @@ int excit_slice_init(excit_t it, excit_t src, excit_t indexer)
it->dimension = src->dimension;
return EXCIT_SUCCESS;
}
......@@ -12,3 +12,4 @@ struct slice_it_s {
extern struct excit_func_table_s excit_slice_func_table;
#endif //EXCIT_SLICE_H
#include <stdlib.h>
#include <stdio.h>
#include "dev/excit.h"
#include "tleaf.h"
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;
data_it->depth = 0;
data_it->arities = NULL;
data_it->order = NULL;
data_it->order_inverse = NULL;
data_it->buf = NULL;
data_it->levels = NULL;
return EXCIT_SUCCESS;
}
static void tleaf_it_free(excit_t it)
{
struct tleaf_it_s *data_it = it->data;
free(data_it->arities);
free(data_it->order);
free(data_it->order_inverse);
free(data_it->buf);
excit_free(data_it->levels);
}
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 || it->data == NULL)
return -EXCIT_EINVAL;
int err = EXCIT_SUCCESS;
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) {
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) {
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) {
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) {
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 enum tleaf_it_policy_e policy,
const ssize_t *user_policy)
{
return excit_tleaf_init_with_it(it, depth, arities, policy, user_policy,
NULL);
}
static int tleaf_it_size(const excit_t it, ssize_t *size)
{
struct tleaf_it_s *data_it = it->data;
return excit_size(data_it->levels, size);
}
static int tleaf_it_rewind(excit_t it)
{
struct tleaf_it_s *data_it = it->data;
return excit_rewind(data_it->levels);
}
static int tleaf_it_copy(excit_t dst_it, const excit_t src_it)
{
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_dup(src->levels);
if (levels == NULL) {
err = -EXCIT_ENOMEM;
goto error;
}
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);
error:
return err;
}
static int tleaf_it_pos(const excit_t it, ssize_t *value)
{
struct tleaf_it_s *data_it = it->data;
return excit_pos(data_it->levels, value);
}
static ssize_t tleaf_it_value(struct tleaf_it_s *it, const int inverse)
{
ssize_t i, acc = 1, val = 0;
ssize_t *order = inverse ? it->order_inverse : it->order;
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)
{
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)
{
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)
{
struct tleaf_it_s *data_it = it->data;
int err = excit_next(data_it->levels, data_it->buf);
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)
{
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, 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);
error:
return err;
}
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,
NULL,
tleaf_it_nth,
tleaf_it_rank,
tleaf_it_pos
};
#ifndef TLEAF_H
#define TLEAF_H
#include "excit.h"
struct tleaf_it_s {
ssize_t depth;
ssize_t *arities;
ssize_t *order;
ssize_t *order_inverse;
ssize_t *buf;
excit_t levels;
};
extern struct excit_func_table_s excit_tleaf_func_table;
#endif //TLEAF_H
......@@ -5,6 +5,81 @@
#define ES EXCIT_SUCCESS
#define TLEAF_DEPTH 3
#define TLEAF_NSPLIT 2
void test_tleaf_iterator(void)
{
excit_t it;
ssize_t depth = TLEAF_DEPTH+1;
ssize_t arities[(TLEAF_DEPTH)] = {3, 2, 4};
ssize_t i = 0, value;
ssize_t size = 1, it_size = 0;
int err = EXCIT_SUCCESS;
for (i = 0; i < depth-1; i++)
size *= arities[i];
it = excit_alloc(EXCIT_TLEAF);
err = excit_tleaf_init(it, depth, arities,
TLEAF_POLICY_ROUND_ROBIN, NULL);
assert(err == EXCIT_SUCCESS);
err = excit_size(it, &it_size);
assert(err == EXCIT_SUCCESS);
assert(it_size == size);
for (i = 0; i < size; i++) {
err = excit_next(it, &value);
assert(err == EXCIT_SUCCESS);
assert(value == i);
}
err = excit_next(it, &value);
assert(err == EXCIT_STOPIT);
excit_t split[TLEAF_NSPLIT];
for (i = 0; i < TLEAF_NSPLIT; i++)
split[i] = excit_alloc(EXCIT_TLEAF);
err = tleaf_it_split(it, 2, TLEAF_NSPLIT, split);
assert(err == EXCIT_SUCCESS);
err = excit_rewind(split[1]);
assert(err == EXCIT_SUCCESS);
err = excit_size(split[1], &it_size);
assert(err == EXCIT_SUCCESS);
assert(it_size == size/TLEAF_NSPLIT);
err = excit_next(split[1], &value);
assert(err == EXCIT_SUCCESS);
assert(value == 2);
err = excit_next(split[1], &value);
assert(err == EXCIT_SUCCESS);
assert(value == 3);
err = excit_next(split[1], &value);
assert(err == EXCIT_SUCCESS);
assert(value == 6);
err = excit_next(split[1], &value);
assert(err == EXCIT_SUCCESS);
assert(value == 7);
err = excit_next(split[1], &value);
assert(err == EXCIT_SUCCESS);
assert(value == 10);
err = excit_next(split[1], &value);
assert(err == EXCIT_SUCCESS);
assert(value == 11);
for (i = 0; i < TLEAF_NSPLIT; i++)
excit_free(split[i]);
excit_free(it);
}
void test_range_iterator(void)
{
excit_t it;
......@@ -664,5 +739,6 @@ int main(int argc, char *argv[])
test_cons_iterator();
test_repeat_iterator();
test_hilbert2d_iterator();
test_tleaf_iterator();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment