/
NumericRange.ts
88 lines (71 loc) · 2.23 KB
/
NumericRange.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*!
* Copyright 2021 Cognite AS
*/
export class NumericRange {
readonly from: number;
readonly count: number;
readonly toInclusive: number;
constructor(from: number, count: number) {
if (count < 0) {
throw new Error('Range cannot have negative number of elements');
}
this.from = from;
this.count = count;
this.toInclusive = from + count - 1;
}
static createFromInterval(from: number, toInclusive: number): NumericRange {
return new NumericRange(from, toInclusive - from + 1);
}
*values(): Generator<number> {
for (let i = this.from; i <= this.toInclusive; ++i) {
yield i;
}
}
toArray(): number[] {
return Array.from(this.values());
}
equal(other: NumericRange): boolean {
return this.from === other.from && this.count === other.count;
}
contains(value: number): boolean {
return value >= this.from && value <= this.toInclusive;
}
intersects(range: NumericRange): boolean {
return this.from <= range.toInclusive && this.toInclusive >= range.from;
}
intersectsOrCoinciding(range: NumericRange): boolean {
return this.from <= range.toInclusive + 1 && this.toInclusive + 1 >= range.from;
}
intersectionWith(range: NumericRange): NumericRange | undefined {
if (!this.intersects(range)) {
return undefined;
} else {
return NumericRange.createFromInterval(
Math.max(this.from, range.from),
Math.min(this.toInclusive, range.toInclusive)
);
}
}
isInside(range: NumericRange): boolean {
return this.from >= range.from && this.toInclusive <= range.toInclusive;
}
union(range: NumericRange): NumericRange {
return NumericRange.createFromInterval(
Math.min(this.from, range.from),
Math.max(this.toInclusive, range.toInclusive)
);
}
forEach(action: (value: number) => void): void {
for (let i = this.from; i <= this.toInclusive; ++i) {
action(i);
}
}
toString(): string {
return '(' + this.from + ', ' + this.toInclusive + ')';
}
static isNumericRange(value: any): value is NumericRange {
if (!value) return false;
const range = value as NumericRange;
return range.from !== undefined && range.count !== undefined && range.toInclusive !== undefined;
}
}