From c4b334976acfe4ddb0d0ba713bd653d2ec860d26 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 30 Sep 2018 17:18:04 +0300 Subject: [PATCH] Switch to kotlin 1.3 eap and mpp build --- README.md | 29 ++++++++- build.gradle | 17 +++--- kmath-common/build.gradle | 22 ------- .../kmath/structures/NDArrayFactories.kt | 38 ------------ kmath-core/build.gradle | 58 ++++++++++++++++++ .../kmath/expressions/Expression.kt | 0 .../scientifik/kmath/misc/Cumulative.kt | 0 .../kotlin/scientifik/kmath/misc/Grids.kt | 7 +-- .../scientifik/kmath/operations/Algebra.kt | 0 .../scientifik/kmath/operations/Fields.kt | 0 .../kmath/operations/OptionalOperations.kt | 0 .../kmath/structures/BufferNDField.kt | 3 +- .../kmath/structures/LinearAlgrebra.kt | 61 +++++++++++++------ .../scientifik/kmath/structures/NDArray.kt | 18 +++--- .../scientifik/kmath/structures/NDArrays.kt | 54 ++++++++++++++++ .../expressions/FieldExpressionContextTest.kt | 0 .../scientifik/kmath/misc/CumulativeKtTest.kt | 0 .../kmath/operations/RealFieldTest.kt | 0 .../kmath/structures/ArrayMatrixTest.kt | 8 +-- .../kmath/structures/RealNDFieldTest.kt | 11 ++-- .../kmath/structures/SimpleNDFieldTest.kt | 1 + .../kmath/structures/ArrayBenchmark.kt | 0 .../scientifik/kmath/structures/_NDArrays.kt | 8 +++ .../scientifik/kmath/structures/_NDArrays.kt | 6 +- kmath-jvm/build.gradle | 38 ------------ settings.gradle | 15 ++++- 26 files changed, 234 insertions(+), 160 deletions(-) delete mode 100644 kmath-common/build.gradle delete mode 100644 kmath-common/src/main/kotlin/scientifik/kmath/structures/NDArrayFactories.kt create mode 100644 kmath-core/build.gradle rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/expressions/Expression.kt (100%) rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/misc/Cumulative.kt (100%) rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/misc/Grids.kt (90%) rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/operations/Algebra.kt (100%) rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/operations/Fields.kt (100%) rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/operations/OptionalOperations.kt (100%) rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/structures/BufferNDField.kt (96%) rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/structures/LinearAlgrebra.kt (66%) rename {kmath-common/src/main => kmath-core/src/commonMain}/kotlin/scientifik/kmath/structures/NDArray.kt (96%) create mode 100644 kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDArrays.kt rename {kmath-common/src/test => kmath-core/src/commonTest}/kotlin/scientifik/kmath/expressions/FieldExpressionContextTest.kt (100%) rename {kmath-common/src/test => kmath-core/src/commonTest}/kotlin/scientifik/kmath/misc/CumulativeKtTest.kt (100%) rename {kmath-common/src/test => kmath-core/src/commonTest}/kotlin/scientifik/kmath/operations/RealFieldTest.kt (100%) rename {kmath-jvm/src/test => kmath-core/src/commonTest}/kotlin/scientifik/kmath/structures/ArrayMatrixTest.kt (77%) rename {kmath-jvm/src/test => kmath-core/src/commonTest}/kotlin/scientifik/kmath/structures/RealNDFieldTest.kt (74%) rename {kmath-common/src/test => kmath-core/src/commonTest}/kotlin/scientifik/kmath/structures/SimpleNDFieldTest.kt (85%) rename {kmath-jvm => kmath-core}/src/jmh/kotlin/scietifik/kmath/structures/ArrayBenchmark.kt (100%) create mode 100644 kmath-core/src/jsMain/kotlin/scientifik/kmath/structures/_NDArrays.kt rename kmath-jvm/src/main/kotlin/scientifik/kmath/structures/RealNDArray.kt => kmath-core/src/jvmMain/kotlin/scientifik/kmath/structures/_NDArrays.kt (73%) delete mode 100644 kmath-jvm/build.gradle diff --git a/README.md b/README.md index 8f914d791..d5831b03a 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,33 @@ but worse than optimized native/scipy (mostly due to boxing operations on primit of optimized parts should be better than scipy. ## Releases -The project is currently in pre-release stage. Work builds could be obtained with -[![](https://jitpack.io/v/altavir/kmath.svg)](https://jitpack.io/#altavir/kmath). + +The project is currently in pre-release stage. Nightly builds could be used by adding additional repository to (groovy) gradle config: +```groovy +repositories { + maven { url = "http://npm.mipt.ru:8081/artifactory/gradle-dev" } + mavenCentral() +} +``` +or for kotlin gradle dsl: + +```kotlin +repositories { + maven { setUrl("http://npm.mipt.ru:8081/artifactory/gradle-dev") } + mavenCentral() +} +``` + +Then use regular dependency like +```groovy +compile(group: 'scientifik', name: 'kmath-core-jvm', version: '0.0.1-SNAPSHOT') +``` +or in kotlin +```kotlin +compile(group = "scientifik", name = "kmath-core-jvm", version = "0.0.1-SNAPSHOT") +``` + +Work builds could be obtained with [![](https://jitpack.io/v/altavir/kmath.svg)](https://jitpack.io/#altavir/kmath). ## Contributing The project requires a lot of additional work. Please fill free to contribute in any way and propose new features. \ No newline at end of file diff --git a/build.gradle b/build.gradle index a3af48ee0..655acfe2d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,17 +1,19 @@ buildscript { - ext.kotlin_version = '1.2.71' + ext.kotlin_version = '1.3.0-rc-116' repositories { jcenter() + maven { + url = "http://dl.bintray.com/kotlin/kotlin-eap" + } } + dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+" } } - -allprojects{ - apply plugin: 'maven' +allprojects { apply plugin: 'maven-publish' apply plugin: "com.jfrog.artifactory" @@ -27,13 +29,11 @@ artifactory { repoKey = 'gradle-dev-local' username = "${artifactory_user}" password = "${artifactory_password}" - maven = true - } defaults { - publications 'defaultPublication' - publishBuildInfo = true + publications('jvm', 'kotlinMultiplatform', 'metadata') + publishBuildInfo = false publishArtifacts = true publishPom = true publishIvy = false @@ -44,7 +44,6 @@ artifactory { repoKey = 'gradle-dev' username = "${artifactory_user}" password = "${artifactory_password}" - maven = true } } } \ No newline at end of file diff --git a/kmath-common/build.gradle b/kmath-common/build.gradle deleted file mode 100644 index eecc32818..000000000 --- a/kmath-common/build.gradle +++ /dev/null @@ -1,22 +0,0 @@ -plugins{ - id "kotlin-platform-common" -} - -description = "Platform-independent interfaces for kotlin maths" - -repositories { - mavenCentral() -} - -dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version" - testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version" - testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version" -} - -kotlin { - experimental { - coroutines "enable" - } -} - diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/structures/NDArrayFactories.kt b/kmath-common/src/main/kotlin/scientifik/kmath/structures/NDArrayFactories.kt deleted file mode 100644 index b3e3850e9..000000000 --- a/kmath-common/src/main/kotlin/scientifik/kmath/structures/NDArrayFactories.kt +++ /dev/null @@ -1,38 +0,0 @@ -package scientifik.kmath.structures - -import scientifik.kmath.operations.Field - -/** - * Create a platform-optimized NDArray of doubles - */ -expect fun realNDArray(shape: List, initializer: (List) -> Double = { 0.0 }): NDArray - -fun real2DArray(dim1: Int, dim2: Int, initializer: (Int, Int) -> Double = { _, _ -> 0.0 }): NDArray { - return realNDArray(listOf(dim1, dim2)) { initializer(it[0], it[1]) } -} - -fun real3DArray(dim1: Int, dim2: Int, dim3: Int, initializer: (Int, Int, Int) -> Double = { _, _, _ -> 0.0 }): NDArray { - return realNDArray(listOf(dim1, dim2, dim3)) { initializer(it[0], it[1], it[2]) } -} - - -class SimpleNDField(field: Field, shape: List) : BufferNDField(shape, field) { - override fun createBuffer(capacity: Int, initializer: (Int) -> T): Buffer { - val array = ArrayList(capacity) - (0 until capacity).forEach { - array.add(initializer(it)) - } - - return object : Buffer { - override fun get(index: Int): T = array[index] - - override fun set(index: Int, value: T) { - array[index] = initializer(index) - } - } - } -} - -fun simpleNDArray(field: Field, shape: List, initializer: (List) -> T): NDArray { - return SimpleNDField(field, shape).produce { initializer(it) } -} \ No newline at end of file diff --git a/kmath-core/build.gradle b/kmath-core/build.gradle new file mode 100644 index 000000000..8e0e6ca2e --- /dev/null +++ b/kmath-core/build.gradle @@ -0,0 +1,58 @@ +plugins { + id 'kotlin-multiplatform'// version '1.3.0-rc-116' + id "me.champeau.gradle.jmh" version "0.4.5" +} + +repositories { + maven { url = 'http://dl.bintray.com/kotlin/kotlin-eap' } + mavenCentral() +} + +kotlin { + targets { + fromPreset(presets.jvm, 'jvm') + fromPreset(presets.js, 'js') + // For ARM, preset should be changed to presets.iosArm32 or presets.iosArm64 + // For Linux, preset should be changed to e.g. presets.linuxX64 + // For MacOS, preset should be changed to e.g. presets.macosX64 + //fromPreset(presets.mingwX64, 'mingw') + } + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + commonTest { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-test-common' + implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + } + } + jvmTest { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-test' + implementation 'org.jetbrains.kotlin:kotlin-test-junit' + } + } + jsMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-js' + } + } + jsTest { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-test-js' + } + } +// mingwMain { +// } +// mingwTest { +// } + } +} diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt similarity index 100% rename from kmath-common/src/main/kotlin/scientifik/kmath/expressions/Expression.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/misc/Cumulative.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Cumulative.kt similarity index 100% rename from kmath-common/src/main/kotlin/scientifik/kmath/misc/Cumulative.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Cumulative.kt diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/misc/Grids.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt similarity index 90% rename from kmath-common/src/main/kotlin/scientifik/kmath/misc/Grids.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt index 5ea4bd949..b48afbdcc 100644 --- a/kmath-common/src/main/kotlin/scientifik/kmath/misc/Grids.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt @@ -1,8 +1,5 @@ package scientifik.kmath.misc -import kotlin.coroutines.experimental.buildSequence - - /** * Convert double range to sequence. * @@ -14,14 +11,14 @@ import kotlin.coroutines.experimental.buildSequence fun ClosedFloatingPointRange.toSequence(step: Double): Sequence { return when { step == 0.0 -> error("Zero step in double progression") - step > 0 -> buildSequence { + step > 0 -> sequence { var current = start while (current <= endInclusive) { yield(current) current += step } } - else -> buildSequence { + else -> sequence { var current = endInclusive while (current >= start) { yield(current) diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt similarity index 100% rename from kmath-common/src/main/kotlin/scientifik/kmath/operations/Algebra.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/operations/Fields.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Fields.kt similarity index 100% rename from kmath-common/src/main/kotlin/scientifik/kmath/operations/Fields.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Fields.kt diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt similarity index 100% rename from kmath-common/src/main/kotlin/scientifik/kmath/operations/OptionalOperations.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/structures/BufferNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferNDField.kt similarity index 96% rename from kmath-common/src/main/kotlin/scientifik/kmath/structures/BufferNDField.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferNDField.kt index 5b3ef4c6a..9fe7efe87 100644 --- a/kmath-common/src/main/kotlin/scientifik/kmath/structures/BufferNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferNDField.kt @@ -1,7 +1,6 @@ package scientifik.kmath.structures import scientifik.kmath.operations.Field -import kotlin.coroutines.experimental.buildSequence /** @@ -42,7 +41,7 @@ abstract class BufferNDField(shape: List, field: Field) : NDField( //TODO introduce a fast way to calculate index of the next element? protected fun index(offset: Int): List { - return buildSequence { + return sequence { var current = offset var strideIndex = strides.size - 2 while (strideIndex >= 0) { diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/structures/LinearAlgrebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LinearAlgrebra.kt similarity index 66% rename from kmath-common/src/main/kotlin/scientifik/kmath/structures/LinearAlgrebra.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LinearAlgrebra.kt index 62bad9b75..a5e6f2ce1 100644 --- a/kmath-common/src/main/kotlin/scientifik/kmath/structures/LinearAlgrebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LinearAlgrebra.kt @@ -4,6 +4,7 @@ import scientifik.kmath.operations.DoubleField import scientifik.kmath.operations.Field import scientifik.kmath.operations.Space import scientifik.kmath.operations.SpaceElement +import scientifik.kmath.structures.NDArrays.createSimpleNDFieldFactory /** * The space for linear elements. Supports scalar product alongside with standard linear operations. @@ -18,7 +19,7 @@ abstract class LinearSpace>(val rows: Int, v abstract fun produce(initializer: (Int, Int) -> T): V /** - * Produce new linear space with given dimensions + * Produce new linear space with given dimensions. The space produced could be raised from cache since [LinearSpace] does not have mutable elements */ abstract fun produceSpace(rows: Int, columns: Int): LinearSpace @@ -36,12 +37,12 @@ abstract class LinearSpace>(val rows: Int, v } /** - * Dot product + * Dot product. Throws exception on dimension mismatch */ fun multiply(a: V, b: V): V { if (a.rows != b.columns) { //TODO replace by specific exception - error("Dimension mismatch in vector dot product") + error("Dimension mismatch in linear structure dot product: [${a.rows},${a.columns}]*[${b.rows},${b.columns}]") } return produceSpace(a.rows, b.columns).produce { i, j -> (0..a.columns).asSequence().map { k -> field.multiply(a[i, k], b[k, j]) }.reduce { first, second -> field.add(first, second) } @@ -55,16 +56,25 @@ abstract class LinearSpace>(val rows: Int, v * A matrix-like structure that is not dependent on specific space implementation */ interface LinearStructure { + /** + * Number of rows + */ val rows: Int + /** + * Number of columns + */ val columns: Int + /** + * Get element in row [i] and column [j]. Throws error in case of call ounside structure dimensions + */ operator fun get(i: Int, j: Int): T fun transpose(): LinearStructure { return object : LinearStructure { override val rows: Int = this@LinearStructure.columns override val columns: Int = this@LinearStructure.rows - override fun get(i: Int, j: Int): T = this@LinearStructure.get(j, i) + override fun get(i: Int, j: Int): T = this@LinearStructure[j, i] } } } @@ -78,15 +88,23 @@ interface Vector : LinearStructure { /** - * DoubleArray-based implementation of vector space + * NDArray-based implementation of vector space. By default uses slow [SimpleNDField], but could be overridden with custom [NDField] factory. */ -class ArraySpace(rows: Int, columns: Int, field: Field) : LinearSpace>(rows, columns, field) { +class ArraySpace( + rows: Int, + columns: Int, + field: Field, + val ndFactory: NDFieldFactory = createSimpleNDFieldFactory(field) +) : LinearSpace>(rows, columns, field) { + + val ndField by lazy { + ndFactory(listOf(rows, columns)) + } override fun produce(initializer: (Int, Int) -> T): LinearStructure = ArrayMatrix(this, initializer) - override fun produceSpace(rows: Int, columns: Int): LinearSpace> { - return ArraySpace(rows, columns, field) + return ArraySpace(rows, columns, field, ndFactory) } } @@ -95,14 +113,16 @@ class ArraySpace(rows: Int, columns: Int, field: Field) : LinearSpac */ class ArrayMatrix(override val context: ArraySpace, initializer: (Int, Int) -> T) : LinearStructure, SpaceElement, ArraySpace> { - val list: List> = (0 until rows).map { i -> (0 until columns).map { j -> initializer(i, j) } } + private val array = context.ndField.produce { list -> initializer(list[0], list[1]) } + + //val list: List> = (0 until rows).map { i -> (0 until columns).map { j -> initializer(i, j) } } override val rows: Int get() = context.rows override val columns: Int get() = context.columns override fun get(i: Int, j: Int): T { - return list[i][j] + return array[i, j] } override val self: ArrayMatrix get() = this @@ -117,7 +137,7 @@ class ArrayVector(override val context: ArraySpace, initializer: (In } } - val list: List = (0 until context.rows).map(initializer) + private val array = context.ndField.produce { list -> initializer(list[0]) } override val rows: Int get() = context.rows @@ -125,20 +145,25 @@ class ArrayVector(override val context: ArraySpace, initializer: (In override val columns: Int = 1 override fun get(i: Int, j: Int): T { - return list[i] + return array[i] } override val self: ArrayVector get() = this } -fun vector(size: Int, field: Field, initializer: (Int) -> T) = ArrayVector(ArraySpace(size, 1, field), initializer) -//TODO replace by primitive array version -fun realVector(size: Int, initializer: (Int) -> Double) = vector(size, DoubleField, initializer) +fun vector(size: Int, field: Field, initializer: (Int) -> T) = + ArrayVector(ArraySpace(size, 1, field), initializer) + +fun realVector(size: Int, initializer: (Int) -> Double) = + ArrayVector(ArraySpace(size, 1, DoubleField, realNDFieldFactory), initializer) fun Array.asVector(field: Field) = vector(size, field) { this[it] } -//TODO add inferred field from field element + fun DoubleArray.asVector() = realVector(this.size) { this[it] } -fun matrix(rows: Int, columns: Int, field: Field, initializer: (Int, Int) -> T) = ArrayMatrix(ArraySpace(rows, columns, field), initializer) -fun realMatrix(rows: Int, columns: Int, initializer: (Int, Int) -> Double) = matrix(rows, columns, DoubleField, initializer) \ No newline at end of file +fun matrix(rows: Int, columns: Int, field: Field, initializer: (Int, Int) -> T) = + ArrayMatrix(ArraySpace(rows, columns, field), initializer) + +fun realMatrix(rows: Int, columns: Int, initializer: (Int, Int) -> Double) = + ArrayMatrix(ArraySpace(rows, columns, DoubleField, realNDFieldFactory), initializer) diff --git a/kmath-common/src/main/kotlin/scientifik/kmath/structures/NDArray.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDArray.kt similarity index 96% rename from kmath-common/src/main/kotlin/scientifik/kmath/structures/NDArray.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDArray.kt index 462cd6adb..b1ceed5b1 100644 --- a/kmath-common/src/main/kotlin/scientifik/kmath/structures/NDArray.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDArray.kt @@ -136,7 +136,7 @@ operator fun Function1.invoke(ndArray: NDArray): NDArray = ndArr * Summation operation for [NDArray] and single element */ operator fun NDArray.plus(arg: T): NDArray = transform { _, value -> - with(context.field){ + with(context.field) { arg + value } } @@ -149,8 +149,8 @@ operator fun T.plus(arg: NDArray): NDArray = arg + this /** * Subtraction operation between [NDArray] and single element */ -operator fun NDArray.minus(arg: T): NDArray = transform { _, value -> - with(context.field){ +operator fun NDArray.minus(arg: T): NDArray = transform { _, value -> + with(context.field) { arg - value } } @@ -159,7 +159,7 @@ operator fun NDArray.minus(arg: T): NDArray = transform { _, value -> * Reverse minus operation */ operator fun T.minus(arg: NDArray): NDArray = arg.transform { _, value -> - with(arg.context.field){ + with(arg.context.field) { this@minus - value } } @@ -170,7 +170,7 @@ operator fun T.minus(arg: NDArray): NDArray = arg.transform { _, value * Product operation for [NDArray] and single element */ operator fun NDArray.times(arg: T): NDArray = transform { _, value -> - with(context.field){ + with(context.field) { arg * value } } @@ -183,8 +183,8 @@ operator fun T.times(arg: NDArray): NDArray = arg * this /** * Division operation between [NDArray] and single element */ -operator fun NDArray.div(arg: T): NDArray = transform { _, value -> - with(context.field){ +operator fun NDArray.div(arg: T): NDArray = transform { _, value -> + with(context.field) { arg / value } } @@ -193,8 +193,8 @@ operator fun NDArray.div(arg: T): NDArray = transform { _, value -> * Reverse division operation */ operator fun T.div(arg: NDArray): NDArray = arg.transform { _, value -> - with(arg.context.field){ - this@div/ value + with(arg.context.field) { + this@div / value } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDArrays.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDArrays.kt new file mode 100644 index 000000000..ee5ff0a74 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDArrays.kt @@ -0,0 +1,54 @@ +package scientifik.kmath.structures + +import scientifik.kmath.operations.Field + +typealias NDFieldFactory = (shape: List) -> NDField + +/** + * The factory class for fast platform-dependent implementation of NDField of doubles + */ +expect val realNDFieldFactory: NDFieldFactory + +object NDArrays { + /** + * Create a platform-optimized NDArray of doubles + */ + fun realNDArray(shape: List, initializer: (List) -> Double = { 0.0 }): NDArray { + return realNDFieldFactory(shape).produce(initializer) + } + + fun real1DArray(dim: Int, initializer: (Int) -> Double = { _ -> 0.0 }): NDArray { + return realNDArray(listOf(dim)) { initializer(it[0]) } + } + + fun real2DArray(dim1: Int, dim2: Int, initializer: (Int, Int) -> Double = { _, _ -> 0.0 }): NDArray { + return realNDArray(listOf(dim1, dim2)) { initializer(it[0], it[1]) } + } + + fun real3DArray(dim1: Int, dim2: Int, dim3: Int, initializer: (Int, Int, Int) -> Double = { _, _, _ -> 0.0 }): NDArray { + return realNDArray(listOf(dim1, dim2, dim3)) { initializer(it[0], it[1], it[2]) } + } + + class SimpleNDField(field: Field, shape: List) : BufferNDField(shape, field) { + override fun createBuffer(capacity: Int, initializer: (Int) -> T): Buffer { + val array = ArrayList(capacity) + (0 until capacity).forEach { + array.add(initializer(it)) + } + + return object : Buffer { + override fun get(index: Int): T = array[index] + + override fun set(index: Int, value: T) { + array[index] = initializer(index) + } + } + } + } + + fun createSimpleNDFieldFactory(field: Field): NDFieldFactory = { list -> SimpleNDField(field, list) } + + fun simpleNDArray(field: Field, shape: List, initializer: (List) -> T): NDArray { + return SimpleNDField(field, shape).produce { initializer(it) } + } +} \ No newline at end of file diff --git a/kmath-common/src/test/kotlin/scientifik/kmath/expressions/FieldExpressionContextTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/FieldExpressionContextTest.kt similarity index 100% rename from kmath-common/src/test/kotlin/scientifik/kmath/expressions/FieldExpressionContextTest.kt rename to kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/FieldExpressionContextTest.kt diff --git a/kmath-common/src/test/kotlin/scientifik/kmath/misc/CumulativeKtTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/CumulativeKtTest.kt similarity index 100% rename from kmath-common/src/test/kotlin/scientifik/kmath/misc/CumulativeKtTest.kt rename to kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/CumulativeKtTest.kt diff --git a/kmath-common/src/test/kotlin/scientifik/kmath/operations/RealFieldTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/RealFieldTest.kt similarity index 100% rename from kmath-common/src/test/kotlin/scientifik/kmath/operations/RealFieldTest.kt rename to kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/RealFieldTest.kt diff --git a/kmath-jvm/src/test/kotlin/scientifik/kmath/structures/ArrayMatrixTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/ArrayMatrixTest.kt similarity index 77% rename from kmath-jvm/src/test/kotlin/scientifik/kmath/structures/ArrayMatrixTest.kt rename to kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/ArrayMatrixTest.kt index 70fd8a6a9..10d383a22 100644 --- a/kmath-jvm/src/test/kotlin/scientifik/kmath/structures/ArrayMatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/ArrayMatrixTest.kt @@ -1,7 +1,7 @@ package scientifik.kmath.structures -import org.junit.Assert.assertEquals -import org.junit.Test +import kotlin.test.Test +import kotlin.test.assertEquals class ArrayMatrixTest { @@ -10,7 +10,7 @@ class ArrayMatrixTest { val vector1 = realVector(5) { it.toDouble() } val vector2 = realVector(5) { 5 - it.toDouble() } val sum = vector1 + vector2 - assertEquals(5.0, sum[2, 0], 0.1) + assertEquals(5.0, sum[2, 0]) } @Test @@ -21,6 +21,6 @@ class ArrayMatrixTest { vector1 dot (vector2.transpose()) } - assertEquals(10.0, product[1, 0], 0.1) + assertEquals(10.0, product[1, 0]) } } \ No newline at end of file diff --git a/kmath-jvm/src/test/kotlin/scientifik/kmath/structures/RealNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/RealNDFieldTest.kt similarity index 74% rename from kmath-jvm/src/test/kotlin/scientifik/kmath/structures/RealNDFieldTest.kt rename to kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/RealNDFieldTest.kt index 9bed502f9..329f13189 100644 --- a/kmath-jvm/src/test/kotlin/scientifik/kmath/structures/RealNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/RealNDFieldTest.kt @@ -1,8 +1,9 @@ package scientifik.kmath.structures -import org.junit.Assert.assertEquals +import scientifik.kmath.structures.NDArrays.real2DArray import kotlin.math.pow import kotlin.test.Test +import kotlin.test.assertEquals class RealNDFieldTest { val array1 = real2DArray(3, 3) { i, j -> (i + j).toDouble() } @@ -11,13 +12,13 @@ class RealNDFieldTest { @Test fun testSum() { val sum = array1 + array2 - assertEquals(4.0, sum[2, 2], 0.1) + assertEquals(4.0, sum[2, 2]) } @Test fun testProduct() { val product = array1 * array2 - assertEquals(0.0, product[2, 2], 0.1) + assertEquals(0.0, product[2, 2]) } @Test @@ -28,7 +29,7 @@ class RealNDFieldTest { for (i in 0..2) { for (j in 0..2) { val expected = (i * 10 + j).toDouble() - assertEquals("Error at index [$i, $j]", expected, array[i, j], 0.1) + assertEquals(expected, array[i, j],"Error at index [$i, $j]") } } } @@ -37,6 +38,6 @@ class RealNDFieldTest { fun testExternalFunction() { val function: (Double) -> Double = { x -> x.pow(2) + 2 * x + 1 } val result = function(array1) + 1.0 - assertEquals(10.0, result[1,1],0.01) + assertEquals(10.0, result[1,1]) } } diff --git a/kmath-common/src/test/kotlin/scientifik/kmath/structures/SimpleNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/SimpleNDFieldTest.kt similarity index 85% rename from kmath-common/src/test/kotlin/scientifik/kmath/structures/SimpleNDFieldTest.kt rename to kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/SimpleNDFieldTest.kt index 5a4317251..21431dad5 100644 --- a/kmath-common/src/test/kotlin/scientifik/kmath/structures/SimpleNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/SimpleNDFieldTest.kt @@ -1,6 +1,7 @@ package scientifik.kmath.structures import scientifik.kmath.operations.DoubleField +import scientifik.kmath.structures.NDArrays.simpleNDArray import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-jvm/src/jmh/kotlin/scietifik/kmath/structures/ArrayBenchmark.kt b/kmath-core/src/jmh/kotlin/scietifik/kmath/structures/ArrayBenchmark.kt similarity index 100% rename from kmath-jvm/src/jmh/kotlin/scietifik/kmath/structures/ArrayBenchmark.kt rename to kmath-core/src/jmh/kotlin/scietifik/kmath/structures/ArrayBenchmark.kt diff --git a/kmath-core/src/jsMain/kotlin/scientifik/kmath/structures/_NDArrays.kt b/kmath-core/src/jsMain/kotlin/scientifik/kmath/structures/_NDArrays.kt new file mode 100644 index 000000000..29e64a575 --- /dev/null +++ b/kmath-core/src/jsMain/kotlin/scientifik/kmath/structures/_NDArrays.kt @@ -0,0 +1,8 @@ +package scientifik.kmath.structures + +import scientifik.kmath.operations.DoubleField + +/** + * Using boxing implementation for js + */ +actual val realNDFieldFactory: NDFieldFactory = NDArrays.createSimpleNDFieldFactory(DoubleField) \ No newline at end of file diff --git a/kmath-jvm/src/main/kotlin/scientifik/kmath/structures/RealNDArray.kt b/kmath-core/src/jvmMain/kotlin/scientifik/kmath/structures/_NDArrays.kt similarity index 73% rename from kmath-jvm/src/main/kotlin/scientifik/kmath/structures/RealNDArray.kt rename to kmath-core/src/jvmMain/kotlin/scientifik/kmath/structures/_NDArrays.kt index 8099e8700..c46d4210a 100644 --- a/kmath-jvm/src/main/kotlin/scientifik/kmath/structures/RealNDArray.kt +++ b/kmath-core/src/jvmMain/kotlin/scientifik/kmath/structures/_NDArrays.kt @@ -17,8 +17,4 @@ private class RealNDField(shape: List) : BufferNDField(shape, Doubl } } -actual fun realNDArray(shape: List, initializer: (List) -> Double): NDArray { - //TODO create a cache for fields to save time generating strides? - - return RealNDField(shape).produce { initializer(it) } -} \ No newline at end of file +actual val realNDFieldFactory: NDFieldFactory = { shape -> RealNDField(shape) } \ No newline at end of file diff --git a/kmath-jvm/build.gradle b/kmath-jvm/build.gradle deleted file mode 100644 index b8952a379..000000000 --- a/kmath-jvm/build.gradle +++ /dev/null @@ -1,38 +0,0 @@ -plugins{ - id "kotlin-platform-jvm" - id "me.champeau.gradle.jmh" version "0.4.5" -} - -repositories { - mavenCentral() -} - -dependencies { - expectedBy project(":kmath-common") - compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - testCompile "junit:junit:4.12" - testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" - testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" -} - -compileKotlin { - kotlinOptions.jvmTarget = "1.8" -} -compileTestKotlin { - kotlinOptions.jvmTarget = "1.8" -} -sourceCompatibility = "1.8" - -kotlin { - experimental { - coroutines "enable" - } -} - -publishing { - publications { - defaultPublication(MavenPublication) { - from components.java - } - } -} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 9dce0ac08..03760221a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,13 @@ -rootProject.name = 'kmath' -include 'kmath-common' -include 'kmath-jvm' +pluginManagement { + repositories { + maven { url = 'http://dl.bintray.com/kotlin/kotlin-eap' } + mavenCentral() + maven { url = 'https://plugins.gradle.org/m2/' } + } +} + +enableFeaturePreview('GRADLE_METADATA') + +rootProject.name = 'kmath' +include ':kmath-core'