@@ -339,18 +339,16 @@ find_nondominated_set_2d_(const double * restrict points, size_t size,
339339 D. Jesus, Luís Paquete, A software library for archiving nondominated
340340 points, GECCO 2021. https://github.com/TLDart/nondLib/blob/main/nondlib.hpp
341341
342- rows will be sorted by cmp_ppdouble_asc_rev_3d().
343- max_dim will be != 3 only if the rows pointers have been shifted.
342+ rows should be already sorted by cmp_ppdouble_asc_rev_3d().
343+
344+ When find_one_dominated, return as soon as it finds one dominated point.
344345*/
345- static inline size_t
346- find_nondominated_set_3d_helper (const double * restrict points ,
347- const double * * rows ,
348- size_t size , dimension_t max_dim ,
349- const bool keep_weakly , boolvec * restrict nondom )
346+ static __force_inline__ size_t
347+ find_nondominated_3d_impl_sorted (const double * * restrict rows , size_t size ,
348+ const bool keep_weakly ,
349+ const bool find_one_dominated )
350350{
351351 ASSUME (size > 1 );
352- // Sort in ascending lexicographic order from the last dimension.
353- qsort_typesafe (rows , size , cmp_ppdouble_asc_rev_3d );
354352
355353 avl_tree_t tree ;
356354 avl_init_tree (& tree , qsort_cmp_pdouble_asc_x_nonzero );
@@ -364,11 +362,12 @@ find_nondominated_set_3d_helper(const double * restrict points,
364362 avl_insert_after (& tree , node - 1 , node );
365363
366364 // In this context, size means "no dominated solution found".
367- size_t new_size = size , j = 1 ;
365+ size_t new_size = size , j = 1 , k = 0 ;
368366 const double * last_dom = NULL ;
369367 const double * restrict pk = rows [0 ];
370368 do {
371369 bool dominated ;
370+ size_t pos_dom = j ;
372371 const double * restrict pj = rows [j ];
373372 DEBUG2 (printf_point ("pj = [ " , pj , 3 , " ], " ));
374373 if (pk [0 ] > pj [0 ] || pk [1 ] > pj [1 ]) {
@@ -418,8 +417,10 @@ find_nondominated_set_3d_helper(const double * restrict points,
418417 const bool k_eq_j = (pk [0 ] == pj [0 ]) & (pk [1 ] == pj [1 ]) & (pk [2 ] == pj [2 ]);
419418 if (!keep_weakly ) { // We don't keep duplicates;
420419 dominated = true;
421- if (unlikely (k_eq_j ) && pj < pk ) // Only the first duplicated point is kept.
422- SWAP (pk , pj );
420+ if (unlikely (k_eq_j ) && pj < pk ) { // Only the first duplicated point is kept.
421+ pos_dom = k ;
422+ pj = pk ;
423+ }
423424 } else { // or it is not a duplicate, so it is non-weakly dominated;
424425 dominated = likely (!k_eq_j )
425426 // or pk was dominated, then this one is also dominated.
@@ -428,19 +429,17 @@ find_nondominated_set_3d_helper(const double * restrict points,
428429 DEBUG2 (printf_point ("weakly dominated by pk: " , pk , 3 , "\n" ));
429430 }
430431 if (dominated ) { // pj is dominated by a point in the tree or by prev.
431- /* Map the order in rows[], which is sorted, to the original order
432- in points. */
433- size_t pos_last_dom = row_index_from_ptr (points , pj , max_dim );
434- if (unlikely (nondom == NULL )) {
432+ if (find_one_dominated ) {
435433 // In this context, it means "position of the first dominated solution found".
436- new_size = pos_last_dom ;
434+ new_size = pos_dom ;
437435 goto early_end ;
438436 }
439- nondom [pos_last_dom ] = false;
440437 last_dom = pj ;
438+ rows [pos_dom ] = NULL ;
441439 new_size -- ;
442440 } else {
443441 pk = pj ;
442+ k = j ;
444443 }
445444 j ++ ;
446445 } while (j < size );
@@ -450,13 +449,26 @@ find_nondominated_set_3d_helper(const double * restrict points,
450449 return new_size ;
451450}
452451
452+ static __force_inline__ size_t
453+ find_nondominated_3d_impl (const double * * restrict rows , size_t size ,
454+ const bool keep_weakly ,
455+ const bool find_one_dominated )
456+ {
457+ // Sort in ascending lexicographic order from the last dimension.
458+ qsort_typesafe (rows , size , cmp_ppdouble_asc_rev_3d );
459+ // Help GCC generate all possible specializations of this function.
460+ return keep_weakly
461+ ? find_nondominated_3d_impl_sorted (rows , size , true, find_one_dominated )
462+ : find_nondominated_3d_impl_sorted (rows , size , false, find_one_dominated );
463+ }
464+
453465static inline size_t
454466find_dominated_3d_ (const double * restrict points , size_t size , bool keep_weakly )
455467{
456468 const double * * rows = generate_row_pointers (points , size , 3 );
457- size_t pos = keep_weakly
458- ? find_nondominated_set_3d_helper ( points , rows , size , 3 , true, /* nondom=*/ NULL )
459- : find_nondominated_set_3d_helper (points , rows , size , 3 , false, /* nondom=*/ NULL );
469+ size_t pos = find_nondominated_3d_impl ( rows , size , keep_weakly , /* find_one_dominated=*/ true);
470+ if ( pos < size )
471+ pos = row_index_from_ptr (points , rows [ pos ], 3 );
460472 free (rows );
461473 return pos ;
462474}
@@ -469,11 +481,20 @@ static inline size_t
469481find_nondominated_set_3d_ (const double * restrict points , size_t size ,
470482 const bool keep_weakly , boolvec * restrict nondom )
471483{
472- const double * * rows = generate_row_pointers (points , size , 3 );
473484 ASSUME (nondom != NULL );
474- size_t new_size = keep_weakly
475- ? find_nondominated_set_3d_helper (points , rows , size , 3 , true, nondom )
476- : find_nondominated_set_3d_helper (points , rows , size , 3 , false, nondom );
485+ const double * * rows = generate_row_pointers (points , size , 3 );
486+ size_t new_size = find_nondominated_3d_impl (rows , size , keep_weakly , /* find_one_dominated=*/ false);
487+
488+ if (new_size < size ) {
489+ memset (nondom , false, size * sizeof (* nondom ));
490+ size_t k = 0 , n = 0 ;
491+ do {
492+ while (rows [k ] == NULL ) k ++ ; // Find next nondominated (there must be at least one).
493+ nondom [row_index_from_ptr (points , rows [k ], 3 )] = true;
494+ n ++ ;
495+ k ++ ;
496+ } while (n < new_size );
497+ }
477498 free (rows );
478499 return new_size ;
479500}
0 commit comments