forked from kscience/kmath
[WIP] moving from features to attributes
This commit is contained in:
parent
c0a7cff1d8
commit
d3893ab7e6
17
attributes-kt/build.gradle.kts
Normal file
17
attributes-kt/build.gradle.kts
Normal file
@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
}
|
||||
|
||||
kscience {
|
||||
jvm()
|
||||
js()
|
||||
native()
|
||||
wasm()
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = space.kscience.gradle.Maturity.DEVELOPMENT
|
||||
description = """
|
||||
An API and basic implementation for arranging objects in a continuous memory block.
|
||||
""".trimIndent()
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
import kotlin.reflect.KType
|
||||
|
||||
public interface Attribute<T>
|
||||
|
||||
|
||||
public interface AttributeWithDefault<T> : Attribute<T> {
|
||||
public val default: T
|
||||
}
|
||||
|
||||
public interface SetAttribute<V> : Attribute<Set<V>>
|
||||
|
||||
/**
|
||||
* An attribute that has a type parameter for value
|
||||
*/
|
||||
public abstract class PolymorphicAttribute<T>(public val type: KType) : Attribute<T> {
|
||||
override fun equals(other: Any?): Boolean = (other as? PolymorphicAttribute<*>)?.type == this.type
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return type.hashCode()
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
/**
|
||||
* A container for attributes. [attributes] could be made mutable by implementation
|
||||
*/
|
||||
public interface AttributeContainer {
|
||||
public val attributes: Attributes
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
@JvmInline
|
||||
public value class Attributes internal constructor(public val content: Map<out Attribute<*>, Any>) {
|
||||
|
||||
public val keys: Set<Attribute<*>> get() = content.keys
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public operator fun <T> get(attribute: Attribute<T>): T? = content[attribute] as? T
|
||||
|
||||
override fun toString(): String = "Attributes(value=${content.entries})"
|
||||
|
||||
public companion object {
|
||||
public val EMPTY: Attributes = Attributes(emptyMap())
|
||||
}
|
||||
}
|
||||
|
||||
public fun Attributes.isEmpty(): Boolean = content.isEmpty()
|
||||
|
||||
public fun <T> Attributes.getOrDefault(attribute: AttributeWithDefault<T>): T = get(attribute) ?: attribute.default
|
||||
|
||||
public fun <T, A : Attribute<T>> Attributes.withAttribute(
|
||||
attribute: A,
|
||||
attrValue: T?,
|
||||
): Attributes = Attributes(
|
||||
if (attrValue == null) {
|
||||
content - attribute
|
||||
} else {
|
||||
content + (attribute to attrValue)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Add an element to a [SetAttribute]
|
||||
*/
|
||||
public fun <T, A : SetAttribute<T>> Attributes.withAttributeElement(
|
||||
attribute: A,
|
||||
attrValue: T,
|
||||
): Attributes {
|
||||
val currentSet: Set<T> = get(attribute) ?: emptySet()
|
||||
return Attributes(
|
||||
content + (attribute to (currentSet + attrValue))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from [SetAttribute]
|
||||
*/
|
||||
public fun <T, A : SetAttribute<T>> Attributes.withoutAttributeElement(
|
||||
attribute: A,
|
||||
attrValue: T,
|
||||
): Attributes {
|
||||
val currentSet: Set<T> = get(attribute) ?: emptySet()
|
||||
return Attributes(
|
||||
content + (attribute to (currentSet - attrValue))
|
||||
)
|
||||
}
|
||||
|
||||
public fun <T : Any, A : Attribute<T>> Attributes(
|
||||
attribute: A,
|
||||
attrValue: T,
|
||||
): Attributes = Attributes(mapOf(attribute to attrValue))
|
||||
|
||||
public operator fun Attributes.plus(other: Attributes): Attributes = Attributes(content + other.content)
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
/**
|
||||
* A safe builder for [Attributes]
|
||||
*/
|
||||
public class AttributesBuilder internal constructor(private val map: MutableMap<Attribute<*>, Any> = mutableMapOf()) {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public operator fun <T> get(attribute: Attribute<T>): T? = map[attribute] as? T
|
||||
|
||||
public operator fun <V> Attribute<V>.invoke(value: V?) {
|
||||
if (value == null) {
|
||||
map.remove(this)
|
||||
} else {
|
||||
map[this] = value
|
||||
}
|
||||
}
|
||||
|
||||
public fun from(attributes: Attributes) {
|
||||
map.putAll(attributes.content)
|
||||
}
|
||||
|
||||
public fun <V> SetAttribute<V>.add(
|
||||
attrValue: V,
|
||||
) {
|
||||
val currentSet: Set<V> = get(this) ?: emptySet()
|
||||
map[this] = currentSet + attrValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from [SetAttribute]
|
||||
*/
|
||||
public fun <V> SetAttribute<V>.remove(
|
||||
attrValue: V,
|
||||
) {
|
||||
val currentSet: Set<V> = get(this) ?: emptySet()
|
||||
map[this] = currentSet - attrValue
|
||||
}
|
||||
|
||||
public fun build(): Attributes = Attributes(map)
|
||||
}
|
||||
|
||||
public fun AttributesBuilder(
|
||||
attributes: Attributes,
|
||||
): AttributesBuilder = AttributesBuilder(attributes.content.toMutableMap())
|
||||
|
||||
public fun Attributes(builder: AttributesBuilder.() -> Unit): Attributes = AttributesBuilder().apply(builder).build()
|
@ -15,7 +15,7 @@ allprojects {
|
||||
}
|
||||
|
||||
group = "space.kscience"
|
||||
version = "0.3.2-dev-1"
|
||||
version = "0.4.0-dev-1"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
@ -1,9 +1,3 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
rootProject.name = "kmath"
|
||||
|
||||
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||
|
||||
dependencyResolutionManagement {
|
||||
|
@ -6,11 +6,10 @@ kotlin.code.style=official
|
||||
kotlin.mpp.stability.nowarn=true
|
||||
kotlin.native.ignoreDisabledTargets=true
|
||||
|
||||
org.gradle.configureondemand=true
|
||||
org.gradle.jvmargs=-Xmx4096m
|
||||
|
||||
toolsVersion=0.14.8-kotlin-1.8.20
|
||||
|
||||
toolsVersion=0.14.9-kotlin-1.8.20
|
||||
|
||||
org.gradle.parallel=true
|
||||
org.gradle.workers.max=4
|
||||
org.gradle.configureondemand=true
|
||||
org.gradle.jvmargs=-Xmx4096m
|
||||
|
||||
|
@ -106,7 +106,7 @@ public object CMLinearSpace : LinearSpace<Double, DoubleField> {
|
||||
val origin = structure.toCM().origin
|
||||
|
||||
return when (type) {
|
||||
DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null
|
||||
IsDiagonal::class -> if (origin is DiagonalMatrix) IsDiagonal else null
|
||||
|
||||
DeterminantFeature::class, LupDecompositionFeature::class -> object :
|
||||
DeterminantFeature<Double>,
|
||||
|
@ -10,6 +10,7 @@ kscience{
|
||||
|
||||
dependencies {
|
||||
api(projects.kmathMemory)
|
||||
api(projects.attributesKt)
|
||||
}
|
||||
|
||||
testDependencies {
|
||||
|
@ -5,54 +5,49 @@
|
||||
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.kmath.nd.StructureFeature
|
||||
import space.kscience.attributes.Attribute
|
||||
|
||||
/**
|
||||
* A marker interface representing some properties of matrices or additional transformations of them. Features are used
|
||||
* to optimize matrix operations performance in some cases or retrieve the APIs.
|
||||
*/
|
||||
public interface MatrixFeature: StructureFeature
|
||||
public interface MatrixFeature<T> : Attribute<T>
|
||||
|
||||
/**
|
||||
* Matrices with this feature are considered to have only diagonal non-null elements.
|
||||
* Matrices with this feature are considered to have only diagonal non-zero elements.
|
||||
*/
|
||||
public interface DiagonalFeature : MatrixFeature {
|
||||
public companion object : DiagonalFeature
|
||||
public interface IsDiagonal : MatrixFeature<Unit> {
|
||||
public companion object : IsDiagonal
|
||||
}
|
||||
|
||||
/**
|
||||
* Matrices with this feature have all zero elements.
|
||||
*/
|
||||
public object ZeroFeature : DiagonalFeature
|
||||
public object IsZero : IsDiagonal
|
||||
|
||||
/**
|
||||
* Matrices with this feature have unit elements on diagonal and zero elements in all other places.
|
||||
*/
|
||||
public object UnitFeature : DiagonalFeature
|
||||
public object IsUnit : IsDiagonal
|
||||
|
||||
/**
|
||||
* Matrices with this feature can be inverted: *[inverse] = a<sup>−1</sup>* where *a* is the owning matrix.
|
||||
*
|
||||
* @param T the type of matrices' items.
|
||||
*/
|
||||
public interface InverseMatrixFeature<out T : Any> : MatrixFeature {
|
||||
/**
|
||||
* The inverse matrix of the matrix that owns this feature.
|
||||
*/
|
||||
public val inverse: Matrix<T>
|
||||
public class Inverted<T> private constructor() : MatrixFeature<Matrix<T>> {
|
||||
internal val instance: Inverted<Nothing> = Inverted()
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public val <T> LinearSpace<T, *>.Inverted: Inverted<T> get() = Inverted.instance as Inverted<T>
|
||||
|
||||
/**
|
||||
* Matrices with this feature can compute their determinant.
|
||||
*
|
||||
* @param T the type of matrices' items.
|
||||
*/
|
||||
public interface DeterminantFeature<out T : Any> : MatrixFeature {
|
||||
/**
|
||||
* The determinant of the matrix that owns this feature.
|
||||
*/
|
||||
public val determinant: T
|
||||
}
|
||||
public class DeterminantFeature<T : Any> : MatrixFeature<T>
|
||||
|
||||
/**
|
||||
* Produces a [DeterminantFeature] where the [DeterminantFeature.determinant] is [determinant].
|
||||
@ -68,12 +63,12 @@ public fun <T : Any> DeterminantFeature(determinant: T): DeterminantFeature<T> =
|
||||
/**
|
||||
* Matrices with this feature are lower triangular ones.
|
||||
*/
|
||||
public object LFeature : MatrixFeature
|
||||
public object LFeature : MatrixFeature<Unit>
|
||||
|
||||
/**
|
||||
* Matrices with this feature are upper triangular ones.
|
||||
*/
|
||||
public object UFeature : MatrixFeature
|
||||
public object UFeature : MatrixFeature<Unit>
|
||||
|
||||
/**
|
||||
* Matrices with this feature support LU factorization: *a = [l] · [u]* where *a* is the owning matrix.
|
||||
@ -117,7 +112,7 @@ public interface LupDecompositionFeature<out T : Any> : MatrixFeature {
|
||||
|
||||
/**
|
||||
* Matrices with this feature are orthogonal ones: *a · a<sup>T</sup> = u* where *a* is the owning matrix, *u*
|
||||
* is the unit matrix ([UnitFeature]).
|
||||
* is the unit matrix ([IsUnit]).
|
||||
*/
|
||||
public object OrthogonalFeature : MatrixFeature
|
||||
|
||||
|
@ -5,11 +5,10 @@
|
||||
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.attributes.Attributes
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.misc.FeatureSet
|
||||
import space.kscience.kmath.nd.StructureFeature
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* A [Matrix] that holds [MatrixFeature] objects.
|
||||
@ -18,18 +17,10 @@ import kotlin.reflect.KClass
|
||||
*/
|
||||
public class MatrixWrapper<out T : Any> internal constructor(
|
||||
public val origin: Matrix<T>,
|
||||
public val features: FeatureSet<StructureFeature>,
|
||||
public val attributes: Attributes,
|
||||
) : Matrix<T> by origin {
|
||||
|
||||
/**
|
||||
* Get the first feature matching given class. Does not guarantee that matrix has only one feature matching the
|
||||
* criteria.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <F : StructureFeature> getFeature(type: KClass<out F>): F? =
|
||||
features.getFeature(type) ?: origin.getFeature(type)
|
||||
|
||||
override fun toString(): String = "MatrixWrapper(matrix=$origin, features=$features)"
|
||||
override fun toString(): String = "MatrixWrapper(matrix=$origin, features=$attributes)"
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +35,7 @@ public val <T : Any> Matrix<T>.origin: Matrix<T>
|
||||
* Add a single feature to a [Matrix]
|
||||
*/
|
||||
public fun <T : Any> Matrix<T>.withFeature(newFeature: MatrixFeature): MatrixWrapper<T> = if (this is MatrixWrapper) {
|
||||
MatrixWrapper(origin, features.with(newFeature))
|
||||
MatrixWrapper(origin, attributes.with(newFeature))
|
||||
} else {
|
||||
MatrixWrapper(this, FeatureSet.of(newFeature))
|
||||
}
|
||||
@ -57,20 +48,20 @@ public operator fun <T : Any> Matrix<T>.plus(newFeature: MatrixFeature): MatrixW
|
||||
*/
|
||||
public fun <T : Any> Matrix<T>.withFeatures(newFeatures: Iterable<MatrixFeature>): MatrixWrapper<T> =
|
||||
if (this is MatrixWrapper) {
|
||||
MatrixWrapper(origin, features.with(newFeatures))
|
||||
MatrixWrapper(origin, attributes.with(newFeatures))
|
||||
} else {
|
||||
MatrixWrapper(this, FeatureSet.of(newFeatures))
|
||||
}
|
||||
|
||||
/**
|
||||
* Diagonal matrix of ones. The matrix is virtual no actual matrix is created.
|
||||
* Diagonal matrix of ones. The matrix is virtual, no actual matrix is created.
|
||||
*/
|
||||
public fun <T : Any> LinearSpace<T, Ring<T>>.one(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
): Matrix<T> = VirtualMatrix(rows, columns) { i, j ->
|
||||
if (i == j) elementAlgebra.one else elementAlgebra.zero
|
||||
}.withFeature(UnitFeature)
|
||||
}.withFeature(IsUnit)
|
||||
|
||||
|
||||
/**
|
||||
@ -81,7 +72,7 @@ public fun <T : Any> LinearSpace<T, Ring<T>>.zero(
|
||||
columns: Int,
|
||||
): Matrix<T> = VirtualMatrix(rows, columns) { _, _ ->
|
||||
elementAlgebra.zero
|
||||
}.withFeature(ZeroFeature)
|
||||
}.withFeature(IsZero)
|
||||
|
||||
public class TransposedFeature<out T : Any>(public val original: Matrix<T>) : MatrixFeature
|
||||
|
||||
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2022 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.misc
|
||||
|
||||
import kotlin.jvm.JvmInline
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* An entity that contains a set of features defined by their types
|
||||
*/
|
||||
public interface Featured<F : Any> {
|
||||
public fun <T : F> getFeature(type: FeatureKey<T>): T?
|
||||
}
|
||||
|
||||
public typealias FeatureKey<T> = KClass<out T>
|
||||
|
||||
public interface Feature<F : Feature<F>> {
|
||||
|
||||
/**
|
||||
* A key used for extraction
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public val key: FeatureKey<F>
|
||||
get() = this::class as FeatureKey<F>
|
||||
}
|
||||
|
||||
/**
|
||||
* A container for a set of features
|
||||
*/
|
||||
@JvmInline
|
||||
public value class FeatureSet<F : Feature<F>> private constructor(public val features: Map<FeatureKey<F>, F>) : Featured<F> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : F> getFeature(type: FeatureKey<T>): T? = features[type]?.let { it as T }
|
||||
|
||||
public inline fun <reified T : F> getFeature(): T? = getFeature(T::class)
|
||||
|
||||
public fun <T : F> with(feature: T, type: FeatureKey<F> = feature.key): FeatureSet<F> =
|
||||
FeatureSet(features + (type to feature))
|
||||
|
||||
public fun with(other: FeatureSet<F>): FeatureSet<F> = FeatureSet(features + other.features)
|
||||
|
||||
public fun with(vararg otherFeatures: F): FeatureSet<F> =
|
||||
FeatureSet(features + otherFeatures.associateBy { it.key })
|
||||
|
||||
public fun with(otherFeatures: Iterable<F>): FeatureSet<F> =
|
||||
FeatureSet(features + otherFeatures.associateBy { it.key })
|
||||
|
||||
public operator fun iterator(): Iterator<F> = features.values.iterator()
|
||||
|
||||
override fun toString(): String = features.values.joinToString(prefix = "[ ", postfix = " ]")
|
||||
|
||||
|
||||
public companion object {
|
||||
public fun <F : Feature<F>> of(vararg features: F): FeatureSet<F> = FeatureSet(features.associateBy { it.key })
|
||||
public fun <F : Feature<F>> of(features: Iterable<F>): FeatureSet<F> =
|
||||
FeatureSet(features.associateBy { it.key })
|
||||
}
|
||||
}
|
@ -114,7 +114,7 @@ public interface GroupOpsND<T, out A : GroupOps<T>> : GroupOps<StructureND<T>>,
|
||||
override fun add(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
|
||||
zip(left, right) { aValue, bValue -> add(aValue, bValue) }
|
||||
|
||||
// TODO move to extensions after KEEP-176
|
||||
// TODO implement using context receivers
|
||||
|
||||
/**
|
||||
* Adds an ND structure to an element of it.
|
||||
@ -181,8 +181,6 @@ public interface RingOpsND<T, out A : RingOps<T>> : RingOps<StructureND<T>>, Gro
|
||||
override fun multiply(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
|
||||
zip(left, right) { aValue, bValue -> multiply(aValue, bValue) }
|
||||
|
||||
//TODO move to extensions with context receivers
|
||||
|
||||
/**
|
||||
* Multiplies an ND structure by an element of it.
|
||||
*
|
||||
@ -232,7 +230,6 @@ public interface FieldOpsND<T, out A : Field<T>> :
|
||||
override fun divide(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
|
||||
zip(left, right) { aValue, bValue -> divide(aValue, bValue) }
|
||||
|
||||
//TODO move to extensions after https://github.com/Kotlin/KEEP/blob/master/proposals/context-receivers.md
|
||||
/**
|
||||
* Divides an ND structure by an element of it.
|
||||
*
|
||||
|
@ -5,10 +5,10 @@
|
||||
|
||||
package space.kscience.kmath.nd
|
||||
|
||||
import space.kscience.attributes.Attribute
|
||||
import space.kscience.attributes.AttributeContainer
|
||||
import space.kscience.kmath.PerformancePitfall
|
||||
import space.kscience.kmath.linear.LinearSpace
|
||||
import space.kscience.kmath.misc.Feature
|
||||
import space.kscience.kmath.misc.Featured
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
@ -17,7 +17,7 @@ import kotlin.jvm.JvmName
|
||||
import kotlin.math.abs
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
public interface StructureFeature : Feature<StructureFeature>
|
||||
public interface StructureFeature<T> : Attribute<T>
|
||||
|
||||
/**
|
||||
* Represents n-dimensional structure i.e., multidimensional container of items of the same type and size. The number
|
||||
@ -28,7 +28,7 @@ public interface StructureFeature : Feature<StructureFeature>
|
||||
*
|
||||
* @param T the type of items.
|
||||
*/
|
||||
public interface StructureND<out T> : Featured<StructureFeature>, WithShape {
|
||||
public interface StructureND<out T> : AttributeContainer, WithShape {
|
||||
/**
|
||||
* The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of
|
||||
* this structure.
|
||||
@ -57,12 +57,6 @@ public interface StructureND<out T> : Featured<StructureFeature>, WithShape {
|
||||
@PerformancePitfall
|
||||
public fun elements(): Sequence<Pair<IntArray, T>> = indices.asSequence().map { it to get(it) }
|
||||
|
||||
/**
|
||||
* Feature is some additional structure information that allows to access it special properties or hints.
|
||||
* If the feature is not present, `null` is returned.
|
||||
*/
|
||||
override fun <F : StructureFeature> getFeature(type: KClass<out F>): F? = null
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* Indicates whether some [StructureND] is equal to another one.
|
||||
|
@ -10,7 +10,7 @@ plugins {
|
||||
description = "Symja integration module"
|
||||
|
||||
dependencies {
|
||||
api("org.matheclipse:matheclipse-core:2.0.0-SNAPSHOT") {
|
||||
api("org.matheclipse:matheclipse-core:2.0.0") {
|
||||
// Incorrect transitive dependencies
|
||||
exclude("org.apfloat", "apfloat")
|
||||
exclude("org.hipparchus", "hipparchus-clustering")
|
||||
|
@ -21,6 +21,7 @@ dependencyResolutionManagement {
|
||||
|
||||
include(
|
||||
":test-utils",
|
||||
":attributes-kt",
|
||||
":kmath-memory",
|
||||
":kmath-complex",
|
||||
":kmath-core",
|
||||
|
Loading…
Reference in New Issue
Block a user