Skip to content

Commit 35ea58d

Browse files
duncanMRmergify[bot]
authored andcommitted
Add tests for tsk_tree_position_seek functions
1 parent b9ee27d commit 35ea58d

File tree

2 files changed

+211
-8
lines changed

2 files changed

+211
-8
lines changed

c/tests/test_trees.c

Lines changed: 204 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* MIT License
33
*
4-
* Copyright (c) 2019-2023 Tskit Developers
4+
* Copyright (c) 2019-2024 Tskit Developers
55
*
66
* Permission is hereby granted, free of charge, to any person obtaining a copy
77
* of this software and associated documentation files (the "Software"), to deal
@@ -182,6 +182,8 @@ verify_tree_pos(const tsk_treeseq_t *ts, tsk_size_t num_trees, tsk_id_t *tree_pa
182182
const tsk_size_t N = tsk_treeseq_get_num_nodes(ts);
183183
const tsk_id_t *edges_parent = ts->tables->edges.parent;
184184
const tsk_id_t *edges_child = ts->tables->edges.child;
185+
const double *restrict edges_left = ts->tables->edges.left;
186+
const double *restrict edges_right = ts->tables->edges.right;
185187
tsk_tree_position_t tree_pos;
186188
tsk_id_t *known_parent;
187189
tsk_id_t *parent = tsk_malloc(N * sizeof(*parent));
@@ -262,7 +264,62 @@ verify_tree_pos(const tsk_treeseq_t *ts, tsk_size_t num_trees, tsk_id_t *tree_pa
262264
CU_ASSERT_EQUAL(parent[u], TSK_NULL);
263265
}
264266

265-
tsk_tree_position_free(&tree_pos);
267+
for (index = 0; index < (tsk_id_t) num_trees; index++) {
268+
known_parent = tree_parents + N * (tsk_size_t) index;
269+
ret = tsk_tree_position_init(&tree_pos, ts, 0);
270+
CU_ASSERT_EQUAL_FATAL(ret, 0);
271+
272+
ret = tsk_tree_position_seek_forward(&tree_pos, index);
273+
CU_ASSERT_EQUAL_FATAL(ret, 0);
274+
CU_ASSERT_EQUAL(index, tree_pos.index);
275+
276+
for (j = tree_pos.in.start; j != tree_pos.in.stop; j++) {
277+
e = tree_pos.in.order[j];
278+
if (edges_left[e] <= tree_pos.interval.left
279+
&& tree_pos.interval.left < edges_right[e]) {
280+
parent[edges_child[e]] = edges_parent[e];
281+
}
282+
}
283+
for (u = 0; u < (tsk_id_t) N; u++) {
284+
CU_ASSERT_EQUAL(parent[u], known_parent[u]);
285+
}
286+
287+
tsk_tree_position_free(&tree_pos);
288+
for (u = 0; u < (tsk_id_t) N; u++) {
289+
parent[u] = TSK_NULL;
290+
}
291+
}
292+
293+
valid = tsk_tree_position_next(&tree_pos);
294+
CU_ASSERT_FALSE(valid);
295+
296+
for (index = (tsk_id_t) num_trees - 1; index >= 0; index--) {
297+
known_parent = tree_parents + N * (tsk_size_t) index;
298+
ret = tsk_tree_position_init(&tree_pos, ts, 0);
299+
CU_ASSERT_EQUAL_FATAL(ret, 0);
300+
301+
ret = tsk_tree_position_seek_backward(&tree_pos, index);
302+
CU_ASSERT_EQUAL_FATAL(ret, 0);
303+
CU_ASSERT_EQUAL(index, tree_pos.index);
304+
305+
for (j = tree_pos.in.start; j != tree_pos.in.stop; j--) {
306+
e = tree_pos.in.order[j];
307+
if (edges_right[e] >= tree_pos.interval.right
308+
&& tree_pos.interval.right > edges_left[e]) {
309+
parent[edges_child[e]] = edges_parent[e];
310+
}
311+
}
312+
313+
for (u = 0; u < (tsk_id_t) N; u++) {
314+
CU_ASSERT_EQUAL(parent[u], known_parent[u]);
315+
}
316+
317+
for (u = 0; u < (tsk_id_t) N; u++) {
318+
parent[u] = TSK_NULL;
319+
}
320+
tsk_tree_position_free(&tree_pos);
321+
}
322+
266323
tsk_safe_free(parent);
267324
}
268325

@@ -5350,6 +5407,7 @@ test_single_tree_tree_pos(void)
53505407
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 0);
53515408
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 0);
53525409
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_removal_order);
5410+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_FORWARD);
53535411

53545412
valid = tsk_tree_position_next(&tree_pos);
53555413
CU_ASSERT_FATAL(!valid);
@@ -5360,6 +5418,7 @@ test_single_tree_tree_pos(void)
53605418
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 0);
53615419
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 6);
53625420
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_removal_order);
5421+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_FORWARD);
53635422

53645423
valid = tsk_tree_position_prev(&tree_pos);
53655424
CU_ASSERT_FATAL(valid);
@@ -5372,6 +5431,7 @@ test_single_tree_tree_pos(void)
53725431
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 5);
53735432
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 5);
53745433
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_insertion_order);
5434+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_REVERSE);
53755435

53765436
valid = tsk_tree_position_prev(&tree_pos);
53775437
CU_ASSERT_FATAL(!valid);
@@ -5380,6 +5440,42 @@ test_single_tree_tree_pos(void)
53805440
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 5);
53815441
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, -1);
53825442
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_insertion_order);
5443+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_REVERSE);
5444+
5445+
ret = tsk_tree_position_seek_forward(&tree_pos, 0);
5446+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5447+
5448+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.left, 0);
5449+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.right, 1);
5450+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.start, 0);
5451+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.stop, 6);
5452+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.order, ts.tables->indexes.edge_insertion_order);
5453+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 0);
5454+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 0);
5455+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_removal_order)
5456+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_FORWARD);
5457+
5458+
valid = tsk_tree_position_next(&tree_pos);
5459+
CU_ASSERT_FATAL(!valid);
5460+
5461+
CU_ASSERT_EQUAL_FATAL(tree_pos.index, -1);
5462+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 0);
5463+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 6);
5464+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_removal_order);
5465+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_FORWARD);
5466+
5467+
ret = tsk_tree_position_seek_backward(&tree_pos, 0);
5468+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5469+
5470+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.left, 0);
5471+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.right, 1);
5472+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.start, 5);
5473+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.stop, -1);
5474+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.order, ts.tables->indexes.edge_removal_order);
5475+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 5);
5476+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 5);
5477+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_insertion_order);
5478+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_REVERSE);
53835479

53845480
tsk_tree_position_free(&tree_pos);
53855481
tsk_treeseq_free(&ts);
@@ -5409,6 +5505,110 @@ test_simple_multi_tree(void)
54095505
tsk_treeseq_free(&ts);
54105506
}
54115507

5508+
static void
5509+
test_multi_tree_direction_switching_tree_pos(void)
5510+
{
5511+
tsk_treeseq_t ts;
5512+
tsk_tree_position_t tree_pos;
5513+
bool valid;
5514+
int ret = 0;
5515+
5516+
tsk_treeseq_from_text(&ts, 10, paper_ex_nodes, paper_ex_edges, NULL, paper_ex_sites,
5517+
paper_ex_mutations, paper_ex_individuals, NULL, 0);
5518+
5519+
ret = tsk_tree_position_init(&tree_pos, &ts, 0);
5520+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5521+
valid = tsk_tree_position_next(&tree_pos);
5522+
CU_ASSERT_FATAL(valid);
5523+
5524+
CU_ASSERT_EQUAL_FATAL(tree_pos.index, 0);
5525+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.left, 0);
5526+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.right, 2);
5527+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.start, 0);
5528+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.stop, 6);
5529+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.order, ts.tables->indexes.edge_insertion_order);
5530+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 0);
5531+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 0);
5532+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_removal_order);
5533+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_FORWARD);
5534+
5535+
valid = tsk_tree_position_prev(&tree_pos);
5536+
CU_ASSERT_FATAL(!valid);
5537+
5538+
CU_ASSERT_EQUAL_FATAL(tree_pos.index, -1);
5539+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 5);
5540+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, -1);
5541+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_insertion_order);
5542+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_REVERSE);
5543+
5544+
valid = tsk_tree_position_prev(&tree_pos);
5545+
CU_ASSERT_FATAL(valid);
5546+
5547+
CU_ASSERT_EQUAL_FATAL(tree_pos.index, 2);
5548+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.left, 7);
5549+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.right, 10);
5550+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.start, 10);
5551+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.stop, 4);
5552+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.order, ts.tables->indexes.edge_removal_order);
5553+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 10);
5554+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 10);
5555+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_insertion_order);
5556+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_REVERSE);
5557+
5558+
valid = tsk_tree_position_next(&tree_pos);
5559+
CU_ASSERT_FATAL(!valid);
5560+
5561+
CU_ASSERT_EQUAL_FATAL(tree_pos.index, -1);
5562+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 5);
5563+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 11);
5564+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_removal_order);
5565+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_FORWARD);
5566+
5567+
ret = tsk_tree_position_seek_forward(&tree_pos, 2);
5568+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5569+
5570+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.left, 7);
5571+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.right, 10);
5572+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.start, 0);
5573+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.stop, 11);
5574+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.order, ts.tables->indexes.edge_insertion_order);
5575+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 5);
5576+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 5);
5577+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_removal_order);
5578+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_FORWARD);
5579+
5580+
ret = tsk_tree_position_seek_backward(&tree_pos, 0);
5581+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5582+
5583+
CU_ASSERT_EQUAL_FATAL(tree_pos.index, 0);
5584+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.left, 0);
5585+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.right, 2);
5586+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.start, 4);
5587+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.stop, -1);
5588+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.order, ts.tables->indexes.edge_removal_order);
5589+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 10);
5590+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 5);
5591+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_insertion_order);
5592+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_REVERSE);
5593+
5594+
ret = tsk_tree_position_seek_forward(&tree_pos, 2);
5595+
CU_ASSERT_EQUAL_FATAL(ret, 0);
5596+
5597+
CU_ASSERT_EQUAL_FATAL(tree_pos.index, 2);
5598+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.left, 7);
5599+
CU_ASSERT_EQUAL_FATAL(tree_pos.interval.right, 10);
5600+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.start, 6);
5601+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.stop, 11);
5602+
CU_ASSERT_EQUAL_FATAL(tree_pos.in.order, ts.tables->indexes.edge_insertion_order);
5603+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.start, 0);
5604+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.stop, 5);
5605+
CU_ASSERT_EQUAL_FATAL(tree_pos.out.order, ts.tables->indexes.edge_removal_order);
5606+
CU_ASSERT_EQUAL_FATAL(tree_pos.direction, TSK_DIR_FORWARD);
5607+
5608+
tsk_tree_position_free(&tree_pos);
5609+
tsk_treeseq_free(&ts);
5610+
}
5611+
54125612
static void
54135613
test_unary_multi_tree(void)
54145614
{
@@ -8501,6 +8701,8 @@ main(int argc, char **argv)
85018701

85028702
/* Multi tree tests */
85038703
{ "test_simple_multi_tree", test_simple_multi_tree },
8704+
{ "test_multi_tree_direction_switching_tree_pos",
8705+
test_multi_tree_direction_switching_tree_pos },
85048706
{ "test_nonbinary_multi_tree", test_nonbinary_multi_tree },
85058707
{ "test_unary_multi_tree", test_unary_multi_tree },
85068708
{ "test_internal_sample_multi_tree", test_internal_sample_multi_tree },

c/tskit/trees.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5741,6 +5741,8 @@ tsk_tree_seek_from_null(tsk_tree_t *self, double x, tsk_flags_t TSK_UNUSED(optio
57415741
const tsk_id_t *restrict edge_child = tables->edges.child;
57425742
const double *restrict edge_left = tables->edges.left;
57435743
const double *restrict edge_right = tables->edges.right;
5744+
double interval_left = self->interval.left;
5745+
double interval_right = self->interval.right;
57445746
const double *restrict breakpoints = self->tree_sequence->breakpoints;
57455747
const tsk_size_t num_trees = self->tree_sequence->num_trees;
57465748
const double L = tsk_treeseq_get_sequence_length(self->tree_sequence);
@@ -5756,11 +5758,10 @@ tsk_tree_seek_from_null(tsk_tree_t *self, double x, tsk_flags_t TSK_UNUSED(optio
57565758
if (ret != 0) {
57575759
goto out;
57585760
}
5759-
tsk_tree_update_index_and_interval(self);
5761+
interval_left = self->tree_pos.interval.left;
57605762
for (j = self->tree_pos.in.start; j != self->tree_pos.in.stop; j++) {
57615763
e = self->tree_pos.in.order[j];
5762-
if (edge_left[e] <= self->interval.left
5763-
&& self->interval.left < edge_right[e]) {
5764+
if (edge_left[e] <= interval_left && interval_left < edge_right[e]) {
57645765
tsk_tree_insert_edge(self, edge_parent[e], edge_child[e], e);
57655766
}
57665767
}
@@ -5769,15 +5770,15 @@ tsk_tree_seek_from_null(tsk_tree_t *self, double x, tsk_flags_t TSK_UNUSED(optio
57695770
if (ret != 0) {
57705771
goto out;
57715772
}
5772-
tsk_tree_update_index_and_interval(self);
5773+
interval_right = self->tree_pos.interval.right;
57735774
for (j = self->tree_pos.in.start; j != self->tree_pos.in.stop; j--) {
57745775
e = self->tree_pos.in.order[j];
5775-
if (edge_right[e] >= self->interval.right
5776-
&& self->interval.right > edge_left[e]) {
5776+
if (edge_right[e] >= interval_right && interval_right > edge_left[e]) {
57775777
tsk_tree_insert_edge(self, edge_parent[e], edge_child[e], e);
57785778
}
57795779
}
57805780
}
5781+
tsk_tree_update_index_and_interval(self);
57815782
out:
57825783
return ret;
57835784
}

0 commit comments

Comments
 (0)