LLVM: include/llvm/ADT/IntervalTree.h Source File (original) (raw)

198template <typename PointT, typename ValueT> class IntervalData {

199protected:

202

203private:

207

208public:

211 : Left(Left), Right(Right), Value(Value) {

212 assert(Left <= Right && "'Left' must be less or equal to 'Right'");

213 }

218

219

220

222

223

224

226

227

228

230 return left(Point) && right(Point);

231 }

232};

249 "PointT must be a fundamental type");

251 "ValueT must be a fundamental or pointer type");

252

253public:

258

261

262private:

265

266 class IntervalNode {

267 PointType MiddlePoint;

268 IntervalNode *Left = nullptr;

269 IntervalNode *Right = nullptr;

270 unsigned BucketIntervalsStart = 0;

271 unsigned BucketIntervalsSize = 0;

272

273 public:

274 PointType middle() const { return MiddlePoint; }

275 unsigned start() const { return BucketIntervalsStart; }

276 unsigned size() const { return BucketIntervalsSize; }

277

278 IntervalNode(PointType Point, unsigned Start)

279 : MiddlePoint(Point), BucketIntervalsStart(Start) {}

280

282 };

283

284 Allocator &NodeAllocator;

285 IntervalNode *Root = nullptr;

286 IntervalVector Intervals;

287

288 PointsVector EndPoints;

289

290

291

292

293

294

295

296

297

298 IntervalReferences IntervalsLeft;

299 IntervalReferences IntervalsRight;

300

301

302

304

305

306 void deleteTree(IntervalNode *Node) {

308 deleteTree(Node->Left);

309 deleteTree(Node->Right);

310 Node->~IntervalNode();

311 NodeAllocator.Deallocate(Node);

312 }

313 }

314

315

316 static void printList(raw_ostream &OS, IntervalReferences &IntervalSet,

317 unsigned Start, unsigned Size, bool HexFormat = true) {

318 assert(Start + Size <= IntervalSet.size() &&

319 "Start + Size must be in bounds of the IntervalSet");

320 const char *Format = HexFormat ? "[0x%08x,0x%08x] " : "[%2d,%2d] ";

322 for (unsigned Position = Start; Position < Start + Size; ++Position)

323 OS << format(Format, IntervalSet[Position]->left(),

324 IntervalSet[Position]->right());

325 } else {

326 OS << "[]";

327 }

328 OS << "\n";

329 }

330

331

332 void printNode(raw_ostream &OS, unsigned Level, IntervalNode *Node,

333 bool HexFormat = true) {

334 const char *Format = HexFormat ? "MP:0x%08x " : "MP:%2d ";

336 OS << format("%5d: ", Level);

337 OS.indent(Level * 2);

339 printList(OS, IntervalSet, Node->start(), Node->size(), HexFormat);

340 };

341

342 PrintNodeData("IR", IntervalsRight);

343 PrintNodeData("IL", IntervalsLeft);

344 }

345

346

347 void printTree(raw_ostream &OS, unsigned Level, IntervalNode *Node,

348 bool HexFormat = true) {

349 if (Node) {

350 printNode(OS, Level, Node, HexFormat);

352 printTree(OS, Level, Node->Left, HexFormat);

353 printTree(OS, Level, Node->Right, HexFormat);

354 }

355 }

356

357

358

359

360

361

362

363

364 IntervalNode *createTree(unsigned &IntervalsSize, int PointsBeginIndex,

365 int PointsEndIndex, int ReferencesBeginIndex,

366 int ReferencesSize) {

367

368

369

370

371

372

373

374

375

376

377 if (PointsBeginIndex > PointsEndIndex ||

378 ReferencesBeginIndex >= ReferencesSize)

379 return nullptr;

380

381 int MiddleIndex = (PointsBeginIndex + PointsEndIndex) / 2;

382 PointType MiddlePoint = EndPoints[MiddleIndex];

383

384 unsigned NewBucketStart = IntervalsSize;

385 unsigned NewBucketSize = 0;

386 int ReferencesRightIndex = ReferencesSize;

387

388 IntervalNode *Root =

389 new (NodeAllocator) IntervalNode(MiddlePoint, NewBucketStart);

390

391

392

393

394 for (int Index = ReferencesBeginIndex; Index < ReferencesRightIndex;) {

395

396

397 if (References[Index]->contains(MiddlePoint)) {

398 IntervalsLeft[IntervalsSize] = References[Index];

399 IntervalsRight[IntervalsSize] = References[Index];

400 ++IntervalsSize;

401 Root->BucketIntervalsSize = ++NewBucketSize;

402

403 if (Index < --ReferencesRightIndex)

404 std::swap(References[Index], References[ReferencesRightIndex]);

405 if (ReferencesRightIndex < --ReferencesSize)

406 std::swap(References[ReferencesRightIndex],

407 References[ReferencesSize]);

408 continue;

409 }

410

411 if (References[Index]->left() > MiddlePoint) {

412 if (Index < --ReferencesRightIndex)

413 std::swap(References[Index], References[ReferencesRightIndex]);

414 continue;

415 }

417 }

418

419

420 if (NewBucketSize > 1) {

421

422 std::stable_sort(IntervalsLeft.begin() + NewBucketStart,

423 IntervalsLeft.begin() + NewBucketStart + NewBucketSize,

425 return LHS->left() < RHS->left();

426 });

427

428 std::stable_sort(IntervalsRight.begin() + NewBucketStart,

429 IntervalsRight.begin() + NewBucketStart + NewBucketSize,

431 return LHS->right() > RHS->right();

432 });

433 }

434

435 if (PointsBeginIndex <= MiddleIndex - 1) {

436 Root->Left = createTree(IntervalsSize, PointsBeginIndex, MiddleIndex - 1,

437 ReferencesBeginIndex, ReferencesRightIndex);

438 }

439

440 if (MiddleIndex + 1 <= PointsEndIndex) {

441 Root->Right = createTree(IntervalsSize, MiddleIndex + 1, PointsEndIndex,

442 ReferencesRightIndex, ReferencesSize);

443 }

444

445 return Root;

446 }

447

448public:

449 class find_iterator {

450 public:

456

457 private:

460

461

462

463 IntervalNode *Node = nullptr;

465 unsigned Index = 0;

466

467

468

469

470 void initNode() {

471 Index = 0;

472 while (Node) {

473

474

475 if (Point == Node->middle()) {

476 if (Node->size() == 0) {

477

478 Node = nullptr;

479 }

480 return;

481 }

482

483 if (Point < Node->middle()) {

484

485

486

487 if (Node->size() && (*AscendingBuckets)[Node->start()]->left(Point)) {

488 return;

489 }

490 Node = Node->Left;

491 } else {

492 if (Node->size() &&

493 (*DescendingBuckets)[Node->start()]->right(Point)) {

494 return;

495 }

496 Node = Node->Right;

497 }

498 }

499 }

500

501

502

503

504

505 void nextInterval() {

506

507

508

509 if (++Index < Node->size()) {

510 if (Node->middle() == Point)

511 return;

512 if (Point < Node->middle()) {

513

514 if (!(*AscendingBuckets)[Node->start() + Index]->left(Point)) {

515

516

517 Node = Node->Left;

518 initNode();

519 }

520 } else {

521

522 if (!(*DescendingBuckets)[Node->start() + Index]->right(Point)) {

523

524

525 Node = Node->Right;

526 initNode();

527 }

528 }

529 } else {

530

531 if (Point == Node->middle()) {

532 Node = nullptr;

533 Index = 0;

534 return;

535 }

536

537 Node = Point < Node->middle() ? Node->Left : Node->Right;

538 initNode();

539 }

540 }

541

542 find_iterator() = default;

546 : AscendingBuckets(Left), DescendingBuckets(Right), Node(Node),

547 Point(Point), Index(0) {

548 initNode();

549 }

550

551 const DataType *current() const {

552 return (Point <= Node->middle())

553 ? (*AscendingBuckets)[Node->start() + Index]

554 : (*DescendingBuckets)[Node->start() + Index];

555 }

556

557 public:

559 nextInterval();

560 return *this;

561 }

562

564 find_iterator Iter(*this);

565 nextInterval();

566 return Iter;

567 }

568

569

572

573

582

584 };

585

586private:

588

589public:

591 : NodeAllocator(NodeAllocator) {}

593

594

595 bool empty() const { return Root == nullptr; }

596

597

599 deleteTree(Root);

600 Root = nullptr;

601 Intervals.clear();

602 IntervalsLeft.clear();

603 IntervalsRight.clear();

604 EndPoints.clear();

605 }

606

607

609 assert(empty() && "Invalid insertion. Interval tree already constructed.");

611 }

612

613

614

616 assert(empty() && "Interval tree it is not constructed.");

618 for (find_iterator Iter = find(Point), E = find_end(); Iter != E; ++Iter)

620 return IntervalSet;

621 }

622

623

624

625

627 std::stable_sort(IntervalSet.begin(), IntervalSet.end(),

629 return Sort == Sorting::Ascending

630 ? (LHS->right() - LHS->left()) >

631 (RHS->right() - RHS->left())

632 : (LHS->right() - LHS->left()) <

633 (RHS->right() - RHS->left());

634 });

635 }

636

637

638

639

641 printTree(OS, 0, Root, HexFormat);

642 }

643

644

646 assert(empty() && "Interval tree already constructed.");

647

648

653 References.push_back(std::addressof(Data));

654 }

655 std::stable_sort(Points.begin(), Points.end());

658

659 EndPoints.assign(Points.begin(), Points.end());

660

661 IntervalsLeft.resize(Intervals.size());

662 IntervalsRight.resize(Intervals.size());

663

664

665

666

667 unsigned IntervalsSize = 0;

668 Root =

669 createTree(IntervalsSize, 0, EndPoints.size() - 1,

670 0, References.size());

671

672

673 References.clear();

674 }

675

676

677

678

682 : find_iterator(&IntervalsLeft, &IntervalsRight, Root, Point);

683 }

684

685

686 find_iterator find_end() const { return End; }

687};