]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add an assertion to IndexSet::compress(). 15953/head
authorWolfgang Bangerth <bangerth@colostate.edu>
Thu, 31 Aug 2023 22:55:11 +0000 (16:55 -0600)
committerWolfgang Bangerth <bangerth@colostate.edu>
Thu, 31 Aug 2023 22:55:11 +0000 (16:55 -0600)
source/base/index_set.cc

index f3c7b66b660e98b8f245f8bd409e5da8d648dc4d..168e1ecaa09b69e49b0b49b7659b34769f821d9f 100644 (file)
@@ -99,64 +99,84 @@ IndexSet::IndexSet(const Epetra_BlockMap &map)
 void
 IndexSet::do_compress() const
 {
-  // we will, in the following, modify mutable variables. this can only
-  // work in multithreaded applications if we lock the data structures
-  // via a mutex, so that users can call 'const' functions from threads
-  // in parallel (and these 'const' functions can then call compress()
-  // which itself calls the current function)
-  std::lock_guard<std::mutex> lock(compress_mutex);
-
-  // see if any of the contiguous ranges can be merged. do not use
-  // std::vector::erase in-place as it is quadratic in the number of
-  // ranges. since the ranges are sorted by their first index, determining
-  // overlap isn't all that hard
-  std::vector<Range>::iterator store = ranges.begin();
-  for (std::vector<Range>::iterator i = ranges.begin(); i != ranges.end();)
-    {
-      std::vector<Range>::iterator next = i;
-      ++next;
-
-      size_type first_index = i->begin;
-      size_type last_index  = i->end;
-
-      // see if we can merge any of the following ranges
-      while (next != ranges.end() && (next->begin <= last_index))
-        {
-          last_index = std::max(last_index, next->end);
-          ++next;
-        }
-      i = next;
-
-      // store the new range in the slot we last occupied
-      *store = Range(first_index, last_index);
-      ++store;
-    }
-  // use a compact array with exactly the right amount of storage
-  if (store != ranges.end())
-    {
-      std::vector<Range> new_ranges(ranges.begin(), store);
-      ranges.swap(new_ranges);
-    }
+  {
+    // we will, in the following, modify mutable variables. this can only
+    // work in multithreaded applications if we lock the data structures
+    // via a mutex, so that users can call 'const' functions from threads
+    // in parallel (and these 'const' functions can then call compress()
+    // which itself calls the current function)
+    std::lock_guard<std::mutex> lock(compress_mutex);
+
+    // see if any of the contiguous ranges can be merged. do not use
+    // std::vector::erase in-place as it is quadratic in the number of
+    // ranges. since the ranges are sorted by their first index, determining
+    // overlap isn't all that hard
+    std::vector<Range>::iterator store = ranges.begin();
+    for (std::vector<Range>::iterator i = ranges.begin(); i != ranges.end();)
+      {
+        std::vector<Range>::iterator next = i;
+        ++next;
+
+        size_type first_index = i->begin;
+        size_type last_index  = i->end;
+
+        // see if we can merge any of the following ranges
+        while (next != ranges.end() && (next->begin <= last_index))
+          {
+            last_index = std::max(last_index, next->end);
+            ++next;
+          }
+        i = next;
+
+        // store the new range in the slot we last occupied
+        *store = Range(first_index, last_index);
+        ++store;
+      }
+    // use a compact array with exactly the right amount of storage
+    if (store != ranges.end())
+      {
+        std::vector<Range> new_ranges(ranges.begin(), store);
+        ranges.swap(new_ranges);
+      }
+
+    // now compute indices within set and the range with most elements
+    size_type next_index = 0, largest_range_size = 0;
+    for (std::vector<Range>::iterator i = ranges.begin(); i != ranges.end();
+         ++i)
+      {
+        Assert(i->begin < i->end, ExcInternalError());
+
+        i->nth_index_in_set = next_index;
+        next_index += (i->end - i->begin);
+        if (i->end - i->begin > largest_range_size)
+          {
+            largest_range_size = i->end - i->begin;
+            largest_range      = i - ranges.begin();
+          }
+      }
+    is_compressed = true;
+
+    // check that next_index is correct. needs to be after the previous
+    // statement because we otherwise will get into an endless loop
+    Assert(next_index == n_elements(), ExcInternalError());
+  }
 
-  // now compute indices within set and the range with most elements
-  size_type next_index = 0, largest_range_size = 0;
-  for (std::vector<Range>::iterator i = ranges.begin(); i != ranges.end(); ++i)
-    {
-      Assert(i->begin < i->end, ExcInternalError());
-
-      i->nth_index_in_set = next_index;
-      next_index += (i->end - i->begin);
-      if (i->end - i->begin > largest_range_size)
-        {
-          largest_range_size = i->end - i->begin;
-          largest_range      = i - ranges.begin();
-        }
-    }
-  is_compressed = true;
-
-  // check that next_index is correct. needs to be after the previous
-  // statement because we otherwise will get into an endless loop
-  Assert(next_index == n_elements(), ExcInternalError());
+#ifdef DEBUG
+  // A consistency check: We should only ever have added indices
+  // that are within the range of the index set. Instead of doing
+  // this in every one of the many functions that add indices,
+  // do this in the current, central location
+  for (const auto &range : ranges)
+    Assert((range.begin < index_space_size) && (range.end <= index_space_size),
+           ExcMessage("In the process of creating the current IndexSet "
+                      "object, you added indices beyond the size of the index "
+                      "space. Specifically, you added elements that form the "
+                      "range [" +
+                      std::to_string(range.begin) + "," +
+                      std::to_string(range.end) +
+                      "), but the size of the index space is only " +
+                      std::to_string(index_space_size) + "."));
+#endif
 }
 
 

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.