@@ -169,7 +169,7 @@ pareto_rank_2d(const double * restrict points, size_t size)
169169 fprintf (stderr , "\n[1] : " ); vector_fprintf (stderr , help_1 , size );
170170#endif
171171
172- // Sort in ascending lexicographic order from the first dimension.
172+ // Sort in ascending lexicographic order from the second dimension.
173173 qsort (p , size , sizeof (* p ), cmp_double_asc_rev_2d );
174174
175175#ifdef PARETO_RANK_2D_DEBUG
@@ -185,43 +185,44 @@ pareto_rank_2d(const double * restrict points, size_t size)
185185#endif
186186
187187 int * rank = malloc (size * sizeof (* rank ));
188- const double * * front_last = malloc (size * sizeof (* front_last ));
188+ double * front_last = malloc (size * sizeof (* front_last ));
189189 int n_front = 0 ;
190- front_last [0 ] = p [0 ];
190+ front_last [0 ] = p [0 ][ 0 ] ;
191191 rank [(p [0 ] - points ) / dim ] = 0 ; // The first point is in the first front.
192+ int last_rank = 0 ;
192193 for (size_t k = 1 ; k < size ; k ++ ) {
193- const double * pk = p [k ];
194- const double * plast = front_last [n_front ];
195- if (pk [0 ] < plast [0 ]) {
194+ const double * restrict pk = p [k ];
195+ // Duplicated points are kept in the same front.
196+ if (pk [0 ] == p [k - 1 ][0 ] && pk [1 ] == p [k - 1 ][1 ]) {
197+ rank [(pk - points ) / dim ] = last_rank ;
198+ continue ;
199+ }
200+ const double plast = front_last [n_front ];
201+ if (pk [0 ] < plast ) {
196202 int low = 0 ;
197- int high = n_front + 1 ;
198- do {
199- int mid = low + (high - low ) / 2 ;
200- assert (mid <= n_front );
201- const double * pmid = front_last [mid ];
202- if (pk [0 ] < pmid [0 ])
203- high = mid ;
204- else if (pk [0 ] > pmid [0 ] || (pk [0 ] == pmid [0 ] && pk [1 ] > pmid [1 ]))
205- low = mid + 1 ;
206- else { // Duplicated points are assigned to the same front.
207- low = mid ;
208- break ;
209- }
210- } while (low < high );
211- assert (low <= n_front );
212- assert (pk [0 ] < front_last [low ][0 ]
213- || (pk [0 ] == front_last [low ][0 ]
214- && pk [1 ] == front_last [low ][1 ]));
215- front_last [low ] = pk ;
216- rank [(pk - points )/dim ] = low ;
217- } else if (pk [0 ] == plast [0 ] && pk [1 ] == plast [1 ]) {
218- front_last [n_front ] = pk ;
219- rank [(pk - points )/dim ] = n_front ;
203+ if (n_front > 0 ) {
204+ int high = n_front + 1 ;
205+ do {
206+ int mid = low + (high - low ) / 2 ;
207+ assert (mid <= n_front );
208+ const double pmid = front_last [mid ];
209+ // FIXME: When mid == n_front, then pk[0] < pmid, so avoid this test.
210+ if (pk [0 ] < pmid )
211+ high = mid ;
212+ else {
213+ low = mid + 1 ;
214+ }
215+ } while (low < high );
216+ }
217+ assert (low <= n_front );
218+ assert (pk [0 ] < front_last [low ]);
219+ last_rank = low ;
220220 } else {
221221 n_front ++ ;
222- front_last [n_front ] = pk ;
223- rank [(pk - points )/dim ] = n_front ;
222+ last_rank = n_front ;
224223 }
224+ front_last [last_rank ] = pk [0 ];
225+ rank [(pk - points )/dim ] = last_rank ;
225226 }
226227 free (front_last );
227228#ifdef PARETO_RANK_2D_DEBUG
0 commit comments