forked from kscience/kmath
Merge remote-tracking branch 'origin/dev' into dev
# Conflicts: # build.gradle # settings.gradle
This commit is contained in:
commit
75bedde1fa
@ -2,11 +2,6 @@ plugins {
|
|||||||
id 'kotlin-multiplatform'
|
id 'kotlin-multiplatform'
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven { url = 'http://dl.bintray.com/kotlin/kotlin-eap' }
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
targets {
|
targets {
|
||||||
fromPreset(presets.jvm, 'jvm')
|
fromPreset(presets.jvm, 'jvm')
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package scientifik.kmath.linear
|
package scientifik.kmath.linear
|
||||||
|
|
||||||
import scientifik.kmath.operations.DoubleField
|
import scientifik.kmath.operations.*
|
||||||
import scientifik.kmath.operations.Field
|
|
||||||
import scientifik.kmath.operations.Space
|
|
||||||
import scientifik.kmath.operations.SpaceElement
|
|
||||||
import scientifik.kmath.structures.*
|
import scientifik.kmath.structures.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,8 +67,6 @@ abstract class MatrixSpace<T : Any>(val rows: Int, val columns: Int, val field:
|
|||||||
result = 31 * result + field.hashCode()
|
result = 31 * result + field.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun <T : Any> Matrix<T>.dot(b: Matrix<T>): Matrix<T> = this.context.multiply(this, b)
|
infix fun <T : Any> Matrix<T>.dot(b: Matrix<T>): Matrix<T> = this.context.multiply(this, b)
|
||||||
@ -191,11 +186,11 @@ interface Vector<T : Any> : SpaceElement<Vector<T>, VectorSpace<T>>, Buffer<T>,
|
|||||||
typealias NDFieldFactory<T> = (IntArray) -> NDField<T>
|
typealias NDFieldFactory<T> = (IntArray) -> NDField<T>
|
||||||
|
|
||||||
internal fun <T : Any> genericNDFieldFactory(field: Field<T>): NDFieldFactory<T> = { index -> GenericNDField(index, field) }
|
internal fun <T : Any> genericNDFieldFactory(field: Field<T>): NDFieldFactory<T> = { index -> GenericNDField(index, field) }
|
||||||
internal val realNDFieldFactory: NDFieldFactory<Double> = { index -> GenericNDField(index, DoubleField) }
|
internal val realNDFieldFactory: NDFieldFactory<Double> = { index -> ExtendedNDField(index, DoubleField) }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NDArray-based implementation of vector space. By default uses slow [SimpleNDField], but could be overridden with custom [NDField] factory.
|
* NDArray-based implementation of vector space. By default uses slow [GenericNDField], but could be overridden with custom [NDField] factory.
|
||||||
*/
|
*/
|
||||||
class ArrayMatrixSpace<T : Any>(
|
class ArrayMatrixSpace<T : Any>(
|
||||||
rows: Int,
|
rows: Int,
|
||||||
@ -318,3 +313,8 @@ fun <T : Any> Vector<T>.toMatrix(): Matrix<T> {
|
|||||||
return Matrix.of(size, 1, context.field) { i, _ -> get(i) }
|
return Matrix.of(size, 1, context.field) { i, _ -> get(i) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object VectorL2Norm: Norm<Vector<out Number>, Double> {
|
||||||
|
override fun norm(arg: Vector<out Number>): Double {
|
||||||
|
return kotlin.math.sqrt(arg.sumByDouble { it.toDouble() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,10 +2,20 @@ package scientifik.kmath.operations
|
|||||||
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advanced Number-like field that implements basic operations
|
||||||
|
*/
|
||||||
|
interface ExtendedField<N : Any> :
|
||||||
|
Field<N>,
|
||||||
|
TrigonometricOperations<N>,
|
||||||
|
PowerOperations<N>,
|
||||||
|
ExponentialOperations<N>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field for real values
|
* Field for real values
|
||||||
*/
|
*/
|
||||||
object RealField : Field<Real>, TrigonometricOperations<Real>, PowerOperations<Real>, ExponentialOperations<Real> {
|
object RealField : ExtendedField<Real>, Norm<Real, Real> {
|
||||||
override val zero: Real = Real(0.0)
|
override val zero: Real = Real(0.0)
|
||||||
override fun add(a: Real, b: Real): Real = Real(a.value + b.value)
|
override fun add(a: Real, b: Real): Real = Real(a.value + b.value)
|
||||||
override val one: Real = Real(1.0)
|
override val one: Real = Real(1.0)
|
||||||
@ -21,25 +31,16 @@ object RealField : Field<Real>, TrigonometricOperations<Real>, PowerOperations<R
|
|||||||
override fun exp(arg: Real): Real = Real(kotlin.math.exp(arg.value))
|
override fun exp(arg: Real): Real = Real(kotlin.math.exp(arg.value))
|
||||||
|
|
||||||
override fun ln(arg: Real): Real = Real(kotlin.math.ln(arg.value))
|
override fun ln(arg: Real): Real = Real(kotlin.math.ln(arg.value))
|
||||||
|
|
||||||
|
override fun norm(arg: Real): Real = Real(kotlin.math.abs(arg.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Real field element wrapping double.
|
* Real field element wrapping double.
|
||||||
*
|
*
|
||||||
* TODO could be replaced by inline class in kotlin 1.3 if it would allow to avoid boxing
|
* TODO inline does not work due to compiler bug. Waiting for fix for KT-27586
|
||||||
*/
|
*/
|
||||||
data class Real(val value: Double) : Number(), FieldElement<Real, RealField> {
|
inline class Real(val value: Double) : FieldElement<Real, RealField> {
|
||||||
/*
|
|
||||||
* The class uses composition instead of inheritance since Double is final
|
|
||||||
*/
|
|
||||||
|
|
||||||
override fun toByte(): Byte = value.toByte()
|
|
||||||
override fun toChar(): Char = value.toChar()
|
|
||||||
override fun toDouble(): Double = value
|
|
||||||
override fun toFloat(): Float = value.toFloat()
|
|
||||||
override fun toInt(): Int = value.toInt()
|
|
||||||
override fun toLong(): Long = value.toLong()
|
|
||||||
override fun toShort(): Short = value.toShort()
|
|
||||||
|
|
||||||
//values are dynamically calculated to save memory
|
//values are dynamically calculated to save memory
|
||||||
override val self
|
override val self
|
||||||
@ -53,7 +54,7 @@ data class Real(val value: Double) : Number(), FieldElement<Real, RealField> {
|
|||||||
/**
|
/**
|
||||||
* A field for double without boxing. Does not produce appropriate field element
|
* A field for double without boxing. Does not produce appropriate field element
|
||||||
*/
|
*/
|
||||||
object DoubleField : Field<Double>, TrigonometricOperations<Double>, PowerOperations<Double>, ExponentialOperations<Double> {
|
object DoubleField : ExtendedField<Double>, Norm<Double, Double> {
|
||||||
override val zero: Double = 0.0
|
override val zero: Double = 0.0
|
||||||
override fun add(a: Double, b: Double): Double = a + b
|
override fun add(a: Double, b: Double): Double = a + b
|
||||||
override fun multiply(a: Double, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") b: Double): Double = a * b
|
override fun multiply(a: Double, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") b: Double): Double = a * b
|
||||||
@ -68,4 +69,6 @@ object DoubleField : Field<Double>, TrigonometricOperations<Double>, PowerOperat
|
|||||||
override fun exp(arg: Double): Double = kotlin.math.exp(arg)
|
override fun exp(arg: Double): Double = kotlin.math.exp(arg)
|
||||||
|
|
||||||
override fun ln(arg: Double): Double = kotlin.math.ln(arg)
|
override fun ln(arg: Double): Double = kotlin.math.ln(arg)
|
||||||
|
|
||||||
|
override fun norm(arg: Double): Double = kotlin.math.abs(arg)
|
||||||
}
|
}
|
@ -46,3 +46,9 @@ interface ExponentialOperations<T> {
|
|||||||
|
|
||||||
fun <T : MathElement<T, out ExponentialOperations<T>>> exp(arg: T): T = arg.context.exp(arg)
|
fun <T : MathElement<T, out ExponentialOperations<T>>> exp(arg: T): T = arg.context.exp(arg)
|
||||||
fun <T : MathElement<T, out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg)
|
fun <T : MathElement<T, out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg)
|
||||||
|
|
||||||
|
interface Norm<in T, out R> {
|
||||||
|
fun norm(arg: T): R
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : MathElement<T, out Norm<T, R>>, R> norm(arg: T): R = arg.context.norm(arg)
|
@ -42,6 +42,7 @@ inline class ListBuffer<T>(private val list: MutableList<T>) : MutableBuffer<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
|
class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
|
||||||
|
//Can't inline because array invariant
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() = array.size
|
get() = array.size
|
||||||
|
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import scientifik.kmath.operations.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NDField that supports [ExtendedField] operations on its elements
|
||||||
|
*/
|
||||||
|
class ExtendedNDField<N: Any>(shape: IntArray, override val field: ExtendedField<N>) : NDField<N>(shape, field),
|
||||||
|
TrigonometricOperations<NDArray<N>>,
|
||||||
|
PowerOperations<NDArray<N>>,
|
||||||
|
ExponentialOperations<NDArray<N>> {
|
||||||
|
|
||||||
|
override fun produceStructure(initializer: (IntArray) -> N): NDStructure<N> {
|
||||||
|
return genericNdStructure(shape, initializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun power(arg: NDArray<N>, pow: Double): NDArray<N> {
|
||||||
|
return arg.transform { d -> with(field){power(d,pow)} }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun exp(arg: NDArray<N>): NDArray<N> {
|
||||||
|
return arg.transform { d -> with(field){exp(d)} }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ln(arg: NDArray<N>): NDArray<N> {
|
||||||
|
return arg.transform { d -> with(field){ln(d)} }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sin(arg: NDArray<N>): NDArray<N> {
|
||||||
|
return arg.transform { d -> with(field){sin(d)} }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cos(arg: NDArray<N>): NDArray<N> {
|
||||||
|
return arg.transform { d -> with(field){cos(d)} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import scientifik.kmath.operations.DoubleField
|
||||||
import scientifik.kmath.operations.Field
|
import scientifik.kmath.operations.Field
|
||||||
import scientifik.kmath.operations.FieldElement
|
import scientifik.kmath.operations.FieldElement
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : Run
|
|||||||
* @param field - operations field defined on individual array element
|
* @param field - operations field defined on individual array element
|
||||||
* @param T the type of the element contained in NDArray
|
* @param T the type of the element contained in NDArray
|
||||||
*/
|
*/
|
||||||
abstract class NDField<T>(val shape: IntArray, val field: Field<T>) : Field<NDArray<T>> {
|
abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field<NDArray<T>> {
|
||||||
|
|
||||||
abstract fun produceStructure(initializer: (IntArray) -> T): NDStructure<T>
|
abstract fun produceStructure(initializer: (IntArray) -> T): NDStructure<T>
|
||||||
|
|
||||||
@ -173,7 +174,7 @@ object NDArrays {
|
|||||||
* Create a platform-optimized NDArray of doubles
|
* Create a platform-optimized NDArray of doubles
|
||||||
*/
|
*/
|
||||||
fun realNDArray(shape: IntArray, initializer: (IntArray) -> Double = { 0.0 }): NDArray<Double> {
|
fun realNDArray(shape: IntArray, initializer: (IntArray) -> Double = { 0.0 }): NDArray<Double> {
|
||||||
return RealNDField(shape).produce(initializer)
|
return ExtendedNDField(shape, DoubleField).produce(initializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun real1DArray(dim: Int, initializer: (Int) -> Double = { _ -> 0.0 }): NDArray<Double> {
|
fun real1DArray(dim: Int, initializer: (Int) -> Double = { _ -> 0.0 }): NDArray<Double> {
|
||||||
@ -188,7 +189,7 @@ object NDArrays {
|
|||||||
return realNDArray(intArrayOf(dim1, dim2, dim3)) { initializer(it[0], it[1], it[2]) }
|
return realNDArray(intArrayOf(dim1, dim2, dim3)) { initializer(it[0], it[1], it[2]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun produceReal(shape: IntArray, block: RealNDField.() -> RealNDArray) = RealNDField(shape).run(block)
|
inline fun produceReal(shape: IntArray, block: ExtendedNDField<Double>.() -> NDArray<Double>) = ExtendedNDField(shape, DoubleField).run(block)
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Simple boxing NDField
|
// * Simple boxing NDField
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
package scientifik.kmath.structures
|
|
||||||
|
|
||||||
import scientifik.kmath.operations.DoubleField
|
|
||||||
import scientifik.kmath.operations.ExponentialOperations
|
|
||||||
import scientifik.kmath.operations.PowerOperations
|
|
||||||
import scientifik.kmath.operations.TrigonometricOperations
|
|
||||||
import kotlin.math.*
|
|
||||||
|
|
||||||
typealias RealNDArray = NDArray<Double>
|
|
||||||
|
|
||||||
|
|
||||||
class RealNDField(shape: IntArray) : NDField<Double>(shape, DoubleField),
|
|
||||||
TrigonometricOperations<RealNDArray>,
|
|
||||||
PowerOperations<RealNDArray>,
|
|
||||||
ExponentialOperations<RealNDArray> {
|
|
||||||
|
|
||||||
override fun produceStructure(initializer: (IntArray) -> Double): NDStructure<Double> {
|
|
||||||
return genericNdStructure(shape, initializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun power(arg: RealNDArray, pow: Double): RealNDArray {
|
|
||||||
return arg.transform { d -> d.pow(pow) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun exp(arg: RealNDArray): RealNDArray {
|
|
||||||
return arg.transform { d -> exp(d) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun ln(arg: RealNDArray): RealNDArray {
|
|
||||||
return arg.transform { d -> ln(d) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun sin(arg: RealNDArray): RealNDArray {
|
|
||||||
return arg.transform { d -> sin(d) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cos(arg: RealNDArray): RealNDArray {
|
|
||||||
return arg.transform { d -> cos(d) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun abs(arg: RealNDArray): RealNDArray {
|
|
||||||
return arg.transform { d -> abs(d) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -6,9 +6,11 @@ import kotlin.test.assertEquals
|
|||||||
class RealFieldTest {
|
class RealFieldTest {
|
||||||
@Test
|
@Test
|
||||||
fun testSqrt() {
|
fun testSqrt() {
|
||||||
|
|
||||||
|
//fails because KT-27586
|
||||||
val sqrt = with(RealField) {
|
val sqrt = with(RealField) {
|
||||||
sqrt( 25 * one)
|
sqrt( 25 * one)
|
||||||
}
|
}
|
||||||
assertEquals(5.0, sqrt.toDouble())
|
assertEquals(5.0, sqrt.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import scientifik.kmath.linear.Vector
|
||||||
|
import scientifik.kmath.linear.VectorL2Norm
|
||||||
|
import scientifik.kmath.operations.Norm
|
||||||
import scientifik.kmath.structures.NDArrays.produceReal
|
import scientifik.kmath.structures.NDArrays.produceReal
|
||||||
import scientifik.kmath.structures.NDArrays.real2DArray
|
import scientifik.kmath.structures.NDArrays.real2DArray
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@ -7,7 +10,7 @@ import kotlin.math.pow
|
|||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class RealNDFieldTest {
|
class NumberNDFieldTest {
|
||||||
val array1 = real2DArray(3, 3) { i, j -> (i + j).toDouble() }
|
val array1 = real2DArray(3, 3) { i, j -> (i + j).toDouble() }
|
||||||
val array2 = real2DArray(3, 3) { i, j -> (i - j).toDouble() }
|
val array2 = real2DArray(3, 3) { i, j -> (i - j).toDouble() }
|
||||||
|
|
||||||
@ -46,14 +49,22 @@ class RealNDFieldTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testLibraryFunction() {
|
fun testLibraryFunction() {
|
||||||
val abs: (Double) -> Double = ::abs
|
val abs: (Double) -> Double = ::abs
|
||||||
val result = abs(array1)
|
val result = abs(array2)
|
||||||
assertEquals(10.0, result[1,1])
|
assertEquals(2.0, result[0,2])
|
||||||
|
}
|
||||||
|
|
||||||
|
object L2Norm: Norm<NDArray<out Number>, Double> {
|
||||||
|
override fun norm(arg: NDArray<out Number>): Double {
|
||||||
|
return kotlin.math.sqrt(arg.sumByDouble { it.second.toDouble() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAbs(){
|
fun testInternalContext(){
|
||||||
val res = produceReal(array1.shape){
|
produceReal(array1.shape){
|
||||||
1 + abs(array1) + exp(array2)
|
with(L2Norm) {
|
||||||
|
1 + norm(array1) + exp(array2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
53
kmath-io/build.gradle
Normal file
53
kmath-io/build.gradle
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
plugins {
|
||||||
|
id 'kotlin-multiplatform'
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
api project(":kmath-core")
|
||||||
|
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 {
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,6 @@ plugins {
|
|||||||
id "me.champeau.gradle.jmh" version "0.4.7"
|
id "me.champeau.gradle.jmh" version "0.4.7"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven { url = 'http://dl.bintray.com/kotlin/kotlin-eap' }
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':kmath-core')
|
implementation project(':kmath-core')
|
||||||
jmh 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
jmh 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
||||||
|
Loading…
Reference in New Issue
Block a user