#include #include #include #include #include #include "range_structures.h" using namespace std; static vector FindParticularSolution(const ArrayDimension& dim1, const ArrayDimension& dim2) { for (uint64_t i = 0; i < dim1.tripCount; i++) { uint64_t leftPart = dim1.start + i * dim1.step; for (uint64_t j = 0; j < dim2.tripCount; j++) { uint64_t rightPart = dim2.start + j * dim2.step; if (leftPart == rightPart) return { i, j }; } } return {}; } /* dim1 /\ dim2 */ static ArrayDimension* DimensionIntersection(const ArrayDimension& dim1, const ArrayDimension& dim2) { vector partSolution = FindParticularSolution(dim1, dim2); if (partSolution.empty()) return NULL; int64_t x0 = partSolution[0], y0 = partSolution[1]; /* x = x_0 + c * t */ /* y = y_0 + d * t */ int64_t c = dim2.step / gcd(dim1.step, dim2.step); int64_t d = dim1.step / gcd(dim1.step, dim2.step); int64_t tXMin, tXMax, tYMin, tYMax; tXMin = -x0 / c; tXMax = (dim1.tripCount - 1 - x0) / c; tYMin = -y0 / d; tYMax = (dim2.tripCount - 1 - y0) / d; int64_t tMin = max(tXMin, tYMin); uint64_t tMax = min(tXMax, tYMax); if (tMin > tMax) return NULL; uint64_t start3 = dim1.start + x0 * dim1.step; uint64_t step3 = c * dim1.step; ArrayDimension* result = new(ArrayDimension){ start3, step3, tMax + 1 }; return result; } /* dim1 / dim2 */ static vector DimensionDifference(const ArrayDimension& dim1, const ArrayDimension& dim2) { ArrayDimension* intersection = DimensionIntersection(dim1, dim2); if (!intersection) return { dim1 }; vector result; /* add the part before intersection */ if (dim1.start < intersection->start) result.push_back({ dim1.start, dim1.step, (intersection->start - dim1.start) / dim1.step }); /* add the parts between intersection steps */ uint64_t start = (intersection->start - dim1.start) / dim1.step; uint64_t interValue = intersection->start; for (int64_t i = start; dim1.start + i * dim1.step <= intersection->start + intersection->step * (intersection->tripCount - 1); i++) { uint64_t centerValue = dim1.start + i * dim1.step; if (centerValue == interValue) { if (i - start > 1) { result.push_back({ dim1.start + (start + 1) * dim1.step, dim1.step, i - start - 1 }); start = i; } interValue += intersection->step; } } /* add the part after intersection */ if (intersection->start + intersection->step * (intersection->tripCount - 1) < dim1.start + dim1.step * (dim1.tripCount - 1)) { /* first value after intersection */ uint64_t right_start = intersection->start + intersection->step * (intersection->tripCount - 1) + dim1.step; uint64_t tripCount = (dim1.start + dim1.step * dim1.tripCount - right_start) / dim1.step; result.push_back({ right_start, dim1.step, tripCount }); } delete(intersection); return result; } static vector DimensionUnion(const ArrayDimension& dim1, const ArrayDimension& dim2) { vector res; ArrayDimension* inter = DimensionIntersection(dim1, dim2); if (!inter) return { dim1, dim2 }; res.push_back(*inter); delete(inter); vector diff1, diff2; diff1 = DimensionDifference(dim1, dim2); diff2 = DimensionDifference(dim2, dim1); res.insert(res.end(), diff1.begin(), diff1.end()); res.insert(res.end(), diff2.begin(), diff2.end()); return res; } static vector ElementsIntersection(const vector& firstElement, const vector& secondElement) { if (firstElement.empty() || secondElement.empty()) return {}; size_t dimAmount = firstElement.size(); /* check if there is no intersecction */ for (size_t i = 0; i < dimAmount; i++) if (FindParticularSolution(firstElement[i], secondElement[i]).empty()) return {}; vector result(dimAmount); for (size_t i = 0; i < dimAmount; i++) { ArrayDimension* resPtr = DimensionIntersection(firstElement[i], secondElement[i]); if (resPtr) result[i] = *resPtr; else return {}; } return result; } static vector> ElementsDifference(const vector& firstElement, const vector& secondElement) { if (firstElement.empty() || secondElement.empty()) return {}; vector intersection = ElementsIntersection(firstElement, secondElement); vector> result; if (intersection.empty()) return { firstElement }; for (int i = 0; i < firstElement.size(); i++) { auto dimDiff = DimensionDifference(firstElement[i], secondElement[i]); if (!dimDiff.empty()) { vector firstCopy = firstElement; for (const auto& range : dimDiff) { firstCopy[i] = range; result.push_back(firstCopy); } } } return result; } static void ElementsUnion(const vector& firstElement, const vector& secondElement, vector>& lc, vector>& rc, vector& intersection) { /* lc(rc) is a set of ranges, which only exist in first(second) element*/ intersection = ElementsIntersection(firstElement, secondElement); lc = ElementsDifference(firstElement, intersection); rc = ElementsDifference(secondElement, intersection); } void AccessingSet::FindUncovered(const vector& element, vector>& result) const { vector> newTails; result.push_back(element); for (const auto& currentElement : allElements) { for (const auto& tailLoc : result) { auto intersection = ElementsIntersection(tailLoc, currentElement); auto diff = ElementsDifference(tailLoc, intersection); if (!diff.empty()) { newTails.insert(newTails.end(), diff.begin(), diff.end()); } } result = newTails; newTails.clear(); } } bool AccessingSet::ContainsElement(const vector& element) const { vector> tails; FindUncovered(element, tails); return !tails.empty(); } void AccessingSet::FindCoveredBy(const vector& element, vector>& result) const { for (const auto& currentElement : allElements) { auto intersection = ElementsIntersection(element, currentElement); if (!intersection.empty()) result.push_back(intersection); } } vector> AccessingSet::GetElements() const { return allElements; } void AccessingSet::Insert(const vector& element) { vector> tails; FindUncovered(element, tails); allElements.insert(allElements.end(), tails.begin(), tails.end()); } AccessingSet AccessingSet::Union(const AccessingSet& source) { AccessingSet result; for (auto& element : source.GetElements()) result.Insert(element); for (auto& element : allElements) result.Insert(element); return result; } AccessingSet AccessingSet::Intersect(const AccessingSet& secondSet) const { vector> result; if (secondSet.GetElements().empty() || this->allElements.empty()) return AccessingSet(result); for (const auto& element : allElements) { if (secondSet.ContainsElement(element)) result.push_back(element); else { vector> coveredBy; secondSet.FindCoveredBy(element, coveredBy); if (!coveredBy.empty()) result.insert(result.end(), coveredBy.begin(), coveredBy.end()); } } return AccessingSet(result); } AccessingSet AccessingSet::Diff(const AccessingSet& secondSet) const { if (secondSet.GetElements().empty() || allElements.empty()) return *this; AccessingSet intersection = this->Intersect(secondSet); AccessingSet uncovered = *this; vector> result; for (const auto& element : intersection.GetElements()) { vector> current_uncovered; uncovered.FindUncovered(element, current_uncovered); uncovered = AccessingSet(current_uncovered); } return uncovered; } bool operator!=(const ArrayDimension& lhs, const ArrayDimension& rhs) { return !(lhs.start == rhs.start && lhs.step == rhs.step && lhs.tripCount == rhs.tripCount); } bool operator!=(const AccessingSet& lhs, const AccessingSet& rhs) { for (size_t i = 0; i < lhs.allElements.size(); i++) for (size_t j = 0; j < lhs.allElements[i].size(); j++) if (lhs.allElements[i][j] != rhs.allElements[i][j]) return true; return false; } bool operator!=(const ArrayAccessingIndexes& lhs, const ArrayAccessingIndexes& rhs) { if (lhs.size() != rhs.size()) return true; for (auto& [key, value] : lhs) if (rhs.find(key) == rhs.end()) return true; return false; }