Switch to kotlin 1.3 eap and mpp build
This commit is contained in:
parent
38c7f4382a
commit
c4b334976a
29
README.md
29
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.
|
of optimized parts should be better than scipy.
|
||||||
|
|
||||||
## Releases
|
## 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
|
## Contributing
|
||||||
The project requires a lot of additional work. Please fill free to contribute in any way and propose new features.
|
The project requires a lot of additional work. Please fill free to contribute in any way and propose new features.
|
17
build.gradle
17
build.gradle
@ -1,17 +1,19 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.2.71'
|
ext.kotlin_version = '1.3.0-rc-116'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url = "http://dl.bintray.com/kotlin/kotlin-eap"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"
|
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
allprojects {
|
||||||
allprojects{
|
|
||||||
apply plugin: 'maven'
|
|
||||||
apply plugin: 'maven-publish'
|
apply plugin: 'maven-publish'
|
||||||
apply plugin: "com.jfrog.artifactory"
|
apply plugin: "com.jfrog.artifactory"
|
||||||
|
|
||||||
@ -27,13 +29,11 @@ artifactory {
|
|||||||
repoKey = 'gradle-dev-local'
|
repoKey = 'gradle-dev-local'
|
||||||
username = "${artifactory_user}"
|
username = "${artifactory_user}"
|
||||||
password = "${artifactory_password}"
|
password = "${artifactory_password}"
|
||||||
maven = true
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults {
|
defaults {
|
||||||
publications 'defaultPublication'
|
publications('jvm', 'kotlinMultiplatform', 'metadata')
|
||||||
publishBuildInfo = true
|
publishBuildInfo = false
|
||||||
publishArtifacts = true
|
publishArtifacts = true
|
||||||
publishPom = true
|
publishPom = true
|
||||||
publishIvy = false
|
publishIvy = false
|
||||||
@ -44,7 +44,6 @@ artifactory {
|
|||||||
repoKey = 'gradle-dev'
|
repoKey = 'gradle-dev'
|
||||||
username = "${artifactory_user}"
|
username = "${artifactory_user}"
|
||||||
password = "${artifactory_password}"
|
password = "${artifactory_password}"
|
||||||
maven = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<Int>, initializer: (List<Int>) -> Double = { 0.0 }): NDArray<Double>
|
|
||||||
|
|
||||||
fun real2DArray(dim1: Int, dim2: Int, initializer: (Int, Int) -> Double = { _, _ -> 0.0 }): NDArray<Double> {
|
|
||||||
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<Double> {
|
|
||||||
return realNDArray(listOf(dim1, dim2, dim3)) { initializer(it[0], it[1], it[2]) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleNDField<T: Any>(field: Field<T>, shape: List<Int>) : BufferNDField<T>(shape, field) {
|
|
||||||
override fun createBuffer(capacity: Int, initializer: (Int) -> T): Buffer<T> {
|
|
||||||
val array = ArrayList<T>(capacity)
|
|
||||||
(0 until capacity).forEach {
|
|
||||||
array.add(initializer(it))
|
|
||||||
}
|
|
||||||
|
|
||||||
return object : Buffer<T> {
|
|
||||||
override fun get(index: Int): T = array[index]
|
|
||||||
|
|
||||||
override fun set(index: Int, value: T) {
|
|
||||||
array[index] = initializer(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T: Any> simpleNDArray(field: Field<T>, shape: List<Int>, initializer: (List<Int>) -> T): NDArray<T> {
|
|
||||||
return SimpleNDField(field, shape).produce { initializer(it) }
|
|
||||||
}
|
|
58
kmath-core/build.gradle
Normal file
58
kmath-core/build.gradle
Normal file
@ -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 {
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,5 @@
|
|||||||
package scientifik.kmath.misc
|
package scientifik.kmath.misc
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.buildSequence
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert double range to sequence.
|
* Convert double range to sequence.
|
||||||
*
|
*
|
||||||
@ -14,14 +11,14 @@ import kotlin.coroutines.experimental.buildSequence
|
|||||||
fun ClosedFloatingPointRange<Double>.toSequence(step: Double): Sequence<Double> {
|
fun ClosedFloatingPointRange<Double>.toSequence(step: Double): Sequence<Double> {
|
||||||
return when {
|
return when {
|
||||||
step == 0.0 -> error("Zero step in double progression")
|
step == 0.0 -> error("Zero step in double progression")
|
||||||
step > 0 -> buildSequence {
|
step > 0 -> sequence {
|
||||||
var current = start
|
var current = start
|
||||||
while (current <= endInclusive) {
|
while (current <= endInclusive) {
|
||||||
yield(current)
|
yield(current)
|
||||||
current += step
|
current += step
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> buildSequence {
|
else -> sequence {
|
||||||
var current = endInclusive
|
var current = endInclusive
|
||||||
while (current >= start) {
|
while (current >= start) {
|
||||||
yield(current)
|
yield(current)
|
@ -1,7 +1,6 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
import scientifik.kmath.operations.Field
|
import scientifik.kmath.operations.Field
|
||||||
import kotlin.coroutines.experimental.buildSequence
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +41,7 @@ abstract class BufferNDField<T>(shape: List<Int>, field: Field<T>) : NDField<T>(
|
|||||||
|
|
||||||
//TODO introduce a fast way to calculate index of the next element?
|
//TODO introduce a fast way to calculate index of the next element?
|
||||||
protected fun index(offset: Int): List<Int> {
|
protected fun index(offset: Int): List<Int> {
|
||||||
return buildSequence {
|
return sequence {
|
||||||
var current = offset
|
var current = offset
|
||||||
var strideIndex = strides.size - 2
|
var strideIndex = strides.size - 2
|
||||||
while (strideIndex >= 0) {
|
while (strideIndex >= 0) {
|
@ -4,6 +4,7 @@ import scientifik.kmath.operations.DoubleField
|
|||||||
import scientifik.kmath.operations.Field
|
import scientifik.kmath.operations.Field
|
||||||
import scientifik.kmath.operations.Space
|
import scientifik.kmath.operations.Space
|
||||||
import scientifik.kmath.operations.SpaceElement
|
import scientifik.kmath.operations.SpaceElement
|
||||||
|
import scientifik.kmath.structures.NDArrays.createSimpleNDFieldFactory
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The space for linear elements. Supports scalar product alongside with standard linear operations.
|
* The space for linear elements. Supports scalar product alongside with standard linear operations.
|
||||||
@ -18,7 +19,7 @@ abstract class LinearSpace<T : Any, V : LinearStructure<out T>>(val rows: Int, v
|
|||||||
abstract fun produce(initializer: (Int, Int) -> T): 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<T, V>
|
abstract fun produceSpace(rows: Int, columns: Int): LinearSpace<T, V>
|
||||||
|
|
||||||
@ -36,12 +37,12 @@ abstract class LinearSpace<T : Any, V : LinearStructure<out T>>(val rows: Int, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dot product
|
* Dot product. Throws exception on dimension mismatch
|
||||||
*/
|
*/
|
||||||
fun multiply(a: V, b: V): V {
|
fun multiply(a: V, b: V): V {
|
||||||
if (a.rows != b.columns) {
|
if (a.rows != b.columns) {
|
||||||
//TODO replace by specific exception
|
//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 ->
|
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) }
|
(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<T : Any, V : LinearStructure<out T>>(val rows: Int, v
|
|||||||
* A matrix-like structure that is not dependent on specific space implementation
|
* A matrix-like structure that is not dependent on specific space implementation
|
||||||
*/
|
*/
|
||||||
interface LinearStructure<T : Any> {
|
interface LinearStructure<T : Any> {
|
||||||
|
/**
|
||||||
|
* Number of rows
|
||||||
|
*/
|
||||||
val rows: Int
|
val rows: Int
|
||||||
|
/**
|
||||||
|
* Number of columns
|
||||||
|
*/
|
||||||
val columns: Int
|
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
|
operator fun get(i: Int, j: Int): T
|
||||||
|
|
||||||
fun transpose(): LinearStructure<T> {
|
fun transpose(): LinearStructure<T> {
|
||||||
return object : LinearStructure<T> {
|
return object : LinearStructure<T> {
|
||||||
override val rows: Int = this@LinearStructure.columns
|
override val rows: Int = this@LinearStructure.columns
|
||||||
override val columns: Int = this@LinearStructure.rows
|
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<T : Any> : LinearStructure<T> {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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<T : Any>(rows: Int, columns: Int, field: Field<T>) : LinearSpace<T, LinearStructure<out T>>(rows, columns, field) {
|
class ArraySpace<T : Any>(
|
||||||
|
rows: Int,
|
||||||
|
columns: Int,
|
||||||
|
field: Field<T>,
|
||||||
|
val ndFactory: NDFieldFactory<T> = createSimpleNDFieldFactory(field)
|
||||||
|
) : LinearSpace<T, LinearStructure<out T>>(rows, columns, field) {
|
||||||
|
|
||||||
|
val ndField by lazy {
|
||||||
|
ndFactory(listOf(rows, columns))
|
||||||
|
}
|
||||||
|
|
||||||
override fun produce(initializer: (Int, Int) -> T): LinearStructure<T> = ArrayMatrix<T>(this, initializer)
|
override fun produce(initializer: (Int, Int) -> T): LinearStructure<T> = ArrayMatrix<T>(this, initializer)
|
||||||
|
|
||||||
|
|
||||||
override fun produceSpace(rows: Int, columns: Int): LinearSpace<T, LinearStructure<out T>> {
|
override fun produceSpace(rows: Int, columns: Int): LinearSpace<T, LinearStructure<out T>> {
|
||||||
return ArraySpace(rows, columns, field)
|
return ArraySpace(rows, columns, field, ndFactory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,14 +113,16 @@ class ArraySpace<T : Any>(rows: Int, columns: Int, field: Field<T>) : LinearSpac
|
|||||||
*/
|
*/
|
||||||
class ArrayMatrix<T : Any>(override val context: ArraySpace<T>, initializer: (Int, Int) -> T) : LinearStructure<T>, SpaceElement<LinearStructure<out T>, ArraySpace<T>> {
|
class ArrayMatrix<T : Any>(override val context: ArraySpace<T>, initializer: (Int, Int) -> T) : LinearStructure<T>, SpaceElement<LinearStructure<out T>, ArraySpace<T>> {
|
||||||
|
|
||||||
val list: List<List<T>> = (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<List<T>> = (0 until rows).map { i -> (0 until columns).map { j -> initializer(i, j) } }
|
||||||
|
|
||||||
override val rows: Int get() = context.rows
|
override val rows: Int get() = context.rows
|
||||||
|
|
||||||
override val columns: Int get() = context.columns
|
override val columns: Int get() = context.columns
|
||||||
|
|
||||||
override fun get(i: Int, j: Int): T {
|
override fun get(i: Int, j: Int): T {
|
||||||
return list[i][j]
|
return array[i, j]
|
||||||
}
|
}
|
||||||
|
|
||||||
override val self: ArrayMatrix<T> get() = this
|
override val self: ArrayMatrix<T> get() = this
|
||||||
@ -117,7 +137,7 @@ class ArrayVector<T : Any>(override val context: ArraySpace<T>, initializer: (In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val list: List<T> = (0 until context.rows).map(initializer)
|
private val array = context.ndField.produce { list -> initializer(list[0]) }
|
||||||
|
|
||||||
|
|
||||||
override val rows: Int get() = context.rows
|
override val rows: Int get() = context.rows
|
||||||
@ -125,20 +145,25 @@ class ArrayVector<T : Any>(override val context: ArraySpace<T>, initializer: (In
|
|||||||
override val columns: Int = 1
|
override val columns: Int = 1
|
||||||
|
|
||||||
override fun get(i: Int, j: Int): T {
|
override fun get(i: Int, j: Int): T {
|
||||||
return list[i]
|
return array[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
override val self: ArrayVector<T> get() = this
|
override val self: ArrayVector<T> get() = this
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> vector(size: Int, field: Field<T>, initializer: (Int) -> T) = ArrayVector(ArraySpace(size, 1, field), initializer)
|
fun <T : Any> vector(size: Int, field: Field<T>, initializer: (Int) -> T) =
|
||||||
//TODO replace by primitive array version
|
ArrayVector(ArraySpace(size, 1, field), initializer)
|
||||||
fun realVector(size: Int, initializer: (Int) -> Double) = vector(size, DoubleField, initializer)
|
|
||||||
|
fun realVector(size: Int, initializer: (Int) -> Double) =
|
||||||
|
ArrayVector(ArraySpace(size, 1, DoubleField, realNDFieldFactory), initializer)
|
||||||
|
|
||||||
fun <T : Any> Array<T>.asVector(field: Field<T>) = vector(size, field) { this[it] }
|
fun <T : Any> Array<T>.asVector(field: Field<T>) = vector(size, field) { this[it] }
|
||||||
//TODO add inferred field from field element
|
|
||||||
fun DoubleArray.asVector() = realVector(this.size) { this[it] }
|
fun DoubleArray.asVector() = realVector(this.size) { this[it] }
|
||||||
|
|
||||||
fun <T : Any> matrix(rows: Int, columns: Int, field: Field<T>, initializer: (Int, Int) -> T) = ArrayMatrix<T>(ArraySpace(rows, columns, field), initializer)
|
fun <T : Any> matrix(rows: Int, columns: Int, field: Field<T>, initializer: (Int, Int) -> T) =
|
||||||
fun realMatrix(rows: Int, columns: Int, initializer: (Int, Int) -> Double) = matrix(rows, columns, DoubleField, initializer)
|
ArrayMatrix(ArraySpace(rows, columns, field), initializer)
|
||||||
|
|
||||||
|
fun realMatrix(rows: Int, columns: Int, initializer: (Int, Int) -> Double) =
|
||||||
|
ArrayMatrix(ArraySpace(rows, columns, DoubleField, realNDFieldFactory), initializer)
|
@ -136,7 +136,7 @@ operator fun <T> Function1<T, T>.invoke(ndArray: NDArray<T>): NDArray<T> = ndArr
|
|||||||
* Summation operation for [NDArray] and single element
|
* Summation operation for [NDArray] and single element
|
||||||
*/
|
*/
|
||||||
operator fun <T> NDArray<T>.plus(arg: T): NDArray<T> = transform { _, value ->
|
operator fun <T> NDArray<T>.plus(arg: T): NDArray<T> = transform { _, value ->
|
||||||
with(context.field){
|
with(context.field) {
|
||||||
arg + value
|
arg + value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ operator fun <T> T.plus(arg: NDArray<T>): NDArray<T> = arg + this
|
|||||||
* Subtraction operation between [NDArray] and single element
|
* Subtraction operation between [NDArray] and single element
|
||||||
*/
|
*/
|
||||||
operator fun <T> NDArray<T>.minus(arg: T): NDArray<T> = transform { _, value ->
|
operator fun <T> NDArray<T>.minus(arg: T): NDArray<T> = transform { _, value ->
|
||||||
with(context.field){
|
with(context.field) {
|
||||||
arg - value
|
arg - value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,7 +159,7 @@ operator fun <T> NDArray<T>.minus(arg: T): NDArray<T> = transform { _, value ->
|
|||||||
* Reverse minus operation
|
* Reverse minus operation
|
||||||
*/
|
*/
|
||||||
operator fun <T> T.minus(arg: NDArray<T>): NDArray<T> = arg.transform { _, value ->
|
operator fun <T> T.minus(arg: NDArray<T>): NDArray<T> = arg.transform { _, value ->
|
||||||
with(arg.context.field){
|
with(arg.context.field) {
|
||||||
this@minus - value
|
this@minus - value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ operator fun <T> T.minus(arg: NDArray<T>): NDArray<T> = arg.transform { _, value
|
|||||||
* Product operation for [NDArray] and single element
|
* Product operation for [NDArray] and single element
|
||||||
*/
|
*/
|
||||||
operator fun <T> NDArray<T>.times(arg: T): NDArray<T> = transform { _, value ->
|
operator fun <T> NDArray<T>.times(arg: T): NDArray<T> = transform { _, value ->
|
||||||
with(context.field){
|
with(context.field) {
|
||||||
arg * value
|
arg * value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ operator fun <T> T.times(arg: NDArray<T>): NDArray<T> = arg * this
|
|||||||
* Division operation between [NDArray] and single element
|
* Division operation between [NDArray] and single element
|
||||||
*/
|
*/
|
||||||
operator fun <T> NDArray<T>.div(arg: T): NDArray<T> = transform { _, value ->
|
operator fun <T> NDArray<T>.div(arg: T): NDArray<T> = transform { _, value ->
|
||||||
with(context.field){
|
with(context.field) {
|
||||||
arg / value
|
arg / value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,8 +193,8 @@ operator fun <T> NDArray<T>.div(arg: T): NDArray<T> = transform { _, value ->
|
|||||||
* Reverse division operation
|
* Reverse division operation
|
||||||
*/
|
*/
|
||||||
operator fun <T> T.div(arg: NDArray<T>): NDArray<T> = arg.transform { _, value ->
|
operator fun <T> T.div(arg: NDArray<T>): NDArray<T> = arg.transform { _, value ->
|
||||||
with(arg.context.field){
|
with(arg.context.field) {
|
||||||
this@div/ value
|
this@div / value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import scientifik.kmath.operations.Field
|
||||||
|
|
||||||
|
typealias NDFieldFactory<T> = (shape: List<Int>) -> NDField<T>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The factory class for fast platform-dependent implementation of NDField of doubles
|
||||||
|
*/
|
||||||
|
expect val realNDFieldFactory: NDFieldFactory<Double>
|
||||||
|
|
||||||
|
object NDArrays {
|
||||||
|
/**
|
||||||
|
* Create a platform-optimized NDArray of doubles
|
||||||
|
*/
|
||||||
|
fun realNDArray(shape: List<Int>, initializer: (List<Int>) -> Double = { 0.0 }): NDArray<Double> {
|
||||||
|
return realNDFieldFactory(shape).produce(initializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun real1DArray(dim: Int, initializer: (Int) -> Double = { _ -> 0.0 }): NDArray<Double> {
|
||||||
|
return realNDArray(listOf(dim)) { initializer(it[0]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun real2DArray(dim1: Int, dim2: Int, initializer: (Int, Int) -> Double = { _, _ -> 0.0 }): NDArray<Double> {
|
||||||
|
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<Double> {
|
||||||
|
return realNDArray(listOf(dim1, dim2, dim3)) { initializer(it[0], it[1], it[2]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleNDField<T : Any>(field: Field<T>, shape: List<Int>) : BufferNDField<T>(shape, field) {
|
||||||
|
override fun createBuffer(capacity: Int, initializer: (Int) -> T): Buffer<T> {
|
||||||
|
val array = ArrayList<T>(capacity)
|
||||||
|
(0 until capacity).forEach {
|
||||||
|
array.add(initializer(it))
|
||||||
|
}
|
||||||
|
|
||||||
|
return object : Buffer<T> {
|
||||||
|
override fun get(index: Int): T = array[index]
|
||||||
|
|
||||||
|
override fun set(index: Int, value: T) {
|
||||||
|
array[index] = initializer(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any> createSimpleNDFieldFactory(field: Field<T>): NDFieldFactory<T> = { list -> SimpleNDField(field, list) }
|
||||||
|
|
||||||
|
fun <T : Any> simpleNDArray(field: Field<T>, shape: List<Int>, initializer: (List<Int>) -> T): NDArray<T> {
|
||||||
|
return SimpleNDField(field, shape).produce { initializer(it) }
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
import org.junit.Assert.assertEquals
|
import kotlin.test.Test
|
||||||
import org.junit.Test
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class ArrayMatrixTest {
|
class ArrayMatrixTest {
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ class ArrayMatrixTest {
|
|||||||
val vector1 = realVector(5) { it.toDouble() }
|
val vector1 = realVector(5) { it.toDouble() }
|
||||||
val vector2 = realVector(5) { 5 - it.toDouble() }
|
val vector2 = realVector(5) { 5 - it.toDouble() }
|
||||||
val sum = vector1 + vector2
|
val sum = vector1 + vector2
|
||||||
assertEquals(5.0, sum[2, 0], 0.1)
|
assertEquals(5.0, sum[2, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -21,6 +21,6 @@ class ArrayMatrixTest {
|
|||||||
vector1 dot (vector2.transpose())
|
vector1 dot (vector2.transpose())
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(10.0, product[1, 0], 0.1)
|
assertEquals(10.0, product[1, 0])
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,9 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
import org.junit.Assert.assertEquals
|
import scientifik.kmath.structures.NDArrays.real2DArray
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class RealNDFieldTest {
|
class RealNDFieldTest {
|
||||||
val array1 = real2DArray(3, 3) { i, j -> (i + j).toDouble() }
|
val array1 = real2DArray(3, 3) { i, j -> (i + j).toDouble() }
|
||||||
@ -11,13 +12,13 @@ class RealNDFieldTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testSum() {
|
fun testSum() {
|
||||||
val sum = array1 + array2
|
val sum = array1 + array2
|
||||||
assertEquals(4.0, sum[2, 2], 0.1)
|
assertEquals(4.0, sum[2, 2])
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testProduct() {
|
fun testProduct() {
|
||||||
val product = array1 * array2
|
val product = array1 * array2
|
||||||
assertEquals(0.0, product[2, 2], 0.1)
|
assertEquals(0.0, product[2, 2])
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -28,7 +29,7 @@ class RealNDFieldTest {
|
|||||||
for (i in 0..2) {
|
for (i in 0..2) {
|
||||||
for (j in 0..2) {
|
for (j in 0..2) {
|
||||||
val expected = (i * 10 + j).toDouble()
|
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() {
|
fun testExternalFunction() {
|
||||||
val function: (Double) -> Double = { x -> x.pow(2) + 2 * x + 1 }
|
val function: (Double) -> Double = { x -> x.pow(2) + 2 * x + 1 }
|
||||||
val result = function(array1) + 1.0
|
val result = function(array1) + 1.0
|
||||||
assertEquals(10.0, result[1,1],0.01)
|
assertEquals(10.0, result[1,1])
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
import scientifik.kmath.operations.DoubleField
|
import scientifik.kmath.operations.DoubleField
|
||||||
|
import scientifik.kmath.structures.NDArrays.simpleNDArray
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import scientifik.kmath.operations.DoubleField
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using boxing implementation for js
|
||||||
|
*/
|
||||||
|
actual val realNDFieldFactory: NDFieldFactory<Double> = NDArrays.createSimpleNDFieldFactory(DoubleField)
|
@ -17,8 +17,4 @@ private class RealNDField(shape: List<Int>) : BufferNDField<Double>(shape, Doubl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun realNDArray(shape: List<Int>, initializer: (List<Int>) -> Double): NDArray<Double> {
|
actual val realNDFieldFactory: NDFieldFactory<Double> = { shape -> RealNDField(shape) }
|
||||||
//TODO create a cache for fields to save time generating strides?
|
|
||||||
|
|
||||||
return RealNDField(shape).produce { initializer(it) }
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,13 @@
|
|||||||
rootProject.name = 'kmath'
|
pluginManagement {
|
||||||
include 'kmath-common'
|
repositories {
|
||||||
include 'kmath-jvm'
|
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'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user