1
1
package org.jetbrains.kotlinx.dataframe.impl
2
2
3
+ import org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers
3
4
import org.jetbrains.kotlinx.dataframe.impl.api.createConverter
4
- import org.jetbrains.kotlinx.dataframe.impl.commonNumberType
5
5
import java.math.BigDecimal
6
6
import java.math.BigInteger
7
7
import kotlin.reflect.KClass
@@ -13,70 +13,65 @@ import kotlin.reflect.typeOf
13
13
* Number type graph, structured in terms of number complexity.
14
14
* A number can always be expressed lossless by a number of a more complex type (any of its parents).
15
15
*
16
- * ```
17
- * BigDecimal
18
- * / \\
19
- * BigInteger |
20
- * | |
21
- * ULong |
22
- * | |
23
- * Long Double
24
- * \\ / |
25
- * UInt |
26
- * | |
27
- * Int Float
28
- * | /
29
- * UShort
30
- * |
31
- * Short
32
- * |
33
- * UByte
34
- * |
35
- * Byte
36
- * ```
16
+ * {@include [UnifyingNumbers.Graph]}
37
17
*
38
18
* For any two numbers, we can find the nearest common ancestor in this graph
39
19
* by calling [DirectedAcyclicGraph.findNearestCommonVertex].
40
- * @see getCommonNumberClass
41
- * @see commonNumberClass
20
+ * @see getUnifiedNumberClass
21
+ * @see unifiedNumberClass
22
+ * @see UnifyingNumbers
42
23
*/
43
- internal val numberTypeGraph: DirectedAcyclicGraph <KType > by lazy {
44
- dagOf(
45
- typeOf<BigDecimal >() to typeOf<BigInteger >(),
46
- typeOf<BigDecimal >() to typeOf<Double >(),
47
- typeOf<BigInteger >() to typeOf<ULong >(),
48
- typeOf<ULong >() to typeOf<Long >(),
49
- typeOf<Long >() to typeOf<UInt >(),
50
- typeOf<Double >() to typeOf<UInt >(),
51
- typeOf<Double >() to typeOf<Float >(),
52
- typeOf<UInt >() to typeOf<Int >(),
53
- typeOf<Int >() to typeOf<UShort >(),
54
- typeOf<Float >() to typeOf<UShort >(),
55
- typeOf<UShort >() to typeOf<Short >(),
56
- typeOf<Short >() to typeOf<UByte >(),
57
- typeOf<UByte >() to typeOf<Byte >(),
58
- )
24
+ internal val unifiedNumberTypeGraph: DirectedAcyclicGraph <KType > by lazy {
25
+ buildDag {
26
+ addEdge(typeOf<BigDecimal >(), typeOf<BigInteger >())
27
+ addEdge(typeOf<BigDecimal >(), typeOf<Double >())
28
+
29
+ addEdge(typeOf<BigInteger >(), typeOf<ULong >())
30
+ addEdge(typeOf<BigInteger >(), typeOf<Long >())
31
+
32
+ addEdge(typeOf<ULong >(), typeOf<UInt >())
33
+
34
+ addEdge(typeOf<Long >(), typeOf<UInt >())
35
+ addEdge(typeOf<Long >(), typeOf<Int >())
36
+
37
+ addEdge(typeOf<Double >(), typeOf<Int >())
38
+ addEdge(typeOf<Double >(), typeOf<Float >())
39
+ addEdge(typeOf<Double >(), typeOf<UInt >())
40
+
41
+ addEdge(typeOf<UInt >(), typeOf<UShort >())
42
+
43
+ addEdge(typeOf<Int >(), typeOf<UShort >())
44
+ addEdge(typeOf<Int >(), typeOf<Short >())
45
+
46
+ addEdge(typeOf<Float >(), typeOf<Short >())
47
+ addEdge(typeOf<Float >(), typeOf<UShort >())
48
+
49
+ addEdge(typeOf<UShort >(), typeOf<UByte >())
50
+
51
+ addEdge(typeOf<Short >(), typeOf<UByte >())
52
+ addEdge(typeOf<Short >(), typeOf<Byte >())
53
+ }
59
54
}
60
55
61
- /* * @include [numberTypeGraph ] */
62
- internal val numberClassGraph : DirectedAcyclicGraph <KClass <* >> by lazy {
63
- numberTypeGraph .map { it.classifier as KClass <* > }
56
+ /* * @include [unifiedNumberTypeGraph ] */
57
+ internal val unifiedNumberClassGraph : DirectedAcyclicGraph <KClass <* >> by lazy {
58
+ unifiedNumberTypeGraph .map { it.classifier as KClass <* > }
64
59
}
65
60
66
61
/* *
67
62
* Determines the nearest common numeric type, in terms of complexity, between two given classes/types.
68
63
*
69
64
* Unsigned types are supported too even though they are not a [Number] instance,
70
- * but unless an unsigned type is provided in the input, it will never be returned.
71
- * Meaning, given two [Number] inputs , the output will always be a [Number].
65
+ * but unless two unsigned types are provided in the input, it will never be returned.
66
+ * Meaning, a single [Number] input , the output will always be a [Number].
72
67
*
73
68
* @param first The first numeric type to compare. Can be null, in which case the second to is returned.
74
69
* @param second The second numeric to compare. Cannot be null.
75
70
* @return The nearest common numeric type between the two input classes.
76
71
* If no common class is found, [IllegalStateException] is thrown.
77
- * @see numberTypeGraph
72
+ * @see UnifyingNumbers
78
73
*/
79
- internal fun getCommonNumberType (first : KType ? , second : KType ): KType {
74
+ internal fun getUnifiedNumberType (first : KType ? , second : KType ): KType {
80
75
if (first == null ) return second
81
76
82
77
val firstWithoutNullability = first.withNullability(false )
@@ -85,56 +80,57 @@ internal fun getCommonNumberType(first: KType?, second: KType): KType {
85
80
val result = if (firstWithoutNullability == secondWithoutNullability) {
86
81
firstWithoutNullability
87
82
} else {
88
- numberTypeGraph .findNearestCommonVertex(firstWithoutNullability, secondWithoutNullability)
83
+ unifiedNumberTypeGraph .findNearestCommonVertex(firstWithoutNullability, secondWithoutNullability)
89
84
? : error(" Can not find common number type for $first and $second " )
90
85
}
91
86
92
87
return if (first.isMarkedNullable || second.isMarkedNullable) result.withNullability(true ) else result
93
88
}
94
89
95
- /* * @include [getCommonNumberType ] */
90
+ /* * @include [getUnifiedNumberType ] */
96
91
@Suppress(" IntroduceWhenSubject" )
97
- internal fun getCommonNumberClass (first : KClass <* >? , second : KClass <* >): KClass <* > =
92
+ internal fun getUnifiedNumberClass (first : KClass <* >? , second : KClass <* >): KClass <* > =
98
93
when {
99
94
first == null -> second
100
95
101
96
first == second -> first
102
97
103
- else -> numberClassGraph .findNearestCommonVertex(first, second)
98
+ else -> unifiedNumberClassGraph .findNearestCommonVertex(first, second)
104
99
? : error(" Can not find common number type for $first and $second " )
105
100
}
106
101
107
102
/* *
108
103
* Determines the nearest common numeric type, in terms of complexity, all types in [this].
109
104
*
110
105
* Unsigned types are supported too even though they are not a [Number] instance,
111
- * but unless an unsigned type is provided in the input , it will never be returned.
112
- * Meaning, given just [Number] inputs , the output will always be a [Number].
106
+ * but unless the input solely exists of unsigned numbers , it will never be returned.
107
+ * Meaning, given a [Number] in the input , the output will always be a [Number].
113
108
*
114
109
* @return The nearest common numeric type between the input types.
115
110
* If no common type is found, it returns [Number].
116
- * @see numberTypeGraph
111
+ * @see UnifyingNumbers
117
112
*/
118
- internal fun Iterable<KType>.commonNumberType (): KType = fold(null as KType ? , ::getCommonNumberType) ? : typeOf<Number >()
113
+ internal fun Iterable<KType>.unifiedNumberType (): KType =
114
+ fold(null as KType ? , ::getUnifiedNumberType) ? : typeOf<Number >()
119
115
120
- /* * @include [commonNumberType ] */
121
- internal fun Iterable <KClass <* >>.commonNumberClass (): KClass <* > =
122
- fold(null as KClass <* >? , ::getCommonNumberClass ) ? : Number ::class
116
+ /* * @include [unifiedNumberType ] */
117
+ internal fun Iterable <KClass <* >>.unifiedNumberClass (): KClass <* > =
118
+ fold(null as KClass <* >? , ::getUnifiedNumberClass ) ? : Number ::class
123
119
124
120
/* *
125
121
* Converts the elements of the given iterable of numbers into a common numeric type based on complexity.
126
122
* The common numeric type is determined using the provided [commonNumberType] parameter
127
- * or calculated with [Iterable.commonNumberType ] from the iterable's elements if not explicitly specified.
123
+ * or calculated with [Iterable.unifiedNumberType ] from the iterable's elements if not explicitly specified.
128
124
*
129
125
* @param commonNumberType The desired common numeric type to convert the elements to.
130
126
* This is determined by default using the types of the elements in the iterable.
131
127
* @return A new iterable of numbers where each element is converted to the specified or inferred common number type.
132
128
* @throws IllegalStateException if an element cannot be converted to the common number type.
133
- * @see Iterable.commonNumberType
129
+ * @see UnifyingNumbers
134
130
*/
135
131
@Suppress(" UNCHECKED_CAST" )
136
- internal fun Iterable<Number>.convertToCommonNumberType (
137
- commonNumberType : KType = this.types().commonNumberType (),
132
+ internal fun Iterable<Number>.convertToUnifiedNumberType (
133
+ commonNumberType : KType = this.types().unifiedNumberType (),
138
134
): Iterable <Number > {
139
135
val converter = createConverter(typeOf<Number >(), commonNumberType)!! as (Number ) -> Number ?
140
136
return map {
0 commit comments