]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 3365: Create and use uniquify function for removing duplicate Grobs
authorDavid Kastrup <dak@gnu.org>
Tue, 14 May 2013 10:00:08 +0000 (12:00 +0200)
committerDavid Kastrup <dak@gnu.org>
Sat, 18 May 2013 16:13:13 +0000 (18:13 +0200)
As opposed to the previous code, this retains the original order, making
results independent from GUILE's memory allocation algorithms.

lily/accidental-placement.cc
lily/grob-array.cc
lily/grob.cc
lily/include/grob.hh
lily/system.cc

index 1f2a943045bf1d687642a4146ec9567a07fd9461..b7a41c0266fdb07a7b1933d76d736ce7aa1665a1 100644 (file)
@@ -342,9 +342,8 @@ extract_heads_and_stems (vector<Accidental_placement_entry *> const &apes)
   for (vsize i = ret.size (); i--;)
     if (Grob *s = Rhythmic_head::get_stem (ret[i]))
       ret.push_back (s);
-
-  vector_sort (ret, less<Grob *> ());
-  uniq (ret);
+  
+  uniquify (ret);
   return ret;
 }
 
index 62d071cee17a03d69a5639c05d3ea318276f6682..d0cf11106878b12c73a80d6222cfb7aed955100e 100644 (file)
@@ -98,8 +98,7 @@ Grob_array::remove_duplicates ()
 {
   assert (!ordered_);
 
-  vector_sort (grobs_, less<Grob *> ());
-  ::uniq (grobs_);
+  uniquify (grobs_);
 }
 
 bool
index a6b862e04eee586495fd6e1b3aff343e0340678b..43828310a799d833820018766c776d8cbd138288 100644 (file)
@@ -972,3 +972,50 @@ Grob::check_cross_staff (Grob *commony)
   return false;
 }
 
+static
+bool
+indirect_less (Grob **a, Grob **b)
+{
+  // Use original order as tie breaker.  That gives us a stable sort
+  // at the lower price tag of an unstable one, and we want a stable
+  // sort in order to reliably retain the first instance of a grob
+  // pointer.
+  return *a < *b || (*a == *b && a < b);
+}
+
+static
+bool
+indirect_eq (Grob **a, Grob **b)
+{
+  return *a == *b;
+}
+
+static
+bool
+direct_less (Grob **a, Grob **b)
+{
+  return a < b;
+}
+
+// uniquify uniquifies on the memory addresses of the Grobs, but then
+// uses the original order.  This makes results independent from the
+// memory allocation of Grobs.
+
+void
+uniquify (vector <Grob *> & grobs)
+{
+  vector <Grob **> vec (grobs.size ());
+  for (vsize i = 0; i < grobs.size (); i++)
+    vec[i] = &grobs[i];
+  vector_sort (vec, indirect_less);
+  vec.erase (unique (vec.begin (), vec.end (), indirect_eq), vec.end ());
+  vector_sort (vec, direct_less);
+
+  // Since the output is a sorted copy of the input with some elements
+  // removed, we can fill in the vector in-place if we do it starting
+  // from the front.
+  for (vsize i = 0; i < vec.size (); i++)
+    grobs[i] = *vec[i];
+  grobs.erase (grobs.begin () + vec.size (), grobs.end ());
+  return;
+}
index 70c9c0a94e0a92ad2e9dfb3006473411b86da50f..bc4071eb042410c2a83c4ee22869307ed5d9a6d5 100644 (file)
@@ -176,6 +176,9 @@ DECLARE_UNSMOB (Grob, grob);
 Spanner *unsmob_spanner (SCM);
 Item *unsmob_item (SCM);
 
+/* unification */
+void uniquify (vector <Grob *> &);
+
 /* refpoints */
 Grob *common_refpoint_of_list (SCM elt_list, Grob *, Axis a);
 Grob *common_refpoint_of_array (vector<Grob *> const &, Grob *, Axis a);
index b2e0d53a880405a5037811a2f057a25e1bad2749..1ec46fbaf655c342d3e9a6e20faae3df9f352c0f 100644 (file)
@@ -548,8 +548,7 @@ System::post_processing ()
      anyway. */
 
   vector<Grob *> all_elts_sorted (all_elements_->array ());
-  vector_sort (all_elts_sorted, std::less<Grob *> ());
-  uniq (all_elts_sorted);
+  uniquify (all_elts_sorted);
   this->get_stencil ();
   for (vsize i = all_elts_sorted.size (); i--;)
     {