Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
Molstar
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Michal Malý
Molstar
Commits
fbd7c35f
Commit
fbd7c35f
authored
7 years ago
by
David Sehnal
Browse files
Options
Downloads
Patches
Plain Diff
collections refactoring
parent
2f78edea
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/structure/collections/multi-set.ts
+164
-139
164 additions, 139 deletions
src/structure/collections/multi-set.ts
src/structure/collections/ordered-set.ts
+8
-10
8 additions, 10 deletions
src/structure/collections/ordered-set.ts
with
172 additions
and
149 deletions
src/structure/collections/multi-set.ts
+
164
−
139
View file @
fbd7c35f
...
...
@@ -11,177 +11,204 @@ import { sortArray } from './sort'
import
{
hash1
}
from
'
./hash-functions
'
/** A map-like representation of integer set */
interface
MultiSet
{
/*
'@type': 'int-multi-set'
*/
}
interface
MultiSet
{
'
@type
'
:
'
int-multi-set
'
}
namespace
MultiSet
{
export
const
Empty
:
MultiSet
=
{
offsets
:
[
0
],
hashCode
:
0
,
keys
:
OrderedSet
.
Empty
}
as
MultiSetElements
as
any
;
export
function
create
(
data
:
IntTuple
|
ArrayLike
<
IntTuple
>
|
IntTuple
|
{
[
id
:
number
]:
OrderedSet
}):
MultiSet
{
if
(
typeof
data
===
'
number
'
)
return
data
;
if
(
IntTuple
.
is
(
data
))
return
IntTuple
.
pack1
(
data
)
as
number
;
if
(
isArrayLike
(
data
))
return
ofTuples
(
data
);
return
ofObject
(
data
as
{
[
id
:
number
]:
OrderedSet
});
}
if
(
IntTuple
.
is
(
data
))
return
IntTuple
.
pack1
(
data
)
as
any
;
if
(
isArrayLike
(
data
))
return
ofTuples
(
data
)
as
any
;
return
ofObject
(
data
as
{
[
id
:
number
]:
OrderedSet
})
as
any
;
}
export
const
keys
:
(
set
:
MultiSet
)
=>
OrderedSet
=
keysI
as
any
;
export
const
keyCount
:
(
set
:
MultiSet
)
=>
number
=
keyCountI
as
any
;
export
const
hasKey
:
(
set
:
MultiSet
,
key
:
number
)
=>
boolean
=
hasKeyI
as
any
;
export
const
geyKey
:
(
set
:
MultiSet
,
i
:
number
)
=>
number
=
getKeyI
as
any
;
export
const
getByKey
:
(
set
:
MultiSet
,
key
:
number
)
=>
OrderedSet
=
getByKeyI
as
any
;
export
const
getByIndex
:
(
set
:
MultiSet
,
i
:
number
)
=>
OrderedSet
=
getByIndexI
as
any
;
export
const
has
:
(
set
:
MultiSet
,
x
:
IntTuple
)
=>
boolean
=
hasI
as
any
;
export
const
indexOf
:
(
set
:
MultiSet
,
x
:
IntTuple
)
=>
number
=
indexOfI
as
any
;
export
const
getAt
:
(
set
:
MultiSet
,
i
:
number
)
=>
IntTuple
=
getAtI
as
any
;
export
const
values
:
(
set
:
MultiSet
)
=>
Iterator
<
IntTuple
.
Unpacked
>
=
valuesI
as
any
;
export
const
size
:
(
set
:
MultiSet
)
=>
number
=
sizeI
as
any
;
export
const
hashCode
:
(
set
:
MultiSet
)
=>
number
=
hashCodeI
as
any
;
export
const
areEqual
:
(
a
:
MultiSet
,
b
:
MultiSet
)
=>
boolean
=
areEqualI
as
any
;
export
const
areIntersecting
:
(
a
:
MultiSet
,
b
:
MultiSet
)
=>
boolean
=
areIntersectingI
as
any
;
export
const
union
:
(
a
:
MultiSet
,
b
:
MultiSet
)
=>
MultiSet
=
unionI
as
any
;
export
const
unionMany
:
(
sets
:
MultiSet
[])
=>
MultiSet
=
unionManyI
as
any
;
export
const
intersect
:
(
a
:
MultiSet
,
b
:
MultiSet
)
=>
MultiSet
=
intersectI
as
any
;
export
const
subtract
:
(
a
:
MultiSet
,
b
:
MultiSet
)
=>
MultiSet
=
subtractI
as
any
;
}
export
function
keys
(
set
:
MultiSet
):
OrderedSet
{
if
(
typeof
set
===
'
number
'
)
return
OrderedSet
.
ofSingleton
(
set
);
return
(
set
as
MultiSetElements
).
keys
;
}
export
default
MultiSet
export
function
keyCount
(
set
:
MultiSet
):
number
{
if
(
typeof
set
===
'
number
'
)
return
1
;
return
OrderedSet
.
size
((
set
as
MultiSetElements
).
keys
);
}
/** Long and painful implementation starts here */
export
function
hasKey
(
set
:
MultiSet
,
key
:
number
):
boolean
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
fst
(
set
)
===
key
;
return
OrderedSet
.
has
((
set
as
MultiSetElements
).
keys
,
key
);
}
interface
MultiSetElements
{
[
id
:
number
]:
OrderedSet
,
offsets
:
number
[],
hashCode
:
number
,
keys
:
OrderedSet
}
type
MultiSetImpl
=
IntTuple
|
MultiSetElements
export
function
getKey
(
set
:
MultiSet
,
index
:
number
):
number
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
fst
(
set
);
return
OrderedSet
.
getAt
(
(
set
as
MultiSetElements
).
keys
,
index
)
;
}
function
keysI
(
set
:
MultiSet
Impl
):
OrderedSet
{
if
(
typeof
set
===
'
number
'
)
return
OrderedSet
.
ofSingleton
(
set
);
return
(
set
as
MultiSetElements
).
keys
;
}
export
function
has
(
set
:
MultiSet
,
t
:
IntTuple
):
boolean
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
areEqual
(
t
,
set
);
IntTuple
.
unpack
(
t
,
_hasP
);
return
OrderedSet
.
has
((
set
as
MultiSetElements
).
keys
,
_hasP
.
fst
)
?
OrderedSet
.
has
((
set
as
MultiSetElements
)[
_hasP
.
fst
],
_hasP
.
snd
)
:
false
;
}
const
_hasP
=
IntTuple
.
zero
();
function
keyCountI
(
set
:
MultiSetImpl
):
number
{
if
(
typeof
set
===
'
number
'
)
return
1
;
return
OrderedSet
.
size
((
set
as
MultiSetElements
).
keys
);
}
export
function
getByKey
(
set
:
MultiSet
,
key
:
number
):
OrderedSet
{
if
(
typeof
set
===
'
number
'
)
{
IntTuple
.
unpack
(
set
,
_gS
);
return
_gS
.
fst
===
key
?
OrderedSet
.
ofSingleton
(
_gS
.
snd
)
:
OrderedSet
.
Empty
;
}
return
OrderedSet
.
has
((
set
as
MultiSetElements
).
keys
,
key
)
?
(
set
as
MultiSetElements
)[
key
]
:
OrderedSet
.
Empty
;
}
const
_gS
=
IntTuple
.
zero
();
function
hasKeyI
(
set
:
MultiSetImpl
,
key
:
number
):
boolean
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
fst
(
set
)
===
key
;
return
OrderedSet
.
has
((
set
as
MultiSetElements
).
keys
,
key
);
}
export
function
getByIndex
(
set
:
MultiSet
,
index
:
number
):
OrderedSet
{
if
(
typeof
set
===
'
number
'
)
return
index
===
0
?
OrderedSet
.
ofSingleton
(
IntTuple
.
snd
(
set
))
:
OrderedSet
.
Empty
;
const
key
=
OrderedSet
.
getAt
((
set
as
MultiSetElements
).
keys
,
index
);
return
(
set
as
MultiSetElements
)[
key
]
||
OrderedSet
.
Empty
;
}
function
getKeyI
(
set
:
MultiSetImpl
,
index
:
number
):
number
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
fst
(
set
);
return
OrderedSet
.
getAt
((
set
as
MultiSetElements
).
keys
,
index
);
}
export
function
getAt
(
set
:
MultiSet
,
i
:
number
):
IntTuple
{
if
(
typeof
set
===
'
number
'
)
return
set
;
return
getAtE
(
set
as
MultiSetElements
,
i
);
}
function
hasI
(
set
:
MultiSetImpl
,
t
:
IntTuple
):
boolean
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
areEqual
(
t
,
set
);
IntTuple
.
unpack
(
t
,
_hasP
);
return
OrderedSet
.
has
((
set
as
MultiSetElements
).
keys
,
_hasP
.
fst
)
?
OrderedSet
.
has
((
set
as
MultiSetElements
)[
_hasP
.
fst
],
_hasP
.
snd
)
:
false
;
}
const
_hasP
=
IntTuple
.
zero
();
export
function
indexOf
(
set
:
MultiSet
,
t
:
IntTuple
)
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
areEqual
(
set
,
t
)
?
0
:
-
1
;
return
indexOfE
(
set
as
MultiSetElements
,
t
);
function
getByKeyI
(
set
:
MultiSetImpl
,
key
:
number
):
OrderedSet
{
if
(
typeof
set
===
'
number
'
)
{
IntTuple
.
unpack
(
set
,
_gS
);
return
_gS
.
fst
===
key
?
OrderedSet
.
ofSingleton
(
_gS
.
snd
)
:
OrderedSet
.
Empty
;
}
return
OrderedSet
.
has
((
set
as
MultiSetElements
).
keys
,
key
)
?
(
set
as
MultiSetElements
)[
key
]
:
OrderedSet
.
Empty
;
}
const
_gS
=
IntTuple
.
zero
();
/** Number elements in the "child" sets */
export
function
size
(
set
:
MultiSet
)
{
if
(
typeof
set
===
'
number
'
)
return
1
;
return
(
set
as
MultiSetElements
)
.
offsets
[(
set
as
MultiSetElements
).
offsets
.
length
-
1
]
;
}
function
getByIndexI
(
set
:
MultiSetImpl
,
index
:
number
):
OrderedSet
{
if
(
typeof
set
===
'
number
'
)
return
index
===
0
?
OrderedSet
.
ofSingleton
(
IntTuple
.
snd
(
set
))
:
OrderedSet
.
Empty
;
const
key
=
OrderedSet
.
getAt
((
set
as
MultiSetElements
).
keys
,
index
)
;
return
(
set
as
MultiSetElements
)
[
key
]
||
OrderedSet
.
Empty
;
}
export
function
hashCode
(
set
:
MultiSet
)
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
hashCode
(
set
);
if
((
set
as
MultiSetElements
).
hashCode
!==
-
1
)
return
(
set
as
MultiSetElements
).
hashCode
;
return
computeHash
((
set
as
MultiSetElements
));
}
function
getAtI
(
set
:
MultiSetImpl
,
i
:
number
):
IntTuple
{
if
(
typeof
set
===
'
number
'
)
return
set
;
return
getAtE
(
set
as
MultiSetElements
,
i
);
}
export
function
areEqual
(
a
:
MultiSet
,
b
:
MultiSet
):
boolean
{
if
(
typeof
a
===
'
number
'
)
{
if
(
typeof
b
===
'
number
'
)
return
IntTuple
.
areEqual
(
a
,
b
);
return
false
;
}
if
(
typeof
b
===
'
number
'
)
return
false
;
return
areEqualEE
(
a
as
MultiSetElements
,
b
as
MultiSetElements
);
}
function
indexOfI
(
set
:
MultiSetImpl
,
t
:
IntTuple
)
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
areEqual
(
set
,
t
)
?
0
:
-
1
;
return
indexOfE
(
set
as
MultiSetElements
,
t
);
}
export
function
areIntersecting
(
a
:
MultiSet
,
b
:
MultiSet
):
boolean
{
if
(
typeof
a
===
'
number
'
)
{
if
(
typeof
b
===
'
number
'
)
return
IntTuple
.
areEqual
(
a
,
b
);
return
areIntersectingNE
(
a
,
b
as
MultiSetElements
);
}
if
(
typeof
b
===
'
number
'
)
return
areIntersectingNE
(
b
,
a
as
MultiSetElements
);
return
areIntersectingEE
(
a
as
MultiSetElements
,
b
as
MultiSetElements
);
}
/** Number elements in the "child" sets */
function
sizeI
(
set
:
MultiSetImpl
)
{
if
(
typeof
set
===
'
number
'
)
return
1
;
return
(
set
as
MultiSetElements
).
offsets
[(
set
as
MultiSetElements
).
offsets
.
length
-
1
];
}
export
function
intersect
(
a
:
MultiSet
,
b
:
MultiSet
):
MultiSet
{
if
(
typeof
a
===
'
number
'
)
{
if
(
typeof
b
===
'
number
'
)
return
IntTuple
.
areEqual
(
a
,
b
)
?
a
:
Empty
;
return
intersectNE
(
a
,
b
as
MultiSetElements
);
}
if
(
typeof
b
===
'
number
'
)
return
intersectNE
(
b
,
a
as
MultiSetElements
);
return
intersectEE
(
a
as
MultiSetElements
,
b
as
MultiSetElements
);
function
hashCodeI
(
set
:
MultiSetImpl
)
{
if
(
typeof
set
===
'
number
'
)
return
IntTuple
.
hashCode
(
set
);
if
((
set
as
MultiSetElements
).
hashCode
!==
-
1
)
return
(
set
as
MultiSetElements
).
hashCode
;
return
computeHash
((
set
as
MultiSetElements
));
}
function
areEqualI
(
a
:
MultiSetImpl
,
b
:
MultiSetImpl
)
{
if
(
typeof
a
===
'
number
'
)
{
if
(
typeof
b
===
'
number
'
)
return
IntTuple
.
areEqual
(
a
,
b
);
return
false
;
}
if
(
typeof
b
===
'
number
'
)
return
false
;
return
areEqualEE
(
a
as
MultiSetElements
,
b
as
MultiSetElements
);
}
export
function
subtract
(
a
:
MultiSet
,
b
:
MultiSet
):
MultiSet
{
if
(
typeof
a
===
'
number
'
)
{
if
(
typeof
b
===
'
number
'
)
return
IntTuple
.
areEqual
(
a
,
b
)
?
Empty
:
a
;
return
subtractNE
(
a
,
b
as
MultiSetElements
);
}
if
(
typeof
b
===
'
number
'
)
return
subtractEN
(
a
as
MultiSetElements
,
b
);
return
subtractEE
(
a
as
MultiSetElements
,
b
as
MultiSetElements
);
function
areIntersectingI
(
a
:
MultiSetImpl
,
b
:
MultiSetImpl
)
{
if
(
typeof
a
===
'
number
'
)
{
if
(
typeof
b
===
'
number
'
)
return
IntTuple
.
areEqual
(
a
,
b
);
return
areIntersectingNE
(
a
,
b
as
MultiSetElements
);
}
if
(
typeof
b
===
'
number
'
)
return
areIntersectingNE
(
b
,
a
as
MultiSetElements
);
return
areIntersectingEE
(
a
as
MultiSetElements
,
b
as
MultiSetElements
);
}
export
function
union
(
a
:
MultiSet
,
b
:
MultiSet
):
MultiSet
{
return
findUnion
([
a
,
b
]);
function
intersectI
(
a
:
MultiSetImpl
,
b
:
MultiSetImpl
)
{
if
(
typeof
a
===
'
number
'
)
{
if
(
typeof
b
===
'
number
'
)
return
IntTuple
.
areEqual
(
a
,
b
)
?
a
:
MultiSet
.
Empty
;
return
intersectNE
(
a
,
b
as
MultiSetElements
);
}
if
(
typeof
b
===
'
number
'
)
return
intersectNE
(
b
,
a
as
MultiSetElements
);
return
intersectEE
(
a
as
MultiSetElements
,
b
as
MultiSetElements
);
}
export
function
unionMany
(
sets
:
ArrayLike
<
MultiSet
>
):
MultiSet
{
return
findUnion
(
sets
);
function
subtractI
(
a
:
MultiSetImpl
,
b
:
MultiSetImpl
)
{
if
(
typeof
a
===
'
number
'
)
{
if
(
typeof
b
===
'
number
'
)
return
IntTuple
.
areEqual
(
a
,
b
)
?
MultiSet
.
Empty
:
a
;
return
subtractNE
(
a
,
b
as
MultiSetElements
);
}
if
(
typeof
b
===
'
number
'
)
return
subtractEN
(
a
as
MultiSetElements
,
b
);
return
subtractEE
(
a
as
MultiSetElements
,
b
as
MultiSetElements
);
}
class
ElementsIterator
implements
Iterator
<
IntTuple
.
Unpacked
>
{
private
pair
=
IntTuple
.
zero
();
function
unionI
(
a
:
MultiSetImpl
,
b
:
MultiSetImpl
)
{
return
findUnion
([
a
,
b
]);
}
private
keyCount
:
number
;
private
setIndex
=
-
1
;
private
currentIndex
=
0
;
private
currentSize
=
0
;
private
currentSet
:
OrderedSet
=
OrderedSet
.
Empty
;
function
unionManyI
(
sets
:
ArrayLike
<
MultiSetImpl
>
)
{
return
findUnion
(
sets
);
}
[
Symbol
.
iterator
]()
{
return
new
ElementsIterator
(
this
.
elements
);
};
done
:
boolean
;
next
()
{
const
value
=
this
.
move
();
return
{
value
,
done
:
this
.
done
}
}
class
ElementsIterator
implements
Iterator
<
IntTuple
.
Unpacked
>
{
private
pair
=
IntTuple
.
zero
();
move
()
{
if
(
this
.
done
)
return
this
.
pair
;
private
keyCount
:
number
;
private
setIndex
=
-
1
;
private
currentIndex
=
0
;
private
currentSize
=
0
;
private
currentSet
:
OrderedSet
=
OrderedSet
.
Empty
;
if
(
this
.
currentIndex
>=
this
.
currentSize
)
{
if
(
!
this
.
advance
())
return
this
.
pair
;
}
[
Symbol
.
iterator
]()
{
return
new
ElementsIterator
(
this
.
elements
);
};
done
:
boolean
;
next
()
{
const
value
=
this
.
move
();
return
{
value
,
done
:
this
.
done
}
}
this
.
pair
.
snd
=
OrderedSet
.
getAt
(
this
.
currentSet
,
this
.
currentIndex
++
);
return
this
.
pair
;
}
move
()
{
if
(
this
.
done
)
return
this
.
pair
;
private
advance
()
{
if
(
++
this
.
setIndex
>=
this
.
keyCount
)
{
this
.
done
=
true
;
return
false
;
}
const
unit
=
OrderedSet
.
getAt
(
this
.
elements
.
keys
,
this
.
setIndex
);
this
.
pair
.
fst
=
unit
;
this
.
currentSet
=
this
.
elements
[
unit
];
this
.
currentIndex
=
0
;
this
.
currentSize
=
OrderedSet
.
size
(
this
.
currentSet
);
return
true
;
if
(
this
.
currentIndex
>=
this
.
currentSize
)
{
if
(
!
this
.
advance
())
return
this
.
pair
;
}
constructor
(
private
elements
:
MultiSetElements
)
{
this
.
keyCount
=
OrderedSet
.
size
(
elements
.
keys
);
this
.
done
=
this
.
keyCount
===
0
;
this
.
advance
();
this
.
pair
.
snd
=
OrderedSet
.
getAt
(
this
.
currentSet
,
this
.
currentIndex
++
);
return
this
.
pair
;
}
private
advance
()
{
if
(
++
this
.
setIndex
>=
this
.
keyCount
)
{
this
.
done
=
true
;
return
false
;
}
const
unit
=
OrderedSet
.
getAt
(
this
.
elements
.
keys
,
this
.
setIndex
);
this
.
pair
.
fst
=
unit
;
this
.
currentSet
=
this
.
elements
[
unit
];
this
.
currentIndex
=
0
;
this
.
currentSize
=
OrderedSet
.
size
(
this
.
currentSet
);
return
true
;
}
export
function
values
(
set
:
MultiSet
):
Iterator
<
IntTuple
.
Unpacked
>
{
if
(
typeof
set
===
'
number
'
)
return
Iterator
.
Value
(
IntTuple
.
unpack1
(
set
));
return
new
ElementsIterator
(
set
as
MultiSetElements
);
constructor
(
private
elements
:
MultiSetElements
)
{
this
.
keyCount
=
OrderedSet
.
size
(
elements
.
keys
);
this
.
done
=
this
.
keyCount
===
0
;
this
.
advance
();
}
}
interface
MultiSetElements
{
[
id
:
number
]:
OrderedSet
,
offsets
:
number
[],
hashCode
:
number
,
keys
:
OrderedSet
}
function
valuesI
(
set
:
MultiSetImpl
):
Iterator
<
IntTuple
.
Unpacked
>
{
if
(
typeof
set
===
'
number
'
)
return
Iterator
.
Value
(
IntTuple
.
unpack1
(
set
));
return
new
ElementsIterator
(
set
as
MultiSetElements
);
}
function
isArrayLike
(
x
:
any
):
x
is
ArrayLike
<
number
>
{
return
x
&&
(
typeof
x
.
length
===
'
number
'
&&
(
x
instanceof
Array
||
!!
x
.
buffer
));
...
...
@@ -259,7 +286,7 @@ function normalizeArray(xs: number[]) {
return
xs
;
}
function
ofTuples
(
xs
:
ArrayLike
<
IntTuple
>
)
:
MultiSet
{
function
ofTuples
(
xs
:
ArrayLike
<
IntTuple
>
)
{
if
(
xs
.
length
===
0
)
return
MultiSet
.
Empty
;
const
sets
:
{
[
key
:
number
]:
number
[]
}
=
Object
.
create
(
null
);
const
p
=
IntTuple
.
zero
();
...
...
@@ -322,7 +349,7 @@ function computeHash(set: MultiSetElements) {
hash
=
(
31
*
hash
+
k
)
|
0
;
hash
=
(
31
*
hash
+
OrderedSet
.
hashCode
(
set
[
k
]))
|
0
;
}
hash
=
(
31
*
hash
+
MultiSet
.
size
(
set
))
|
0
;
hash
=
(
31
*
hash
+
size
I
(
set
))
|
0
;
hash
=
hash1
(
hash
);
set
.
hashCode
=
hash
;
return
hash
;
...
...
@@ -330,7 +357,7 @@ function computeHash(set: MultiSetElements) {
function
areEqualEE
(
a
:
MultiSetElements
,
b
:
MultiSetElements
)
{
if
(
a
===
b
)
return
true
;
if
(
MultiSet
.
size
(
a
)
!==
MultiSet
.
size
(
a
))
return
false
;
if
(
size
I
(
a
)
!==
size
I
(
a
))
return
false
;
const
keys
=
a
.
keys
;
if
(
!
OrderedSet
.
areEqual
(
keys
,
b
.
keys
))
return
false
;
...
...
@@ -393,7 +420,7 @@ function subtractNE(a: IntTuple, b: MultiSetElements) {
}
const
_sEN
=
IntTuple
.
zero
();
function
subtractEN
(
a
:
MultiSetElements
,
b
:
IntTuple
):
MultiSet
{
function
subtractEN
(
a
:
MultiSetElements
,
b
:
IntTuple
):
MultiSet
Impl
{
const
aKeys
=
a
.
keys
;
IntTuple
.
unpack
(
b
,
_sEN
);
if
(
!
OrderedSet
.
has
(
aKeys
,
_sEN
.
fst
)
||
!
OrderedSet
.
has
(
a
[
_sEN
.
fst
],
_sEN
.
snd
))
return
a
;
...
...
@@ -439,10 +466,10 @@ function subtractEE(a: MultiSetElements, b: MultiSetElements) {
return
ofObjectOrdered
(
OrderedSet
.
ofSortedArray
(
keys
),
ret
);
}
function
findUnion
(
sets
:
ArrayLike
<
MultiSet
>
)
{
function
findUnion
(
sets
:
ArrayLike
<
MultiSet
Impl
>
)
{
if
(
!
sets
.
length
)
return
MultiSet
.
Empty
;
if
(
sets
.
length
===
1
)
return
sets
[
0
];
if
(
sets
.
length
===
2
&&
MultiSet
.
areEqual
(
sets
[
0
],
sets
[
1
]))
return
sets
[
0
];
if
(
sets
.
length
===
2
&&
areEqual
I
(
sets
[
0
],
sets
[
1
]))
return
sets
[
0
];
const
eCount
=
{
count
:
0
};
const
ns
=
unionN
(
sets
,
eCount
);
...
...
@@ -452,14 +479,14 @@ function findUnion(sets: ArrayLike<MultiSet>) {
const
s
=
sets
[
i
];
if
(
typeof
s
!==
'
number
'
)
unionInto
(
ret
,
s
as
MultiSetElements
);
}
if
(
MultiSet
.
size
(
ns
)
>
0
)
{
if
(
sizeI
(
ns
as
MultiSetImpl
)
>
0
)
{
if
(
typeof
ns
===
'
number
'
)
unionIntoN
(
ret
,
ns
);
else
unionInto
(
ret
,
ns
as
MultiSetElements
);
}
return
ofObject
(
ret
);
}
function
unionN
(
sets
:
ArrayLike
<
MultiSet
>
,
eCount
:
{
count
:
number
})
{
function
unionN
(
sets
:
ArrayLike
<
MultiSet
Impl
>
,
eCount
:
{
count
:
number
})
{
let
countN
=
0
,
countE
=
0
;
for
(
let
i
=
0
,
_i
=
sets
.
length
;
i
<
_i
;
i
++
)
{
if
(
typeof
sets
[
i
]
===
'
number
'
)
countN
++
;
...
...
@@ -496,6 +523,4 @@ function unionIntoN(data: { [key: number]: OrderedSet }, a: IntTuple) {
}
else
{
data
[
_uIN
.
fst
]
=
OrderedSet
.
ofSingleton
(
_uIN
.
snd
);
}
}
export
default
MultiSet
\ No newline at end of file
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/structure/collections/ordered-set.ts
+
8
−
10
View file @
fbd7c35f
...
...
@@ -22,21 +22,22 @@ namespace OrderedSet {
return
xs
as
any
;
}
export
const
size
:
(
set
:
OrderedSet
)
=>
number
=
sizeI
as
any
;
export
const
has
:
(
set
:
OrderedSet
,
x
:
number
)
=>
boolean
=
hasI
as
any
;
export
const
indexOf
:
(
set
:
OrderedSet
,
x
:
number
)
=>
number
=
indexOfI
as
any
;
export
const
getAt
:
(
set
:
OrderedSet
,
i
:
number
)
=>
number
=
getAtI
as
any
;
export
const
min
:
(
set
:
OrderedSet
)
=>
number
=
minI
as
any
;
export
const
max
:
(
set
:
OrderedSet
)
=>
number
=
maxI
as
any
;
export
const
size
:
(
set
:
OrderedSet
)
=>
number
=
sizeI
as
any
;
export
const
hashCode
:
(
set
:
OrderedSet
)
=>
number
=
hashCodeI
as
any
;
export
const
areEqual
:
BinaryTest
=
areEqualI
as
any
;
export
const
areIntersecting
:
BinaryTest
=
areIntersectingI
as
any
;
export
const
isSubset
:
BinaryTest
=
isSubsetI
as
any
;
export
const
areEqual
:
(
a
:
OrderedSet
,
b
:
OrderedSet
)
=>
boolean
=
areEqualI
as
any
;
export
const
areIntersecting
:
(
a
:
OrderedSet
,
b
:
OrderedSet
)
=>
boolean
=
areIntersectingI
as
any
;
export
const
isSubset
:
(
a
:
OrderedSet
,
b
:
OrderedSet
)
=>
boolean
=
isSubsetI
as
any
;
export
const
union
:
BinaryOp
=
unionI
as
any
;
export
const
intersect
:
BinaryOp
=
intersectI
as
any
;
export
const
subtract
:
BinaryOp
=
subtractI
as
any
;
export
const
union
:
(
a
:
OrderedSet
,
b
:
OrderedSet
)
=>
OrderedSet
=
unionI
as
any
;
export
const
intersect
:
(
a
:
OrderedSet
,
b
:
OrderedSet
)
=>
OrderedSet
=
intersectI
as
any
;
export
const
subtract
:
(
a
:
OrderedSet
,
b
:
OrderedSet
)
=>
OrderedSet
=
subtractI
as
any
;
export
const
getInsertionIndex
:
(
set
:
OrderedSet
,
x
:
number
)
=>
number
=
getInsertionIndexI
as
any
;
export
const
getIntervalRange
:
(
set
:
OrderedSet
,
min
:
number
,
max
:
number
)
=>
{
start
:
number
,
end
:
number
}
=
getIntervalRangeI
as
any
;
...
...
@@ -46,9 +47,6 @@ export default OrderedSet
/** Long and painful implementation starts here */
type
BinaryTest
=
(
a
:
OrderedSet
,
b
:
OrderedSet
)
=>
boolean
type
BinaryOp
=
(
a
:
OrderedSet
,
b
:
OrderedSet
)
=>
OrderedSet
type
Range
=
IntTuple
type
SortedArray
=
ArrayLike
<
number
>
type
OrderedSetImpl
=
Range
|
SortedArray
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment