Skip to content

Commit d47dd78

Browse files
populations
1 parent b8d8e44 commit d47dd78

File tree

3 files changed

+158
-0
lines changed

3 files changed

+158
-0
lines changed

c/tests/test_tables.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3820,6 +3820,67 @@ test_population_table(void)
38203820
free(metadata_offset);
38213821
}
38223822

3823+
static void
3824+
test_population_table_update_row(void)
3825+
{
3826+
int ret;
3827+
tsk_id_t ret_id;
3828+
tsk_population_table_t table;
3829+
tsk_population_t row;
3830+
const char *metadata = "ABC";
3831+
3832+
ret = tsk_population_table_init(&table, 0);
3833+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3834+
3835+
ret_id = tsk_population_table_add_row(&table, metadata, 1);
3836+
CU_ASSERT_FATAL(ret_id >= 0);
3837+
ret_id = tsk_population_table_add_row(&table, metadata, 2);
3838+
CU_ASSERT_FATAL(ret_id >= 0);
3839+
ret_id = tsk_population_table_add_row(&table, metadata, 3);
3840+
CU_ASSERT_FATAL(ret_id >= 0);
3841+
3842+
ret = tsk_population_table_update_row(&table, 0, &metadata[1], 1);
3843+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3844+
ret = tsk_population_table_get_row(&table, 0, &row);
3845+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3846+
CU_ASSERT_EQUAL_FATAL(row.metadata_length, 1);
3847+
CU_ASSERT_EQUAL_FATAL(row.metadata[0], 'B');
3848+
3849+
ret = tsk_population_table_update_row(&table, 0, row.metadata, row.metadata_length);
3850+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3851+
ret = tsk_population_table_get_row(&table, 0, &row);
3852+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3853+
CU_ASSERT_EQUAL_FATAL(row.metadata_length, 1);
3854+
CU_ASSERT_EQUAL_FATAL(row.metadata[0], 'B');
3855+
3856+
ret = tsk_population_table_update_row(&table, 0, metadata, 3);
3857+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3858+
ret = tsk_population_table_get_row(&table, 0, &row);
3859+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3860+
CU_ASSERT_EQUAL_FATAL(row.metadata_length, 3);
3861+
CU_ASSERT_EQUAL_FATAL(row.metadata[0], 'A');
3862+
CU_ASSERT_EQUAL_FATAL(row.metadata[1], 'B');
3863+
CU_ASSERT_EQUAL_FATAL(row.metadata[2], 'C');
3864+
3865+
ret = tsk_population_table_update_row(&table, 1, NULL, 0);
3866+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3867+
ret = tsk_population_table_get_row(&table, 1, &row);
3868+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3869+
CU_ASSERT_EQUAL_FATAL(row.metadata_length, 0);
3870+
3871+
ret = tsk_population_table_get_row(&table, 2, &row);
3872+
CU_ASSERT_EQUAL_FATAL(ret, 0);
3873+
CU_ASSERT_EQUAL_FATAL(row.metadata_length, 3);
3874+
CU_ASSERT_EQUAL_FATAL(row.metadata[0], 'A');
3875+
CU_ASSERT_EQUAL_FATAL(row.metadata[1], 'B');
3876+
CU_ASSERT_EQUAL_FATAL(row.metadata[2], 'C');
3877+
3878+
ret = tsk_population_table_update_row(&table, 3, NULL, 0);
3879+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_POPULATION_OUT_OF_BOUNDS);
3880+
3881+
tsk_population_table_free(&table);
3882+
}
3883+
38233884
static void
38243885
test_provenance_table(void)
38253886
{
@@ -7588,6 +7649,7 @@ main(int argc, char **argv)
75887649
{ "test_individual_table", test_individual_table },
75897650
{ "test_individual_table_update_row", test_individual_table_update_row },
75907651
{ "test_population_table", test_population_table },
7652+
{ "test_population_table_update_row", test_population_table_update_row },
75917653
{ "test_provenance_table", test_provenance_table },
75927654
{ "test_table_size_increments", test_table_size_increments },
75937655
{ "test_table_collection_equals_options", test_table_collection_equals_options },

c/tskit/tables.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4620,6 +4620,75 @@ tsk_population_table_add_row(
46204620
return ret;
46214621
}
46224622

4623+
static int
4624+
tsk_population_table_update_row_rewrite(tsk_population_table_t *self, tsk_id_t index,
4625+
const char *metadata, tsk_size_t metadata_length)
4626+
{
4627+
int ret = 0;
4628+
tsk_id_t j, ret_id;
4629+
tsk_population_table_t copy;
4630+
tsk_size_t num_rows;
4631+
tsk_id_t *rows = NULL;
4632+
4633+
ret = tsk_population_table_copy(self, &copy, 0);
4634+
if (ret != 0) {
4635+
goto out;
4636+
}
4637+
rows = malloc(self->num_rows * sizeof(*rows));
4638+
if (rows == NULL) {
4639+
ret = TSK_ERR_NO_MEMORY;
4640+
goto out;
4641+
}
4642+
4643+
ret = tsk_population_table_truncate(self, (tsk_size_t) index);
4644+
tsk_bug_assert(ret == 0);
4645+
ret_id = tsk_population_table_add_row(self, metadata, metadata_length);
4646+
if (ret_id < 0) {
4647+
ret = (int) ret_id;
4648+
goto out;
4649+
}
4650+
num_rows = 0;
4651+
for (j = index + 1; j < (tsk_id_t) copy.num_rows; j++) {
4652+
rows[num_rows] = j;
4653+
num_rows++;
4654+
}
4655+
ret = tsk_population_table_extend(self, &copy, num_rows, rows, 0);
4656+
if (ret != 0) {
4657+
goto out;
4658+
}
4659+
out:
4660+
tsk_population_table_free(&copy);
4661+
tsk_safe_free(rows);
4662+
return ret;
4663+
}
4664+
4665+
int
4666+
tsk_population_table_update_row(tsk_population_table_t *self, tsk_id_t index,
4667+
const char *metadata, tsk_size_t metadata_length)
4668+
{
4669+
int ret = 0;
4670+
tsk_population_t current_row;
4671+
4672+
ret = tsk_population_table_get_row(self, index, &current_row);
4673+
if (ret != 0) {
4674+
goto out;
4675+
}
4676+
if (current_row.metadata_length == metadata_length) {
4677+
/* Note: important to use memmove here as we may be provided pointers
4678+
* to the column memory as input via get_row */
4679+
memmove(&self->metadata[self->metadata_offset[index]], metadata,
4680+
metadata_length * sizeof(*metadata));
4681+
} else {
4682+
ret = tsk_population_table_update_row_rewrite(
4683+
self, index, metadata, metadata_length);
4684+
if (ret != 0) {
4685+
goto out;
4686+
}
4687+
}
4688+
out:
4689+
return ret;
4690+
}
4691+
46234692
int
46244693
tsk_population_table_clear(tsk_population_table_t *self)
46254694
{

c/tskit/tables.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,6 +2309,33 @@ Add a new population with the specified ``metadata`` to the table. A copy of the
23092309
tsk_id_t tsk_population_table_add_row(
23102310
tsk_population_table_t *self, const char *metadata, tsk_size_t metadata_length);
23112311

2312+
/**
2313+
@brief Updates the row at the specified index.
2314+
2315+
@rst
2316+
Rewrite the row at the specified index in this table to use the specified
2317+
values. A copy of the ``metadata`` parameter is taken immediately. See the
2318+
:ref:`table definition <sec_population_table_definition>` for details of the
2319+
columns in this table.
2320+
2321+
.. warning::
2322+
Because of the way that ragged columns are encoded, this method requires a
2323+
full rewrite of the internal column memory in worst case, and would
2324+
therefore be inefficient for bulk updates for such columns. However, if the
2325+
sizes of all ragged column values are unchanged in the updated row, this
2326+
method is guaranteed to only update the memory for the row in question.
2327+
@endrst
2328+
2329+
@param self A pointer to a tsk_population_table_t object.
2330+
@param index The row to update.
2331+
@param metadata The metadata to be associated with the population. This
2332+
is a pointer to arbitrary memory. Can be ``NULL`` if ``metadata_length`` is 0.
2333+
@param metadata_length The size of the metadata array in bytes.
2334+
@return Return 0 on success or a negative value on failure.
2335+
*/
2336+
int tsk_population_table_update_row(tsk_population_table_t *self, tsk_id_t index,
2337+
const char *metadata, tsk_size_t metadata_length);
2338+
23122339
/**
23132340
@brief Clears this table, setting the number of rows to zero.
23142341

0 commit comments

Comments
 (0)