Skip to content

Commit e03c5f8

Browse files
committed
Rewrite tests and remove some support functions
1 parent 9c6d13a commit e03c5f8

File tree

17 files changed

+858
-1058
lines changed

17 files changed

+858
-1058
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,10 @@ jobs:
1818
- 'ubuntu-latest'
1919
java:
2020
- version: '11'
21+
- version: '17'
2122
gradle:
2223
- version: '7.6.4' # Latest stable 7
2324
command: 'gradle'
24-
- version: '8.8' # Latest stable 8
25-
command: 'gradle'
26-
- version: 'current' # Latest stable
27-
command: 'gradle'
2825
- version: 'wrapper'
2926
command: './gradlew' # Workaround for issue https://github.com/gradle/actions/issues/273
3027
runs-on: ${{ matrix.os }}

disjointmap/build.gradle.kts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ val junitVersion = "5.8.1"
77

88
dependencies {
99
implementation (libs.kotlinx.immutablecollections)
10-
1110
compileOnly (libs.jsr305)
12-
1311
testImplementation (libs.junit)
12+
testImplementation (libs.kotest)
1413
}

disjointmap/src/main/java/com/virtlink/collections/N.java

Lines changed: 0 additions & 48 deletions
This file was deleted.

disjointmap/src/main/kotlin/com/virtlink/collections/DisjointMap.kt

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package com.virtlink.collections
22

33
/**
4-
* A map of key in disjoint sets with a value.
4+
* A map of disjoint sets associated with a value.
55
*
6-
* @param K the type of keys
7-
* @param V the type of values
6+
* @param K The type of keys.
7+
* @param V The type of values.
88
*/
99
interface DisjointMap<K, out V> {
1010

@@ -21,34 +21,34 @@ interface DisjointMap<K, out V> {
2121
* Gets the value associated with the set that contains the specified key;
2222
* or `null` when the key is not in the map.
2323
*
24-
* @param key the key whose associated value to get
25-
* @return the associated value; or `null` when the key is not in the map
24+
* @param key The key whose associated value to get.
25+
* @return The associated value; or `null` when the key is not in the map.
2626
*/
2727
operator fun get(key: K): V?
2828

2929
/**
3030
* Gets the value associated with the set that contains the specified key;
3131
* or the default value when the key is not in the map.
3232
*
33-
* @param key the key whose associated value to get
34-
* @return the associated value; or [defaultValue] when the key is not in the map
33+
* @param key The key whose associated value to get.
34+
* @return The associated value (which may be `null`); or [defaultValue] when the key is not in the map.
3535
*/
3636
fun getOrDefault(key: K, defaultValue: @UnsafeVariance V): V
3737

3838
/**
3939
* Finds the representative of the set that includes the given key.
4040
*
41-
* @param key the key to look for
42-
* @return the representative of the set that includes the given key;
43-
* which may be the key itself; or `null` when the key is not in the map
41+
* @param key The key to look for.
42+
* @return The representative of the set that includes the given key;
43+
* which may be the key itself; or `null` when the key is not in the map.
4444
*/
4545
fun find(key: K): K?
4646

4747
/**
4848
* Whether the collection contains the specified key.
4949
*
5050
* @return `true` when the collection contains the specified key;
51-
* otherwise, `false`
51+
* otherwise, `false`.
5252
*/
5353
operator fun contains(key: K): Boolean {
5454
return find(key) != null
@@ -57,10 +57,10 @@ interface DisjointMap<K, out V> {
5757
/**
5858
* Determines whether the given keys are in the same set.
5959
*
60-
* @param key1 one key
61-
* @param key2 another key
60+
* @param key1 One key.
61+
* @param key2 Another key.
6262
* @return `true` when the keys are present and part of the same set;
63-
* otherwise, `false`
63+
* otherwise, `false`.
6464
*/
6565
fun same(key1: K, key2: K): Boolean {
6666
val rep1 = find(key1)
@@ -71,7 +71,7 @@ interface DisjointMap<K, out V> {
7171
/**
7272
* Copies the sets from this disjoint map to a new map.
7373
*
74-
* @return the new map
74+
* @return The new map of disjoint sets to values.
7575
*/
7676
fun toMap(): Map<Set<K>, V>
7777

disjointmap/src/main/kotlin/com/virtlink/collections/DisjointMapImpl.kt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ internal fun <K, V> findMutable(
2929

3030
// TODO: Can we do this iteratively, to avoid updating the parents and ranks maps so much?
3131
// Find the representative of the parent key
32-
val representative = N.assumeNotNull(findMutable(parent, roots, parents, ranks))
33-
if (parent != representative) {
32+
val representative = findMutable(parent, roots, parents, ranks)
33+
if (representative != null && parent != representative) {
3434
// Path compression:
3535
// Update the key to point directly to the representative key
3636
parents[key] = representative
@@ -64,6 +64,7 @@ internal fun <K, V> findMutable(
6464
* @param V the type of values
6565
* @return whether disjoint sets have been unified
6666
*/
67+
@Suppress("UNCHECKED_CAST")
6768
internal fun <K, V> unionMutable(
6869
key1: K,
6970
key2: K,
@@ -92,14 +93,14 @@ internal fun <K, V> unionMutable(
9293
elem in roots.keys && repr in roots.keys -> {
9394
// NOTE: We know both `element` and `rep` are in the values map,
9495
// so values.get() should only return null when their value happens to be null.
95-
val repValue = N.of(roots[repr])
96-
val elemValue = N.of(roots[elem])
96+
val repValue = roots[repr] as V
97+
val elemValue = roots[elem] as V
9798
unify(repValue, elemValue)
9899
}
99100
// - the value associated with the representative element;
100-
repr in roots.keys -> N.of(roots[repr])
101+
repr in roots.keys -> roots[repr] as V
101102
// - the value associated with the eliminated element; or
102-
elem in roots.keys -> N.of(roots[elem])
103+
elem in roots.keys -> roots[elem] as V
103104
// - the default value when neither element has an associated value.
104105
else -> default()
105106
}
@@ -241,7 +242,10 @@ internal fun <K, V> DisjointMap<K, V>.toMapImpl(
241242
roots.keys.forEach { k -> mapping[k] = mutableSetOf(k) }
242243
parents.keys.forEach { k -> mapping[find(k)]!!.add(k) }
243244

244-
return mapping.map { (rep, keys) -> keys.toPersistentSet() to N.of(roots[rep]) }
245+
return mapping.map { (rep, keys) ->
246+
@Suppress("UNCHECKED_CAST")
247+
keys.toPersistentSet() to (roots[rep] as V)
248+
}
245249
.toMap<Set<K>, V>()
246250
}
247251

disjointmap/src/main/kotlin/com/virtlink/collections/ImmutableDisjointMap.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import kotlinx.collections.immutable.ImmutableMap
55
/**
66
* An immutable disjoint map.
77
*
8-
* @param K the type of keys
9-
* @param V the type of values
8+
* @param K The type of keys.
9+
* @param V The type of values.
1010
*/
1111
interface ImmutableDisjointMap<K, out V> : DisjointMap<K, V> {
1212

disjointmap/src/main/kotlin/com/virtlink/collections/MutableUnionFindMap.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ class MutableUnionFindMap<K, V> internal constructor(
2929

3030
override fun getOrDefault(key: K, defaultValue: @UnsafeVariance V): V {
3131
val rep = find(key) ?: return defaultValue
32-
return this._roots[rep] ?: defaultValue
32+
@Suppress("UNCHECKED_CAST")
33+
// We know the key is in the map,
34+
// so this only returns `null` if the value in the map is `null`.
35+
return this._roots[rep] as V
3336
}
3437

3538
override fun find(key: K): K? {

disjointmap/src/main/kotlin/com/virtlink/collections/PersistentUnionFindMap.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ class PersistentUnionFindMap<K, V> internal constructor(
3939

4040
override fun getOrDefault(key: K, defaultValue: @UnsafeVariance V): V {
4141
val rep = find(key) ?: return defaultValue
42-
return this._roots[rep] ?: defaultValue
42+
@Suppress("UNCHECKED_CAST")
43+
// We know the key is in the map,
44+
// so this only returns `null` if the value in the map is `null`.
45+
return this._roots[rep] as V
4346
}
4447

4548
override fun find(key: K): K? {

0 commit comments

Comments
 (0)