Commit 4b54d0f5 authored by Nicolas Denoyelle's avatar Nicolas Denoyelle

Merge branch 'documentation' into tleaf

parents 1a956f14 a8e2470b
...@@ -2,6 +2,6 @@ AM_CFLAGS = -Wall -Werror -pedantic ...@@ -2,6 +2,6 @@ AM_CFLAGS = -Wall -Werror -pedantic
lib_LTLIBRARIES = libexcit.la lib_LTLIBRARIES = libexcit.la
libexcit_la_SOURCES = excit.c slice.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 tleaf.c
include_HEADERS = excit.h include_HEADERS = excit.h
#include "dev/excit.h" #include "dev/excit.h"
#include "slice.h" #include "composition.h"
static int slice_it_alloc(excit_t data) static int composition_it_alloc(excit_t data)
{ {
struct slice_it_s *it = (struct slice_it_s *)data->data; struct composition_it_s *it = (struct composition_it_s *)data->data;
it->src = NULL; it->src = NULL;
it->indexer = NULL; it->indexer = NULL;
return EXCIT_SUCCESS; return EXCIT_SUCCESS;
} }
static void slice_it_free(excit_t data) static void composition_it_free(excit_t data)
{ {
struct slice_it_s *it = (struct slice_it_s *)data->data; struct composition_it_s *it = (struct composition_it_s *)data->data;
excit_free(it->src); excit_free(it->src);
excit_free(it->indexer); excit_free(it->indexer);
} }
static int slice_it_copy(excit_t dst, const excit_t src) static int composition_it_copy(excit_t dst, const excit_t src)
{ {
const struct slice_it_s *it = (const struct slice_it_s *)src->data; const struct composition_it_s *it = (const struct composition_it_s *)src->data;
struct slice_it_s *result = (struct slice_it_s *)dst->data; struct composition_it_s *result = (struct composition_it_s *)dst->data;
result->src = excit_dup(it->src); result->src = excit_dup(it->src);
if (!result->src) if (!result->src)
...@@ -34,9 +34,9 @@ static int slice_it_copy(excit_t dst, const excit_t src) ...@@ -34,9 +34,9 @@ static int slice_it_copy(excit_t dst, const excit_t src)
return EXCIT_SUCCESS; return EXCIT_SUCCESS;
} }
static int slice_it_next(excit_t data, ssize_t *indexes) static int composition_it_next(excit_t data, ssize_t *indexes)
{ {
struct slice_it_s *it = (struct slice_it_s *)data->data; struct composition_it_s *it = (struct composition_it_s *)data->data;
ssize_t n; ssize_t n;
int err = excit_next(it->indexer, &n); int err = excit_next(it->indexer, &n);
...@@ -45,9 +45,9 @@ static int slice_it_next(excit_t data, ssize_t *indexes) ...@@ -45,9 +45,9 @@ static int slice_it_next(excit_t data, ssize_t *indexes)
return excit_nth(it->src, n, indexes); return excit_nth(it->src, n, indexes);
} }
static int slice_it_peek(const excit_t data, ssize_t *indexes) static int composition_it_peek(const excit_t data, ssize_t *indexes)
{ {
const struct slice_it_s *it = (const struct slice_it_s *)data->data; const struct composition_it_s *it = (const struct composition_it_s *)data->data;
ssize_t n; ssize_t n;
int err = excit_peek(it->indexer, &n); int err = excit_peek(it->indexer, &n);
...@@ -56,23 +56,23 @@ static int slice_it_peek(const excit_t data, ssize_t *indexes) ...@@ -56,23 +56,23 @@ static int slice_it_peek(const excit_t data, ssize_t *indexes)
return excit_nth(it->src, n, indexes); return excit_nth(it->src, n, indexes);
} }
static int slice_it_size(const excit_t data, ssize_t *size) static int composition_it_size(const excit_t data, ssize_t *size)
{ {
const struct slice_it_s *it = (const struct slice_it_s *)data->data; const struct composition_it_s *it = (const struct composition_it_s *)data->data;
return excit_size(it->indexer, size); return excit_size(it->indexer, size);
} }
static int slice_it_rewind(excit_t data) static int composition_it_rewind(excit_t data)
{ {
struct slice_it_s *it = (struct slice_it_s *)data->data; struct composition_it_s *it = (struct composition_it_s *)data->data;
return excit_rewind(it->indexer); return excit_rewind(it->indexer);
} }
static int slice_it_nth(const excit_t data, ssize_t n, ssize_t *indexes) static int composition_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; const struct composition_it_s *it = (const struct composition_it_s *)data->data;
ssize_t p; ssize_t p;
int err = excit_nth(it->indexer, n, &p); int err = excit_nth(it->indexer, n, &p);
...@@ -81,10 +81,10 @@ static int slice_it_nth(const excit_t data, ssize_t n, ssize_t *indexes) ...@@ -81,10 +81,10 @@ static int slice_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
return excit_nth(it->src, p, indexes); return excit_nth(it->src, p, indexes);
} }
static int slice_it_rank(const excit_t data, const ssize_t *indexes, static int composition_it_rank(const excit_t data, const ssize_t *indexes,
ssize_t *n) ssize_t *n)
{ {
const struct slice_it_s *it = (const struct slice_it_s *)data->data; const struct composition_it_s *it = (const struct composition_it_s *)data->data;
ssize_t inner_n; ssize_t inner_n;
int err = excit_rank(it->src, indexes, &inner_n); int err = excit_rank(it->src, indexes, &inner_n);
...@@ -93,16 +93,16 @@ static int slice_it_rank(const excit_t data, const ssize_t *indexes, ...@@ -93,16 +93,16 @@ static int slice_it_rank(const excit_t data, const ssize_t *indexes,
return excit_rank(it->indexer, &inner_n, n); return excit_rank(it->indexer, &inner_n, n);
} }
static int slice_it_pos(const excit_t data, ssize_t *n) static int composition_it_pos(const excit_t data, ssize_t *n)
{ {
const struct slice_it_s *it = (const struct slice_it_s *)data->data; const struct composition_it_s *it = (const struct composition_it_s *)data->data;
return excit_pos(it->indexer, n); return excit_pos(it->indexer, n);
} }
static int slice_it_split(const excit_t data, ssize_t n, excit_t *results) static int composition_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; const struct composition_it_s *it = (const struct composition_it_s *)data->data;
int err = excit_split(it->indexer, n, results); int err = excit_split(it->indexer, n, results);
if (err) if (err)
...@@ -114,7 +114,7 @@ static int slice_it_split(const excit_t data, ssize_t n, excit_t *results) ...@@ -114,7 +114,7 @@ static int slice_it_split(const excit_t data, ssize_t n, excit_t *results)
excit_t tmp2; excit_t tmp2;
tmp = results[i]; tmp = results[i];
results[i] = excit_alloc(EXCIT_SLICE); results[i] = excit_alloc(EXCIT_COMPOSITION);
if (!results[i]) { if (!results[i]) {
excit_free(tmp); excit_free(tmp);
err = -EXCIT_ENOMEM; err = -EXCIT_ENOMEM;
...@@ -126,7 +126,7 @@ static int slice_it_split(const excit_t data, ssize_t n, excit_t *results) ...@@ -126,7 +126,7 @@ static int slice_it_split(const excit_t data, ssize_t n, excit_t *results)
err = -EXCIT_ENOMEM; err = -EXCIT_ENOMEM;
goto error; goto error;
} }
err = excit_slice_init(results[i], tmp2, tmp); err = excit_composition_init(results[i], tmp2, tmp);
if (err) { if (err) {
excit_free(tmp); excit_free(tmp);
excit_free(tmp2); excit_free(tmp2);
...@@ -140,26 +140,26 @@ error: ...@@ -140,26 +140,26 @@ error:
return err; return err;
} }
struct excit_func_table_s excit_slice_func_table = { struct excit_func_table_s excit_composition_func_table = {
slice_it_alloc, composition_it_alloc,
slice_it_free, composition_it_free,
slice_it_copy, composition_it_copy,
slice_it_next, composition_it_next,
slice_it_peek, composition_it_peek,
slice_it_size, composition_it_size,
slice_it_rewind, composition_it_rewind,
slice_it_split, composition_it_split,
slice_it_nth, composition_it_nth,
slice_it_rank, composition_it_rank,
slice_it_pos composition_it_pos
}; };
int excit_slice_init(excit_t it, excit_t src, excit_t indexer) int excit_composition_init(excit_t it, excit_t src, excit_t indexer)
{ {
if (!it || it->type != EXCIT_SLICE || !src || !indexer if (!it || it->type != EXCIT_COMPOSITION || !src || !indexer
|| indexer->dimension != 1) || indexer->dimension != 1)
return -EXCIT_EINVAL; return -EXCIT_EINVAL;
struct slice_it_s *slice_it = (struct slice_it_s *)it->data; struct composition_it_s *composition_it = (struct composition_it_s *)it->data;
ssize_t size_src; ssize_t size_src;
ssize_t size_indexer; ssize_t size_indexer;
int err = excit_size(src, &size_src); int err = excit_size(src, &size_src);
...@@ -171,8 +171,8 @@ int excit_slice_init(excit_t it, excit_t src, excit_t indexer) ...@@ -171,8 +171,8 @@ int excit_slice_init(excit_t it, excit_t src, excit_t indexer)
return err; return err;
if (size_indexer > size_src) if (size_indexer > size_src)
return -EXCIT_EDOM; return -EXCIT_EDOM;
slice_it->src = src; composition_it->src = src;
slice_it->indexer = indexer; composition_it->indexer = indexer;
it->dimension = src->dimension; it->dimension = src->dimension;
return EXCIT_SUCCESS; return EXCIT_SUCCESS;
} }
......
...@@ -4,12 +4,12 @@ ...@@ -4,12 +4,12 @@
#include "excit.h" #include "excit.h"
#include "dev/excit.h" #include "dev/excit.h"
struct slice_it_s { struct composition_it_s {
excit_t src; excit_t src;
excit_t indexer; excit_t indexer;
}; };
extern struct excit_func_table_s excit_slice_func_table; extern struct excit_func_table_s excit_composition_func_table;
#endif //EXCIT_SLICE_H #endif //EXCIT_SLICE_H
#include <stdlib.h> #include <stdlib.h>
#include "excit.h" #include "excit.h"
#include "dev/excit.h" #include "dev/excit.h"
#include "slice.h" #include "composition.h"
#include "prod.h" #include "prod.h"
#include "cons.h" #include "cons.h"
#include "repeat.h" #include "repeat.h"
...@@ -19,7 +19,7 @@ const char *excit_type_name(enum excit_type_e type) ...@@ -19,7 +19,7 @@ const char *excit_type_name(enum excit_type_e type)
CASE(EXCIT_REPEAT); CASE(EXCIT_REPEAT);
CASE(EXCIT_HILBERT2D); CASE(EXCIT_HILBERT2D);
CASE(EXCIT_PRODUCT); CASE(EXCIT_PRODUCT);
CASE(EXCIT_SLICE); CASE(EXCIT_COMPOSITION);
CASE(EXCIT_USER); CASE(EXCIT_USER);
CASE(EXCIT_TYPE_MAX); CASE(EXCIT_TYPE_MAX);
default: default:
...@@ -115,8 +115,8 @@ excit_t excit_alloc(enum excit_type_e type) ...@@ -115,8 +115,8 @@ excit_t excit_alloc(enum excit_type_e type)
case EXCIT_PRODUCT: case EXCIT_PRODUCT:
ALLOC_EXCIT(prod); ALLOC_EXCIT(prod);
break; break;
case EXCIT_SLICE: case EXCIT_COMPOSITION:
ALLOC_EXCIT(slice); ALLOC_EXCIT(composition);
break; break;
case EXCIT_TLEAF: case EXCIT_TLEAF:
ALLOC_EXCIT(tleaf); ALLOC_EXCIT(tleaf);
...@@ -270,12 +270,12 @@ int excit_split(const excit_t it, ssize_t n, excit_t *results) ...@@ -270,12 +270,12 @@ int excit_split(const excit_t it, ssize_t n, excit_t *results)
if (!tmp) if (!tmp)
goto error2; goto error2;
tmp2 = results[i]; tmp2 = results[i];
results[i] = excit_alloc(EXCIT_SLICE); results[i] = excit_alloc(EXCIT_COMPOSITION);
if (!results[i]) { if (!results[i]) {
excit_free(tmp2); excit_free(tmp2);
goto error2; goto error2;
} }
err = excit_slice_init(results[i], tmp, tmp2); err = excit_composition_init(results[i], tmp, tmp2);
if (err) { if (err) {
excit_free(tmp2); excit_free(tmp2);
goto error2; goto error2;
......
...@@ -4,20 +4,87 @@ ...@@ -4,20 +4,87 @@
#include <stdlib.h> #include <stdlib.h>
/* /*
* The different types of iterator supported. All iterators use the same * excit library provides an interface to build multi-dimensional iterators over
* integer type (ssize_t) for values. * indexes.
* excit iterators walk an array of n elements indexed from 0 to n-1,
* and returns the aforementionned elements.
* excit return elements which type can only be an index of type ssize_t,
* or an array of indexes (a multi-dimensional index) if the defined iterator
* has several dimensions. ssize_t elements can fit pointers. Thus, it makes
* excit library the ideal tool box for indexing and ealking complex structures.
*
* excit implements its own interface with several iterators (see excit_type_e).
* For instance, excit implementation of product iterators enable to mix iterators
* to create more complex ones. The library balanced tree "tleaf" iterator is built
* on top of product iterator.
*
* excit library uses the concept of "ownership".
* An excit iterator has the ownership of its internal data, i.e it will free
* its owned data upon call to excit_free(). This ownership
* may be transferred to another iterator through a library function such as
* excit_cons_init() or excit_product_add().
* Thus ownership must be carefully watched to avoid memory leaks or double free.
*
* excit library provides a rank function to find the index given an element.
*/ */
enum excit_type_e { enum excit_type_e {
EXCIT_INVALID, /*!< Tag for invalid iterators */ /*!< Tag for invalid iterators */
EXCIT_RANGE, /*!< Iterator over a range of values */ EXCIT_INVALID,
EXCIT_CONS, /*!< Sliding window iterator */ /*!<
EXCIT_REPEAT, /*!< Ierator that stutters a certain amount of times */ * Iterator over a range of values.
EXCIT_HILBERT2D, /*!< Hilbert space filing curve */ * See function excit_range_init for further details on iterator
EXCIT_PRODUCT, /*!< Iterator over the catesian product of iterators */ * behaviour.
EXCIT_SLICE, /*!< Iterator using another iterator to index a third */ */
EXCIT_TLEAF, /*!< Iterator on tree leaves with all leaves at same depth */ EXCIT_RANGE,
EXCIT_USER, /*!< User-defined iterator */ /*!<
EXCIT_TYPE_MAX /*!< Guard */ * Sliding window iterator
* See function excit_cons_init for further details on iterator
* behaviour.
*/
EXCIT_CONS,
/*!<
* Iterator that stutters a certain amount of times.
* Builds an iterator on top of another iterator repeating the latter elements.
* See function excit_repeat_init() for further details on iterator
* behaviour.
*/
EXCIT_REPEAT,
/*!< Hilbert space filing curve */
EXCIT_HILBERT2D,
/*!<
* Iterator over the catesian product of iterators.
* The result iterator dimension is the sum of of input iterator dimensions.
*/
EXCIT_PRODUCT,
/*!<
* Iterator composing two iterators,
* i.e using an iterator to index another.
* It is possible to chain composition iterators as long as
* input and output sets are compatible.
* (Only dimension compatibility is not enforced by the library).
* It is straightforward to build a composition iterator by composing two range iterators.
*/
EXCIT_COMPOSITION,
/*!<
* Iterator on balanced tree leaves.
* The iterator walks an index of leaves according to a policy.
* tleaf iterator has a special tleaf_it_split() for splitting the
* tree at a specific level.
* See tleaf_it_policy_e and excit_tleaf_init() for further explaination.
*/
EXCIT_TLEAF,
/*!<
* User-defined iterator
* excit library allow users to define their own iterator.
* To do so, they need to populate the function table excit_func_table_s
* with the routines to manipulate the aforementionned iterator.
* The outcome is that they will enjoy the functionnalities of the library
* for mixing with other iterators.
*/
EXCIT_USER,
/*!< Guard */
EXCIT_TYPE_MAX
}; };
/* /*
...@@ -96,6 +163,8 @@ struct excit_func_table_s { ...@@ -96,6 +163,8 @@ struct excit_func_table_s {
/* /*
* This funciton is called during excit_dup. It is responsible for * This funciton is called during excit_dup. It is responsible for
* duplicating the content of the inner data between src_it and dst_it. * duplicating the content of the inner data between src_it and dst_it.
* The internal state of the iterator must also be copied, i.e subsequent
* calls to excit_next() must return the same results for both iterators.
* Returns EXCIT_SUCCESS or an error code. * Returns EXCIT_SUCCESS or an error code.
*/ */
int (*copy)(excit_t dst_it, const excit_t src_it); int (*copy)(excit_t dst_it, const excit_t src_it);
...@@ -185,7 +254,7 @@ excit_t excit_alloc_user(struct excit_func_table_s *func_table, ...@@ -185,7 +254,7 @@ excit_t excit_alloc_user(struct excit_func_table_s *func_table,
size_t data_size); size_t data_size);
/* /*
* Duplicates an iterator. * Duplicates an iterator and keep its internal state.
* "it": iterator to duplicate. * "it": iterator to duplicate.
* Returns an iterator that will need to be freed unless ownership is * Returns an iterator that will need to be freed unless ownership is
* transfered or NULL if an error occured. * transfered or NULL if an error occured.
...@@ -262,7 +331,8 @@ int excit_size(const excit_t it, ssize_t *size); ...@@ -262,7 +331,8 @@ int excit_size(const excit_t it, ssize_t *size);
int excit_split(const excit_t it, ssize_t n, excit_t *results); int excit_split(const excit_t it, ssize_t n, excit_t *results);
/* /*
* Gets the nth element of an iterator. * Gets the nth element of an iterator. If an iterator has k dimensions,
* then the nth element is an array of k nth elements along each dimension.
* "it": an iterator. * "it": an iterator.
* "rank": rank of the element, comprised between 0 and the size of the * "rank": rank of the element, comprised between 0 and the size of the
* iterator. * iterator.
...@@ -273,14 +343,17 @@ int excit_split(const excit_t it, ssize_t n, excit_t *results); ...@@ -273,14 +343,17 @@ int excit_split(const excit_t it, ssize_t n, excit_t *results);
int excit_nth(const excit_t it, ssize_t rank, ssize_t *indexes); int excit_nth(const excit_t it, ssize_t rank, ssize_t *indexes);
/* /*
* Gets the rank of an element of an iterator. * Gets the rank of an element of an iterator. The rank of an element is its
* iteration index, i.e excit_nth(excit_rank(element)) should return element.
* If the iterator has k dimensions, element is an array of the k values
* composing element.
* "it": an iterator. * "it": an iterator.
* "indexes": an array of indexes corresponding to the element of the iterator. * "indexes": an array of indexes corresponding to the element of the iterator.
* "rank": a pointer to a variable where the result will be stored, no result is * "rank": a pointer to a variable where the result will be stored, no result is
* returned if NULL. * returned if NULL.
* Returns EXCIT_SUCCESS or an error code. * Returns EXCIT_SUCCESS or an error code.
*/ */
int excit_rank(const excit_t it, const ssize_t *indexes, ssize_t *rank); int excit_rank(const excit_t it, const ssize_t *element, ssize_t *rank);
/* /*
* Gets the position of the iterator. * Gets the position of the iterator.
...@@ -311,7 +384,7 @@ int excit_skip(excit_t it); ...@@ -311,7 +384,7 @@ int excit_skip(excit_t it);
int excit_cyclic_next(excit_t it, ssize_t *indexes, int *looped); int excit_cyclic_next(excit_t it, ssize_t *indexes, int *looped);
/* /*
* Initializes a range iterator to iterate from first to last (included) by sep. * Initializes a range iterator to iterate from first to last (included) by step.
* "it": a range iterator. * "it": a range iterator.
* "first": first value of the range. * "first": first value of the range.
* "last": last value of the range. * "last": last value of the range.
...@@ -398,13 +471,13 @@ int excit_product_split_dim(const excit_t it, ssize_t dim, ssize_t n, ...@@ -398,13 +471,13 @@ int excit_product_split_dim(const excit_t it, ssize_t dim, ssize_t n,
excit_t *results); excit_t *results);
/* /*
* Initializes a slice iterator by giving asrc iterator and an indexer iterator. * Initializes a composition iterator by giving a src iterator and an indexer iterator.
* "it": a slice iterator. * "it": a composition iterator.
* "src": the iterator whom elements are to be returned. * "src": the iterator whom elements are to be returned.
* "indexer": the iterator that will provide the rank of the elements to return. * "indexer": the iterator that will provide the rank of the elements to return.
* Returns EXCIT_SUCCESS or an error code. * Returns EXCIT_SUCCESS or an error code.
*/ */
int excit_slice_init(excit_t it, excit_t src, excit_t indexer); int excit_composition_init(excit_t it, excit_t src, excit_t indexer);
enum tleaf_it_policy_e { enum tleaf_it_policy_e {
TLEAF_POLICY_ROUND_ROBIN, /* Iterate on tree leaves in a round-robin fashion */ TLEAF_POLICY_ROUND_ROBIN, /* Iterate on tree leaves in a round-robin fashion */
...@@ -414,6 +487,10 @@ enum tleaf_it_policy_e { ...@@ -414,6 +487,10 @@ enum tleaf_it_policy_e {
/* /*
* Initialize a tleaf iterator by giving its depth, levels arity and iteration policy. * Initialize a tleaf iterator by giving its depth, levels arity and iteration policy.
* example building a user scatter policy:
* excit_tleaf_init(it, 4, {3, 2, 4}, TLEAF_POLICY_USER, {2, 1, 0});
* gives the output index:
* 0,6,12,18,3,9,15,21,1,7,13,19,4,10,16,22,2,8,14,20,5,11,17,23.
* "it": a tleaf iterator * "it": a tleaf iterator
* "depth": the total number of levels of the tree, including leaves * "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. * "arity": An array of size (depth-1). For each level, the number of children attached to a node.
...@@ -422,11 +499,13 @@ enum tleaf_it_policy_e { ...@@ -422,11 +499,13 @@ enum tleaf_it_policy_e {
* It is intended to prune node of certain levels while keeping index of the initial structure. * It is intended to prune node of certain levels while keeping index of the initial structure.
* Ownership of index is not taken. The iterator allocates a copy of index and manage it internally. * Ownership of index is not taken. The iterator allocates a copy of index and manage it internally.
* "policy": A policy for iteration on 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. * "user_policy": If policy is TLEAF_POLICY_USER, then this argument must be an array of size (depth-1) providing the
* when resolving indexes. Underneath, a product iterator of range iterator returns indexes on last levels upon iterator queries. This set of indexes is then * order (from 0 to (depth-2)) in which levels are walked.
* 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 * 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. * obtained from walking from root to leaves.
*/ */
int excit_tleaf_init(excit_t it, int excit_tleaf_init(excit_t it,
const ssize_t depth, const ssize_t depth,
...@@ -436,10 +515,11 @@ int excit_tleaf_init(excit_t it, ...@@ -436,10 +515,11 @@ int excit_tleaf_init(excit_t it,
const ssize_t *user_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. * Split a tree at a given level. The behaviour is different from the generic function excit_split for the
* split might be sparse, depending on the tree level where the split occures and the number of parts.
* "it": a tleaf iterator. * "it": a tleaf iterator.
* "level": The level to split. * "level": The level to split.
* "n": The number of slices. n must divide the target level arity. * "n": The number of parts. n must divide the target level arity.
* "out": an array of n allocated tleaf iterators. * "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); int tleaf_it_split(const excit_t it, const ssize_t level, const ssize_t n, excit_t *out);
......
...@@ -184,7 +184,8 @@ int tleaf_it_rank(const excit_t it, const ssize_t *indexes, ssize_t *n) ...@@ -184,7 +184,8 @@ int tleaf_it_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
acc *= data_it->arities[i]; acc *= data_it->arities[i];
} }
*n = val; if (n != NULL)
*n = val;
return EXCIT_SUCCESS; return EXCIT_SUCCESS;
} }
...@@ -399,6 +400,8 @@ int tleaf_it_split(const excit_t it, const ssize_t depth, ...@@ -399,6 +400,8 @@ int tleaf_it_split(const excit_t it, const ssize_t depth,
if (data_it->arities[depth] % n != 0) if (data_it->arities[depth] % n != 0)
return -EXCIT_EINVAL; return -EXCIT_EINVAL;
if (out == NULL)
return EXCIT_SUCCESS;
int err; int err;
excit_t *levels, *levels_inverse; excit_t *levels, *levels_inverse;
......
...@@ -12,9 +12,9 @@ excit_repeat_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_repeat.c ...@@ -12,9 +12,9 @@ excit_repeat_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_repeat.c
excit_cons_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_cons.c excit_cons_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_cons.c
excit_tleaf_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_tleaf.c excit_tleaf_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_tleaf.c
excit_hilbert2d_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_hilbert2d.c excit_hilbert2d_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_hilbert2d.c
excit_slice_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_slice.c excit_composition_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_composition.c
UNIT_TESTS = excit_range excit_product excit_repeat excit_cons excit_hilbert2d excit_slice excit_tleaf UNIT_TESTS = excit_range excit_product excit_repeat excit_cons excit_hilbert2d excit_composition excit_tleaf
# all tests # all tests
check_PROGRAMS = $(UNIT_TESTS) check_PROGRAMS = $(UNIT_TESTS)
......
...@@ -15,16 +15,16 @@ excit_t create_test_range(ssize_t start, ssize_t stop, ssize_t step) ...@@ -15,16 +15,16 @@ excit_t create_test_range(ssize_t start, ssize_t stop, ssize_t step)
return it; return it;
} }
void test_alloc_init_slice(excit_t source, excit_t indexer) void test_alloc_init_composition(excit_t source, excit_t indexer)
{ {
excit_t it; excit_t it;
ssize_t dim, expected_dim, size, expected_size; ssize_t dim, expected_dim, size, expected_size;
it = excit_alloc_test(EXCIT_SLICE); it = excit_alloc_test(EXCIT_COMPOSITION);
assert(excit_dimension(it, &dim) == ES); assert(excit_dimension(it, &dim) == ES);
assert(dim == 0); assert(dim == 0);
assert(excit_slice_init(it, excit_dup(source), excit_dup(indexer)) == assert(excit_composition_init(it, excit_dup(source), excit_dup(indexer)) ==
ES); ES);
assert(excit_dimension(it, &dim) == ES); assert(excit_dimension(it, &dim) == ES);
assert(excit_dimension(source, &expected_dim) == ES); assert(excit_dimension(source, &expected_dim) == ES);
...@@ -36,19 +36,19 @@ void test_alloc_init_slice(excit_t source, excit_t indexer) ...@@ -36,19 +36,19 @@ void test_alloc_init_slice(excit_t source, excit_t indexer)
excit_free(it); excit_free(it);
} }
excit_t create_test_slice(excit_t source, excit_t indexer) excit_t create_test_composition(excit_t source, excit_t indexer)
{ {
excit_t it; excit_t it;
it = excit_alloc_test(EXCIT_SLICE); it = excit_alloc_test(EXCIT_COMPOSITION);
assert(excit_slice_init(it, excit_dup(source), excit_dup(indexer)) == assert(excit_composition_init(it, excit_dup(source), excit_dup(indexer)) ==
ES); ES);
return it; return it;
} }
void test_next_slice(excit_t source, excit_t indexer) void test_next_composition(excit_t source, excit_t indexer)
{ {
excit_t it = create_test_slice(source, indexer); excit_t it = create_test_composition(source, indexer);
excit_t iit = excit_dup(indexer); excit_t iit = excit_dup(indexer);
...@@ -73,16 +73,16 @@ void test_next_slice(excit_t source, excit_t indexer) ...@@ -73,16 +73,16 @@ void test_next_slice(excit_t source, excit_t indexer)
excit_free(iit); excit_free(iit);
} }
void test_slice_iterator(excit_t source, excit_t indexer) void test_composition_iterator(excit_t source, excit_t indexer)
{ {
test_alloc_init_slice(source, indexer); test_alloc_init_composition(source, indexer);
test_next_slice(source, indexer); test_next_composition(source, indexer);
int i = 0;