test_sln_tree.c (19650B)
1 /* Copyright (C) 2022, 2026 |Méso|Star> (contact@meso-star.com) 2 * Copyright (C) 2026 Université de Lorraine 3 * Copyright (C) 2022 Centre National de la Recherche Scientifique 4 * Copyright (C) 2022 Université Paul Sabatier 5 * 6 * This file is part of Star-Line. 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #include "test_sln_lines.h" 22 #include "sln.h" 23 24 #include <star/shtr.h> 25 26 #include <rsys/algorithm.h> 27 #include <rsys/math.h> 28 #include <rsys/mem_allocator.h> 29 30 /******************************************************************************* 31 * Helper function 32 ******************************************************************************/ 33 /* This test assumes that all the lines contained into the list are 34 * partitionned in the tree */ 35 static void 36 check_tree_lines 37 (const struct sln_tree* tree, 38 struct shtr_line_list* line_list) 39 { 40 #define STACK_SIZE \ 41 ( SLN_TREE_DEPTH_MAX \ 42 * SLN_TREE_ARITY_MAX - 1/*1st child*/ \ 43 + 1/*Dummy node*/) 44 const struct sln_node* stack[STACK_SIZE] = {NULL}; 45 struct sln_tree_desc desc = SLN_TREE_DESC_NULL; 46 size_t istack = 0; 47 const struct sln_node* node = NULL; 48 49 char* found_lines = NULL; 50 size_t found_nlines = 0; 51 size_t line_list_sz; 52 53 CHK(shtr_line_list_get_size(line_list, &line_list_sz) == RES_OK); 54 CHK(sln_tree_get_desc(tree, &desc) == RES_OK); 55 56 CHK(found_lines = mem_calloc(line_list_sz, sizeof(char))); 57 58 stack[istack++] = NULL; /* Dummy node to stop the recursion */ 59 60 node = sln_tree_get_root(tree); 61 while(node) { 62 struct sln_node_desc node_desc = SLN_NODE_DESC_NULL; 63 size_t node_nlines = 0; 64 65 CHK(sln_node_get_desc(tree, node, &node_desc) == RES_OK); 66 node_nlines = node_desc.ilines[1] - node_desc.ilines[0] + 1; 67 68 if(!sln_node_is_leaf(node)) { 69 unsigned i = 0; 70 unsigned n = sln_node_get_child_count(tree, node); 71 72 CHK(node_nlines > desc.leaf_nlines); 73 74 FOR_EACH(i, 1, n) { 75 stack[istack++] = sln_node_get_child(tree, node, i); 76 } 77 node = sln_node_get_child(tree, node, 0); /* Handle the child 0 */ 78 79 } else { 80 size_t iline; 81 82 CHK(node_nlines <= desc.leaf_nlines); 83 FOR_EACH(iline, node_desc.ilines[0], node_desc.ilines[1]+1) { 84 if(!found_lines[iline]) { 85 found_nlines += 1; 86 found_lines[iline] = 1; 87 } 88 } 89 90 node = stack[--istack]; /* Pop the next node */ 91 } 92 } 93 94 /* Check that all lines are found */ 95 CHK(found_nlines == line_list_sz); 96 97 mem_rm(found_lines); 98 #undef STACK_SIZE 99 } 100 101 static void 102 check_mesh_equality(const struct sln_mesh* mesh1, const struct sln_mesh* mesh2) 103 { 104 size_t i; 105 CHK(mesh1 && mesh2); 106 CHK(mesh1->nvertices == mesh2->nvertices); 107 108 FOR_EACH(i, 0, mesh1->nvertices) { 109 CHK(mesh1->vertices[i].wavenumber == mesh2->vertices[i].wavenumber); 110 CHK(mesh1->vertices[i].ka == mesh2->vertices[i].ka); 111 } 112 } 113 114 static void 115 check_node_equality 116 (const struct sln_tree* tree1, 117 const struct sln_tree* tree2, 118 const struct sln_node* node1, 119 const struct sln_node* node2) 120 { 121 struct sln_mesh mesh1 = SLN_MESH_NULL; 122 struct sln_mesh mesh2 = SLN_MESH_NULL; 123 struct sln_node_desc desc1 = SLN_NODE_DESC_NULL; 124 struct sln_node_desc desc2 = SLN_NODE_DESC_NULL; 125 size_t iline = 0; 126 127 CHK(node1 && node2); 128 CHK(sln_node_is_leaf(node1) == sln_node_is_leaf(node2)); 129 CHK(sln_node_get_desc(tree1, node1, &desc1) == RES_OK); 130 CHK(sln_node_get_desc(tree2, node2, &desc2) == RES_OK); 131 132 CHK(desc1.ilines[0] == desc2.ilines[0]); 133 CHK(desc1.ilines[1] == desc2.ilines[1]); 134 CHK(desc1.nvertices == desc2.nvertices); 135 CHK(desc1.nchildren == desc2.nchildren); 136 137 FOR_EACH(iline, desc1.ilines[0], desc1.ilines[1]+1) { 138 struct sln_line line1 = SLN_LINE_NULL; 139 struct sln_line line2 = SLN_LINE_NULL; 140 CHK(sln_tree_get_line(tree1, iline, NULL, &line1) == RES_OK); 141 CHK(sln_tree_get_line(tree2, iline, NULL, &line2) == RES_OK); 142 143 CHK(line1.wavenumber == line2.wavenumber); 144 CHK(line1.profile_factor == line2.profile_factor); 145 CHK(line1.gamma_d == line2.gamma_d); 146 CHK(line1.gamma_l == line2.gamma_l); 147 CHK(line1.molecule_id == line2.molecule_id); 148 } 149 150 CHK(sln_node_get_mesh(tree1, node1, &mesh1) == RES_OK); 151 CHK(sln_node_get_mesh(tree2, node2, &mesh2) == RES_OK); 152 check_mesh_equality(&mesh1, &mesh2); 153 } 154 155 static void 156 check_tree_equality 157 (const struct sln_tree* tree1, 158 const struct sln_tree* tree2) 159 { 160 #define STACK_SIZE \ 161 ( SLN_TREE_DEPTH_MAX \ 162 * (SLN_TREE_ARITY_MAX-1/*1st child*/) * 2/*#trees*/ \ 163 + 1/*Dummy node*/) 164 165 const struct sln_node* stack[STACK_SIZE] = {NULL}; 166 int istack = 0; 167 168 struct sln_tree_desc desc1 = SLN_TREE_DESC_NULL; 169 struct sln_tree_desc desc2 = SLN_TREE_DESC_NULL; 170 const struct sln_node* node1 = NULL; 171 const struct sln_node* node2 = NULL; 172 173 CHK(sln_tree_get_desc(tree1, &desc1) == RES_OK); 174 CHK(sln_tree_get_desc(tree2, &desc2) == RES_OK); 175 CHK(desc1.leaf_nlines == desc2.leaf_nlines); 176 CHK(desc1.mesh_decimation_err == desc2.mesh_decimation_err); 177 CHK(desc1.mesh_type == desc2.mesh_type); 178 CHK(desc1.line_profile == desc2.line_profile); 179 CHK(desc1.pressure == desc2.pressure); 180 CHK(desc1.temperature == desc2.temperature); 181 CHK(desc1.depth == desc2.depth); 182 CHK(desc1.nlines == desc2.nlines); 183 CHK(desc1.nvertices == desc2.nvertices); 184 CHK(desc1.nnodes == desc2.nnodes); 185 CHK(desc1.arity == desc2.arity); 186 187 stack[istack++] = NULL; 188 stack[istack++] = NULL; 189 190 node1 = sln_tree_get_root(tree1); 191 node2 = sln_tree_get_root(tree2); 192 193 while(node1 || node2) { 194 CHK((!node1 && !node2) || (node1 && node2)); 195 check_node_equality(tree1, tree2, node1, node2); 196 197 if(sln_node_is_leaf(node1)) { 198 node2 = stack[--istack]; 199 node1 = stack[--istack]; 200 } else { 201 unsigned i = 0; 202 unsigned n = sln_node_get_child_count(tree1, node1); 203 204 FOR_EACH(i, 1, n) { 205 stack[istack++] = sln_node_get_child(tree1, node1, i); 206 stack[istack++] = sln_node_get_child(tree2, node2, i); 207 } 208 node1 = sln_node_get_child(tree1, node1, 0); 209 node2 = sln_node_get_child(tree2, node2, 0); 210 } 211 } 212 213 #undef STACK_SIZE 214 } 215 216 static void 217 check_node_value(const struct sln_tree* tree, const struct sln_node* node) 218 { 219 struct sln_node_desc desc = SLN_NODE_DESC_NULL; 220 struct sln_line line = SLN_LINE_NULL; 221 size_t iline = 0; 222 double ka_ref = 0; 223 double ka_node = 0; 224 double nu = 0; 225 226 CHK(sln_node_get_desc(tree, node, &desc) == RES_OK); 227 228 CHK(sln_tree_get_line(tree, desc.ilines[0], NULL, &line) == RES_OK); 229 nu = line.wavenumber + 10; 230 CHK(sln_tree_get_line(tree, desc.ilines[1], NULL, &line) == RES_OK); 231 nu += line.wavenumber - 10; 232 nu *= 0.5; 233 234 ka_node = sln_node_eval(tree, node, NULL, nu); 235 FOR_EACH(iline, desc.ilines[0], desc.ilines[1]+1/*inclusive*/) { 236 CHK(sln_tree_get_line(tree, iline, NULL, &line) == RES_OK); 237 ka_ref += sln_line_eval(tree, &line, nu); 238 } 239 240 CHK(eq_eps(ka_node, ka_ref, ka_ref*1e-6)); 241 } 242 243 static void 244 test_tree 245 (struct sln_device* sln, 246 const struct sln_tree_create_args* tree_args_in, 247 struct shtr_line_list* line_list) 248 { 249 struct sln_tree_create_args tree_args = SLN_TREE_CREATE_ARGS_DEFAULT; 250 struct sln_tree_desc desc = SLN_TREE_DESC_NULL; 251 struct sln_node_desc node_desc = SLN_NODE_DESC_NULL; 252 struct sln_mesh mesh = SLN_MESH_NULL; 253 struct sln_tree* tree = NULL; 254 const struct sln_node* node = NULL; 255 struct sln_line line = SLN_LINE_NULL; 256 size_t nlines = 0; 257 size_t nleaf = 0; 258 unsigned depth = 0; 259 260 CHK(sln && tree_args_in && line_list); 261 tree_args = *tree_args_in; 262 263 CHK(sln_tree_create(NULL, &tree_args, &tree) == RES_BAD_ARG); 264 CHK(sln_tree_create(sln, NULL, &tree) == RES_BAD_ARG); 265 CHK(sln_tree_create(sln, &tree_args, NULL) == RES_BAD_ARG); 266 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_OK); 267 268 CHK(shtr_line_list_get_size(line_list, &nlines) == RES_OK); 269 270 CHK(sln_tree_get_desc(NULL, &desc) == RES_BAD_ARG); 271 CHK(sln_tree_get_desc(tree, NULL) == RES_BAD_ARG); 272 CHK(sln_tree_get_desc(tree, &desc) == RES_OK); 273 274 CHK(desc.leaf_nlines >= 1); 275 CHK(desc.mesh_decimation_err == tree_args.mesh_decimation_err); 276 CHK(desc.mesh_type == tree_args.mesh_type); 277 CHK(desc.line_profile == tree_args.line_profile); 278 CHK(desc.nlines == nlines); 279 CHK(desc.nvertices >= 1); 280 CHK(desc.nnodes >= 1); 281 282 nleaf = (desc.nlines + desc.leaf_nlines-1/*ceil*/)/ desc.leaf_nlines; 283 depth = (unsigned)ceil(log((double)nleaf)/log((double)desc.arity)); 284 CHK(desc.depth == depth); 285 286 CHK(desc.pressure == tree_args.pressure); 287 CHK(desc.temperature == tree_args.temperature); 288 CHK(desc.arity == tree_args.arity); 289 290 CHK(sln_tree_get_line(NULL, 0, NULL, &line) == RES_BAD_ARG); 291 CHK(sln_tree_get_line(tree, nlines, NULL, &line) == RES_BAD_ARG); 292 CHK(sln_tree_get_line(tree, 0, NULL, NULL) == RES_BAD_ARG); 293 CHK(sln_tree_get_line(tree, 0, NULL, &line) == RES_OK); 294 CHK(sln_tree_get_line(tree, nlines-1, NULL, &line) == RES_OK); 295 296 CHK(node = sln_tree_get_root(tree)); 297 CHK(node != NULL); 298 299 CHK(sln_node_get_desc(NULL, node, &node_desc) == RES_BAD_ARG); 300 CHK(sln_node_get_desc(tree, NULL, &node_desc) == RES_BAD_ARG); 301 CHK(sln_node_get_desc(tree, node, NULL) == RES_BAD_ARG); 302 CHK(sln_node_get_desc(tree, node, &node_desc) == RES_OK); 303 CHK(node_desc.ilines[0] == 0); 304 CHK(node_desc.ilines[1] == desc.nlines - 1); 305 CHK(node_desc.nvertices >= 1 && node_desc.nvertices <= desc.nvertices); 306 CHK(node_desc.nchildren <= desc.arity); 307 308 while(!sln_node_is_leaf(node)) { 309 struct sln_node_desc node_desc_next = SLN_NODE_DESC_NULL; 310 311 CHK(sln_node_get_child_count(tree, node) != 0); 312 CHK(sln_node_get_child_count(tree, node) <= desc.arity); 313 314 node = sln_node_get_child(tree, node, 0); 315 316 CHK(sln_node_get_desc(tree, node, &node_desc_next) == RES_OK); 317 318 #define NLINES(Desc) ((Desc).ilines[1] - (Desc).ilines[0] + 1) 319 CHK(NLINES(node_desc_next) >= 1); 320 CHK(NLINES(node_desc_next) < NLINES(node_desc)); 321 #undef NLINES 322 323 CHK(node_desc_next.nvertices >= 1); 324 if(sln_node_is_leaf(node)) { 325 CHK(node_desc_next.nchildren == 0); 326 } else { 327 CHK(node_desc_next.nchildren != 0); 328 CHK(node_desc_next.nchildren <= desc.arity); 329 } 330 331 node_desc = node_desc_next; 332 } 333 CHK(sln_node_get_child_count(tree, node) == 0); 334 335 CHK(node_desc.ilines[1] - node_desc.ilines[0] + 1 <= desc.leaf_nlines); 336 337 CHK(sln_node_get_mesh(NULL, node, &mesh) == RES_BAD_ARG); 338 CHK(sln_node_get_mesh(tree, NULL, &mesh) == RES_BAD_ARG); 339 CHK(sln_node_get_mesh(tree, node, NULL) == RES_BAD_ARG); 340 CHK(sln_node_get_mesh(tree, node, &mesh) == RES_OK); 341 check_node_value(tree, node); 342 343 CHK(node = sln_tree_get_root(tree)); 344 check_tree_lines(tree, line_list); 345 346 CHK(sln_tree_ref_get(NULL) == RES_BAD_ARG); 347 CHK(sln_tree_ref_get(tree) == RES_OK); 348 CHK(sln_tree_ref_put(NULL) == RES_BAD_ARG); 349 CHK(sln_tree_ref_put(tree) == RES_OK); 350 CHK(sln_tree_ref_put(tree) == RES_OK); 351 352 tree_args.mesh_decimation_err = -1; 353 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG); 354 tree_args.mesh_decimation_err = SLN_TREE_CREATE_ARGS_DEFAULT.mesh_decimation_err; 355 356 tree_args.mesh_type = SLN_MESH_TYPES_COUNT__; 357 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG); 358 tree_args.mesh_type = SLN_TREE_CREATE_ARGS_DEFAULT.mesh_type; 359 360 tree_args.line_profile = SLN_LINE_PROFILES_COUNT__; 361 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG); 362 tree_args.line_profile = SLN_TREE_CREATE_ARGS_DEFAULT.line_profile; 363 364 tree_args.arity = 1; 365 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG); 366 tree_args.arity = SLN_TREE_ARITY_MAX + 1; 367 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG); 368 tree_args.arity = SLN_TREE_CREATE_ARGS_DEFAULT.arity; 369 370 tree_args.leaf_nlines = 0; 371 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG); 372 tree_args.leaf_nlines = SLN_LEAF_NLINES_MAX + 1; 373 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG); 374 tree_args.leaf_nlines = SLN_TREE_CREATE_ARGS_DEFAULT.leaf_nlines; 375 376 tree_args.nthreads_hint = 0; 377 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG); 378 tree_args.nthreads_hint = 1; 379 380 /* Check that, as expected, the tree is created correctly using the arguments 381 * defined so far. This will confirm that the creation failures tested so far 382 * are indeed due to arguments explicitly defined as incorrect, and not to 383 * invalid arguments introduced by mistake */ 384 CHK(sln_tree_create(sln, &tree_args, &tree) == RES_OK); 385 386 if(tree_args.arity == 2 && tree_args.collapse_polylines == 0) { 387 struct sln_tree* tree2 = NULL; 388 389 /* Verify that, when constructing a binary tree, creating polylines for 390 * internal nodes by reducing the polylines of their children results in 391 * exactly the same tree as when the polyline of an internal node is 392 * constructed by merging the polylines of its children */ 393 tree_args.collapse_polylines = 1; 394 CHK(sln_tree_create(sln, &tree_args, &tree2) == RES_OK); 395 check_tree_equality(tree, tree2); 396 397 CHK(sln_tree_ref_put(tree2) == RES_OK); 398 } 399 400 CHK(sln_tree_ref_put(tree) == RES_OK); 401 } 402 403 404 static void 405 test_tree_serialization 406 (struct sln_device* sln, 407 const struct sln_tree_create_args* tree_args) 408 { 409 struct sln_tree_write_args wargs = SLN_TREE_WRITE_ARGS_NULL; 410 struct sln_tree_read_args rargs = SLN_TREE_READ_ARGS_NULL; 411 struct sln_tree* tree1 = NULL; 412 struct sln_tree* tree2 = NULL; 413 414 const char* filename = "tree.sln"; 415 FILE* fp = NULL; 416 417 CHK(sln_tree_create(sln, tree_args, &tree1) == RES_OK); 418 419 CHK(fp = fopen(filename, "w+")); 420 421 wargs.file = fp; 422 CHK(sln_tree_write(NULL, &wargs) == RES_BAD_ARG); 423 CHK(sln_tree_write(tree1, NULL) == RES_BAD_ARG); 424 wargs.file = NULL; 425 CHK(sln_tree_write(tree1, &wargs) == RES_BAD_ARG); 426 wargs.file = fp; 427 CHK(sln_tree_write(tree1, &wargs) == RES_OK); 428 rewind(fp); 429 430 rargs.metadata = tree_args->metadata; 431 rargs.lines = tree_args->lines; 432 rargs.file = fp; 433 CHK(sln_tree_read(NULL, &rargs, &tree2) == RES_BAD_ARG); 434 CHK(sln_tree_read(sln, NULL, &tree2) == RES_BAD_ARG); 435 rargs.metadata = NULL; 436 CHK(sln_tree_read(sln, &rargs, &tree2) == RES_BAD_ARG); 437 rargs.metadata = tree_args->metadata; 438 rargs.lines = NULL; 439 CHK(sln_tree_read(sln, &rargs, &tree2) == RES_BAD_ARG); 440 rargs.lines = tree_args->lines; 441 rargs.file = NULL; 442 CHK(sln_tree_read(sln, &rargs, &tree2) == RES_BAD_ARG); 443 rargs.file = fp; 444 CHK(sln_tree_read(sln, &rargs, NULL) == RES_BAD_ARG); 445 CHK(sln_tree_read(sln, &rargs, &tree2) == RES_OK); 446 fclose(fp); 447 448 check_tree_equality(tree1, tree2); 449 CHK(sln_tree_ref_put(tree2) == RES_OK); 450 451 wargs.file = NULL; 452 wargs.filename = filename; 453 CHK(sln_tree_write(tree1, &wargs) == RES_OK); 454 455 rargs.file = NULL; 456 rargs.filename = "nop"; 457 CHK(sln_tree_read(sln, &rargs, &tree2) == RES_IO_ERR); 458 rargs.filename = filename; 459 rargs.disable_line_hash_check = 1; 460 CHK(sln_tree_read(sln, &rargs, &tree2) == RES_OK); 461 462 check_tree_equality(tree1, tree2); 463 464 CHK(sln_tree_ref_put(tree2) == RES_OK); 465 CHK(sln_tree_ref_put(tree1) == RES_OK); 466 } 467 468 /******************************************************************************* 469 * Test function 470 ******************************************************************************/ 471 int 472 main(int argc, char** argv) 473 { 474 struct sln_device_create_args dev_args = SLN_DEVICE_CREATE_ARGS_DEFAULT; 475 struct sln_tree_create_args tree_args = SLN_TREE_CREATE_ARGS_DEFAULT; 476 struct sln_device* sln = NULL; 477 478 struct shtr_create_args shtr_args = SHTR_CREATE_ARGS_DEFAULT; 479 struct shtr* shtr = NULL; 480 struct shtr_line_list_load_args line_load_args = SHTR_LINE_LIST_LOAD_ARGS_NULL; 481 struct shtr_line_list* line_list = NULL; 482 struct shtr_isotope_metadata* metadata = NULL; 483 484 FILE* fp_lines = NULL; 485 FILE* fp_mdata = NULL; 486 (void)argc, (void)argv; 487 488 /* Generate the file of the isotope metadata */ 489 CHK(fp_mdata = tmpfile()); 490 fprintf(fp_mdata, "Molecule # Iso Abundance Q(296K) gj Molar Mass(g)\n"); 491 write_shtr_molecule(fp_mdata, &g_H2O); 492 write_shtr_molecule(fp_mdata, &g_CO2); 493 write_shtr_molecule(fp_mdata, &g_O3); 494 rewind(fp_mdata); 495 496 /* Generate the file of lines */ 497 CHK(fp_lines = tmpfile()); 498 write_shtr_lines(fp_lines, g_lines, g_nlines); 499 rewind(fp_lines); 500 501 /* Load the isotope metadata and the lines */ 502 shtr_args.verbose = 1; 503 CHK(shtr_create(&shtr_args, &shtr) == RES_OK); 504 CHK(shtr_isotope_metadata_load_stream(shtr, fp_mdata, NULL, &metadata) == RES_OK); 505 506 line_load_args.filename = "stream"; 507 line_load_args.file = fp_lines; 508 CHK(shtr_line_list_load(shtr, &line_load_args, &line_list) == RES_OK); 509 510 CHK(fclose(fp_lines) == 0); 511 CHK(fclose(fp_mdata) == 0); 512 513 dev_args.verbose = 1; 514 CHK(sln_device_create(&dev_args, &sln) == RES_OK); 515 516 /* Create the mixture */ 517 tree_args.metadata = metadata; 518 tree_args.lines = line_list; 519 tree_args.molecules[SHTR_H2O].concentration = 1.0/3.0; 520 tree_args.molecules[SHTR_H2O].cutoff = 25; 521 tree_args.molecules[SHTR_CO2].concentration = 1.0/3.0; 522 tree_args.molecules[SHTR_CO2].cutoff = 50; 523 tree_args.molecules[SHTR_O3 ].concentration = 1.0/3.0; 524 tree_args.molecules[SHTR_O3 ].cutoff = 25; 525 tree_args.pressure = 1; 526 tree_args.temperature = 296; 527 528 test_tree(sln, &tree_args, line_list); 529 test_tree_serialization(sln, &tree_args); 530 531 /* Test a tree with a non default arity */ 532 tree_args.arity = 13; 533 test_tree(sln, &tree_args, line_list); 534 test_tree_serialization(sln, &tree_args); 535 536 /* Test a tree with a non default arity built sequentially*/ 537 tree_args.arity = 13; 538 tree_args.nthreads_hint = 1; 539 test_tree(sln, &tree_args, line_list); 540 test_tree_serialization(sln, &tree_args); 541 tree_args.nthreads_hint = SLN_TREE_CREATE_ARGS_DEFAULT.nthreads_hint; 542 543 /* Test a tree with a non-standard arity, where the polylines of the internal 544 * nodes are created by collapsing the polylines of their child nodes */ 545 tree_args.arity = 5; 546 tree_args.collapse_polylines = 1; 547 test_tree(sln, &tree_args, line_list); 548 test_tree_serialization(sln, &tree_args); 549 550 /* Test a tree where the number of rows per leaf is greater than 1 */ 551 tree_args.arity = 4; 552 tree_args.leaf_nlines = 3; 553 tree_args.collapse_polylines = 0; 554 test_tree(sln, &tree_args, line_list); 555 test_tree_serialization(sln, &tree_args); 556 557 /* Test a tree in which the number of lines per leaf is greater than 1. The 558 * polylines for the leaves and internal nodes are created by reducing, 559 * respectively, the polyline of the leaf lines or those of the internal 560 * nodes' children */ 561 tree_args.arity = 3; 562 tree_args.leaf_nlines = 6; 563 tree_args.collapse_polylines = 1; 564 test_tree(sln, &tree_args, line_list); 565 test_tree_serialization(sln, &tree_args); 566 567 /* Test building a tree forcing all lines beeing in the root of the tree */ 568 CHK(g_nlines < SLN_LEAF_NLINES_MAX); 569 tree_args.arity = 2; 570 tree_args.leaf_nlines = (unsigned)g_nlines; 571 tree_args.collapse_polylines = 0; 572 test_tree(sln, &tree_args, line_list); 573 test_tree_serialization(sln, &tree_args); 574 575 CHK(sln_device_ref_put(sln) == RES_OK); 576 CHK(shtr_ref_put(shtr) == RES_OK); 577 CHK(shtr_line_list_ref_put(line_list) == RES_OK); 578 CHK(shtr_isotope_metadata_ref_put(metadata) == RES_OK); 579 CHK(mem_allocated_size() == 0); 580 return 0; 581 }