Commit 70e9d1ff authored by Brice Videau's avatar Brice Videau
Browse files

Added loop iterator.

parent 205db61d
Pipeline #11106 passed with stages
in 29 seconds
......@@ -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 index.c tleaf.c
libexcit_la_SOURCES = excit.c composition.c prod.c cons.c repeat.c hilbert2d.c range.c index.c tleaf.c loop.c
include_HEADERS = excit.h
......@@ -18,6 +18,7 @@
#include "range.h"
#include "index.h"
#include "tleaf.h"
#include "loop.h"
#define CASE(val) case val: return #val; break
......@@ -31,7 +32,9 @@ const char *excit_type_name(enum excit_type_e type)
CASE(EXCIT_HILBERT2D);
CASE(EXCIT_PRODUCT);
CASE(EXCIT_COMPOSITION);
CASE(EXCIT_TLEAF);
CASE(EXCIT_USER);
CASE(EXCIT_LOOP);
CASE(EXCIT_TYPE_MAX);
default:
return NULL;
......@@ -135,6 +138,9 @@ excit_t excit_alloc(enum excit_type_e type)
case EXCIT_TLEAF:
ALLOC_EXCIT(tleaf);
break;
case EXCIT_LOOP:
ALLOC_EXCIT(loop);
break;
default:
goto error;
}
......
......@@ -97,6 +97,11 @@ enum excit_type_e {
* for mixing with other iterators.
*/
EXCIT_USER,
/*!<
* Interator looping a given amount of time over another iterator.
* See excit_loop_init() for further explanation.
*/
EXCIT_LOOP,
/*!< Guard */
EXCIT_TYPE_MAX
};
......@@ -509,6 +514,15 @@ int excit_product_split_dim(const_excit_t it, ssize_t dim, ssize_t n,
*/
int excit_composition_init(excit_t it, excit_t src, excit_t indexer);
/*
* Initializes a loop iterator by giving a src iterator and a number of loops to achieve.
* "it": a loop iterator.
* "src": the iterator to loop over.
* "n": the number of time to loop over the src iterator.
* Returns EXCIT_SUCCESS or an error code.
*/
int excit_loop_init(excit_t it, excit_t src, ssize_t n);
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 spreading as much as possible */
......
/*******************************************************************************
* Copyright 2019 UChicago Argonne, LLC.
* (c.f. AUTHORS, LICENSE)
*
* This file is part of the EXCIT project.
* For more info, see https://xgitlab.cels.anl.gov/argo/excit
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
#include "dev/excit.h"
#include "loop.h"
static int loop_it_alloc(excit_t data)
{
struct loop_it_s *it = (struct loop_it_s *)data->data;
it->it = NULL;
it->n = 0;
it->counter = 0;
return EXCIT_SUCCESS;
}
static void loop_it_free(excit_t data)
{
struct loop_it_s *it = (struct loop_it_s *)data->data;
excit_free(it->it);
}
static int loop_it_copy(excit_t ddst, const_excit_t dsrc)
{
struct loop_it_s *dst = (struct loop_it_s *)ddst->data;
const struct loop_it_s *src = (const struct loop_it_s *)dsrc->data;
excit_t copy = excit_dup(src->it);
if (!copy)
return -EXCIT_EINVAL;
dst->it = copy;
dst->n = src->n;
dst->counter = src->counter;
return EXCIT_SUCCESS;
}
static int loop_it_peek(const_excit_t data, ssize_t *indexes)
{
const struct loop_it_s *it = (const struct loop_it_s *)data->data;
return excit_peek(it->it, indexes);
}
static int loop_it_next(excit_t data, ssize_t *indexes)
{
struct loop_it_s *it = (struct loop_it_s *)data->data;
int err;
if (it->counter == it->n - 1)
return excit_next(it->it, indexes);
int looped;
err = excit_cyclic_next(it->it, indexes, &looped);
if (looped)
it->counter++;
return err;
}
static int loop_it_size(const_excit_t data, ssize_t *size)
{
const struct loop_it_s *it = (const struct loop_it_s *)data->data;
int err = excit_size(it->it, size);
if (err)
return err;
*size *= it->n;
return EXCIT_SUCCESS;
}
static int loop_it_rewind(excit_t data)
{
struct loop_it_s *it = (struct loop_it_s *)data->data;
it->counter = 0;
return excit_rewind(it->it);
}
static int loop_it_nth(const_excit_t data, ssize_t n, ssize_t *val)
{
ssize_t size;
const struct loop_it_s *it = (const struct loop_it_s *)data->data;
int err = excit_size(it->it, &size);
if (err)
return err;
if (n < 0 || n >= size*it->n)
return -EXCIT_EDOM;
return excit_nth(it->it, n % size, val);
}
static int loop_it_pos(const_excit_t data, ssize_t *n)
{
ssize_t inner_n;
ssize_t size;
const struct loop_it_s *it = (const struct loop_it_s *)data->data;
int err = excit_pos(it->it, &inner_n);
if (err)
return err;
err = excit_size(it->it, &size);
if (err)
return err;
if (n)
*n = inner_n + it->counter * size;
return EXCIT_SUCCESS;
}
struct excit_func_table_s excit_loop_func_table = {
loop_it_alloc,
loop_it_free,
loop_it_copy,
loop_it_next,
loop_it_peek,
loop_it_size,
loop_it_rewind,
NULL,
loop_it_nth,
NULL,
loop_it_pos
};
int excit_loop_init(excit_t it, excit_t src, ssize_t n)
{
if (!it || it->type != EXCIT_LOOP || !src || n <= 0)
return -EXCIT_EINVAL;
struct loop_it_s *loop_it = (struct loop_it_s *)it->data;
excit_free(loop_it->it);
it->dimension = src->dimension;
loop_it->it = src;
loop_it->n = n;
loop_it->counter = 0;
return EXCIT_SUCCESS;
}
/*******************************************************************************
* Copyright 2019 UChicago Argonne, LLC.
* (c.f. AUTHORS, LICENSE)
*
* This file is part of the EXCIT project.
* For more info, see https://xgitlab.cels.anl.gov/argo/excit
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
#ifndef EXCIT_LOOP_H
#define EXCIT_LOOP_H
#include "excit.h"
#include "dev/excit.h"
struct loop_it_s {
excit_t it;
ssize_t n;
ssize_t counter;
};
extern struct excit_func_table_s excit_loop_func_table;
#endif //EXCIT_LOOP_H
......@@ -10,12 +10,13 @@ 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
excit_loop_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_loop.c
excit_cons_SOURCES = $(LIBHSOURCES) $(LIBCSOURCES) excit_cons.c
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_index excit_tleaf
UNIT_TESTS = excit_range excit_product excit_repeat excit_cons excit_hilbert2d excit_composition excit_index excit_tleaf excit_loop
# all tests
check_PROGRAMS = $(UNIT_TESTS)
......
/*******************************************************************************
* Copyright 2019 UChicago Argonne, LLC.
* (c.f. AUTHORS, LICENSE)
*
* This file is part of the EXCIT project.
* For more info, see https://xgitlab.cels.anl.gov/argo/excit
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "excit.h"
#include "excit_test.h"
excit_t create_test_range(ssize_t start, ssize_t stop, ssize_t step)
{
excit_t it;
it = excit_alloc_test(EXCIT_RANGE);
assert(excit_range_init(it, start, stop, step) == ES);
return it;
}
void test_alloc_init_loop(int loop, excit_t sit)
{
excit_t it;
ssize_t dim, expected_dim, size, expected_size;
it = excit_alloc_test(EXCIT_LOOP);
assert(excit_dimension(it, &dim) == ES);
assert(dim == 0);
assert(excit_loop_init(it, excit_dup(sit), loop) == ES);
assert(excit_dimension(it, &dim) == ES);
assert(excit_dimension(sit, &expected_dim) == ES);
assert(dim == expected_dim);
assert(excit_size(sit, &expected_size) == ES);
expected_size *= loop;
assert(excit_size(it, &size) == ES);
assert(size == expected_size);
excit_free(it);
}
excit_t create_test_loop(int loop, excit_t sit)
{
excit_t it;
it = excit_alloc_test(EXCIT_LOOP);
assert(excit_loop_init(it, excit_dup(sit), loop) == ES);
return it;
}
void test_next_loop(int loop, excit_t sit)
{
excit_t it, new_sit;
ssize_t *indexes1, *indexes2;
ssize_t dim;
it = create_test_loop(loop, sit);
new_sit = excit_dup(sit);
assert(excit_dimension(it, &dim) == ES);
indexes1 = (ssize_t *) malloc(dim * sizeof(ssize_t));
indexes2 = (ssize_t *) malloc(dim * sizeof(ssize_t));
for (int i = 0; i < loop; i++) {
while (excit_next(new_sit, indexes1) == ES) {
assert(excit_next(it, indexes2) == ES);
assert(memcmp(indexes1, indexes2, dim * sizeof(ssize_t))
== 0);
}
assert(excit_rewind(new_sit) == ES);
}
assert(excit_next(it, indexes2) == EXCIT_STOPIT);
free(indexes1);
free(indexes2);
excit_free(it);
excit_free(new_sit);
}
void test_loop_iterator(int loop, excit_t sit)
{
test_alloc_init_loop(loop, sit);
test_next_loop(loop, sit);
int i = 0;
while (synthetic_tests[i]) {
excit_t it = create_test_loop(loop, sit);
synthetic_tests[i] (it);
excit_free(it);
i++;
}
}
int main(int argc, char *argv[])
{
excit_t it1, it2, it3;
it1 = create_test_range(0, 3, 1);
test_loop_iterator(3, it1);
it2 = create_test_range(-15, 14, 2);
test_loop_iterator(3, it2);
it3 = excit_alloc_test(EXCIT_PRODUCT);
assert(excit_product_add_copy(it3, it1) == ES);
assert(excit_product_add_copy(it3, it2) == ES);
test_loop_iterator(4, it3);
excit_free(it1);
excit_free(it2);
excit_free(it3);
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