@@ -426,7 +426,129 @@ TEST_CASE("Incremental update y-bus") {
426426 }
427427}
428428
429- // TODO:
430- // - test counting_sort_element()
429+ TEST_CASE (" Test counting_sort_element" ) {
430+ using math_solver::counting_sort_element;
431+ using math_solver::YBusElementMap;
432+ using enum power_grid_model::YBusElementType;
433+
434+ SUBCASE (" Test basic sorting" ) {
435+ // Create test data: elements at various matrix positions
436+ std::vector<YBusElementMap> vec = {
437+ {{2 , 1 }, {bft, 5 }}, // pos (2,1)
438+ {{0 , 0 }, {bff, 0 }}, // pos (0,0)
439+ {{1 , 2 }, {btf, 3 }}, // pos (1,2)
440+ {{0 , 1 }, {bft, 1 }}, // pos (0,1)
441+ {{2 , 1 }, {shunt, 6 }}, // pos (2,1) - same position as first
442+ {{1 , 0 }, {btf, 2 }}, // pos (1,0)
443+ {{2 , 2 }, {btt, 7 }}, // pos (2,2)
444+ };
445+
446+ // Expected sorted order: by row first, then by column
447+ // (0,0), (0,1), (1,0), (1,2), (2,1), (2,1), (2,2)
448+ std::vector<std::pair<Idx, Idx>> expected_positions = {{0 , 0 }, {0 , 1 }, {1 , 0 }, {1 , 2 }, {2 , 1 }, {2 , 1 }, {2 , 2 }};
449+
450+ Idx const n_bus = 3 ;
451+ counting_sort_element (vec, n_bus);
452+
453+ // Verify sorting
454+ CHECK (vec.size () == 7 );
455+ for (size_t i = 0 ; i < vec.size (); ++i) {
456+ CHECK (vec[i].pos .first == expected_positions[i].first );
457+ CHECK (vec[i].pos .second == expected_positions[i].second );
458+ }
459+
460+ // Verify specific elements are preserved correctly
461+ CHECK (vec[0 ].element .element_type == bff);
462+ CHECK (vec[0 ].element .idx == 0 );
463+ CHECK (vec[1 ].element .element_type == bft);
464+ CHECK (vec[1 ].element .idx == 1 );
465+ }
466+
467+ SUBCASE (" Test with single bus" ) {
468+ std::vector<YBusElementMap> vec = {{{0 , 0 }, {shunt, 10 }}};
469+
470+ counting_sort_element (vec, 1 );
471+
472+ CHECK (vec.size () == 1 );
473+ CHECK (vec[0 ].pos == std::make_pair (0 , 0 ));
474+ CHECK (vec[0 ].element .element_type == shunt);
475+ CHECK (vec[0 ].element .idx == 10 );
476+ }
477+
478+ SUBCASE (" Test with empty vector" ) {
479+ std::vector<YBusElementMap> vec;
480+ counting_sort_element (vec, 5 );
481+ CHECK (vec.empty ());
482+ }
483+
484+ SUBCASE (" Test stability - elements with same position maintain relative order" ) {
485+ std::vector<YBusElementMap> vec = {
486+ {{1 , 1 }, {bff, 100 }},
487+ {{1 , 1 }, {bft, 200 }},
488+ {{1 , 1 }, {shunt, 300 }},
489+ };
490+
491+ counting_sort_element (vec, 2 );
492+
493+ CHECK (vec.size () == 3 );
494+ // All should be at position (1,1)
495+ for (const auto & element : vec) {
496+ CHECK (element.pos == std::make_pair (1 , 1 ));
497+ }
498+ // Original relative order should be preserved (stable sort)
499+ CHECK (vec[0 ].element .idx == 100 );
500+ CHECK (vec[1 ].element .idx == 200 );
501+ CHECK (vec[2 ].element .idx == 300 );
502+ }
503+
504+ SUBCASE (" Test large sparse matrix scenario" ) {
505+ std::vector<YBusElementMap> vec;
506+ Idx const n_bus = 10 ;
507+
508+ // Add elements in reverse order to test sorting thoroughly
509+ for (Idx i = n_bus * n_bus - 1 ; i != static_cast <Idx>(-1 ); --i) {
510+ Idx const row = i / n_bus;
511+ Idx const col = i % n_bus;
512+ if ((row + col) % 3 == 0 ) { // Sparse pattern
513+ vec.push_back ({{row, col}, {bff, row * n_bus + col}});
514+ }
515+ }
516+
517+ size_t original_size = vec.size ();
518+ counting_sort_element (vec, n_bus);
519+
520+ CHECK (vec.size () == original_size);
521+
522+ // Verify sorted order
523+ for (size_t i = 1 ; i < vec.size (); ++i) {
524+ auto [prev_row, prev_col] = vec[i - 1 ].pos ;
525+ auto [curr_row, curr_col] = vec[i].pos ;
526+
527+ // Check row-major order
528+ if (prev_row == curr_row) {
529+ CHECK (prev_col <= curr_col); // Same row, column should be non-decreasing
530+ } else {
531+ CHECK (prev_row < curr_row); // Different row, previous row should be smaller
532+ }
533+ }
534+ }
535+
536+ SUBCASE (" Test all YBusElementType values" ) {
537+ std::vector<YBusElementMap> vec = {
538+ {{1 , 1 }, {fill_in_tf, 6 }}, {{0 , 1 }, {bft, 1 }}, {{1 , 0 }, {btf, 2 }}, {{0 , 0 }, {bff, 0 }},
539+ {{1 , 1 }, {btt, 3 }}, {{2 , 2 }, {shunt, 4 }}, {{1 , 2 }, {fill_in_ft, 5 }},
540+ };
541+
542+ counting_sort_element (vec, 3 );
543+
544+ // Verify positions are sorted correctly
545+ std::vector<std::pair<Idx, Idx>> expected_positions = {{0 , 0 }, {0 , 1 }, {1 , 0 }, {1 , 1 }, {1 , 1 }, {1 , 2 }, {2 , 2 }};
546+
547+ CHECK (vec.size () == 7 );
548+ for (size_t i = 0 ; i < vec.size (); ++i) {
549+ CHECK (vec[i].pos == expected_positions[i]);
550+ }
551+ }
552+ }
431553
432554} // namespace power_grid_model
0 commit comments