| 193 | |
| 194 | // factor the common terms out |
| 195 | template<> AndExpr DisjointExpr<AndExpr>::factor() const { |
| 196 | assert(!vals.empty()); |
| 197 | if (vals.size() == 1) |
| 198 | return vals.begin()->first; |
| 199 | |
| 200 | AndExpr ret; |
| 201 | vector<pair<AndExpr, expr>> vals2; |
| 202 | vals2.insert(vals2.end(), vals.begin(), vals.end()); |
| 203 | |
| 204 | vector<pair<set<expr>::iterator, set<expr>::iterator>> its; |
| 205 | its.reserve(vals2.size()); |
| 206 | for (auto &v : vals2) { |
| 207 | its.emplace_back(v.first.exprs.begin(), v.first.exprs.end()); |
| 208 | } |
| 209 | |
| 210 | auto &it0 = its[0].first; |
| 211 | while (it0 != its[0].second) { |
| 212 | const expr &e0 = *it0; |
| 213 | bool in_all = true; |
| 214 | for (unsigned i = 1, e = its.size(); i != e; ++i) { |
| 215 | auto &it2 = its[i].first; |
| 216 | if (it2 == its[i].second) { |
| 217 | goto end; |
| 218 | } |
| 219 | auto cmp = *it2 <=> e0; |
| 220 | if (cmp < 0) { |
| 221 | ++it2; |
| 222 | --i; // repeate this AndExpr |
| 223 | } else if (cmp > 0) { |
| 224 | ++it0; |
| 225 | in_all = false; |
| 226 | break; |
| 227 | } |
| 228 | } |
| 229 | if (in_all) { |
| 230 | ret.add(e0); |
| 231 | unsigned i = 0; |
| 232 | for (auto &v : vals2) { |
| 233 | auto &it = its[i++].first; |
| 234 | it = v.first.exprs.erase(it); |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | end: |
| 239 | DisjointExpr<expr> leftovers; |
| 240 | for (auto &[v, domain] : vals2) { |
| 241 | leftovers.add(std::move(v)(), std::move(domain)); |
| 242 | } |
| 243 | ret.add(*std::move(leftovers)()); |
| 244 | return ret; |
| 245 | } |
| 246 | |
| 247 | |
| 248 | void FunctionExpr::add(const expr &key, expr &&val) { |
no test coverage detected