Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
argo
excit
Commits
8bf1ee7c
Commit
8bf1ee7c
authored
Jan 25, 2019
by
Brice Videau
Browse files
Merge branch 'index' into 'master'
Index See merge request
!8
parents
c617c134
e886e6f0
Changes
12
Hide whitespace changes
Inline
Side-by-side
src/Makefile.am
View file @
8bf1ee7c
...
...
@@ -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 tleaf.c
libexcit_la_SOURCES
=
excit.c composition.c prod.c cons.c repeat.c hilbert2d.c range.c
index.c
tleaf.c
include_HEADERS
=
excit.h
src/cons.c
View file @
8bf1ee7c
...
...
@@ -151,12 +151,15 @@ static int cons_it_peek(const excit_t data, ssize_t *indexes)
int
n
=
it
->
n
;
if
(
indexes
)
{
circular_fifo_dump
(
&
it
->
fifo
,
indexes
);
err
=
excit_peek
(
it
->
it
,
indexes
+
dim
*
(
n
-
1
));
if
(
err
)
return
err
;
circular_fifo_dump
(
&
it
->
fifo
,
indexes
);
}
else
err
=
excit_peek
(
it
->
it
,
NULL
);
if
(
err
)
return
err
;
return
EXCIT_SUCCESS
;
}
...
...
@@ -167,9 +170,11 @@ static int cons_it_next(excit_t data, ssize_t *indexes)
int
dim
=
it
->
it
->
dimension
;
int
n
=
it
->
n
;
if
(
indexes
)
{
circular_fifo_dump
(
&
it
->
fifo
,
indexes
);
if
(
indexes
)
{
err
=
excit_next
(
it
->
it
,
indexes
+
dim
*
(
n
-
1
));
if
(
err
)
return
err
;
circular_fifo_dump
(
&
it
->
fifo
,
indexes
);
}
else
err
=
excit_next
(
it
->
it
,
NULL
);
if
(
err
)
...
...
src/excit.c
View file @
8bf1ee7c
...
...
@@ -7,6 +7,7 @@
#include
"repeat.h"
#include
"hilbert2d.h"
#include
"range.h"
#include
"index.h"
#include
"tleaf.h"
#define CASE(val) case val: return #val; break
...
...
@@ -14,6 +15,7 @@
const
char
*
excit_type_name
(
enum
excit_type_e
type
)
{
switch
(
type
)
{
CASE
(
EXCIT_INDEX
);
CASE
(
EXCIT_RANGE
);
CASE
(
EXCIT_CONS
);
CASE
(
EXCIT_REPEAT
);
...
...
@@ -100,6 +102,9 @@ excit_t excit_alloc(enum excit_type_e type)
excit_t
it
=
NULL
;
switch
(
type
)
{
case
EXCIT_INDEX
:
ALLOC_EXCIT
(
index
);
break
;
case
EXCIT_RANGE
:
ALLOC_EXCIT
(
range
);
break
;
...
...
src/excit.h
View file @
8bf1ee7c
...
...
@@ -31,6 +31,11 @@
enum
excit_type_e
{
/*!< Tag for invalid iterators */
EXCIT_INVALID
,
/*!<
* Iterator over an array of indexes.
* If indexes are uniques, the iterator is made inversible (see excit_rank()).
*/
EXCIT_INDEX
,
/*!<
* Iterator over a range of values.
* See function excit_range_init for further details on iterator
...
...
@@ -383,6 +388,11 @@ int excit_skip(excit_t it);
*/
int
excit_cyclic_next
(
excit_t
it
,
ssize_t
*
indexes
,
int
*
looped
);
/*
* Initialize an index iterator with a set of indexes.
*/
int
excit_index_init
(
excit_t
it
,
const
ssize_t
len
,
const
ssize_t
*
index
);
/*
* Initializes a range iterator to iterate from first to last (included) by step.
* "it": a range iterator.
...
...
src/index.c
0 → 100644
View file @
8bf1ee7c
#include
<stdlib.h>
#include
<stdio.h>
#include
<string.h>
#include
"dev/excit.h"
#include
"index.h"
static
int
comp_index_val
(
const
void
*
a_ptr
,
const
void
*
b_ptr
)
{
const
struct
index_s
*
a
=
a_ptr
;
const
struct
index_s
*
b
=
b_ptr
;
if
(
a
->
sorted_value
<
b
->
sorted_value
)
return
-
1
;
if
(
a
->
sorted_value
>
b
->
sorted_value
)
return
1
;
return
0
;
}
static
struct
index_s
*
make_index
(
const
ssize_t
len
,
const
ssize_t
*
values
)
{
ssize_t
i
;
struct
index_s
*
index
=
malloc
((
len
)
*
sizeof
(
*
index
));
if
(
index
==
NULL
)
return
NULL
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
index
[
i
].
sorted_value
=
values
[
i
];
index
[
i
].
sorted_index
=
i
;
}
qsort
(
index
,
len
,
sizeof
(
*
index
),
comp_index_val
);
for
(
i
=
0
;
i
<
len
;
i
++
)
index
[
i
].
value
=
values
[
i
];
return
index
;
}
static
inline
struct
index_s
*
copy_index
(
const
ssize_t
len
,
const
struct
index_s
*
x
)
{
struct
index_s
*
index
=
malloc
((
len
)
*
sizeof
(
*
index
));
if
(
index
==
NULL
)
return
NULL
;
memcpy
(
index
,
x
,
(
len
)
*
sizeof
(
*
x
));
return
index
;
}
static
inline
struct
index_s
*
search_index
(
const
ssize_t
val
,
const
ssize_t
len
,
const
struct
index_s
*
x
)
{
struct
index_s
key
=
{
0
,
val
,
0
};
return
bsearch
(
&
key
,
x
,
len
,
sizeof
(
*
x
),
comp_index_val
);
}
static
inline
ssize_t
search_index_pos
(
const
ssize_t
val
,
const
ssize_t
len
,
const
struct
index_s
*
x
)
{
struct
index_s
*
found
=
search_index
(
val
,
len
,
x
);
if
(
found
==
NULL
)
return
-
1
;
return
found
->
sorted_index
;
}
/******************************************************************************/
static
int
index_it_alloc
(
excit_t
it
)
{
it
->
dimension
=
1
;
struct
index_it_s
*
data_it
=
it
->
data
;
data_it
->
pos
=
0
;
data_it
->
len
=
0
;
data_it
->
inversible
=
0
;
data_it
->
index
=
NULL
;
return
EXCIT_SUCCESS
;
}
static
void
index_it_free
(
excit_t
it
)
{
struct
index_it_s
*
data_it
=
it
->
data
;
if
(
data_it
->
index
!=
NULL
)
free
(
data_it
->
index
);
}
static
int
index_it_size
(
const
excit_t
it
,
ssize_t
*
size
)
{
struct
index_it_s
*
data_it
=
it
->
data
;
*
size
=
data_it
->
len
;
return
EXCIT_SUCCESS
;
}
static
int
index_it_rewind
(
excit_t
it
)
{
struct
index_it_s
*
data_it
=
it
->
data
;
data_it
->
pos
=
0
;
return
EXCIT_SUCCESS
;
}
static
int
index_it_copy
(
excit_t
dst_it
,
const
excit_t
src_it
)
{
int
err
=
EXCIT_SUCCESS
;
struct
index_it_s
*
dst
=
dst_it
->
data
;
struct
index_it_s
*
src
=
src_it
->
data
;
dst
->
pos
=
src
->
pos
;
dst
->
len
=
src
->
len
;
if
(
src
->
len
==
0
)
return
EXCIT_SUCCESS
;
if
(
src
->
index
!=
NULL
)
{
dst
->
index
=
copy_index
(
src
->
len
,
src
->
index
);
if
(
dst
->
index
==
NULL
)
{
err
=
-
EXCIT_ENOMEM
;
goto
exit_with_values
;
}
}
return
EXCIT_SUCCESS
;
exit_with_values:
free
(
dst
->
index
);
dst
->
index
=
NULL
;
return
err
;
}
static
int
index_it_pos
(
const
excit_t
it
,
ssize_t
*
value
)
{
if
(
value
==
NULL
)
return
EXCIT_SUCCESS
;
struct
index_it_s
*
data_it
=
it
->
data
;
*
value
=
data_it
->
pos
;
if
(
data_it
->
pos
>=
data_it
->
len
)
return
EXCIT_STOPIT
;
return
EXCIT_SUCCESS
;
}
static
int
index_it_nth
(
const
excit_t
it
,
ssize_t
n
,
ssize_t
*
indexes
)
{
struct
index_it_s
*
data_it
=
it
->
data
;
if
(
n
<
0
||
n
>=
data_it
->
len
)
return
-
EXCIT_EDOM
;
if
(
indexes
)
*
indexes
=
data_it
->
index
[
n
].
value
;
return
EXCIT_SUCCESS
;
}
static
int
index_it_peek
(
const
excit_t
it
,
ssize_t
*
value
)
{
struct
index_it_s
*
data_it
=
it
->
data
;
if
(
data_it
->
pos
>=
data_it
->
len
)
return
EXCIT_STOPIT
;
if
(
value
)
*
value
=
data_it
->
index
[
data_it
->
pos
].
value
;
return
EXCIT_SUCCESS
;
}
static
int
index_it_next
(
excit_t
it
,
ssize_t
*
indexes
)
{
struct
index_it_s
*
data_it
=
it
->
data
;
if
(
data_it
->
pos
>=
data_it
->
len
)
return
EXCIT_STOPIT
;
if
(
indexes
)
*
indexes
=
data_it
->
index
[
data_it
->
pos
].
value
;
data_it
->
pos
++
;
return
EXCIT_SUCCESS
;
}
static
int
index_it_rank
(
const
excit_t
it
,
const
ssize_t
*
indexes
,
ssize_t
*
n
)
{
struct
index_it_s
*
data_it
=
it
->
data
;
if
(
!
data_it
->
inversible
)
return
-
EXCIT_ENOTSUP
;
if
(
indexes
==
NULL
)
return
EXCIT_SUCCESS
;
if
(
*
indexes
<
data_it
->
index
[
0
].
sorted_value
||
*
indexes
>=
data_it
->
index
[
data_it
->
len
-
1
].
sorted_value
)
return
-
EXCIT_EDOM
;
if
(
n
!=
NULL
)
*
n
=
search_index_pos
(
*
indexes
,
data_it
->
len
,
data_it
->
index
);
return
EXCIT_SUCCESS
;
}
int
excit_index_init
(
excit_t
it
,
const
ssize_t
len
,
const
ssize_t
*
index
)
{
ssize_t
i
;
if
(
it
==
NULL
||
it
->
data
==
NULL
)
return
-
EXCIT_EINVAL
;
struct
index_it_s
*
data_it
=
it
->
data
;
data_it
->
len
=
len
;
data_it
->
index
=
make_index
(
len
,
index
);
if
(
data_it
->
index
==
NULL
)
return
-
EXCIT_ENOMEM
;
// Check for duplicates
data_it
->
inversible
=
1
;
for
(
i
=
1
;
i
<
len
;
i
++
)
if
(
data_it
->
index
[
i
].
sorted_value
==
data_it
->
index
[
i
-
1
].
sorted_value
)
{
data_it
->
inversible
=
0
;
break
;
}
return
EXCIT_SUCCESS
;
}
struct
excit_func_table_s
excit_index_func_table
=
{
index_it_alloc
,
index_it_free
,
index_it_copy
,
index_it_next
,
index_it_peek
,
index_it_size
,
index_it_rewind
,
NULL
,
index_it_nth
,
index_it_rank
,
index_it_pos
};
src/index.h
0 → 100644
View file @
8bf1ee7c
#ifndef EXCIT_INDEX_H
#define EXCIT_INDEX_H
struct
index_s
{
ssize_t
value
;
ssize_t
sorted_value
;
ssize_t
sorted_index
;
};
struct
index_it_s
{
ssize_t
pos
;
ssize_t
len
;
struct
index_s
*
index
;
int
inversible
;
};
extern
struct
excit_func_table_s
excit_index_func_table
;
#endif //EXCIT_INDEX_H
src/prod.c
View file @
8bf1ee7c
#include
<string.h>
#include
"dev/excit.h"
#include
"prod.h"
...
...
@@ -7,6 +8,7 @@ static int prod_it_alloc(excit_t data)
it
->
count
=
0
;
it
->
its
=
NULL
;
it
->
buff
=
NULL
;
return
EXCIT_SUCCESS
;
}
...
...
@@ -18,6 +20,7 @@ static void prod_it_free(excit_t data)
for
(
ssize_t
i
=
0
;
i
<
it
->
count
;
i
++
)
excit_free
(
it
->
its
[
i
]);
free
(
it
->
its
);
free
(
it
->
buff
);
}
}
...
...
@@ -29,6 +32,12 @@ static int prod_it_copy(excit_t dst, const excit_t src)
result
->
its
=
(
excit_t
*
)
malloc
(
it
->
count
*
sizeof
(
excit_t
));
if
(
!
result
->
its
)
return
-
EXCIT_ENOMEM
;
result
->
buff
=
(
ssize_t
*
)
malloc
(
src
->
dimension
*
sizeof
(
ssize_t
));
if
(
!
result
->
buff
){
free
(
result
->
its
);
return
-
EXCIT_ENOMEM
;
}
ssize_t
i
;
for
(
i
=
0
;
i
<
it
->
count
;
i
++
)
{
...
...
@@ -184,11 +193,8 @@ static inline int prod_it_peeknext_helper(excit_t data, ssize_t *indexes,
return
-
EXCIT_EINVAL
;
looped
=
next
;
for
(
i
=
it
->
count
-
1
;
i
>
0
;
i
--
)
{
if
(
indexes
)
{
offset
-=
it
->
its
[
i
]
->
dimension
;
next_indexes
=
indexes
+
offset
;
}
else
next_indexes
=
NULL
;
offset
-=
it
->
its
[
i
]
->
dimension
;
next_indexes
=
it
->
buff
+
offset
;
if
(
looped
)
err
=
excit_cyclic_next
(
it
->
its
[
i
],
next_indexes
,
&
looped
);
...
...
@@ -197,17 +203,17 @@ static inline int prod_it_peeknext_helper(excit_t data, ssize_t *indexes,
if
(
err
)
return
err
;
}
if
(
indexes
)
{
offset
-=
it
->
its
[
i
]
->
dimension
;
next_indexes
=
indexes
+
offset
;
}
else
next_indexes
=
NULL
;
offset
-=
it
->
its
[
i
]
->
dimension
;
next_indexes
=
it
->
buff
+
offset
;
if
(
looped
)
err
=
excit_next
(
it
->
its
[
0
],
next_indexes
);
else
err
=
excit_peek
(
it
->
its
[
0
],
next_indexes
);
if
(
err
)
return
err
;
if
(
indexes
)
memcpy
(
indexes
,
it
->
buff
,
data
->
dimension
*
sizeof
(
ssize_t
));
return
EXCIT_SUCCESS
;
}
...
...
@@ -288,6 +294,8 @@ int excit_product_add_copy(excit_t it, excit_t added_it)
int
excit_product_add
(
excit_t
it
,
excit_t
added_it
)
{
int
err
=
EXCIT_SUCCESS
;
if
(
!
it
||
it
->
type
!=
EXCIT_PRODUCT
||
!
it
->
data
||
!
added_it
)
return
-
EXCIT_EINVAL
;
...
...
@@ -295,14 +303,30 @@ int excit_product_add(excit_t it, excit_t added_it)
ssize_t
mew_count
=
prod_it
->
count
+
1
;
excit_t
*
new_its
=
(
excit_t
*
)
realloc
(
prod_it
->
its
,
mew_count
*
sizeof
(
excit_t
));
(
excit_t
*
)
realloc
(
prod_it
->
its
,
mew_count
*
sizeof
(
excit_t
));
if
(
!
new_its
)
return
-
EXCIT_ENOMEM
;
ssize_t
*
new_buff
=
realloc
(
prod_it
->
buff
,
(
added_it
->
dimension
+
it
->
dimension
)
*
sizeof
(
ssize_t
));
if
(
!
new_buff
){
err
=
-
EXCIT_ENOMEM
;
goto
exit_with_new_its
;
}
prod_it
->
its
=
new_its
;
prod_it
->
buff
=
new_buff
;
prod_it
->
its
[
prod_it
->
count
]
=
added_it
;
prod_it
->
count
=
mew_count
;
it
->
dimension
+=
added_it
->
dimension
;
return
EXCIT_SUCCESS
;
exit_with_new_its:
free
(
new_its
);
return
err
;
}
struct
excit_func_table_s
excit_prod_func_table
=
{
...
...
src/prod.h
View file @
8bf1ee7c
...
...
@@ -6,6 +6,7 @@
struct
prod_it_s
{
ssize_t
count
;
ssize_t
*
buff
;
excit_t
*
its
;
};
...
...
src/tleaf.c
View file @
8bf1ee7c
...
...
@@ -13,8 +13,6 @@ static int tleaf_init_with_it(excit_t 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
;
...
...
@@ -123,7 +121,7 @@ static ssize_t tleaf_it_value(struct tleaf_it_s *it)
return
val
;
}
int
tleaf_it_nth
(
const
excit_t
it
,
ssize_t
n
,
ssize_t
*
indexes
)
static
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
);
...
...
@@ -135,7 +133,7 @@ int tleaf_it_nth(const excit_t it, ssize_t n, ssize_t *indexes)
return
EXCIT_SUCCESS
;
}
int
tleaf_it_peek
(
const
excit_t
it
,
ssize_t
*
value
)
static
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
);
...
...
@@ -147,7 +145,7 @@ int tleaf_it_peek(const excit_t it, ssize_t *value)
return
EXCIT_SUCCESS
;
}
int
tleaf_it_next
(
excit_t
it
,
ssize_t
*
indexes
)
static
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
);
...
...
@@ -160,7 +158,7 @@ int tleaf_it_next(excit_t it, ssize_t *indexes)
return
EXCIT_SUCCESS
;
}
int
tleaf_it_rank
(
const
excit_t
it
,
const
ssize_t
*
indexes
,
ssize_t
*
n
)
static
int
tleaf_it_rank
(
const
excit_t
it
,
const
ssize_t
*
indexes
,
ssize_t
*
n
)
{
ssize_t
size
;
int
err
;
...
...
@@ -190,7 +188,7 @@ int tleaf_it_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
return
EXCIT_SUCCESS
;
}
int
tleaf_it_make_levels
(
struct
tleaf_it_s
*
tleaf
,
const
excit_t
*
indexes
,
static
int
tleaf_it_make_levels
(
struct
tleaf_it_s
*
tleaf
,
const
excit_t
*
indexes
,
ssize_t
*
order
,
excit_t
*
levels
)
{
ssize_t
i
;
...
...
@@ -370,7 +368,7 @@ int excit_tleaf_init(excit_t it,
user_policy
,
NULL
,
NULL
);
}
int
tleaf_split_levels
(
excit_t
levels
,
const
ssize_t
depth
,
const
ssize_t
n
,
static
int
tleaf_split_levels
(
excit_t
levels
,
const
ssize_t
depth
,
const
ssize_t
n
,
excit_t
**
out
)
{
*
out
=
malloc
(
sizeof
(
**
out
)
*
n
);
...
...
tests/Makefile.am
View file @
8bf1ee7c
...
...
@@ -6,6 +6,7 @@ AM_LDFLAGS = ../src/libexcit.la
LIBHSOURCES
=
excit_test.h
LIBCSOURCES
=
excit_test.c
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
...
...
@@ -14,7 +15,7 @@ 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_tleaf
UNIT_TESTS
=
excit_range excit_product excit_repeat excit_cons excit_hilbert2d excit_composition
excit_index
excit_tleaf
# all tests
check_PROGRAMS
=
$(UNIT_TESTS)
...
...
tests/excit_index.c
0 → 100644
View file @
8bf1ee7c
#include
<assert.h>
#include
<stdlib.h>
#include
<sys/time.h>
#include
"excit.h"
#include
"excit_test.h"
#define NTESTS 1
#define MAX_LEN 4096
#define MIN_LEN 16
static
void
rand_seed
(
void
)
{
struct
timeval
tv
;
unsigned
int
us
;
gettimeofday
(
&
tv
,
NULL
);
us
=
(
unsigned
int
)(
1000000
*
tv
.
tv_sec
+
tv
.
tv_usec
);
srand
(
us
);
}
static
void
shuffle
(
const
ssize_t
len
,
ssize_t
*
x
)
{
ssize_t
i
,
swap
,
rnd
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
swap
=
x
[
i
];
rnd
=
rand
()
%
(
len
-
i
);
x
[
i
]
=
x
[
i
+
rnd
];
x
[
i
+
rnd
]
=
swap
;
}
}
static
ssize_t
*
make_unique_index
(
const
ssize_t
len
)
{
ssize_t
i
;
ssize_t
*
index
=
malloc
(
len
*
sizeof
(
*
index
));
assert
(
index
!=
NULL
);
for
(
i
=
0
;
i
<
len
;
i
++
)
index
[
i
]
=
i
;
shuffle
(
len
,
index
);
return
index
;
}
static
ssize_t
*
make_index
(
const
ssize_t
len
)
{
ssize_t
i
;
ssize_t
*
index
=
malloc
(
len
*
sizeof
(
*
index
));
assert
(
index
!=
NULL
);
for
(
i
=
0
;
i
<
len
;
i
++
)
index
[
i
]
=
rand
()
%
len
;
return
index
;
}
void
run_tests
(
const
ssize_t
len
,
const
ssize_t
*
index
)
{
ssize_t
i
=
0
;
excit_t
it
;
while
(
synthetic_tests
[
i
])
{
it
=
excit_alloc
(
EXCIT_INDEX
);
assert
(
it
!=
NULL
);
assert
(
excit_index_init
(
it
,
len
,
index
)
==
EXCIT_SUCCESS
);
synthetic_tests
[
i
]
(
it
);
excit_free
(
it
);
i
++
;
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
ssize_t
n
=
NTESTS
;
rand_seed
();
while
(
n
--
)
{
ssize_t
len
=
MIN_LEN
+
rand
()
%
(
MAX_LEN
-
MIN_LEN
);
ssize_t
*
uind
=
make_unique_index
(
len
);
run_tests
(
len
,
uind
);
free
(
uind
);
ssize_t
*
ind
=
make_index
(
len
);
run_tests
(
len
,
ind
);
free
(
ind
);
}