llvm.org GIT mirror llvm / 5f456cd
Disallow overlapping inserts, even when inserting the same value. We always disallowed overlapping inserts with different values, and this makes the insertion code smaller and faster. If an overwriting insert is needed, it can be added as a separate method that trims any existing intervals before inserting. The immediate use cases for IntervalMap don't need this - they only use disjoint insertions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120264 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 9 years ago
2 changed file(s) with 55 addition(s) and 175 deletion(s). Raw diff Collapse all Expand all
585585 return Traits::startLess(x, start(i)) ? NotFound : value(i);
586586 }
587587
588 IdxPair insertFrom(unsigned i, unsigned Size, KeyT a, KeyT b, ValT y);
589 unsigned extendStop(unsigned i, unsigned Size, KeyT b);
588 unsigned insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y);
590589
591590 #ifndef NDEBUG
592591 void dump(raw_ostream &OS, unsigned Size) {
609608 /// @param y Value be mapped.
610609 /// @return (insert position, new size), or (i, Capacity+1) on overflow.
611610 template
612 IdxPair LeafNode::
613 insertFrom(unsigned i, unsigned Size, KeyT a, KeyT b, ValT y) {
611 unsigned LeafNode::
612 insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y) {
613 unsigned i = Pos;
614614 assert(i <= Size && Size <= N && "Invalid index");
615615 assert(!Traits::stopLess(b, a) && "Invalid interval");
616616
617617 // Verify the findFrom invariant.
618618 assert((i == 0 || Traits::stopLess(stop(i - 1), a)));
619619 assert((i == Size || !Traits::stopLess(stop(i), a)));
620 assert((i == Size || Traits::stopLess(b, start(i))) && "Overlapping insert");
620621
621622 // Coalesce with previous interval.
622 if (i && value(i - 1) == y && Traits::adjacent(stop(i - 1), a))
623 return IdxPair(i - 1, extendStop(i - 1, Size, b));
623 if (i && value(i - 1) == y && Traits::adjacent(stop(i - 1), a)) {
624 Pos = i - 1;
625 // Also coalesce with next interval?
626 if (i != Size && value(i) == y && Traits::adjacent(b, start(i))) {
627 stop(i - 1) = stop(i);
628 this->erase(i, Size);
629 return Size - 1;
630 }
631 stop(i - 1) = b;
632 return Size;
633 }
624634
625635 // Detect overflow.
626636 if (i == N)
627 return IdxPair(i, N + 1);
637 return N + 1;
628638
629639 // Add new interval at end.
630640 if (i == Size) {
631641 start(i) = a;
632642 stop(i) = b;
633643 value(i) = y;
634 return IdxPair(i, Size + 1);
635 }
636
637 // Overlapping intervals?
638 if (!Traits::stopLess(b, start(i))) {
639 assert(value(i) == y && "Inconsistent values in overlapping intervals");
640 if (Traits::startLess(a, start(i)))
641 start(i) = a;
642 return IdxPair(i, extendStop(i, Size, b));
644 return Size + 1;
643645 }
644646
645647 // Try to coalesce with following interval.
646648 if (value(i) == y && Traits::adjacent(b, start(i))) {
647649 start(i) = a;
648 return IdxPair(i, Size);
650 return Size;
649651 }
650652
651653 // We must insert before i. Detect overflow.
652654 if (Size == N)
653 return IdxPair(i, N + 1);
655 return N + 1;
654656
655657 // Insert before i.
656658 this->shift(i, Size);
657659 start(i) = a;
658660 stop(i) = b;
659661 value(i) = y;
660 return IdxPair(i, Size + 1);
661 }
662
663 /// extendStop - Extend stop(i) to b, coalescing with following intervals.
664 /// @param i Interval to extend.
665 /// @param Size Number of elements in node.
666 /// @param b New interval end point.
667 /// @return New node size after coalescing.
668 template
669 unsigned LeafNode::
670 extendStop(unsigned i, unsigned Size, KeyT b) {
671 assert(i < Size && Size <= N && "Bad indices");
672
673 // Are we even extending the interval?
674 if (Traits::startLess(b, stop(i)))
675 return Size;
676
677 // Find the first interval that may be preserved.
678 unsigned j = findFrom(i + 1, Size, b);
679 if (j < Size) {
680 // Would key[i] overlap key[j] after the extension?
681 if (Traits::stopLess(b, start(j))) {
682 // Not overlapping. Perhaps adjacent and coalescable?
683 if (value(i) == value(j) && Traits::adjacent(b, start(j)))
684 b = stop(j++);
685 } else {
686 // Overlap. Include key[j] in the new interval.
687 assert(value(i) == value(j) && "Overlapping values");
688 b = stop(j++);
689 }
690 }
691 stop(i) = b;
692
693 // Entries [i+1;j) were coalesced.
694 if (i + 1 < j && j < Size)
695 this->erase(i + 1, j, Size);
696 return Size - (j - (i + 1));
662 return Size + 1;
697663 }
698664
699665
11371103
11381104 // Easy insert into root leaf.
11391105 unsigned p = rootLeaf().findFrom(0, rootSize, a);
1140 rootSize = rootLeaf().insertFrom(p, rootSize, a, b, y).second;
1106 rootSize = rootLeaf().insertFrom(p, rootSize, a, b, y);
11411107 }
11421108
11431109 /// clear - Remove all entries.
16961662 IntervalMapImpl::Path &P = this->path;
16971663
16981664 // Try simple root leaf insert.
1699 IdxPair IP = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y);
1665 unsigned Size = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y);
17001666
17011667 // Was the root node insert successful?
1702 if (IP.second <= RootLeaf::Capacity) {
1703 P.leafOffset() = IP.first;
1704 P.setSize(0, IM.rootSize = IP.second);
1668 if (Size <= RootLeaf::Capacity) {
1669 P.setSize(0, IM.rootSize = Size);
17051670 return;
17061671 }
17071672
17181683 void IntervalMap::
17191684 iterator::treeInsert(KeyT a, KeyT b, ValT y) {
17201685 using namespace IntervalMapImpl;
1721 IntervalMap &IM = *this->map;
17221686 Path &P = this->path;
17231687
1688 if (!P.valid())
1689 P.legalizeForInsert(this->map->height);
1690
17241691 // Check if this insertion will extend the node to the left.
1725 if (P.valid() && P.leafOffset() == 0 &&
1726 Traits::startLess(a, P.leaf().start(0))) {
1692 if (P.leafOffset() == 0 && Traits::startLess(a, P.leaf().start(0))) {
17271693 // Node is growing to the left, will it affect a left sibling node?
1728 if (NodeRef Sib = P.getLeftSibling(IM.height)) {
1694 if (NodeRef Sib = P.getLeftSibling(P.height())) {
17291695 Leaf &SibLeaf = Sib.get();
17301696 unsigned SibOfs = Sib.size() - 1;
17311697 if (SibLeaf.value(SibOfs) == y &&
17361702 // 2. Extend a to SibLeaf, erase the SibLeaf entry and continue.
17371703 // We prefer 1., but need 2 when coalescing to the right as well.
17381704 Leaf &CurLeaf = P.leaf();
1739 P.moveLeft(IM.height);
1705 P.moveLeft(P.height());
17401706 if (Traits::stopLess(b, CurLeaf.start(0)) &&
17411707 (y != CurLeaf.value(0) || !Traits::adjacent(b, CurLeaf.start(0)))) {
17421708 // Easy, just extend SibLeaf and we're done.
1743 setNodeStop(IM.height, SibLeaf.stop(SibOfs) = b);
1709 setNodeStop(P.height(), SibLeaf.stop(SibOfs) = b);
17441710 return;
17451711 } else {
17461712 // We have both left and right coalescing. Erase the old SibLeaf entry
17511717 }
17521718 } else {
17531719 // No left sibling means we are at begin(). Update cached bound.
1754 IM.rootBranchStart() = a;
1720 this->map->rootBranchStart() = a;
17551721 }
17561722 }
17571723
1758 P.legalizeForInsert(IM.height);
1759 IdxPair IP = P.leaf().insertFrom(P.leafOffset(), P.leafSize(), a, b, y);
1724 // When we are inserting at the end of a leaf node, we must update stops.
1725 unsigned Size = P.leafSize();
1726 bool Grow = P.leafOffset() == Size;
1727 Size = P.leaf().insertFrom(P.leafOffset(), Size, a, b, y);
17601728
17611729 // Leaf insertion unsuccessful? Overflow and try again.
1762 if (IP.second > Leaf::Capacity) {
1763 overflow(IM.height);
1764 IP = P.leaf().insertFrom(P.leafOffset(), P.leafSize(), a, b, y);
1765 assert(IP.second <= Leaf::Capacity && "overflow() didn't make room");
1730 if (Size > Leaf::Capacity) {
1731 overflow(P.height());
1732 Grow = P.leafOffset() == P.leafSize();
1733 Size = P.leaf().insertFrom(P.leafOffset(), P.leafSize(), a, b, y);
1734 assert(Size <= Leaf::Capacity && "overflow() didn't make room");
17661735 }
17671736
17681737 // Inserted, update offset and leaf size.
1769 P.leafOffset() = IP.first;
1770 P.setSize(IM.height, IP.second);
1738 P.setSize(P.height(), Size);
17711739
17721740 // Insert was the last node entry, update stops.
1773 if (IP.first == IP.second - 1)
1774 setNodeStop(IM.height, P.leaf().stop(IP.first));
1741 if (Grow)
1742 setNodeStop(P.height(), b);
17751743 }
17761744
17771745 /// erase - erase the current interval and move to the next position.
115115 EXPECT_EQ(90u, map.start());
116116 EXPECT_EQ(150u, map.stop());
117117
118 // Overlap left.
119 map.insert(80, 100, 1);
118 // Coalesce from the right.
119 map.insert(151, 200, 1);
120120 EXPECT_EQ(1, std::distance(map.begin(), map.end()));
121 EXPECT_EQ(80u, map.start());
122 EXPECT_EQ(150u, map.stop());
123
124 // Inside.
125 map.insert(100, 130, 1);
126 EXPECT_EQ(1, std::distance(map.begin(), map.end()));
127 EXPECT_EQ(80u, map.start());
128 EXPECT_EQ(150u, map.stop());
129
130 // Overlap both.
131 map.insert(70, 160, 1);
132 EXPECT_EQ(1, std::distance(map.begin(), map.end()));
133 EXPECT_EQ(70u, map.start());
134 EXPECT_EQ(160u, map.stop());
135
136 // Overlap right.
137 map.insert(80, 170, 1);
138 EXPECT_EQ(1, std::distance(map.begin(), map.end()));
139 EXPECT_EQ(70u, map.start());
140 EXPECT_EQ(170u, map.stop());
141
142 // Coalesce from the right.
143 map.insert(170, 200, 1);
144 EXPECT_EQ(1, std::distance(map.begin(), map.end()));
145 EXPECT_EQ(70u, map.start());
121 EXPECT_EQ(90u, map.start());
146122 EXPECT_EQ(200u, map.stop());
147123
148124 // Non-coalesce from the left.
149 map.insert(60, 69, 2);
125 map.insert(60, 89, 2);
150126 EXPECT_EQ(2, std::distance(map.begin(), map.end()));
151127 EXPECT_EQ(60u, map.start());
152128 EXPECT_EQ(200u, map.stop());
153 EXPECT_EQ(2u, map.lookup(69));
154 EXPECT_EQ(1u, map.lookup(70));
129 EXPECT_EQ(2u, map.lookup(89));
130 EXPECT_EQ(1u, map.lookup(90));
155131
156132 UUMap::iterator I = map.begin();
157133 EXPECT_EQ(60u, I.start());
158 EXPECT_EQ(69u, I.stop());
134 EXPECT_EQ(89u, I.stop());
159135 EXPECT_EQ(2u, I.value());
160136 ++I;
161 EXPECT_EQ(70u, I.start());
137 EXPECT_EQ(90u, I.start());
162138 EXPECT_EQ(200u, I.stop());
163139 EXPECT_EQ(1u, I.value());
164140 ++I;
175151 // Erase from the left.
176152 map.begin().erase();
177153 EXPECT_EQ(2, std::distance(map.begin(), map.end()));
178 EXPECT_EQ(70u, map.start());
154 EXPECT_EQ(90u, map.start());
179155 EXPECT_EQ(210u, map.stop());
180156
181157 // Erase from the right.
182158 (--map.end()).erase();
183159 EXPECT_EQ(1, std::distance(map.begin(), map.end()));
184 EXPECT_EQ(70u, map.start());
160 EXPECT_EQ(90u, map.start());
185161 EXPECT_EQ(200u, map.stop());
186162 }
187163
287263 ++I;
288264 EXPECT_FALSE(I.valid());
289265
290 // Coalesce multiple with overlap right.
291 // [100;115] [120;150] [160;170]
292 map.insert(116, 165, 1);
293 I = map.begin();
294 ASSERT_TRUE(I.valid());
295 EXPECT_EQ(100u, I.start());
296 EXPECT_EQ(170u, I.stop());
297 ++I;
298 EXPECT_FALSE(I.valid());
299
300 // Coalesce multiple with overlap left
301 // [100;170]
302 map.insert(180, 190, 1);
303 map.insert(200, 210, 1);
304 map.insert(220, 230, 1);
305 // [100;170] [180;190] [200;210] [220;230]
306 map.insert(160, 199, 1);
307 I = map.begin();
308 ASSERT_TRUE(I.valid());
309 EXPECT_EQ(100u, I.start());
310 EXPECT_EQ(210u, I.stop());
311 ++I;
312 ASSERT_TRUE(I.valid());
313 EXPECT_EQ(220u, I.start());
314 EXPECT_EQ(230u, I.stop());
315 ++I;
316 EXPECT_FALSE(I.valid());
317
318 // Overwrite 2 from gap to gap.
319 // [100;210] [220;230]
320 map.insert(50, 250, 1);
321 I = map.begin();
322 ASSERT_TRUE(I.valid());
323 EXPECT_EQ(50u, I.start());
324 EXPECT_EQ(250u, I.stop());
325 ++I;
326 EXPECT_FALSE(I.valid());
327
328 // Coalesce at end of full root.
329 // [50;250]
330 map.insert(260, 270, 1);
331 map.insert(280, 290, 1);
332 map.insert(300, 310, 1);
333 // [50;250] [260;270] [280;290] [300;310]
334 map.insert(311, 320, 1);
335 I = map.begin();
336 ASSERT_TRUE(I.valid());
337 EXPECT_EQ(50u, I.start());
338 EXPECT_EQ(250u, I.stop());
339 ++I;
340 ASSERT_TRUE(I.valid());
341 EXPECT_EQ(260u, I.start());
342 EXPECT_EQ(270u, I.stop());
343 ++I;
344 ASSERT_TRUE(I.valid());
345 EXPECT_EQ(280u, I.start());
346 EXPECT_EQ(290u, I.stop());
347 ++I;
348 ASSERT_TRUE(I.valid());
349 EXPECT_EQ(300u, I.start());
350 EXPECT_EQ(320u, I.stop());
351 ++I;
352 EXPECT_FALSE(I.valid());
353
354266 // Test clear() on non-branched map.
355267 map.clear();
356268 EXPECT_TRUE(map.empty());