LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
interval_set_operations.cpp
浏览该文件的文档.
2#include <utility>
3
4namespace LMCAS {
8
9namespace {
10
12 const std::vector<Interval>& intervals,
14 const std::string& operation) {
15 auto normalized = normalize_intervals_checked(intervals, context);
16 if (!normalized) {
18 normalized.error().code, normalized.error().message, operation);
19 }
20
21 std::vector<CheckedInterval> checked;
22 auto normalized_intervals = std::move(normalized.value());
23 checked.reserve(normalized_intervals.size());
24 for (auto& interval : normalized_intervals) {
25 auto lower = comparable_endpoint(interval.lower, context, operation);
26 if (!lower) {
27 return Result<std::vector<CheckedInterval>>::failure(lower.error());
28 }
29 auto upper = comparable_endpoint(interval.upper, context, operation);
30 if (!upper) {
32 }
33 checked.push_back(CheckedInterval{
34 std::move(interval), std::move(lower.value()), std::move(upper.value())});
35 }
36 return Result<std::vector<CheckedInterval>>::success(std::move(checked));
37}
38
39Endpoint complement_lower_from_upper(const Endpoint& upper) {
40 Endpoint lower;
41 lower.value = upper.value;
42 lower.is_open = !upper.is_open;
43 lower.is_neg_infinity = false;
44 lower.is_pos_infinity = false;
45 return lower;
46}
47
48Endpoint complement_upper_from_lower(const Endpoint& lower) {
49 Endpoint upper;
50 upper.value = lower.value;
51 upper.is_open = !lower.is_open;
52 upper.is_neg_infinity = false;
53 upper.is_pos_infinity = false;
54 return upper;
55}
56
58 int lower_order, int upper_order) {
59 Interval candidate{
60 lower_order >= 0 ? a.interval.lower : b.interval.lower,
61 upper_order <= 0 ? a.interval.upper : b.interval.upper
62 };
63 if (lower_order == 0) {
64 candidate.lower.is_open = a.interval.lower.is_open || b.interval.lower.is_open;
65 }
66 if (upper_order == 0) {
67 candidate.upper.is_open = a.interval.upper.is_open || b.interval.upper.is_open;
68 }
69 return candidate;
70}
71
72}
73
74Result<IntervalUnion> IntervalUnion::intersect_checked(
75 const IntervalUnion& other,
76 ComputationContext& context) const {
77 constexpr const char* operation = "interval_union_intersect";
78 auto left = checked_interval_views(intervals_, context, operation);
79 if (!left) {
80 return Result<IntervalUnion>::failure(left.error());
81 }
82 auto right = checked_interval_views(other.intervals_, context, operation);
83 if (!right) {
85 }
86
87 const auto& a_intervals = left.value();
88 const auto& b_intervals = right.value();
89 std::vector<Interval> result;
90 std::size_t i = 0;
91 std::size_t j = 0;
92 while (i < a_intervals.size() && j < b_intervals.size()) {
93 const auto& a = a_intervals[i];
94 const auto& b = b_intervals[j];
95 auto lower_order = compare_comparable(a.lower, b.lower, context);
96 if (!lower_order) {
97 return Result<IntervalUnion>::failure(lower_order.error());
98 }
99 auto upper_order = compare_comparable(a.upper, b.upper, context);
100 if (!upper_order) {
101 return Result<IntervalUnion>::failure(upper_order.error());
102 }
103 auto candidate = intersection_candidate(
104 a, b, lower_order.value(), upper_order.value());
105 auto empty = interval_is_empty_checked(candidate, context);
106 if (!empty) {
108 empty.error().code, empty.error().message, operation);
109 }
110 if (!empty.value()) {
111 result.push_back(std::move(candidate));
112 }
113
114 if (upper_order.value() < 0) {
115 ++i;
116 } else {
117 ++j;
118 }
119 }
120
121 auto normalized = normalize_intervals_checked(std::move(result), context);
122 if (!normalized) {
124 normalized.error().code, normalized.error().message, operation);
125 }
127 IntervalUnion::from_checked_normalized(std::move(normalized.value())));
128}
129
130Result<IntervalUnion> IntervalUnion::intersect_checked(
131 const IntervalUnion& other) const {
133 return intersect_checked(other, context);
134}
135
136Result<IntervalUnion> IntervalUnion::unite_checked(
137 const IntervalUnion& other,
139 constexpr const char* operation = "interval_union_unite";
140 std::vector<Interval> all;
141 all.reserve(intervals_.size() + other.intervals_.size());
142 all.insert(all.end(), intervals_.begin(), intervals_.end());
143 all.insert(all.end(), other.intervals_.begin(), other.intervals_.end());
144
145 auto step = context.consume_steps(all.size(), operation);
146 if (!step) {
147 return Result<IntervalUnion>::failure(step.error());
148 }
149 auto normalized = normalize_intervals_checked(std::move(all), context);
150 if (!normalized) {
151 return Result<IntervalUnion>::failure(normalized.error());
152 }
154 IntervalUnion::from_checked_normalized(std::move(normalized.value())));
155}
156
157Result<IntervalUnion> IntervalUnion::unite_checked(
158 const IntervalUnion& other) const {
160 return unite_checked(other, context);
161}
162
163Result<IntervalUnion> IntervalUnion::complement_checked(
165 constexpr const char* operation = "interval_union_complement";
166 auto checked = checked_interval_views(intervals_, context, operation);
167 if (!checked) {
168 return Result<IntervalUnion>::failure(checked.error());
169 }
170 const auto& intervals = checked.value();
171
172 if (intervals.empty()) {
174 IntervalUnion::from_checked_normalized({Interval::entire_line()}));
175 }
176 if (intervals.size() == 1 &&
177 intervals[0].interval.lower.is_neg_infinity &&
178 intervals[0].interval.upper.is_pos_infinity) {
179 return Result<IntervalUnion>::success(IntervalUnion::from_checked_normalized({}));
180 }
181
182 std::vector<Interval> result;
183 const Interval& first = intervals.front().interval;
184 if (!first.lower.is_neg_infinity) {
185 result.push_back(Interval{
186 Endpoint::neg_inf(),
187 complement_upper_from_lower(first.lower)
188 });
189 }
190
191 for (std::size_t i = 0; i + 1 < intervals.size(); ++i) {
192 const Interval& current = intervals[i].interval;
193 const Interval& next = intervals[i + 1].interval;
194 result.push_back(Interval{
195 complement_lower_from_upper(current.upper),
197 });
198 }
199
200 const Interval& last = intervals.back().interval;
201 if (!last.upper.is_pos_infinity) {
202 result.push_back(Interval{
203 complement_lower_from_upper(last.upper),
204 Endpoint::pos_inf()
205 });
206 }
207
208 auto normalized = normalize_intervals_checked(std::move(result), context);
209 if (!normalized) {
210 return Result<IntervalUnion>::failure(normalized.error());
211 }
213 IntervalUnion::from_checked_normalized(std::move(normalized.value())));
214}
215
216Result<IntervalUnion> IntervalUnion::complement_checked() const {
218 return complement_checked(context);
219}
220
221}
CasError & error()
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
Result< std::vector< CheckedInterval > > checked_interval_views(const std::vector< Interval > &intervals, ComputationContext &context, const std::string &operation)
Interval intersection_candidate(const CheckedInterval &a, const CheckedInterval &b, int lower_order, int upper_order)
Result< ComparableEndpoint > comparable_endpoint(const Endpoint &endpoint, ComputationContext &context, const std::string &operation)
ComputationContext const std::string & operation
Result< int > compare_comparable(const ComparableEndpoint &left, const ComparableEndpoint &right, ComputationContext &context)
Result< ComparableEndpoint > comparable_endpoint(const Endpoint &endpoint, ComputationContext &context, const std::string &operation)
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult interval(ExprPtr lower, ExprPtr upper, bool lower_closed, bool upper_closed)
Result< bool > interval_is_empty_checked(const Interval &interval, ComputationContext &context)
const ExprPtr & lower
const MultiPoly & b
Result< std::vector< Interval > > normalize_intervals_checked(std::vector< Interval > intervals, ComputationContext &context)
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
const ExprPtr & right
Result< int > compare_comparable(const ComparableEndpoint &left, const ComparableEndpoint &right, ComputationContext &context)