star-line

Structure for accelerating line importance sampling
git clone git://git.meso-star.fr/star-line.git
Log | Files | Refs | README | LICENSE

commit 1a4496eef4c5ad30a2e289ac89377c50746caad7
parent 70df096314ca59941e4b1aa38fb02775b6e46704
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 15 Apr 2026 15:32:48 +0200

Add a test on tree construction

Verify that constructing a binary tree by merging child polylines or by
collapsing them within the parent node yields the same result.

Diffstat:
Msrc/test_sln_tree.c | 212++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 114 insertions(+), 98 deletions(-)

diff --git a/src/test_sln_tree.c b/src/test_sln_tree.c @@ -142,6 +142,109 @@ check_tree_lines } static void +check_mesh_equality(const struct sln_mesh* mesh1, const struct sln_mesh* mesh2) +{ + size_t i; + CHK(mesh1 && mesh2); + CHK(mesh1->nvertices == mesh2->nvertices); + + FOR_EACH(i, 0, mesh1->nvertices) { + CHK(mesh1->vertices[i].wavenumber == mesh2->vertices[i].wavenumber); + CHK(mesh1->vertices[i].ka == mesh2->vertices[i].ka); + } +} + +static void +check_node_equality + (const struct sln_tree* tree1, + const struct sln_tree* tree2, + const struct sln_node* node1, + const struct sln_node* node2) +{ + struct sln_mesh mesh1 = SLN_MESH_NULL; + struct sln_mesh mesh2 = SLN_MESH_NULL; + size_t iline, nlines; + + CHK(node1 && node2); + CHK(sln_node_is_leaf(node1) == sln_node_is_leaf(node2)); + CHK(sln_node_get_line_count(node1) == sln_node_get_line_count(node2)); + nlines = sln_node_get_line_count(node1); + + FOR_EACH(iline, 0, nlines) { + struct shtr_line line1 = SHTR_LINE_NULL; + struct shtr_line line2 = SHTR_LINE_NULL; + CHK(sln_node_get_line(tree1, node1, iline, &line1) == RES_OK); + CHK(sln_node_get_line(tree2, node2, iline, &line2) == RES_OK); + CHK(shtr_line_eq(&line1, &line2)); + } + + CHK(sln_node_get_mesh(tree1, node1, &mesh1) == RES_OK); + CHK(sln_node_get_mesh(tree2, node2, &mesh2) == RES_OK); + check_mesh_equality(&mesh1, &mesh2); +} + +static void +check_tree_equality + (const struct sln_tree* tree1, + const struct sln_tree* tree2) +{ + #define STACK_SIZE \ + ( SLN_TREE_DEPTH_MAX \ + * (SLN_TREE_ARITY_MAX-1/*1st child*/) * 2/*#trees*/ \ + + 1/*Dummy node*/) + + const struct sln_node* stack[STACK_SIZE] = {NULL}; + int istack = 0; + + struct sln_tree_desc desc1 = SLN_TREE_DESC_NULL; + struct sln_tree_desc desc2 = SLN_TREE_DESC_NULL; + const struct sln_node* node1 = NULL; + const struct sln_node* node2 = NULL; + + CHK(sln_tree_get_desc(tree1, &desc1) == RES_OK); + CHK(sln_tree_get_desc(tree2, &desc2) == RES_OK); + CHK(desc1.max_nlines_per_leaf == desc2.max_nlines_per_leaf); + CHK(desc1.mesh_decimation_err == desc2.mesh_decimation_err); + CHK(desc1.mesh_type == desc2.mesh_type); + CHK(desc1.line_profile == desc2.line_profile); + CHK(desc1.pressure == desc2.pressure); + CHK(desc1.temperature == desc2.temperature); + CHK(desc1.depth == desc2.depth); + CHK(desc1.nlines == desc2.nlines); + CHK(desc1.nvertices == desc2.nvertices); + CHK(desc1.nnodes == desc2.nnodes); + CHK(desc1.arity == desc2.arity); + + stack[istack++] = NULL; + stack[istack++] = NULL; + + node1 = sln_tree_get_root(tree1); + node2 = sln_tree_get_root(tree2); + + while(node1 || node2) { + CHK((!node1 && !node2) || (node1 && node2)); + check_node_equality(tree1, tree2, node1, node2); + + if(sln_node_is_leaf(node1)) { + node2 = stack[--istack]; + node1 = stack[--istack]; + } else { + unsigned i = 0; + unsigned n = sln_node_get_child_count(tree1, node1); + + FOR_EACH(i, 1, n) { + stack[istack++] = sln_node_get_child(tree1, node1, i); + stack[istack++] = sln_node_get_child(tree2, node2, i); + } + node1 = sln_node_get_child(tree1, node1, 0); + node2 = sln_node_get_child(tree2, node2, 0); + } + } + + #undef STACK_SIZE +} + +static void test_tree (struct sln_device* sln, const struct sln_tree_create_args* tree_args_in, @@ -253,111 +356,24 @@ test_tree tree_args.line_profile = SLN_LINE_PROFILE_VOIGT; CHK(sln_tree_create(sln, &tree_args, &tree) == RES_OK); - CHK(sln_tree_ref_put(tree) == RES_OK); -} -static void -check_mesh_equality(const struct sln_mesh* mesh1, const struct sln_mesh* mesh2) -{ - size_t i; - CHK(mesh1 && mesh2); - CHK(mesh1->nvertices == mesh2->nvertices); - - FOR_EACH(i, 0, mesh1->nvertices) { - CHK(mesh1->vertices[i].wavenumber == mesh2->vertices[i].wavenumber); - CHK(mesh1->vertices[i].ka == mesh2->vertices[i].ka); - } -} + if(tree_args.arity == 2 && tree_args.collapse_polylines == 0) { + struct sln_tree* tree2 = NULL; -static void -check_node_equality - (const struct sln_tree* tree1, - const struct sln_tree* tree2, - const struct sln_node* node1, - const struct sln_node* node2) -{ - struct sln_mesh mesh1 = SLN_MESH_NULL; - struct sln_mesh mesh2 = SLN_MESH_NULL; - size_t iline, nlines; + /* Verify that, when constructing a binary tree, creating polylines for + * internal nodes by reducing the polylines of their children results in + * exactly the same tree as when the polyline of an internal node is + * constructed by merging the polylines of its children */ + tree_args.collapse_polylines = 1; + CHK(sln_tree_create(sln, &tree_args, &tree2) == RES_OK); + check_tree_equality(tree, tree2); - CHK(node1 && node2); - CHK(sln_node_is_leaf(node1) == sln_node_is_leaf(node2)); - CHK(sln_node_get_line_count(node1) == sln_node_get_line_count(node2)); - nlines = sln_node_get_line_count(node1); - - FOR_EACH(iline, 0, nlines) { - struct shtr_line line1 = SHTR_LINE_NULL; - struct shtr_line line2 = SHTR_LINE_NULL; - CHK(sln_node_get_line(tree1, node1, iline, &line1) == RES_OK); - CHK(sln_node_get_line(tree2, node2, iline, &line2) == RES_OK); - CHK(shtr_line_eq(&line1, &line2)); + CHK(sln_tree_ref_put(tree2) == RES_OK); } - CHK(sln_node_get_mesh(tree1, node1, &mesh1) == RES_OK); - CHK(sln_node_get_mesh(tree2, node2, &mesh2) == RES_OK); - check_mesh_equality(&mesh1, &mesh2); + CHK(sln_tree_ref_put(tree) == RES_OK); } -static void -check_tree_equality - (const struct sln_tree* tree1, - const struct sln_tree* tree2) -{ - #define STACK_SIZE \ - ( SLN_TREE_DEPTH_MAX \ - * (SLN_TREE_ARITY_MAX-1/*1st child*/) * 2/*#trees*/ \ - + 1/*Dummy node*/) - - const struct sln_node* stack[STACK_SIZE] = {NULL}; - int istack = 0; - - struct sln_tree_desc desc1 = SLN_TREE_DESC_NULL; - struct sln_tree_desc desc2 = SLN_TREE_DESC_NULL; - const struct sln_node* node1 = NULL; - const struct sln_node* node2 = NULL; - - CHK(sln_tree_get_desc(tree1, &desc1) == RES_OK); - CHK(sln_tree_get_desc(tree2, &desc2) == RES_OK); - CHK(desc1.max_nlines_per_leaf == desc2.max_nlines_per_leaf); - CHK(desc1.mesh_decimation_err == desc2.mesh_decimation_err); - CHK(desc1.mesh_type == desc2.mesh_type); - CHK(desc1.line_profile == desc2.line_profile); - CHK(desc1.pressure == desc2.pressure); - CHK(desc1.temperature == desc2.temperature); - CHK(desc1.depth == desc2.depth); - CHK(desc1.nlines == desc2.nlines); - CHK(desc1.nvertices == desc2.nvertices); - CHK(desc1.nnodes == desc2.nnodes); - CHK(desc1.arity == desc2.arity); - - stack[istack++] = NULL; - stack[istack++] = NULL; - - node1 = sln_tree_get_root(tree1); - node2 = sln_tree_get_root(tree2); - - while(node1 || node2) { - CHK((!node1 && !node2) || (node1 && node2)); - check_node_equality(tree1, tree2, node1, node2); - - if(sln_node_is_leaf(node1)) { - node2 = stack[--istack]; - node1 = stack[--istack]; - } else { - unsigned i = 0; - unsigned n = sln_node_get_child_count(tree1, node1); - - FOR_EACH(i, 1, n) { - stack[istack++] = sln_node_get_child(tree1, node1, i); - stack[istack++] = sln_node_get_child(tree2, node2, i); - } - node1 = sln_node_get_child(tree1, node1, 0); - node2 = sln_node_get_child(tree2, node2, 0); - } - } - - #undef STACK_SIZE -} static void test_tree_serialization