ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange( ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, const llvm::APSInt &Adjustment) { RangeSet New = getSymGERange(State, Sym, From, Adjustment); if (New.isEmpty()) return nullptr; RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment); return Out.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, Out); }
ProgramStateRef RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); switch (AdjustmentType.testInRange(Int, true)) { case APSIntType::RTR_Below: return nullptr; case APSIntType::RTR_Within: break; case APSIntType::RTR_Above: return St; } // Special case for Int == Max. This is always feasible. llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); llvm::APSInt Max = AdjustmentType.getMaxValue(); if (ComparisonVal == Max) return St; llvm::APSInt Min = AdjustmentType.getMinValue(); llvm::APSInt Lower = Min-Adjustment; llvm::APSInt Upper = ComparisonVal-Adjustment; RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); }
ProgramStateRef RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { RangeSet New = getSymLERange(St, Sym, Int, Adjustment); return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); }
const ProgramState* RangeConstraintManager::assumeSymEQ(const ProgramState *state, SymbolRef sym, const llvm::APSInt& Int, const llvm::APSInt& Adjustment) { // [Int-Adjustment, Int-Adjustment] BasicValueFactory &BV = state->getBasicVals(); llvm::APSInt AdjInt = Int-Adjustment; RangeSet New = GetRange(state, sym).Intersect(BV, F, AdjInt, AdjInt); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); }
ProgramStateRef RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) return nullptr; // [Int-Adjustment, Int-Adjustment] llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment; RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt); return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); }
const ProgramState* RangeConstraintManager::assumeSymNE(const ProgramState *state, SymbolRef sym, const llvm::APSInt& Int, const llvm::APSInt& Adjustment) { BasicValueFactory &BV = state->getBasicVals(); llvm::APSInt Lower = Int-Adjustment; llvm::APSInt Upper = Lower; --Lower; ++Upper; // [Int-Adjustment+1, Int-Adjustment-1] // Notice that the lower bound is greater than the upper bound. RangeSet New = GetRange(state, sym).Intersect(BV, F, Upper, Lower); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); }
ProgramStateRef RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) return St; llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment; llvm::APSInt Upper = Lower; --Lower; ++Upper; // [Int-Adjustment+1, Int-Adjustment-1] // Notice that the lower bound is greater than the upper bound. RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower); return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); }
const ProgramState* RangeConstraintManager::assumeSymGT(const ProgramState *state, SymbolRef sym, const llvm::APSInt& Int, const llvm::APSInt& Adjustment) { BasicValueFactory &BV = state->getBasicVals(); QualType T = state->getSymbolManager().getType(sym); const llvm::APSInt &Max = BV.getMaxValue(T); // Special case for Int == Max. This is always false. if (Int == Max) return NULL; llvm::APSInt Lower = Int-Adjustment; llvm::APSInt Upper = Max-Adjustment; ++Lower; RangeSet New = GetRange(state, sym).Intersect(BV, F, Lower, Upper); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); }
/** * Splits the selected segments by inserting new nodes in the middle. The * selected segments are defined by each pair of consecutive \a indexRanges. * * This method can deal with both polygons as well as polylines. For polygons, * pass <code>true</code> for \a closed. */ static QPolygonF splitPolygonSegments(const QPolygonF &polygon, const RangeSet<int> &indexRanges, bool closed) { if (indexRanges.isEmpty()) return polygon; const int n = polygon.size(); QPolygonF result = polygon; RangeSet<int>::Range firstRange = indexRanges.begin(); RangeSet<int>::Range it = indexRanges.end(); // assert: firstRange != it if (closed) { RangeSet<int>::Range lastRange = it; --lastRange; // We know there is at least one range // Handle the case where the first and last nodes are selected if (firstRange.first() == 0 && lastRange.last() == n - 1) { const QPointF splitPoint = (result.first() + result.last()) / 2; result.append(splitPoint); } } do { --it; for (int i = it.last(); i > it.first(); --i) { const QPointF splitPoint = (result.at(i) + result.at(i - 1)) / 2; result.insert(i, splitPoint); } } while (it != firstRange); return result; }
/** * Joins the nodes at the given \a indexRanges. Each consecutive sequence * of nodes will be joined into a single node at the average location. * * This method can deal with both polygons as well as polylines. For polygons, * pass <code>true</code> for \a closed. */ static QPolygonF joinPolygonNodes(const QPolygonF &polygon, const RangeSet<int> &indexRanges, bool closed) { if (indexRanges.isEmpty()) return polygon; // Do nothing when dealing with a polygon with less than 3 points // (we'd no longer have a polygon) const int n = polygon.size(); if (n < 3) return polygon; RangeSet<int>::Range firstRange = indexRanges.begin(); RangeSet<int>::Range it = indexRanges.end(); RangeSet<int>::Range lastRange = it; --lastRange; // We know there is at least one range QPolygonF result = polygon; // Indexes need to be offset when first and last range are joined. int indexOffset = 0; // Check whether the first and last ranges connect if (firstRange.first() == 0 && lastRange.last() == n - 1) { // Do nothing when the selection spans the whole polygon if (firstRange == lastRange) return polygon; // Join points of the first and last range when the polygon is closed if (closed) { QPointF averagePoint; for (int i = firstRange.first(); i <= firstRange.last(); i++) averagePoint += polygon.at(i); for (int i = lastRange.first(); i <= lastRange.last(); i++) averagePoint += polygon.at(i); averagePoint /= firstRange.length() + lastRange.length(); result.remove(lastRange.first(), lastRange.length()); result.remove(1, firstRange.length() - 1); result.replace(0, averagePoint); indexOffset = firstRange.length() - 1; // We have dealt with these ranges now // assert: firstRange != lastRange ++firstRange; --it; } } while (it != firstRange) { --it; // Merge the consecutive nodes into a single average point QPointF averagePoint; for (int i = it.first(); i <= it.last(); i++) averagePoint += polygon.at(i - indexOffset); averagePoint /= it.length(); result.remove(it.first() + 1 - indexOffset, it.length() - 1); result.replace(it.first() - indexOffset, averagePoint); } return result; }