Skip to content

Commit 5e9df02

Browse files
Automated commit of generated code
1 parent 3a71ce3 commit 5e9df02

File tree

17 files changed

+146
-89
lines changed

17 files changed

+146
-89
lines changed

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt

+5-11
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ import org.jetbrains.kotlinx.dataframe.columns.ColumnReference
1414
import org.jetbrains.kotlinx.dataframe.columns.toColumnSet
1515
import org.jetbrains.kotlinx.dataframe.columns.toColumnsSetOf
1616
import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregators
17-
import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.cast2
1817
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll
1918
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor
2019
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf
2120
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfRow
22-
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.of
2321
import org.jetbrains.kotlinx.dataframe.impl.aggregation.primitiveNumberColumns
2422
import org.jetbrains.kotlinx.dataframe.impl.columns.toNumberColumns
2523
import org.jetbrains.kotlinx.dataframe.impl.primitiveNumberTypes
@@ -38,16 +36,12 @@ import kotlin.reflect.typeOf
3836

3937
// region DataColumn
4038

41-
public fun <T : Number> DataColumn<T?>.mean(skipNA: Boolean = skipNA_default): Double =
42-
Aggregators.mean(skipNA).aggregate(this)
39+
public fun DataColumn<Number?>.mean(skipNA: Boolean = skipNA_default): Double = Aggregators.mean(skipNA).aggregate(this)
4340

4441
public inline fun <T, reified R : Number> DataColumn<T>.meanOf(
4542
skipNA: Boolean = skipNA_default,
46-
noinline expression: (T) -> R?,
47-
): Double =
48-
Aggregators.mean(skipNA)
49-
.cast2<R?, Double>()
50-
.aggregateOf(this, expression)
43+
crossinline expression: (T) -> R?,
44+
): Double = Aggregators.mean(skipNA).aggregateOf(this, expression)
5145

5246
// endregion
5347

@@ -113,8 +107,8 @@ public fun <T, C : Number> DataFrame<T>.mean(vararg columns: KProperty<C?>, skip
113107

114108
public inline fun <T, reified D : Number> DataFrame<T>.meanOf(
115109
skipNA: Boolean = skipNA_default,
116-
noinline expression: RowExpression<T, D?>,
117-
): Double = Aggregators.mean(skipNA).of(this, expression)
110+
crossinline expression: RowExpression<T, D?>,
111+
): Double = Aggregators.mean(skipNA).aggregateOf(this, expression)
118112

119113
// endregion
120114

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns
1818
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll
1919
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor
2020
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf
21-
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.of
2221
import org.jetbrains.kotlinx.dataframe.impl.columns.toComparableColumns
2322
import org.jetbrains.kotlinx.dataframe.impl.suggestIfNull
2423
import org.jetbrains.kotlinx.dataframe.math.median
@@ -101,7 +100,7 @@ public fun <T, C : Comparable<C>> DataFrame<T>.medianOrNull(vararg columns: KPro
101100

102101
public inline fun <T, reified R : Comparable<R>> DataFrame<T>.medianOf(
103102
crossinline expression: RowExpression<T, R?>,
104-
): R? = Aggregators.median.of(this, expression) as R?
103+
): R? = Aggregators.median.aggregateOf(this, expression) as R?
105104

106105
// endregion
107106

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns
1616
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll
1717
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor
1818
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf
19-
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.of
2019
import org.jetbrains.kotlinx.dataframe.impl.columns.toComparableColumns
2120
import org.jetbrains.kotlinx.dataframe.impl.suggestIfNull
2221
import org.jetbrains.kotlinx.dataframe.math.percentile
@@ -121,7 +120,7 @@ public fun <T, C : Comparable<C>> DataFrame<T>.percentileOrNull(percentile: Doub
121120
public inline fun <T, reified R : Comparable<R>> DataFrame<T>.percentileOf(
122121
percentile: Double,
123122
crossinline expression: RowExpression<T, R?>,
124-
): R? = Aggregators.percentile(percentile).of(this, expression) as R?
123+
): R? = Aggregators.percentile(percentile).aggregateOf(this, expression) as R?
125124

126125
// endregion
127126

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.cast2
1818
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll
1919
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor
2020
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf
21-
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.of
2221
import org.jetbrains.kotlinx.dataframe.impl.aggregation.numberColumns
2322
import org.jetbrains.kotlinx.dataframe.math.std
2423
import kotlin.reflect.KProperty
@@ -99,7 +98,7 @@ public inline fun <T, reified R : Number> DataFrame<T>.stdOf(
9998
skipNA: Boolean = skipNA_default,
10099
ddof: Int = ddof_default,
101100
crossinline expression: RowExpression<T, R?>,
102-
): Double = Aggregators.std(skipNA, ddof).of(this, expression) ?: .0
101+
): Double = Aggregators.std(skipNA, ddof).aggregateOf(this, expression) ?: .0
103102

104103
// endregion
105104

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.cast
2020
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll
2121
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor
2222
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf
23-
import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.of
2423
import org.jetbrains.kotlinx.dataframe.impl.aggregation.numberColumns
2524
import org.jetbrains.kotlinx.dataframe.impl.columns.toNumberColumns
2625
import org.jetbrains.kotlinx.dataframe.impl.zero
@@ -38,8 +37,8 @@ public fun <T : Number> DataColumn<T>.sum(): T = values.sum(type())
3837
@JvmName("sumTNullable")
3938
public fun <T : Number> DataColumn<T?>.sum(): T = values.sum(type())
4039

41-
public inline fun <T, reified R : Number> DataColumn<T>.sumOf(crossinline expression: (T) -> R): R? =
42-
(Aggregators.sum as Aggregator<*, *>).cast<R>().of(this, expression)
40+
public inline fun <T, reified R : Number> DataColumn<T>.sumOf(noinline expression: (T) -> R): R? =
41+
(Aggregators.sum as Aggregator<*, *>).cast<R>().aggregateOf(this, expression)
4342

4443
// endregion
4544

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/UnifyingNumbers.kt

+8
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions
2525
* | / |
2626
* | / |
2727
* UByte Byte
28+
* \ /
29+
* \ /
30+
* Nothing?
2831
* ```
2932
* For each number type in the graph, it holds that a number of that type can be expressed lossless by
3033
* a number of a more complex type (any of its parents).
@@ -36,6 +39,8 @@ import org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions
3639
* potentially losing a little precision, but a warning will be given.
3740
*
3841
* See [UnifiedNumberTypeOptions] for these settings.
42+
*
43+
* At the bottom of the graph is [Nothing]. This can be interpreted as `null`.
3944
*/
4045
internal interface UnifyingNumbers {
4146

@@ -55,6 +60,9 @@ internal interface UnifyingNumbers {
5560
* | / |
5661
* | / |
5762
* UByte Byte
63+
* \ /
64+
* \ /
65+
* Nothing?
5866
* ```
5967
*/
6068
interface Graph

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/NumberTypeUtils.kt

+16-3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ private val unifiedNumberTypeGraphs = mutableMapOf<UnifiedNumberTypeOptions, Dir
4949
* | / |
5050
* | / |
5151
* UByte Byte
52+
* \ /
53+
* \ /
54+
* Nothing?
5255
* ```
5356
*
5457
* For any two numbers, we can find the nearest common ancestor in this graph
@@ -97,6 +100,9 @@ internal fun getUnifiedNumberTypeGraph(
97100

98101
addEdge(typeOf<Short>(), typeOf<UByte>())
99102
addEdge(typeOf<Short>(), typeOf<Byte>())
103+
104+
addEdge(typeOf<UByte>(), nothingType)
105+
addEdge(typeOf<Byte>(), nothingType)
100106
}
101107
}
102108

@@ -118,6 +124,9 @@ internal fun getUnifiedNumberTypeGraph(
118124
* | / |
119125
* | / |
120126
* UByte Byte
127+
* \ /
128+
* \ /
129+
* Nothing?
121130
* ```
122131
*
123132
* For any two numbers, we can find the nearest common ancestor in this graph
@@ -162,7 +171,11 @@ internal fun getUnifiedNumberType(
162171
?: error("Can not find common number type for $first and $second")
163172
}
164173

165-
return if (first.isMarkedNullable || second.isMarkedNullable) result.withNullability(true) else result
174+
return if (first.isMarkedNullable || second.isMarkedNullable) {
175+
result.withNullability(true)
176+
} else {
177+
result
178+
}
166179
}
167180

168181
/** Determines the nearest common numeric type, in terms of complexity, between two given classes/types.
@@ -245,7 +258,7 @@ internal fun Iterable<Number?>.convertToUnifiedNumberType(
245258
options: UnifiedNumberTypeOptions = UnifiedNumberTypeOptions.DEFAULT,
246259
commonNumberType: KType? = null,
247260
): Iterable<Number?> {
248-
val commonNumberType = commonNumberType ?: this.filterNotNull().types().unifiedNumberType(options)
261+
val commonNumberType = commonNumberType ?: this.types().unifiedNumberType(options)
249262
val converter = createConverter(typeOf<Number>(), commonNumberType)!! as (Number) -> Number?
250263
return map {
251264
if (it == null) return@map null
@@ -286,7 +299,7 @@ internal fun Sequence<Number?>.convertToUnifiedNumberType(
286299
options: UnifiedNumberTypeOptions = UnifiedNumberTypeOptions.DEFAULT,
287300
commonNumberType: KType? = null,
288301
): Sequence<Number?> {
289-
val commonNumberType = commonNumberType ?: this.filterNotNull().asIterable().types().unifiedNumberType(options)
302+
val commonNumberType = commonNumberType ?: this.asIterable().types().unifiedNumberType(options)
290303
val converter = createConverter(typeOf<Number>(), commonNumberType)!! as (Number) -> Number?
291304
return map {
292305
if (it == null) return@map null

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt

+12-5
Original file line numberDiff line numberDiff line change
@@ -667,19 +667,26 @@ internal fun Any.isBigNumber(): Boolean = this is BigInteger || this is BigDecim
667667
*
668668
* The [KClass] is determined by retrieving the runtime class of each element.
669669
*
670+
* [Nothing::class][Nothing] is used for elements that are `null`.
671+
*
670672
* @return A set of [KClass] objects representing the runtime types of elements in the iterable.
671673
*/
672-
internal fun Iterable<Any>.classes(): Set<KClass<*>> = mapTo(mutableSetOf()) { it::class }
674+
internal fun Iterable<Any?>.classes(): Set<KClass<*>> =
675+
mapTo(mutableSetOf()) {
676+
if (it == null) Nothing::class else it::class
677+
}
673678

674679
/**
675680
* Returns a set of [KType] objects representing the star-projected types of the runtime classes
676681
* of all unique elements in the iterable.
677682
*
678-
* The method internally relies on the [classes] function to collect the runtime classes of the
679-
* elements in the iterable and then maps each class to its star-projected type.
680-
*
681683
* This can be a heavy operation!
682684
*
685+
* [typeOf<Nothing?>()][nullableNothingType] is used for elements that are `null`.
686+
*
683687
* @return A set of [KType] objects corresponding to the star-projected runtime types of elements in the iterable.
684688
*/
685-
internal fun Iterable<Any>.types(): Set<KType> = classes().mapTo(mutableSetOf()) { it.createStarProjectedType(false) }
689+
internal fun Iterable<Any?>.types(): Set<KType> =
690+
mapTo(mutableSetOf()) {
691+
if (it == null) nullableNothingType else it::class.createStarProjectedType(false)
692+
}

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt

+13-9
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import kotlin.reflect.full.withNullability
1313
* The [AggregatorBase] class is a base implementation of this interface.
1414
*
1515
* @param Value The type of the values to be aggregated.
16-
* This can be nullable for [Iterables][Iterable] or not, depending on the use case.
17-
* For columns, [Value] will always be considered nullable; nulls are filtered out from columns anyway.
16+
* The input can always have nulls, they are filtered out.
1817
* @param Return The type of the resulting value. Can optionally be nullable.
1918
*/
2019
@PublishedApi
@@ -26,17 +25,19 @@ internal interface Aggregator<in Value, out Return> {
2625
/**
2726
* Base function of [Aggregator].
2827
*
29-
* Aggregates the given values, taking [type] into account, and computes a single resulting value.
28+
* Aggregates the given values, taking [type] into account,
29+
* filtering nulls (only if [type.isMarkedNullable][KType.isMarkedNullable]),
30+
* and computes a single resulting value.
3031
*
3132
* When using [AggregatorBase], this can be supplied by the [AggregatorBase.aggregator] argument.
3233
*
3334
* When the exact [type] is unknown, use [aggregateCalculatingType].
3435
*/
35-
fun aggregate(values: Iterable<Value>, type: KType): Return
36+
fun aggregate(values: Iterable<Value?>, type: KType): Return
3637

3738
/**
3839
* Aggregates the data in the given column and computes a single resulting value.
39-
* Nulls are filtered out by default, then [aggregate] (with [Iterable] and [KType]) is called.
40+
* Calls [aggregate] (with [Iterable] and [KType]).
4041
*
4142
* See [AggregatorBase.aggregate].
4243
*/
@@ -55,9 +56,9 @@ internal interface Aggregator<in Value, out Return> {
5556
* @param valueTypes The types of the values.
5657
* If provided, this can be used to avoid calculating the types of [values] at runtime with reflection.
5758
* It should contain all types of [values].
58-
* If `null`, the types of [values] will be calculated at runtime (heavy!).
59+
* If `null` or empty, the types of [values] will be calculated at runtime (heavy!).
5960
*/
60-
fun aggregateCalculatingType(values: Iterable<Value>, valueTypes: Set<KType>? = null): Return
61+
fun aggregateCalculatingType(values: Iterable<Value?>, valueTypes: Set<KType>? = null): Return
6162

6263
/**
6364
* Function that can give the return type of [aggregate] as [KType], given the type of the input.
@@ -92,8 +93,11 @@ internal fun <Value, Return> Aggregator<*, *>.cast2(): Aggregator<Value, Return>
9293
/** Type alias for [Aggregator.calculateReturnTypeOrNull] */
9394
internal typealias CalculateReturnTypeOrNull = (type: KType, emptyInput: Boolean) -> KType?
9495

95-
/** Type alias for [Aggregator.aggregate]. */
96-
internal typealias Aggregate<Value, Return> = Iterable<Value>.(type: KType) -> Return
96+
/**
97+
* Type alias for the argument for [Aggregator.aggregate].
98+
* Nulls have already been filtered out when this argument is called.
99+
*/
100+
internal typealias Aggregate<Value, Return> = Iterable<Value & Any>.(type: KType) -> Return
97101

98102
/** Common case for [CalculateReturnTypeOrNull], preserves return type, but makes it nullable for empty inputs. */
99103
internal val preserveReturnTypeNullIfEmpty: CalculateReturnTypeOrNull = { type, emptyInput ->

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorBase.kt

+29-16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import org.jetbrains.kotlinx.dataframe.DataColumn
44
import org.jetbrains.kotlinx.dataframe.api.asIterable
55
import org.jetbrains.kotlinx.dataframe.api.asSequence
66
import org.jetbrains.kotlinx.dataframe.impl.commonType
7+
import org.jetbrains.kotlinx.dataframe.impl.nothingType
78
import kotlin.reflect.KType
89
import kotlin.reflect.full.withNullability
910

@@ -14,7 +15,7 @@ import kotlin.reflect.full.withNullability
1415
* or multiple [DataColumns][DataColumn].
1516
*
1617
* @param name The name of this aggregator.
17-
* @param aggregator Functional argument for the [aggregate] function.
18+
* @param aggregator Functional argument for the [aggregate] function. Nulls are filtered out before this is called.
1819
*/
1920
internal abstract class AggregatorBase<in Value, out Return>(
2021
override val name: String,
@@ -25,13 +26,26 @@ internal abstract class AggregatorBase<in Value, out Return>(
2526
/**
2627
* Base function of [Aggregator].
2728
*
28-
* Aggregates the given values, taking [type] into account, and computes a single resulting value.
29+
* Aggregates the given values, taking [type] into account,
30+
* filtering nulls (only if [type.isMarkedNullable][KType.isMarkedNullable]),
31+
* and computes a single resulting value.
2932
*
30-
* Uses [aggregator] to compute the result.
33+
* When using [AggregatorBase], this can be supplied by the [AggregatorBase.aggregator] argument.
3134
*
3235
* When the exact [type] is unknown, use [aggregateCalculatingType].
3336
*/
34-
override fun aggregate(values: Iterable<Value>, type: KType): Return = aggregator(values, type)
37+
@Suppress("UNCHECKED_CAST")
38+
override fun aggregate(values: Iterable<Value?>, type: KType): Return =
39+
aggregator(
40+
// values =
41+
if (type.isMarkedNullable) {
42+
values.asSequence().filterNotNull().asIterable()
43+
} else {
44+
values as Iterable<Value & Any>
45+
},
46+
// type =
47+
type.withNullability(false),
48+
)
3549

3650
/**
3751
* Function that can give the return type of [aggregate] as [KType], given the type of the input.
@@ -44,7 +58,7 @@ internal abstract class AggregatorBase<in Value, out Return>(
4458
* @return The return type of [aggregate] as [KType].
4559
*/
4660
override fun calculateReturnTypeOrNull(type: KType, emptyInput: Boolean): KType? =
47-
getReturnTypeOrNull(type, emptyInput)
61+
getReturnTypeOrNull(type.withNullability(false), emptyInput)
4862

4963
/**
5064
* Aggregates the data in the given column and computes a single resulting value.
@@ -54,13 +68,8 @@ internal abstract class AggregatorBase<in Value, out Return>(
5468
@Suppress("UNCHECKED_CAST")
5569
override fun aggregate(column: DataColumn<Value?>): Return =
5670
aggregate(
57-
values =
58-
if (column.hasNulls()) {
59-
column.asSequence().filterNotNull().asIterable()
60-
} else {
61-
column.asIterable() as Iterable<Value>
62-
},
63-
type = column.type().withNullability(false),
71+
values = column.asIterable(),
72+
type = column.type(),
6473
)
6574

6675
/** Special case of [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator.aggregate] with [Iterable] that calculates the common type of the values at runtime.
@@ -70,9 +79,9 @@ internal abstract class AggregatorBase<in Value, out Return>(
7079
* @param valueTypes The types of the values.
7180
* If provided, this can be used to avoid calculating the types of [values][org.jetbrains.kotlinx.dataframe.values] at runtime with reflection.
7281
* It should contain all types of [values][org.jetbrains.kotlinx.dataframe.values].
73-
* If `null`, the types of [values][org.jetbrains.kotlinx.dataframe.values] will be calculated at runtime (heavy!). */
74-
override fun aggregateCalculatingType(values: Iterable<Value>, valueTypes: Set<KType>?): Return {
75-
val commonType = if (valueTypes != null) {
82+
* If `null` or empty, the types of [values][org.jetbrains.kotlinx.dataframe.values] will be calculated at runtime (heavy!). */
83+
override fun aggregateCalculatingType(values: Iterable<Value?>, valueTypes: Set<KType>?): Return {
84+
val commonType = if (valueTypes != null && valueTypes.isNotEmpty()) {
7685
valueTypes.commonType(false)
7786
} else {
7887
var hasNulls = false
@@ -84,7 +93,11 @@ internal abstract class AggregatorBase<in Value, out Return>(
8493
it.javaClass.kotlin
8594
}
8695
}
87-
classes.commonType(hasNulls)
96+
if (classes.isEmpty()) {
97+
nothingType(hasNulls)
98+
} else {
99+
classes.commonType(hasNulls)
100+
}
88101
}
89102
return aggregate(values, commonType)
90103
}

0 commit comments

Comments
 (0)