From 388d016fdfd2efe7d1156c1738b179826b9f123f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 31 Jan 2019 18:19:02 +0300 Subject: [PATCH] Specialized 1d and 2d NDStructures --- build.gradle.kts | 22 ++++- kmath-core/build.gradle.kts | 7 +- .../kotlin/scientifik/kmath/linear/Matrix.kt | 4 +- .../kmath/structures/NDStructure.kt | 4 +- .../kmath/structures/SpecializedStructures.kt | 88 +++++++++++++++++++ 5 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/SpecializedStructures.kt diff --git a/build.gradle.kts b/build.gradle.kts index 6f0478fc2..06c37d2a3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension + buildscript { val kotlinVersion: String by rootProject.extra("1.3.20") val ioVersion: String by rootProject.extra("0.1.2") @@ -27,11 +29,27 @@ allprojects { version = "0.0.3-dev-4" repositories { - maven("https://dl.bintray.com/kotlin/kotlin-eap") + //maven("https://dl.bintray.com/kotlin/kotlin-eap") jcenter() } + + extensions.findByType()?.apply { + jvm { + compilations.all { + kotlinOptions { + jvmTarget = "1.8" + } + } + } + targets.all { + sourceSets.all { + languageSettings.progressiveMode = true + languageSettings.enableLanguageFeature("+InlineClasses") + } + } + } } if (file("artifactory.gradle").exists()) { apply(from = "artifactory.gradle") -} \ No newline at end of file +} diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 2e753f624..43059db0e 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { kotlin("multiplatform") } @@ -8,13 +10,16 @@ kotlin { compilations.all { kotlinOptions { jvmTarget = "1.8" - freeCompilerArgs += "-progressive" } } } js() sourceSets { + all { + languageSettings.progressiveMode = true + } + val commonMain by getting { dependencies { api(kotlin("stdlib")) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/Matrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/Matrix.kt index 533e77d61..7ec3a95f4 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/Matrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/Matrix.kt @@ -110,7 +110,7 @@ interface GenericMatrixContext> : MatrixContext { /** * Specialized 2-d structure */ -interface Matrix : NDStructure { +interface Matrix : Structure2D { val rowNum: Int val colNum: Int @@ -124,8 +124,6 @@ interface Matrix : NDStructure { */ fun suggestFeature(vararg features: MatrixFeature): Matrix - operator fun get(i: Int, j: Int): T - override fun get(index: IntArray): T = get(index[0], index[1]) override val shape: IntArray get() = intArrayOf(rowNum, colNum) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt index 4c437bf88..5f16f0444 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt @@ -16,7 +16,9 @@ interface NDStructure { fun equals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean { return when { st1 === st2 -> true - st1 is BufferNDStructure<*> && st2 is BufferNDStructure<*> && st1.strides == st2.strides -> st1.buffer.contentEquals(st2.buffer) + st1 is BufferNDStructure<*> && st2 is BufferNDStructure<*> && st1.strides == st2.strides -> st1.buffer.contentEquals( + st2.buffer + ) else -> st1.elements().all { (index, value) -> value == st2[index] } } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/SpecializedStructures.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/SpecializedStructures.kt new file mode 100644 index 000000000..b0373288b --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/SpecializedStructures.kt @@ -0,0 +1,88 @@ +package scientifik.kmath.structures + +/** + * A structure that is guaranteed to be one-dimensional + */ +interface Structure1D : NDStructure, Buffer { + override val dimension: Int get() = 1 + + override fun get(index: IntArray): T { + if (index.size != 1) error("Index dimension mismatch. Expected 1 but found ${index.size}") + return get(index[0]) + } + + override fun iterator(): Iterator = (0 until size).asSequence().map { get(it) }.iterator() +} + +/** + * A 1D wrapper for nd-structure + */ +private inline class Structure1DWrapper(val structure: NDStructure) : Structure1D { + + override val shape: IntArray get() = structure.shape + override val size: Int get() = structure.shape[0] + + override fun get(index: Int): T = structure[index] + + override fun elements(): Sequence> = structure.elements() +} + +/** + * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch + */ +fun NDStructure.as1D(): Structure1D = if (shape.size == 1) { + Structure1DWrapper(this) +} else { + error("Can't create 1d-structure from ${shape.size}d-structure") +} + +/** + * A structure wrapper for buffer + */ +private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D { + override val shape: IntArray get() = intArrayOf(buffer.size) + + override val size: Int get() = buffer.size + + override fun elements(): Sequence> = + asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + + override fun get(index: Int): T = buffer.get(index) +} + +/** + * Represent this buffer as 1D structure + */ +fun Buffer.asND(): Structure1D = Buffer1DWrapper(this) + +/** + * A structure that is guaranteed to be two-dimensional + */ +interface Structure2D : NDStructure { + operator fun get(i: Int, j: Int): T + + override fun get(index: IntArray): T { + if (index.size != 2) error("Index dimension mismatch. Expected 2 but found ${index.size}") + return get(index[0], index[1]) + } +} + +/** + * A 2D wrapper for nd-structure + */ +private inline class Structure2DWrapper(val structure: NDStructure) : Structure2D { + override fun get(i: Int, j: Int): T = structure[i, j] + + override val shape: IntArray get() = structure.shape + + override fun elements(): Sequence> = structure.elements() +} + +/** + * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch + */ +fun NDStructure.as2D(): Structure2D = if (shape.size == 2) { + Structure2DWrapper(this) +} else { + error("Can't create 2d-structure from ${shape.size}d-structure") +} \ No newline at end of file