Skip to content

Commit

Permalink
Properly formulate the invariant.
Browse files Browse the repository at this point in the history
  • Loading branch information
thorstenhater committed Sep 25, 2024
1 parent 9b1ca35 commit 6b41b3a
Showing 1 changed file with 19 additions and 21 deletions.
40 changes: 19 additions & 21 deletions arbor/util/piecewise.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <format>

// Create/manipulate 1-d piecewise defined objects.
//
Expand Down Expand Up @@ -398,7 +399,6 @@ struct pw_elements {
void push_back(double left, double right, U&& v) {
if (!empty() && left != vertex_.back()) throw std::runtime_error("noncontiguous element");
if (right<left) throw std::runtime_error("inverted element");

// Extend value_ first in case a conversion/copy/move throws.
value_.push_back(std::forward<U>(v));
if (vertex_.empty()) vertex_.push_back(left);
Expand All @@ -407,10 +407,7 @@ struct pw_elements {

template <typename U>
void push_back(double right, U&& v) {
if (empty()) {
throw std::runtime_error("require initial left vertex for element");
}

if (empty()) throw std::runtime_error("require initial left vertex for element");
push_back(vertex_.back(), right, std::forward<U>(v));
}

Expand All @@ -424,39 +421,40 @@ struct pw_elements {
using std::begin;
using std::end;

auto vi = begin(vertices);
auto ve = end(vertices);
auto ei = begin(values);
auto ee = end(values);
// Invariant, see below
// empty() || value_.size() + 1 = vertex_.size()
auto vs = std::size(vertices);
auto es = std::size(values);
// check invariant
if (!((es == 0 && es == vs)
|| (es != 0 && es + 1 == vs))) {
throw std::runtime_error{std::format("Vertices and values need to have matching lengths; #vertices={} #values={}.", vs, es)};
}

// clean-up
clear();

// empty case
if (ei == ee) {
if (vi != ve) throw std::runtime_error{"Vertices and values need to have same length; values too long."};
return;
}
if (vi == ve) throw std::runtime_error{"Vertices and values need to have same length; values too short."};
reserve(vertices.size());
// We know that invariant holds from here on.
if (es == 0) return;

auto vi = begin(vertices);
auto ei = begin(values);
auto ee = end(values);

reserve(vs);
double left = *vi++;
if (vi == ve) throw std::runtime_error{"Vertices and values need to have same length; values too short."};
double right = *vi++;
push_back(left, right, *ei++);

while (ei != ee) {
if (vi == ve) throw std::runtime_error{"Vertices and values need to have same length; values too short."};
double right = *vi++;
push_back(right, *ei++);
}
if (vi != ve) throw std::runtime_error{"Vertices and values need to have same length; values too long."};
}

private:
// Consistency requirements:
// 1. empty() || value_.size()+1 = vertex_.size()
// 2. vertex_[i]<=vertex_[j] for i<=j.

std::vector<double> vertex_;
std::vector<X> value_;
};
Expand Down

0 comments on commit 6b41b3a

Please sign in to comment.