Dimensions for JS

This commit is contained in:
Alexander Nozik 2020-04-27 15:43:03 +03:00
parent fbe7363cde
commit 30730f1051
7 changed files with 74 additions and 29 deletions

View File

@ -14,6 +14,7 @@ fun DMatrixContext<Double, RealField>.simple() {
m1.transpose() + m2
}
object D5 : Dimension {
override val dim: UInt = 5u
}

View File

@ -7,8 +7,13 @@ description = "A proof of concept module for adding typ-safe dimensions to struc
kotlin.sourceSets {
commonMain {
dependencies {
implementation(kotlin("reflect"))
api(project(":kmath-core"))
}
}
jvmMain{
dependencies{
api(kotlin("reflect"))
}
}
}

View File

@ -1,37 +1,35 @@
package scientifik.kmath.dimensions
import kotlin.reflect.KClass
/**
* An interface which is not used in runtime. Designates a size of some structure.
* All descendants should be singleton objects.
* An abstract class which is not used in runtime. Designates a size of some structure.
* Could be replaced later by fully inline constructs
*/
interface Dimension {
val dim: UInt
companion object {
@Suppress("NOTHING_TO_INLINE")
inline fun of(dim: UInt): Dimension {
return when (dim) {
1u -> D1
2u -> D2
3u -> D3
else -> object : Dimension {
override val dim: UInt = dim
}
}
}
}
}
expect inline fun <reified D : Dimension> Dimension.Companion.dim(): UInt
fun <D : Dimension> KClass<D>.dim(): UInt = Dimension.resolve(this).dim
expect fun <D : Dimension> Dimension.Companion.resolve(type: KClass<D>): D
expect fun Dimension.Companion.of(dim: UInt): Dimension
inline fun <reified D : Dimension> Dimension.Companion.dim(): UInt = D::class.dim()
object D1 : Dimension {
override val dim: UInt = 1u
override val dim: UInt get() = 1U
}
object D2 : Dimension {
override val dim: UInt = 2u
override val dim: UInt get() = 2U
}
object D3 : Dimension {
override val dim: UInt = 3u
override val dim: UInt get() = 31U
}

View File

@ -29,7 +29,7 @@ interface DMatrix<T, R : Dimension, C : Dimension> : Structure2D<T> {
/**
* The same as [coerce] but without dimension checks. Use with caution
*/
inline fun <T, reified R : Dimension, reified C : Dimension> coerceUnsafe(structure: Structure2D<T>): DMatrix<T, R, C> {
fun <T, R : Dimension, C : Dimension> coerceUnsafe(structure: Structure2D<T>): DMatrix<T, R, C> {
return DMatrixWrapper(structure)
}
}
@ -57,7 +57,7 @@ interface DPoint<T, D : Dimension> : Point<T> {
return DPointWrapper(point)
}
inline fun <T, reified D : Dimension> coerceUnsafe(point: Point<T>): DPoint<T, D> {
fun <T, D : Dimension> coerceUnsafe(point: Point<T>): DPoint<T, D> {
return DPointWrapper(point)
}
}
@ -81,8 +81,15 @@ inline class DPointWrapper<T, D : Dimension>(val point: Point<T>) :
*/
inline class DMatrixContext<T : Any, Ri : Ring<T>>(val context: GenericMatrixContext<T, Ri>) {
inline fun <reified R : Dimension, reified C : Dimension> Matrix<T>.coerce(): DMatrix<T, C, R> =
DMatrix.coerceUnsafe(this)
inline fun <reified R : Dimension, reified C : Dimension> Matrix<T>.coerce(): DMatrix<T, R, C> {
if (rowNum != Dimension.dim<R>().toInt()) {
error("Row number mismatch: expected ${Dimension.dim<R>()} but found $rowNum")
}
if (colNum != Dimension.dim<C>().toInt()) {
error("Column number mismatch: expected ${Dimension.dim<C>()} but found $colNum")
}
return DMatrix.coerceUnsafe(this)
}
/**
* Produce a matrix with this context and given dimensions
@ -90,7 +97,7 @@ inline class DMatrixContext<T : Any, Ri : Ring<T>>(val context: GenericMatrixCon
inline fun <reified R : Dimension, reified C : Dimension> produce(noinline initializer: (i: Int, j: Int) -> T): DMatrix<T, R, C> {
val rows = Dimension.dim<R>()
val cols = Dimension.dim<C>()
return context.produce(rows.toInt(), cols.toInt(), initializer).coerce()
return context.produce(rows.toInt(), cols.toInt(), initializer).coerce<R,C>()
}
inline fun <reified D : Dimension> point(noinline initializer: (Int) -> T): DPoint<T, D> {

View File

@ -1,5 +1,8 @@
package scientifik.kmath.dimensions
package scientifik.dimensions
import scientifik.kmath.dimensions.D2
import scientifik.kmath.dimensions.D3
import scientifik.kmath.dimensions.DMatrixContext
import kotlin.test.Test

View File

@ -1,5 +1,22 @@
package scientifik.kmath.dimensions
actual inline fun <reified D : Dimension> Dimension.Companion.dim(): UInt {
TODO("KClass::objectInstance does not work")
import kotlin.reflect.KClass
private val dimensionMap = hashMapOf<UInt, Dimension>(
1u to D1,
2u to D2,
3u to D3
)
@Suppress("UNCHECKED_CAST")
actual fun <D : Dimension> Dimension.Companion.resolve(type: KClass<D>): D {
return dimensionMap.entries.find { it.value::class == type }?.value as? D ?: error("Can't resolve dimension $type")
}
actual fun Dimension.Companion.of(dim: UInt): Dimension {
return dimensionMap.getOrPut(dim) {
object : Dimension {
override val dim: UInt get() = dim
}
}
}

View File

@ -1,4 +1,18 @@
package scientifik.kmath.dimensions
actual inline fun <reified D : Dimension> Dimension.Companion.dim(): UInt =
D::class.objectInstance?.dim ?: error("Dimension object must be a singleton")
import kotlin.reflect.KClass
actual fun <D:Dimension> Dimension.Companion.resolve(type: KClass<D>): D{
return type.objectInstance ?: error("No object instance for dimension class")
}
actual fun Dimension.Companion.of(dim: UInt): Dimension{
return when(dim){
1u -> D1
2u -> D2
3u -> D3
else -> object : Dimension {
override val dim: UInt get() = dim
}
}
}