• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { SparseBitVector } from '../../utils/SparseBitVector';
17
18type Idx = number;
19export interface IPtsCollection<T extends Idx> {
20    contains(elem: T): boolean;
21    insert(elem: T): boolean;
22    remove(elem: T): boolean;
23    clone(): this;
24    union(other: this): boolean;
25    subtract(other: this): boolean;
26    clear(): void;
27    count(): number;
28    isEmpty(): boolean;
29    superset(other: this): boolean;
30    intersect(other: this): boolean;
31    getProtoPtsSet(): any;
32    [Symbol.iterator](): IterableIterator<T>;
33}
34
35/*
36 * Return PtsSet or PtsBV 's constructor by input type
37 */
38export function createPtsCollectionCtor<T extends Idx>(type: PtsCollectionType): new () => IPtsCollection<T> {
39    if (type === PtsCollectionType.Set) {
40        return PtsSet<T>;
41    } else if (type === PtsCollectionType.BitVector) {
42        return PtsBV<T>;
43    }
44    throw new Error(`Unsupported pts collection type: ${type}`);
45}
46
47/*
48 * A simple set to store pts data
49 */
50export class PtsSet<T extends Idx> implements IPtsCollection<T> {
51    pts: Set<T>;
52
53    constructor() {
54        this.pts = new Set();
55    }
56
57    contains(elem: T): boolean {
58        return this.pts.has(elem);
59    }
60
61    insert(elem: T): boolean {
62        if (this.pts.has(elem)) {
63            return false;
64        }
65        this.pts.add(elem);
66        return true;
67    }
68
69    remove(elem: T): boolean {
70        if (!this.pts.has(elem)) {
71            return false;
72        }
73        this.pts.delete(elem);
74        return true;
75    }
76
77    clone(): this {
78        let clonedSet = new PtsSet<T>();
79        clonedSet.pts = new Set<T>(this.pts);
80        // TODO: need validate
81        return clonedSet as this;
82    }
83
84    union(other: this): boolean {
85        let changed = false;
86        for (const elem of other.pts) {
87            changed = this.insert(elem) || changed;
88        }
89        return changed;
90    }
91
92    subtract(other: this): boolean {
93        let changed = false;
94        for (const elem of other.pts) {
95            changed = this.remove(elem) || changed;
96        }
97
98        return changed;
99    }
100
101    clear(): void {
102        this.pts.clear();
103    }
104
105    count(): number {
106        return this.pts.size;
107    }
108
109    isEmpty(): boolean {
110        return this.pts.size === 0;
111    }
112
113    // If current collection is a super set of other
114    superset(other: this): boolean {
115        for (const elem of other.pts) {
116            if (!this.pts.has(elem)) {
117                return false;
118            }
119        }
120        return true;
121    }
122
123    // If current collection is intersect with other
124    intersect(other: this): boolean {
125        for (const elem of other.pts) {
126            if (this.pts.has(elem)) {
127                return true;
128            }
129        }
130        return false;
131    }
132
133    getProtoPtsSet(): Set<T> {
134        return this.pts;
135    }
136
137    [Symbol.iterator](): IterableIterator<T> {
138        return this.pts[Symbol.iterator]();
139    }
140}
141
142export class PtsBV<T extends Idx> implements IPtsCollection<T> {
143    pts: SparseBitVector;
144
145    constructor() {
146        this.pts = new SparseBitVector();
147    }
148
149    contains(elem: T): boolean {
150        return this.pts.test(elem);
151    }
152
153    insert(elem: T): boolean {
154        this.pts.set(elem);
155        return true;
156    }
157
158    remove(elem: T): boolean {
159        this.pts.reset(elem);
160        return true;
161    }
162
163    clone(): this {
164        let cloned = new PtsBV<T>();
165        cloned.pts = this.pts.clone();
166        return cloned as this;
167    }
168
169    union(other: this): boolean {
170        return this.pts.unionWith(other.pts);
171    }
172
173    subtract(other: this): boolean {
174        return this.pts.subtractWith(other.pts);
175    }
176
177    clear(): void {
178        this.pts.clear();
179    }
180
181    count(): number {
182        return this.pts.count();
183    }
184
185    isEmpty(): boolean {
186        return this.pts.isEmpty();
187    }
188
189    // If current collection is a super set of other
190    superset(other: this): boolean {
191        for (const elem of other.pts) {
192            if (!this.pts.test(elem)) {
193                return false;
194            }
195        }
196        return true;
197    }
198
199    // If current collection is intersect with other
200    intersect(other: this): boolean {
201        for (const elem of other.pts) {
202            if (this.pts.test(elem)) {
203                return true;
204            }
205        }
206        return false;
207    }
208
209    getProtoPtsSet(): SparseBitVector {
210        return this.pts;
211    }
212
213    [Symbol.iterator](): IterableIterator<T> {
214        return this.pts[Symbol.iterator]() as IterableIterator<T>;
215    }
216}
217
218export enum PtsCollectionType {
219    Set,
220    BitVector,
221}
222export class DiffPTData<K, D extends Idx, DS extends IPtsCollection<D>> {
223    private diffPtsMap: Map<K, DS>;
224    private propaPtsMap: Map<K, DS>;
225
226    constructor(private DSCreator: new () => DS) {
227        this.diffPtsMap = new Map();
228        this.propaPtsMap = new Map();
229    }
230
231    clear(): void {
232        this.diffPtsMap.clear();
233        this.propaPtsMap.clear();
234    }
235
236    addPts(v: K, elem: D): boolean {
237        let propa = this.propaPtsMap.get(v);
238        if (propa && propa.contains(elem)) {
239            return false;
240        }
241        let diff = this.diffPtsMap.get(v) || new this.DSCreator();
242        this.diffPtsMap.set(v, diff);
243        return diff.insert(elem);
244    }
245
246    resetElem(v: K): boolean {
247        let propa = this.propaPtsMap.get(v);
248        if (propa) {
249            this.diffPtsMap.set(v, propa.clone());
250            return true;
251        }
252        return false;
253    }
254
255    unionDiffPts(dstv: K, srcv: K): boolean {
256        if (dstv === srcv) {
257            return false;
258        }
259        let changed = false;
260        let diff = this.diffPtsMap.get(srcv);
261        if (diff) {
262            let srcDs = diff.clone();
263            changed = this.unionPtsTo(dstv, srcDs);
264        }
265        return changed;
266    }
267
268    unionPts(dstv: K, srcv: K): boolean {
269        if (dstv === srcv) {
270            return false;
271        }
272        let changed = false;
273        let diff = this.diffPtsMap.get(srcv);
274        if (diff) {
275            let srcDs = diff.clone();
276            changed = this.unionPtsTo(dstv, srcDs);
277        }
278        let propa = this.propaPtsMap.get(srcv);
279        if (propa) {
280            let srcDs = propa.clone();
281            changed = this.unionPtsTo(dstv, srcDs) || changed;
282        }
283        return changed;
284    }
285
286    unionPtsTo(dstv: K, srcDs: DS): boolean {
287        let diff = this.diffPtsMap.get(dstv) || new this.DSCreator();
288        let propa = this.propaPtsMap.get(dstv) || new this.DSCreator();
289        let newSet = srcDs.clone();
290        newSet.subtract(propa);
291        let changed = diff.union(newSet);
292        this.diffPtsMap.set(dstv, diff);
293        return changed;
294    }
295
296    removePtsElem(v: K, elem: D): boolean {
297        let removedFromDiff = this.diffPtsMap.get(v)?.remove(elem) ?? false;
298        let removedFromPropa = this.propaPtsMap.get(v)?.remove(elem) ?? false;
299        return removedFromDiff || removedFromPropa;
300    }
301
302    getDiffPts(v: K): DS | undefined {
303        return this.diffPtsMap.get(v);
304    }
305
306    getMutDiffPts(v: K): DS | undefined {
307        if (!this.diffPtsMap.has(v)) {
308            this.diffPtsMap.set(v, new this.DSCreator());
309        }
310        return this.diffPtsMap.get(v);
311    }
312
313    getPropaPts(v: K): DS | undefined {
314        return this.propaPtsMap.get(v);
315    }
316
317    getAllPropaPts(): Map<K, DS> {
318        return this.propaPtsMap;
319    }
320
321    getPropaPtsMut(v: K): DS {
322        if (!this.propaPtsMap.has(v)) {
323            this.propaPtsMap.set(v, new this.DSCreator());
324        }
325        return this.propaPtsMap.get(v)!;
326    }
327
328    flush(v: K): void {
329        if (!this.diffPtsMap.has(v)) {
330            return;
331        }
332        let diff = this.diffPtsMap.get(v)!;
333        let propa = this.getPropaPtsMut(v);
334        // do not clear origin propa, only copy the pt and add it to diff
335        propa.union(diff);
336        diff.clear();
337    }
338
339    clearPts(v: K): void {
340        let diff = this.diffPtsMap.get(v);
341        if (diff) {
342            diff.clear();
343        }
344        let propa = this.propaPtsMap.get(v);
345        if (propa) {
346            propa.clear();
347        }
348    }
349
350    clearDiffPts(v: K): void {
351        let diff = this.diffPtsMap.get(v);
352        if (diff) {
353            diff.clear();
354        }
355    }
356
357    clearPropaPts(v: K): void {
358        let propa = this.propaPtsMap.get(v);
359        if (propa) {
360            propa.clear();
361        }
362    }
363
364    calculateDiff(src: K, dst: K): DS {
365        let srcDiff = this.diffPtsMap.get(src)!;
366        let dstPropa = this.propaPtsMap.get(dst);
367        if (!dstPropa) {
368            return srcDiff.clone();
369        }
370
371        let result = srcDiff.clone();
372
373        result.subtract(dstPropa);
374        return result;
375    }
376}
377