Skip to content

Commit

Permalink
add a IntervalHashSet
Browse files Browse the repository at this point in the history
  • Loading branch information
hexsprite committed Jan 19, 2024
1 parent f80c538 commit 39e5c3a
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 23 deletions.
11 changes: 9 additions & 2 deletions src/IntervalSet.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { SortedSet } from '@rimbu/core'
import { HashSet, Hasher, SortedSet } from '@rimbu/core'
import { Interval } from './Interval'

/**
* A HashSet of Intervals.
*/
export const IntervalHashSet = HashSet.createContext<Interval>({
hasher: Hasher.anyDeepHasher(), // deep so it should also hash the data part
})

export const compareIntervals = (a: Interval, b: Interval) => {
return (
a.start - b.start ||
Expand All @@ -12,7 +19,7 @@ export const compareIntervals = (a: Interval, b: Interval) => {
/**
* A SortedSet of Intervals.
*/
export const IntervalSet = SortedSet.createContext<Interval>({
export const IntervalSortedSet = SortedSet.createContext<Interval>({
comp: {
compare: compareIntervals,
isComparable(obj): obj is Interval {
Expand Down
17 changes: 9 additions & 8 deletions src/IntervalTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import { debug } from './debug'
import { Node } from './Node'
import { Interval } from './Interval'
import { SortedMap, HashSet } from '@rimbu/core'
import { IntervalSet } from './IntervalSet'
import { IntervalSortedSet } from './IntervalSet'
import { IntervalTuples } from './types'
import { IntervalHashSet } from './IntervalSet'

export class IntervalTree {
public allIntervals: HashSet<Interval>
Expand Down Expand Up @@ -88,7 +89,7 @@ export class IntervalTree {
*/
public chop(start: number, end: number): void {
assert(start < end, 'start must be <= end')
const insertionsBuilder = HashSet.builder<Interval>()
const insertionsBuilder = IntervalHashSet.builder<Interval>()
const startHits = this.search(start).filter((iv) => iv.start < start)
const endHits = this.search(end).filter((iv) => iv.end > end)
startHits.forEach((iv) => {
Expand All @@ -115,7 +116,7 @@ export class IntervalTree {

chopAll(intervals: [number, number][]) {
intervals.forEach(([start, end]) => {
const insertionsBuilder = HashSet.builder<Interval>()
const insertionsBuilder = IntervalHashSet.builder<Interval>()
const startHits = this.search(start).filter((iv) => iv.start < start)
const endHits = this.search(end).filter((iv) => iv.end > end)
startHits.forEach((iv) => {
Expand Down Expand Up @@ -217,7 +218,7 @@ badInterval=${iv}
}

public toString() {
const sortedIntervals = IntervalSet.from(this.allIntervals)
const sortedIntervals = IntervalSortedSet.from(this.allIntervals)
return `IntervalTree([ ${sortedIntervals.toArray().join(', ')} ])`
}

Expand All @@ -236,7 +237,7 @@ badInterval=${iv}
merged.push(higher)
}

const sortedIntervals = IntervalSet.from(this.allIntervals)
const sortedIntervals = IntervalSortedSet.from(this.allIntervals)
sortedIntervals.forEach((higher) => {
if (!merged.length) {
newSeries(higher)
Expand Down Expand Up @@ -277,9 +278,9 @@ badInterval=${iv}
strict = false
): HashSet<Interval> {
if (!this.topNode) {
return HashSet.empty()
return IntervalHashSet.empty()
}
const resultBuilder = HashSet.builder<Interval>()
const resultBuilder = IntervalHashSet.builder<Interval>()
if (end === undefined) {
return this.topNode.searchPoint(start, resultBuilder).build()
}
Expand Down Expand Up @@ -402,7 +403,7 @@ badInterval=${iv}
}

private initialize(intervals: Interval[] = []) {
this.allIntervals = HashSet.from(intervals)
this.allIntervals = IntervalHashSet.from(intervals)
this.topNode = Node.fromIntervals(intervals)!
this.boundaryTable = SortedMap.empty()
this.addBoundariesAll(intervals)
Expand Down
24 changes: 11 additions & 13 deletions src/Node.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import assert from 'assert'

import { Interval } from './Interval'
import { compareIntervals } from './IntervalSet'
import { IntervalHashSet, compareIntervals } from './IntervalSet'
import { HashSet } from '@rimbu/core'
import { debug } from './debug'

Expand All @@ -23,7 +23,9 @@ export class Node {
balance = 0
) {
this.xCenter = xCenter
this.sCenter = Array.isArray(sCenter) ? HashSet.from(sCenter) : sCenter
this.sCenter = Array.isArray(sCenter)
? IntervalHashSet.from(sCenter)
: sCenter
this.leftNode = leftNode ?? null
this.rightNode = rightNode ?? null
// depth & balance are set when rotated
Expand Down Expand Up @@ -246,15 +248,11 @@ export class Node {

public searchPoint(point: number, resultBuilder: HashSet.Builder<Interval>) {
// Returns all intervals that contain point.
// debug('searchPoint: point=', point, this.toString())
// debug('searchPoint: result=', resultBuilder.toString())
this.sCenter.forEach((interval) => {
// debug('searchPoint: interval=', interval)
if (interval.start <= point && point < interval.end) {
// debug('searchPoint interval', interval)
resultBuilder.add(interval)
}
})
resultBuilder.addAll(
this.sCenter.filter(
(interval) => interval.start <= point && point < interval.end
)
)
if (point < this.xCenter && this.getBranch(0)) {
this.getBranch(0).searchPoint(point, resultBuilder)
} else if (point > this.xCenter && this.getBranch(1)) {
Expand All @@ -264,7 +262,7 @@ export class Node {
}

public searchOverlap(pointList: number[]): HashSet<Interval> {
const resultBuilder = HashSet.builder<Interval>()
const resultBuilder = IntervalHashSet.builder<Interval>()
for (const point of pointList) {
this.searchPoint(point, resultBuilder)
}
Expand Down Expand Up @@ -515,7 +513,7 @@ export class Node {
}

public allChildren(): HashSet<Interval> {
return this.allChildrenHelper(HashSet.empty())
return this.allChildrenHelper(IntervalHashSet.empty())
}

private allChildrenHelper(result: HashSet<Interval>): HashSet<Interval> {
Expand Down

0 comments on commit 39e5c3a

Please sign in to comment.